Server : LiteSpeed
System : Linux server51.dnsbootclub.com 4.18.0-553.62.1.lve.el8.x86_64 #1 SMP Mon Jul 21 17:50:35 UTC 2025 x86_64
User : nandedex ( 1060)
PHP Version : 8.1.33
Disable Function : NONE
Directory :  /home/nandedex/www/s.nandedexpress.com/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]


Current File : /home/nandedex/www/s.nandedexpress.com/includes.tar
class-bulk-theme-upgrader-skin.php000064400000005144151212616040013170 0ustar00<?php
/**
 * Upgrader API: Bulk_Plugin_Upgrader_Skin class
 *
 * @package WordPress
 * @subpackage Upgrader
 * @since 4.6.0
 */

/**
 * Bulk Theme Upgrader Skin for WordPress Theme Upgrades.
 *
 * @since 3.0.0
 * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader-skins.php.
 *
 * @see Bulk_Upgrader_Skin
 */
class Bulk_Theme_Upgrader_Skin extends Bulk_Upgrader_Skin {

	/**
	 * Theme info.
	 *
	 * The Theme_Upgrader::bulk_upgrade() method will fill this in
	 * with info retrieved from the Theme_Upgrader::theme_info() method,
	 * which in turn calls the wp_get_theme() function.
	 *
	 * @since 3.0.0
	 * @var WP_Theme|false The theme's info object, or false.
	 */
	public $theme_info = false;

	/**
	 * Sets up the strings used in the update process.
	 *
	 * @since 3.0.0
	 */
	public function add_strings() {
		parent::add_strings();
		/* translators: 1: Theme name, 2: Number of the theme, 3: Total number of themes being updated. */
		$this->upgrader->strings['skin_before_update_header'] = __( 'Updating Theme %1$s (%2$d/%3$d)' );
	}

	/**
	 * Performs an action before a bulk theme update.
	 *
	 * @since 3.0.0
	 *
	 * @param string $title
	 */
	public function before( $title = '' ) {
		parent::before( $this->theme_info->display( 'Name' ) );
	}

	/**
	 * Performs an action following a bulk theme update.
	 *
	 * @since 3.0.0
	 *
	 * @param string $title
	 */
	public function after( $title = '' ) {
		parent::after( $this->theme_info->display( 'Name' ) );
		$this->decrement_update_count( 'theme' );
	}

	/**
	 * Displays the footer following the bulk update process.
	 *
	 * @since 3.0.0
	 */
	public function bulk_footer() {
		parent::bulk_footer();

		$update_actions = array(
			'themes_page'  => sprintf(
				'<a href="%s" target="_parent">%s</a>',
				self_admin_url( 'themes.php' ),
				__( 'Go to Themes page' )
			),
			'updates_page' => sprintf(
				'<a href="%s" target="_parent">%s</a>',
				self_admin_url( 'update-core.php' ),
				__( 'Go to WordPress Updates page' )
			),
		);

		if ( ! current_user_can( 'switch_themes' ) && ! current_user_can( 'edit_theme_options' ) ) {
			unset( $update_actions['themes_page'] );
		}

		/**
		 * Filters the list of action links available following bulk theme updates.
		 *
		 * @since 3.0.0
		 *
		 * @param string[] $update_actions Array of theme action links.
		 * @param WP_Theme $theme_info     Theme object for the last-updated theme.
		 */
		$update_actions = apply_filters( 'update_bulk_theme_complete_actions', $update_actions, $this->theme_info );

		if ( ! empty( $update_actions ) ) {
			$this->feedback( implode( ' | ', (array) $update_actions ) );
		}
	}
}
class-walker-nav-menu-checklist.php000064400000012773151212616040013350 0ustar00<?php
/**
 * Navigation Menu API: Walker_Nav_Menu_Checklist class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 4.4.0
 */

/**
 * Create HTML list of nav menu input items.
 *
 * @since 3.0.0
 * @uses Walker_Nav_Menu
 */
class Walker_Nav_Menu_Checklist extends Walker_Nav_Menu {
	/**
	 * @param array|false $fields Database fields to use.
	 */
	public function __construct( $fields = false ) {
		if ( $fields ) {
			$this->db_fields = $fields;
		}
	}

	/**
	 * Starts the list before the elements are added.
	 *
	 * @see Walker_Nav_Menu::start_lvl()
	 *
	 * @since 3.0.0
	 *
	 * @param string   $output Used to append additional content (passed by reference).
	 * @param int      $depth  Depth of page. Used for padding.
	 * @param stdClass $args   Not used.
	 */
	public function start_lvl( &$output, $depth = 0, $args = null ) {
		$indent  = str_repeat( "\t", $depth );
		$output .= "\n$indent<ul class='children'>\n";
	}

	/**
	 * Ends the list of after the elements are added.
	 *
	 * @see Walker_Nav_Menu::end_lvl()
	 *
	 * @since 3.0.0
	 *
	 * @param string   $output Used to append additional content (passed by reference).
	 * @param int      $depth  Depth of page. Used for padding.
	 * @param stdClass $args   Not used.
	 */
	public function end_lvl( &$output, $depth = 0, $args = null ) {
		$indent  = str_repeat( "\t", $depth );
		$output .= "\n$indent</ul>";
	}

	/**
	 * Start the element output.
	 *
	 * @see Walker_Nav_Menu::start_el()
	 *
	 * @since 3.0.0
	 * @since 5.9.0 Renamed `$item` to `$data_object` and `$id` to `$current_object_id`
	 *              to match parent class for PHP 8 named parameter support.
	 *
	 * @global int        $_nav_menu_placeholder
	 * @global int|string $nav_menu_selected_id
	 *
	 * @param string   $output            Used to append additional content (passed by reference).
	 * @param WP_Post  $data_object       Menu item data object.
	 * @param int      $depth             Depth of menu item. Used for padding.
	 * @param stdClass $args              Not used.
	 * @param int      $current_object_id Optional. ID of the current menu item. Default 0.
	 */
	public function start_el( &$output, $data_object, $depth = 0, $args = null, $current_object_id = 0 ) {
		global $_nav_menu_placeholder, $nav_menu_selected_id;

		// Restores the more descriptive, specific name for use within this method.
		$menu_item = $data_object;

		$_nav_menu_placeholder = ( 0 > $_nav_menu_placeholder ) ? (int) $_nav_menu_placeholder - 1 : -1;
		$possible_object_id    = isset( $menu_item->post_type ) && 'nav_menu_item' === $menu_item->post_type ? $menu_item->object_id : $_nav_menu_placeholder;
		$possible_db_id        = ( ! empty( $menu_item->ID ) ) && ( 0 < $possible_object_id ) ? (int) $menu_item->ID : 0;

		$indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';

		$output .= $indent . '<li>';
		$output .= '<label class="menu-item-title">';
		$output .= '<input type="checkbox"' . wp_nav_menu_disabled_check( $nav_menu_selected_id, false ) . ' class="menu-item-checkbox';

		if ( ! empty( $menu_item->front_or_home ) ) {
			$output .= ' add-to-top';
		}

		$output .= '" name="menu-item[' . $possible_object_id . '][menu-item-object-id]" value="' . esc_attr( $menu_item->object_id ) . '" /> ';

		if ( ! empty( $menu_item->label ) ) {
			$title = $menu_item->label;
		} elseif ( isset( $menu_item->post_type ) ) {
			/** This filter is documented in wp-includes/post-template.php */
			$title = apply_filters( 'the_title', $menu_item->post_title, $menu_item->ID );
		}

		$output .= isset( $title ) ? esc_html( $title ) : esc_html( $menu_item->title );

		if ( empty( $menu_item->label ) && isset( $menu_item->post_type ) && 'page' === $menu_item->post_type ) {
			// Append post states.
			$output .= _post_states( $menu_item, false );
		}

		$output .= '</label>';

		// Menu item hidden fields.
		$output .= '<input type="hidden" class="menu-item-db-id" name="menu-item[' . $possible_object_id . '][menu-item-db-id]" value="' . $possible_db_id . '" />';
		$output .= '<input type="hidden" class="menu-item-object" name="menu-item[' . $possible_object_id . '][menu-item-object]" value="' . esc_attr( $menu_item->object ) . '" />';
		$output .= '<input type="hidden" class="menu-item-parent-id" name="menu-item[' . $possible_object_id . '][menu-item-parent-id]" value="' . esc_attr( $menu_item->menu_item_parent ) . '" />';
		$output .= '<input type="hidden" class="menu-item-type" name="menu-item[' . $possible_object_id . '][menu-item-type]" value="' . esc_attr( $menu_item->type ) . '" />';
		$output .= '<input type="hidden" class="menu-item-title" name="menu-item[' . $possible_object_id . '][menu-item-title]" value="' . esc_attr( $menu_item->title ) . '" />';
		$output .= '<input type="hidden" class="menu-item-url" name="menu-item[' . $possible_object_id . '][menu-item-url]" value="' . esc_url( $menu_item->url ) . '" />';
		$output .= '<input type="hidden" class="menu-item-target" name="menu-item[' . $possible_object_id . '][menu-item-target]" value="' . esc_attr( $menu_item->target ) . '" />';
		$output .= '<input type="hidden" class="menu-item-attr-title" name="menu-item[' . $possible_object_id . '][menu-item-attr-title]" value="' . esc_attr( $menu_item->attr_title ) . '" />';
		$output .= '<input type="hidden" class="menu-item-classes" name="menu-item[' . $possible_object_id . '][menu-item-classes]" value="' . esc_attr( implode( ' ', $menu_item->classes ) ) . '" />';
		$output .= '<input type="hidden" class="menu-item-xfn" name="menu-item[' . $possible_object_id . '][menu-item-xfn]" value="' . esc_attr( $menu_item->xfn ) . '" />';
	}
}
revision.php000064400000040271151212616040007115 0ustar00<?php
/**
 * WordPress Administration Revisions API
 *
 * @package WordPress
 * @subpackage Administration
 * @since 3.6.0
 */

/**
 * Get the revision UI diff.
 *
 * @since 3.6.0
 *
 * @param WP_Post|int $post         The post object or post ID.
 * @param int         $compare_from The revision ID to compare from.
 * @param int         $compare_to   The revision ID to come to.
 * @return array|false Associative array of a post's revisioned fields and their diffs.
 *                     Or, false on failure.
 */
function wp_get_revision_ui_diff( $post, $compare_from, $compare_to ) {
	$post = get_post( $post );
	if ( ! $post ) {
		return false;
	}

	if ( $compare_from ) {
		$compare_from = get_post( $compare_from );
		if ( ! $compare_from ) {
			return false;
		}
	} else {
		// If we're dealing with the first revision...
		$compare_from = false;
	}

	$compare_to = get_post( $compare_to );
	if ( ! $compare_to ) {
		return false;
	}

	/*
	 * If comparing revisions, make sure we are dealing with the right post parent.
	 * The parent post may be a 'revision' when revisions are disabled and we're looking at autosaves.
	 */
	if ( $compare_from && $compare_from->post_parent !== $post->ID && $compare_from->ID !== $post->ID ) {
		return false;
	}
	if ( $compare_to->post_parent !== $post->ID && $compare_to->ID !== $post->ID ) {
		return false;
	}

	if ( $compare_from && strtotime( $compare_from->post_date_gmt ) > strtotime( $compare_to->post_date_gmt ) ) {
		$temp         = $compare_from;
		$compare_from = $compare_to;
		$compare_to   = $temp;
	}

	// Add default title if title field is empty.
	if ( $compare_from && empty( $compare_from->post_title ) ) {
		$compare_from->post_title = __( '(no title)' );
	}
	if ( empty( $compare_to->post_title ) ) {
		$compare_to->post_title = __( '(no title)' );
	}

	$return = array();

	foreach ( _wp_post_revision_fields( $post ) as $field => $name ) {
		/**
		 * Contextually filter a post revision field.
		 *
		 * The dynamic portion of the hook name, `$field`, corresponds to a name of a
		 * field of the revision object.
		 *
		 * Possible hook names include:
		 *
		 *  - `_wp_post_revision_field_post_title`
		 *  - `_wp_post_revision_field_post_content`
		 *  - `_wp_post_revision_field_post_excerpt`
		 *
		 * @since 3.6.0
		 *
		 * @param string  $revision_field The current revision field to compare to or from.
		 * @param string  $field          The current revision field.
		 * @param WP_Post $compare_from   The revision post object to compare to or from.
		 * @param string  $context        The context of whether the current revision is the old
		 *                                or the new one. Either 'to' or 'from'.
		 */
		$content_from = $compare_from ? apply_filters( "_wp_post_revision_field_{$field}", $compare_from->$field, $field, $compare_from, 'from' ) : '';

		/** This filter is documented in wp-admin/includes/revision.php */
		$content_to = apply_filters( "_wp_post_revision_field_{$field}", $compare_to->$field, $field, $compare_to, 'to' );

		$args = array(
			'show_split_view' => true,
			'title_left'      => __( 'Removed' ),
			'title_right'     => __( 'Added' ),
		);

		/**
		 * Filters revisions text diff options.
		 *
		 * Filters the options passed to wp_text_diff() when viewing a post revision.
		 *
		 * @since 4.1.0
		 *
		 * @param array   $args {
		 *     Associative array of options to pass to wp_text_diff().
		 *
		 *     @type bool $show_split_view True for split view (two columns), false for
		 *                                 un-split view (single column). Default true.
		 * }
		 * @param string  $field        The current revision field.
		 * @param WP_Post $compare_from The revision post to compare from.
		 * @param WP_Post $compare_to   The revision post to compare to.
		 */
		$args = apply_filters( 'revision_text_diff_options', $args, $field, $compare_from, $compare_to );

		$diff = wp_text_diff( $content_from, $content_to, $args );

		if ( ! $diff && 'post_title' === $field ) {
			/*
			 * It's a better user experience to still show the Title, even if it didn't change.
			 * No, you didn't see this.
			 */
			$diff = '<table class="diff"><colgroup><col class="content diffsplit left"><col class="content diffsplit middle"><col class="content diffsplit right"></colgroup><tbody><tr>';

			// In split screen mode, show the title before/after side by side.
			if ( true === $args['show_split_view'] ) {
				$diff .= '<td>' . esc_html( $compare_from->post_title ) . '</td><td></td><td>' . esc_html( $compare_to->post_title ) . '</td>';
			} else {
				$diff .= '<td>' . esc_html( $compare_from->post_title ) . '</td>';

				// In single column mode, only show the title once if unchanged.
				if ( $compare_from->post_title !== $compare_to->post_title ) {
					$diff .= '</tr><tr><td>' . esc_html( $compare_to->post_title ) . '</td>';
				}
			}

			$diff .= '</tr></tbody>';
			$diff .= '</table>';
		}

		if ( $diff ) {
			$return[] = array(
				'id'   => $field,
				'name' => $name,
				'diff' => $diff,
			);
		}
	}

	/**
	 * Filters the fields displayed in the post revision diff UI.
	 *
	 * @since 4.1.0
	 *
	 * @param array[] $return       Array of revision UI fields. Each item is an array of id, name, and diff.
	 * @param WP_Post $compare_from The revision post to compare from.
	 * @param WP_Post $compare_to   The revision post to compare to.
	 */
	return apply_filters( 'wp_get_revision_ui_diff', $return, $compare_from, $compare_to );
}

/**
 * Prepare revisions for JavaScript.
 *
 * @since 3.6.0
 *
 * @param WP_Post|int $post                 The post object or post ID.
 * @param int         $selected_revision_id The selected revision ID.
 * @param int         $from                 Optional. The revision ID to compare from.
 * @return array An associative array of revision data and related settings.
 */
function wp_prepare_revisions_for_js( $post, $selected_revision_id, $from = null ) {
	$post    = get_post( $post );
	$authors = array();
	$now_gmt = time();

	$revisions = wp_get_post_revisions(
		$post->ID,
		array(
			'order'         => 'ASC',
			'check_enabled' => false,
		)
	);
	// If revisions are disabled, we only want autosaves and the current post.
	if ( ! wp_revisions_enabled( $post ) ) {
		foreach ( $revisions as $revision_id => $revision ) {
			if ( ! wp_is_post_autosave( $revision ) ) {
				unset( $revisions[ $revision_id ] );
			}
		}
		$revisions = array( $post->ID => $post ) + $revisions;
	}

	$show_avatars = get_option( 'show_avatars' );

	update_post_author_caches( $revisions );

	$can_restore = current_user_can( 'edit_post', $post->ID );
	$current_id  = false;

	foreach ( $revisions as $revision ) {
		$modified     = strtotime( $revision->post_modified );
		$modified_gmt = strtotime( $revision->post_modified_gmt . ' +0000' );
		if ( $can_restore ) {
			$restore_link = str_replace(
				'&amp;',
				'&',
				wp_nonce_url(
					add_query_arg(
						array(
							'revision' => $revision->ID,
							'action'   => 'restore',
						),
						admin_url( 'revision.php' )
					),
					"restore-post_{$revision->ID}"
				)
			);
		}

		if ( ! isset( $authors[ $revision->post_author ] ) ) {
			$authors[ $revision->post_author ] = array(
				'id'     => (int) $revision->post_author,
				'avatar' => $show_avatars ? get_avatar( $revision->post_author, 32 ) : '',
				'name'   => get_the_author_meta( 'display_name', $revision->post_author ),
			);
		}

		$autosave = (bool) wp_is_post_autosave( $revision );
		$current  = ! $autosave && $revision->post_modified_gmt === $post->post_modified_gmt;
		if ( $current && ! empty( $current_id ) ) {
			// If multiple revisions have the same post_modified_gmt, highest ID is current.
			if ( $current_id < $revision->ID ) {
				$revisions[ $current_id ]['current'] = false;
				$current_id                          = $revision->ID;
			} else {
				$current = false;
			}
		} elseif ( $current ) {
			$current_id = $revision->ID;
		}

		$revisions_data = array(
			'id'         => $revision->ID,
			'title'      => get_the_title( $post->ID ),
			'author'     => $authors[ $revision->post_author ],
			'date'       => date_i18n( __( 'M j, Y @ H:i' ), $modified ),
			'dateShort'  => date_i18n( _x( 'j M Y @ H:i', 'revision date short format' ), $modified ),
			/* translators: %s: Human-readable time difference. */
			'timeAgo'    => sprintf( __( '%s ago' ), human_time_diff( $modified_gmt, $now_gmt ) ),
			'autosave'   => $autosave,
			'current'    => $current,
			'restoreUrl' => $can_restore ? $restore_link : false,
		);

		/**
		 * Filters the array of revisions used on the revisions screen.
		 *
		 * @since 4.4.0
		 *
		 * @param array   $revisions_data {
		 *     The bootstrapped data for the revisions screen.
		 *
		 *     @type int        $id         Revision ID.
		 *     @type string     $title      Title for the revision's parent WP_Post object.
		 *     @type int        $author     Revision post author ID.
		 *     @type string     $date       Date the revision was modified.
		 *     @type string     $dateShort  Short-form version of the date the revision was modified.
		 *     @type string     $timeAgo    GMT-aware amount of time ago the revision was modified.
		 *     @type bool       $autosave   Whether the revision is an autosave.
		 *     @type bool       $current    Whether the revision is both not an autosave and the post
		 *                                  modified date matches the revision modified date (GMT-aware).
		 *     @type bool|false $restoreUrl URL if the revision can be restored, false otherwise.
		 * }
		 * @param WP_Post $revision       The revision's WP_Post object.
		 * @param WP_Post $post           The revision's parent WP_Post object.
		 */
		$revisions[ $revision->ID ] = apply_filters( 'wp_prepare_revision_for_js', $revisions_data, $revision, $post );
	}

	/*
	 * If we only have one revision, the initial revision is missing. This happens
	 * when we have an autosave and the user has clicked 'View the Autosave'.
	 */
	if ( 1 === count( $revisions ) ) {
		$revisions[ $post->ID ] = array(
			'id'         => $post->ID,
			'title'      => get_the_title( $post->ID ),
			'author'     => $authors[ $revision->post_author ],
			'date'       => date_i18n( __( 'M j, Y @ H:i' ), strtotime( $post->post_modified ) ),
			'dateShort'  => date_i18n( _x( 'j M @ H:i', 'revision date short format' ), strtotime( $post->post_modified ) ),
			/* translators: %s: Human-readable time difference. */
			'timeAgo'    => sprintf( __( '%s ago' ), human_time_diff( strtotime( $post->post_modified_gmt ), $now_gmt ) ),
			'autosave'   => false,
			'current'    => true,
			'restoreUrl' => false,
		);
		$current_id             = $post->ID;
	}

	/*
	 * If a post has been saved since the latest revision (no revisioned fields
	 * were changed), we may not have a "current" revision. Mark the latest
	 * revision as "current".
	 */
	if ( empty( $current_id ) ) {
		if ( $revisions[ $revision->ID ]['autosave'] ) {
			$revision = end( $revisions );
			while ( $revision['autosave'] ) {
				$revision = prev( $revisions );
			}
			$current_id = $revision['id'];
		} else {
			$current_id = $revision->ID;
		}
		$revisions[ $current_id ]['current'] = true;
	}

	// Now, grab the initial diff.
	$compare_two_mode = is_numeric( $from );
	if ( ! $compare_two_mode ) {
		$found = array_search( $selected_revision_id, array_keys( $revisions ), true );
		if ( $found ) {
			$from = array_keys( array_slice( $revisions, $found - 1, 1, true ) );
			$from = reset( $from );
		} else {
			$from = 0;
		}
	}

	$from = absint( $from );

	$diffs = array(
		array(
			'id'     => $from . ':' . $selected_revision_id,
			'fields' => wp_get_revision_ui_diff( $post->ID, $from, $selected_revision_id ),
		),
	);

	return array(
		'postId'         => $post->ID,
		'nonce'          => wp_create_nonce( 'revisions-ajax-nonce' ),
		'revisionData'   => array_values( $revisions ),
		'to'             => $selected_revision_id,
		'from'           => $from,
		'diffData'       => $diffs,
		'baseUrl'        => parse_url( admin_url( 'revision.php' ), PHP_URL_PATH ),
		'compareTwoMode' => absint( $compare_two_mode ), // Apparently booleans are not allowed.
		'revisionIds'    => array_keys( $revisions ),
	);
}

/**
 * Print JavaScript templates required for the revisions experience.
 *
 * @since 4.1.0
 *
 * @global WP_Post $post Global post object.
 */
function wp_print_revision_templates() {
	global $post;
	?><script id="tmpl-revisions-frame" type="text/html">
		<div class="revisions-control-frame"></div>
		<div class="revisions-diff-frame"></div>
	</script>

	<script id="tmpl-revisions-buttons" type="text/html">
		<div class="revisions-previous">
			<input class="button" type="button" value="<?php echo esc_attr_x( 'Previous', 'Button label for a previous revision' ); ?>" />
		</div>

		<div class="revisions-next">
			<input class="button" type="button" value="<?php echo esc_attr_x( 'Next', 'Button label for a next revision' ); ?>" />
		</div>
	</script>

	<script id="tmpl-revisions-slider-hidden-help" type="text/html">
		<h2 class="screen-reader-text"><?php esc_html_e( 'Select a revision' ); ?></h2>
		<p id="revisions-slider-hidden-help" hidden><?php esc_html_e( 'Change revision by using the left and right arrow keys' ); ?></p>
	</script>

	<script id="tmpl-revisions-checkbox" type="text/html">
		<div class="revision-toggle-compare-mode">
			<label>
				<input type="checkbox" class="compare-two-revisions"
				<#
				if ( 'undefined' !== typeof data && data.model.attributes.compareTwoMode ) {
					#> checked="checked"<#
				}
				#>
				/>
				<?php esc_html_e( 'Compare any two revisions' ); ?>
			</label>
		</div>
	</script>

	<script id="tmpl-revisions-meta" type="text/html">
		<# if ( ! _.isUndefined( data.attributes ) ) { #>
			<div class="diff-title">
				<# if ( 'from' === data.type ) { #>
					<strong id="diff-title-from"><?php _ex( 'From:', 'Followed by post revision info' ); ?></strong>
				<# } else if ( 'to' === data.type ) { #>
					<strong id="diff-title-to"><?php _ex( 'To:', 'Followed by post revision info' ); ?></strong>
				<# } #>
				<div class="author-card<# if ( data.attributes.autosave ) { #> autosave<# } #>">
					<div>
						{{{ data.attributes.author.avatar }}}
						<div class="author-info" id="diff-title-author">
						<# if ( data.attributes.autosave ) { #>
							<span class="byline">
							<?php
							printf(
								/* translators: %s: User's display name. */
								__( 'Autosave by %s' ),
								'<span class="author-name">{{ data.attributes.author.name }}</span>'
							);
							?>
								</span>
						<# } else if ( data.attributes.current ) { #>
							<span class="byline">
							<?php
							printf(
								/* translators: %s: User's display name. */
								__( 'Current Revision by %s' ),
								'<span class="author-name">{{ data.attributes.author.name }}</span>'
							);
							?>
								</span>
						<# } else { #>
							<span class="byline">
							<?php
							printf(
								/* translators: %s: User's display name. */
								__( 'Revision by %s' ),
								'<span class="author-name">{{ data.attributes.author.name }}</span>'
							);
							?>
								</span>
						<# } #>
							<span class="time-ago">{{ data.attributes.timeAgo }}</span>
							<span class="date">({{ data.attributes.dateShort }})</span>
						</div>
					</div>
				<# if ( 'to' === data.type && data.attributes.restoreUrl ) { #>
					<input  <?php if ( wp_check_post_lock( $post->ID ) ) { ?>
						disabled="disabled"
					<?php } else { ?>
						<# if ( data.attributes.current ) { #>
							disabled="disabled"
						<# } #>
					<?php } ?>
					<# if ( data.attributes.autosave ) { #>
						type="button" class="restore-revision button button-primary" value="<?php esc_attr_e( 'Restore This Autosave' ); ?>" />
					<# } else { #>
						type="button" class="restore-revision button button-primary" value="<?php esc_attr_e( 'Restore This Revision' ); ?>" />
					<# } #>
				<# } #>
			</div>
		<# if ( 'tooltip' === data.type ) { #>
			<div class="revisions-tooltip-arrow"><span></span></div>
		<# } #>
	<# } #>
	</script>

	<script id="tmpl-revisions-diff" type="text/html">
		<div class="loading-indicator"><span class="spinner"></span></div>
		<div class="diff-error"><?php _e( 'An error occurred while loading the comparison. Please refresh the page and try again.' ); ?></div>
		<div class="diff">
		<# _.each( data.fields, function( field ) { #>
			<h2>{{ field.name }}</h2>
			{{{ field.diff }}}
		<# }); #>
		</div>
	</script>
	<?php
}
misc.php000064400000131354151212616040006215 0ustar00<?php
/**
 * Misc WordPress Administration API.
 *
 * @package WordPress
 * @subpackage Administration
 */

/**
 * Returns whether the server is running Apache with the mod_rewrite module loaded.
 *
 * @since 2.0.0
 *
 * @return bool Whether the server is running Apache with the mod_rewrite module loaded.
 */
function got_mod_rewrite() {
	$got_rewrite = apache_mod_loaded( 'mod_rewrite', true );

	/**
	 * Filters whether Apache and mod_rewrite are present.
	 *
	 * This filter was previously used to force URL rewriting for other servers,
	 * like nginx. Use the {@see 'got_url_rewrite'} filter in got_url_rewrite() instead.
	 *
	 * @since 2.5.0
	 *
	 * @see got_url_rewrite()
	 *
	 * @param bool $got_rewrite Whether Apache and mod_rewrite are present.
	 */
	return apply_filters( 'got_rewrite', $got_rewrite );
}

/**
 * Returns whether the server supports URL rewriting.
 *
 * Detects Apache's mod_rewrite, IIS 7.0+ permalink support, and nginx.
 *
 * @since 3.7.0
 *
 * @global bool $is_nginx
 * @global bool $is_caddy
 *
 * @return bool Whether the server supports URL rewriting.
 */
function got_url_rewrite() {
	$got_url_rewrite = ( got_mod_rewrite() || $GLOBALS['is_nginx'] || $GLOBALS['is_caddy'] || iis7_supports_permalinks() );

	/**
	 * Filters whether URL rewriting is available.
	 *
	 * @since 3.7.0
	 *
	 * @param bool $got_url_rewrite Whether URL rewriting is available.
	 */
	return apply_filters( 'got_url_rewrite', $got_url_rewrite );
}

/**
 * Extracts strings from between the BEGIN and END markers in the .htaccess file.
 *
 * @since 1.5.0
 *
 * @param string $filename Filename to extract the strings from.
 * @param string $marker   The marker to extract the strings from.
 * @return string[] An array of strings from a file (.htaccess) from between BEGIN and END markers.
 */
function extract_from_markers( $filename, $marker ) {
	$result = array();

	if ( ! file_exists( $filename ) ) {
		return $result;
	}

	$markerdata = explode( "\n", implode( '', file( $filename ) ) );

	$state = false;

	foreach ( $markerdata as $markerline ) {
		if ( str_contains( $markerline, '# END ' . $marker ) ) {
			$state = false;
		}

		if ( $state ) {
			if ( str_starts_with( $markerline, '#' ) ) {
				continue;
			}

			$result[] = $markerline;
		}

		if ( str_contains( $markerline, '# BEGIN ' . $marker ) ) {
			$state = true;
		}
	}

	return $result;
}

/**
 * Inserts an array of strings into a file (.htaccess), placing it between
 * BEGIN and END markers.
 *
 * Replaces existing marked info. Retains surrounding
 * data. Creates file if none exists.
 *
 * @since 1.5.0
 *
 * @param string       $filename  Filename to alter.
 * @param string       $marker    The marker to alter.
 * @param array|string $insertion The new content to insert.
 * @return bool True on write success, false on failure.
 */
function insert_with_markers( $filename, $marker, $insertion ) {
	if ( ! file_exists( $filename ) ) {
		if ( ! is_writable( dirname( $filename ) ) ) {
			return false;
		}

		if ( ! touch( $filename ) ) {
			return false;
		}

		// Make sure the file is created with a minimum set of permissions.
		$perms = fileperms( $filename );

		if ( $perms ) {
			chmod( $filename, $perms | 0644 );
		}
	} elseif ( ! is_writable( $filename ) ) {
		return false;
	}

	if ( ! is_array( $insertion ) ) {
		$insertion = explode( "\n", $insertion );
	}

	$switched_locale = switch_to_locale( get_locale() );

	$instructions = sprintf(
		/* translators: 1: Marker. */
		__(
			'The directives (lines) between "BEGIN %1$s" and "END %1$s" are
dynamically generated, and should only be modified via WordPress filters.
Any changes to the directives between these markers will be overwritten.'
		),
		$marker
	);

	$instructions = explode( "\n", $instructions );

	foreach ( $instructions as $line => $text ) {
		$instructions[ $line ] = '# ' . $text;
	}

	/**
	 * Filters the inline instructions inserted before the dynamically generated content.
	 *
	 * @since 5.3.0
	 *
	 * @param string[] $instructions Array of lines with inline instructions.
	 * @param string   $marker       The marker being inserted.
	 */
	$instructions = apply_filters( 'insert_with_markers_inline_instructions', $instructions, $marker );

	if ( $switched_locale ) {
		restore_previous_locale();
	}

	$insertion = array_merge( $instructions, $insertion );

	$start_marker = "# BEGIN {$marker}";
	$end_marker   = "# END {$marker}";

	$fp = fopen( $filename, 'r+' );

	if ( ! $fp ) {
		return false;
	}

	// Attempt to get a lock. If the filesystem supports locking, this will block until the lock is acquired.
	flock( $fp, LOCK_EX );

	$lines = array();

	while ( ! feof( $fp ) ) {
		$lines[] = rtrim( fgets( $fp ), "\r\n" );
	}

	// Split out the existing file into the preceding lines, and those that appear after the marker.
	$pre_lines        = array();
	$post_lines       = array();
	$existing_lines   = array();
	$found_marker     = false;
	$found_end_marker = false;

	foreach ( $lines as $line ) {
		if ( ! $found_marker && str_contains( $line, $start_marker ) ) {
			$found_marker = true;
			continue;
		} elseif ( ! $found_end_marker && str_contains( $line, $end_marker ) ) {
			$found_end_marker = true;
			continue;
		}

		if ( ! $found_marker ) {
			$pre_lines[] = $line;
		} elseif ( $found_end_marker ) {
			$post_lines[] = $line;
		} else {
			$existing_lines[] = $line;
		}
	}

	// Check to see if there was a change.
	if ( $existing_lines === $insertion ) {
		flock( $fp, LOCK_UN );
		fclose( $fp );

		return true;
	}

	// Generate the new file data.
	$new_file_data = implode(
		"\n",
		array_merge(
			$pre_lines,
			array( $start_marker ),
			$insertion,
			array( $end_marker ),
			$post_lines
		)
	);

	// Write to the start of the file, and truncate it to that length.
	fseek( $fp, 0 );
	$bytes = fwrite( $fp, $new_file_data );

	if ( $bytes ) {
		ftruncate( $fp, ftell( $fp ) );
	}

	fflush( $fp );
	flock( $fp, LOCK_UN );
	fclose( $fp );

	return (bool) $bytes;
}

/**
 * Updates the htaccess file with the current rules if it is writable.
 *
 * Always writes to the file if it exists and is writable to ensure that we
 * blank out old rules.
 *
 * @since 1.5.0
 *
 * @global WP_Rewrite $wp_rewrite WordPress rewrite component.
 *
 * @return bool|null True on write success, false on failure. Null in multisite.
 */
function save_mod_rewrite_rules() {
	global $wp_rewrite;

	if ( is_multisite() ) {
		return null;
	}

	// Ensure get_home_path() is declared.
	require_once ABSPATH . 'wp-admin/includes/file.php';

	$home_path     = get_home_path();
	$htaccess_file = $home_path . '.htaccess';

	/*
	 * If the file doesn't already exist check for write access to the directory
	 * and whether we have some rules. Else check for write access to the file.
	 */
	if ( ! file_exists( $htaccess_file ) && is_writable( $home_path ) && $wp_rewrite->using_mod_rewrite_permalinks()
		|| is_writable( $htaccess_file )
	) {
		if ( got_mod_rewrite() ) {
			$rules = explode( "\n", $wp_rewrite->mod_rewrite_rules() );

			return insert_with_markers( $htaccess_file, 'WordPress', $rules );
		}
	}

	return false;
}

/**
 * Updates the IIS web.config file with the current rules if it is writable.
 * If the permalinks do not require rewrite rules then the rules are deleted from the web.config file.
 *
 * @since 2.8.0
 *
 * @global WP_Rewrite $wp_rewrite WordPress rewrite component.
 *
 * @return bool|null True on write success, false on failure. Null in multisite.
 */
function iis7_save_url_rewrite_rules() {
	global $wp_rewrite;

	if ( is_multisite() ) {
		return null;
	}

	// Ensure get_home_path() is declared.
	require_once ABSPATH . 'wp-admin/includes/file.php';

	$home_path       = get_home_path();
	$web_config_file = $home_path . 'web.config';

	// Using win_is_writable() instead of is_writable() because of a bug in Windows PHP.
	if ( iis7_supports_permalinks()
		&& ( ! file_exists( $web_config_file ) && win_is_writable( $home_path ) && $wp_rewrite->using_mod_rewrite_permalinks()
			|| win_is_writable( $web_config_file ) )
	) {
		$rule = $wp_rewrite->iis7_url_rewrite_rules( false );

		if ( ! empty( $rule ) ) {
			return iis7_add_rewrite_rule( $web_config_file, $rule );
		} else {
			return iis7_delete_rewrite_rule( $web_config_file );
		}
	}

	return false;
}

/**
 * Updates the "recently-edited" file for the plugin or theme file editor.
 *
 * @since 1.5.0
 *
 * @param string $file
 */
function update_recently_edited( $file ) {
	$oldfiles = (array) get_option( 'recently_edited' );

	if ( $oldfiles ) {
		$oldfiles   = array_reverse( $oldfiles );
		$oldfiles[] = $file;
		$oldfiles   = array_reverse( $oldfiles );
		$oldfiles   = array_unique( $oldfiles );

		if ( 5 < count( $oldfiles ) ) {
			array_pop( $oldfiles );
		}
	} else {
		$oldfiles[] = $file;
	}

	update_option( 'recently_edited', $oldfiles );
}

/**
 * Makes a tree structure for the theme file editor's file list.
 *
 * @since 4.9.0
 * @access private
 *
 * @param array $allowed_files List of theme file paths.
 * @return array Tree structure for listing theme files.
 */
function wp_make_theme_file_tree( $allowed_files ) {
	$tree_list = array();

	foreach ( $allowed_files as $file_name => $absolute_filename ) {
		$list     = explode( '/', $file_name );
		$last_dir = &$tree_list;

		foreach ( $list as $dir ) {
			$last_dir =& $last_dir[ $dir ];
		}

		$last_dir = $file_name;
	}

	return $tree_list;
}

/**
 * Outputs the formatted file list for the theme file editor.
 *
 * @since 4.9.0
 * @access private
 *
 * @global string $relative_file Name of the file being edited relative to the
 *                               theme directory.
 * @global string $stylesheet    The stylesheet name of the theme being edited.
 *
 * @param array|string $tree  List of file/folder paths, or filename.
 * @param int          $level The aria-level for the current iteration.
 * @param int          $size  The aria-setsize for the current iteration.
 * @param int          $index The aria-posinset for the current iteration.
 */
function wp_print_theme_file_tree( $tree, $level = 2, $size = 1, $index = 1 ) {
	global $relative_file, $stylesheet;

	if ( is_array( $tree ) ) {
		$index = 0;
		$size  = count( $tree );

		foreach ( $tree as $label => $theme_file ) :
			++$index;

			if ( ! is_array( $theme_file ) ) {
				wp_print_theme_file_tree( $theme_file, $level, $index, $size );
				continue;
			}
			?>
			<li role="treeitem" aria-expanded="true" tabindex="-1"
				aria-level="<?php echo esc_attr( $level ); ?>"
				aria-setsize="<?php echo esc_attr( $size ); ?>"
				aria-posinset="<?php echo esc_attr( $index ); ?>">
				<span class="folder-label"><?php echo esc_html( $label ); ?> <span class="screen-reader-text">
					<?php
					/* translators: Hidden accessibility text. */
					_e( 'folder' );
					?>
				</span><span aria-hidden="true" class="icon"></span></span>
				<ul role="group" class="tree-folder"><?php wp_print_theme_file_tree( $theme_file, $level + 1, $index, $size ); ?></ul>
			</li>
			<?php
		endforeach;
	} else {
		$filename = $tree;
		$url      = add_query_arg(
			array(
				'file'  => rawurlencode( $tree ),
				'theme' => rawurlencode( $stylesheet ),
			),
			self_admin_url( 'theme-editor.php' )
		);
		?>
		<li role="none" class="<?php echo esc_attr( $relative_file === $filename ? 'current-file' : '' ); ?>">
			<a role="treeitem" tabindex="<?php echo esc_attr( $relative_file === $filename ? '0' : '-1' ); ?>"
				href="<?php echo esc_url( $url ); ?>"
				aria-level="<?php echo esc_attr( $level ); ?>"
				aria-setsize="<?php echo esc_attr( $size ); ?>"
				aria-posinset="<?php echo esc_attr( $index ); ?>">
				<?php
				$file_description = esc_html( get_file_description( $filename ) );

				if ( $file_description !== $filename && wp_basename( $filename ) !== $file_description ) {
					$file_description .= '<br /><span class="nonessential">(' . esc_html( $filename ) . ')</span>';
				}

				if ( $relative_file === $filename ) {
					echo '<span class="notice notice-info">' . $file_description . '</span>';
				} else {
					echo $file_description;
				}
				?>
			</a>
		</li>
		<?php
	}
}

/**
 * Makes a tree structure for the plugin file editor's file list.
 *
 * @since 4.9.0
 * @access private
 *
 * @param array $plugin_editable_files List of plugin file paths.
 * @return array Tree structure for listing plugin files.
 */
function wp_make_plugin_file_tree( $plugin_editable_files ) {
	$tree_list = array();

	foreach ( $plugin_editable_files as $plugin_file ) {
		$list     = explode( '/', preg_replace( '#^.+?/#', '', $plugin_file ) );
		$last_dir = &$tree_list;

		foreach ( $list as $dir ) {
			$last_dir =& $last_dir[ $dir ];
		}

		$last_dir = $plugin_file;
	}

	return $tree_list;
}

/**
 * Outputs the formatted file list for the plugin file editor.
 *
 * @since 4.9.0
 * @access private
 *
 * @param array|string $tree  List of file/folder paths, or filename.
 * @param string       $label Name of file or folder to print.
 * @param int          $level The aria-level for the current iteration.
 * @param int          $size  The aria-setsize for the current iteration.
 * @param int          $index The aria-posinset for the current iteration.
 */
function wp_print_plugin_file_tree( $tree, $label = '', $level = 2, $size = 1, $index = 1 ) {
	global $file, $plugin;

	if ( is_array( $tree ) ) {
		$index = 0;
		$size  = count( $tree );

		foreach ( $tree as $label => $plugin_file ) :
			++$index;

			if ( ! is_array( $plugin_file ) ) {
				wp_print_plugin_file_tree( $plugin_file, $label, $level, $index, $size );
				continue;
			}
			?>
			<li role="treeitem" aria-expanded="true" tabindex="-1"
				aria-level="<?php echo esc_attr( $level ); ?>"
				aria-setsize="<?php echo esc_attr( $size ); ?>"
				aria-posinset="<?php echo esc_attr( $index ); ?>">
				<span class="folder-label"><?php echo esc_html( $label ); ?> <span class="screen-reader-text">
					<?php
					/* translators: Hidden accessibility text. */
					_e( 'folder' );
					?>
				</span><span aria-hidden="true" class="icon"></span></span>
				<ul role="group" class="tree-folder"><?php wp_print_plugin_file_tree( $plugin_file, '', $level + 1, $index, $size ); ?></ul>
			</li>
			<?php
		endforeach;
	} else {
		$url = add_query_arg(
			array(
				'file'   => rawurlencode( $tree ),
				'plugin' => rawurlencode( $plugin ),
			),
			self_admin_url( 'plugin-editor.php' )
		);
		?>
		<li role="none" class="<?php echo esc_attr( $file === $tree ? 'current-file' : '' ); ?>">
			<a role="treeitem" tabindex="<?php echo esc_attr( $file === $tree ? '0' : '-1' ); ?>"
				href="<?php echo esc_url( $url ); ?>"
				aria-level="<?php echo esc_attr( $level ); ?>"
				aria-setsize="<?php echo esc_attr( $size ); ?>"
				aria-posinset="<?php echo esc_attr( $index ); ?>">
				<?php
				if ( $file === $tree ) {
					echo '<span class="notice notice-info">' . esc_html( $label ) . '</span>';
				} else {
					echo esc_html( $label );
				}
				?>
			</a>
		</li>
		<?php
	}
}

/**
 * Flushes rewrite rules if `siteurl`, `home` or `page_on_front` changed.
 *
 * @since 2.1.0
 *
 * @param string $old_value
 * @param string $value
 */
function update_home_siteurl( $old_value, $value ) {
	if ( wp_installing() ) {
		return;
	}

	if ( is_multisite() && ms_is_switched() ) {
		delete_option( 'rewrite_rules' );
	} else {
		flush_rewrite_rules();
	}
}

/**
 * Resets global variables based on `$_GET` and `$_POST`.
 *
 * This function resets global variables based on the names passed
 * in the `$vars` array to the value of `$_POST[$var]` or `$_GET[$var]` or an
 * empty string if neither is defined.
 *
 * @since 2.0.0
 *
 * @param array $vars An array of globals to reset.
 */
function wp_reset_vars( $vars ) {
	foreach ( $vars as $var ) {
		if ( empty( $_POST[ $var ] ) ) {
			if ( empty( $_GET[ $var ] ) ) {
				$GLOBALS[ $var ] = '';
			} else {
				$GLOBALS[ $var ] = $_GET[ $var ];
			}
		} else {
			$GLOBALS[ $var ] = $_POST[ $var ];
		}
	}
}

/**
 * Displays the given administration message.
 *
 * @since 2.1.0
 *
 * @param string|WP_Error $message
 */
function show_message( $message ) {
	if ( is_wp_error( $message ) ) {
		if ( $message->get_error_data() && is_string( $message->get_error_data() ) ) {
			$message = $message->get_error_message() . ': ' . $message->get_error_data();
		} else {
			$message = $message->get_error_message();
		}
	}

	echo "<p>$message</p>\n";
	wp_ob_end_flush_all();
	flush();
}

/**
 * @since 2.8.0
 *
 * @param string $content
 * @return string[] Array of function names.
 */
function wp_doc_link_parse( $content ) {
	if ( ! is_string( $content ) || empty( $content ) ) {
		return array();
	}

	if ( ! function_exists( 'token_get_all' ) ) {
		return array();
	}

	$tokens           = token_get_all( $content );
	$count            = count( $tokens );
	$functions        = array();
	$ignore_functions = array();

	for ( $t = 0; $t < $count - 2; $t++ ) {
		if ( ! is_array( $tokens[ $t ] ) ) {
			continue;
		}

		if ( T_STRING === $tokens[ $t ][0] && ( '(' === $tokens[ $t + 1 ] || '(' === $tokens[ $t + 2 ] ) ) {
			// If it's a function or class defined locally, there's not going to be any docs available.
			if ( ( isset( $tokens[ $t - 2 ][1] ) && in_array( $tokens[ $t - 2 ][1], array( 'function', 'class' ), true ) )
				|| ( isset( $tokens[ $t - 2 ][0] ) && T_OBJECT_OPERATOR === $tokens[ $t - 1 ][0] )
			) {
				$ignore_functions[] = $tokens[ $t ][1];
			}

			// Add this to our stack of unique references.
			$functions[] = $tokens[ $t ][1];
		}
	}

	$functions = array_unique( $functions );
	sort( $functions );

	/**
	 * Filters the list of functions and classes to be ignored from the documentation lookup.
	 *
	 * @since 2.8.0
	 *
	 * @param string[] $ignore_functions Array of names of functions and classes to be ignored.
	 */
	$ignore_functions = apply_filters( 'documentation_ignore_functions', $ignore_functions );

	$ignore_functions = array_unique( $ignore_functions );

	$output = array();

	foreach ( $functions as $function ) {
		if ( in_array( $function, $ignore_functions, true ) ) {
			continue;
		}

		$output[] = $function;
	}

	return $output;
}

/**
 * Saves option for number of rows when listing posts, pages, comments, etc.
 *
 * @since 2.8.0
 */
function set_screen_options() {
	if ( ! isset( $_POST['wp_screen_options'] ) || ! is_array( $_POST['wp_screen_options'] ) ) {
		return;
	}

	check_admin_referer( 'screen-options-nonce', 'screenoptionnonce' );

	$user = wp_get_current_user();

	if ( ! $user ) {
		return;
	}

	$option = $_POST['wp_screen_options']['option'];
	$value  = $_POST['wp_screen_options']['value'];

	if ( sanitize_key( $option ) !== $option ) {
		return;
	}

	$map_option = $option;
	$type       = str_replace( 'edit_', '', $map_option );
	$type       = str_replace( '_per_page', '', $type );

	if ( in_array( $type, get_taxonomies(), true ) ) {
		$map_option = 'edit_tags_per_page';
	} elseif ( in_array( $type, get_post_types(), true ) ) {
		$map_option = 'edit_per_page';
	} else {
		$option = str_replace( '-', '_', $option );
	}

	switch ( $map_option ) {
		case 'edit_per_page':
		case 'users_per_page':
		case 'edit_comments_per_page':
		case 'upload_per_page':
		case 'edit_tags_per_page':
		case 'plugins_per_page':
		case 'export_personal_data_requests_per_page':
		case 'remove_personal_data_requests_per_page':
			// Network admin.
		case 'sites_network_per_page':
		case 'users_network_per_page':
		case 'site_users_network_per_page':
		case 'plugins_network_per_page':
		case 'themes_network_per_page':
		case 'site_themes_network_per_page':
			$value = (int) $value;

			if ( $value < 1 || $value > 999 ) {
				return;
			}

			break;

		default:
			$screen_option = false;

			if ( str_ends_with( $option, '_page' ) || 'layout_columns' === $option ) {
				/**
				 * Filters a screen option value before it is set.
				 *
				 * The filter can also be used to modify non-standard `[items]_per_page`
				 * settings. See the parent function for a full list of standard options.
				 *
				 * Returning false from the filter will skip saving the current option.
				 *
				 * @since 2.8.0
				 * @since 5.4.2 Only applied to options ending with '_page',
				 *              or the 'layout_columns' option.
				 *
				 * @see set_screen_options()
				 *
				 * @param mixed  $screen_option The value to save instead of the option value.
				 *                              Default false (to skip saving the current option).
				 * @param string $option        The option name.
				 * @param int    $value         The option value.
				 */
				$screen_option = apply_filters( 'set-screen-option', $screen_option, $option, $value ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
			}

			/**
			 * Filters a screen option value before it is set.
			 *
			 * The dynamic portion of the hook name, `$option`, refers to the option name.
			 *
			 * Returning false from the filter will skip saving the current option.
			 *
			 * @since 5.4.2
			 *
			 * @see set_screen_options()
			 *
			 * @param mixed   $screen_option The value to save instead of the option value.
			 *                               Default false (to skip saving the current option).
			 * @param string  $option        The option name.
			 * @param int     $value         The option value.
			 */
			$value = apply_filters( "set_screen_option_{$option}", $screen_option, $option, $value );

			if ( false === $value ) {
				return;
			}

			break;
	}

	update_user_meta( $user->ID, $option, $value );

	$url = remove_query_arg( array( 'pagenum', 'apage', 'paged' ), wp_get_referer() );

	if ( isset( $_POST['mode'] ) ) {
		$url = add_query_arg( array( 'mode' => $_POST['mode'] ), $url );
	}

	wp_safe_redirect( $url );
	exit;
}

/**
 * Checks if rewrite rule for WordPress already exists in the IIS 7+ configuration file.
 *
 * @since 2.8.0
 *
 * @param string $filename The file path to the configuration file.
 * @return bool
 */
function iis7_rewrite_rule_exists( $filename ) {
	if ( ! file_exists( $filename ) ) {
		return false;
	}

	if ( ! class_exists( 'DOMDocument', false ) ) {
		return false;
	}

	$doc = new DOMDocument();

	if ( $doc->load( $filename ) === false ) {
		return false;
	}

	$xpath = new DOMXPath( $doc );
	$rules = $xpath->query( '/configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'wordpress\')] | /configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'WordPress\')]' );

	if ( 0 === $rules->length ) {
		return false;
	}

	return true;
}

/**
 * Deletes WordPress rewrite rule from web.config file if it exists there.
 *
 * @since 2.8.0
 *
 * @param string $filename Name of the configuration file.
 * @return bool
 */
function iis7_delete_rewrite_rule( $filename ) {
	// If configuration file does not exist then rules also do not exist, so there is nothing to delete.
	if ( ! file_exists( $filename ) ) {
		return true;
	}

	if ( ! class_exists( 'DOMDocument', false ) ) {
		return false;
	}

	$doc                     = new DOMDocument();
	$doc->preserveWhiteSpace = false;

	if ( $doc->load( $filename ) === false ) {
		return false;
	}

	$xpath = new DOMXPath( $doc );
	$rules = $xpath->query( '/configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'wordpress\')] | /configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'WordPress\')]' );

	if ( $rules->length > 0 ) {
		$child  = $rules->item( 0 );
		$parent = $child->parentNode;
		$parent->removeChild( $child );
		$doc->formatOutput = true;
		saveDomDocument( $doc, $filename );
	}

	return true;
}

/**
 * Adds WordPress rewrite rule to the IIS 7+ configuration file.
 *
 * @since 2.8.0
 *
 * @param string $filename     The file path to the configuration file.
 * @param string $rewrite_rule The XML fragment with URL Rewrite rule.
 * @return bool
 */
function iis7_add_rewrite_rule( $filename, $rewrite_rule ) {
	if ( ! class_exists( 'DOMDocument', false ) ) {
		return false;
	}

	// If configuration file does not exist then we create one.
	if ( ! file_exists( $filename ) ) {
		$fp = fopen( $filename, 'w' );
		fwrite( $fp, '<configuration/>' );
		fclose( $fp );
	}

	$doc                     = new DOMDocument();
	$doc->preserveWhiteSpace = false;

	if ( $doc->load( $filename ) === false ) {
		return false;
	}

	$xpath = new DOMXPath( $doc );

	// First check if the rule already exists as in that case there is no need to re-add it.
	$wordpress_rules = $xpath->query( '/configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'wordpress\')] | /configuration/system.webServer/rewrite/rules/rule[starts-with(@name,\'WordPress\')]' );

	if ( $wordpress_rules->length > 0 ) {
		return true;
	}

	// Check the XPath to the rewrite rule and create XML nodes if they do not exist.
	$xml_nodes = $xpath->query( '/configuration/system.webServer/rewrite/rules' );

	if ( $xml_nodes->length > 0 ) {
		$rules_node = $xml_nodes->item( 0 );
	} else {
		$rules_node = $doc->createElement( 'rules' );

		$xml_nodes = $xpath->query( '/configuration/system.webServer/rewrite' );

		if ( $xml_nodes->length > 0 ) {
			$rewrite_node = $xml_nodes->item( 0 );
			$rewrite_node->appendChild( $rules_node );
		} else {
			$rewrite_node = $doc->createElement( 'rewrite' );
			$rewrite_node->appendChild( $rules_node );

			$xml_nodes = $xpath->query( '/configuration/system.webServer' );

			if ( $xml_nodes->length > 0 ) {
				$system_web_server_node = $xml_nodes->item( 0 );
				$system_web_server_node->appendChild( $rewrite_node );
			} else {
				$system_web_server_node = $doc->createElement( 'system.webServer' );
				$system_web_server_node->appendChild( $rewrite_node );

				$xml_nodes = $xpath->query( '/configuration' );

				if ( $xml_nodes->length > 0 ) {
					$config_node = $xml_nodes->item( 0 );
					$config_node->appendChild( $system_web_server_node );
				} else {
					$config_node = $doc->createElement( 'configuration' );
					$doc->appendChild( $config_node );
					$config_node->appendChild( $system_web_server_node );
				}
			}
		}
	}

	$rule_fragment = $doc->createDocumentFragment();
	$rule_fragment->appendXML( $rewrite_rule );
	$rules_node->appendChild( $rule_fragment );

	$doc->encoding     = 'UTF-8';
	$doc->formatOutput = true;
	saveDomDocument( $doc, $filename );

	return true;
}

/**
 * Saves the XML document into a file.
 *
 * @since 2.8.0
 *
 * @param DOMDocument $doc
 * @param string      $filename
 */
function saveDomDocument( $doc, $filename ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionNameInvalid
	$config = $doc->saveXML();
	$config = preg_replace( "/([^\r])\n/", "$1\r\n", $config );

	$fp = fopen( $filename, 'w' );
	fwrite( $fp, $config );
	fclose( $fp );
}

/**
 * Displays the default administration color scheme picker (Used in user-edit.php).
 *
 * @since 3.0.0
 *
 * @global array $_wp_admin_css_colors
 *
 * @param int $user_id User ID.
 */
function admin_color_scheme_picker( $user_id ) {
	global $_wp_admin_css_colors;

	ksort( $_wp_admin_css_colors );

	if ( isset( $_wp_admin_css_colors['fresh'] ) ) {
		// Set Default ('fresh') and Light should go first.
		$_wp_admin_css_colors = array_filter(
			array_merge(
				array(
					'fresh'  => '',
					'light'  => '',
					'modern' => '',
				),
				$_wp_admin_css_colors
			)
		);
	}

	$current_color = get_user_option( 'admin_color', $user_id );

	if ( empty( $current_color ) || ! isset( $_wp_admin_css_colors[ $current_color ] ) ) {
		$current_color = 'fresh';
	}
	?>
	<fieldset id="color-picker" class="scheme-list">
		<legend class="screen-reader-text"><span><?php _e( 'Administration Color Scheme' ); ?></span></legend>
		<?php
		wp_nonce_field( 'save-color-scheme', 'color-nonce', false );
		foreach ( $_wp_admin_css_colors as $color => $color_info ) :

			?>
			<div class="color-option <?php echo ( $color === $current_color ) ? 'selected' : ''; ?>">
				<input name="admin_color" id="admin_color_<?php echo esc_attr( $color ); ?>" type="radio" value="<?php echo esc_attr( $color ); ?>" class="tog" <?php checked( $color, $current_color ); ?> />
				<input type="hidden" class="css_url" value="<?php echo esc_url( $color_info->url ); ?>" />
				<input type="hidden" class="icon_colors" value="<?php echo esc_attr( wp_json_encode( array( 'icons' => $color_info->icon_colors ) ) ); ?>" />
				<label for="admin_color_<?php echo esc_attr( $color ); ?>"><?php echo esc_html( $color_info->name ); ?></label>
				<div class="color-palette">
				<?php
				foreach ( $color_info->colors as $html_color ) {
					?>
					<div class="color-palette-shade" style="background-color: <?php echo esc_attr( $html_color ); ?>">&nbsp;</div>
					<?php
				}
				?>
				</div>
			</div>
			<?php

		endforeach;
		?>
	</fieldset>
	<?php
}

/**
 *
 * @since 3.8.0
 *
 * @global array $_wp_admin_css_colors
 */
function wp_color_scheme_settings() {
	global $_wp_admin_css_colors;

	$color_scheme = get_user_option( 'admin_color' );

	// It's possible to have a color scheme set that is no longer registered.
	if ( empty( $_wp_admin_css_colors[ $color_scheme ] ) ) {
		$color_scheme = 'fresh';
	}

	if ( ! empty( $_wp_admin_css_colors[ $color_scheme ]->icon_colors ) ) {
		$icon_colors = $_wp_admin_css_colors[ $color_scheme ]->icon_colors;
	} elseif ( ! empty( $_wp_admin_css_colors['fresh']->icon_colors ) ) {
		$icon_colors = $_wp_admin_css_colors['fresh']->icon_colors;
	} else {
		// Fall back to the default set of icon colors if the default scheme is missing.
		$icon_colors = array(
			'base'    => '#a7aaad',
			'focus'   => '#72aee6',
			'current' => '#fff',
		);
	}

	echo '<script type="text/javascript">var _wpColorScheme = ' . wp_json_encode( array( 'icons' => $icon_colors ), JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) . ";</script>\n";
}

/**
 * Displays the viewport meta in the admin.
 *
 * @since 5.5.0
 */
function wp_admin_viewport_meta() {
	/**
	 * Filters the viewport meta in the admin.
	 *
	 * @since 5.5.0
	 *
	 * @param string $viewport_meta The viewport meta.
	 */
	$viewport_meta = apply_filters( 'admin_viewport_meta', 'width=device-width,initial-scale=1.0' );

	if ( empty( $viewport_meta ) ) {
		return;
	}

	echo '<meta name="viewport" content="' . esc_attr( $viewport_meta ) . '">';
}

/**
 * Adds viewport meta for mobile in Customizer.
 *
 * Hooked to the {@see 'admin_viewport_meta'} filter.
 *
 * @since 5.5.0
 *
 * @param string $viewport_meta The viewport meta.
 * @return string Filtered viewport meta.
 */
function _customizer_mobile_viewport_meta( $viewport_meta ) {
	return trim( $viewport_meta, ',' ) . ',minimum-scale=0.5,maximum-scale=1.2';
}

/**
 * Checks lock status for posts displayed on the Posts screen.
 *
 * @since 3.6.0
 *
 * @param array  $response  The Heartbeat response.
 * @param array  $data      The $_POST data sent.
 * @param string $screen_id The screen ID.
 * @return array The Heartbeat response.
 */
function wp_check_locked_posts( $response, $data, $screen_id ) {
	$checked = array();

	if ( array_key_exists( 'wp-check-locked-posts', $data ) && is_array( $data['wp-check-locked-posts'] ) ) {
		foreach ( $data['wp-check-locked-posts'] as $key ) {
			$post_id = absint( substr( $key, 5 ) );

			if ( ! $post_id ) {
				continue;
			}

			$user_id = wp_check_post_lock( $post_id );

			if ( $user_id ) {
				$user = get_userdata( $user_id );

				if ( $user && current_user_can( 'edit_post', $post_id ) ) {
					$send = array(
						'name' => $user->display_name,
						/* translators: %s: User's display name. */
						'text' => sprintf( __( '%s is currently editing' ), $user->display_name ),
					);

					if ( get_option( 'show_avatars' ) ) {
						$send['avatar_src']    = get_avatar_url( $user->ID, array( 'size' => 18 ) );
						$send['avatar_src_2x'] = get_avatar_url( $user->ID, array( 'size' => 36 ) );
					}

					$checked[ $key ] = $send;
				}
			}
		}
	}

	if ( ! empty( $checked ) ) {
		$response['wp-check-locked-posts'] = $checked;
	}

	return $response;
}

/**
 * Checks lock status on the New/Edit Post screen and refresh the lock.
 *
 * @since 3.6.0
 *
 * @param array  $response  The Heartbeat response.
 * @param array  $data      The $_POST data sent.
 * @param string $screen_id The screen ID.
 * @return array The Heartbeat response.
 */
function wp_refresh_post_lock( $response, $data, $screen_id ) {
	if ( array_key_exists( 'wp-refresh-post-lock', $data ) ) {
		$received = $data['wp-refresh-post-lock'];
		$send     = array();

		$post_id = absint( $received['post_id'] );

		if ( ! $post_id ) {
			return $response;
		}

		if ( ! current_user_can( 'edit_post', $post_id ) ) {
			return $response;
		}

		$user_id = wp_check_post_lock( $post_id );
		$user    = get_userdata( $user_id );

		if ( $user ) {
			$error = array(
				'name' => $user->display_name,
				/* translators: %s: User's display name. */
				'text' => sprintf( __( '%s has taken over and is currently editing.' ), $user->display_name ),
			);

			if ( get_option( 'show_avatars' ) ) {
				$error['avatar_src']    = get_avatar_url( $user->ID, array( 'size' => 64 ) );
				$error['avatar_src_2x'] = get_avatar_url( $user->ID, array( 'size' => 128 ) );
			}

			$send['lock_error'] = $error;
		} else {
			$new_lock = wp_set_post_lock( $post_id );

			if ( $new_lock ) {
				$send['new_lock'] = implode( ':', $new_lock );
			}
		}

		$response['wp-refresh-post-lock'] = $send;
	}

	return $response;
}

/**
 * Checks nonce expiration on the New/Edit Post screen and refresh if needed.
 *
 * @since 3.6.0
 *
 * @param array  $response  The Heartbeat response.
 * @param array  $data      The $_POST data sent.
 * @param string $screen_id The screen ID.
 * @return array The Heartbeat response.
 */
function wp_refresh_post_nonces( $response, $data, $screen_id ) {
	if ( array_key_exists( 'wp-refresh-post-nonces', $data ) ) {
		$received = $data['wp-refresh-post-nonces'];

		$response['wp-refresh-post-nonces'] = array( 'check' => 1 );

		$post_id = absint( $received['post_id'] );

		if ( ! $post_id ) {
			return $response;
		}

		if ( ! current_user_can( 'edit_post', $post_id ) ) {
			return $response;
		}

		$response['wp-refresh-post-nonces'] = array(
			'replace' => array(
				'getpermalinknonce'    => wp_create_nonce( 'getpermalink' ),
				'samplepermalinknonce' => wp_create_nonce( 'samplepermalink' ),
				'closedpostboxesnonce' => wp_create_nonce( 'closedpostboxes' ),
				'_ajax_linking_nonce'  => wp_create_nonce( 'internal-linking' ),
				'_wpnonce'             => wp_create_nonce( 'update-post_' . $post_id ),
			),
		);
	}

	return $response;
}

/**
 * Refresh nonces used with meta boxes in the block editor.
 *
 * @since 6.1.0
 *
 * @param array  $response  The Heartbeat response.
 * @param array  $data      The $_POST data sent.
 * @return array The Heartbeat response.
 */
function wp_refresh_metabox_loader_nonces( $response, $data ) {
	if ( empty( $data['wp-refresh-metabox-loader-nonces'] ) ) {
		return $response;
	}

	$received = $data['wp-refresh-metabox-loader-nonces'];
	$post_id  = (int) $received['post_id'];

	if ( ! $post_id ) {
		return $response;
	}

	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		return $response;
	}

	$response['wp-refresh-metabox-loader-nonces'] = array(
		'replace' => array(
			'metabox_loader_nonce' => wp_create_nonce( 'meta-box-loader' ),
			'_wpnonce'             => wp_create_nonce( 'update-post_' . $post_id ),
		),
	);

	return $response;
}

/**
 * Adds the latest Heartbeat and REST API nonce to the Heartbeat response.
 *
 * @since 5.0.0
 *
 * @param array $response The Heartbeat response.
 * @return array The Heartbeat response.
 */
function wp_refresh_heartbeat_nonces( $response ) {
	// Refresh the Rest API nonce.
	$response['rest_nonce'] = wp_create_nonce( 'wp_rest' );

	// Refresh the Heartbeat nonce.
	$response['heartbeat_nonce'] = wp_create_nonce( 'heartbeat-nonce' );

	return $response;
}

/**
 * Disables suspension of Heartbeat on the Add/Edit Post screens.
 *
 * @since 3.8.0
 *
 * @global string $pagenow The filename of the current screen.
 *
 * @param array $settings An array of Heartbeat settings.
 * @return array Filtered Heartbeat settings.
 */
function wp_heartbeat_set_suspension( $settings ) {
	global $pagenow;

	if ( 'post.php' === $pagenow || 'post-new.php' === $pagenow ) {
		$settings['suspension'] = 'disable';
	}

	return $settings;
}

/**
 * Performs autosave with heartbeat.
 *
 * @since 3.9.0
 *
 * @param array $response The Heartbeat response.
 * @param array $data     The $_POST data sent.
 * @return array The Heartbeat response.
 */
function heartbeat_autosave( $response, $data ) {
	if ( ! empty( $data['wp_autosave'] ) ) {
		$saved = wp_autosave( $data['wp_autosave'] );

		if ( is_wp_error( $saved ) ) {
			$response['wp_autosave'] = array(
				'success' => false,
				'message' => $saved->get_error_message(),
			);
		} elseif ( empty( $saved ) ) {
			$response['wp_autosave'] = array(
				'success' => false,
				'message' => __( 'Error while saving.' ),
			);
		} else {
			/* translators: Draft saved date format, see https://www.php.net/manual/datetime.format.php */
			$draft_saved_date_format = __( 'g:i:s a' );
			$response['wp_autosave'] = array(
				'success' => true,
				/* translators: %s: Date and time. */
				'message' => sprintf( __( 'Draft saved at %s.' ), date_i18n( $draft_saved_date_format ) ),
			);
		}
	}

	return $response;
}

/**
 * Removes single-use URL parameters and create canonical link based on new URL.
 *
 * Removes specific query string parameters from a URL, create the canonical link,
 * put it in the admin header, and change the current URL to match.
 *
 * @since 4.2.0
 */
function wp_admin_canonical_url() {
	$removable_query_args = wp_removable_query_args();

	if ( empty( $removable_query_args ) ) {
		return;
	}

	// Ensure we're using an absolute URL.
	$current_url  = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
	$filtered_url = remove_query_arg( $removable_query_args, $current_url );

	/**
	 * Filters the admin canonical URL value.
	 *
	 * @since 6.5.0
	 *
	 * @param string $filtered_url The admin canonical URL value.
	 */
	$filtered_url = apply_filters( 'wp_admin_canonical_url', $filtered_url );
	?>
	<link id="wp-admin-canonical" rel="canonical" href="<?php echo esc_url( $filtered_url ); ?>" />
	<script>
		if ( window.history.replaceState ) {
			window.history.replaceState( null, null, document.getElementById( 'wp-admin-canonical' ).href + window.location.hash );
		}
	</script>
	<?php
}

/**
 * Outputs JS that reloads the page if the user navigated to it with the Back or Forward button.
 *
 * Used on the Edit Post and Add New Post screens. Needed to ensure the page is not loaded from browser cache,
 * so the post title and editor content are the last saved versions. Ideally this script should run first in the head.
 *
 * @since 4.6.0
 */
function wp_page_reload_on_back_button_js() {
	?>
	<script>
		if ( typeof performance !== 'undefined' && performance.navigation && performance.navigation.type === 2 ) {
			document.location.reload( true );
		}
	</script>
	<?php
}

/**
 * Sends a confirmation request email when a change of site admin email address is attempted.
 *
 * The new site admin address will not become active until confirmed.
 *
 * @since 3.0.0
 * @since 4.9.0 This function was moved from wp-admin/includes/ms.php so it's no longer Multisite specific.
 *
 * @param string $old_value The old site admin email address.
 * @param string $value     The proposed new site admin email address.
 */
function update_option_new_admin_email( $old_value, $value ) {
	if ( get_option( 'admin_email' ) === $value || ! is_email( $value ) ) {
		return;
	}

	$hash            = md5( $value . time() . wp_rand() );
	$new_admin_email = array(
		'hash'     => $hash,
		'newemail' => $value,
	);
	update_option( 'adminhash', $new_admin_email, false );

	$switched_locale = switch_to_user_locale( get_current_user_id() );

	/* translators: Do not translate USERNAME, ADMIN_URL, EMAIL, SITENAME, SITEURL: those are placeholders. */
	$email_text = __(
		'Howdy,

A site administrator (###USERNAME###) recently requested to have the
administration email address changed on this site:
###SITEURL###

To confirm this change, please click on the following link:
###ADMIN_URL###

You can safely ignore and delete this email if you do not want to
take this action.

This email has been sent to ###EMAIL###

Regards,
All at ###SITENAME###
###SITEURL###'
	);

	/**
	 * Filters the text of the email sent when a change of site admin email address is attempted.
	 *
	 * The following strings have a special meaning and will get replaced dynamically:
	 *
	 *  - `###USERNAME###`  The current user's username.
	 *  - `###ADMIN_URL###` The link to click on to confirm the email change.
	 *  - `###EMAIL###`     The proposed new site admin email address.
	 *  - `###SITENAME###`  The name of the site.
	 *  - `###SITEURL###`   The URL to the site.
	 *
	 * @since MU (3.0.0)
	 * @since 4.9.0 This filter is no longer Multisite specific.
	 *
	 * @param string $email_text      Text in the email.
	 * @param array  $new_admin_email {
	 *     Data relating to the new site admin email address.
	 *
	 *     @type string $hash     The secure hash used in the confirmation link URL.
	 *     @type string $newemail The proposed new site admin email address.
	 * }
	 */
	$content = apply_filters( 'new_admin_email_content', $email_text, $new_admin_email );

	$current_user = wp_get_current_user();
	$content      = str_replace( '###USERNAME###', $current_user->user_login, $content );
	$content      = str_replace( '###ADMIN_URL###', esc_url( self_admin_url( 'options.php?adminhash=' . $hash ) ), $content );
	$content      = str_replace( '###EMAIL###', $value, $content );
	$content      = str_replace( '###SITENAME###', wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ), $content );
	$content      = str_replace( '###SITEURL###', home_url(), $content );

	if ( '' !== get_option( 'blogname' ) ) {
		$site_title = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
	} else {
		$site_title = parse_url( home_url(), PHP_URL_HOST );
	}

	$subject = sprintf(
		/* translators: New admin email address notification email subject. %s: Site title. */
		__( '[%s] New Admin Email Address' ),
		$site_title
	);

	/**
	 * Filters the subject of the email sent when a change of site admin email address is attempted.
	 *
	 * @since 6.5.0
	 *
	 * @param string $subject Subject of the email.
	 */
	$subject = apply_filters( 'new_admin_email_subject', $subject );

	wp_mail( $value, $subject, $content );

	if ( $switched_locale ) {
		restore_previous_locale();
	}
}

/**
 * Appends '(Draft)' to draft page titles in the privacy page dropdown
 * so that unpublished content is obvious.
 *
 * @since 4.9.8
 * @access private
 *
 * @param string  $title Page title.
 * @param WP_Post $page  Page data object.
 * @return string Page title.
 */
function _wp_privacy_settings_filter_draft_page_titles( $title, $page ) {
	if ( 'draft' === $page->post_status && 'privacy' === get_current_screen()->id ) {
		/* translators: %s: Page title. */
		$title = sprintf( __( '%s (Draft)' ), $title );
	}

	return $title;
}

/**
 * Checks if the user needs to update PHP.
 *
 * @since 5.1.0
 * @since 5.1.1 Added the {@see 'wp_is_php_version_acceptable'} filter.
 *
 * @return array|false {
 *     Array of PHP version data. False on failure.
 *
 *     @type string $recommended_version The PHP version recommended by WordPress.
 *     @type string $minimum_version     The minimum required PHP version.
 *     @type bool   $is_supported        Whether the PHP version is actively supported.
 *     @type bool   $is_secure           Whether the PHP version receives security updates.
 *     @type bool   $is_acceptable       Whether the PHP version is still acceptable or warnings
 *                                       should be shown and an update recommended.
 * }
 */
function wp_check_php_version() {
	$version = PHP_VERSION;
	$key     = md5( $version );

	$response = get_site_transient( 'php_check_' . $key );

	if ( false === $response ) {
		$url = 'http://api.wordpress.org/core/serve-happy/1.0/';

		if ( wp_http_supports( array( 'ssl' ) ) ) {
			$url = set_url_scheme( $url, 'https' );
		}

		$url = add_query_arg( 'php_version', $version, $url );

		$response = wp_remote_get( $url );

		if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
			return false;
		}

		$response = json_decode( wp_remote_retrieve_body( $response ), true );

		if ( ! is_array( $response ) ) {
			return false;
		}

		set_site_transient( 'php_check_' . $key, $response, WEEK_IN_SECONDS );
	}

	if ( isset( $response['is_acceptable'] ) && $response['is_acceptable'] ) {
		/**
		 * Filters whether the active PHP version is considered acceptable by WordPress.
		 *
		 * Returning false will trigger a PHP version warning to show up in the admin dashboard to administrators.
		 *
		 * This filter is only run if the wordpress.org Serve Happy API considers the PHP version acceptable, ensuring
		 * that this filter can only make this check stricter, but not loosen it.
		 *
		 * @since 5.1.1
		 *
		 * @param bool   $is_acceptable Whether the PHP version is considered acceptable. Default true.
		 * @param string $version       PHP version checked.
		 */
		$response['is_acceptable'] = (bool) apply_filters( 'wp_is_php_version_acceptable', true, $version );
	}

	$response['is_lower_than_future_minimum'] = false;

	// The minimum supported PHP version will be updated to 7.4 in the future. Check if the current version is lower.
	if ( version_compare( $version, '7.4', '<' ) ) {
		$response['is_lower_than_future_minimum'] = true;

		// Force showing of warnings.
		$response['is_acceptable'] = false;
	}

	return $response;
}
class-theme-installer-skin.php000064400000031426151212616040012423 0ustar00<?php
/**
 * Upgrader API: Theme_Installer_Skin class
 *
 * @package WordPress
 * @subpackage Upgrader
 * @since 4.6.0
 */

/**
 * Theme Installer Skin for the WordPress Theme Installer.
 *
 * @since 2.8.0
 * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader-skins.php.
 *
 * @see WP_Upgrader_Skin
 */
class Theme_Installer_Skin extends WP_Upgrader_Skin {
	public $api;
	public $type;
	public $url;
	public $overwrite;

	private $is_downgrading = false;

	/**
	 * Constructor.
	 *
	 * Sets up the theme installer skin.
	 *
	 * @since 2.8.0
	 *
	 * @param array $args
	 */
	public function __construct( $args = array() ) {
		$defaults = array(
			'type'      => 'web',
			'url'       => '',
			'theme'     => '',
			'nonce'     => '',
			'title'     => '',
			'overwrite' => '',
		);
		$args     = wp_parse_args( $args, $defaults );

		$this->type      = $args['type'];
		$this->url       = $args['url'];
		$this->api       = isset( $args['api'] ) ? $args['api'] : array();
		$this->overwrite = $args['overwrite'];

		parent::__construct( $args );
	}

	/**
	 * Performs an action before installing a theme.
	 *
	 * @since 2.8.0
	 */
	public function before() {
		if ( ! empty( $this->api ) ) {
			$this->upgrader->strings['process_success'] = sprintf(
				$this->upgrader->strings['process_success_specific'],
				$this->api->name,
				$this->api->version
			);
		}
	}

	/**
	 * Hides the `process_failed` error when updating a theme by uploading a zip file.
	 *
	 * @since 5.5.0
	 *
	 * @param WP_Error $wp_error WP_Error object.
	 * @return bool True if the error should be hidden, false otherwise.
	 */
	public function hide_process_failed( $wp_error ) {
		if (
			'upload' === $this->type &&
			'' === $this->overwrite &&
			$wp_error->get_error_code() === 'folder_exists'
		) {
			return true;
		}

		return false;
	}

	/**
	 * Performs an action following a single theme install.
	 *
	 * @since 2.8.0
	 */
	public function after() {
		if ( $this->do_overwrite() ) {
			return;
		}

		if ( empty( $this->upgrader->result['destination_name'] ) ) {
			return;
		}

		$theme_info = $this->upgrader->theme_info();
		if ( empty( $theme_info ) ) {
			return;
		}

		$name       = $theme_info->display( 'Name' );
		$stylesheet = $this->upgrader->result['destination_name'];
		$template   = $theme_info->get_template();

		$activate_link = add_query_arg(
			array(
				'action'     => 'activate',
				'template'   => urlencode( $template ),
				'stylesheet' => urlencode( $stylesheet ),
			),
			admin_url( 'themes.php' )
		);
		$activate_link = wp_nonce_url( $activate_link, 'switch-theme_' . $stylesheet );

		$install_actions = array();

		if ( current_user_can( 'edit_theme_options' ) && ( $theme_info->is_block_theme() || current_user_can( 'customize' ) ) ) {
			if ( $theme_info->is_block_theme() ) {
				$customize_url = add_query_arg(
					array(
						'wp_theme_preview' => urlencode( $stylesheet ),
						'return'           => urlencode( admin_url( 'web' === $this->type ? 'theme-install.php' : 'themes.php' ) ),
					),
					admin_url( 'site-editor.php' )
				);
			} else {
				$customize_url = add_query_arg(
					array(
						'theme'  => urlencode( $stylesheet ),
						'return' => urlencode( admin_url( 'web' === $this->type ? 'theme-install.php' : 'themes.php' ) ),
					),
					admin_url( 'customize.php' )
				);
			}

			$install_actions['preview'] = sprintf(
				'<a href="%s" class="hide-if-no-customize load-customize">' .
				'<span aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></a>',
				esc_url( $customize_url ),
				__( 'Live Preview' ),
				/* translators: Hidden accessibility text. %s: Theme name. */
				sprintf( __( 'Live Preview &#8220;%s&#8221;' ), $name )
			);
		}

		$install_actions['activate'] = sprintf(
			'<a href="%s" class="activatelink">' .
			'<span aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></a>',
			esc_url( $activate_link ),
			_x( 'Activate', 'theme' ),
			/* translators: Hidden accessibility text. %s: Theme name. */
			sprintf( _x( 'Activate &#8220;%s&#8221;', 'theme' ), $name )
		);

		if ( is_network_admin() && current_user_can( 'manage_network_themes' ) ) {
			$install_actions['network_enable'] = sprintf(
				'<a href="%s" target="_parent">%s</a>',
				esc_url( wp_nonce_url( 'themes.php?action=enable&amp;theme=' . urlencode( $stylesheet ), 'enable-theme_' . $stylesheet ) ),
				__( 'Network Enable' )
			);
		}

		if ( 'web' === $this->type ) {
			$install_actions['themes_page'] = sprintf(
				'<a href="%s" target="_parent">%s</a>',
				self_admin_url( 'theme-install.php' ),
				__( 'Go to Theme Installer' )
			);
		} elseif ( current_user_can( 'switch_themes' ) || current_user_can( 'edit_theme_options' ) ) {
			$install_actions['themes_page'] = sprintf(
				'<a href="%s" target="_parent">%s</a>',
				self_admin_url( 'themes.php' ),
				__( 'Go to Themes page' )
			);
		}

		if ( ! $this->result || is_wp_error( $this->result ) || is_network_admin() || ! current_user_can( 'switch_themes' ) ) {
			unset( $install_actions['activate'], $install_actions['preview'] );
		} elseif ( get_option( 'template' ) === $stylesheet ) {
			unset( $install_actions['activate'] );
		}

		/**
		 * Filters the list of action links available following a single theme installation.
		 *
		 * @since 2.8.0
		 *
		 * @param string[] $install_actions Array of theme action links.
		 * @param object   $api             Object containing WordPress.org API theme data.
		 * @param string   $stylesheet      Theme directory name.
		 * @param WP_Theme $theme_info      Theme object.
		 */
		$install_actions = apply_filters( 'install_theme_complete_actions', $install_actions, $this->api, $stylesheet, $theme_info );
		if ( ! empty( $install_actions ) ) {
			$this->feedback( implode( ' | ', (array) $install_actions ) );
		}
	}

	/**
	 * Checks if the theme can be overwritten and outputs the HTML for overwriting a theme on upload.
	 *
	 * @since 5.5.0
	 *
	 * @return bool Whether the theme can be overwritten and HTML was outputted.
	 */
	private function do_overwrite() {
		if ( 'upload' !== $this->type || ! is_wp_error( $this->result ) || 'folder_exists' !== $this->result->get_error_code() ) {
			return false;
		}

		$folder = $this->result->get_error_data( 'folder_exists' );
		$folder = rtrim( $folder, '/' );

		$current_theme_data = false;
		$all_themes         = wp_get_themes( array( 'errors' => null ) );

		foreach ( $all_themes as $theme ) {
			$stylesheet_dir = wp_normalize_path( $theme->get_stylesheet_directory() );

			if ( rtrim( $stylesheet_dir, '/' ) !== $folder ) {
				continue;
			}

			$current_theme_data = $theme;
		}

		$new_theme_data = $this->upgrader->new_theme_data;

		if ( ! $current_theme_data || ! $new_theme_data ) {
			return false;
		}

		echo '<h2 class="update-from-upload-heading">' . esc_html__( 'This theme is already installed.' ) . '</h2>';

		// Check errors for active theme.
		if ( is_wp_error( $current_theme_data->errors() ) ) {
			$this->feedback( 'current_theme_has_errors', $current_theme_data->errors()->get_error_message() );
		}

		$this->is_downgrading = version_compare( $current_theme_data['Version'], $new_theme_data['Version'], '>' );

		$is_invalid_parent = false;
		if ( ! empty( $new_theme_data['Template'] ) ) {
			$is_invalid_parent = ! in_array( $new_theme_data['Template'], array_keys( $all_themes ), true );
		}

		$rows = array(
			'Name'        => __( 'Theme name' ),
			'Version'     => __( 'Version' ),
			'Author'      => __( 'Author' ),
			'RequiresWP'  => __( 'Required WordPress version' ),
			'RequiresPHP' => __( 'Required PHP version' ),
			'Template'    => __( 'Parent theme' ),
		);

		$table  = '<table class="update-from-upload-comparison"><tbody>';
		$table .= '<tr><th></th><th>' . esc_html_x( 'Installed', 'theme' ) . '</th><th>' . esc_html_x( 'Uploaded', 'theme' ) . '</th></tr>';

		$is_same_theme = true; // Let's consider only these rows.

		foreach ( $rows as $field => $label ) {
			$old_value = $current_theme_data->display( $field, false );
			$old_value = $old_value ? (string) $old_value : '-';

			$new_value = ! empty( $new_theme_data[ $field ] ) ? (string) $new_theme_data[ $field ] : '-';

			if ( $old_value === $new_value && '-' === $new_value && 'Template' === $field ) {
				continue;
			}

			$is_same_theme = $is_same_theme && ( $old_value === $new_value );

			$diff_field     = ( 'Version' !== $field && $new_value !== $old_value );
			$diff_version   = ( 'Version' === $field && $this->is_downgrading );
			$invalid_parent = false;

			if ( 'Template' === $field && $is_invalid_parent ) {
				$invalid_parent = true;
				$new_value     .= ' ' . __( '(not found)' );
			}

			$table .= '<tr><td class="name-label">' . $label . '</td><td>' . wp_strip_all_tags( $old_value ) . '</td>';
			$table .= ( $diff_field || $diff_version || $invalid_parent ) ? '<td class="warning">' : '<td>';
			$table .= wp_strip_all_tags( $new_value ) . '</td></tr>';
		}

		$table .= '</tbody></table>';

		/**
		 * Filters the compare table output for overwriting a theme package on upload.
		 *
		 * @since 5.5.0
		 *
		 * @param string   $table              The output table with Name, Version, Author, RequiresWP, and RequiresPHP info.
		 * @param WP_Theme $current_theme_data Active theme data.
		 * @param array    $new_theme_data     Array with uploaded theme data.
		 */
		echo apply_filters( 'install_theme_overwrite_comparison', $table, $current_theme_data, $new_theme_data );

		$install_actions = array();
		$can_update      = true;

		$blocked_message  = '<p>' . esc_html__( 'The theme cannot be updated due to the following:' ) . '</p>';
		$blocked_message .= '<ul class="ul-disc">';

		$requires_php = isset( $new_theme_data['RequiresPHP'] ) ? $new_theme_data['RequiresPHP'] : null;
		$requires_wp  = isset( $new_theme_data['RequiresWP'] ) ? $new_theme_data['RequiresWP'] : null;

		if ( ! is_php_version_compatible( $requires_php ) ) {
			$error = sprintf(
				/* translators: 1: Current PHP version, 2: Version required by the uploaded theme. */
				__( 'The PHP version on your server is %1$s, however the uploaded theme requires %2$s.' ),
				PHP_VERSION,
				$requires_php
			);

			$blocked_message .= '<li>' . esc_html( $error ) . '</li>';
			$can_update       = false;
		}

		if ( ! is_wp_version_compatible( $requires_wp ) ) {
			$error = sprintf(
				/* translators: 1: Current WordPress version, 2: Version required by the uploaded theme. */
				__( 'Your WordPress version is %1$s, however the uploaded theme requires %2$s.' ),
				esc_html( wp_get_wp_version() ),
				$requires_wp
			);

			$blocked_message .= '<li>' . esc_html( $error ) . '</li>';
			$can_update       = false;
		}

		$blocked_message .= '</ul>';

		if ( $can_update ) {
			if ( $this->is_downgrading ) {
				$warning = sprintf(
					/* translators: %s: Documentation URL. */
					__( 'You are uploading an older version of the installed theme. You can continue to install the older version, but be sure to <a href="%s">back up your database and files</a> first.' ),
					__( 'https://developer.wordpress.org/advanced-administration/security/backup/' )
				);
			} else {
				$warning = sprintf(
					/* translators: %s: Documentation URL. */
					__( 'You are updating a theme. Be sure to <a href="%s">back up your database and files</a> first.' ),
					__( 'https://developer.wordpress.org/advanced-administration/security/backup/' )
				);
			}

			echo '<p class="update-from-upload-notice">' . $warning . '</p>';

			$overwrite = $this->is_downgrading ? 'downgrade-theme' : 'update-theme';

			$install_actions['overwrite_theme'] = sprintf(
				'<a class="button button-primary update-from-upload-overwrite" href="%s" target="_parent">%s</a>',
				wp_nonce_url( add_query_arg( 'overwrite', $overwrite, $this->url ), 'theme-upload' ),
				_x( 'Replace installed with uploaded', 'theme' )
			);
		} else {
			echo $blocked_message;
		}

		$cancel_url = add_query_arg( 'action', 'upload-theme-cancel-overwrite', $this->url );

		$install_actions['themes_page'] = sprintf(
			'<a class="button" href="%s" target="_parent">%s</a>',
			wp_nonce_url( $cancel_url, 'theme-upload-cancel-overwrite' ),
			__( 'Cancel and go back' )
		);

		/**
		 * Filters the list of action links available following a single theme installation failure
		 * when overwriting is allowed.
		 *
		 * @since 5.5.0
		 *
		 * @param string[] $install_actions Array of theme action links.
		 * @param object   $api             Object containing WordPress.org API theme data.
		 * @param array    $new_theme_data  Array with uploaded theme data.
		 */
		$install_actions = apply_filters( 'install_theme_overwrite_actions', $install_actions, $this->api, $new_theme_data );

		if ( ! empty( $install_actions ) ) {
			printf(
				'<p class="update-from-upload-expired hidden">%s</p>',
				__( 'The uploaded file has expired. Please go back and upload it again.' )
			);
			echo '<p class="update-from-upload-actions">' . implode( ' ', (array) $install_actions ) . '</p>';
		}

		return true;
	}
}
class-wp-site-icon.php000064400000014416151212616040010702 0ustar00<?php
/**
 * Administration API: WP_Site_Icon class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 4.3.0
 */

/**
 * Core class used to implement site icon functionality.
 *
 * @since 4.3.0
 */
#[AllowDynamicProperties]
class WP_Site_Icon {

	/**
	 * The minimum size of the site icon.
	 *
	 * @since 4.3.0
	 * @var int
	 */
	public $min_size = 512;

	/**
	 * The size to which to crop the image so that we can display it in the UI nicely.
	 *
	 * @since 4.3.0
	 * @var int
	 */
	public $page_crop = 512;

	/**
	 * List of site icon sizes.
	 *
	 * @since 4.3.0
	 * @var int[]
	 */
	public $site_icon_sizes = array(
		/*
		 * Square, medium sized tiles for IE11+.
		 *
		 * See https://msdn.microsoft.com/library/dn455106(v=vs.85).aspx
		 */
		270,

		/*
		 * App icon for Android/Chrome.
		 *
		 * @link https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android
		 * @link https://developer.chrome.com/multidevice/android/installtohomescreen
		 */
		192,

		/*
		 * App icons up to iPhone 6 Plus.
		 *
		 * See https://developer.apple.com/library/prerelease/ios/documentation/UserExperience/Conceptual/MobileHIG/IconMatrix.html
		 */
		180,

		// Our regular Favicon.
		32,
	);

	/**
	 * Registers actions and filters.
	 *
	 * @since 4.3.0
	 */
	public function __construct() {
		add_action( 'delete_attachment', array( $this, 'delete_attachment_data' ) );
		add_filter( 'get_post_metadata', array( $this, 'get_post_metadata' ), 10, 4 );
	}

	/**
	 * Creates an attachment 'object'.
	 *
	 * @since 4.3.0
	 * @deprecated 6.5.0
	 *
	 * @param string $cropped              Cropped image URL.
	 * @param int    $parent_attachment_id Attachment ID of parent image.
	 * @return array An array with attachment object data.
	 */
	public function create_attachment_object( $cropped, $parent_attachment_id ) {
		_deprecated_function( __METHOD__, '6.5.0', 'wp_copy_parent_attachment_properties()' );

		$parent     = get_post( $parent_attachment_id );
		$parent_url = wp_get_attachment_url( $parent->ID );
		$url        = str_replace( wp_basename( $parent_url ), wp_basename( $cropped ), $parent_url );

		$size       = wp_getimagesize( $cropped );
		$image_type = ( $size ) ? $size['mime'] : 'image/jpeg';

		$attachment = array(
			'ID'             => $parent_attachment_id,
			'post_title'     => wp_basename( $cropped ),
			'post_content'   => $url,
			'post_mime_type' => $image_type,
			'guid'           => $url,
			'context'        => 'site-icon',
		);

		return $attachment;
	}

	/**
	 * Inserts an attachment.
	 *
	 * @since 4.3.0
	 *
	 * @param array  $attachment An array with attachment object data.
	 * @param string $file       File path of the attached image.
	 * @return int               Attachment ID.
	 */
	public function insert_attachment( $attachment, $file ) {
		$attachment_id = wp_insert_attachment( $attachment, $file );
		$metadata      = wp_generate_attachment_metadata( $attachment_id, $file );

		/**
		 * Filters the site icon attachment metadata.
		 *
		 * @since 4.3.0
		 *
		 * @see wp_generate_attachment_metadata()
		 *
		 * @param array $metadata Attachment metadata.
		 */
		$metadata = apply_filters( 'site_icon_attachment_metadata', $metadata );
		wp_update_attachment_metadata( $attachment_id, $metadata );

		return $attachment_id;
	}

	/**
	 * Adds additional sizes to be made when creating the site icon images.
	 *
	 * @since 4.3.0
	 *
	 * @param array[] $sizes Array of arrays containing information for additional sizes.
	 * @return array[] Array of arrays containing additional image sizes.
	 */
	public function additional_sizes( $sizes = array() ) {
		$only_crop_sizes = array();

		/**
		 * Filters the different dimensions that a site icon is saved in.
		 *
		 * @since 4.3.0
		 *
		 * @param int[] $site_icon_sizes Array of sizes available for the Site Icon.
		 */
		$this->site_icon_sizes = apply_filters( 'site_icon_image_sizes', $this->site_icon_sizes );

		// Use a natural sort of numbers.
		natsort( $this->site_icon_sizes );
		$this->site_icon_sizes = array_reverse( $this->site_icon_sizes );

		// Ensure that we only resize the image into sizes that allow cropping.
		foreach ( $sizes as $name => $size_array ) {
			if ( isset( $size_array['crop'] ) ) {
				$only_crop_sizes[ $name ] = $size_array;
			}
		}

		foreach ( $this->site_icon_sizes as $size ) {
			if ( $size < $this->min_size ) {
				$only_crop_sizes[ 'site_icon-' . $size ] = array(
					'width ' => $size,
					'height' => $size,
					'crop'   => true,
				);
			}
		}

		return $only_crop_sizes;
	}

	/**
	 * Adds Site Icon sizes to the array of image sizes on demand.
	 *
	 * @since 4.3.0
	 *
	 * @param string[] $sizes Array of image size names.
	 * @return string[] Array of image size names.
	 */
	public function intermediate_image_sizes( $sizes = array() ) {
		/** This filter is documented in wp-admin/includes/class-wp-site-icon.php */
		$this->site_icon_sizes = apply_filters( 'site_icon_image_sizes', $this->site_icon_sizes );
		foreach ( $this->site_icon_sizes as $size ) {
			$sizes[] = 'site_icon-' . $size;
		}

		return $sizes;
	}

	/**
	 * Deletes the Site Icon when the image file is deleted.
	 *
	 * @since 4.3.0
	 *
	 * @param int $post_id Attachment ID.
	 */
	public function delete_attachment_data( $post_id ) {
		$site_icon_id = (int) get_option( 'site_icon' );

		if ( $site_icon_id && $post_id === $site_icon_id ) {
			delete_option( 'site_icon' );
		}
	}

	/**
	 * Adds custom image sizes when meta data for an image is requested, that happens to be used as Site Icon.
	 *
	 * @since 4.3.0
	 *
	 * @param null|array|string $value    The value get_metadata() should return a single metadata value, or an
	 *                                    array of values.
	 * @param int               $post_id  Post ID.
	 * @param string            $meta_key Meta key.
	 * @param bool              $single   Whether to return only the first value of the specified `$meta_key`.
	 * @return array|null|string The attachment metadata value, array of values, or null.
	 */
	public function get_post_metadata( $value, $post_id, $meta_key, $single ) {
		if ( $single && '_wp_attachment_backup_sizes' === $meta_key ) {
			$site_icon_id = (int) get_option( 'site_icon' );

			if ( $post_id === $site_icon_id ) {
				add_filter( 'intermediate_image_sizes', array( $this, 'intermediate_image_sizes' ) );
			}
		}

		return $value;
	}
}
comment.php000064400000014127151212616040006722 0ustar00<?php
/**
 * WordPress Comment Administration API.
 *
 * @package WordPress
 * @subpackage Administration
 * @since 2.3.0
 */

/**
 * Determines if a comment exists based on author and date.
 *
 * For best performance, use `$timezone = 'gmt'`, which queries a field that is properly indexed. The default value
 * for `$timezone` is 'blog' for legacy reasons.
 *
 * @since 2.0.0
 * @since 4.4.0 Added the `$timezone` parameter.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param string $comment_author Author of the comment.
 * @param string $comment_date   Date of the comment.
 * @param string $timezone       Timezone. Accepts 'blog' or 'gmt'. Default 'blog'.
 * @return string|null Comment post ID on success.
 */
function comment_exists( $comment_author, $comment_date, $timezone = 'blog' ) {
	global $wpdb;

	$date_field = 'comment_date';
	if ( 'gmt' === $timezone ) {
		$date_field = 'comment_date_gmt';
	}

	return $wpdb->get_var(
		$wpdb->prepare(
			"SELECT comment_post_ID FROM $wpdb->comments
			WHERE comment_author = %s AND $date_field = %s",
			stripslashes( $comment_author ),
			stripslashes( $comment_date )
		)
	);
}

/**
 * Updates a comment with values provided in $_POST.
 *
 * @since 2.0.0
 * @since 5.5.0 A return value was added.
 *
 * @return int|WP_Error The value 1 if the comment was updated, 0 if not updated.
 *                      A WP_Error object on failure.
 */
function edit_comment() {
	if ( ! current_user_can( 'edit_comment', (int) $_POST['comment_ID'] ) ) {
		wp_die( __( 'Sorry, you are not allowed to edit comments on this post.' ) );
	}

	if ( isset( $_POST['newcomment_author'] ) ) {
		$_POST['comment_author'] = $_POST['newcomment_author'];
	}
	if ( isset( $_POST['newcomment_author_email'] ) ) {
		$_POST['comment_author_email'] = $_POST['newcomment_author_email'];
	}
	if ( isset( $_POST['newcomment_author_url'] ) ) {
		$_POST['comment_author_url'] = $_POST['newcomment_author_url'];
	}
	if ( isset( $_POST['comment_status'] ) ) {
		$_POST['comment_approved'] = $_POST['comment_status'];
	}
	if ( isset( $_POST['content'] ) ) {
		$_POST['comment_content'] = $_POST['content'];
	}
	if ( isset( $_POST['comment_ID'] ) ) {
		$_POST['comment_ID'] = (int) $_POST['comment_ID'];
	}

	foreach ( array( 'aa', 'mm', 'jj', 'hh', 'mn' ) as $timeunit ) {
		if ( ! empty( $_POST[ 'hidden_' . $timeunit ] ) && $_POST[ 'hidden_' . $timeunit ] !== $_POST[ $timeunit ] ) {
			$_POST['edit_date'] = '1';
			break;
		}
	}

	if ( ! empty( $_POST['edit_date'] ) ) {
		$aa = $_POST['aa'];
		$mm = $_POST['mm'];
		$jj = $_POST['jj'];
		$hh = $_POST['hh'];
		$mn = $_POST['mn'];
		$ss = $_POST['ss'];
		$jj = ( $jj > 31 ) ? 31 : $jj;
		$hh = ( $hh > 23 ) ? $hh - 24 : $hh;
		$mn = ( $mn > 59 ) ? $mn - 60 : $mn;
		$ss = ( $ss > 59 ) ? $ss - 60 : $ss;

		$_POST['comment_date'] = "$aa-$mm-$jj $hh:$mn:$ss";
	}

	return wp_update_comment( $_POST, true );
}

/**
 * Returns a WP_Comment object based on comment ID.
 *
 * @since 2.0.0
 *
 * @param int $id ID of comment to retrieve.
 * @return WP_Comment|false Comment if found. False on failure.
 */
function get_comment_to_edit( $id ) {
	$comment = get_comment( $id );
	if ( ! $comment ) {
		return false;
	}

	$comment->comment_ID      = (int) $comment->comment_ID;
	$comment->comment_post_ID = (int) $comment->comment_post_ID;

	$comment->comment_content = format_to_edit( $comment->comment_content );
	/**
	 * Filters the comment content before editing.
	 *
	 * @since 2.0.0
	 *
	 * @param string $comment_content Comment content.
	 */
	$comment->comment_content = apply_filters( 'comment_edit_pre', $comment->comment_content );

	$comment->comment_author       = format_to_edit( $comment->comment_author );
	$comment->comment_author_email = format_to_edit( $comment->comment_author_email );
	$comment->comment_author_url   = format_to_edit( $comment->comment_author_url );
	$comment->comment_author_url   = esc_url( $comment->comment_author_url );

	return $comment;
}

/**
 * Gets the number of pending comments on a post or posts.
 *
 * @since 2.3.0
 * @since 6.9.0 Exclude the 'note' comment type from the count.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int|int[] $post_id Either a single Post ID or an array of Post IDs
 * @return int|int[] Either a single Posts pending comments as an int or an array of ints keyed on the Post IDs
 */
function get_pending_comments_num( $post_id ) {
	global $wpdb;

	$single = false;
	if ( ! is_array( $post_id ) ) {
		$post_id_array = (array) $post_id;
		$single        = true;
	} else {
		$post_id_array = $post_id;
	}
	$post_id_array = array_map( 'intval', $post_id_array );
	$post_id_in    = "'" . implode( "', '", $post_id_array ) . "'";

	$pending = $wpdb->get_results( "SELECT comment_post_ID, COUNT(comment_ID) as num_comments FROM $wpdb->comments WHERE comment_post_ID IN ( $post_id_in ) AND comment_approved = '0' AND comment_type != 'note' GROUP BY comment_post_ID", ARRAY_A );

	if ( $single ) {
		if ( empty( $pending ) ) {
			return 0;
		} else {
			return absint( $pending[0]['num_comments'] );
		}
	}

	$pending_keyed = array();

	// Default to zero pending for all posts in request.
	foreach ( $post_id_array as $id ) {
		$pending_keyed[ $id ] = 0;
	}

	if ( ! empty( $pending ) ) {
		foreach ( $pending as $pend ) {
			$pending_keyed[ $pend['comment_post_ID'] ] = absint( $pend['num_comments'] );
		}
	}

	return $pending_keyed;
}

/**
 * Adds avatars to relevant places in admin.
 *
 * @since 2.5.0
 *
 * @param string $name User name.
 * @return string Avatar with the user name.
 */
function floated_admin_avatar( $name ) {
	$avatar = get_avatar( get_comment(), 32, 'mystery' );
	return "$avatar $name";
}

/**
 * Enqueues comment shortcuts jQuery script.
 *
 * @since 2.7.0
 */
function enqueue_comment_hotkeys_js() {
	if ( 'true' === get_user_option( 'comment_shortcuts' ) ) {
		wp_enqueue_script( 'jquery-table-hotkeys' );
	}
}

/**
 * Displays error message at bottom of comments.
 *
 * @since 2.5.0
 *
 * @param string $msg Error Message. Assumed to contain HTML and be sanitized.
 */
function comment_footer_die( $msg ) {
	echo "<div class='wrap'><p>$msg</p></div>";
	require_once ABSPATH . 'wp-admin/admin-footer.php';
	die;
}
template.php000064400000301727151212616040007100 0ustar00<?php
/**
 * Template WordPress Administration API.
 *
 * A Big Mess. Also some neat functions that are nicely written.
 *
 * @package WordPress
 * @subpackage Administration
 */

/** Walker_Category_Checklist class */
require_once ABSPATH . 'wp-admin/includes/class-walker-category-checklist.php';

/** WP_Internal_Pointers class */
require_once ABSPATH . 'wp-admin/includes/class-wp-internal-pointers.php';

//
// Category Checklists.
//

/**
 * Outputs an unordered list of checkbox input elements labeled with category names.
 *
 * @since 2.5.1
 *
 * @see wp_terms_checklist()
 *
 * @param int         $post_id              Optional. Post to generate a categories checklist for. Default 0.
 *                                          $selected_cats must not be an array. Default 0.
 * @param int         $descendants_and_self Optional. ID of the category to output along with its descendants.
 *                                          Default 0.
 * @param int[]|false $selected_cats        Optional. Array of category IDs to mark as checked. Default false.
 * @param int[]|false $popular_cats         Optional. Array of category IDs to receive the "popular-category" class.
 *                                          Default false.
 * @param Walker      $walker               Optional. Walker object to use to build the output.
 *                                          Default is a Walker_Category_Checklist instance.
 * @param bool        $checked_ontop        Optional. Whether to move checked items out of the hierarchy and to
 *                                          the top of the list. Default true.
 */
function wp_category_checklist( $post_id = 0, $descendants_and_self = 0, $selected_cats = false, $popular_cats = false, $walker = null, $checked_ontop = true ) {
	wp_terms_checklist(
		$post_id,
		array(
			'taxonomy'             => 'category',
			'descendants_and_self' => $descendants_and_self,
			'selected_cats'        => $selected_cats,
			'popular_cats'         => $popular_cats,
			'walker'               => $walker,
			'checked_ontop'        => $checked_ontop,
		)
	);
}

/**
 * Outputs an unordered list of checkbox input elements labelled with term names.
 *
 * Taxonomy-independent version of wp_category_checklist().
 *
 * @since 3.0.0
 * @since 4.4.0 Introduced the `$echo` argument.
 *
 * @param int          $post_id Optional. Post ID. Default 0.
 * @param array|string $args {
 *     Optional. Array or string of arguments for generating a terms checklist. Default empty array.
 *
 *     @type int    $descendants_and_self ID of the category to output along with its descendants.
 *                                        Default 0.
 *     @type int[]  $selected_cats        Array of category IDs to mark as checked. Default false.
 *     @type int[]  $popular_cats         Array of category IDs to receive the "popular-category" class.
 *                                        Default false.
 *     @type Walker $walker               Walker object to use to build the output. Default empty which
 *                                        results in a Walker_Category_Checklist instance being used.
 *     @type string $taxonomy             Taxonomy to generate the checklist for. Default 'category'.
 *     @type bool   $checked_ontop        Whether to move checked items out of the hierarchy and to
 *                                        the top of the list. Default true.
 *     @type bool   $echo                 Whether to echo the generated markup. False to return the markup instead
 *                                        of echoing it. Default true.
 * }
 * @return string HTML list of input elements.
 */
function wp_terms_checklist( $post_id = 0, $args = array() ) {
	$defaults = array(
		'descendants_and_self' => 0,
		'selected_cats'        => false,
		'popular_cats'         => false,
		'walker'               => null,
		'taxonomy'             => 'category',
		'checked_ontop'        => true,
		'echo'                 => true,
	);

	/**
	 * Filters the taxonomy terms checklist arguments.
	 *
	 * @since 3.4.0
	 *
	 * @see wp_terms_checklist()
	 *
	 * @param array|string $args    An array or string of arguments.
	 * @param int          $post_id The post ID.
	 */
	$params = apply_filters( 'wp_terms_checklist_args', $args, $post_id );

	$parsed_args = wp_parse_args( $params, $defaults );

	if ( empty( $parsed_args['walker'] ) || ! ( $parsed_args['walker'] instanceof Walker ) ) {
		$walker = new Walker_Category_Checklist();
	} else {
		$walker = $parsed_args['walker'];
	}

	$taxonomy             = $parsed_args['taxonomy'];
	$descendants_and_self = (int) $parsed_args['descendants_and_self'];

	$args = array( 'taxonomy' => $taxonomy );

	$tax              = get_taxonomy( $taxonomy );
	$args['disabled'] = ! current_user_can( $tax->cap->assign_terms );

	$args['list_only'] = ! empty( $parsed_args['list_only'] );

	if ( is_array( $parsed_args['selected_cats'] ) ) {
		$args['selected_cats'] = array_map( 'intval', $parsed_args['selected_cats'] );
	} elseif ( $post_id ) {
		$args['selected_cats'] = wp_get_object_terms( $post_id, $taxonomy, array_merge( $args, array( 'fields' => 'ids' ) ) );
	} else {
		$args['selected_cats'] = array();
	}

	if ( is_array( $parsed_args['popular_cats'] ) ) {
		$args['popular_cats'] = array_map( 'intval', $parsed_args['popular_cats'] );
	} else {
		$args['popular_cats'] = get_terms(
			array(
				'taxonomy'     => $taxonomy,
				'fields'       => 'ids',
				'orderby'      => 'count',
				'order'        => 'DESC',
				'number'       => 10,
				'hierarchical' => false,
			)
		);
	}

	if ( $descendants_and_self ) {
		$categories = (array) get_terms(
			array(
				'taxonomy'     => $taxonomy,
				'child_of'     => $descendants_and_self,
				'hierarchical' => 0,
				'hide_empty'   => 0,
			)
		);
		$self       = get_term( $descendants_and_self, $taxonomy );
		array_unshift( $categories, $self );
	} else {
		$categories = (array) get_terms(
			array(
				'taxonomy' => $taxonomy,
				'get'      => 'all',
			)
		);
	}

	$output = '';

	if ( $parsed_args['checked_ontop'] ) {
		/*
		 * Post-process $categories rather than adding an exclude to the get_terms() query
		 * to keep the query the same across all posts (for any query cache).
		 */
		$checked_categories = array();
		$keys               = array_keys( $categories );

		foreach ( $keys as $k ) {
			if ( in_array( $categories[ $k ]->term_id, $args['selected_cats'], true ) ) {
				$checked_categories[] = $categories[ $k ];
				unset( $categories[ $k ] );
			}
		}

		// Put checked categories on top.
		$output .= $walker->walk( $checked_categories, 0, $args );
	}
	// Then the rest of them.
	$output .= $walker->walk( $categories, 0, $args );

	if ( $parsed_args['echo'] ) {
		echo $output;
	}

	return $output;
}

/**
 * Retrieves a list of the most popular terms from the specified taxonomy.
 *
 * If the `$display` argument is true then the elements for a list of checkbox
 * `<input>` elements labelled with the names of the selected terms is output.
 * If the `$post_ID` global is not empty then the terms associated with that
 * post will be marked as checked.
 *
 * @since 2.5.0
 *
 * @param string $taxonomy     Taxonomy to retrieve terms from.
 * @param int    $default_term Optional. Not used.
 * @param int    $number       Optional. Number of terms to retrieve. Default 10.
 * @param bool   $display      Optional. Whether to display the list as well. Default true.
 * @return int[] Array of popular term IDs.
 */
function wp_popular_terms_checklist( $taxonomy, $default_term = 0, $number = 10, $display = true ) {
	$post = get_post();

	if ( $post && $post->ID ) {
		$checked_terms = wp_get_object_terms( $post->ID, $taxonomy, array( 'fields' => 'ids' ) );
	} else {
		$checked_terms = array();
	}

	$terms = get_terms(
		array(
			'taxonomy'     => $taxonomy,
			'orderby'      => 'count',
			'order'        => 'DESC',
			'number'       => $number,
			'hierarchical' => false,
		)
	);

	$tax = get_taxonomy( $taxonomy );

	$popular_ids = array();

	foreach ( (array) $terms as $term ) {
		$popular_ids[] = $term->term_id;

		if ( ! $display ) { // Hack for Ajax use.
			continue;
		}

		$id      = "popular-$taxonomy-$term->term_id";
		$checked = in_array( $term->term_id, $checked_terms, true ) ? 'checked="checked"' : '';
		?>

		<li id="<?php echo $id; ?>" class="popular-category">
			<label class="selectit">
				<input id="in-<?php echo $id; ?>" type="checkbox" <?php echo $checked; ?> value="<?php echo (int) $term->term_id; ?>" <?php disabled( ! current_user_can( $tax->cap->assign_terms ) ); ?> />
				<?php
				/** This filter is documented in wp-includes/category-template.php */
				echo esc_html( apply_filters( 'the_category', $term->name, '', '' ) );
				?>
			</label>
		</li>

		<?php
	}
	return $popular_ids;
}

/**
 * Outputs a link category checklist element.
 *
 * @since 2.5.1
 *
 * @param int $link_id Optional. The link ID. Default 0.
 */
function wp_link_category_checklist( $link_id = 0 ) {
	$default = 1;

	$checked_categories = array();

	if ( $link_id ) {
		$checked_categories = wp_get_link_cats( $link_id );
		// No selected categories, strange.
		if ( ! count( $checked_categories ) ) {
			$checked_categories[] = $default;
		}
	} else {
		$checked_categories[] = $default;
	}

	$categories = get_terms(
		array(
			'taxonomy'   => 'link_category',
			'orderby'    => 'name',
			'hide_empty' => 0,
		)
	);

	if ( empty( $categories ) ) {
		return;
	}

	foreach ( $categories as $category ) {
		$cat_id = $category->term_id;

		/** This filter is documented in wp-includes/category-template.php */
		$name    = esc_html( apply_filters( 'the_category', $category->name, '', '' ) );
		$checked = in_array( $cat_id, $checked_categories, true ) ? ' checked="checked"' : '';
		echo '<li id="link-category-', $cat_id, '"><label for="in-link-category-', $cat_id, '" class="selectit"><input value="', $cat_id, '" type="checkbox" name="link_category[]" id="in-link-category-', $cat_id, '"', $checked, '/> ', $name, '</label></li>';
	}
}

/**
 * Adds hidden fields with the data for use in the inline editor for posts and pages.
 *
 * @since 2.7.0
 *
 * @param WP_Post $post Post object.
 */
function get_inline_data( $post ) {
	$post_type_object = get_post_type_object( $post->post_type );
	if ( ! current_user_can( 'edit_post', $post->ID ) ) {
		return;
	}

	$title = esc_textarea( trim( $post->post_title ) );

	echo '
<div class="hidden" id="inline_' . $post->ID . '">
	<div class="post_title">' . $title . '</div>' .
	/** This filter is documented in wp-admin/edit-tag-form.php */
	'<div class="post_name">' . apply_filters( 'editable_slug', $post->post_name, $post ) . '</div>
	<div class="post_author">' . $post->post_author . '</div>
	<div class="comment_status">' . esc_html( $post->comment_status ) . '</div>
	<div class="ping_status">' . esc_html( $post->ping_status ) . '</div>
	<div class="_status">' . esc_html( $post->post_status ) . '</div>
	<div class="jj">' . mysql2date( 'd', $post->post_date, false ) . '</div>
	<div class="mm">' . mysql2date( 'm', $post->post_date, false ) . '</div>
	<div class="aa">' . mysql2date( 'Y', $post->post_date, false ) . '</div>
	<div class="hh">' . mysql2date( 'H', $post->post_date, false ) . '</div>
	<div class="mn">' . mysql2date( 'i', $post->post_date, false ) . '</div>
	<div class="ss">' . mysql2date( 's', $post->post_date, false ) . '</div>
	<div class="post_password">' . esc_html( $post->post_password ) . '</div>';

	if ( $post_type_object->hierarchical ) {
		echo '<div class="post_parent">' . $post->post_parent . '</div>';
	}

	echo '<div class="page_template">' . ( $post->page_template ? esc_html( $post->page_template ) : 'default' ) . '</div>';

	if ( post_type_supports( $post->post_type, 'page-attributes' ) ) {
		echo '<div class="menu_order">' . $post->menu_order . '</div>';
	}

	$taxonomy_names = get_object_taxonomies( $post->post_type );

	foreach ( $taxonomy_names as $taxonomy_name ) {
		$taxonomy = get_taxonomy( $taxonomy_name );

		if ( ! $taxonomy->show_in_quick_edit ) {
			continue;
		}

		if ( $taxonomy->hierarchical ) {

			$terms = get_object_term_cache( $post->ID, $taxonomy_name );
			if ( false === $terms ) {
				$terms = wp_get_object_terms( $post->ID, $taxonomy_name );
				wp_cache_add( $post->ID, wp_list_pluck( $terms, 'term_id' ), $taxonomy_name . '_relationships' );
			}
			$term_ids = empty( $terms ) ? array() : wp_list_pluck( $terms, 'term_id' );

			echo '<div class="post_category" id="' . $taxonomy_name . '_' . $post->ID . '">' . implode( ',', $term_ids ) . '</div>';

		} else {

			$terms_to_edit = get_terms_to_edit( $post->ID, $taxonomy_name );
			if ( ! is_string( $terms_to_edit ) ) {
				$terms_to_edit = '';
			}

			echo '<div class="tags_input" id="' . $taxonomy_name . '_' . $post->ID . '">'
				. esc_html( str_replace( ',', ', ', $terms_to_edit ) ) . '</div>';

		}
	}

	if ( ! $post_type_object->hierarchical ) {
		echo '<div class="sticky">' . ( is_sticky( $post->ID ) ? 'sticky' : '' ) . '</div>';
	}

	if ( post_type_supports( $post->post_type, 'post-formats' ) ) {
		echo '<div class="post_format">' . esc_html( get_post_format( $post->ID ) ) . '</div>';
	}

	/**
	 * Fires after outputting the fields for the inline editor for posts and pages.
	 *
	 * @since 4.9.8
	 *
	 * @param WP_Post      $post             The current post object.
	 * @param WP_Post_Type $post_type_object The current post's post type object.
	 */
	do_action( 'add_inline_data', $post, $post_type_object );

	echo '</div>';
}

/**
 * Outputs the in-line comment reply-to form in the Comments list table.
 *
 * @since 2.7.0
 *
 * @global WP_List_Table $wp_list_table
 *
 * @param int    $position  Optional. The value of the 'position' input field. Default 1.
 * @param bool   $checkbox  Optional. The value of the 'checkbox' input field. Default false.
 * @param string $mode      Optional. If set to 'single', will use WP_Post_Comments_List_Table,
 *                          otherwise WP_Comments_List_Table. Default 'single'.
 * @param bool   $table_row Optional. Whether to use a table instead of a div element. Default true.
 */
function wp_comment_reply( $position = 1, $checkbox = false, $mode = 'single', $table_row = true ) {
	global $wp_list_table;
	/**
	 * Filters the in-line comment reply-to form output in the Comments
	 * list table.
	 *
	 * Returning a non-empty value here will short-circuit display
	 * of the in-line comment-reply form in the Comments list table,
	 * echoing the returned value instead.
	 *
	 * @since 2.7.0
	 *
	 * @see wp_comment_reply()
	 *
	 * @param string $content The reply-to form content.
	 * @param array  $args    An array of default args.
	 */
	$content = apply_filters(
		'wp_comment_reply',
		'',
		array(
			'position' => $position,
			'checkbox' => $checkbox,
			'mode'     => $mode,
		)
	);

	if ( ! empty( $content ) ) {
		echo $content;
		return;
	}

	if ( ! $wp_list_table ) {
		if ( 'single' === $mode ) {
			$wp_list_table = _get_list_table( 'WP_Post_Comments_List_Table' );
		} else {
			$wp_list_table = _get_list_table( 'WP_Comments_List_Table' );
		}
	}

	?>
<form method="get">
	<?php if ( $table_row ) : ?>
<table style="display:none;"><tbody id="com-reply"><tr id="replyrow" class="inline-edit-row" style="display:none;"><td colspan="<?php echo $wp_list_table->get_column_count(); ?>" class="colspanchange">
<?php else : ?>
<div id="com-reply" style="display:none;"><div id="replyrow" style="display:none;">
<?php endif; ?>
	<fieldset class="comment-reply">
	<legend>
		<span class="hidden" id="editlegend"><?php _e( 'Edit Comment' ); ?></span>
		<span class="hidden" id="replyhead"><?php _e( 'Reply to Comment' ); ?></span>
		<span class="hidden" id="addhead"><?php _e( 'Add Comment' ); ?></span>
	</legend>

	<div id="replycontainer">
	<label for="replycontent" class="screen-reader-text">
		<?php
		/* translators: Hidden accessibility text. */
		_e( 'Comment' );
		?>
	</label>
	<?php
	$quicktags_settings = array( 'buttons' => 'strong,em,link,block,del,ins,img,ul,ol,li,code,close' );
	wp_editor(
		'',
		'replycontent',
		array(
			'media_buttons' => false,
			'tinymce'       => false,
			'quicktags'     => $quicktags_settings,
		)
	);
	?>
	</div>

	<div id="edithead" style="display:none;">
		<div class="inside">
		<label for="author-name"><?php _e( 'Name' ); ?></label>
		<input type="text" name="newcomment_author" size="50" value="" id="author-name" />
		</div>

		<div class="inside">
		<label for="author-email"><?php _e( 'Email' ); ?></label>
		<input type="text" name="newcomment_author_email" size="50" value="" id="author-email" />
		</div>

		<div class="inside">
		<label for="author-url"><?php _e( 'URL' ); ?></label>
		<input type="text" id="author-url" name="newcomment_author_url" class="code" size="103" value="" />
		</div>
	</div>

	<div id="replysubmit" class="submit">
		<p class="reply-submit-buttons">
			<button type="button" class="save button button-primary">
				<span id="addbtn" style="display: none;"><?php _e( 'Add Comment' ); ?></span>
				<span id="savebtn" style="display: none;"><?php _e( 'Update Comment' ); ?></span>
				<span id="replybtn" style="display: none;"><?php _e( 'Submit Reply' ); ?></span>
			</button>
			<button type="button" class="cancel button"><?php _e( 'Cancel' ); ?></button>
			<span class="waiting spinner"></span>
		</p>
		<?php
		wp_admin_notice(
			'<p class="error"></p>',
			array(
				'type'               => 'error',
				'additional_classes' => array( 'notice-alt', 'inline', 'hidden' ),
				'paragraph_wrap'     => false,
			)
		);
		?>
	</div>

	<input type="hidden" name="action" id="action" value="" />
	<input type="hidden" name="comment_ID" id="comment_ID" value="" />
	<input type="hidden" name="comment_post_ID" id="comment_post_ID" value="" />
	<input type="hidden" name="status" id="status" value="" />
	<input type="hidden" name="position" id="position" value="<?php echo $position; ?>" />
	<input type="hidden" name="checkbox" id="checkbox" value="<?php echo $checkbox ? 1 : 0; ?>" />
	<input type="hidden" name="mode" id="mode" value="<?php echo esc_attr( $mode ); ?>" />
	<?php
		wp_nonce_field( 'replyto-comment', '_ajax_nonce-replyto-comment', false );
	if ( current_user_can( 'unfiltered_html' ) ) {
		wp_nonce_field( 'unfiltered-html-comment', '_wp_unfiltered_html_comment', false );
	}
	?>
	</fieldset>
	<?php if ( $table_row ) : ?>
</td></tr></tbody></table>
	<?php else : ?>
</div></div>
	<?php endif; ?>
</form>
	<?php
}

/**
 * Outputs 'undo move to Trash' text for comments.
 *
 * @since 2.9.0
 */
function wp_comment_trashnotice() {
	?>
<div class="hidden" id="trash-undo-holder">
	<div class="trash-undo-inside">
		<?php
		/* translators: %s: Comment author, filled by Ajax. */
		printf( __( 'Comment by %s moved to the Trash.' ), '<strong></strong>' );
		?>
		<span class="undo untrash"><a href="#"><?php _e( 'Undo' ); ?></a></span>
	</div>
</div>
<div class="hidden" id="spam-undo-holder">
	<div class="spam-undo-inside">
		<?php
		/* translators: %s: Comment author, filled by Ajax. */
		printf( __( 'Comment by %s marked as spam.' ), '<strong></strong>' );
		?>
		<span class="undo unspam"><a href="#"><?php _e( 'Undo' ); ?></a></span>
	</div>
</div>
	<?php
}

/**
 * Outputs a post's public meta data in the Custom Fields meta box.
 *
 * @since 1.2.0
 *
 * @param array[] $meta An array of meta data arrays keyed on 'meta_key' and 'meta_value'.
 */
function list_meta( $meta ) {
	// Exit if no meta.
	if ( ! $meta ) {
		echo '
<table id="list-table" style="display: none;">
	<thead>
	<tr>
		<th class="left">' . _x( 'Name', 'meta name' ) . '</th>
		<th>' . __( 'Value' ) . '</th>
	</tr>
	</thead>
	<tbody id="the-list" data-wp-lists="list:meta">
	<tr><td></td></tr>
	</tbody>
</table>'; // TBODY needed for list-manipulation JS.
		return;
	}
	$count = 0;
	?>
<table id="list-table">
	<thead>
	<tr>
		<th class="left"><?php _ex( 'Name', 'meta name' ); ?></th>
		<th><?php _e( 'Value' ); ?></th>
	</tr>
	</thead>
	<tbody id='the-list' data-wp-lists='list:meta'>
	<?php
	foreach ( $meta as $entry ) {
		echo _list_meta_row( $entry, $count );
	}
	?>
	</tbody>
</table>
	<?php
}

/**
 * Outputs a single row of public meta data in the Custom Fields meta box.
 *
 * @since 2.5.0
 *
 * @param array $entry An array of meta data keyed on 'meta_key' and 'meta_value'.
 * @param int   $count Reference to the row number.
 * @return string A single row of public meta data.
 */
function _list_meta_row( $entry, &$count ) {
	static $update_nonce = '';

	if ( is_protected_meta( $entry['meta_key'], 'post' ) ) {
		return '';
	}

	if ( ! $update_nonce ) {
		$update_nonce = wp_create_nonce( 'add-meta' );
	}

	$r = '';
	++$count;

	if ( is_serialized( $entry['meta_value'] ) ) {
		if ( is_serialized_string( $entry['meta_value'] ) ) {
			// This is a serialized string, so we should display it.
			$entry['meta_value'] = maybe_unserialize( $entry['meta_value'] );
		} else {
			// This is a serialized array/object so we should NOT display it.
			--$count;
			return '';
		}
	}

	$entry['meta_key']   = esc_attr( $entry['meta_key'] );
	$entry['meta_value'] = esc_textarea( $entry['meta_value'] ); // Using a <textarea />.
	$entry['meta_id']    = (int) $entry['meta_id'];

	$delete_nonce = wp_create_nonce( 'delete-meta_' . $entry['meta_id'] );

	$r .= "\n\t<tr id='meta-{$entry['meta_id']}'>";
	$r .= "\n\t\t<td class='left'><label class='screen-reader-text' for='meta-{$entry['meta_id']}-key'>" .
		/* translators: Hidden accessibility text. */
		__( 'Key' ) .
	"</label><input name='meta[{$entry['meta_id']}][key]' id='meta-{$entry['meta_id']}-key' type='text' size='20' value='{$entry['meta_key']}' />";

	$r .= "\n\t\t<div class='submit'>";
	$r .= get_submit_button( __( 'Delete' ), 'deletemeta small', "deletemeta[{$entry['meta_id']}]", false, array( 'data-wp-lists' => "delete:the-list:meta-{$entry['meta_id']}::_ajax_nonce=$delete_nonce" ) );
	$r .= "\n\t\t";
	$r .= get_submit_button( __( 'Update' ), 'updatemeta small', "meta-{$entry['meta_id']}-submit", false, array( 'data-wp-lists' => "add:the-list:meta-{$entry['meta_id']}::_ajax_nonce-add-meta=$update_nonce" ) );
	$r .= '</div>';
	$r .= wp_nonce_field( 'change-meta', '_ajax_nonce', false, false );
	$r .= '</td>';

	$r .= "\n\t\t<td><label class='screen-reader-text' for='meta-{$entry['meta_id']}-value'>" .
		/* translators: Hidden accessibility text. */
		__( 'Value' ) .
	"</label><textarea name='meta[{$entry['meta_id']}][value]' id='meta-{$entry['meta_id']}-value' rows='2' cols='30'>{$entry['meta_value']}</textarea></td>\n\t</tr>";
	return $r;
}

/**
 * Prints the form in the Custom Fields meta box.
 *
 * @since 1.2.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param WP_Post $post Optional. The post being edited.
 */
function meta_form( $post = null ) {
	global $wpdb;
	$post = get_post( $post );

	/**
	 * Filters values for the meta key dropdown in the Custom Fields meta box.
	 *
	 * Returning a non-null value will effectively short-circuit and avoid a
	 * potentially expensive query against postmeta.
	 *
	 * @since 4.4.0
	 *
	 * @param array|null $keys Pre-defined meta keys to be used in place of a postmeta query. Default null.
	 * @param WP_Post    $post The current post object.
	 */
	$keys = apply_filters( 'postmeta_form_keys', null, $post );

	if ( null === $keys ) {
		/**
		 * Filters the number of custom fields to retrieve for the drop-down
		 * in the Custom Fields meta box.
		 *
		 * @since 2.1.0
		 *
		 * @param int $limit Number of custom fields to retrieve. Default 30.
		 */
		$limit = apply_filters( 'postmeta_form_limit', 30 );

		$keys = $wpdb->get_col(
			$wpdb->prepare(
				"SELECT DISTINCT meta_key
				FROM $wpdb->postmeta
				WHERE meta_key NOT BETWEEN '_' AND '_z'
				HAVING meta_key NOT LIKE %s
				ORDER BY meta_key
				LIMIT %d",
				$wpdb->esc_like( '_' ) . '%',
				$limit
			)
		);
	}

	if ( $keys ) {
		natcasesort( $keys );
	}
	?>
<p><strong><?php _e( 'Add Custom Field:' ); ?></strong></p>
<table id="newmeta">
<thead>
<tr>
<th class="left"><label for="metakeyselect"><?php _ex( 'Name', 'meta name' ); ?></label></th>
<th><label for="metavalue"><?php _e( 'Value' ); ?></label></th>
</tr>
</thead>

<tbody>
<tr>
<td id="newmetaleft" class="left">
	<?php if ( $keys ) { ?>
<select id="metakeyselect" name="metakeyselect">
<option value="#NONE#"><?php _e( '&mdash; Select &mdash;' ); ?></option>
		<?php
		foreach ( $keys as $key ) {
			if ( is_protected_meta( $key, 'post' ) || ! current_user_can( 'add_post_meta', $post->ID, $key ) ) {
				continue;
			}
			echo "\n<option value='" . esc_attr( $key ) . "'>" . esc_html( $key ) . '</option>';
		}
		?>
</select>
<input class="hidden" type="text" id="metakeyinput" name="metakeyinput" value="" aria-label="<?php _e( 'New custom field name' ); ?>" />
<button type="button" id="newmeta-button" class="button button-small hide-if-no-js" onclick="jQuery('#metakeyinput, #metakeyselect, #enternew, #cancelnew').toggleClass('hidden');jQuery('#metakeyinput, #metakeyselect').filter(':visible').trigger('focus');">
<span id="enternew"><?php _e( 'Enter new' ); ?></span>
<span id="cancelnew" class="hidden"><?php _e( 'Cancel' ); ?></span></button>
<?php } else { ?>
<input type="text" id="metakeyinput" name="metakeyinput" value="" />
<?php } ?>
</td>
<td><textarea id="metavalue" name="metavalue" rows="2" cols="25"></textarea>
	<?php wp_nonce_field( 'add-meta', '_ajax_nonce-add-meta', false ); ?>
</td>
</tr>
</tbody>
</table>
<div class="submit add-custom-field">
	<?php
	submit_button(
		__( 'Add Custom Field' ),
		'',
		'addmeta',
		false,
		array(
			'id'            => 'newmeta-submit',
			'data-wp-lists' => 'add:the-list:newmeta',
		)
	);
	?>
</div>
	<?php
}

/**
 * Prints out HTML form date elements for editing post or comment publish date.
 *
 * @since 0.71
 * @since 4.4.0 Converted to use get_comment() instead of the global `$comment`.
 *
 * @global WP_Locale $wp_locale WordPress date and time locale object.
 *
 * @param int|bool $edit      Accepts 1|true for editing the date, 0|false for adding the date.
 * @param int|bool $for_post  Accepts 1|true for applying the date to a post, 0|false for a comment.
 * @param int      $tab_index The tabindex attribute to add. Default 0.
 * @param int|bool $multi     Optional. Whether the additional fields and buttons should be added.
 *                            Default 0|false.
 */
function touch_time( $edit = 1, $for_post = 1, $tab_index = 0, $multi = 0 ) {
	global $wp_locale;
	$post = get_post();

	if ( $for_post ) {
		$edit = ! ( in_array( $post->post_status, array( 'draft', 'pending' ), true ) && ( ! $post->post_date_gmt || '0000-00-00 00:00:00' === $post->post_date_gmt ) );
	}

	$tab_index_attribute = '';
	if ( (int) $tab_index > 0 ) {
		$tab_index_attribute = " tabindex=\"$tab_index\"";
	}

	$post_date = ( $for_post ) ? $post->post_date : get_comment()->comment_date;
	$jj        = ( $edit ) ? mysql2date( 'd', $post_date, false ) : current_time( 'd' );
	$mm        = ( $edit ) ? mysql2date( 'm', $post_date, false ) : current_time( 'm' );
	$aa        = ( $edit ) ? mysql2date( 'Y', $post_date, false ) : current_time( 'Y' );
	$hh        = ( $edit ) ? mysql2date( 'H', $post_date, false ) : current_time( 'H' );
	$mn        = ( $edit ) ? mysql2date( 'i', $post_date, false ) : current_time( 'i' );
	$ss        = ( $edit ) ? mysql2date( 's', $post_date, false ) : current_time( 's' );

	$cur_jj = current_time( 'd' );
	$cur_mm = current_time( 'm' );
	$cur_aa = current_time( 'Y' );
	$cur_hh = current_time( 'H' );
	$cur_mn = current_time( 'i' );

	$month = '<label><span class="screen-reader-text">' .
		/* translators: Hidden accessibility text. */
		__( 'Month' ) .
	'</span><select class="form-required" ' . ( $multi ? '' : 'id="mm" ' ) . 'name="mm"' . $tab_index_attribute . ">\n";
	for ( $i = 1; $i < 13; $i = $i + 1 ) {
		$monthnum  = zeroise( $i, 2 );
		$monthtext = $wp_locale->get_month_abbrev( $wp_locale->get_month( $i ) );
		$month    .= "\t\t\t" . '<option value="' . $monthnum . '" data-text="' . $monthtext . '" ' . selected( $monthnum, $mm, false ) . '>';
		/* translators: 1: Month number (01, 02, etc.), 2: Month abbreviation. */
		$month .= sprintf( __( '%1$s-%2$s' ), $monthnum, $monthtext ) . "</option>\n";
	}
	$month .= '</select></label>';

	$day = '<label><span class="screen-reader-text">' .
		/* translators: Hidden accessibility text. */
		__( 'Day' ) .
	'</span><input type="text" ' . ( $multi ? '' : 'id="jj" ' ) . 'name="jj" value="' . $jj . '" size="2" maxlength="2"' . $tab_index_attribute . ' autocomplete="off" class="form-required" inputmode="numeric" /></label>';
	$year = '<label><span class="screen-reader-text">' .
		/* translators: Hidden accessibility text. */
		__( 'Year' ) .
	'</span><input type="text" ' . ( $multi ? '' : 'id="aa" ' ) . 'name="aa" value="' . $aa . '" size="4" maxlength="4"' . $tab_index_attribute . ' autocomplete="off" class="form-required" inputmode="numeric" /></label>';
	$hour = '<label><span class="screen-reader-text">' .
		/* translators: Hidden accessibility text. */
		__( 'Hour' ) .
	'</span><input type="text" ' . ( $multi ? '' : 'id="hh" ' ) . 'name="hh" value="' . $hh . '" size="2" maxlength="2"' . $tab_index_attribute . ' autocomplete="off" class="form-required" inputmode="numeric" /></label>';
	$minute = '<label><span class="screen-reader-text">' .
		/* translators: Hidden accessibility text. */
		__( 'Minute' ) .
	'</span><input type="text" ' . ( $multi ? '' : 'id="mn" ' ) . 'name="mn" value="' . $mn . '" size="2" maxlength="2"' . $tab_index_attribute . ' autocomplete="off" class="form-required" inputmode="numeric" /></label>';

	echo '<div class="timestamp-wrap">';
	/* translators: 1: Month, 2: Day, 3: Year, 4: Hour, 5: Minute. */
	printf( __( '%1$s %2$s, %3$s at %4$s:%5$s' ), $month, $day, $year, $hour, $minute );

	echo '</div><input type="hidden" id="ss" name="ss" value="' . $ss . '" />';

	if ( $multi ) {
		return;
	}

	echo "\n\n";

	$map = array(
		'mm' => array( $mm, $cur_mm ),
		'jj' => array( $jj, $cur_jj ),
		'aa' => array( $aa, $cur_aa ),
		'hh' => array( $hh, $cur_hh ),
		'mn' => array( $mn, $cur_mn ),
	);

	foreach ( $map as $timeunit => $value ) {
		list( $unit, $curr ) = $value;

		echo '<input type="hidden" id="hidden_' . $timeunit . '" name="hidden_' . $timeunit . '" value="' . $unit . '" />' . "\n";
		$cur_timeunit = 'cur_' . $timeunit;
		echo '<input type="hidden" id="' . $cur_timeunit . '" name="' . $cur_timeunit . '" value="' . $curr . '" />' . "\n";
	}
	?>

<p>
<a href="#edit_timestamp" class="save-timestamp hide-if-no-js button"><?php _e( 'OK' ); ?></a>
<a href="#edit_timestamp" class="cancel-timestamp hide-if-no-js button-cancel"><?php _e( 'Cancel' ); ?></a>
</p>
	<?php
}

/**
 * Prints out option HTML elements for the page templates drop-down.
 *
 * @since 1.5.0
 * @since 4.7.0 Added the `$post_type` parameter.
 *
 * @param string $default_template Optional. The template file name. Default empty.
 * @param string $post_type        Optional. Post type to get templates for. Default 'page'.
 */
function page_template_dropdown( $default_template = '', $post_type = 'page' ) {
	$templates = get_page_templates( null, $post_type );

	ksort( $templates );

	foreach ( array_keys( $templates ) as $template ) {
		$selected = selected( $default_template, $templates[ $template ], false );
		echo "\n\t<option value='" . esc_attr( $templates[ $template ] ) . "' $selected>" . esc_html( $template ) . '</option>';
	}
}

/**
 * Prints out option HTML elements for the page parents drop-down.
 *
 * @since 1.5.0
 * @since 4.4.0 `$post` argument was added.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int         $default_page Optional. The default page ID to be pre-selected. Default 0.
 * @param int         $parent_page  Optional. The parent page ID. Default 0.
 * @param int         $level        Optional. Page depth level. Default 0.
 * @param int|WP_Post $post         Post ID or WP_Post object.
 * @return void|false Void on success, false if the page has no children.
 */
function parent_dropdown( $default_page = 0, $parent_page = 0, $level = 0, $post = null ) {
	global $wpdb;

	$post  = get_post( $post );
	$items = $wpdb->get_results(
		$wpdb->prepare(
			"SELECT ID, post_parent, post_title
			FROM $wpdb->posts
			WHERE post_parent = %d AND post_type = 'page'
			ORDER BY menu_order",
			$parent_page
		)
	);

	if ( $items ) {
		foreach ( $items as $item ) {
			// A page cannot be its own parent.
			if ( $post && $post->ID && (int) $item->ID === $post->ID ) {
				continue;
			}

			$pad      = str_repeat( '&nbsp;', $level * 3 );
			$selected = selected( $default_page, $item->ID, false );

			echo "\n\t<option class='level-$level' value='$item->ID' $selected>$pad " . esc_html( $item->post_title ) . '</option>';
			parent_dropdown( $default_page, $item->ID, $level + 1 );
		}
	} else {
		return false;
	}
}

/**
 * Prints out option HTML elements for role selectors.
 *
 * @since 2.1.0
 *
 * @param string $selected Slug for the role that should be already selected.
 */
function wp_dropdown_roles( $selected = '' ) {
	$r = '';

	$editable_roles = array_reverse( get_editable_roles() );

	foreach ( $editable_roles as $role => $details ) {
		$name = translate_user_role( $details['name'] );
		// Preselect specified role.
		if ( $selected === $role ) {
			$r .= "\n\t<option selected='selected' value='" . esc_attr( $role ) . "'>$name</option>";
		} else {
			$r .= "\n\t<option value='" . esc_attr( $role ) . "'>$name</option>";
		}
	}

	echo $r;
}

/**
 * Outputs the form used by the importers to accept the data to be imported.
 *
 * @since 2.0.0
 *
 * @param string $action The action attribute for the form.
 */
function wp_import_upload_form( $action ) {

	/**
	 * Filters the maximum allowed upload size for import files.
	 *
	 * @since 2.3.0
	 *
	 * @see wp_max_upload_size()
	 *
	 * @param int $max_upload_size Allowed upload size. Default 1 MB.
	 */
	$bytes      = apply_filters( 'import_upload_size_limit', wp_max_upload_size() );
	$size       = size_format( $bytes );
	$upload_dir = wp_upload_dir();
	if ( ! empty( $upload_dir['error'] ) ) :
		$upload_directory_error  = '<p>' . __( 'Before you can upload your import file, you will need to fix the following error:' ) . '</p>';
		$upload_directory_error .= '<p><strong>' . $upload_dir['error'] . '</strong></p>';
		wp_admin_notice(
			$upload_directory_error,
			array(
				'additional_classes' => array( 'error' ),
				'paragraph_wrap'     => false,
			)
		);
	else :
		?>
<form enctype="multipart/form-data" id="import-upload-form" method="post" class="wp-upload-form" action="<?php echo esc_url( wp_nonce_url( $action, 'import-upload' ) ); ?>">
<p>
		<?php
		printf(
			'<label for="upload">%s</label> (%s)',
			__( 'Choose a file from your computer:' ),
			/* translators: %s: Maximum allowed file size. */
			sprintf( __( 'Maximum size: %s' ), $size )
		);
		?>
<input type="file" id="upload" name="import" size="25" />
<input type="hidden" name="action" value="save" />
<input type="hidden" name="max_file_size" value="<?php echo $bytes; ?>" />
</p>
		<?php submit_button( __( 'Upload file and import' ), 'primary' ); ?>
</form>
		<?php
	endif;
}

/**
 * Adds a meta box to one or more screens.
 *
 * @since 2.5.0
 * @since 4.4.0 The `$screen` parameter now accepts an array of screen IDs.
 *
 * @global array $wp_meta_boxes Global meta box state.
 *
 * @param string                 $id            Meta box ID (used in the 'id' attribute for the meta box).
 * @param string                 $title         Title of the meta box.
 * @param callable               $callback      Function that fills the box with the desired content.
 *                                              The function should echo its output.
 * @param string|array|WP_Screen $screen        Optional. The screen or screens on which to show the box
 *                                              (such as a post type, 'link', or 'comment'). Accepts a single
 *                                              screen ID, WP_Screen object, or array of screen IDs. Default
 *                                              is the current screen.  If you have used add_menu_page() or
 *                                              add_submenu_page() to create a new screen (and hence screen_id),
 *                                              make sure your menu slug conforms to the limits of sanitize_key()
 *                                              otherwise the 'screen' menu may not correctly render on your page.
 * @param string                 $context       Optional. The context within the screen where the box
 *                                              should display. Available contexts vary from screen to
 *                                              screen. Post edit screen contexts include 'normal', 'side',
 *                                              and 'advanced'. Comments screen contexts include 'normal'
 *                                              and 'side'. Menus meta boxes (accordion sections) all use
 *                                              the 'side' context. Global default is 'advanced'.
 * @param string                 $priority      Optional. The priority within the context where the box should show.
 *                                              Accepts 'high', 'core', 'default', or 'low'. Default 'default'.
 * @param array                  $callback_args Optional. Data that should be set as the $args property
 *                                              of the box array (which is the second parameter passed
 *                                              to your callback). Default null.
 */
function add_meta_box( $id, $title, $callback, $screen = null, $context = 'advanced', $priority = 'default', $callback_args = null ) {
	global $wp_meta_boxes;

	if ( empty( $screen ) ) {
		$screen = get_current_screen();
	} elseif ( is_string( $screen ) ) {
		$screen = convert_to_screen( $screen );
	} elseif ( is_array( $screen ) ) {
		foreach ( $screen as $single_screen ) {
			add_meta_box( $id, $title, $callback, $single_screen, $context, $priority, $callback_args );
		}
	}

	if ( ! isset( $screen->id ) ) {
		return;
	}

	$page = $screen->id;

	if ( ! isset( $wp_meta_boxes ) ) {
		$wp_meta_boxes = array();
	}
	if ( ! isset( $wp_meta_boxes[ $page ] ) ) {
		$wp_meta_boxes[ $page ] = array();
	}
	if ( ! isset( $wp_meta_boxes[ $page ][ $context ] ) ) {
		$wp_meta_boxes[ $page ][ $context ] = array();
	}

	foreach ( array_keys( $wp_meta_boxes[ $page ] ) as $a_context ) {
		foreach ( array( 'high', 'core', 'default', 'low' ) as $a_priority ) {
			if ( ! isset( $wp_meta_boxes[ $page ][ $a_context ][ $a_priority ][ $id ] ) ) {
				continue;
			}

			// If a core box was previously removed, don't add.
			if ( ( 'core' === $priority || 'sorted' === $priority )
				&& false === $wp_meta_boxes[ $page ][ $a_context ][ $a_priority ][ $id ]
			) {
				return;
			}

			// If a core box was previously added by a plugin, don't add.
			if ( 'core' === $priority ) {
				/*
				 * If the box was added with default priority, give it core priority
				 * to maintain sort order.
				 */
				if ( 'default' === $a_priority ) {
					$wp_meta_boxes[ $page ][ $a_context ]['core'][ $id ] = $wp_meta_boxes[ $page ][ $a_context ]['default'][ $id ];
					unset( $wp_meta_boxes[ $page ][ $a_context ]['default'][ $id ] );
				}
				return;
			}

			// If no priority given and ID already present, use existing priority.
			if ( empty( $priority ) ) {
				$priority = $a_priority;
				/*
				 * Else, if we're adding to the sorted priority, we don't know the title
				 * or callback. Grab them from the previously added context/priority.
				 */
			} elseif ( 'sorted' === $priority ) {
				$title         = $wp_meta_boxes[ $page ][ $a_context ][ $a_priority ][ $id ]['title'];
				$callback      = $wp_meta_boxes[ $page ][ $a_context ][ $a_priority ][ $id ]['callback'];
				$callback_args = $wp_meta_boxes[ $page ][ $a_context ][ $a_priority ][ $id ]['args'];
			}

			// An ID can be in only one priority and one context.
			if ( $priority !== $a_priority || $context !== $a_context ) {
				unset( $wp_meta_boxes[ $page ][ $a_context ][ $a_priority ][ $id ] );
			}
		}
	}

	if ( empty( $priority ) ) {
		$priority = 'low';
	}

	if ( ! isset( $wp_meta_boxes[ $page ][ $context ][ $priority ] ) ) {
		$wp_meta_boxes[ $page ][ $context ][ $priority ] = array();
	}

	$wp_meta_boxes[ $page ][ $context ][ $priority ][ $id ] = array(
		'id'       => $id,
		'title'    => $title,
		'callback' => $callback,
		'args'     => $callback_args,
	);
}


/**
 * Renders a "fake" meta box with an information message,
 * shown on the block editor, when an incompatible meta box is found.
 *
 * @since 5.0.0
 *
 * @param mixed $data_object The data object being rendered on this screen.
 * @param array $box         {
 *     Custom formats meta box arguments.
 *
 *     @type string   $id           Meta box 'id' attribute.
 *     @type string   $title        Meta box title.
 *     @type callable $old_callback The original callback for this meta box.
 *     @type array    $args         Extra meta box arguments.
 * }
 */
function do_block_editor_incompatible_meta_box( $data_object, $box ) {
	$plugin  = _get_plugin_from_callback( $box['old_callback'] );
	$plugins = get_plugins();
	echo '<p>';
	if ( $plugin ) {
		/* translators: %s: The name of the plugin that generated this meta box. */
		printf( __( 'This meta box, from the %s plugin, is not compatible with the block editor.' ), "<strong>{$plugin['Name']}</strong>" );
	} else {
		_e( 'This meta box is not compatible with the block editor.' );
	}
	echo '</p>';

	if ( empty( $plugins['classic-editor/classic-editor.php'] ) ) {
		if ( current_user_can( 'install_plugins' ) ) {
			$install_url = wp_nonce_url(
				self_admin_url( 'plugin-install.php?tab=favorites&user=wordpressdotorg&save=0' ),
				'save_wporg_username_' . get_current_user_id()
			);

			echo '<p>';
			/* translators: %s: A link to install the Classic Editor plugin. */
			printf( __( 'Please install the <a href="%s">Classic Editor plugin</a> to use this meta box.' ), esc_url( $install_url ) );
			echo '</p>';
		}
	} elseif ( is_plugin_inactive( 'classic-editor/classic-editor.php' ) ) {
		if ( current_user_can( 'activate_plugins' ) ) {
			$activate_url = wp_nonce_url(
				self_admin_url( 'plugins.php?action=activate&plugin=classic-editor/classic-editor.php' ),
				'activate-plugin_classic-editor/classic-editor.php'
			);

			echo '<p>';
			/* translators: %s: A link to activate the Classic Editor plugin. */
			printf( __( 'Please activate the <a href="%s">Classic Editor plugin</a> to use this meta box.' ), esc_url( $activate_url ) );
			echo '</p>';
		}
	} elseif ( $data_object instanceof WP_Post ) {
		$edit_url = add_query_arg(
			array(
				'classic-editor'         => '',
				'classic-editor__forget' => '',
			),
			get_edit_post_link( $data_object )
		);
		echo '<p>';
		/* translators: %s: A link to use the Classic Editor plugin. */
		printf( __( 'Please open the <a href="%s">classic editor</a> to use this meta box.' ), esc_url( $edit_url ) );
		echo '</p>';
	}
}

/**
 * Internal helper function to find the plugin from a meta box callback.
 *
 * @since 5.0.0
 *
 * @access private
 *
 * @param callable $callback The callback function to check.
 * @return array|null The plugin that the callback belongs to, or null if it doesn't belong to a plugin.
 */
function _get_plugin_from_callback( $callback ) {
	try {
		if ( is_array( $callback ) ) {
			$reflection = new ReflectionMethod( $callback[0], $callback[1] );
		} elseif ( is_string( $callback ) && str_contains( $callback, '::' ) ) {
			$reflection = new ReflectionMethod( $callback );
		} else {
			$reflection = new ReflectionFunction( $callback );
		}
	} catch ( ReflectionException $exception ) {
		// We could not properly reflect on the callable, so we abort here.
		return null;
	}

	// Don't show an error if it's an internal PHP function.
	if ( ! $reflection->isInternal() ) {

		// Only show errors if the meta box was registered by a plugin.
		$filename   = wp_normalize_path( $reflection->getFileName() );
		$plugin_dir = wp_normalize_path( WP_PLUGIN_DIR );

		if ( str_starts_with( $filename, $plugin_dir ) ) {
			$filename = str_replace( $plugin_dir, '', $filename );
			$filename = preg_replace( '|^/([^/]*/).*$|', '\\1', $filename );

			$plugins = get_plugins();

			foreach ( $plugins as $name => $plugin ) {
				if ( str_starts_with( $name, $filename ) ) {
					return $plugin;
				}
			}
		}
	}

	return null;
}

/**
 * Meta-Box template function.
 *
 * @since 2.5.0
 *
 * @global array $wp_meta_boxes Global meta box state.
 *
 * @param string|WP_Screen $screen      The screen identifier. If you have used add_menu_page() or
 *                                      add_submenu_page() to create a new screen (and hence screen_id)
 *                                      make sure your menu slug conforms to the limits of sanitize_key()
 *                                      otherwise the 'screen' menu may not correctly render on your page.
 * @param string           $context     The screen context for which to display meta boxes.
 * @param mixed            $data_object Gets passed to the meta box callback function as the first parameter.
 *                                      Often this is the object that's the focus of the current screen,
 *                                      for example a `WP_Post` or `WP_Comment` object.
 * @return int Number of meta_boxes.
 */
function do_meta_boxes( $screen, $context, $data_object ) {
	global $wp_meta_boxes;
	static $already_sorted = false;

	if ( empty( $screen ) ) {
		$screen = get_current_screen();
	} elseif ( is_string( $screen ) ) {
		$screen = convert_to_screen( $screen );
	}

	$page = $screen->id;

	$hidden = get_hidden_meta_boxes( $screen );

	printf( '<div id="%s-sortables" class="meta-box-sortables">', esc_attr( $context ) );

	/*
	 * Grab the ones the user has manually sorted.
	 * Pull them out of their previous context/priority and into the one the user chose.
	 */
	$sorted = get_user_option( "meta-box-order_$page" );

	if ( ! $already_sorted && $sorted ) {
		foreach ( $sorted as $box_context => $ids ) {
			foreach ( explode( ',', $ids ) as $id ) {
				if ( $id && 'dashboard_browser_nag' !== $id ) {
					add_meta_box( $id, null, null, $screen, $box_context, 'sorted' );
				}
			}
		}
	}

	$already_sorted = true;

	$i = 0;

	if ( isset( $wp_meta_boxes[ $page ][ $context ] ) ) {
		foreach ( array( 'high', 'sorted', 'core', 'default', 'low' ) as $priority ) {
			if ( isset( $wp_meta_boxes[ $page ][ $context ][ $priority ] ) ) {
				foreach ( (array) $wp_meta_boxes[ $page ][ $context ][ $priority ] as $box ) {
					if ( false === $box || ! $box['title'] ) {
						continue;
					}

					$block_compatible = true;
					if ( is_array( $box['args'] ) ) {
						// If a meta box is just here for back compat, don't show it in the block editor.
						if ( $screen->is_block_editor() && isset( $box['args']['__back_compat_meta_box'] ) && $box['args']['__back_compat_meta_box'] ) {
							continue;
						}

						if ( isset( $box['args']['__block_editor_compatible_meta_box'] ) ) {
							$block_compatible = (bool) $box['args']['__block_editor_compatible_meta_box'];
							unset( $box['args']['__block_editor_compatible_meta_box'] );
						}

						// If the meta box is declared as incompatible with the block editor, override the callback function.
						if ( ! $block_compatible && $screen->is_block_editor() ) {
							$box['old_callback'] = $box['callback'];
							$box['callback']     = 'do_block_editor_incompatible_meta_box';
						}

						if ( isset( $box['args']['__back_compat_meta_box'] ) ) {
							$block_compatible = $block_compatible || (bool) $box['args']['__back_compat_meta_box'];
							unset( $box['args']['__back_compat_meta_box'] );
						}
					}

					++$i;
					// get_hidden_meta_boxes() doesn't apply in the block editor.
					$hidden_class = ( ! $screen->is_block_editor() && in_array( $box['id'], $hidden, true ) ) ? ' hide-if-js' : '';
					echo '<div id="' . $box['id'] . '" class="postbox ' . postbox_classes( $box['id'], $page ) . $hidden_class . '" ' . '>' . "\n";

					echo '<div class="postbox-header">';
					echo '<h2 class="hndle">';
					if ( 'dashboard_php_nag' === $box['id'] ) {
						echo '<span aria-hidden="true" class="dashicons dashicons-warning"></span>';
						echo '<span class="screen-reader-text">' .
							/* translators: Hidden accessibility text. */
							__( 'Warning:' ) .
						' </span>';
					}
					echo $box['title'];
					echo "</h2>\n";

					if ( 'dashboard_browser_nag' !== $box['id'] ) {
						$widget_title = $box['title'];

						if ( is_array( $box['args'] ) && isset( $box['args']['__widget_basename'] ) ) {
							$widget_title = $box['args']['__widget_basename'];
							// Do not pass this parameter to the user callback function.
							unset( $box['args']['__widget_basename'] );
						}

						echo '<div class="handle-actions hide-if-no-js">';

						echo '<button type="button" class="handle-order-higher" aria-disabled="false" aria-describedby="' . $box['id'] . '-handle-order-higher-description">';
						echo '<span class="screen-reader-text">' .
							/* translators: Hidden accessibility text. */
							__( 'Move up' ) .
						'</span>';
						echo '<span class="order-higher-indicator" aria-hidden="true"></span>';
						echo '</button>';
						echo '<span class="hidden" id="' . $box['id'] . '-handle-order-higher-description">' . sprintf(
							/* translators: %s: Meta box title. */
							__( 'Move %s box up' ),
							$widget_title
						) . '</span>';

						echo '<button type="button" class="handle-order-lower" aria-disabled="false" aria-describedby="' . $box['id'] . '-handle-order-lower-description">';
						echo '<span class="screen-reader-text">' .
							/* translators: Hidden accessibility text. */
							__( 'Move down' ) .
						'</span>';
						echo '<span class="order-lower-indicator" aria-hidden="true"></span>';
						echo '</button>';
						echo '<span class="hidden" id="' . $box['id'] . '-handle-order-lower-description">' . sprintf(
							/* translators: %s: Meta box title. */
							__( 'Move %s box down' ),
							$widget_title
						) . '</span>';

						echo '<button type="button" class="handlediv" aria-expanded="true">';
						echo '<span class="screen-reader-text">' . sprintf(
							/* translators: %s: Hidden accessibility text. Meta box title. */
							__( 'Toggle panel: %s' ),
							$widget_title
						) . '</span>';
						echo '<span class="toggle-indicator" aria-hidden="true"></span>';
						echo '</button>';

						echo '</div>';
					}
					echo '</div>';

					echo '<div class="inside">' . "\n";

					if ( WP_DEBUG && ! $block_compatible && 'edit' === $screen->parent_base && ! $screen->is_block_editor() && ! isset( $_GET['meta-box-loader'] ) ) {
						$plugin = _get_plugin_from_callback( $box['callback'] );
						if ( $plugin ) {
							$meta_box_not_compatible_message = sprintf(
								/* translators: %s: The name of the plugin that generated this meta box. */
								__( 'This meta box, from the %s plugin, is not compatible with the block editor.' ),
								"<strong>{$plugin['Name']}</strong>"
							);
							wp_admin_notice(
								$meta_box_not_compatible_message,
								array(
									'additional_classes' => array( 'error', 'inline' ),
								)
							);
						}
					}

					call_user_func( $box['callback'], $data_object, $box );
					echo "</div>\n";
					echo "</div>\n";
				}
			}
		}
	}

	echo '</div>';

	return $i;
}

/**
 * Removes a meta box from one or more screens.
 *
 * @since 2.6.0
 * @since 4.4.0 The `$screen` parameter now accepts an array of screen IDs.
 *
 * @global array $wp_meta_boxes Global meta box state.
 *
 * @param string                 $id      Meta box ID (used in the 'id' attribute for the meta box).
 * @param string|array|WP_Screen $screen  The screen or screens on which the meta box is shown (such as a
 *                                        post type, 'link', or 'comment'). Accepts a single screen ID,
 *                                        WP_Screen object, or array of screen IDs.
 * @param string                 $context The context within the screen where the box is set to display.
 *                                        Contexts vary from screen to screen. Post edit screen contexts
 *                                        include 'normal', 'side', and 'advanced'. Comments screen contexts
 *                                        include 'normal' and 'side'. Menus meta boxes (accordion sections)
 *                                        all use the 'side' context.
 */
function remove_meta_box( $id, $screen, $context ) {
	global $wp_meta_boxes;

	if ( empty( $screen ) ) {
		$screen = get_current_screen();
	} elseif ( is_string( $screen ) ) {
		$screen = convert_to_screen( $screen );
	} elseif ( is_array( $screen ) ) {
		foreach ( $screen as $single_screen ) {
			remove_meta_box( $id, $single_screen, $context );
		}
	}

	if ( ! isset( $screen->id ) ) {
		return;
	}

	$page = $screen->id;

	if ( ! isset( $wp_meta_boxes ) ) {
		$wp_meta_boxes = array();
	}
	if ( ! isset( $wp_meta_boxes[ $page ] ) ) {
		$wp_meta_boxes[ $page ] = array();
	}
	if ( ! isset( $wp_meta_boxes[ $page ][ $context ] ) ) {
		$wp_meta_boxes[ $page ][ $context ] = array();
	}

	foreach ( array( 'high', 'core', 'default', 'low' ) as $priority ) {
		$wp_meta_boxes[ $page ][ $context ][ $priority ][ $id ] = false;
	}
}

/**
 * Meta Box Accordion Template Function.
 *
 * Largely made up of abstracted code from do_meta_boxes(), this
 * function serves to build meta boxes as list items for display as
 * a collapsible accordion.
 *
 * @since 3.6.0
 *
 * @uses global $wp_meta_boxes Used to retrieve registered meta boxes.
 *
 * @param string|object $screen      The screen identifier.
 * @param string        $context     The screen context for which to display accordion sections.
 * @param mixed         $data_object Gets passed to the section callback function as the first parameter.
 * @return int Number of meta boxes as accordion sections.
 */
function do_accordion_sections( $screen, $context, $data_object ) {
	global $wp_meta_boxes;

	wp_enqueue_script( 'accordion' );

	if ( empty( $screen ) ) {
		$screen = get_current_screen();
	} elseif ( is_string( $screen ) ) {
		$screen = convert_to_screen( $screen );
	}

	$page = $screen->id;

	$hidden = get_hidden_meta_boxes( $screen );
	?>
	<div id="side-sortables" class="accordion-container">
		<ul class="outer-border">
	<?php
	$i          = 0;
	$first_open = false;

	if ( isset( $wp_meta_boxes[ $page ][ $context ] ) ) {
		foreach ( array( 'high', 'core', 'default', 'low' ) as $priority ) {
			if ( isset( $wp_meta_boxes[ $page ][ $context ][ $priority ] ) ) {
				foreach ( $wp_meta_boxes[ $page ][ $context ][ $priority ] as $box ) {
					if ( false === $box || ! $box['title'] ) {
						continue;
					}

					++$i;
					$hidden_class = in_array( $box['id'], $hidden, true ) ? 'hide-if-js' : '';

					$open_class    = '';
					$aria_expanded = 'false';
					if ( ! $first_open && empty( $hidden_class ) ) {
						$first_open    = true;
						$open_class    = 'open';
						$aria_expanded = 'true';
					}
					?>
					<li class="control-section accordion-section <?php echo $hidden_class; ?> <?php echo $open_class; ?> <?php echo esc_attr( $box['id'] ); ?>" id="<?php echo esc_attr( $box['id'] ); ?>">
						<h3 class="accordion-section-title hndle">
							<button type="button" class="accordion-trigger" aria-expanded="<?php echo $aria_expanded; ?>" aria-controls="<?php echo esc_attr( $box['id'] ); ?>-content">
								<span class="accordion-title">
									<?php echo esc_html( $box['title'] ); ?>
									<span class="dashicons dashicons-arrow-down" aria-hidden="true"></span>
								</span>
							</button>
						</h3>
						<div class="accordion-section-content <?php postbox_classes( $box['id'], $page ); ?>" id="<?php echo esc_attr( $box['id'] ); ?>-content">
							<div class="inside">
								<?php call_user_func( $box['callback'], $data_object, $box ); ?>
							</div><!-- .inside -->
						</div><!-- .accordion-section-content -->
					</li><!-- .accordion-section -->
					<?php
				}
			}
		}
	}
	?>
		</ul><!-- .outer-border -->
	</div><!-- .accordion-container -->
	<?php
	return $i;
}

/**
 * Adds a new section to a settings page.
 *
 * Part of the Settings API. Use this to define new settings sections for an admin page.
 * Show settings sections in your admin page callback function with do_settings_sections().
 * Add settings fields to your section with add_settings_field().
 *
 * The $callback argument should be the name of a function that echoes out any
 * content you want to show at the top of the settings section before the actual
 * fields. It can output nothing if you want.
 *
 * @since 2.7.0
 * @since 6.1.0 Added an `$args` parameter for the section's HTML wrapper and class name.
 *
 * @global array $wp_settings_sections Storage array of all settings sections added to admin pages.
 *
 * @param string   $id       Slug-name to identify the section. Used in the 'id' attribute of tags.
 * @param string   $title    Formatted title of the section. Shown as the heading for the section.
 * @param callable $callback Function that echos out any content at the top of the section (between heading and fields).
 * @param string   $page     The slug-name of the settings page on which to show the section. Built-in pages include
 *                           'general', 'reading', 'writing', 'discussion', 'media', etc. Create your own using
 *                           add_options_page();
 * @param array    $args     {
 *     Arguments used to create the settings section.
 *
 *     @type string $before_section HTML content to prepend to the section's HTML output.
 *                                  Receives the section's class name as `%s`. Default empty.
 *     @type string $after_section  HTML content to append to the section's HTML output. Default empty.
 *     @type string $section_class  The class name to use for the section. Default empty.
 * }
 */
function add_settings_section( $id, $title, $callback, $page, $args = array() ) {
	global $wp_settings_sections;

	$defaults = array(
		'id'             => $id,
		'title'          => $title,
		'callback'       => $callback,
		'before_section' => '',
		'after_section'  => '',
		'section_class'  => '',
	);

	$section = wp_parse_args( $args, $defaults );

	if ( 'misc' === $page ) {
		_deprecated_argument(
			__FUNCTION__,
			'3.0.0',
			sprintf(
				/* translators: %s: misc */
				__( 'The "%s" options group has been removed. Use another settings group.' ),
				'misc'
			)
		);
		$page = 'general';
	}

	if ( 'privacy' === $page ) {
		_deprecated_argument(
			__FUNCTION__,
			'3.5.0',
			sprintf(
				/* translators: %s: privacy */
				__( 'The "%s" options group has been removed. Use another settings group.' ),
				'privacy'
			)
		);
		$page = 'reading';
	}

	$wp_settings_sections[ $page ][ $id ] = $section;
}

/**
 * Adds a new field to a section of a settings page.
 *
 * Part of the Settings API. Use this to define a settings field that will show
 * as part of a settings section inside a settings page. The fields are shown using
 * do_settings_fields() in do_settings_sections().
 *
 * The $callback argument should be the name of a function that echoes out the
 * HTML input tags for this setting field. Use get_option() to retrieve existing
 * values to show.
 *
 * @since 2.7.0
 * @since 4.2.0 The `$class` argument was added.
 *
 * @global array $wp_settings_fields Storage array of settings fields and info about their pages/sections.
 *
 * @param string   $id       Slug-name to identify the field. Used in the 'id' attribute of tags.
 * @param string   $title    Formatted title of the field. Shown as the label for the field
 *                           during output.
 * @param callable $callback Function that fills the field with the desired form inputs. The
 *                           function should echo its output.
 * @param string   $page     The slug-name of the settings page on which to show the section
 *                           (general, reading, writing, ...).
 * @param string   $section  Optional. The slug-name of the section of the settings page
 *                           in which to show the box. Default 'default'.
 * @param array    $args {
 *     Optional. Extra arguments that get passed to the callback function.
 *
 *     @type string $label_for When supplied, the setting title will be wrapped
 *                             in a `<label>` element, its `for` attribute populated
 *                             with this value.
 *     @type string $class     CSS Class to be added to the `<tr>` element when the
 *                             field is output.
 * }
 */
function add_settings_field( $id, $title, $callback, $page, $section = 'default', $args = array() ) {
	global $wp_settings_fields;

	if ( 'misc' === $page ) {
		_deprecated_argument(
			__FUNCTION__,
			'3.0.0',
			sprintf(
				/* translators: %s: misc */
				__( 'The "%s" options group has been removed. Use another settings group.' ),
				'misc'
			)
		);
		$page = 'general';
	}

	if ( 'privacy' === $page ) {
		_deprecated_argument(
			__FUNCTION__,
			'3.5.0',
			sprintf(
				/* translators: %s: privacy */
				__( 'The "%s" options group has been removed. Use another settings group.' ),
				'privacy'
			)
		);
		$page = 'reading';
	}

	$wp_settings_fields[ $page ][ $section ][ $id ] = array(
		'id'       => $id,
		'title'    => $title,
		'callback' => $callback,
		'args'     => $args,
	);
}

/**
 * Prints out all settings sections added to a particular settings page.
 *
 * Part of the Settings API. Use this in a settings page callback function
 * to output all the sections and fields that were added to that $page with
 * add_settings_section() and add_settings_field()
 *
 * @since 2.7.0
 *
 * @global array $wp_settings_sections Storage array of all settings sections added to admin pages.
 * @global array $wp_settings_fields Storage array of settings fields and info about their pages/sections.
 *
 * @param string $page The slug name of the page whose settings sections you want to output.
 */
function do_settings_sections( $page ) {
	global $wp_settings_sections, $wp_settings_fields;

	if ( ! isset( $wp_settings_sections[ $page ] ) ) {
		return;
	}

	foreach ( (array) $wp_settings_sections[ $page ] as $section ) {
		if ( '' !== $section['before_section'] ) {
			if ( '' !== $section['section_class'] ) {
				echo wp_kses_post( sprintf( $section['before_section'], esc_attr( $section['section_class'] ) ) );
			} else {
				echo wp_kses_post( $section['before_section'] );
			}
		}

		if ( $section['title'] ) {
			echo "<h2>{$section['title']}</h2>\n";
		}

		if ( $section['callback'] ) {
			call_user_func( $section['callback'], $section );
		}

		if ( isset( $wp_settings_fields[ $page ][ $section['id'] ] ) ) {
			echo '<table class="form-table" role="presentation">';
			do_settings_fields( $page, $section['id'] );
			echo '</table>';
		}

		if ( '' !== $section['after_section'] ) {
			echo wp_kses_post( $section['after_section'] );
		}
	}
}

/**
 * Prints out the settings fields for a particular settings section.
 *
 * Part of the Settings API. Use this in a settings page to output
 * a specific section. Should normally be called by do_settings_sections()
 * rather than directly.
 *
 * @since 2.7.0
 *
 * @global array $wp_settings_fields Storage array of settings fields and their pages/sections.
 *
 * @param string $page Slug title of the admin page whose settings fields you want to show.
 * @param string $section Slug title of the settings section whose fields you want to show.
 */
function do_settings_fields( $page, $section ) {
	global $wp_settings_fields;

	if ( ! isset( $wp_settings_fields[ $page ][ $section ] ) ) {
		return;
	}

	foreach ( (array) $wp_settings_fields[ $page ][ $section ] as $field ) {
		$class = '';

		if ( ! empty( $field['args']['class'] ) ) {
			$class = ' class="' . esc_attr( $field['args']['class'] ) . '"';
		}

		echo "<tr{$class}>";

		if ( ! empty( $field['args']['label_for'] ) ) {
			echo '<th scope="row"><label for="' . esc_attr( $field['args']['label_for'] ) . '">' . $field['title'] . '</label></th>';
		} else {
			echo '<th scope="row">' . $field['title'] . '</th>';
		}

		echo '<td>';
		call_user_func( $field['callback'], $field['args'] );
		echo '</td>';
		echo '</tr>';
	}
}

/**
 * Registers a settings error to be displayed to the user.
 *
 * Part of the Settings API. Use this to show messages to users about settings validation
 * problems, missing settings or anything else.
 *
 * Settings errors should be added inside the $sanitize_callback function defined in
 * register_setting() for a given setting to give feedback about the submission.
 *
 * By default messages will show immediately after the submission that generated the error.
 * Additional calls to settings_errors() can be used to show errors even when the settings
 * page is first accessed.
 *
 * @since 3.0.0
 * @since 5.3.0 Added `warning` and `info` as possible values for `$type`.
 *
 * @global array[] $wp_settings_errors Storage array of errors registered during this pageload
 *
 * @param string $setting Slug title of the setting to which this error applies.
 * @param string $code    Slug-name to identify the error. Used as part of 'id' attribute in HTML output.
 * @param string $message The formatted message text to display to the user (will be shown inside styled
 *                        `<div>` and `<p>` tags).
 * @param string $type    Optional. Message type, controls HTML class. Possible values include 'error',
 *                        'success', 'warning', 'info'. Default 'error'.
 */
function add_settings_error( $setting, $code, $message, $type = 'error' ) {
	global $wp_settings_errors;

	$wp_settings_errors[] = array(
		'setting' => $setting,
		'code'    => $code,
		'message' => $message,
		'type'    => $type,
	);
}

/**
 * Fetches settings errors registered by add_settings_error().
 *
 * Checks the $wp_settings_errors array for any errors declared during the current
 * pageload and returns them.
 *
 * If changes were just submitted ($_GET['settings-updated']) and settings errors were saved
 * to the 'settings_errors' transient then those errors will be returned instead. This
 * is used to pass errors back across pageloads.
 *
 * Use the $sanitize argument to manually re-sanitize the option before returning errors.
 * This is useful if you have errors or notices you want to show even when the user
 * hasn't submitted data (i.e. when they first load an options page, or in the {@see 'admin_notices'}
 * action hook).
 *
 * @since 3.0.0
 *
 * @global array[] $wp_settings_errors Storage array of errors registered during this pageload
 *
 * @param string $setting  Optional. Slug title of a specific setting whose errors you want.
 * @param bool   $sanitize Optional. Whether to re-sanitize the setting value before returning errors.
 * @return array[] {
 *     Array of settings error arrays.
 *
 *     @type array ...$0 {
 *         Associative array of setting error data.
 *
 *         @type string $setting Slug title of the setting to which this error applies.
 *         @type string $code    Slug-name to identify the error. Used as part of 'id' attribute in HTML output.
 *         @type string $message The formatted message text to display to the user (will be shown inside styled
 *                               `<div>` and `<p>` tags).
 *         @type string $type    Optional. Message type, controls HTML class. Possible values include 'error',
 *                               'success', 'warning', 'info'. Default 'error'.
 *     }
 * }
 */
function get_settings_errors( $setting = '', $sanitize = false ) {
	global $wp_settings_errors;

	/*
	 * If $sanitize is true, manually re-run the sanitization for this option
	 * This allows the $sanitize_callback from register_setting() to run, adding
	 * any settings errors you want to show by default.
	 */
	if ( $sanitize ) {
		sanitize_option( $setting, get_option( $setting ) );
	}

	// If settings were passed back from options.php then use them.
	if ( isset( $_GET['settings-updated'] ) && $_GET['settings-updated'] && get_transient( 'settings_errors' ) ) {
		$wp_settings_errors = array_merge( (array) $wp_settings_errors, get_transient( 'settings_errors' ) );
		delete_transient( 'settings_errors' );
	}

	// Check global in case errors have been added on this pageload.
	if ( empty( $wp_settings_errors ) ) {
		return array();
	}

	// Filter the results to those of a specific setting if one was set.
	if ( $setting ) {
		$setting_errors = array();

		foreach ( (array) $wp_settings_errors as $key => $details ) {
			if ( $setting === $details['setting'] ) {
				$setting_errors[] = $wp_settings_errors[ $key ];
			}
		}

		return $setting_errors;
	}

	return $wp_settings_errors;
}

/**
 * Displays settings errors registered by add_settings_error().
 *
 * Part of the Settings API. Outputs a div for each error retrieved by
 * get_settings_errors().
 *
 * This is called automatically after a settings page based on the
 * Settings API is submitted. Errors should be added during the validation
 * callback function for a setting defined in register_setting().
 *
 * The $sanitize option is passed into get_settings_errors() and will
 * re-run the setting sanitization
 * on its current value.
 *
 * The $hide_on_update option will cause errors to only show when the settings
 * page is first loaded. if the user has already saved new values it will be
 * hidden to avoid repeating messages already shown in the default error
 * reporting after submission. This is useful to show general errors like
 * missing settings when the user arrives at the settings page.
 *
 * @since 3.0.0
 * @since 5.3.0 Legacy `error` and `updated` CSS classes are mapped to
 *              `notice-error` and `notice-success`.
 *
 * @param string $setting        Optional slug title of a specific setting whose errors you want.
 * @param bool   $sanitize       Whether to re-sanitize the setting value before returning errors.
 * @param bool   $hide_on_update If set to true errors will not be shown if the settings page has
 *                               already been submitted.
 */
function settings_errors( $setting = '', $sanitize = false, $hide_on_update = false ) {

	if ( $hide_on_update && ! empty( $_GET['settings-updated'] ) ) {
		return;
	}

	$settings_errors = get_settings_errors( $setting, $sanitize );

	if ( empty( $settings_errors ) ) {
		return;
	}

	$output = '';

	foreach ( $settings_errors as $key => $details ) {
		if ( 'updated' === $details['type'] ) {
			$details['type'] = 'success';
		}

		if ( in_array( $details['type'], array( 'error', 'success', 'warning', 'info' ), true ) ) {
			$details['type'] = 'notice-' . $details['type'];
		}

		$css_id    = sprintf(
			'setting-error-%s',
			esc_attr( $details['code'] )
		);
		$css_class = sprintf(
			'notice %s settings-error is-dismissible',
			esc_attr( $details['type'] )
		);

		$output .= "<div id='$css_id' class='$css_class'> \n";
		$output .= "<p><strong>{$details['message']}</strong></p>";
		$output .= "</div> \n";
	}

	echo $output;
}

/**
 * Outputs the modal window used for attaching media to posts or pages in the media-listing screen.
 *
 * @since 2.7.0
 *
 * @param string $found_action Optional. The value of the 'found_action' input field. Default empty string.
 */
function find_posts_div( $found_action = '' ) {
	?>
	<div id="find-posts" class="find-box" style="display: none;">
		<div id="find-posts-head" class="find-box-head">
			<?php _e( 'Attach to existing content' ); ?>
			<button type="button" id="find-posts-close"><span class="screen-reader-text">
				<?php
				/* translators: Hidden accessibility text. */
				_e( 'Close media attachment panel' );
				?>
			</span></button>
		</div>
		<div class="find-box-inside">
			<div class="find-box-search">
				<?php if ( $found_action ) { ?>
					<input type="hidden" name="found_action" value="<?php echo esc_attr( $found_action ); ?>" />
				<?php } ?>
				<input type="hidden" name="affected" id="affected" value="" />
				<?php wp_nonce_field( 'find-posts', '_ajax_nonce', false ); ?>
				<label class="screen-reader-text" for="find-posts-input">
					<?php
					/* translators: Hidden accessibility text. */
					_e( 'Search' );
					?>
				</label>
				<input type="text" id="find-posts-input" name="ps" value="" />
				<span class="spinner"></span>
				<input type="button" id="find-posts-search" value="<?php esc_attr_e( 'Search' ); ?>" class="button" />
				<div class="clear"></div>
			</div>
			<div id="find-posts-response"></div>
		</div>
		<div class="find-box-buttons">
			<?php submit_button( __( 'Select' ), 'primary alignright', 'find-posts-submit', false ); ?>
			<div class="clear"></div>
		</div>
	</div>
	<?php
}

/**
 * Displays the post password.
 *
 * The password is passed through esc_attr() to ensure that it is safe for placing in an HTML attribute.
 *
 * @since 2.7.0
 */
function the_post_password() {
	$post = get_post();
	if ( isset( $post->post_password ) ) {
		echo esc_attr( $post->post_password );
	}
}

/**
 * Gets the post title.
 *
 * The post title is fetched and if it is blank then a default string is
 * returned.
 *
 * @since 2.7.0
 *
 * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post.
 * @return string The post title if set.
 */
function _draft_or_post_title( $post = 0 ) {
	$title = get_the_title( $post );
	if ( empty( $title ) ) {
		$title = __( '(no title)' );
	}
	return esc_html( $title );
}

/**
 * Displays the search query.
 *
 * A simple wrapper to display the "s" parameter in a `GET` URI. This function
 * should only be used when the_search_query() cannot.
 *
 * @since 2.7.0
 */
function _admin_search_query() {
	echo isset( $_REQUEST['s'] ) ? esc_attr( wp_unslash( $_REQUEST['s'] ) ) : '';
}

/**
 * Generic Iframe header for use with Thickbox.
 *
 * @since 2.7.0
 *
 * @global string    $hook_suffix
 * @global string    $admin_body_class
 * @global string    $body_id
 * @global WP_Locale $wp_locale        WordPress date and time locale object.
 *
 * @param string $title      Optional. Title of the Iframe page. Default empty.
 * @param bool   $deprecated Not used.
 */
function iframe_header( $title = '', $deprecated = false ) {
	global $hook_suffix, $admin_body_class, $body_id, $wp_locale;

	show_admin_bar( false );

	$admin_body_class = preg_replace( '/[^a-z0-9_-]+/i', '-', $hook_suffix );

	$current_screen = get_current_screen();

	header( 'Content-Type: ' . get_option( 'html_type' ) . '; charset=' . get_option( 'blog_charset' ) );
	_wp_admin_html_begin();
	?>
<title><?php bloginfo( 'name' ); ?> &rsaquo; <?php echo $title; ?> &#8212; <?php _e( 'WordPress' ); ?></title>
	<?php
	wp_enqueue_style( 'colors' );
	?>
<script type="text/javascript">
addLoadEvent = function(func){if(typeof jQuery!=='undefined')jQuery(function(){func();});else if(typeof wpOnload!=='function'){wpOnload=func;}else{var oldonload=wpOnload;wpOnload=function(){oldonload();func();}}};
function tb_close(){var win=window.dialogArguments||opener||parent||top;win.tb_remove();}
var ajaxurl = '<?php echo esc_js( admin_url( 'admin-ajax.php', 'relative' ) ); ?>',
	pagenow = '<?php echo esc_js( $current_screen->id ); ?>',
	typenow = '<?php echo esc_js( $current_screen->post_type ); ?>',
	adminpage = '<?php echo esc_js( $admin_body_class ); ?>',
	thousandsSeparator = '<?php echo esc_js( $wp_locale->number_format['thousands_sep'] ); ?>',
	decimalPoint = '<?php echo esc_js( $wp_locale->number_format['decimal_point'] ); ?>',
	isRtl = <?php echo (int) is_rtl(); ?>;
</script>
	<?php
	/** This action is documented in wp-admin/admin-header.php */
	do_action( 'admin_enqueue_scripts', $hook_suffix );

	/** This action is documented in wp-admin/admin-header.php */
	do_action( "admin_print_styles-{$hook_suffix}" );  // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores

	/** This action is documented in wp-admin/admin-header.php */
	do_action( 'admin_print_styles' );

	/** This action is documented in wp-admin/admin-header.php */
	do_action( "admin_print_scripts-{$hook_suffix}" ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores

	/** This action is documented in wp-admin/admin-header.php */
	do_action( 'admin_print_scripts' );

	/** This action is documented in wp-admin/admin-header.php */
	do_action( "admin_head-{$hook_suffix}" ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores

	/** This action is documented in wp-admin/admin-header.php */
	do_action( 'admin_head' );

	$admin_body_class .= ' locale-' . sanitize_html_class( strtolower( str_replace( '_', '-', get_user_locale() ) ) );

	if ( is_rtl() ) {
		$admin_body_class .= ' rtl';
	}

	?>
</head>
	<?php
	$admin_body_id = isset( $body_id ) ? 'id="' . $body_id . '" ' : '';

	/** This filter is documented in wp-admin/admin-header.php */
	$admin_body_classes = apply_filters( 'admin_body_class', '' );
	$admin_body_classes = ltrim( $admin_body_classes . ' ' . $admin_body_class );
	?>
<body <?php echo $admin_body_id; ?>class="wp-admin wp-core-ui no-js iframe <?php echo esc_attr( $admin_body_classes ); ?>">
<script type="text/javascript">
(function(){
var c = document.body.className;
c = c.replace(/no-js/, 'js');
document.body.className = c;
})();
</script>
	<?php
}

/**
 * Generic Iframe footer for use with Thickbox.
 *
 * @since 2.7.0
 */
function iframe_footer() {
	/*
	 * We're going to hide any footer output on iFrame pages,
	 * but run the hooks anyway since they output JavaScript
	 * or other needed content.
	 */

	/**
	 * @global string $hook_suffix
	 */
	global $hook_suffix;
	?>
	<div class="hidden">
	<?php
	/** This action is documented in wp-admin/admin-footer.php */
	do_action( 'admin_footer', $hook_suffix );

	/** This action is documented in wp-admin/admin-footer.php */
	do_action( "admin_print_footer_scripts-{$hook_suffix}" ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores

	/** This action is documented in wp-admin/admin-footer.php */
	do_action( 'admin_print_footer_scripts' );
	?>
	</div>
<script type="text/javascript">if(typeof wpOnload==='function')wpOnload();</script>
</body>
</html>
	<?php
}

/**
 * Echoes or returns the post states as HTML.
 *
 * @since 2.7.0
 * @since 5.3.0 Added the `$display` parameter and a return value.
 *
 * @see get_post_states()
 *
 * @param WP_Post $post    The post to retrieve states for.
 * @param bool    $display Optional. Whether to display the post states as an HTML string.
 *                         Default true.
 * @return string Post states string.
 */
function _post_states( $post, $display = true ) {
	$post_states      = get_post_states( $post );
	$post_states_html = '';

	if ( ! empty( $post_states ) ) {
		$state_count = count( $post_states );

		$i = 0;

		$post_states_html .= ' &mdash; ';

		foreach ( $post_states as $state ) {
			++$i;

			$separator = ( $i < $state_count ) ? ', ' : '';

			$post_states_html .= "<span class='post-state'>{$state}{$separator}</span>";
		}
	}

	/**
	 * Filters the HTML string of post states.
	 *
	 * @since 6.9.0
	 *
	 * @param string                 $post_states_html All relevant post states combined into an HTML string for display.
	 *                                                 E.g. `&mdash; <span class='post-state'>Draft, </span><span class='post-state'>Sticky</span>`.
	 * @param array<string, string>  $post_states      A mapping of post state slugs to translated post state labels.
	 *                                                 E.g. `array( 'draft' => __( 'Draft' ), 'sticky' => __( 'Sticky' ), ... )`.
	 * @param WP_Post                $post             The current post object.
	 */
	$post_states_html = apply_filters( 'post_states_html', $post_states_html, $post_states, $post );

	if ( $display ) {
		echo $post_states_html;
	}

	return $post_states_html;
}

/**
 * Retrieves an array of post states from a post.
 *
 * @since 5.3.0
 *
 * @param WP_Post $post The post to retrieve states for.
 * @return string[] Array of post state labels keyed by their state.
 */
function get_post_states( $post ) {
	$post_states = array();

	if ( isset( $_REQUEST['post_status'] ) ) {
		$post_status = $_REQUEST['post_status'];
	} else {
		$post_status = '';
	}

	if ( ! empty( $post->post_password ) ) {
		$post_states['protected'] = _x( 'Password protected', 'post status' );
	}

	if ( 'private' === $post->post_status && 'private' !== $post_status ) {
		$post_states['private'] = _x( 'Private', 'post status' );
	}

	if ( 'draft' === $post->post_status ) {
		if ( get_post_meta( $post->ID, '_customize_changeset_uuid', true ) ) {
			$post_states[] = __( 'Customization Draft' );
		} elseif ( 'draft' !== $post_status ) {
			$post_states['draft'] = _x( 'Draft', 'post status' );
		}
	} elseif ( 'trash' === $post->post_status && get_post_meta( $post->ID, '_customize_changeset_uuid', true ) ) {
		$post_states[] = _x( 'Customization Draft', 'post status' );
	}

	if ( 'pending' === $post->post_status && 'pending' !== $post_status ) {
		$post_states['pending'] = _x( 'Pending', 'post status' );
	}

	if ( is_sticky( $post->ID ) ) {
		$post_states['sticky'] = _x( 'Sticky', 'post status' );
	}

	if ( 'future' === $post->post_status ) {
		$post_states['scheduled'] = _x( 'Scheduled', 'post status' );
	}

	if ( 'page' === get_option( 'show_on_front' ) ) {
		if ( (int) get_option( 'page_on_front' ) === $post->ID ) {
			$post_states['page_on_front'] = _x( 'Front Page', 'page label' );
		}

		if ( (int) get_option( 'page_for_posts' ) === $post->ID ) {
			$post_states['page_for_posts'] = _x( 'Posts Page', 'page label' );
		}
	}

	if ( (int) get_option( 'wp_page_for_privacy_policy' ) === $post->ID ) {
		$post_states['page_for_privacy_policy'] = _x( 'Privacy Policy Page', 'page label' );
	}

	/**
	 * Filters the default post display states used in the posts list table.
	 *
	 * @since 2.8.0
	 * @since 3.6.0 Added the `$post` parameter.
	 * @since 5.5.0 Also applied in the Customizer context. If any admin functions
	 *              are used within the filter, their existence should be checked
	 *              with `function_exists()` before being used.
	 *
	 * @param array<string, string>  $post_states A mapping of post state slugs to translated post state labels.
	 *                                            E.g. `array( 'draft' => __( 'Draft' ), 'sticky' => __( 'Sticky' ), ... )`.
	 * @param WP_Post                $post        The current post object.
	 */
	return apply_filters( 'display_post_states', $post_states, $post );
}

/**
 * Outputs the attachment media states as HTML.
 *
 * @since 3.2.0
 * @since 5.6.0 Added the `$display` parameter and a return value.
 *
 * @param WP_Post $post    The attachment post to retrieve states for.
 * @param bool    $display Optional. Whether to display the post states as an HTML string.
 *                         Default true.
 * @return string Media states string.
 */
function _media_states( $post, $display = true ) {
	$media_states        = get_media_states( $post );
	$media_states_string = '';

	if ( ! empty( $media_states ) ) {
		$state_count = count( $media_states );

		$i = 0;

		$media_states_string .= ' &mdash; ';

		foreach ( $media_states as $state ) {
			++$i;

			$separator = ( $i < $state_count ) ? ', ' : '';

			$media_states_string .= "<span class='post-state'>{$state}{$separator}</span>";
		}
	}

	if ( $display ) {
		echo $media_states_string;
	}

	return $media_states_string;
}

/**
 * Retrieves an array of media states from an attachment.
 *
 * @since 5.6.0
 *
 * @param WP_Post $post The attachment to retrieve states for.
 * @return string[] Array of media state labels keyed by their state.
 */
function get_media_states( $post ) {
	static $header_images;

	$media_states = array();
	$stylesheet   = get_option( 'stylesheet' );

	if ( current_theme_supports( 'custom-header' ) ) {
		$meta_header = get_post_meta( $post->ID, '_wp_attachment_is_custom_header', true );

		if ( is_random_header_image() ) {
			if ( ! isset( $header_images ) ) {
				$header_images = wp_list_pluck( get_uploaded_header_images(), 'attachment_id' );
			}

			if ( $meta_header === $stylesheet && in_array( $post->ID, $header_images, true ) ) {
				$media_states[] = __( 'Header Image' );
			}
		} else {
			$header_image = get_header_image();

			// Display "Header Image" if the image was ever used as a header image.
			if ( ! empty( $meta_header ) && $meta_header === $stylesheet && wp_get_attachment_url( $post->ID ) !== $header_image ) {
				$media_states[] = __( 'Header Image' );
			}

			// Display "Current Header Image" if the image is currently the header image.
			if ( $header_image && wp_get_attachment_url( $post->ID ) === $header_image ) {
				$media_states[] = __( 'Current Header Image' );
			}
		}

		if ( get_theme_support( 'custom-header', 'video' ) && has_header_video() ) {
			$mods = get_theme_mods();
			if ( isset( $mods['header_video'] ) && $post->ID === $mods['header_video'] ) {
				$media_states[] = __( 'Current Header Video' );
			}
		}
	}

	if ( current_theme_supports( 'custom-background' ) ) {
		$meta_background = get_post_meta( $post->ID, '_wp_attachment_is_custom_background', true );

		if ( ! empty( $meta_background ) && $meta_background === $stylesheet ) {
			$media_states[] = __( 'Background Image' );

			$background_image = get_background_image();
			if ( $background_image && wp_get_attachment_url( $post->ID ) === $background_image ) {
				$media_states[] = __( 'Current Background Image' );
			}
		}
	}

	if ( (int) get_option( 'site_icon' ) === $post->ID ) {
		$media_states[] = __( 'Site Icon' );
	}

	if ( (int) get_theme_mod( 'custom_logo' ) === $post->ID ) {
		$media_states[] = __( 'Logo' );
	}

	/**
	 * Filters the default media display states for items in the Media list table.
	 *
	 * @since 3.2.0
	 * @since 4.8.0 Added the `$post` parameter.
	 *
	 * @param string[] $media_states An array of media states. Default 'Header Image',
	 *                               'Background Image', 'Site Icon', 'Logo'.
	 * @param WP_Post  $post         The current attachment object.
	 */
	return apply_filters( 'display_media_states', $media_states, $post );
}

/**
 * Tests support for compressing JavaScript from PHP.
 *
 * Outputs JavaScript that tests if compression from PHP works as expected
 * and sets an option with the result. Has no effect when the current user
 * is not an administrator. To run the test again the option 'can_compress_scripts'
 * has to be deleted.
 *
 * @since 2.8.0
 */
function compression_test() {
	?>
	<script type="text/javascript">
	var compressionNonce = <?php echo wp_json_encode( wp_create_nonce( 'update_can_compress_scripts' ), JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ); ?>;
	var testCompression = {
		get : function(test) {
			var x;
			if ( window.XMLHttpRequest ) {
				x = new XMLHttpRequest();
			} else {
				try{x=new ActiveXObject('Msxml2.XMLHTTP');}catch(e){try{x=new ActiveXObject('Microsoft.XMLHTTP');}catch(e){};}
			}

			if (x) {
				x.onreadystatechange = function() {
					var r, h;
					if ( x.readyState == 4 ) {
						r = x.responseText.substr(0, 18);
						h = x.getResponseHeader('Content-Encoding');
						testCompression.check(r, h, test);
					}
				};

				x.open('GET', ajaxurl + '?action=wp-compression-test&test='+test+'&_ajax_nonce='+compressionNonce+'&'+(new Date()).getTime(), true);
				x.send('');
			}
		},

		check : function(r, h, test) {
			if ( ! r && ! test )
				this.get(1);

			if ( 1 == test ) {
				if ( h && ( h.match(/deflate/i) || h.match(/gzip/i) ) )
					this.get('no');
				else
					this.get(2);

				return;
			}

			if ( 2 == test ) {
				if ( '"wpCompressionTest' === r )
					this.get('yes');
				else
					this.get('no');
			}
		}
	};
	testCompression.check();
	</script>
	<?php
}

/**
 * Echoes a submit button, with provided text and appropriate class(es).
 *
 * @since 3.1.0
 *
 * @see get_submit_button()
 *
 * @param string       $text             Optional. The text of the button. Defaults to 'Save Changes'.
 * @param string       $type             Optional. The type and CSS class(es) of the button. Core values
 *                                       include 'primary', 'small', and 'large'. Default 'primary'.
 * @param string       $name             Optional. The HTML name of the submit button. If no `id` attribute
 *                                       is given in the `$other_attributes` parameter, `$name` will be used
 *                                       as the button's `id`. Default 'submit'.
 * @param bool         $wrap             Optional. True if the output button should be wrapped in a paragraph tag,
 *                                       false otherwise. Default true.
 * @param array|string $other_attributes Optional. Other attributes that should be output with the button,
 *                                       mapping attributes to their values, e.g. `array( 'id' => 'search-submit' )`.
 *                                       These key/value attribute pairs will be output as `attribute="value"`,
 *                                       where attribute is the key. Attributes can also be provided as a string,
 *                                       e.g. `id="search-submit"`, though the array format is generally preferred.
 *                                       Default empty string.
 */
function submit_button( $text = '', $type = 'primary', $name = 'submit', $wrap = true, $other_attributes = '' ) {
	echo get_submit_button( $text, $type, $name, $wrap, $other_attributes );
}

/**
 * Returns a submit button, with provided text and appropriate class.
 *
 * @since 3.1.0
 *
 * @param string       $text             Optional. The text of the button. Defaults to 'Save Changes'.
 * @param string       $type             Optional. The type and CSS class(es) of the button. Core values
 *                                       include 'primary', 'small', and 'large'. Default 'primary large'.
 * @param string       $name             Optional. The HTML name of the submit button. If no `id` attribute
 *                                       is given in the `$other_attributes` parameter, `$name` will be used
 *                                       as the button's `id`. Default 'submit'.
 * @param bool         $wrap             Optional. True if the output button should be wrapped in a paragraph tag,
 *                                       false otherwise. Default true.
 * @param array|string $other_attributes Optional. Other attributes that should be output with the button,
 *                                       mapping attributes to their values, e.g. `array( 'id' => 'search-submit' )`.
 *                                       These key/value attribute pairs will be output as `attribute="value"`,
 *                                       where attribute is the key. Attributes can also be provided as a string,
 *                                       e.g. `id="search-submit"`, though the array format is generally preferred.
 *                                       Default empty string.
 * @return string Submit button HTML.
 */
function get_submit_button( $text = '', $type = 'primary large', $name = 'submit', $wrap = true, $other_attributes = '' ) {
	if ( ! is_array( $type ) ) {
		$type = explode( ' ', $type );
	}

	$button_shorthand = array( 'primary', 'small', 'large' );
	$classes          = array( 'button' );

	foreach ( $type as $t ) {
		if ( 'secondary' === $t || 'button-secondary' === $t ) {
			continue;
		}

		$classes[] = in_array( $t, $button_shorthand, true ) ? 'button-' . $t : $t;
	}

	// Remove empty items, remove duplicate items, and finally build a string.
	$class = implode( ' ', array_unique( array_filter( $classes ) ) );

	$text = $text ? $text : __( 'Save Changes' );

	// Default the id attribute to $name unless an id was specifically provided in $other_attributes.
	$id = $name;
	if ( is_array( $other_attributes ) && isset( $other_attributes['id'] ) ) {
		$id = $other_attributes['id'];
		unset( $other_attributes['id'] );
	}

	$attributes = '';
	if ( is_array( $other_attributes ) ) {
		foreach ( $other_attributes as $attribute => $value ) {
			$attributes .= $attribute . '="' . esc_attr( $value ) . '" '; // Trailing space is important.
		}
	} elseif ( ! empty( $other_attributes ) ) { // Attributes provided as a string.
		$attributes = $other_attributes;
	}

	// Don't output empty name and id attributes.
	$name_attr = $name ? ' name="' . esc_attr( $name ) . '"' : '';
	$id_attr   = $id ? ' id="' . esc_attr( $id ) . '"' : '';

	$button  = '<input type="submit"' . $name_attr . $id_attr . ' class="' . esc_attr( $class );
	$button .= '" value="' . esc_attr( $text ) . '" ' . $attributes . ' />';

	if ( $wrap ) {
		$button = '<p class="submit">' . $button . '</p>';
	}

	return $button;
}

/**
 * Prints out the beginning of the admin HTML header.
 *
 * @since 3.3.0
 *
 * @global bool $is_IE
 */
function _wp_admin_html_begin() {
	global $is_IE;

	$admin_html_class = ( is_admin_bar_showing() ) ? 'wp-toolbar' : '';

	if ( $is_IE ) {
		header( 'X-UA-Compatible: IE=edge' );
	}

	?>
<!DOCTYPE html>
<html class="<?php echo $admin_html_class; ?>"
	<?php
	/**
	 * Fires inside the HTML tag in the admin header.
	 *
	 * @since 2.2.0
	 */
	do_action( 'admin_xml_ns' );

	language_attributes();
	?>
>
<head>
<meta http-equiv="Content-Type" content="<?php bloginfo( 'html_type' ); ?>; charset=<?php echo get_option( 'blog_charset' ); ?>" />
	<?php
}

/**
 * Converts a screen string to a screen object.
 *
 * @since 3.0.0
 *
 * @param string $hook_name The hook name (also known as the hook suffix) used to determine the screen.
 * @return WP_Screen Screen object.
 */
function convert_to_screen( $hook_name ) {
	if ( ! class_exists( 'WP_Screen' ) ) {
		_doing_it_wrong(
			'convert_to_screen(), add_meta_box()',
			sprintf(
				/* translators: 1: wp-admin/includes/template.php, 2: add_meta_box(), 3: add_meta_boxes */
				__( 'Likely direct inclusion of %1$s in order to use %2$s. This is very wrong. Hook the %2$s call into the %3$s action instead.' ),
				'<code>wp-admin/includes/template.php</code>',
				'<code>add_meta_box()</code>',
				'<code>add_meta_boxes</code>'
			),
			'3.3.0'
		);
		return (object) array(
			'id'   => '_invalid',
			'base' => '_are_belong_to_us',
		);
	}

	return WP_Screen::get( $hook_name );
}

/**
 * Outputs the HTML for restoring the post data from DOM storage
 *
 * @since 3.6.0
 * @access private
 */
function _local_storage_notice() {
	$local_storage_message  = '<p class="local-restore">';
	$local_storage_message .= __( 'The backup of this post in your browser is different from the version below.' );
	$local_storage_message .= '<button type="button" class="button restore-backup">' . __( 'Restore the backup' ) . '</button></p>';
	$local_storage_message .= '<p class="help">';
	$local_storage_message .= __( 'This will replace the current editor content with the last backup version. You can use undo and redo in the editor to get the old content back or to return to the restored version.' );
	$local_storage_message .= '</p>';

	wp_admin_notice(
		$local_storage_message,
		array(
			'id'                 => 'local-storage-notice',
			'additional_classes' => array( 'hidden' ),
			'dismissible'        => true,
			'paragraph_wrap'     => false,
		)
	);
}

/**
 * Outputs a HTML element with a star rating for a given rating.
 *
 * Outputs a HTML element with the star rating exposed on a 0..5 scale in
 * half star increments (ie. 1, 1.5, 2 stars). Optionally, if specified, the
 * number of ratings may also be displayed by passing the $number parameter.
 *
 * @since 3.8.0
 * @since 4.4.0 Introduced the `echo` parameter.
 *
 * @param array $args {
 *     Optional. Array of star ratings arguments.
 *
 *     @type int|float $rating The rating to display, expressed in either a 0.5 rating increment,
 *                             or percentage. Default 0.
 *     @type string    $type   Format that the $rating is in. Valid values are 'rating' (default),
 *                             or, 'percent'. Default 'rating'.
 *     @type int       $number The number of ratings that makes up this rating. Default 0.
 *     @type bool      $echo   Whether to echo the generated markup. False to return the markup instead
 *                             of echoing it. Default true.
 * }
 * @return string Star rating HTML.
 */
function wp_star_rating( $args = array() ) {
	$defaults    = array(
		'rating' => 0,
		'type'   => 'rating',
		'number' => 0,
		'echo'   => true,
	);
	$parsed_args = wp_parse_args( $args, $defaults );

	// Non-English decimal places when the $rating is coming from a string.
	$rating = (float) str_replace( ',', '.', $parsed_args['rating'] );

	// Convert percentage to star rating, 0..5 in .5 increments.
	if ( 'percent' === $parsed_args['type'] ) {
		$rating = round( $rating / 10, 0 ) / 2;
	}

	// Calculate the number of each type of star needed.
	$full_stars  = floor( $rating );
	$half_stars  = ceil( $rating - $full_stars );
	$empty_stars = 5 - $full_stars - $half_stars;

	if ( $parsed_args['number'] ) {
		/* translators: Hidden accessibility text. 1: The rating, 2: The number of ratings. */
		$format = _n( '%1$s rating based on %2$s rating', '%1$s rating based on %2$s ratings', $parsed_args['number'] );
		$title  = sprintf( $format, number_format_i18n( $rating, 1 ), number_format_i18n( $parsed_args['number'] ) );
	} else {
		/* translators: Hidden accessibility text. %s: The rating. */
		$title = sprintf( __( '%s rating' ), number_format_i18n( $rating, 1 ) );
	}

	$output  = '<div class="star-rating">';
	$output .= '<span class="screen-reader-text">' . $title . '</span>';
	$output .= str_repeat( '<div class="star star-full" aria-hidden="true"></div>', $full_stars );
	$output .= str_repeat( '<div class="star star-half" aria-hidden="true"></div>', $half_stars );
	$output .= str_repeat( '<div class="star star-empty" aria-hidden="true"></div>', $empty_stars );
	$output .= '</div>';

	if ( $parsed_args['echo'] ) {
		echo $output;
	}

	return $output;
}

/**
 * Outputs a notice when editing the page for posts (internal use only).
 *
 * @ignore
 * @since 4.2.0
 */
function _wp_posts_page_notice() {
	wp_admin_notice(
		__( 'You are currently editing the page that shows your latest posts.' ),
		array(
			'type'               => 'warning',
			'additional_classes' => array( 'inline' ),
		)
	);
}

/**
 * Outputs a notice when editing the page for posts in the block editor (internal use only).
 *
 * @ignore
 * @since 5.8.0
 */
function _wp_block_editor_posts_page_notice() {
	wp_add_inline_script(
		'wp-notices',
		sprintf(
			'wp.data.dispatch( "core/notices" ).createWarningNotice( "%s", { isDismissible: false } )',
			__( 'You are currently editing the page that shows your latest posts.' )
		),
		'after'
	);
}
screen.php000064400000014352151212616040006537 0ustar00<?php
/**
 * WordPress Administration Screen API.
 *
 * @package WordPress
 * @subpackage Administration
 */

/**
 * Get the column headers for a screen
 *
 * @since 2.7.0
 *
 * @param string|WP_Screen $screen The screen you want the headers for
 * @return string[] The column header labels keyed by column ID.
 */
function get_column_headers( $screen ) {
	static $column_headers = array();

	if ( is_string( $screen ) ) {
		$screen = convert_to_screen( $screen );
	}

	if ( ! isset( $column_headers[ $screen->id ] ) ) {
		/**
		 * Filters the column headers for a list table on a specific screen.
		 *
		 * The dynamic portion of the hook name, `$screen->id`, refers to the
		 * ID of a specific screen. For example, the screen ID for the Posts
		 * list table is edit-post, so the filter for that screen would be
		 * manage_edit-post_columns.
		 *
		 * @since 3.0.0
		 *
		 * @param string[] $columns The column header labels keyed by column ID.
		 */
		$column_headers[ $screen->id ] = apply_filters( "manage_{$screen->id}_columns", array() );
	}

	return $column_headers[ $screen->id ];
}

/**
 * Get a list of hidden columns.
 *
 * @since 2.7.0
 *
 * @param string|WP_Screen $screen The screen you want the hidden columns for
 * @return string[] Array of IDs of hidden columns.
 */
function get_hidden_columns( $screen ) {
	if ( is_string( $screen ) ) {
		$screen = convert_to_screen( $screen );
	}

	$hidden = get_user_option( 'manage' . $screen->id . 'columnshidden' );

	$use_defaults = ! is_array( $hidden );

	if ( $use_defaults ) {
		$hidden = array();

		/**
		 * Filters the default list of hidden columns.
		 *
		 * @since 4.4.0
		 *
		 * @param string[]  $hidden Array of IDs of columns hidden by default.
		 * @param WP_Screen $screen WP_Screen object of the current screen.
		 */
		$hidden = apply_filters( 'default_hidden_columns', $hidden, $screen );
	}

	/**
	 * Filters the list of hidden columns.
	 *
	 * @since 4.4.0
	 * @since 4.4.1 Added the `use_defaults` parameter.
	 *
	 * @param string[]  $hidden       Array of IDs of hidden columns.
	 * @param WP_Screen $screen       WP_Screen object of the current screen.
	 * @param bool      $use_defaults Whether to show the default columns.
	 */
	return apply_filters( 'hidden_columns', $hidden, $screen, $use_defaults );
}

/**
 * Prints the meta box preferences for screen meta.
 *
 * @since 2.7.0
 *
 * @global array $wp_meta_boxes Global meta box state.
 *
 * @param WP_Screen $screen
 */
function meta_box_prefs( $screen ) {
	global $wp_meta_boxes;

	if ( is_string( $screen ) ) {
		$screen = convert_to_screen( $screen );
	}

	if ( empty( $wp_meta_boxes[ $screen->id ] ) ) {
		return;
	}

	$hidden = get_hidden_meta_boxes( $screen );

	foreach ( array_keys( $wp_meta_boxes[ $screen->id ] ) as $context ) {
		foreach ( array( 'high', 'core', 'default', 'low' ) as $priority ) {
			if ( ! isset( $wp_meta_boxes[ $screen->id ][ $context ][ $priority ] ) ) {
				continue;
			}

			foreach ( $wp_meta_boxes[ $screen->id ][ $context ][ $priority ] as $box ) {
				if ( false === $box || ! $box['title'] ) {
					continue;
				}

				// Submit box cannot be hidden.
				if ( 'submitdiv' === $box['id'] || 'linksubmitdiv' === $box['id'] ) {
					continue;
				}

				$widget_title = $box['title'];

				if ( is_array( $box['args'] ) && isset( $box['args']['__widget_basename'] ) ) {
					$widget_title = $box['args']['__widget_basename'];
				}

				$is_hidden = in_array( $box['id'], $hidden, true );

				printf(
					'<label for="%1$s-hide"><input class="hide-postbox-tog" name="%1$s-hide" type="checkbox" id="%1$s-hide" value="%1$s" %2$s />%3$s</label>',
					esc_attr( $box['id'] ),
					checked( $is_hidden, false, false ),
					$widget_title
				);
			}
		}
	}
}

/**
 * Gets an array of IDs of hidden meta boxes.
 *
 * @since 2.7.0
 *
 * @param string|WP_Screen $screen Screen identifier
 * @return string[] IDs of hidden meta boxes.
 */
function get_hidden_meta_boxes( $screen ) {
	if ( is_string( $screen ) ) {
		$screen = convert_to_screen( $screen );
	}

	$hidden = get_user_option( "metaboxhidden_{$screen->id}" );

	$use_defaults = ! is_array( $hidden );

	// Hide slug boxes by default.
	if ( $use_defaults ) {
		$hidden = array();

		if ( 'post' === $screen->base ) {
			if ( in_array( $screen->post_type, array( 'post', 'page', 'attachment' ), true ) ) {
				$hidden = array( 'slugdiv', 'trackbacksdiv', 'postcustom', 'postexcerpt', 'commentstatusdiv', 'commentsdiv', 'authordiv', 'revisionsdiv' );
			} else {
				$hidden = array( 'slugdiv' );
			}
		}

		/**
		 * Filters the default list of hidden meta boxes.
		 *
		 * @since 3.1.0
		 *
		 * @param string[]  $hidden An array of IDs of meta boxes hidden by default.
		 * @param WP_Screen $screen WP_Screen object of the current screen.
		 */
		$hidden = apply_filters( 'default_hidden_meta_boxes', $hidden, $screen );
	}

	/**
	 * Filters the list of hidden meta boxes.
	 *
	 * @since 3.3.0
	 *
	 * @param string[]  $hidden       An array of IDs of hidden meta boxes.
	 * @param WP_Screen $screen       WP_Screen object of the current screen.
	 * @param bool      $use_defaults Whether to show the default meta boxes.
	 *                                Default true.
	 */
	return apply_filters( 'hidden_meta_boxes', $hidden, $screen, $use_defaults );
}

/**
 * Register and configure an admin screen option
 *
 * @since 3.1.0
 *
 * @param string $option An option name.
 * @param mixed  $args   Option-dependent arguments.
 */
function add_screen_option( $option, $args = array() ) {
	$current_screen = get_current_screen();

	if ( ! $current_screen ) {
		return;
	}

	$current_screen->add_option( $option, $args );
}

/**
 * Get the current screen object
 *
 * @since 3.1.0
 *
 * @global WP_Screen $current_screen WordPress current screen object.
 *
 * @return WP_Screen|null Current screen object or null when screen not defined.
 */
function get_current_screen() {
	global $current_screen;

	if ( ! isset( $current_screen ) ) {
		return null;
	}

	return $current_screen;
}

/**
 * Set the current screen object
 *
 * @since 3.0.0
 *
 * @param string|WP_Screen $hook_name Optional. The hook name (also known as the hook suffix) used to determine the screen,
 *                                    or an existing screen object.
 */
function set_current_screen( $hook_name = '' ) {
	WP_Screen::get( $hook_name )->set_current_screen();
}
class-wp-importer.php000064400000016530151212616040010650 0ustar00<?php
/**
 * WP_Importer base class
 */
#[AllowDynamicProperties]
class WP_Importer {
	/**
	 * Class Constructor
	 */
	public function __construct() {}

	/**
	 * Returns array with imported permalinks from WordPress database.
	 *
	 * @global wpdb $wpdb WordPress database abstraction object.
	 *
	 * @param string $importer_name
	 * @param string $blog_id
	 * @return array
	 */
	public function get_imported_posts( $importer_name, $blog_id ) {
		global $wpdb;

		$hashtable = array();

		$limit  = 100;
		$offset = 0;

		// Grab all posts in chunks.
		do {
			$meta_key = $importer_name . '_' . $blog_id . '_permalink';
			$results  = $wpdb->get_results(
				$wpdb->prepare(
					"SELECT post_id, meta_value FROM $wpdb->postmeta WHERE meta_key = %s LIMIT %d,%d",
					$meta_key,
					$offset,
					$limit
				)
			);

			// Increment offset.
			$offset = ( $limit + $offset );

			if ( ! empty( $results ) ) {
				foreach ( $results as $r ) {
					// Set permalinks into array.
					$hashtable[ $r->meta_value ] = (int) $r->post_id;
				}
			}
		} while ( count( $results ) === $limit );

		return $hashtable;
	}

	/**
	 * Returns count of imported permalinks from WordPress database.
	 *
	 * @global wpdb $wpdb WordPress database abstraction object.
	 *
	 * @param string $importer_name
	 * @param string $blog_id
	 * @return int
	 */
	public function count_imported_posts( $importer_name, $blog_id ) {
		global $wpdb;

		$count = 0;

		// Get count of permalinks.
		$meta_key = $importer_name . '_' . $blog_id . '_permalink';
		$result   = $wpdb->get_results(
			$wpdb->prepare(
				"SELECT COUNT( post_id ) AS cnt FROM $wpdb->postmeta WHERE meta_key = %s",
				$meta_key
			)
		);

		if ( ! empty( $result ) ) {
			$count = (int) $result[0]->cnt;
		}

		return $count;
	}

	/**
	 * Sets array with imported comments from WordPress database.
	 *
	 * @global wpdb $wpdb WordPress database abstraction object.
	 *
	 * @param string $blog_id
	 * @return array
	 */
	public function get_imported_comments( $blog_id ) {
		global $wpdb;

		$hashtable = array();

		$limit  = 100;
		$offset = 0;

		// Grab all comments in chunks.
		do {
			$results = $wpdb->get_results(
				$wpdb->prepare(
					"SELECT comment_ID, comment_agent FROM $wpdb->comments LIMIT %d,%d",
					$offset,
					$limit
				)
			);

			// Increment offset.
			$offset = ( $limit + $offset );

			if ( ! empty( $results ) ) {
				foreach ( $results as $r ) {
					// Explode comment_agent key.
					list ( $comment_agent_blog_id, $source_comment_id ) = explode( '-', $r->comment_agent );

					$source_comment_id = (int) $source_comment_id;

					// Check if this comment came from this blog.
					if ( (int) $blog_id === (int) $comment_agent_blog_id ) {
						$hashtable[ $source_comment_id ] = (int) $r->comment_ID;
					}
				}
			}
		} while ( count( $results ) === $limit );

		return $hashtable;
	}

	/**
	 * @param int $blog_id
	 * @return int|void
	 */
	public function set_blog( $blog_id ) {
		if ( is_numeric( $blog_id ) ) {
			$blog_id = (int) $blog_id;
		} else {
			$blog   = 'http://' . preg_replace( '#^https?://#', '', $blog_id );
			$parsed = parse_url( $blog );
			if ( ! $parsed || empty( $parsed['host'] ) ) {
				fwrite( STDERR, "Error: can not determine blog_id from $blog_id\n" );
				exit;
			}
			if ( empty( $parsed['path'] ) ) {
				$parsed['path'] = '/';
			}
			$blogs = get_sites(
				array(
					'domain' => $parsed['host'],
					'number' => 1,
					'path'   => $parsed['path'],
				)
			);
			if ( ! $blogs ) {
				fwrite( STDERR, "Error: Could not find blog\n" );
				exit;
			}
			$blog    = array_shift( $blogs );
			$blog_id = (int) $blog->blog_id;
		}

		if ( function_exists( 'is_multisite' ) ) {
			if ( is_multisite() ) {
				switch_to_blog( $blog_id );
			}
		}

		return $blog_id;
	}

	/**
	 * @param int $user_id
	 * @return int|void
	 */
	public function set_user( $user_id ) {
		if ( is_numeric( $user_id ) ) {
			$user_id = (int) $user_id;
		} else {
			$user_id = (int) username_exists( $user_id );
		}

		if ( ! $user_id || ! wp_set_current_user( $user_id ) ) {
			fwrite( STDERR, "Error: can not find user\n" );
			exit;
		}

		return $user_id;
	}

	/**
	 * Sorts by strlen, longest string first.
	 *
	 * @param string $a
	 * @param string $b
	 * @return int
	 */
	public function cmpr_strlen( $a, $b ) {
		return strlen( $b ) - strlen( $a );
	}

	/**
	 * Gets URL.
	 *
	 * @param string $url
	 * @param string $username
	 * @param string $password
	 * @param bool   $head
	 * @return array
	 */
	public function get_page(
		$url,
		$username = '',
		#[\SensitiveParameter]
		$password = '',
		$head = false
	) {
		// Increase the timeout.
		add_filter( 'http_request_timeout', array( $this, 'bump_request_timeout' ) );

		$headers = array();
		$args    = array();
		if ( true === $head ) {
			$args['method'] = 'HEAD';
		}
		if ( ! empty( $username ) && ! empty( $password ) ) {
			$headers['Authorization'] = 'Basic ' . base64_encode( "$username:$password" );
		}

		$args['headers'] = $headers;

		return wp_safe_remote_request( $url, $args );
	}

	/**
	 * Bumps up the request timeout for http requests.
	 *
	 * @param int $val
	 * @return int
	 */
	public function bump_request_timeout( $val ) {
		return 60;
	}

	/**
	 * Checks if user has exceeded disk quota.
	 *
	 * @return bool
	 */
	public function is_user_over_quota() {
		if ( function_exists( 'upload_is_user_over_quota' ) ) {
			if ( upload_is_user_over_quota() ) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Replaces newlines, tabs, and multiple spaces with a single space.
	 *
	 * @param string $text
	 * @return string
	 */
	public function min_whitespace( $text ) {
		return preg_replace( '|[\r\n\t ]+|', ' ', $text );
	}

	/**
	 * Resets global variables that grow out of control during imports.
	 *
	 * @since 3.0.0
	 *
	 * @global wpdb  $wpdb       WordPress database abstraction object.
	 * @global int[] $wp_actions
	 */
	public function stop_the_insanity() {
		global $wpdb, $wp_actions;
		// Or define( 'WP_IMPORTING', true );
		$wpdb->queries = array();
		// Reset $wp_actions to keep it from growing out of control.
		$wp_actions = array();
	}
}

/**
 * Returns value of command line params.
 * Exits when a required param is not set.
 *
 * @param string $param
 * @param bool   $required
 * @return mixed
 */
function get_cli_args( $param, $required = false ) {
	$args = $_SERVER['argv'];
	if ( ! is_array( $args ) ) {
		$args = array();
	}

	$out = array();

	$last_arg = null;
	$return   = null;

	$il = count( $args );

	for ( $i = 1, $il; $i < $il; $i++ ) {
		if ( (bool) preg_match( '/^--(.+)/', $args[ $i ], $match ) ) {
			$parts = explode( '=', $match[1] );
			$key   = preg_replace( '/[^a-z0-9]+/', '', $parts[0] );

			if ( isset( $parts[1] ) ) {
				$out[ $key ] = $parts[1];
			} else {
				$out[ $key ] = true;
			}

			$last_arg = $key;
		} elseif ( (bool) preg_match( '/^-([a-zA-Z0-9]+)/', $args[ $i ], $match ) ) {
			for ( $j = 0, $jl = strlen( $match[1] ); $j < $jl; $j++ ) {
				$key         = $match[1][ $j ];
				$out[ $key ] = true;
			}

			$last_arg = $key;
		} elseif ( null !== $last_arg ) {
			$out[ $last_arg ] = $args[ $i ];
		}
	}

	// Check array for specified param.
	if ( isset( $out[ $param ] ) ) {
		// Set return value.
		$return = $out[ $param ];
	}

	// Check for missing required param.
	if ( ! isset( $out[ $param ] ) && $required ) {
		// Display message and exit.
		echo "\"$param\" parameter is required but was not specified\n";
		exit;
	}

	return $return;
}
class-wp-list-table-compat.php000064400000002731151212616040012326 0ustar00<?php
/**
 * Helper functions for displaying a list of items in an ajaxified HTML table.
 *
 * @package WordPress
 * @subpackage List_Table
 * @since 4.7.0
 */

/**
 * Helper class to be used only by back compat functions.
 *
 * @since 3.1.0
 */
class _WP_List_Table_Compat extends WP_List_Table {
	public $_screen;
	public $_columns;

	/**
	 * Constructor.
	 *
	 * @since 3.1.0
	 *
	 * @param string|WP_Screen $screen  The screen hook name or screen object.
	 * @param string[]         $columns An array of columns with column IDs as the keys
	 *                                  and translated column names as the values.
	 */
	public function __construct( $screen, $columns = array() ) {
		if ( is_string( $screen ) ) {
			$screen = convert_to_screen( $screen );
		}

		$this->_screen = $screen;

		if ( ! empty( $columns ) ) {
			$this->_columns = $columns;
			add_filter( 'manage_' . $screen->id . '_columns', array( $this, 'get_columns' ), 0 );
		}
	}

	/**
	 * Gets a list of all, hidden, and sortable columns.
	 *
	 * @since 3.1.0
	 *
	 * @return array
	 */
	protected function get_column_info() {
		$columns  = get_column_headers( $this->_screen );
		$hidden   = get_hidden_columns( $this->_screen );
		$sortable = array();
		$primary  = $this->get_default_primary_column_name();

		return array( $columns, $hidden, $sortable, $primary );
	}

	/**
	 * Gets a list of columns.
	 *
	 * @since 3.1.0
	 *
	 * @return array
	 */
	public function get_columns() {
		return $this->_columns;
	}
}
continents-cities.php000064400000050074151212616040010723 0ustar00<?php
/**
 * Translation API: Continent and city translations for timezone selection
 *
 * This file is not included anywhere. It exists solely for use by xgettext.
 *
 * @package WordPress
 * @subpackage i18n
 * @since 2.8.0
 */

__( 'Africa', 'continents-cities' );
__( 'Abidjan', 'continents-cities' );
__( 'Accra', 'continents-cities' );
__( 'Addis Ababa', 'continents-cities' );
__( 'Algiers', 'continents-cities' );
__( 'Asmara', 'continents-cities' );
__( 'Asmera', 'continents-cities' );
__( 'Bamako', 'continents-cities' );
__( 'Bangui', 'continents-cities' );
__( 'Banjul', 'continents-cities' );
__( 'Bissau', 'continents-cities' );
__( 'Blantyre', 'continents-cities' );
__( 'Brazzaville', 'continents-cities' );
__( 'Bujumbura', 'continents-cities' );
__( 'Cairo', 'continents-cities' );
__( 'Casablanca', 'continents-cities' );
__( 'Ceuta', 'continents-cities' );
__( 'Conakry', 'continents-cities' );
__( 'Dakar', 'continents-cities' );
__( 'Dar es Salaam', 'continents-cities' );
__( 'Djibouti', 'continents-cities' );
__( 'Douala', 'continents-cities' );
__( 'El Aaiun', 'continents-cities' );
__( 'Freetown', 'continents-cities' );
__( 'Gaborone', 'continents-cities' );
__( 'Harare', 'continents-cities' );
__( 'Johannesburg', 'continents-cities' );
__( 'Juba', 'continents-cities' );
__( 'Kampala', 'continents-cities' );
__( 'Khartoum', 'continents-cities' );
__( 'Kigali', 'continents-cities' );
__( 'Kinshasa', 'continents-cities' );
__( 'Lagos', 'continents-cities' );
__( 'Libreville', 'continents-cities' );
__( 'Lome', 'continents-cities' );
__( 'Luanda', 'continents-cities' );
__( 'Lubumbashi', 'continents-cities' );
__( 'Lusaka', 'continents-cities' );
__( 'Malabo', 'continents-cities' );
__( 'Maputo', 'continents-cities' );
__( 'Maseru', 'continents-cities' );
__( 'Mbabane', 'continents-cities' );
__( 'Mogadishu', 'continents-cities' );
__( 'Monrovia', 'continents-cities' );
__( 'Nairobi', 'continents-cities' );
__( 'Ndjamena', 'continents-cities' );
__( 'Niamey', 'continents-cities' );
__( 'Nouakchott', 'continents-cities' );
__( 'Ouagadougou', 'continents-cities' );
__( 'Porto-Novo', 'continents-cities' );
__( 'Sao Tome', 'continents-cities' );
__( 'Timbuktu', 'continents-cities' );
__( 'Tripoli', 'continents-cities' );
__( 'Tunis', 'continents-cities' );
__( 'Windhoek', 'continents-cities' );

__( 'America', 'continents-cities' );
__( 'Adak', 'continents-cities' );
__( 'Anchorage', 'continents-cities' );
__( 'Anguilla', 'continents-cities' );
__( 'Antigua', 'continents-cities' );
__( 'Araguaina', 'continents-cities' );
__( 'Argentina', 'continents-cities' );
__( 'Buenos Aires', 'continents-cities' );
__( 'Catamarca', 'continents-cities' );
__( 'ComodRivadavia', 'continents-cities' );
__( 'Cordoba', 'continents-cities' );
__( 'Jujuy', 'continents-cities' );
__( 'La Rioja', 'continents-cities' );
__( 'Mendoza', 'continents-cities' );
__( 'Rio Gallegos', 'continents-cities' );
__( 'Salta', 'continents-cities' );
__( 'San Juan', 'continents-cities' );
__( 'San Luis', 'continents-cities' );
__( 'Tucuman', 'continents-cities' );
__( 'Ushuaia', 'continents-cities' );
__( 'Aruba', 'continents-cities' );
__( 'Asuncion', 'continents-cities' );
__( 'Atikokan', 'continents-cities' );
__( 'Atka', 'continents-cities' );
__( 'Bahia', 'continents-cities' );
__( 'Bahia Banderas', 'continents-cities' );
__( 'Barbados', 'continents-cities' );
__( 'Belem', 'continents-cities' );
__( 'Belize', 'continents-cities' );
__( 'Blanc-Sablon', 'continents-cities' );
__( 'Boa Vista', 'continents-cities' );
__( 'Bogota', 'continents-cities' );
__( 'Boise', 'continents-cities' );
__( 'Cambridge Bay', 'continents-cities' );
__( 'Campo Grande', 'continents-cities' );
__( 'Cancun', 'continents-cities' );
__( 'Caracas', 'continents-cities' );
__( 'Cayenne', 'continents-cities' );
__( 'Cayman', 'continents-cities' );
__( 'Chicago', 'continents-cities' );
__( 'Chihuahua', 'continents-cities' );
__( 'Coral Harbour', 'continents-cities' );
__( 'Costa Rica', 'continents-cities' );
__( 'Creston', 'continents-cities' );
__( 'Cuiaba', 'continents-cities' );
__( 'Curacao', 'continents-cities' );
__( 'Danmarkshavn', 'continents-cities' );
__( 'Dawson', 'continents-cities' );
__( 'Dawson Creek', 'continents-cities' );
__( 'Denver', 'continents-cities' );
__( 'Detroit', 'continents-cities' );
__( 'Dominica', 'continents-cities' );
__( 'Edmonton', 'continents-cities' );
__( 'Eirunepe', 'continents-cities' );
__( 'El Salvador', 'continents-cities' );
__( 'Ensenada', 'continents-cities' );
__( 'Fort Nelson', 'continents-cities' );
__( 'Fort Wayne', 'continents-cities' );
__( 'Fortaleza', 'continents-cities' );
__( 'Glace Bay', 'continents-cities' );
__( 'Godthab', 'continents-cities' );
__( 'Goose Bay', 'continents-cities' );
__( 'Grand Turk', 'continents-cities' );
__( 'Grenada', 'continents-cities' );
__( 'Guadeloupe', 'continents-cities' );
__( 'Guatemala', 'continents-cities' );
__( 'Guayaquil', 'continents-cities' );
__( 'Guyana', 'continents-cities' );
__( 'Halifax', 'continents-cities' );
__( 'Havana', 'continents-cities' );
__( 'Hermosillo', 'continents-cities' );
__( 'Indiana', 'continents-cities' );
__( 'Indianapolis', 'continents-cities' );
__( 'Knox', 'continents-cities' );
__( 'Marengo', 'continents-cities' );
__( 'Petersburg', 'continents-cities' );
__( 'Tell City', 'continents-cities' );
__( 'Vevay', 'continents-cities' );
__( 'Vincennes', 'continents-cities' );
__( 'Winamac', 'continents-cities' );
__( 'Inuvik', 'continents-cities' );
__( 'Iqaluit', 'continents-cities' );
__( 'Jamaica', 'continents-cities' );
__( 'Juneau', 'continents-cities' );
__( 'Kentucky', 'continents-cities' );
__( 'Louisville', 'continents-cities' );
__( 'Monticello', 'continents-cities' );
__( 'Knox IN', 'continents-cities' );
__( 'Kralendijk', 'continents-cities' );
__( 'La Paz', 'continents-cities' );
__( 'Lima', 'continents-cities' );
__( 'Los Angeles', 'continents-cities' );
__( 'Lower Princes', 'continents-cities' );
__( 'Maceio', 'continents-cities' );
__( 'Managua', 'continents-cities' );
__( 'Manaus', 'continents-cities' );
__( 'Marigot', 'continents-cities' );
__( 'Martinique', 'continents-cities' );
__( 'Matamoros', 'continents-cities' );
__( 'Mazatlan', 'continents-cities' );
__( 'Menominee', 'continents-cities' );
__( 'Merida', 'continents-cities' );
__( 'Metlakatla', 'continents-cities' );
__( 'Mexico City', 'continents-cities' );
__( 'Miquelon', 'continents-cities' );
__( 'Moncton', 'continents-cities' );
__( 'Monterrey', 'continents-cities' );
__( 'Montevideo', 'continents-cities' );
__( 'Montreal', 'continents-cities' );
__( 'Montserrat', 'continents-cities' );
__( 'Nassau', 'continents-cities' );
__( 'New York', 'continents-cities' );
__( 'Nipigon', 'continents-cities' );
__( 'Nome', 'continents-cities' );
__( 'Noronha', 'continents-cities' );
__( 'North Dakota', 'continents-cities' );
__( 'Beulah', 'continents-cities' );
__( 'Center', 'continents-cities' );
__( 'New Salem', 'continents-cities' );
__( 'Nuuk', 'continents-cities' );
__( 'Ojinaga', 'continents-cities' );
__( 'Panama', 'continents-cities' );
__( 'Pangnirtung', 'continents-cities' );
__( 'Paramaribo', 'continents-cities' );
__( 'Phoenix', 'continents-cities' );
__( 'Port-au-Prince', 'continents-cities' );
__( 'Port of Spain', 'continents-cities' );
__( 'Porto Acre', 'continents-cities' );
__( 'Porto Velho', 'continents-cities' );
__( 'Puerto Rico', 'continents-cities' );
__( 'Punta Arenas', 'continents-cities' );
__( 'Rainy River', 'continents-cities' );
__( 'Rankin Inlet', 'continents-cities' );
__( 'Recife', 'continents-cities' );
__( 'Regina', 'continents-cities' );
__( 'Resolute', 'continents-cities' );
__( 'Rio Branco', 'continents-cities' );
__( 'Rosario', 'continents-cities' );
__( 'Santa Isabel', 'continents-cities' );
__( 'Santarem', 'continents-cities' );
__( 'Santiago', 'continents-cities' );
__( 'Santo Domingo', 'continents-cities' );
__( 'Sao Paulo', 'continents-cities' );
__( 'Scoresbysund', 'continents-cities' );
__( 'Shiprock', 'continents-cities' );
__( 'Sitka', 'continents-cities' );
__( 'St Barthelemy', 'continents-cities' );
__( 'St Johns', 'continents-cities' );
__( 'St Kitts', 'continents-cities' );
__( 'St Lucia', 'continents-cities' );
__( 'St Thomas', 'continents-cities' );
__( 'St Vincent', 'continents-cities' );
__( 'Swift Current', 'continents-cities' );
__( 'Tegucigalpa', 'continents-cities' );
__( 'Thule', 'continents-cities' );
__( 'Thunder Bay', 'continents-cities' );
__( 'Tijuana', 'continents-cities' );
__( 'Toronto', 'continents-cities' );
__( 'Tortola', 'continents-cities' );
__( 'Vancouver', 'continents-cities' );
__( 'Virgin', 'continents-cities' );
__( 'Whitehorse', 'continents-cities' );
__( 'Winnipeg', 'continents-cities' );
__( 'Yakutat', 'continents-cities' );
__( 'Yellowknife', 'continents-cities' );

__( 'Antarctica', 'continents-cities' );
__( 'Casey', 'continents-cities' );
__( 'Davis', 'continents-cities' );
__( 'DumontDUrville', 'continents-cities' );
__( 'Macquarie', 'continents-cities' );
__( 'Mawson', 'continents-cities' );
__( 'McMurdo', 'continents-cities' );
__( 'Palmer', 'continents-cities' );
__( 'Rothera', 'continents-cities' );
__( 'South Pole', 'continents-cities' );
__( 'Syowa', 'continents-cities' );
__( 'Troll', 'continents-cities' );
__( 'Vostok', 'continents-cities' );

__( 'Arctic', 'continents-cities' );
__( 'Longyearbyen', 'continents-cities' );

__( 'Asia', 'continents-cities' );
__( 'Aden', 'continents-cities' );
__( 'Almaty', 'continents-cities' );
__( 'Amman', 'continents-cities' );
__( 'Anadyr', 'continents-cities' );
__( 'Aqtau', 'continents-cities' );
__( 'Aqtobe', 'continents-cities' );
__( 'Ashgabat', 'continents-cities' );
__( 'Ashkhabad', 'continents-cities' );
__( 'Atyrau', 'continents-cities' );
__( 'Baghdad', 'continents-cities' );
__( 'Bahrain', 'continents-cities' );
__( 'Baku', 'continents-cities' );
__( 'Bangkok', 'continents-cities' );
__( 'Barnaul', 'continents-cities' );
__( 'Beirut', 'continents-cities' );
__( 'Bishkek', 'continents-cities' );
__( 'Brunei', 'continents-cities' );
__( 'Calcutta', 'continents-cities' );
__( 'Chita', 'continents-cities' );
__( 'Choibalsan', 'continents-cities' );
__( 'Chongqing', 'continents-cities' );
__( 'Chungking', 'continents-cities' );
__( 'Colombo', 'continents-cities' );
__( 'Dacca', 'continents-cities' );
__( 'Damascus', 'continents-cities' );
__( 'Dhaka', 'continents-cities' );
__( 'Dili', 'continents-cities' );
__( 'Dubai', 'continents-cities' );
__( 'Dushanbe', 'continents-cities' );
__( 'Famagusta', 'continents-cities' );
__( 'Gaza', 'continents-cities' );
__( 'Harbin', 'continents-cities' );
__( 'Hebron', 'continents-cities' );
__( 'Ho Chi Minh', 'continents-cities' );
__( 'Hong Kong', 'continents-cities' );
__( 'Hovd', 'continents-cities' );
__( 'Irkutsk', 'continents-cities' );
__( 'Jakarta', 'continents-cities' );
__( 'Jayapura', 'continents-cities' );
__( 'Jerusalem', 'continents-cities' );
__( 'Kabul', 'continents-cities' );
__( 'Kamchatka', 'continents-cities' );
__( 'Karachi', 'continents-cities' );
__( 'Kashgar', 'continents-cities' );
__( 'Kathmandu', 'continents-cities' );
__( 'Katmandu', 'continents-cities' );
__( 'Khandyga', 'continents-cities' );
__( 'Kolkata', 'continents-cities' );
__( 'Krasnoyarsk', 'continents-cities' );
__( 'Kuala Lumpur', 'continents-cities' );
__( 'Kuching', 'continents-cities' );
__( 'Kuwait', 'continents-cities' );
__( 'Macao', 'continents-cities' );
__( 'Macau', 'continents-cities' );
__( 'Magadan', 'continents-cities' );
__( 'Makassar', 'continents-cities' );
__( 'Manila', 'continents-cities' );
__( 'Muscat', 'continents-cities' );
__( 'Nicosia', 'continents-cities' );
__( 'Novokuznetsk', 'continents-cities' );
__( 'Novosibirsk', 'continents-cities' );
__( 'Omsk', 'continents-cities' );
__( 'Oral', 'continents-cities' );
__( 'Phnom Penh', 'continents-cities' );
__( 'Pontianak', 'continents-cities' );
__( 'Pyongyang', 'continents-cities' );
__( 'Qatar', 'continents-cities' );
__( 'Qostanay', 'continents-cities' );
__( 'Qyzylorda', 'continents-cities' );
__( 'Rangoon', 'continents-cities' );
__( 'Riyadh', 'continents-cities' );
__( 'Saigon', 'continents-cities' );
__( 'Sakhalin', 'continents-cities' );
__( 'Samarkand', 'continents-cities' );
__( 'Seoul', 'continents-cities' );
__( 'Shanghai', 'continents-cities' );
__( 'Singapore', 'continents-cities' );
__( 'Srednekolymsk', 'continents-cities' );
__( 'Taipei', 'continents-cities' );
__( 'Tashkent', 'continents-cities' );
__( 'Tbilisi', 'continents-cities' );
__( 'Tehran', 'continents-cities' );
__( 'Tel Aviv', 'continents-cities' );
__( 'Thimbu', 'continents-cities' );
__( 'Thimphu', 'continents-cities' );
__( 'Tokyo', 'continents-cities' );
__( 'Tomsk', 'continents-cities' );
__( 'Ujung Pandang', 'continents-cities' );
__( 'Ulaanbaatar', 'continents-cities' );
__( 'Ulan Bator', 'continents-cities' );
__( 'Urumqi', 'continents-cities' );
__( 'Ust-Nera', 'continents-cities' );
__( 'Vientiane', 'continents-cities' );
__( 'Vladivostok', 'continents-cities' );
__( 'Yakutsk', 'continents-cities' );
__( 'Yangon', 'continents-cities' );
__( 'Yekaterinburg', 'continents-cities' );
__( 'Yerevan', 'continents-cities' );

__( 'Atlantic', 'continents-cities' );
__( 'Azores', 'continents-cities' );
__( 'Bermuda', 'continents-cities' );
__( 'Canary', 'continents-cities' );
__( 'Cape Verde', 'continents-cities' );
__( 'Faeroe', 'continents-cities' );
__( 'Faroe', 'continents-cities' );
__( 'Jan Mayen', 'continents-cities' );
__( 'Madeira', 'continents-cities' );
__( 'Reykjavik', 'continents-cities' );
__( 'South Georgia', 'continents-cities' );
__( 'St Helena', 'continents-cities' );
__( 'Stanley', 'continents-cities' );

__( 'Australia', 'continents-cities' );
__( 'ACT', 'continents-cities' );
__( 'Adelaide', 'continents-cities' );
__( 'Brisbane', 'continents-cities' );
__( 'Broken Hill', 'continents-cities' );
__( 'Canberra', 'continents-cities' );
__( 'Currie', 'continents-cities' );
__( 'Darwin', 'continents-cities' );
__( 'Eucla', 'continents-cities' );
__( 'Hobart', 'continents-cities' );
__( 'LHI', 'continents-cities' );
__( 'Lindeman', 'continents-cities' );
__( 'Lord Howe', 'continents-cities' );
__( 'Melbourne', 'continents-cities' );
__( 'NSW', 'continents-cities' );
__( 'North', 'continents-cities' );
__( 'Perth', 'continents-cities' );
__( 'Queensland', 'continents-cities' );
__( 'South', 'continents-cities' );
__( 'Sydney', 'continents-cities' );
__( 'Tasmania', 'continents-cities' );
__( 'Victoria', 'continents-cities' );
__( 'West', 'continents-cities' );
__( 'Yancowinna', 'continents-cities' );

__( 'Etc', 'continents-cities' );
__( 'GMT', 'continents-cities' );
__( 'GMT+0', 'continents-cities' );
__( 'GMT+1', 'continents-cities' );
__( 'GMT+10', 'continents-cities' );
__( 'GMT+11', 'continents-cities' );
__( 'GMT+12', 'continents-cities' );
__( 'GMT+2', 'continents-cities' );
__( 'GMT+3', 'continents-cities' );
__( 'GMT+4', 'continents-cities' );
__( 'GMT+5', 'continents-cities' );
__( 'GMT+6', 'continents-cities' );
__( 'GMT+7', 'continents-cities' );
__( 'GMT+8', 'continents-cities' );
__( 'GMT+9', 'continents-cities' );
__( 'GMT-0', 'continents-cities' );
__( 'GMT-1', 'continents-cities' );
__( 'GMT-10', 'continents-cities' );
__( 'GMT-11', 'continents-cities' );
__( 'GMT-12', 'continents-cities' );
__( 'GMT-13', 'continents-cities' );
__( 'GMT-14', 'continents-cities' );
__( 'GMT-2', 'continents-cities' );
__( 'GMT-3', 'continents-cities' );
__( 'GMT-4', 'continents-cities' );
__( 'GMT-5', 'continents-cities' );
__( 'GMT-6', 'continents-cities' );
__( 'GMT-7', 'continents-cities' );
__( 'GMT-8', 'continents-cities' );
__( 'GMT-9', 'continents-cities' );
__( 'GMT0', 'continents-cities' );
__( 'Greenwich', 'continents-cities' );
__( 'UCT', 'continents-cities' );
__( 'UTC', 'continents-cities' );
__( 'Universal', 'continents-cities' );
__( 'Zulu', 'continents-cities' );

__( 'Europe', 'continents-cities' );
__( 'Amsterdam', 'continents-cities' );
__( 'Andorra', 'continents-cities' );
__( 'Astrakhan', 'continents-cities' );
__( 'Athens', 'continents-cities' );
__( 'Belfast', 'continents-cities' );
__( 'Belgrade', 'continents-cities' );
__( 'Berlin', 'continents-cities' );
__( 'Bratislava', 'continents-cities' );
__( 'Brussels', 'continents-cities' );
__( 'Bucharest', 'continents-cities' );
__( 'Budapest', 'continents-cities' );
__( 'Busingen', 'continents-cities' );
__( 'Chisinau', 'continents-cities' );
__( 'Copenhagen', 'continents-cities' );
__( 'Dublin', 'continents-cities' );
__( 'Gibraltar', 'continents-cities' );
__( 'Guernsey', 'continents-cities' );
__( 'Helsinki', 'continents-cities' );
__( 'Isle of Man', 'continents-cities' );
__( 'Istanbul', 'continents-cities' );
__( 'Jersey', 'continents-cities' );
__( 'Kaliningrad', 'continents-cities' );
__( 'Kiev', 'continents-cities' );
__( 'Kyiv', 'continents-cities' );
__( 'Kirov', 'continents-cities' );
__( 'Lisbon', 'continents-cities' );
__( 'Ljubljana', 'continents-cities' );
__( 'London', 'continents-cities' );
__( 'Luxembourg', 'continents-cities' );
__( 'Madrid', 'continents-cities' );
__( 'Malta', 'continents-cities' );
__( 'Mariehamn', 'continents-cities' );
__( 'Minsk', 'continents-cities' );
__( 'Monaco', 'continents-cities' );
__( 'Moscow', 'continents-cities' );
__( 'Oslo', 'continents-cities' );
__( 'Paris', 'continents-cities' );
__( 'Podgorica', 'continents-cities' );
__( 'Prague', 'continents-cities' );
__( 'Riga', 'continents-cities' );
__( 'Rome', 'continents-cities' );
__( 'Samara', 'continents-cities' );
__( 'San Marino', 'continents-cities' );
__( 'Sarajevo', 'continents-cities' );
__( 'Saratov', 'continents-cities' );
__( 'Simferopol', 'continents-cities' );
__( 'Skopje', 'continents-cities' );
__( 'Sofia', 'continents-cities' );
__( 'Stockholm', 'continents-cities' );
__( 'Tallinn', 'continents-cities' );
__( 'Tirane', 'continents-cities' );
__( 'Tiraspol', 'continents-cities' );
__( 'Ulyanovsk', 'continents-cities' );
__( 'Uzhgorod', 'continents-cities' );
__( 'Vaduz', 'continents-cities' );
__( 'Vatican', 'continents-cities' );
__( 'Vienna', 'continents-cities' );
__( 'Vilnius', 'continents-cities' );
__( 'Volgograd', 'continents-cities' );
__( 'Warsaw', 'continents-cities' );
__( 'Zagreb', 'continents-cities' );
__( 'Zaporozhye', 'continents-cities' );
__( 'Zurich', 'continents-cities' );

__( 'Indian', 'continents-cities' );
__( 'Antananarivo', 'continents-cities' );
__( 'Chagos', 'continents-cities' );
__( 'Christmas', 'continents-cities' );
__( 'Cocos', 'continents-cities' );
__( 'Comoro', 'continents-cities' );
__( 'Kerguelen', 'continents-cities' );
__( 'Mahe', 'continents-cities' );
__( 'Maldives', 'continents-cities' );
__( 'Mauritius', 'continents-cities' );
__( 'Mayotte', 'continents-cities' );
__( 'Reunion', 'continents-cities' );

__( 'Pacific', 'continents-cities' );
__( 'Apia', 'continents-cities' );
__( 'Auckland', 'continents-cities' );
__( 'Bougainville', 'continents-cities' );
__( 'Chatham', 'continents-cities' );
__( 'Chuuk', 'continents-cities' );
__( 'Easter', 'continents-cities' );
__( 'Efate', 'continents-cities' );
__( 'Enderbury', 'continents-cities' );
__( 'Fakaofo', 'continents-cities' );
__( 'Fiji', 'continents-cities' );
__( 'Funafuti', 'continents-cities' );
__( 'Galapagos', 'continents-cities' );
__( 'Gambier', 'continents-cities' );
__( 'Guadalcanal', 'continents-cities' );
__( 'Guam', 'continents-cities' );
__( 'Honolulu', 'continents-cities' );
__( 'Johnston', 'continents-cities' );
__( 'Kanton', 'continents-cities' );
__( 'Kiritimati', 'continents-cities' );
__( 'Kosrae', 'continents-cities' );
__( 'Kwajalein', 'continents-cities' );
__( 'Majuro', 'continents-cities' );
__( 'Marquesas', 'continents-cities' );
__( 'Midway', 'continents-cities' );
__( 'Nauru', 'continents-cities' );
__( 'Niue', 'continents-cities' );
__( 'Norfolk', 'continents-cities' );
__( 'Noumea', 'continents-cities' );
__( 'Pago Pago', 'continents-cities' );
__( 'Palau', 'continents-cities' );
__( 'Pitcairn', 'continents-cities' );
__( 'Pohnpei', 'continents-cities' );
__( 'Ponape', 'continents-cities' );
__( 'Port Moresby', 'continents-cities' );
__( 'Rarotonga', 'continents-cities' );
__( 'Saipan', 'continents-cities' );
__( 'Samoa', 'continents-cities' );
__( 'Tahiti', 'continents-cities' );
__( 'Tarawa', 'continents-cities' );
__( 'Tongatapu', 'continents-cities' );
__( 'Truk', 'continents-cities' );
__( 'Wake', 'continents-cities' );
__( 'Wallis', 'continents-cities' );
__( 'Yap', 'continents-cities' );
menu.php000064400000022622151212616040006223 0ustar00<?php
/**
 * Build Administration Menu.
 *
 * @package WordPress
 * @subpackage Administration
 */

if ( is_network_admin() ) {

	/**
	 * Fires before the administration menu loads in the Network Admin.
	 *
	 * The hook fires before menus and sub-menus are removed based on user privileges.
	 *
	 * @since 3.1.0
	 * @access private
	 */
	do_action( '_network_admin_menu' );
} elseif ( is_user_admin() ) {

	/**
	 * Fires before the administration menu loads in the User Admin.
	 *
	 * The hook fires before menus and sub-menus are removed based on user privileges.
	 *
	 * @since 3.1.0
	 * @access private
	 */
	do_action( '_user_admin_menu' );
} else {

	/**
	 * Fires before the administration menu loads in the admin.
	 *
	 * The hook fires before menus and sub-menus are removed based on user privileges.
	 *
	 * @since 2.2.0
	 * @access private
	 */
	do_action( '_admin_menu' );
}

// Create list of page plugin hook names.
foreach ( $menu as $menu_page ) {
	$pos = strpos( $menu_page[2], '?' );

	if ( false !== $pos ) {
		// Handle post_type=post|page|foo pages.
		$hook_name = substr( $menu_page[2], 0, $pos );
		$hook_args = substr( $menu_page[2], $pos + 1 );
		wp_parse_str( $hook_args, $hook_args );

		// Set the hook name to be the post type.
		if ( isset( $hook_args['post_type'] ) ) {
			$hook_name = $hook_args['post_type'];
		} else {
			$hook_name = basename( $hook_name, '.php' );
		}
		unset( $hook_args );
	} else {
		$hook_name = basename( $menu_page[2], '.php' );
	}

	$hook_name = sanitize_title( $hook_name );

	if ( isset( $compat[ $hook_name ] ) ) {
		$hook_name = $compat[ $hook_name ];
	} elseif ( ! $hook_name ) {
		continue;
	}

	$admin_page_hooks[ $menu_page[2] ] = $hook_name;
}
unset( $menu_page, $compat );

$_wp_submenu_nopriv = array();
$_wp_menu_nopriv    = array();
// Loop over submenus and remove pages for which the user does not have privs.
foreach ( $submenu as $parent => $sub ) {
	foreach ( $sub as $index => $data ) {
		if ( ! current_user_can( $data[1] ) ) {
			unset( $submenu[ $parent ][ $index ] );
			$_wp_submenu_nopriv[ $parent ][ $data[2] ] = true;
		}
	}
	unset( $index, $data );

	if ( empty( $submenu[ $parent ] ) ) {
		unset( $submenu[ $parent ] );
	}
}
unset( $sub, $parent );

/*
 * Loop over the top-level menu.
 * Menus for which the original parent is not accessible due to lack of privileges
 * will have the next submenu in line be assigned as the new menu parent.
 */
foreach ( $menu as $id => $data ) {
	if ( empty( $submenu[ $data[2] ] ) ) {
		continue;
	}

	$subs       = $submenu[ $data[2] ];
	$first_sub  = reset( $subs );
	$old_parent = $data[2];
	$new_parent = $first_sub[2];

	/*
	 * If the first submenu is not the same as the assigned parent,
	 * make the first submenu the new parent.
	 */
	if ( $new_parent !== $old_parent ) {
		$_wp_real_parent_file[ $old_parent ] = $new_parent;

		$menu[ $id ][2] = $new_parent;

		foreach ( $submenu[ $old_parent ] as $index => $data ) {
			$submenu[ $new_parent ][ $index ] = $submenu[ $old_parent ][ $index ];
			unset( $submenu[ $old_parent ][ $index ] );
		}
		unset( $submenu[ $old_parent ], $index );

		if ( isset( $_wp_submenu_nopriv[ $old_parent ] ) ) {
			$_wp_submenu_nopriv[ $new_parent ] = $_wp_submenu_nopriv[ $old_parent ];
		}
	}
}
unset( $id, $data, $subs, $first_sub, $old_parent, $new_parent );

if ( is_network_admin() ) {

	/**
	 * Fires before the administration menu loads in the Network Admin.
	 *
	 * @since 3.1.0
	 *
	 * @param string $context Empty context.
	 */
	do_action( 'network_admin_menu', '' );
} elseif ( is_user_admin() ) {

	/**
	 * Fires before the administration menu loads in the User Admin.
	 *
	 * @since 3.1.0
	 *
	 * @param string $context Empty context.
	 */
	do_action( 'user_admin_menu', '' );
} else {

	/**
	 * Fires before the administration menu loads in the admin.
	 *
	 * @since 1.5.0
	 *
	 * @param string $context Empty context.
	 */
	do_action( 'admin_menu', '' );
}

/*
 * Remove menus that have no accessible submenus and require privileges
 * that the user does not have. Run re-parent loop again.
 */
foreach ( $menu as $id => $data ) {
	if ( ! current_user_can( $data[1] ) ) {
		$_wp_menu_nopriv[ $data[2] ] = true;
	}

	/*
	 * If there is only one submenu and it is has same destination as the parent,
	 * remove the submenu.
	 */
	if ( ! empty( $submenu[ $data[2] ] ) && 1 === count( $submenu[ $data[2] ] ) ) {
		$subs      = $submenu[ $data[2] ];
		$first_sub = reset( $subs );

		if ( $data[2] === $first_sub[2] ) {
			unset( $submenu[ $data[2] ] );
		}
	}

	// If submenu is empty...
	if ( empty( $submenu[ $data[2] ] ) ) {
		// And user doesn't have privs, remove menu.
		if ( isset( $_wp_menu_nopriv[ $data[2] ] ) ) {
			unset( $menu[ $id ] );
		}
	}
}
unset( $id, $data, $subs, $first_sub );

/**
 * Adds a CSS class to a string.
 *
 * @since 2.7.0
 *
 * @param string $class_to_add The CSS class to add.
 * @param string $classes      The string to add the CSS class to.
 * @return string The string with the CSS class added.
 */
function add_cssclass( $class_to_add, $classes ) {
	if ( empty( $classes ) ) {
		return $class_to_add;
	}

	return $classes . ' ' . $class_to_add;
}

/**
 * Adds CSS classes for top-level administration menu items.
 *
 * The list of added classes includes `.menu-top-first` and `.menu-top-last`.
 *
 * @since 2.7.0
 *
 * @param array $menu The array of administration menu items.
 * @return array The array of administration menu items with the CSS classes added.
 */
function add_menu_classes( $menu ) {
	$first_item  = false;
	$last_order  = false;
	$items_count = count( $menu );

	$i = 0;

	foreach ( $menu as $order => $top ) {
		++$i;

		if ( 0 === $order ) { // Dashboard is always shown/single.
			$menu[0][4] = add_cssclass( 'menu-top-first', $top[4] );
			$last_order = 0;
			continue;
		}

		if ( str_starts_with( $top[2], 'separator' ) && false !== $last_order ) { // If separator.
			$first_item = true;
			$classes    = $menu[ $last_order ][4];

			$menu[ $last_order ][4] = add_cssclass( 'menu-top-last', $classes );
			continue;
		}

		if ( $first_item ) {
			$first_item = false;
			$classes    = $menu[ $order ][4];

			$menu[ $order ][4] = add_cssclass( 'menu-top-first', $classes );
		}

		if ( $i === $items_count ) { // Last item.
			$classes = $menu[ $order ][4];

			$menu[ $order ][4] = add_cssclass( 'menu-top-last', $classes );
		}

		$last_order = $order;
	}

	/**
	 * Filters administration menu array with classes added for top-level items.
	 *
	 * @since 2.7.0
	 *
	 * @param array $menu Associative array of administration menu items.
	 */
	return apply_filters( 'add_menu_classes', $menu );
}

uksort( $menu, 'strnatcasecmp' ); // Make it all pretty.

/**
 * Filters whether to enable custom ordering of the administration menu.
 *
 * See the {@see 'menu_order'} filter for reordering menu items.
 *
 * @since 2.8.0
 *
 * @param bool $custom Whether custom ordering is enabled. Default false.
 */
if ( apply_filters( 'custom_menu_order', false ) ) {
	$menu_order = array();

	foreach ( $menu as $menu_item ) {
		$menu_order[] = $menu_item[2];
	}
	unset( $menu_item );

	$default_menu_order = $menu_order;

	/**
	 * Filters the order of administration menu items.
	 *
	 * A truthy value must first be passed to the {@see 'custom_menu_order'} filter
	 * for this filter to work. Use the following to enable custom menu ordering:
	 *
	 *     add_filter( 'custom_menu_order', '__return_true' );
	 *
	 * @since 2.8.0
	 *
	 * @param array $menu_order An ordered array of menu items.
	 */
	$menu_order = apply_filters( 'menu_order', $menu_order );
	$menu_order = array_flip( $menu_order );

	$default_menu_order = array_flip( $default_menu_order );

	/**
	 * @global array $menu_order
	 * @global array $default_menu_order
	 *
	 * @param array $a
	 * @param array $b
	 * @return int
	 */
	function sort_menu( $a, $b ) {
		global $menu_order, $default_menu_order;

		$a = $a[2];
		$b = $b[2];

		if ( isset( $menu_order[ $a ] ) && ! isset( $menu_order[ $b ] ) ) {
			return -1;
		} elseif ( ! isset( $menu_order[ $a ] ) && isset( $menu_order[ $b ] ) ) {
			return 1;
		} elseif ( isset( $menu_order[ $a ] ) && isset( $menu_order[ $b ] ) ) {
			if ( $menu_order[ $a ] === $menu_order[ $b ] ) {
				return 0;
			}
			return ( $menu_order[ $a ] < $menu_order[ $b ] ) ? -1 : 1;
		} else {
			return ( $default_menu_order[ $a ] <= $default_menu_order[ $b ] ) ? -1 : 1;
		}
	}

	usort( $menu, 'sort_menu' );
	unset( $menu_order, $default_menu_order );
}

// Prevent adjacent separators.
$prev_menu_was_separator = false;
foreach ( $menu as $id => $data ) {
	if ( false === stristr( $data[4], 'wp-menu-separator' ) ) {

		// This item is not a separator, so falsey the toggler and do nothing.
		$prev_menu_was_separator = false;
	} else {

		// The previous item was a separator, so unset this one.
		if ( true === $prev_menu_was_separator ) {
			unset( $menu[ $id ] );
		}

		// This item is a separator, so truthy the toggler and move on.
		$prev_menu_was_separator = true;
	}
}
unset( $id, $data, $prev_menu_was_separator );

// Remove the last menu item if it is a separator.
$last_menu_key = array_keys( $menu );
$last_menu_key = array_pop( $last_menu_key );
if ( ! empty( $menu ) && 'wp-menu-separator' === $menu[ $last_menu_key ][4] ) {
	unset( $menu[ $last_menu_key ] );
}
unset( $last_menu_key );

if ( ! user_can_access_admin_page() ) {

	/**
	 * Fires when access to an admin page is denied.
	 *
	 * @since 2.5.0
	 */
	do_action( 'admin_page_access_denied' );

	wp_die( __( 'Sorry, you are not allowed to access this page.' ), 403 );
}

$menu = add_menu_classes( $menu );
ajax-actions.php000064400000450527151212616040007651 0ustar00<?php
/**
 * Administration API: Core Ajax handlers
 *
 * @package WordPress
 * @subpackage Administration
 * @since 2.1.0
 */

//
// No-privilege Ajax handlers.
//

/**
 * Handles the Heartbeat API in the no-privilege context via AJAX .
 *
 * Runs when the user is not logged in.
 *
 * @since 3.6.0
 */
function wp_ajax_nopriv_heartbeat() {
	$response = array();

	// 'screen_id' is the same as $current_screen->id and the JS global 'pagenow'.
	if ( ! empty( $_POST['screen_id'] ) ) {
		$screen_id = sanitize_key( $_POST['screen_id'] );
	} else {
		$screen_id = 'front';
	}

	if ( ! empty( $_POST['data'] ) ) {
		$data = wp_unslash( (array) $_POST['data'] );

		/**
		 * Filters Heartbeat Ajax response in no-privilege environments.
		 *
		 * @since 3.6.0
		 *
		 * @param array  $response  The no-priv Heartbeat response.
		 * @param array  $data      The $_POST data sent.
		 * @param string $screen_id The screen ID.
		 */
		$response = apply_filters( 'heartbeat_nopriv_received', $response, $data, $screen_id );
	}

	/**
	 * Filters Heartbeat Ajax response in no-privilege environments when no data is passed.
	 *
	 * @since 3.6.0
	 *
	 * @param array  $response  The no-priv Heartbeat response.
	 * @param string $screen_id The screen ID.
	 */
	$response = apply_filters( 'heartbeat_nopriv_send', $response, $screen_id );

	/**
	 * Fires when Heartbeat ticks in no-privilege environments.
	 *
	 * Allows the transport to be easily replaced with long-polling.
	 *
	 * @since 3.6.0
	 *
	 * @param array  $response  The no-priv Heartbeat response.
	 * @param string $screen_id The screen ID.
	 */
	do_action( 'heartbeat_nopriv_tick', $response, $screen_id );

	// Send the current time according to the server.
	$response['server_time'] = time();

	wp_send_json( $response );
}

//
// GET-based Ajax handlers.
//

/**
 * Handles fetching a list table via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_fetch_list() {
	$list_class = $_GET['list_args']['class'];
	check_ajax_referer( "fetch-list-$list_class", '_ajax_fetch_list_nonce' );

	$wp_list_table = _get_list_table( $list_class, array( 'screen' => $_GET['list_args']['screen']['id'] ) );
	if ( ! $wp_list_table ) {
		wp_die( 0 );
	}

	if ( ! $wp_list_table->ajax_user_can() ) {
		wp_die( -1 );
	}

	$wp_list_table->ajax_response();

	wp_die( 0 );
}

/**
 * Handles tag search via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_ajax_tag_search() {
	if ( ! isset( $_GET['tax'] ) ) {
		wp_die( 0 );
	}

	$taxonomy        = sanitize_key( $_GET['tax'] );
	$taxonomy_object = get_taxonomy( $taxonomy );

	if ( ! $taxonomy_object ) {
		wp_die( 0 );
	}

	if ( ! current_user_can( $taxonomy_object->cap->assign_terms ) ) {
		wp_die( -1 );
	}

	$search = wp_unslash( $_GET['q'] );

	$comma = _x( ',', 'tag delimiter' );
	if ( ',' !== $comma ) {
		$search = str_replace( $comma, ',', $search );
	}

	if ( str_contains( $search, ',' ) ) {
		$search = explode( ',', $search );
		$search = $search[ count( $search ) - 1 ];
	}

	$search = trim( $search );

	/**
	 * Filters the minimum number of characters required to fire a tag search via Ajax.
	 *
	 * @since 4.0.0
	 *
	 * @param int         $characters      The minimum number of characters required. Default 2.
	 * @param WP_Taxonomy $taxonomy_object The taxonomy object.
	 * @param string      $search          The search term.
	 */
	$term_search_min_chars = (int) apply_filters( 'term_search_min_chars', 2, $taxonomy_object, $search );

	/*
	 * Require $term_search_min_chars chars for matching (default: 2)
	 * ensure it's a non-negative, non-zero integer.
	 */
	if ( ( 0 === $term_search_min_chars ) || ( strlen( $search ) < $term_search_min_chars ) ) {
		wp_die();
	}

	$results = get_terms(
		array(
			'taxonomy'   => $taxonomy,
			'name__like' => $search,
			'fields'     => 'names',
			'hide_empty' => false,
			'number'     => isset( $_GET['number'] ) ? (int) $_GET['number'] : 0,
		)
	);

	/**
	 * Filters the Ajax term search results.
	 *
	 * @since 6.1.0
	 *
	 * @param string[]    $results         Array of term names.
	 * @param WP_Taxonomy $taxonomy_object The taxonomy object.
	 * @param string      $search          The search term.
	 */
	$results = apply_filters( 'ajax_term_search_results', $results, $taxonomy_object, $search );

	echo implode( "\n", $results );
	wp_die();
}

/**
 * Handles compression testing via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_wp_compression_test() {
	if ( ! current_user_can( 'manage_options' ) ) {
		wp_die( -1 );
	}

	if ( ini_get( 'zlib.output_compression' ) || 'ob_gzhandler' === ini_get( 'output_handler' ) ) {
		// Use `update_option()` on single site to mark the option for autoloading.
		if ( is_multisite() ) {
			update_site_option( 'can_compress_scripts', 0 );
		} else {
			update_option( 'can_compress_scripts', 0, true );
		}
		wp_die( 0 );
	}

	if ( isset( $_GET['test'] ) ) {
		header( 'Expires: Wed, 11 Jan 1984 05:00:00 GMT' );
		header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
		header( 'Cache-Control: no-cache, must-revalidate, max-age=0' );
		header( 'Content-Type: application/javascript; charset=UTF-8' );
		$force_gzip = ( defined( 'ENFORCE_GZIP' ) && ENFORCE_GZIP );
		$test_str   = '"wpCompressionTest Lorem ipsum dolor sit amet consectetuer mollis sapien urna ut a. Eu nonummy condimentum fringilla tempor pretium platea vel nibh netus Maecenas. Hac molestie amet justo quis pellentesque est ultrices interdum nibh Morbi. Cras mattis pretium Phasellus ante ipsum ipsum ut sociis Suspendisse Lorem. Ante et non molestie. Porta urna Vestibulum egestas id congue nibh eu risus gravida sit. Ac augue auctor Ut et non a elit massa id sodales. Elit eu Nulla at nibh adipiscing mattis lacus mauris at tempus. Netus nibh quis suscipit nec feugiat eget sed lorem et urna. Pellentesque lacus at ut massa consectetuer ligula ut auctor semper Pellentesque. Ut metus massa nibh quam Curabitur molestie nec mauris congue. Volutpat molestie elit justo facilisis neque ac risus Ut nascetur tristique. Vitae sit lorem tellus et quis Phasellus lacus tincidunt nunc Fusce. Pharetra wisi Suspendisse mus sagittis libero lacinia Integer consequat ac Phasellus. Et urna ac cursus tortor aliquam Aliquam amet tellus volutpat Vestibulum. Justo interdum condimentum In augue congue tellus sollicitudin Quisque quis nibh."';

		if ( '1' === $_GET['test'] ) {
			echo $test_str;
			wp_die();
		} elseif ( '2' === $_GET['test'] ) {
			if ( ! isset( $_SERVER['HTTP_ACCEPT_ENCODING'] ) ) {
				wp_die( -1 );
			}

			if ( false !== stripos( $_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate' ) && function_exists( 'gzdeflate' ) && ! $force_gzip ) {
				header( 'Content-Encoding: deflate' );
				$out = gzdeflate( $test_str, 1 );
			} elseif ( false !== stripos( $_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip' ) && function_exists( 'gzencode' ) ) {
				header( 'Content-Encoding: gzip' );
				$out = gzencode( $test_str, 1 );
			} else {
				wp_die( -1 );
			}

			echo $out;
			wp_die();
		} elseif ( 'no' === $_GET['test'] ) {
			check_ajax_referer( 'update_can_compress_scripts' );
			// Use `update_option()` on single site to mark the option for autoloading.
			if ( is_multisite() ) {
				update_site_option( 'can_compress_scripts', 0 );
			} else {
				update_option( 'can_compress_scripts', 0, true );
			}
		} elseif ( 'yes' === $_GET['test'] ) {
			check_ajax_referer( 'update_can_compress_scripts' );
			// Use `update_option()` on single site to mark the option for autoloading.
			if ( is_multisite() ) {
				update_site_option( 'can_compress_scripts', 1 );
			} else {
				update_option( 'can_compress_scripts', 1, true );
			}
		}
	}

	wp_die( 0 );
}

/**
 * Handles image editor previews via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_imgedit_preview() {
	$post_id = (int) $_GET['postid'];
	if ( empty( $post_id ) || ! current_user_can( 'edit_post', $post_id ) ) {
		wp_die( -1 );
	}

	check_ajax_referer( "image_editor-$post_id" );

	require_once ABSPATH . 'wp-admin/includes/image-edit.php';

	if ( ! stream_preview_image( $post_id ) ) {
		wp_die( -1 );
	}

	wp_die();
}

/**
 * Handles oEmbed caching via AJAX.
 *
 * @since 3.1.0
 *
 * @global WP_Embed $wp_embed WordPress Embed object.
 */
function wp_ajax_oembed_cache() {
	$GLOBALS['wp_embed']->cache_oembed( $_GET['post'] );
	wp_die( 0 );
}

/**
 * Handles user autocomplete via AJAX.
 *
 * @since 3.4.0
 */
function wp_ajax_autocomplete_user() {
	if ( ! is_multisite() || ! current_user_can( 'promote_users' ) || wp_is_large_network( 'users' ) ) {
		wp_die( -1 );
	}

	/** This filter is documented in wp-admin/user-new.php */
	if ( ! current_user_can( 'manage_network_users' ) && ! apply_filters( 'autocomplete_users_for_site_admins', false ) ) {
		wp_die( -1 );
	}

	$return = array();

	/*
	 * Check the type of request.
	 * Current allowed values are `add` and `search`.
	 */
	if ( isset( $_REQUEST['autocomplete_type'] ) && 'search' === $_REQUEST['autocomplete_type'] ) {
		$type = $_REQUEST['autocomplete_type'];
	} else {
		$type = 'add';
	}

	/*
	 * Check the desired field for value.
	 * Current allowed values are `user_email` and `user_login`.
	 */
	if ( isset( $_REQUEST['autocomplete_field'] ) && 'user_email' === $_REQUEST['autocomplete_field'] ) {
		$field = $_REQUEST['autocomplete_field'];
	} else {
		$field = 'user_login';
	}

	// Exclude current users of this blog.
	if ( isset( $_REQUEST['site_id'] ) ) {
		$id = absint( $_REQUEST['site_id'] );
	} else {
		$id = get_current_blog_id();
	}

	$include_blog_users = ( 'search' === $type ? get_users(
		array(
			'blog_id' => $id,
			'fields'  => 'ID',
		)
	) : array() );

	$exclude_blog_users = ( 'add' === $type ? get_users(
		array(
			'blog_id' => $id,
			'fields'  => 'ID',
		)
	) : array() );

	$users = get_users(
		array(
			'blog_id'        => false,
			'search'         => '*' . $_REQUEST['term'] . '*',
			'include'        => $include_blog_users,
			'exclude'        => $exclude_blog_users,
			'search_columns' => array( 'user_login', 'user_nicename', 'user_email' ),
		)
	);

	foreach ( $users as $user ) {
		$return[] = array(
			/* translators: 1: User login, 2: User email address. */
			'label' => sprintf( _x( '%1$s (%2$s)', 'user autocomplete result' ), $user->user_login, $user->user_email ),
			'value' => $user->$field,
		);
	}

	wp_die( wp_json_encode( $return ) );
}

/**
 * Handles Ajax requests for community events
 *
 * @since 4.8.0
 */
function wp_ajax_get_community_events() {
	require_once ABSPATH . 'wp-admin/includes/class-wp-community-events.php';

	check_ajax_referer( 'community_events' );

	$search         = isset( $_POST['location'] ) ? wp_unslash( $_POST['location'] ) : '';
	$timezone       = isset( $_POST['timezone'] ) ? wp_unslash( $_POST['timezone'] ) : '';
	$user_id        = get_current_user_id();
	$saved_location = get_user_option( 'community-events-location', $user_id );
	$events_client  = new WP_Community_Events( $user_id, $saved_location );
	$events         = $events_client->get_events( $search, $timezone );
	$ip_changed     = false;

	if ( is_wp_error( $events ) ) {
		wp_send_json_error(
			array(
				'error' => $events->get_error_message(),
			)
		);
	} else {
		if ( empty( $saved_location['ip'] ) && ! empty( $events['location']['ip'] ) ) {
			$ip_changed = true;
		} elseif ( isset( $saved_location['ip'] ) && ! empty( $events['location']['ip'] ) && $saved_location['ip'] !== $events['location']['ip'] ) {
			$ip_changed = true;
		}

		/*
		 * The location should only be updated when it changes. The API doesn't always return
		 * a full location; sometimes it's missing the description or country. The location
		 * that was saved during the initial request is known to be good and complete, though.
		 * It should be left intact until the user explicitly changes it (either by manually
		 * searching for a new location, or by changing their IP address).
		 *
		 * If the location was updated with an incomplete response from the API, then it could
		 * break assumptions that the UI makes (e.g., that there will always be a description
		 * that corresponds to a latitude/longitude location).
		 *
		 * The location is stored network-wide, so that the user doesn't have to set it on each site.
		 */
		if ( $ip_changed || $search ) {
			update_user_meta( $user_id, 'community-events-location', $events['location'] );
		}

		wp_send_json_success( $events );
	}
}

/**
 * Handles dashboard widgets via AJAX.
 *
 * @since 3.4.0
 */
function wp_ajax_dashboard_widgets() {
	require_once ABSPATH . 'wp-admin/includes/dashboard.php';

	$pagenow = $_GET['pagenow'];
	if ( 'dashboard-user' === $pagenow || 'dashboard-network' === $pagenow || 'dashboard' === $pagenow ) {
		set_current_screen( $pagenow );
	}

	switch ( $_GET['widget'] ) {
		case 'dashboard_primary':
			wp_dashboard_primary();
			break;
	}
	wp_die();
}

/**
 * Handles Customizer preview logged-in status via AJAX.
 *
 * @since 3.4.0
 */
function wp_ajax_logged_in() {
	wp_die( 1 );
}

//
// Ajax helpers.
//

/**
 * Sends back current comment total and new page links if they need to be updated.
 *
 * Contrary to normal success Ajax response ("1"), die with time() on success.
 *
 * @since 2.7.0
 * @access private
 *
 * @param int $comment_id
 * @param int $delta
 */
function _wp_ajax_delete_comment_response( $comment_id, $delta = -1 ) {
	$total    = isset( $_POST['_total'] ) ? (int) $_POST['_total'] : 0;
	$per_page = isset( $_POST['_per_page'] ) ? (int) $_POST['_per_page'] : 0;
	$page     = isset( $_POST['_page'] ) ? (int) $_POST['_page'] : 0;
	$url      = isset( $_POST['_url'] ) ? sanitize_url( $_POST['_url'] ) : '';

	// JS didn't send us everything we need to know. Just die with success message.
	if ( ! $total || ! $per_page || ! $page || ! $url ) {
		$time           = time();
		$comment        = get_comment( $comment_id );
		$comment_status = '';
		$comment_link   = '';

		if ( $comment ) {
			$comment_status = $comment->comment_approved;
		}

		if ( 1 === (int) $comment_status ) {
			$comment_link = get_comment_link( $comment );
		}

		$counts = wp_count_comments();

		$x = new WP_Ajax_Response(
			array(
				'what'         => 'comment',
				// Here for completeness - not used.
				'id'           => $comment_id,
				'supplemental' => array(
					'status'               => $comment_status,
					'postId'               => $comment ? $comment->comment_post_ID : '',
					'time'                 => $time,
					'in_moderation'        => $counts->moderated,
					'i18n_comments_text'   => sprintf(
						/* translators: %s: Number of comments. */
						_n( '%s Comment', '%s Comments', $counts->approved ),
						number_format_i18n( $counts->approved )
					),
					'i18n_moderation_text' => sprintf(
						/* translators: %s: Number of comments. */
						_n( '%s Comment in moderation', '%s Comments in moderation', $counts->moderated ),
						number_format_i18n( $counts->moderated )
					),
					'comment_link'         => $comment_link,
				),
			)
		);
		$x->send();
	}

	$total += $delta;
	if ( $total < 0 ) {
		$total = 0;
	}

	// Only do the expensive stuff on a page-break, and about 1 other time per page.
	if ( 0 === $total % $per_page || 1 === mt_rand( 1, $per_page ) ) {
		$post_id = 0;
		// What type of comment count are we looking for?
		$status = 'all';
		$parsed = parse_url( $url );

		if ( isset( $parsed['query'] ) ) {
			parse_str( $parsed['query'], $query_vars );

			if ( ! empty( $query_vars['comment_status'] ) ) {
				$status = $query_vars['comment_status'];
			}

			if ( ! empty( $query_vars['p'] ) ) {
				$post_id = (int) $query_vars['p'];
			}

			if ( ! empty( $query_vars['comment_type'] ) ) {
				$type = $query_vars['comment_type'];
			}
		}

		if ( empty( $type ) ) {
			// Only use the comment count if not filtering by a comment_type.
			$comment_count = wp_count_comments( $post_id );

			// We're looking for a known type of comment count.
			if ( isset( $comment_count->$status ) ) {
				$total = $comment_count->$status;
			}
		}
		// Else use the decremented value from above.
	}

	// The time since the last comment count.
	$time    = time();
	$comment = get_comment( $comment_id );
	$counts  = wp_count_comments();

	$x = new WP_Ajax_Response(
		array(
			'what'         => 'comment',
			'id'           => $comment_id,
			'supplemental' => array(
				'status'               => $comment ? $comment->comment_approved : '',
				'postId'               => $comment ? $comment->comment_post_ID : '',
				/* translators: %s: Number of comments. */
				'total_items_i18n'     => sprintf( _n( '%s item', '%s items', $total ), number_format_i18n( $total ) ),
				'total_pages'          => (int) ceil( $total / $per_page ),
				'total_pages_i18n'     => number_format_i18n( (int) ceil( $total / $per_page ) ),
				'total'                => $total,
				'time'                 => $time,
				'in_moderation'        => $counts->moderated,
				'i18n_moderation_text' => sprintf(
					/* translators: %s: Number of comments. */
					_n( '%s Comment in moderation', '%s Comments in moderation', $counts->moderated ),
					number_format_i18n( $counts->moderated )
				),
			),
		)
	);
	$x->send();
}

//
// POST-based Ajax handlers.
//

/**
 * Handles adding a hierarchical term via AJAX.
 *
 * @since 3.1.0
 * @access private
 */
function _wp_ajax_add_hierarchical_term() {
	$action   = $_POST['action'];
	$taxonomy = get_taxonomy( substr( $action, 4 ) );
	check_ajax_referer( $action, '_ajax_nonce-add-' . $taxonomy->name );

	if ( ! current_user_can( $taxonomy->cap->edit_terms ) ) {
		wp_die( -1 );
	}

	$names  = explode( ',', $_POST[ 'new' . $taxonomy->name ] );
	$parent = isset( $_POST[ 'new' . $taxonomy->name . '_parent' ] ) ? (int) $_POST[ 'new' . $taxonomy->name . '_parent' ] : 0;

	if ( 0 > $parent ) {
		$parent = 0;
	}

	if ( 'category' === $taxonomy->name ) {
		$post_category = isset( $_POST['post_category'] ) ? (array) $_POST['post_category'] : array();
	} else {
		$post_category = ( isset( $_POST['tax_input'] ) && isset( $_POST['tax_input'][ $taxonomy->name ] ) ) ? (array) $_POST['tax_input'][ $taxonomy->name ] : array();
	}

	$checked_categories = array_map( 'absint', (array) $post_category );
	$popular_ids        = wp_popular_terms_checklist( $taxonomy->name, 0, 10, false );

	foreach ( $names as $cat_name ) {
		$cat_name          = trim( $cat_name );
		$category_nicename = sanitize_title( $cat_name );

		if ( '' === $category_nicename ) {
			continue;
		}

		$cat_id = wp_insert_term( $cat_name, $taxonomy->name, array( 'parent' => $parent ) );

		if ( ! $cat_id || is_wp_error( $cat_id ) ) {
			continue;
		} else {
			$cat_id = $cat_id['term_id'];
		}

		$checked_categories[] = $cat_id;

		if ( $parent ) { // Do these all at once in a second.
			continue;
		}

		ob_start();

		wp_terms_checklist(
			0,
			array(
				'taxonomy'             => $taxonomy->name,
				'descendants_and_self' => $cat_id,
				'selected_cats'        => $checked_categories,
				'popular_cats'         => $popular_ids,
			)
		);

		$data = ob_get_clean();

		$add = array(
			'what'     => $taxonomy->name,
			'id'       => $cat_id,
			'data'     => str_replace( array( "\n", "\t" ), '', $data ),
			'position' => -1,
		);
	}

	if ( $parent ) { // Foncy - replace the parent and all its children.
		$parent  = get_term( $parent, $taxonomy->name );
		$term_id = $parent->term_id;

		while ( $parent->parent ) { // Get the top parent.
			$parent = get_term( $parent->parent, $taxonomy->name );
			if ( is_wp_error( $parent ) ) {
				break;
			}
			$term_id = $parent->term_id;
		}

		ob_start();

		wp_terms_checklist(
			0,
			array(
				'taxonomy'             => $taxonomy->name,
				'descendants_and_self' => $term_id,
				'selected_cats'        => $checked_categories,
				'popular_cats'         => $popular_ids,
			)
		);

		$data = ob_get_clean();

		$add = array(
			'what'     => $taxonomy->name,
			'id'       => $term_id,
			'data'     => str_replace( array( "\n", "\t" ), '', $data ),
			'position' => -1,
		);
	}

	$parent_dropdown_args = array(
		'taxonomy'         => $taxonomy->name,
		'hide_empty'       => 0,
		'name'             => 'new' . $taxonomy->name . '_parent',
		'orderby'          => 'name',
		'hierarchical'     => 1,
		'show_option_none' => '&mdash; ' . $taxonomy->labels->parent_item . ' &mdash;',
	);

	/** This filter is documented in wp-admin/includes/meta-boxes.php */
	$parent_dropdown_args = apply_filters( 'post_edit_category_parent_dropdown_args', $parent_dropdown_args );

	ob_start();

	wp_dropdown_categories( $parent_dropdown_args );

	$sup = ob_get_clean();

	$add['supplemental'] = array( 'newcat_parent' => $sup );

	$x = new WP_Ajax_Response( $add );
	$x->send();
}

/**
 * Handles deleting a comment via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_delete_comment() {
	$id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;

	$comment = get_comment( $id );

	if ( ! $comment ) {
		wp_die( time() );
	}

	if ( ! current_user_can( 'edit_comment', $comment->comment_ID ) ) {
		wp_die( -1 );
	}

	check_ajax_referer( "delete-comment_$id" );
	$status = wp_get_comment_status( $comment );
	$delta  = -1;

	if ( isset( $_POST['trash'] ) && '1' === $_POST['trash'] ) {
		if ( 'trash' === $status ) {
			wp_die( time() );
		}

		$r = wp_trash_comment( $comment );
	} elseif ( isset( $_POST['untrash'] ) && '1' === $_POST['untrash'] ) {
		if ( 'trash' !== $status ) {
			wp_die( time() );
		}

		$r = wp_untrash_comment( $comment );

		// Undo trash, not in Trash.
		if ( ! isset( $_POST['comment_status'] ) || 'trash' !== $_POST['comment_status'] ) {
			$delta = 1;
		}
	} elseif ( isset( $_POST['spam'] ) && '1' === $_POST['spam'] ) {
		if ( 'spam' === $status ) {
			wp_die( time() );
		}

		$r = wp_spam_comment( $comment );
	} elseif ( isset( $_POST['unspam'] ) && '1' === $_POST['unspam'] ) {
		if ( 'spam' !== $status ) {
			wp_die( time() );
		}

		$r = wp_unspam_comment( $comment );

		// Undo spam, not in spam.
		if ( ! isset( $_POST['comment_status'] ) || 'spam' !== $_POST['comment_status'] ) {
			$delta = 1;
		}
	} elseif ( isset( $_POST['delete'] ) && '1' === $_POST['delete'] ) {
		$r = wp_delete_comment( $comment );
	} else {
		wp_die( -1 );
	}

	if ( $r ) {
		// Decide if we need to send back '1' or a more complicated response including page links and comment counts.
		_wp_ajax_delete_comment_response( $comment->comment_ID, $delta );
	}

	wp_die( 0 );
}

/**
 * Handles deleting a tag via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_delete_tag() {
	$tag_id = (int) $_POST['tag_ID'];
	check_ajax_referer( "delete-tag_$tag_id" );

	if ( ! current_user_can( 'delete_term', $tag_id ) ) {
		wp_die( -1 );
	}

	$taxonomy = ! empty( $_POST['taxonomy'] ) ? $_POST['taxonomy'] : 'post_tag';
	$tag      = get_term( $tag_id, $taxonomy );

	if ( ! $tag || is_wp_error( $tag ) ) {
		wp_die( 1 );
	}

	if ( wp_delete_term( $tag_id, $taxonomy ) ) {
		wp_die( 1 );
	} else {
		wp_die( 0 );
	}
}

/**
 * Handles deleting a link via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_delete_link() {
	$id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;

	check_ajax_referer( "delete-bookmark_$id" );

	if ( ! current_user_can( 'manage_links' ) ) {
		wp_die( -1 );
	}

	$link = get_bookmark( $id );
	if ( ! $link || is_wp_error( $link ) ) {
		wp_die( 1 );
	}

	if ( wp_delete_link( $id ) ) {
		wp_die( 1 );
	} else {
		wp_die( 0 );
	}
}

/**
 * Handles deleting meta via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_delete_meta() {
	$id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;

	check_ajax_referer( "delete-meta_$id" );
	$meta = get_metadata_by_mid( 'post', $id );

	if ( ! $meta ) {
		wp_die( 1 );
	}

	if ( is_protected_meta( $meta->meta_key, 'post' ) || ! current_user_can( 'delete_post_meta', $meta->post_id, $meta->meta_key ) ) {
		wp_die( -1 );
	}

	if ( delete_meta( $meta->meta_id ) ) {
		wp_die( 1 );
	}

	wp_die( 0 );
}

/**
 * Handles deleting a post via AJAX.
 *
 * @since 3.1.0
 *
 * @param string $action Action to perform.
 */
function wp_ajax_delete_post( $action ) {
	if ( empty( $action ) ) {
		$action = 'delete-post';
	}

	$id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
	check_ajax_referer( "{$action}_$id" );

	if ( ! current_user_can( 'delete_post', $id ) ) {
		wp_die( -1 );
	}

	if ( ! get_post( $id ) ) {
		wp_die( 1 );
	}

	if ( wp_delete_post( $id ) ) {
		wp_die( 1 );
	} else {
		wp_die( 0 );
	}
}

/**
 * Handles sending a post to the Trash via AJAX.
 *
 * @since 3.1.0
 *
 * @param string $action Action to perform.
 */
function wp_ajax_trash_post( $action ) {
	if ( empty( $action ) ) {
		$action = 'trash-post';
	}

	$id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
	check_ajax_referer( "{$action}_$id" );

	if ( ! current_user_can( 'delete_post', $id ) ) {
		wp_die( -1 );
	}

	if ( ! get_post( $id ) ) {
		wp_die( 1 );
	}

	if ( 'trash-post' === $action ) {
		$done = wp_trash_post( $id );
	} else {
		$done = wp_untrash_post( $id );
	}

	if ( $done ) {
		wp_die( 1 );
	}

	wp_die( 0 );
}

/**
 * Handles restoring a post from the Trash via AJAX.
 *
 * @since 3.1.0
 *
 * @param string $action Action to perform.
 */
function wp_ajax_untrash_post( $action ) {
	if ( empty( $action ) ) {
		$action = 'untrash-post';
	}

	wp_ajax_trash_post( $action );
}

/**
 * Handles deleting a page via AJAX.
 *
 * @since 3.1.0
 *
 * @param string $action Action to perform.
 */
function wp_ajax_delete_page( $action ) {
	if ( empty( $action ) ) {
		$action = 'delete-page';
	}

	$id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
	check_ajax_referer( "{$action}_$id" );

	if ( ! current_user_can( 'delete_page', $id ) ) {
		wp_die( -1 );
	}

	if ( ! get_post( $id ) ) {
		wp_die( 1 );
	}

	if ( wp_delete_post( $id ) ) {
		wp_die( 1 );
	} else {
		wp_die( 0 );
	}
}

/**
 * Handles dimming a comment via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_dim_comment() {
	$id      = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
	$comment = get_comment( $id );

	if ( ! $comment ) {
		$x = new WP_Ajax_Response(
			array(
				'what' => 'comment',
				'id'   => new WP_Error(
					'invalid_comment',
					/* translators: %d: Comment ID. */
					sprintf( __( 'Comment %d does not exist' ), $id )
				),
			)
		);
		$x->send();
	}

	if ( ! current_user_can( 'edit_comment', $comment->comment_ID ) && ! current_user_can( 'moderate_comments' ) ) {
		wp_die( -1 );
	}

	$current = wp_get_comment_status( $comment );

	if ( isset( $_POST['new'] ) && $_POST['new'] === $current ) {
		wp_die( time() );
	}

	check_ajax_referer( "approve-comment_$id" );

	if ( in_array( $current, array( 'unapproved', 'spam' ), true ) ) {
		$result = wp_set_comment_status( $comment, 'approve', true );
	} else {
		$result = wp_set_comment_status( $comment, 'hold', true );
	}

	if ( is_wp_error( $result ) ) {
		$x = new WP_Ajax_Response(
			array(
				'what' => 'comment',
				'id'   => $result,
			)
		);
		$x->send();
	}

	// Decide if we need to send back '1' or a more complicated response including page links and comment counts.
	_wp_ajax_delete_comment_response( $comment->comment_ID );
	wp_die( 0 );
}

/**
 * Handles adding a link category via AJAX.
 *
 * @since 3.1.0
 *
 * @param string $action Action to perform.
 */
function wp_ajax_add_link_category( $action ) {
	if ( empty( $action ) ) {
		$action = 'add-link-category';
	}

	check_ajax_referer( $action );

	$taxonomy_object = get_taxonomy( 'link_category' );

	if ( ! current_user_can( $taxonomy_object->cap->manage_terms ) ) {
		wp_die( -1 );
	}

	$names = explode( ',', wp_unslash( $_POST['newcat'] ) );
	$x     = new WP_Ajax_Response();

	foreach ( $names as $cat_name ) {
		$cat_name = trim( $cat_name );
		$slug     = sanitize_title( $cat_name );

		if ( '' === $slug ) {
			continue;
		}

		$cat_id = wp_insert_term( $cat_name, 'link_category' );

		if ( ! $cat_id || is_wp_error( $cat_id ) ) {
			continue;
		} else {
			$cat_id = $cat_id['term_id'];
		}

		$cat_name = esc_html( $cat_name );

		$x->add(
			array(
				'what'     => 'link-category',
				'id'       => $cat_id,
				'data'     => "<li id='link-category-$cat_id'><label for='in-link-category-$cat_id' class='selectit'><input value='" . esc_attr( $cat_id ) . "' type='checkbox' checked='checked' name='link_category[]' id='in-link-category-$cat_id'/> $cat_name</label></li>",
				'position' => -1,
			)
		);
	}
	$x->send();
}

/**
 * Handles adding a tag via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_add_tag() {
	check_ajax_referer( 'add-tag', '_wpnonce_add-tag' );

	$taxonomy        = ! empty( $_POST['taxonomy'] ) ? $_POST['taxonomy'] : 'post_tag';
	$taxonomy_object = get_taxonomy( $taxonomy );

	if ( ! current_user_can( $taxonomy_object->cap->edit_terms ) ) {
		wp_die( -1 );
	}

	$x = new WP_Ajax_Response();

	$tag = wp_insert_term( $_POST['tag-name'], $taxonomy, $_POST );

	if ( $tag && ! is_wp_error( $tag ) ) {
		$tag = get_term( $tag['term_id'], $taxonomy );
	}

	if ( ! $tag || is_wp_error( $tag ) ) {
		$message    = __( 'An error has occurred. Please reload the page and try again.' );
		$error_code = 'error';

		if ( is_wp_error( $tag ) && $tag->get_error_message() ) {
			$message = $tag->get_error_message();
		}

		if ( is_wp_error( $tag ) && $tag->get_error_code() ) {
			$error_code = $tag->get_error_code();
		}

		$x->add(
			array(
				'what' => 'taxonomy',
				'data' => new WP_Error( $error_code, $message ),
			)
		);
		$x->send();
	}

	$wp_list_table = _get_list_table( 'WP_Terms_List_Table', array( 'screen' => $_POST['screen'] ) );

	$level     = 0;
	$noparents = '';

	if ( is_taxonomy_hierarchical( $taxonomy ) ) {
		$level = count( get_ancestors( $tag->term_id, $taxonomy, 'taxonomy' ) );
		ob_start();
		$wp_list_table->single_row( $tag, $level );
		$noparents = ob_get_clean();
	}

	ob_start();
	$wp_list_table->single_row( $tag );
	$parents = ob_get_clean();

	require ABSPATH . 'wp-admin/includes/edit-tag-messages.php';

	$message = '';
	if ( isset( $messages[ $taxonomy_object->name ][1] ) ) {
		$message = $messages[ $taxonomy_object->name ][1];
	} elseif ( isset( $messages['_item'][1] ) ) {
		$message = $messages['_item'][1];
	}

	$x->add(
		array(
			'what'         => 'taxonomy',
			'data'         => $message,
			'supplemental' => array(
				'parents'   => $parents,
				'noparents' => $noparents,
				'notice'    => $message,
			),
		)
	);

	$x->add(
		array(
			'what'         => 'term',
			'position'     => $level,
			'supplemental' => (array) $tag,
		)
	);

	$x->send();
}

/**
 * Handles getting a tagcloud via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_get_tagcloud() {
	if ( ! isset( $_POST['tax'] ) ) {
		wp_die( 0 );
	}

	$taxonomy        = sanitize_key( $_POST['tax'] );
	$taxonomy_object = get_taxonomy( $taxonomy );

	if ( ! $taxonomy_object ) {
		wp_die( 0 );
	}

	if ( ! current_user_can( $taxonomy_object->cap->assign_terms ) ) {
		wp_die( -1 );
	}

	$tags = get_terms(
		array(
			'taxonomy' => $taxonomy,
			'number'   => 45,
			'orderby'  => 'count',
			'order'    => 'DESC',
		)
	);

	if ( empty( $tags ) ) {
		wp_die( $taxonomy_object->labels->not_found );
	}

	if ( is_wp_error( $tags ) ) {
		wp_die( $tags->get_error_message() );
	}

	foreach ( $tags as $key => $tag ) {
		$tags[ $key ]->link = '#';
		$tags[ $key ]->id   = $tag->term_id;
	}

	// We need raw tag names here, so don't filter the output.
	$return = wp_generate_tag_cloud(
		$tags,
		array(
			'filter' => 0,
			'format' => 'list',
		)
	);

	if ( empty( $return ) ) {
		wp_die( 0 );
	}

	echo $return;
	wp_die();
}

/**
 * Handles getting comments via AJAX.
 *
 * @since 3.1.0
 *
 * @global int $post_id
 *
 * @param string $action Action to perform.
 */
function wp_ajax_get_comments( $action ) {
	global $post_id;

	if ( empty( $action ) ) {
		$action = 'get-comments';
	}

	check_ajax_referer( $action );

	if ( empty( $post_id ) && ! empty( $_REQUEST['p'] ) ) {
		$id = absint( $_REQUEST['p'] );
		if ( ! empty( $id ) ) {
			$post_id = $id;
		}
	}

	if ( empty( $post_id ) ) {
		wp_die( -1 );
	}

	$wp_list_table = _get_list_table( 'WP_Post_Comments_List_Table', array( 'screen' => 'edit-comments' ) );

	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		wp_die( -1 );
	}

	$wp_list_table->prepare_items();

	if ( ! $wp_list_table->has_items() ) {
		wp_die( 1 );
	}

	$x = new WP_Ajax_Response();

	ob_start();
	foreach ( $wp_list_table->items as $comment ) {
		if ( ! current_user_can( 'edit_comment', $comment->comment_ID ) && 0 === $comment->comment_approved ) {
			continue;
		}
		get_comment( $comment );
		$wp_list_table->single_row( $comment );
	}
	$comment_list_item = ob_get_clean();

	$x->add(
		array(
			'what' => 'comments',
			'data' => $comment_list_item,
		)
	);

	$x->send();
}

/**
 * Handles replying to a comment via AJAX.
 *
 * @since 3.1.0
 *
 * @param string $action Action to perform.
 */
function wp_ajax_replyto_comment( $action ) {
	if ( empty( $action ) ) {
		$action = 'replyto-comment';
	}

	check_ajax_referer( $action, '_ajax_nonce-replyto-comment' );

	$comment_post_id = (int) $_POST['comment_post_ID'];
	$post            = get_post( $comment_post_id );

	if ( ! $post ) {
		wp_die( -1 );
	}

	if ( ! current_user_can( 'edit_post', $comment_post_id ) ) {
		wp_die( -1 );
	}

	if ( empty( $post->post_status ) ) {
		wp_die( 1 );
	} elseif ( in_array( $post->post_status, array( 'draft', 'pending', 'trash' ), true ) ) {
		wp_die( __( 'You cannot reply to a comment on a draft post.' ) );
	}

	$user = wp_get_current_user();

	if ( $user->exists() ) {
		$comment_author       = wp_slash( $user->display_name );
		$comment_author_email = wp_slash( $user->user_email );
		$comment_author_url   = wp_slash( $user->user_url );
		$user_id              = $user->ID;

		if ( current_user_can( 'unfiltered_html' ) ) {
			if ( ! isset( $_POST['_wp_unfiltered_html_comment'] ) ) {
				$_POST['_wp_unfiltered_html_comment'] = '';
			}

			if ( wp_create_nonce( 'unfiltered-html-comment' ) !== $_POST['_wp_unfiltered_html_comment'] ) {
				kses_remove_filters(); // Start with a clean slate.
				kses_init_filters();   // Set up the filters.
				remove_filter( 'pre_comment_content', 'wp_filter_post_kses' );
				add_filter( 'pre_comment_content', 'wp_filter_kses' );
			}
		}
	} else {
		wp_die( __( 'Sorry, you must be logged in to reply to a comment.' ) );
	}

	$comment_content = trim( $_POST['content'] );

	if ( '' === $comment_content ) {
		wp_die( __( 'Please type your comment text.' ) );
	}

	$comment_type = isset( $_POST['comment_type'] ) ? trim( $_POST['comment_type'] ) : 'comment';

	$comment_parent = 0;

	if ( isset( $_POST['comment_ID'] ) ) {
		$comment_parent = absint( $_POST['comment_ID'] );
	}

	$comment_auto_approved = false;

	$commentdata = array(
		'comment_post_ID' => $comment_post_id,
	);

	$commentdata += compact(
		'comment_author',
		'comment_author_email',
		'comment_author_url',
		'comment_content',
		'comment_type',
		'comment_parent',
		'user_id'
	);

	// Automatically approve parent comment.
	if ( ! empty( $_POST['approve_parent'] ) ) {
		$parent = get_comment( $comment_parent );

		if ( $parent && '0' === $parent->comment_approved && (int) $parent->comment_post_ID === $comment_post_id ) {
			if ( ! current_user_can( 'edit_comment', $parent->comment_ID ) ) {
				wp_die( -1 );
			}

			if ( wp_set_comment_status( $parent, 'approve' ) ) {
				$comment_auto_approved = true;
			}
		}
	}

	$comment_id = wp_new_comment( $commentdata );

	if ( is_wp_error( $comment_id ) ) {
		wp_die( $comment_id->get_error_message() );
	}

	$comment = get_comment( $comment_id );

	if ( ! $comment ) {
		wp_die( 1 );
	}

	$position = ( isset( $_POST['position'] ) && (int) $_POST['position'] ) ? (int) $_POST['position'] : '-1';

	ob_start();
	if ( isset( $_REQUEST['mode'] ) && 'dashboard' === $_REQUEST['mode'] ) {
		require_once ABSPATH . 'wp-admin/includes/dashboard.php';
		_wp_dashboard_recent_comments_row( $comment );
	} else {
		if ( isset( $_REQUEST['mode'] ) && 'single' === $_REQUEST['mode'] ) {
			$wp_list_table = _get_list_table( 'WP_Post_Comments_List_Table', array( 'screen' => 'edit-comments' ) );
		} else {
			$wp_list_table = _get_list_table( 'WP_Comments_List_Table', array( 'screen' => 'edit-comments' ) );
		}
		$wp_list_table->single_row( $comment );
	}
	$comment_list_item = ob_get_clean();

	$response = array(
		'what'     => 'comment',
		'id'       => $comment->comment_ID,
		'data'     => $comment_list_item,
		'position' => $position,
	);

	$counts                   = wp_count_comments();
	$response['supplemental'] = array(
		'in_moderation'        => $counts->moderated,
		'i18n_comments_text'   => sprintf(
			/* translators: %s: Number of comments. */
			_n( '%s Comment', '%s Comments', $counts->approved ),
			number_format_i18n( $counts->approved )
		),
		'i18n_moderation_text' => sprintf(
			/* translators: %s: Number of comments. */
			_n( '%s Comment in moderation', '%s Comments in moderation', $counts->moderated ),
			number_format_i18n( $counts->moderated )
		),
	);

	if ( $comment_auto_approved ) {
		$response['supplemental']['parent_approved'] = $parent->comment_ID;
		$response['supplemental']['parent_post_id']  = $parent->comment_post_ID;
	}

	$x = new WP_Ajax_Response();
	$x->add( $response );
	$x->send();
}

/**
 * Handles editing a comment via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_edit_comment() {
	check_ajax_referer( 'replyto-comment', '_ajax_nonce-replyto-comment' );

	$comment_id = (int) $_POST['comment_ID'];

	if ( ! current_user_can( 'edit_comment', $comment_id ) ) {
		wp_die( -1 );
	}

	if ( '' === $_POST['content'] ) {
		wp_die( __( 'Please type your comment text.' ) );
	}

	if ( isset( $_POST['status'] ) ) {
		$_POST['comment_status'] = $_POST['status'];
	}

	$updated = edit_comment();
	if ( is_wp_error( $updated ) ) {
		wp_die( $updated->get_error_message() );
	}

	$position = ( isset( $_POST['position'] ) && (int) $_POST['position'] ) ? (int) $_POST['position'] : '-1';
	/*
	 * Checkbox is used to differentiate between the Edit Comments screen (1)
	 * and the Comments section on the Edit Post screen (0).
	 */
	$checkbox      = ( isset( $_POST['checkbox'] ) && '1' === $_POST['checkbox'] ) ? 1 : 0;
	$wp_list_table = _get_list_table( $checkbox ? 'WP_Comments_List_Table' : 'WP_Post_Comments_List_Table', array( 'screen' => 'edit-comments' ) );

	$comment = get_comment( $comment_id );

	if ( empty( $comment->comment_ID ) ) {
		wp_die( -1 );
	}

	ob_start();
	$wp_list_table->single_row( $comment );
	$comment_list_item = ob_get_clean();

	$x = new WP_Ajax_Response();

	$x->add(
		array(
			'what'     => 'edit_comment',
			'id'       => $comment->comment_ID,
			'data'     => $comment_list_item,
			'position' => $position,
		)
	);

	$x->send();
}

/**
 * Handles adding a menu item via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_add_menu_item() {
	check_ajax_referer( 'add-menu_item', 'menu-settings-column-nonce' );

	if ( ! current_user_can( 'edit_theme_options' ) ) {
		wp_die( -1 );
	}

	require_once ABSPATH . 'wp-admin/includes/nav-menu.php';

	/*
	 * For performance reasons, we omit some object properties from the checklist.
	 * The following is a hacky way to restore them when adding non-custom items.
	 */
	$menu_items_data = array();

	foreach ( (array) $_POST['menu-item'] as $menu_item_data ) {
		if (
			! empty( $menu_item_data['menu-item-type'] ) &&
			'custom' !== $menu_item_data['menu-item-type'] &&
			! empty( $menu_item_data['menu-item-object-id'] )
		) {
			switch ( $menu_item_data['menu-item-type'] ) {
				case 'post_type':
					$_object = get_post( $menu_item_data['menu-item-object-id'] );
					break;

				case 'post_type_archive':
					$_object = get_post_type_object( $menu_item_data['menu-item-object'] );
					break;

				case 'taxonomy':
					$_object = get_term( $menu_item_data['menu-item-object-id'], $menu_item_data['menu-item-object'] );
					break;
			}

			$_menu_items = array_map( 'wp_setup_nav_menu_item', array( $_object ) );
			$_menu_item  = reset( $_menu_items );

			// Restore the missing menu item properties.
			$menu_item_data['menu-item-description'] = $_menu_item->description;
		}

		$menu_items_data[] = $menu_item_data;
	}

	$item_ids = wp_save_nav_menu_items( 0, $menu_items_data );
	if ( is_wp_error( $item_ids ) ) {
		wp_die( 0 );
	}

	$menu_items = array();

	foreach ( (array) $item_ids as $menu_item_id ) {
		$menu_obj = get_post( $menu_item_id );

		if ( ! empty( $menu_obj->ID ) ) {
			$menu_obj        = wp_setup_nav_menu_item( $menu_obj );
			$menu_obj->title = empty( $menu_obj->title ) ? __( 'Menu Item' ) : $menu_obj->title;
			$menu_obj->label = $menu_obj->title; // Don't show "(pending)" in ajax-added items.
			$menu_items[]    = $menu_obj;
		}
	}

	/** This filter is documented in wp-admin/includes/nav-menu.php */
	$walker_class_name = apply_filters( 'wp_edit_nav_menu_walker', 'Walker_Nav_Menu_Edit', $_POST['menu'] );

	if ( ! class_exists( $walker_class_name ) ) {
		wp_die( 0 );
	}

	if ( ! empty( $menu_items ) ) {
		$args = array(
			'after'       => '',
			'before'      => '',
			'link_after'  => '',
			'link_before' => '',
			'walker'      => new $walker_class_name(),
		);

		echo walk_nav_menu_tree( $menu_items, 0, (object) $args );
	}

	wp_die();
}

/**
 * Handles adding meta via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_add_meta() {
	check_ajax_referer( 'add-meta', '_ajax_nonce-add-meta' );
	$c    = 0;
	$pid  = (int) $_POST['post_id'];
	$post = get_post( $pid );

	if ( isset( $_POST['metakeyselect'] ) || isset( $_POST['metakeyinput'] ) ) {
		if ( ! current_user_can( 'edit_post', $pid ) ) {
			wp_die( -1 );
		}

		if ( isset( $_POST['metakeyselect'] ) && '#NONE#' === $_POST['metakeyselect'] && empty( $_POST['metakeyinput'] ) ) {
			wp_die( 1 );
		}

		// If the post is an autodraft, save the post as a draft and then attempt to save the meta.
		if ( 'auto-draft' === $post->post_status ) {
			$post_data                = array();
			$post_data['action']      = 'draft'; // Warning fix.
			$post_data['post_ID']     = $pid;
			$post_data['post_type']   = $post->post_type;
			$post_data['post_status'] = 'draft';
			$now                      = time();

			$post_data['post_title'] = sprintf(
				/* translators: 1: Post creation date, 2: Post creation time. */
				__( 'Draft created on %1$s at %2$s' ),
				gmdate( __( 'F j, Y' ), $now ),
				gmdate( __( 'g:i a' ), $now )
			);

			$pid = edit_post( $post_data );

			if ( $pid ) {
				if ( is_wp_error( $pid ) ) {
					$x = new WP_Ajax_Response(
						array(
							'what' => 'meta',
							'data' => $pid,
						)
					);
					$x->send();
				}

				$mid = add_meta( $pid );
				if ( ! $mid ) {
					wp_die( __( 'Please provide a custom field value.' ) );
				}
			} else {
				wp_die( 0 );
			}
		} else {
			$mid = add_meta( $pid );
			if ( ! $mid ) {
				wp_die( __( 'Please provide a custom field value.' ) );
			}
		}

		$meta = get_metadata_by_mid( 'post', $mid );
		$pid  = (int) $meta->post_id;
		$meta = get_object_vars( $meta );

		$x = new WP_Ajax_Response(
			array(
				'what'         => 'meta',
				'id'           => $mid,
				'data'         => _list_meta_row( $meta, $c ),
				'position'     => 1,
				'supplemental' => array( 'postid' => $pid ),
			)
		);
	} else { // Update?
		$mid   = (int) key( $_POST['meta'] );
		$key   = wp_unslash( $_POST['meta'][ $mid ]['key'] );
		$value = wp_unslash( $_POST['meta'][ $mid ]['value'] );

		if ( '' === trim( $key ) ) {
			wp_die( __( 'Please provide a custom field name.' ) );
		}

		$meta = get_metadata_by_mid( 'post', $mid );

		if ( ! $meta ) {
			wp_die( 0 ); // If meta doesn't exist.
		}

		if (
			is_protected_meta( $meta->meta_key, 'post' ) || is_protected_meta( $key, 'post' ) ||
			! current_user_can( 'edit_post_meta', $meta->post_id, $meta->meta_key ) ||
			! current_user_can( 'edit_post_meta', $meta->post_id, $key )
		) {
			wp_die( -1 );
		}

		if ( $meta->meta_value !== $value || $meta->meta_key !== $key ) {
			$u = update_metadata_by_mid( 'post', $mid, $value, $key );
			if ( ! $u ) {
				wp_die( 0 ); // We know meta exists; we also know it's unchanged (or DB error, in which case there are bigger problems).
			}
		}

		$x = new WP_Ajax_Response(
			array(
				'what'         => 'meta',
				'id'           => $mid,
				'old_id'       => $mid,
				'data'         => _list_meta_row(
					array(
						'meta_key'   => $key,
						'meta_value' => $value,
						'meta_id'    => $mid,
					),
					$c
				),
				'position'     => 0,
				'supplemental' => array( 'postid' => $meta->post_id ),
			)
		);
	}
	$x->send();
}

/**
 * Handles adding a user via AJAX.
 *
 * @since 3.1.0
 *
 * @param string $action Action to perform.
 */
function wp_ajax_add_user( $action ) {
	if ( empty( $action ) ) {
		$action = 'add-user';
	}

	check_ajax_referer( $action );

	if ( ! current_user_can( 'create_users' ) ) {
		wp_die( -1 );
	}

	$user_id = edit_user();

	if ( ! $user_id ) {
		wp_die( 0 );
	} elseif ( is_wp_error( $user_id ) ) {
		$x = new WP_Ajax_Response(
			array(
				'what' => 'user',
				'id'   => $user_id,
			)
		);
		$x->send();
	}

	$user_object   = get_userdata( $user_id );
	$wp_list_table = _get_list_table( 'WP_Users_List_Table' );

	$role = current( $user_object->roles );

	$x = new WP_Ajax_Response(
		array(
			'what'         => 'user',
			'id'           => $user_id,
			'data'         => $wp_list_table->single_row( $user_object, '', $role ),
			'supplemental' => array(
				'show-link' => sprintf(
					/* translators: %s: The new user. */
					__( 'User %s added' ),
					'<a href="#user-' . $user_id . '">' . $user_object->user_login . '</a>'
				),
				'role'      => $role,
			),
		)
	);
	$x->send();
}

/**
 * Handles closed post boxes via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_closed_postboxes() {
	check_ajax_referer( 'closedpostboxes', 'closedpostboxesnonce' );
	$closed = isset( $_POST['closed'] ) ? explode( ',', $_POST['closed'] ) : array();
	$closed = array_filter( $closed );

	$hidden = isset( $_POST['hidden'] ) ? explode( ',', $_POST['hidden'] ) : array();
	$hidden = array_filter( $hidden );

	$page = isset( $_POST['page'] ) ? $_POST['page'] : '';

	if ( sanitize_key( $page ) !== $page ) {
		wp_die( 0 );
	}

	$user = wp_get_current_user();
	if ( ! $user ) {
		wp_die( -1 );
	}

	if ( is_array( $closed ) ) {
		update_user_meta( $user->ID, "closedpostboxes_$page", $closed );
	}

	if ( is_array( $hidden ) ) {
		// Postboxes that are always shown.
		$hidden = array_diff( $hidden, array( 'submitdiv', 'linksubmitdiv', 'manage-menu', 'create-menu' ) );
		update_user_meta( $user->ID, "metaboxhidden_$page", $hidden );
	}

	wp_die( 1 );
}

/**
 * Handles hidden columns via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_hidden_columns() {
	check_ajax_referer( 'screen-options-nonce', 'screenoptionnonce' );
	$page = isset( $_POST['page'] ) ? $_POST['page'] : '';

	if ( sanitize_key( $page ) !== $page ) {
		wp_die( 0 );
	}

	$user = wp_get_current_user();
	if ( ! $user ) {
		wp_die( -1 );
	}

	$hidden = ! empty( $_POST['hidden'] ) ? explode( ',', $_POST['hidden'] ) : array();
	update_user_meta( $user->ID, "manage{$page}columnshidden", $hidden );

	wp_die( 1 );
}

/**
 * Handles updating whether to display the welcome panel via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_update_welcome_panel() {
	check_ajax_referer( 'welcome-panel-nonce', 'welcomepanelnonce' );

	if ( ! current_user_can( 'edit_theme_options' ) ) {
		wp_die( -1 );
	}

	update_user_meta( get_current_user_id(), 'show_welcome_panel', empty( $_POST['visible'] ) ? 0 : 1 );

	wp_die( 1 );
}

/**
 * Handles for retrieving menu meta boxes via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_menu_get_metabox() {
	if ( ! current_user_can( 'edit_theme_options' ) ) {
		wp_die( -1 );
	}

	require_once ABSPATH . 'wp-admin/includes/nav-menu.php';

	if ( isset( $_POST['item-type'] ) && 'post_type' === $_POST['item-type'] ) {
		$type     = 'posttype';
		$callback = 'wp_nav_menu_item_post_type_meta_box';
		$items    = (array) get_post_types( array( 'show_in_nav_menus' => true ), 'object' );
	} elseif ( isset( $_POST['item-type'] ) && 'taxonomy' === $_POST['item-type'] ) {
		$type     = 'taxonomy';
		$callback = 'wp_nav_menu_item_taxonomy_meta_box';
		$items    = (array) get_taxonomies( array( 'show_ui' => true ), 'object' );
	}

	if ( ! empty( $_POST['item-object'] ) && isset( $items[ $_POST['item-object'] ] ) ) {
		$menus_meta_box_object = $items[ $_POST['item-object'] ];

		/** This filter is documented in wp-admin/includes/nav-menu.php */
		$item = apply_filters( 'nav_menu_meta_box_object', $menus_meta_box_object );

		$box_args = array(
			'id'       => 'add-' . $item->name,
			'title'    => $item->labels->name,
			'callback' => $callback,
			'args'     => $item,
		);

		ob_start();
		$callback( null, $box_args );

		$markup = ob_get_clean();

		echo wp_json_encode(
			array(
				'replace-id' => $type . '-' . $item->name,
				'markup'     => $markup,
			)
		);
	}

	wp_die();
}

/**
 * Handles internal linking via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_wp_link_ajax() {
	check_ajax_referer( 'internal-linking', '_ajax_linking_nonce' );

	$args = array();

	if ( isset( $_POST['search'] ) ) {
		$args['s'] = wp_unslash( $_POST['search'] );
	}

	if ( isset( $_POST['term'] ) ) {
		$args['s'] = wp_unslash( $_POST['term'] );
	}

	$args['pagenum'] = ! empty( $_POST['page'] ) ? absint( $_POST['page'] ) : 1;

	if ( ! class_exists( '_WP_Editors', false ) ) {
		require ABSPATH . WPINC . '/class-wp-editor.php';
	}

	$results = _WP_Editors::wp_link_query( $args );

	if ( ! isset( $results ) ) {
		wp_die( 0 );
	}

	echo wp_json_encode( $results );
	echo "\n";

	wp_die();
}

/**
 * Handles saving menu locations via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_menu_locations_save() {
	if ( ! current_user_can( 'edit_theme_options' ) ) {
		wp_die( -1 );
	}

	check_ajax_referer( 'add-menu_item', 'menu-settings-column-nonce' );

	if ( ! isset( $_POST['menu-locations'] ) ) {
		wp_die( 0 );
	}

	set_theme_mod( 'nav_menu_locations', array_map( 'absint', $_POST['menu-locations'] ) );
	wp_die( 1 );
}

/**
 * Handles saving the meta box order via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_meta_box_order() {
	check_ajax_referer( 'meta-box-order' );
	$order        = isset( $_POST['order'] ) ? (array) $_POST['order'] : false;
	$page_columns = isset( $_POST['page_columns'] ) ? $_POST['page_columns'] : 'auto';

	if ( 'auto' !== $page_columns ) {
		$page_columns = (int) $page_columns;
	}

	$page = isset( $_POST['page'] ) ? $_POST['page'] : '';

	if ( sanitize_key( $page ) !== $page ) {
		wp_die( 0 );
	}

	$user = wp_get_current_user();
	if ( ! $user ) {
		wp_die( -1 );
	}

	if ( $order ) {
		update_user_meta( $user->ID, "meta-box-order_$page", $order );
	}

	if ( $page_columns ) {
		update_user_meta( $user->ID, "screen_layout_$page", $page_columns );
	}

	wp_send_json_success();
}

/**
 * Handles menu quick searching via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_menu_quick_search() {
	if ( ! current_user_can( 'edit_theme_options' ) ) {
		wp_die( -1 );
	}

	require_once ABSPATH . 'wp-admin/includes/nav-menu.php';

	_wp_ajax_menu_quick_search( $_POST );

	wp_die();
}

/**
 * Handles retrieving a permalink via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_get_permalink() {
	check_ajax_referer( 'getpermalink', 'getpermalinknonce' );
	$post_id = isset( $_POST['post_id'] ) ? (int) $_POST['post_id'] : 0;
	wp_die( get_preview_post_link( $post_id ) );
}

/**
 * Handles retrieving a sample permalink via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_sample_permalink() {
	check_ajax_referer( 'samplepermalink', 'samplepermalinknonce' );
	$post_id = isset( $_POST['post_id'] ) ? (int) $_POST['post_id'] : 0;
	$title   = isset( $_POST['new_title'] ) ? $_POST['new_title'] : '';
	$slug    = isset( $_POST['new_slug'] ) ? $_POST['new_slug'] : null;
	wp_die( get_sample_permalink_html( $post_id, $title, $slug ) );
}

/**
 * Handles Quick Edit saving a post from a list table via AJAX.
 *
 * @since 3.1.0
 *
 * @global string $mode List table view mode.
 */
function wp_ajax_inline_save() {
	global $mode;

	check_ajax_referer( 'inlineeditnonce', '_inline_edit' );

	if ( ! isset( $_POST['post_ID'] ) || ! (int) $_POST['post_ID'] ) {
		wp_die();
	}

	$post_id = (int) $_POST['post_ID'];

	if ( 'page' === $_POST['post_type'] ) {
		if ( ! current_user_can( 'edit_page', $post_id ) ) {
			wp_die( __( 'Sorry, you are not allowed to edit this page.' ) );
		}
	} else {
		if ( ! current_user_can( 'edit_post', $post_id ) ) {
			wp_die( __( 'Sorry, you are not allowed to edit this post.' ) );
		}
	}

	$last = wp_check_post_lock( $post_id );
	if ( $last ) {
		$last_user      = get_userdata( $last );
		$last_user_name = $last_user ? $last_user->display_name : __( 'Someone' );

		/* translators: %s: User's display name. */
		$msg_template = __( 'Saving is disabled: %s is currently editing this post.' );

		if ( 'page' === $_POST['post_type'] ) {
			/* translators: %s: User's display name. */
			$msg_template = __( 'Saving is disabled: %s is currently editing this page.' );
		}

		printf( $msg_template, esc_html( $last_user_name ) );
		wp_die();
	}

	$data = &$_POST;

	$post = get_post( $post_id, ARRAY_A );

	// Since it's coming from the database.
	$post = wp_slash( $post );

	$data['content'] = $post['post_content'];
	$data['excerpt'] = $post['post_excerpt'];

	// Rename.
	$data['user_ID'] = get_current_user_id();

	if ( isset( $data['post_parent'] ) ) {
		$data['parent_id'] = $data['post_parent'];
	}

	// Status.
	if ( isset( $data['keep_private'] ) && 'private' === $data['keep_private'] ) {
		$data['visibility']  = 'private';
		$data['post_status'] = 'private';
	} elseif ( isset( $data['_status'] ) ) {
		$data['post_status'] = $data['_status'];
	}

	if ( empty( $data['comment_status'] ) ) {
		$data['comment_status'] = 'closed';
	}

	if ( empty( $data['ping_status'] ) ) {
		$data['ping_status'] = 'closed';
	}

	// Exclude terms from taxonomies that are not supposed to appear in Quick Edit.
	if ( ! empty( $data['tax_input'] ) ) {
		foreach ( $data['tax_input'] as $taxonomy => $terms ) {
			$tax_object = get_taxonomy( $taxonomy );
			/** This filter is documented in wp-admin/includes/class-wp-posts-list-table.php */
			if ( ! apply_filters( 'quick_edit_show_taxonomy', $tax_object->show_in_quick_edit, $taxonomy, $post['post_type'] ) ) {
				unset( $data['tax_input'][ $taxonomy ] );
			}
		}
	}

	// Hack: wp_unique_post_slug() doesn't work for drafts, so we will fake that our post is published.
	if ( ! empty( $data['post_name'] ) && in_array( $post['post_status'], array( 'draft', 'pending' ), true ) ) {
		$post['post_status'] = 'publish';
		$data['post_name']   = wp_unique_post_slug( $data['post_name'], $post['ID'], $post['post_status'], $post['post_type'], $post['post_parent'] );
	}

	// Update the post.
	edit_post();

	$wp_list_table = _get_list_table( 'WP_Posts_List_Table', array( 'screen' => $_POST['screen'] ) );

	$mode = 'excerpt' === $_POST['post_view'] ? 'excerpt' : 'list';

	$level = 0;
	if ( is_post_type_hierarchical( $wp_list_table->screen->post_type ) ) {
		$request_post = array( get_post( $_POST['post_ID'] ) );
		$parent       = $request_post[0]->post_parent;

		while ( $parent > 0 ) {
			$parent_post = get_post( $parent );
			$parent      = $parent_post->post_parent;
			++$level;
		}
	}

	$wp_list_table->display_rows( array( get_post( $_POST['post_ID'] ) ), $level );

	wp_die();
}

/**
 * Handles Quick Edit saving for a term via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_inline_save_tax() {
	check_ajax_referer( 'taxinlineeditnonce', '_inline_edit' );

	$taxonomy        = sanitize_key( $_POST['taxonomy'] );
	$taxonomy_object = get_taxonomy( $taxonomy );

	if ( ! $taxonomy_object ) {
		wp_die( 0 );
	}

	if ( ! isset( $_POST['tax_ID'] ) || ! (int) $_POST['tax_ID'] ) {
		wp_die( -1 );
	}

	$id = (int) $_POST['tax_ID'];

	if ( ! current_user_can( 'edit_term', $id ) ) {
		wp_die( -1 );
	}

	$wp_list_table = _get_list_table( 'WP_Terms_List_Table', array( 'screen' => 'edit-' . $taxonomy ) );

	$tag                  = get_term( $id, $taxonomy );
	$_POST['description'] = $tag->description;

	$updated = wp_update_term( $id, $taxonomy, $_POST );

	if ( $updated && ! is_wp_error( $updated ) ) {
		$tag = get_term( $updated['term_id'], $taxonomy );
		if ( ! $tag || is_wp_error( $tag ) ) {
			if ( is_wp_error( $tag ) && $tag->get_error_message() ) {
				wp_die( $tag->get_error_message() );
			}
			wp_die( __( 'Item not updated.' ) );
		}
	} else {
		if ( is_wp_error( $updated ) && $updated->get_error_message() ) {
			wp_die( $updated->get_error_message() );
		}
		wp_die( __( 'Item not updated.' ) );
	}

	$level  = 0;
	$parent = $tag->parent;

	while ( $parent > 0 ) {
		$parent_tag = get_term( $parent, $taxonomy );
		$parent     = $parent_tag->parent;
		++$level;
	}

	$wp_list_table->single_row( $tag, $level );
	wp_die();
}

/**
 * Handles querying posts for the Find Posts modal via AJAX.
 *
 * @see window.findPosts
 *
 * @since 3.1.0
 */
function wp_ajax_find_posts() {
	check_ajax_referer( 'find-posts' );

	$post_types = get_post_types( array( 'public' => true ), 'objects' );
	unset( $post_types['attachment'] );

	$args = array(
		'post_type'      => array_keys( $post_types ),
		'post_status'    => 'any',
		'posts_per_page' => 50,
	);

	$search = wp_unslash( $_POST['ps'] );

	if ( '' !== $search ) {
		$args['s'] = $search;
	}

	$posts = get_posts( $args );

	if ( ! $posts ) {
		wp_send_json_error( __( 'No items found.' ) );
	}

	$html = '<table class="widefat"><thead><tr><th class="found-radio"><br /></th><th>' . __( 'Title' ) . '</th><th class="no-break">' . __( 'Type' ) . '</th><th class="no-break">' . __( 'Date' ) . '</th><th class="no-break">' . __( 'Status' ) . '</th></tr></thead><tbody>';
	$alt  = '';
	foreach ( $posts as $post ) {
		$title = trim( $post->post_title ) ? $post->post_title : __( '(no title)' );
		$alt   = ( 'alternate' === $alt ) ? '' : 'alternate';

		switch ( $post->post_status ) {
			case 'publish':
			case 'private':
				$stat = __( 'Published' );
				break;
			case 'future':
				$stat = __( 'Scheduled' );
				break;
			case 'pending':
				$stat = __( 'Pending Review' );
				break;
			case 'draft':
				$stat = __( 'Draft' );
				break;
		}

		if ( '0000-00-00 00:00:00' === $post->post_date ) {
			$time = '';
		} else {
			/* translators: Date format in table columns, see https://www.php.net/manual/datetime.format.php */
			$time = mysql2date( __( 'Y/m/d' ), $post->post_date );
		}

		$html .= '<tr class="' . trim( 'found-posts ' . $alt ) . '"><td class="found-radio"><input type="radio" id="found-' . $post->ID . '" name="found_post_id" value="' . esc_attr( $post->ID ) . '"></td>';
		$html .= '<td><label for="found-' . $post->ID . '">' . esc_html( $title ) . '</label></td><td class="no-break">' . esc_html( $post_types[ $post->post_type ]->labels->singular_name ) . '</td><td class="no-break">' . esc_html( $time ) . '</td><td class="no-break">' . esc_html( $stat ) . ' </td></tr>' . "\n\n";
	}

	$html .= '</tbody></table>';

	wp_send_json_success( $html );
}

/**
 * Handles saving the widgets order via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_widgets_order() {
	check_ajax_referer( 'save-sidebar-widgets', 'savewidgets' );

	if ( ! current_user_can( 'edit_theme_options' ) ) {
		wp_die( -1 );
	}

	unset( $_POST['savewidgets'], $_POST['action'] );

	// Save widgets order for all sidebars.
	if ( is_array( $_POST['sidebars'] ) ) {
		$sidebars = array();

		foreach ( wp_unslash( $_POST['sidebars'] ) as $key => $val ) {
			$sb = array();

			if ( ! empty( $val ) ) {
				$val = explode( ',', $val );

				foreach ( $val as $k => $v ) {
					if ( ! str_contains( $v, 'widget-' ) ) {
						continue;
					}

					$sb[ $k ] = substr( $v, strpos( $v, '_' ) + 1 );
				}
			}
			$sidebars[ $key ] = $sb;
		}

		wp_set_sidebars_widgets( $sidebars );
		wp_die( 1 );
	}

	wp_die( -1 );
}

/**
 * Handles saving a widget via AJAX.
 *
 * @since 3.1.0
 *
 * @global array $wp_registered_widgets
 * @global array $wp_registered_widget_controls
 * @global array $wp_registered_widget_updates
 */
function wp_ajax_save_widget() {
	global $wp_registered_widgets, $wp_registered_widget_controls, $wp_registered_widget_updates;

	check_ajax_referer( 'save-sidebar-widgets', 'savewidgets' );

	if ( ! current_user_can( 'edit_theme_options' ) || ! isset( $_POST['id_base'] ) ) {
		wp_die( -1 );
	}

	unset( $_POST['savewidgets'], $_POST['action'] );

	/**
	 * Fires early when editing the widgets displayed in sidebars.
	 *
	 * @since 2.8.0
	 */
	do_action( 'load-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores

	/**
	 * Fires early when editing the widgets displayed in sidebars.
	 *
	 * @since 2.8.0
	 */
	do_action( 'widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores

	/** This action is documented in wp-admin/widgets.php */
	do_action( 'sidebar_admin_setup' );

	$id_base      = wp_unslash( $_POST['id_base'] );
	$widget_id    = wp_unslash( $_POST['widget-id'] );
	$sidebar_id   = $_POST['sidebar'];
	$multi_number = ! empty( $_POST['multi_number'] ) ? (int) $_POST['multi_number'] : 0;
	$settings     = isset( $_POST[ 'widget-' . $id_base ] ) && is_array( $_POST[ 'widget-' . $id_base ] ) ? $_POST[ 'widget-' . $id_base ] : false;
	$error        = '<p>' . __( 'An error has occurred. Please reload the page and try again.' ) . '</p>';

	$sidebars = wp_get_sidebars_widgets();
	$sidebar  = isset( $sidebars[ $sidebar_id ] ) ? $sidebars[ $sidebar_id ] : array();

	// Delete.
	if ( isset( $_POST['delete_widget'] ) && $_POST['delete_widget'] ) {

		if ( ! isset( $wp_registered_widgets[ $widget_id ] ) ) {
			wp_die( $error );
		}

		$sidebar = array_diff( $sidebar, array( $widget_id ) );
		$_POST   = array(
			'sidebar'            => $sidebar_id,
			'widget-' . $id_base => array(),
			'the-widget-id'      => $widget_id,
			'delete_widget'      => '1',
		);

		/** This action is documented in wp-admin/widgets.php */
		do_action( 'delete_widget', $widget_id, $sidebar_id, $id_base );

	} elseif ( $settings && preg_match( '/__i__|%i%/', key( $settings ) ) ) {
		if ( ! $multi_number ) {
			wp_die( $error );
		}

		$_POST[ 'widget-' . $id_base ] = array( $multi_number => reset( $settings ) );
		$widget_id                     = $id_base . '-' . $multi_number;
		$sidebar[]                     = $widget_id;
	}
	$_POST['widget-id'] = $sidebar;

	foreach ( (array) $wp_registered_widget_updates as $name => $control ) {

		if ( $name === $id_base ) {
			if ( ! is_callable( $control['callback'] ) ) {
				continue;
			}

			ob_start();
				call_user_func_array( $control['callback'], $control['params'] );
			ob_end_clean();
			break;
		}
	}

	if ( isset( $_POST['delete_widget'] ) && $_POST['delete_widget'] ) {
		$sidebars[ $sidebar_id ] = $sidebar;
		wp_set_sidebars_widgets( $sidebars );
		echo "deleted:$widget_id";
		wp_die();
	}

	if ( ! empty( $_POST['add_new'] ) ) {
		wp_die();
	}

	$form = $wp_registered_widget_controls[ $widget_id ];
	if ( $form ) {
		call_user_func_array( $form['callback'], $form['params'] );
	}

	wp_die();
}

/**
 * Handles updating a widget via AJAX.
 *
 * @since 3.9.0
 *
 * @global WP_Customize_Manager $wp_customize
 */
function wp_ajax_update_widget() {
	global $wp_customize;
	$wp_customize->widgets->wp_ajax_update_widget();
}

/**
 * Handles removing inactive widgets via AJAX.
 *
 * @since 4.4.0
 */
function wp_ajax_delete_inactive_widgets() {
	check_ajax_referer( 'remove-inactive-widgets', 'removeinactivewidgets' );

	if ( ! current_user_can( 'edit_theme_options' ) ) {
		wp_die( -1 );
	}

	unset( $_POST['removeinactivewidgets'], $_POST['action'] );
	/** This action is documented in wp-admin/includes/ajax-actions.php */
	do_action( 'load-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
	/** This action is documented in wp-admin/includes/ajax-actions.php */
	do_action( 'widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
	/** This action is documented in wp-admin/widgets.php */
	do_action( 'sidebar_admin_setup' );

	$sidebars_widgets = wp_get_sidebars_widgets();

	foreach ( $sidebars_widgets['wp_inactive_widgets'] as $key => $widget_id ) {
		$pieces       = explode( '-', $widget_id );
		$multi_number = array_pop( $pieces );
		$id_base      = implode( '-', $pieces );
		$widget       = get_option( 'widget_' . $id_base );
		unset( $widget[ $multi_number ] );
		update_option( 'widget_' . $id_base, $widget );
		unset( $sidebars_widgets['wp_inactive_widgets'][ $key ] );
	}

	wp_set_sidebars_widgets( $sidebars_widgets );

	wp_die();
}

/**
 * Handles creating missing image sub-sizes for just uploaded images via AJAX.
 *
 * @since 5.3.0
 */
function wp_ajax_media_create_image_subsizes() {
	check_ajax_referer( 'media-form' );

	if ( ! current_user_can( 'upload_files' ) ) {
		wp_send_json_error( array( 'message' => __( 'Sorry, you are not allowed to upload files.' ) ) );
	}

	if ( empty( $_POST['attachment_id'] ) ) {
		wp_send_json_error( array( 'message' => __( 'Upload failed. Please reload and try again.' ) ) );
	}

	$attachment_id = (int) $_POST['attachment_id'];

	if ( ! empty( $_POST['_wp_upload_failed_cleanup'] ) ) {
		// Upload failed. Cleanup.
		if ( wp_attachment_is_image( $attachment_id ) && current_user_can( 'delete_post', $attachment_id ) ) {
			$attachment = get_post( $attachment_id );

			// Created at most 10 min ago.
			if ( $attachment && ( time() - strtotime( $attachment->post_date_gmt ) < 600 ) ) {
				wp_delete_attachment( $attachment_id, true );
				wp_send_json_success();
			}
		}
	}

	/*
	 * Set a custom header with the attachment_id.
	 * Used by the browser/client to resume creating image sub-sizes after a PHP fatal error.
	 */
	if ( ! headers_sent() ) {
		header( 'X-WP-Upload-Attachment-ID: ' . $attachment_id );
	}

	/*
	 * This can still be pretty slow and cause timeout or out of memory errors.
	 * The js that handles the response would need to also handle HTTP 500 errors.
	 */
	wp_update_image_subsizes( $attachment_id );

	if ( ! empty( $_POST['_legacy_support'] ) ) {
		// The old (inline) uploader. Only needs the attachment_id.
		$response = array( 'id' => $attachment_id );
	} else {
		// Media modal and Media Library grid view.
		$response = wp_prepare_attachment_for_js( $attachment_id );

		if ( ! $response ) {
			wp_send_json_error( array( 'message' => __( 'Upload failed.' ) ) );
		}
	}

	// At this point the image has been uploaded successfully.
	wp_send_json_success( $response );
}

/**
 * Handles uploading attachments via AJAX.
 *
 * @since 3.3.0
 */
function wp_ajax_upload_attachment() {
	check_ajax_referer( 'media-form' );
	/*
	 * This function does not use wp_send_json_success() / wp_send_json_error()
	 * as the html4 Plupload handler requires a text/html Content-Type for older IE.
	 * See https://core.trac.wordpress.org/ticket/31037
	 */

	if ( ! current_user_can( 'upload_files' ) ) {
		echo wp_json_encode(
			array(
				'success' => false,
				'data'    => array(
					'message'  => __( 'Sorry, you are not allowed to upload files.' ),
					'filename' => esc_html( $_FILES['async-upload']['name'] ),
				),
			)
		);

		wp_die();
	}

	if ( isset( $_REQUEST['post_id'] ) ) {
		$post_id = $_REQUEST['post_id'];

		if ( ! current_user_can( 'edit_post', $post_id ) ) {
			echo wp_json_encode(
				array(
					'success' => false,
					'data'    => array(
						'message'  => __( 'Sorry, you are not allowed to attach files to this post.' ),
						'filename' => esc_html( $_FILES['async-upload']['name'] ),
					),
				)
			);

			wp_die();
		}
	} else {
		$post_id = null;
	}

	$post_data = ! empty( $_REQUEST['post_data'] ) ? _wp_get_allowed_postdata( _wp_translate_postdata( false, (array) $_REQUEST['post_data'] ) ) : array();

	if ( is_wp_error( $post_data ) ) {
		wp_die( $post_data->get_error_message() );
	}

	// If the context is custom header or background, make sure the uploaded file is an image.
	if ( isset( $post_data['context'] ) && in_array( $post_data['context'], array( 'custom-header', 'custom-background' ), true ) ) {
		$wp_filetype = wp_check_filetype_and_ext( $_FILES['async-upload']['tmp_name'], $_FILES['async-upload']['name'] );

		if ( ! wp_match_mime_types( 'image', $wp_filetype['type'] ) ) {
			echo wp_json_encode(
				array(
					'success' => false,
					'data'    => array(
						'message'  => __( 'The uploaded file is not a valid image. Please try again.' ),
						'filename' => esc_html( $_FILES['async-upload']['name'] ),
					),
				)
			);

			wp_die();
		}
	}

	$attachment_id = media_handle_upload( 'async-upload', $post_id, $post_data );

	if ( is_wp_error( $attachment_id ) ) {
		echo wp_json_encode(
			array(
				'success' => false,
				'data'    => array(
					'message'  => $attachment_id->get_error_message(),
					'filename' => esc_html( $_FILES['async-upload']['name'] ),
				),
			)
		);

		wp_die();
	}

	if ( isset( $post_data['context'] ) && isset( $post_data['theme'] ) ) {
		if ( 'custom-background' === $post_data['context'] ) {
			update_post_meta( $attachment_id, '_wp_attachment_is_custom_background', $post_data['theme'] );
		}

		if ( 'custom-header' === $post_data['context'] ) {
			update_post_meta( $attachment_id, '_wp_attachment_is_custom_header', $post_data['theme'] );
		}
	}

	$attachment = wp_prepare_attachment_for_js( $attachment_id );
	if ( ! $attachment ) {
		wp_die();
	}

	echo wp_json_encode(
		array(
			'success' => true,
			'data'    => $attachment,
		)
	);

	wp_die();
}

/**
 * Handles image editing via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_image_editor() {
	$attachment_id = (int) $_POST['postid'];

	if ( empty( $attachment_id ) || ! current_user_can( 'edit_post', $attachment_id ) ) {
		wp_die( -1 );
	}

	check_ajax_referer( "image_editor-$attachment_id" );
	require_once ABSPATH . 'wp-admin/includes/image-edit.php';

	$msg = false;

	switch ( $_POST['do'] ) {
		case 'save':
			$msg = wp_save_image( $attachment_id );
			if ( ! empty( $msg->error ) ) {
				wp_send_json_error( $msg );
			}

			wp_send_json_success( $msg );
			break;
		case 'scale':
			$msg = wp_save_image( $attachment_id );
			break;
		case 'restore':
			$msg = wp_restore_image( $attachment_id );
			break;
	}

	ob_start();
	wp_image_editor( $attachment_id, $msg );
	$html = ob_get_clean();

	if ( ! empty( $msg->error ) ) {
		wp_send_json_error(
			array(
				'message' => $msg,
				'html'    => $html,
			)
		);
	}

	wp_send_json_success(
		array(
			'message' => $msg,
			'html'    => $html,
		)
	);
}

/**
 * Handles setting the featured image via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_set_post_thumbnail() {
	$json = ! empty( $_REQUEST['json'] ); // New-style request.

	$post_id = (int) $_POST['post_id'];
	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		wp_die( -1 );
	}

	$thumbnail_id = (int) $_POST['thumbnail_id'];

	if ( $json ) {
		check_ajax_referer( "update-post_$post_id" );
	} else {
		check_ajax_referer( "set_post_thumbnail-$post_id" );
	}

	if ( -1 === $thumbnail_id ) {
		if ( delete_post_thumbnail( $post_id ) ) {
			$return = _wp_post_thumbnail_html( null, $post_id );
			$json ? wp_send_json_success( $return ) : wp_die( $return );
		} else {
			wp_die( 0 );
		}
	}

	if ( set_post_thumbnail( $post_id, $thumbnail_id ) ) {
		$return = _wp_post_thumbnail_html( $thumbnail_id, $post_id );
		$json ? wp_send_json_success( $return ) : wp_die( $return );
	}

	wp_die( 0 );
}

/**
 * Handles retrieving HTML for the featured image via AJAX.
 *
 * @since 4.6.0
 */
function wp_ajax_get_post_thumbnail_html() {
	$post_id = (int) $_POST['post_id'];

	check_ajax_referer( "update-post_$post_id" );

	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		wp_die( -1 );
	}

	$thumbnail_id = (int) $_POST['thumbnail_id'];

	// For backward compatibility, -1 refers to no featured image.
	if ( -1 === $thumbnail_id ) {
		$thumbnail_id = null;
	}

	$return = _wp_post_thumbnail_html( $thumbnail_id, $post_id );
	wp_send_json_success( $return );
}

/**
 * Handles setting the featured image for an attachment via AJAX.
 *
 * @since 4.0.0
 *
 * @see set_post_thumbnail()
 */
function wp_ajax_set_attachment_thumbnail() {
	if ( empty( $_POST['urls'] ) || ! is_array( $_POST['urls'] ) ) {
		wp_send_json_error();
	}

	$thumbnail_id = (int) $_POST['thumbnail_id'];
	if ( empty( $thumbnail_id ) ) {
		wp_send_json_error();
	}

	if ( false === check_ajax_referer( 'set-attachment-thumbnail', '_ajax_nonce', false ) ) {
		wp_send_json_error();
	}

	$post_ids = array();
	// For each URL, try to find its corresponding post ID.
	foreach ( $_POST['urls'] as $url ) {
		$post_id = attachment_url_to_postid( $url );
		if ( ! empty( $post_id ) ) {
			$post_ids[] = $post_id;
		}
	}

	if ( empty( $post_ids ) ) {
		wp_send_json_error();
	}

	$success = 0;
	// For each found attachment, set its thumbnail.
	foreach ( $post_ids as $post_id ) {
		if ( ! current_user_can( 'edit_post', $post_id ) ) {
			continue;
		}

		if ( set_post_thumbnail( $post_id, $thumbnail_id ) ) {
			++$success;
		}
	}

	if ( 0 === $success ) {
		wp_send_json_error();
	} else {
		wp_send_json_success();
	}

	wp_send_json_error();
}

/**
 * Handles formatting a date via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_date_format() {
	wp_die( date_i18n( sanitize_option( 'date_format', wp_unslash( $_POST['date'] ) ) ) );
}

/**
 * Handles formatting a time via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_time_format() {
	wp_die( date_i18n( sanitize_option( 'time_format', wp_unslash( $_POST['date'] ) ) ) );
}

/**
 * Handles saving posts from the fullscreen editor via AJAX.
 *
 * @since 3.1.0
 * @deprecated 4.3.0
 */
function wp_ajax_wp_fullscreen_save_post() {
	$post_id = isset( $_POST['post_ID'] ) ? (int) $_POST['post_ID'] : 0;

	$post = null;

	if ( $post_id ) {
		$post = get_post( $post_id );
	}

	check_ajax_referer( 'update-post_' . $post_id, '_wpnonce' );

	$post_id = edit_post();

	if ( is_wp_error( $post_id ) ) {
		wp_send_json_error();
	}

	if ( $post ) {
		$last_date = mysql2date( __( 'F j, Y' ), $post->post_modified );
		$last_time = mysql2date( __( 'g:i a' ), $post->post_modified );
	} else {
		$last_date = date_i18n( __( 'F j, Y' ) );
		$last_time = date_i18n( __( 'g:i a' ) );
	}

	$last_id = get_post_meta( $post_id, '_edit_last', true );
	if ( $last_id ) {
		$last_user = get_userdata( $last_id );
		/* translators: 1: User's display name, 2: Date of last edit, 3: Time of last edit. */
		$last_edited = sprintf( __( 'Last edited by %1$s on %2$s at %3$s' ), esc_html( $last_user->display_name ), $last_date, $last_time );
	} else {
		/* translators: 1: Date of last edit, 2: Time of last edit. */
		$last_edited = sprintf( __( 'Last edited on %1$s at %2$s' ), $last_date, $last_time );
	}

	wp_send_json_success( array( 'last_edited' => $last_edited ) );
}

/**
 * Handles removing a post lock via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_wp_remove_post_lock() {
	if ( empty( $_POST['post_ID'] ) || empty( $_POST['active_post_lock'] ) ) {
		wp_die( 0 );
	}

	$post_id = (int) $_POST['post_ID'];
	$post    = get_post( $post_id );

	if ( ! $post ) {
		wp_die( 0 );
	}

	check_ajax_referer( 'update-post_' . $post_id );

	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		wp_die( -1 );
	}

	$active_lock = array_map( 'absint', explode( ':', $_POST['active_post_lock'] ) );

	if ( get_current_user_id() !== $active_lock[1] ) {
		wp_die( 0 );
	}

	/**
	 * Filters the post lock window duration.
	 *
	 * @since 3.3.0
	 *
	 * @param int $interval The interval in seconds the post lock duration
	 *                      should last, plus 5 seconds. Default 150.
	 */
	$new_lock = ( time() - apply_filters( 'wp_check_post_lock_window', 150 ) + 5 ) . ':' . $active_lock[1];
	update_post_meta( $post_id, '_edit_lock', $new_lock, implode( ':', $active_lock ) );
	wp_die( 1 );
}

/**
 * Handles dismissing a WordPress pointer via AJAX.
 *
 * @since 3.1.0
 */
function wp_ajax_dismiss_wp_pointer() {
	$pointer = $_POST['pointer'];

	if ( sanitize_key( $pointer ) !== $pointer ) {
		wp_die( 0 );
	}

	//  check_ajax_referer( 'dismiss-pointer_' . $pointer );

	$dismissed = array_filter( explode( ',', (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true ) ) );

	if ( in_array( $pointer, $dismissed, true ) ) {
		wp_die( 0 );
	}

	$dismissed[] = $pointer;
	$dismissed   = implode( ',', $dismissed );

	update_user_meta( get_current_user_id(), 'dismissed_wp_pointers', $dismissed );
	wp_die( 1 );
}

/**
 * Handles getting an attachment via AJAX.
 *
 * @since 3.5.0
 */
function wp_ajax_get_attachment() {
	if ( ! isset( $_REQUEST['id'] ) ) {
		wp_send_json_error();
	}

	$id = absint( $_REQUEST['id'] );
	if ( ! $id ) {
		wp_send_json_error();
	}

	$post = get_post( $id );
	if ( ! $post ) {
		wp_send_json_error();
	}

	if ( 'attachment' !== $post->post_type ) {
		wp_send_json_error();
	}

	if ( ! current_user_can( 'upload_files' ) ) {
		wp_send_json_error();
	}

	$attachment = wp_prepare_attachment_for_js( $id );
	if ( ! $attachment ) {
		wp_send_json_error();
	}

	wp_send_json_success( $attachment );
}

/**
 * Handles querying attachments via AJAX.
 *
 * @since 3.5.0
 */
function wp_ajax_query_attachments() {
	if ( ! current_user_can( 'upload_files' ) ) {
		wp_send_json_error();
	}

	$query = isset( $_REQUEST['query'] ) ? (array) $_REQUEST['query'] : array();
	$keys  = array(
		's',
		'order',
		'orderby',
		'posts_per_page',
		'paged',
		'post_mime_type',
		'post_parent',
		'author',
		'post__in',
		'post__not_in',
		'year',
		'monthnum',
	);

	foreach ( get_taxonomies_for_attachments( 'objects' ) as $t ) {
		if ( $t->query_var && isset( $query[ $t->query_var ] ) ) {
			$keys[] = $t->query_var;
		}
	}

	$query              = array_intersect_key( $query, array_flip( $keys ) );
	$query['post_type'] = 'attachment';

	if (
		MEDIA_TRASH &&
		! empty( $_REQUEST['query']['post_status'] ) &&
		'trash' === $_REQUEST['query']['post_status']
	) {
		$query['post_status'] = 'trash';
	} else {
		$query['post_status'] = 'inherit';
	}

	if ( current_user_can( get_post_type_object( 'attachment' )->cap->read_private_posts ) ) {
		$query['post_status'] .= ',private';
	}

	// Filter query clauses to include filenames.
	if ( isset( $query['s'] ) ) {
		add_filter( 'wp_allow_query_attachment_by_filename', '__return_true' );
	}

	/**
	 * Filters the arguments passed to WP_Query during an Ajax
	 * call for querying attachments.
	 *
	 * @since 3.7.0
	 *
	 * @see WP_Query::parse_query()
	 *
	 * @param array $query An array of query variables.
	 */
	$query             = apply_filters( 'ajax_query_attachments_args', $query );
	$attachments_query = new WP_Query( $query );
	update_post_parent_caches( $attachments_query->posts );

	$posts       = array_map( 'wp_prepare_attachment_for_js', $attachments_query->posts );
	$posts       = array_filter( $posts );
	$total_posts = $attachments_query->found_posts;

	if ( $total_posts < 1 ) {
		// Out-of-bounds, run the query again without LIMIT for total count.
		unset( $query['paged'] );

		$count_query = new WP_Query();
		$count_query->query( $query );
		$total_posts = $count_query->found_posts;
	}

	$posts_per_page = (int) $attachments_query->get( 'posts_per_page' );

	$max_pages = $posts_per_page ? (int) ceil( $total_posts / $posts_per_page ) : 0;

	header( 'X-WP-Total: ' . (int) $total_posts );
	header( 'X-WP-TotalPages: ' . $max_pages );

	wp_send_json_success( $posts );
}

/**
 * Handles updating attachment attributes via AJAX.
 *
 * @since 3.5.0
 */
function wp_ajax_save_attachment() {
	if ( ! isset( $_REQUEST['id'] ) || ! isset( $_REQUEST['changes'] ) ) {
		wp_send_json_error();
	}

	$id = absint( $_REQUEST['id'] );
	if ( ! $id ) {
		wp_send_json_error();
	}

	check_ajax_referer( 'update-post_' . $id, 'nonce' );

	if ( ! current_user_can( 'edit_post', $id ) ) {
		wp_send_json_error();
	}

	$changes = $_REQUEST['changes'];
	$post    = get_post( $id, ARRAY_A );

	if ( 'attachment' !== $post['post_type'] ) {
		wp_send_json_error();
	}

	if ( isset( $changes['parent'] ) ) {
		$post['post_parent'] = $changes['parent'];
	}

	if ( isset( $changes['title'] ) ) {
		$post['post_title'] = $changes['title'];
	}

	if ( isset( $changes['caption'] ) ) {
		$post['post_excerpt'] = $changes['caption'];
	}

	if ( isset( $changes['description'] ) ) {
		$post['post_content'] = $changes['description'];
	}

	if ( MEDIA_TRASH && isset( $changes['status'] ) ) {
		$post['post_status'] = $changes['status'];
	}

	if ( isset( $changes['alt'] ) ) {
		$alt = wp_unslash( $changes['alt'] );
		if ( get_post_meta( $id, '_wp_attachment_image_alt', true ) !== $alt ) {
			$alt = wp_strip_all_tags( $alt, true );
			update_post_meta( $id, '_wp_attachment_image_alt', wp_slash( $alt ) );
		}
	}

	if ( wp_attachment_is( 'audio', $post['ID'] ) ) {
		$changed = false;
		$id3data = wp_get_attachment_metadata( $post['ID'] );

		if ( ! is_array( $id3data ) ) {
			$changed = true;
			$id3data = array();
		}

		foreach ( wp_get_attachment_id3_keys( (object) $post, 'edit' ) as $key => $label ) {
			if ( isset( $changes[ $key ] ) ) {
				$changed         = true;
				$id3data[ $key ] = sanitize_text_field( wp_unslash( $changes[ $key ] ) );
			}
		}

		if ( $changed ) {
			wp_update_attachment_metadata( $id, $id3data );
		}
	}

	if ( MEDIA_TRASH && isset( $changes['status'] ) && 'trash' === $changes['status'] ) {
		wp_delete_post( $id );
	} else {
		wp_update_post( $post );
	}

	wp_send_json_success();
}

/**
 * Handles saving backward compatible attachment attributes via AJAX.
 *
 * @since 3.5.0
 */
function wp_ajax_save_attachment_compat() {
	if ( ! isset( $_REQUEST['id'] ) ) {
		wp_send_json_error();
	}

	$id = absint( $_REQUEST['id'] );
	if ( ! $id ) {
		wp_send_json_error();
	}

	if ( empty( $_REQUEST['attachments'] ) || empty( $_REQUEST['attachments'][ $id ] ) ) {
		wp_send_json_error();
	}

	$attachment_data = $_REQUEST['attachments'][ $id ];

	check_ajax_referer( 'update-post_' . $id, 'nonce' );

	if ( ! current_user_can( 'edit_post', $id ) ) {
		wp_send_json_error();
	}

	$post = get_post( $id, ARRAY_A );

	if ( 'attachment' !== $post['post_type'] ) {
		wp_send_json_error();
	}

	/** This filter is documented in wp-admin/includes/media.php */
	$post = apply_filters( 'attachment_fields_to_save', $post, $attachment_data );

	if ( isset( $post['errors'] ) ) {
		$errors = $post['errors']; // @todo return me and display me!
		unset( $post['errors'] );
	}

	wp_update_post( $post );

	foreach ( get_attachment_taxonomies( $post ) as $taxonomy ) {
		if ( isset( $attachment_data[ $taxonomy ] ) ) {
			wp_set_object_terms( $id, array_map( 'trim', preg_split( '/,+/', $attachment_data[ $taxonomy ] ) ), $taxonomy, false );
		}
	}

	$attachment = wp_prepare_attachment_for_js( $id );

	if ( ! $attachment ) {
		wp_send_json_error();
	}

	wp_send_json_success( $attachment );
}

/**
 * Handles saving the attachment order via AJAX.
 *
 * @since 3.5.0
 */
function wp_ajax_save_attachment_order() {
	if ( ! isset( $_REQUEST['post_id'] ) ) {
		wp_send_json_error();
	}

	$post_id = absint( $_REQUEST['post_id'] );
	if ( ! $post_id ) {
		wp_send_json_error();
	}

	if ( empty( $_REQUEST['attachments'] ) ) {
		wp_send_json_error();
	}

	check_ajax_referer( 'update-post_' . $post_id, 'nonce' );

	$attachments = $_REQUEST['attachments'];

	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		wp_send_json_error();
	}

	foreach ( $attachments as $attachment_id => $menu_order ) {
		if ( ! current_user_can( 'edit_post', $attachment_id ) ) {
			continue;
		}

		$attachment = get_post( $attachment_id );

		if ( ! $attachment ) {
			continue;
		}

		if ( 'attachment' !== $attachment->post_type ) {
			continue;
		}

		wp_update_post(
			array(
				'ID'         => $attachment_id,
				'menu_order' => $menu_order,
			)
		);
	}

	wp_send_json_success();
}

/**
 * Handles sending an attachment to the editor via AJAX.
 *
 * Generates the HTML to send an attachment to the editor.
 * Backward compatible with the {@see 'media_send_to_editor'} filter
 * and the chain of filters that follow.
 *
 * @since 3.5.0
 */
function wp_ajax_send_attachment_to_editor() {
	check_ajax_referer( 'media-send-to-editor', 'nonce' );

	$attachment = wp_unslash( $_POST['attachment'] );

	$id = (int) $attachment['id'];

	$post = get_post( $id );
	if ( ! $post ) {
		wp_send_json_error();
	}

	if ( 'attachment' !== $post->post_type ) {
		wp_send_json_error();
	}

	if ( current_user_can( 'edit_post', $id ) ) {
		// If this attachment is unattached, attach it. Primarily a back compat thing.
		$insert_into_post_id = (int) $_POST['post_id'];

		if ( 0 === $post->post_parent && $insert_into_post_id ) {
			wp_update_post(
				array(
					'ID'          => $id,
					'post_parent' => $insert_into_post_id,
				)
			);
		}
	}

	$url = empty( $attachment['url'] ) ? '' : $attachment['url'];
	$rel = ( str_contains( $url, 'attachment_id' ) || get_attachment_link( $id ) === $url );

	remove_filter( 'media_send_to_editor', 'image_media_send_to_editor' );

	if ( str_starts_with( $post->post_mime_type, 'image' ) ) {
		$align = isset( $attachment['align'] ) ? $attachment['align'] : 'none';
		$size  = isset( $attachment['image-size'] ) ? $attachment['image-size'] : 'medium';
		$alt   = isset( $attachment['image_alt'] ) ? $attachment['image_alt'] : '';

		// No whitespace-only captions.
		$caption = isset( $attachment['post_excerpt'] ) ? $attachment['post_excerpt'] : '';
		if ( '' === trim( $caption ) ) {
			$caption = '';
		}

		$title = ''; // We no longer insert title tags into <img> tags, as they are redundant.
		$html  = get_image_send_to_editor( $id, $caption, $title, $align, $url, $rel, $size, $alt );
	} elseif ( wp_attachment_is( 'video', $post ) || wp_attachment_is( 'audio', $post ) ) {
		$html = stripslashes_deep( $_POST['html'] );
	} else {
		$html = isset( $attachment['post_title'] ) ? $attachment['post_title'] : '';
		$rel  = $rel ? ' rel="attachment wp-att-' . $id . '"' : ''; // Hard-coded string, $id is already sanitized.

		if ( ! empty( $url ) ) {
			$html = '<a href="' . esc_url( $url ) . '"' . $rel . '>' . $html . '</a>';
		}
	}

	/** This filter is documented in wp-admin/includes/media.php */
	$html = apply_filters( 'media_send_to_editor', $html, $id, $attachment );

	wp_send_json_success( $html );
}

/**
 * Handles sending a link to the editor via AJAX.
 *
 * Generates the HTML to send a non-image embed link to the editor.
 *
 * Backward compatible with the following filters:
 * - file_send_to_editor_url
 * - audio_send_to_editor_url
 * - video_send_to_editor_url
 *
 * @since 3.5.0
 *
 * @global WP_Post  $post     Global post object.
 * @global WP_Embed $wp_embed WordPress Embed object.
 */
function wp_ajax_send_link_to_editor() {
	global $post, $wp_embed;

	check_ajax_referer( 'media-send-to-editor', 'nonce' );

	$src = wp_unslash( $_POST['src'] );
	if ( ! $src ) {
		wp_send_json_error();
	}

	if ( ! strpos( $src, '://' ) ) {
		$src = 'http://' . $src;
	}

	$src = sanitize_url( $src );
	if ( ! $src ) {
		wp_send_json_error();
	}

	$link_text = trim( wp_unslash( $_POST['link_text'] ) );
	if ( ! $link_text ) {
		$link_text = wp_basename( $src );
	}

	$post = get_post( isset( $_POST['post_id'] ) ? $_POST['post_id'] : 0 );

	// Ping WordPress for an embed.
	$check_embed = $wp_embed->run_shortcode( '[embed]' . $src . '[/embed]' );

	// Fallback that WordPress creates when no oEmbed was found.
	$fallback = $wp_embed->maybe_make_link( $src );

	if ( $check_embed !== $fallback ) {
		// TinyMCE view for [embed] will parse this.
		$html = '[embed]' . $src . '[/embed]';
	} elseif ( $link_text ) {
		$html = '<a href="' . esc_url( $src ) . '">' . $link_text . '</a>';
	} else {
		$html = '';
	}

	// Figure out what filter to run:
	$type = 'file';
	$ext  = preg_replace( '/^.+?\.([^.]+)$/', '$1', $src );
	if ( $ext ) {
		$ext_type = wp_ext2type( $ext );
		if ( 'audio' === $ext_type || 'video' === $ext_type ) {
			$type = $ext_type;
		}
	}

	/** This filter is documented in wp-admin/includes/media.php */
	$html = apply_filters( "{$type}_send_to_editor_url", $html, $src, $link_text );

	wp_send_json_success( $html );
}

/**
 * Handles the Heartbeat API via AJAX.
 *
 * Runs when the user is logged in.
 *
 * @since 3.6.0
 */
function wp_ajax_heartbeat() {
	if ( empty( $_POST['_nonce'] ) ) {
		wp_send_json_error();
	}

	$response    = array();
	$data        = array();
	$nonce_state = wp_verify_nonce( $_POST['_nonce'], 'heartbeat-nonce' );

	// 'screen_id' is the same as $current_screen->id and the JS global 'pagenow'.
	if ( ! empty( $_POST['screen_id'] ) ) {
		$screen_id = sanitize_key( $_POST['screen_id'] );
	} else {
		$screen_id = 'front';
	}

	if ( ! empty( $_POST['data'] ) ) {
		$data = wp_unslash( (array) $_POST['data'] );
	}

	if ( 1 !== $nonce_state ) {
		/**
		 * Filters the nonces to send to the New/Edit Post screen.
		 *
		 * @since 4.3.0
		 *
		 * @param array  $response  The Heartbeat response.
		 * @param array  $data      The $_POST data sent.
		 * @param string $screen_id The screen ID.
		 */
		$response = apply_filters( 'wp_refresh_nonces', $response, $data, $screen_id );

		if ( false === $nonce_state ) {
			// User is logged in but nonces have expired.
			$response['nonces_expired'] = true;
			wp_send_json( $response );
		}
	}

	if ( ! empty( $data ) ) {
		/**
		 * Filters the Heartbeat response received.
		 *
		 * @since 3.6.0
		 *
		 * @param array  $response  The Heartbeat response.
		 * @param array  $data      The $_POST data sent.
		 * @param string $screen_id The screen ID.
		 */
		$response = apply_filters( 'heartbeat_received', $response, $data, $screen_id );
	}

	/**
	 * Filters the Heartbeat response sent.
	 *
	 * @since 3.6.0
	 *
	 * @param array  $response  The Heartbeat response.
	 * @param string $screen_id The screen ID.
	 */
	$response = apply_filters( 'heartbeat_send', $response, $screen_id );

	/**
	 * Fires when Heartbeat ticks in logged-in environments.
	 *
	 * Allows the transport to be easily replaced with long-polling.
	 *
	 * @since 3.6.0
	 *
	 * @param array  $response  The Heartbeat response.
	 * @param string $screen_id The screen ID.
	 */
	do_action( 'heartbeat_tick', $response, $screen_id );

	// Send the current time according to the server.
	$response['server_time'] = time();

	wp_send_json( $response );
}

/**
 * Handles getting revision diffs via AJAX.
 *
 * @since 3.6.0
 */
function wp_ajax_get_revision_diffs() {
	require ABSPATH . 'wp-admin/includes/revision.php';

	$post = get_post( (int) $_REQUEST['post_id'] );
	if ( ! $post ) {
		wp_send_json_error();
	}

	if ( ! current_user_can( 'edit_post', $post->ID ) ) {
		wp_send_json_error();
	}

	// Really just pre-loading the cache here.
	$revisions = wp_get_post_revisions( $post->ID, array( 'check_enabled' => false ) );
	if ( ! $revisions ) {
		wp_send_json_error();
	}

	$return = array();

	// Increase the script timeout limit to allow ample time for diff UI setup.
	if ( function_exists( 'set_time_limit' ) ) {
		set_time_limit( 5 * MINUTE_IN_SECONDS );
	}

	foreach ( $_REQUEST['compare'] as $compare_key ) {
		list( $compare_from, $compare_to ) = explode( ':', $compare_key ); // from:to

		$return[] = array(
			'id'     => $compare_key,
			'fields' => wp_get_revision_ui_diff( $post, $compare_from, $compare_to ),
		);
	}
	wp_send_json_success( $return );
}

/**
 * Handles auto-saving the selected color scheme for
 * a user's own profile via AJAX.
 *
 * @since 3.8.0
 *
 * @global array $_wp_admin_css_colors
 */
function wp_ajax_save_user_color_scheme() {
	global $_wp_admin_css_colors;

	check_ajax_referer( 'save-color-scheme', 'nonce' );

	$color_scheme = sanitize_key( $_POST['color_scheme'] );

	if ( ! isset( $_wp_admin_css_colors[ $color_scheme ] ) ) {
		wp_send_json_error();
	}

	$previous_color_scheme = get_user_meta( get_current_user_id(), 'admin_color', true );
	update_user_meta( get_current_user_id(), 'admin_color', $color_scheme );

	wp_send_json_success(
		array(
			'previousScheme' => 'admin-color-' . $previous_color_scheme,
			'currentScheme'  => 'admin-color-' . $color_scheme,
		)
	);
}

/**
 * Handles getting themes from themes_api() via AJAX.
 *
 * @since 3.9.0
 *
 * @global array $themes_allowedtags
 * @global array $theme_field_defaults
 */
function wp_ajax_query_themes() {
	global $themes_allowedtags, $theme_field_defaults;

	if ( ! current_user_can( 'install_themes' ) ) {
		wp_send_json_error();
	}

	$args = wp_parse_args(
		wp_unslash( $_REQUEST['request'] ),
		array(
			'per_page' => 20,
			'fields'   => array_merge(
				(array) $theme_field_defaults,
				array(
					'reviews_url' => true, // Explicitly request the reviews URL to be linked from the Add Themes screen.
				)
			),
		)
	);

	if ( isset( $args['browse'] ) && 'favorites' === $args['browse'] && ! isset( $args['user'] ) ) {
		$user = get_user_option( 'wporg_favorites' );
		if ( $user ) {
			$args['user'] = $user;
		}
	}

	$old_filter = isset( $args['browse'] ) ? $args['browse'] : 'search';

	/** This filter is documented in wp-admin/includes/class-wp-theme-install-list-table.php */
	$args = apply_filters( 'install_themes_table_api_args_' . $old_filter, $args );

	$api = themes_api( 'query_themes', $args );

	if ( is_wp_error( $api ) ) {
		wp_send_json_error();
	}

	$update_php = network_admin_url( 'update.php?action=install-theme' );

	$installed_themes = search_theme_directories();

	if ( false === $installed_themes ) {
		$installed_themes = array();
	}

	foreach ( $installed_themes as $theme_slug => $theme_data ) {
		// Ignore child themes.
		if ( str_contains( $theme_slug, '/' ) ) {
			unset( $installed_themes[ $theme_slug ] );
		}
	}

	foreach ( $api->themes as &$theme ) {
		$theme->install_url = add_query_arg(
			array(
				'theme'    => $theme->slug,
				'_wpnonce' => wp_create_nonce( 'install-theme_' . $theme->slug ),
			),
			$update_php
		);

		if ( current_user_can( 'switch_themes' ) ) {
			if ( is_multisite() ) {
				$theme->activate_url = add_query_arg(
					array(
						'action'   => 'enable',
						'_wpnonce' => wp_create_nonce( 'enable-theme_' . $theme->slug ),
						'theme'    => $theme->slug,
					),
					network_admin_url( 'themes.php' )
				);
			} else {
				$theme->activate_url = add_query_arg(
					array(
						'action'     => 'activate',
						'_wpnonce'   => wp_create_nonce( 'switch-theme_' . $theme->slug ),
						'stylesheet' => $theme->slug,
					),
					admin_url( 'themes.php' )
				);
			}
		}

		$is_theme_installed = array_key_exists( $theme->slug, $installed_themes );

		// We only care about installed themes.
		$theme->block_theme = $is_theme_installed && wp_get_theme( $theme->slug )->is_block_theme();

		if ( ! is_multisite() && current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) {
			$customize_url = $theme->block_theme ? admin_url( 'site-editor.php' ) : wp_customize_url( $theme->slug );

			$theme->customize_url = add_query_arg(
				array(
					'return' => urlencode( network_admin_url( 'theme-install.php', 'relative' ) ),
				),
				$customize_url
			);
		}

		$theme->name        = wp_kses( $theme->name, $themes_allowedtags );
		$theme->author      = wp_kses( $theme->author['display_name'], $themes_allowedtags );
		$theme->version     = wp_kses( $theme->version, $themes_allowedtags );
		$theme->description = wp_kses( $theme->description, $themes_allowedtags );

		$theme->stars = wp_star_rating(
			array(
				'rating' => $theme->rating,
				'type'   => 'percent',
				'number' => $theme->num_ratings,
				'echo'   => false,
			)
		);

		$theme->num_ratings    = number_format_i18n( $theme->num_ratings );
		$theme->preview_url    = set_url_scheme( $theme->preview_url );
		$theme->compatible_wp  = is_wp_version_compatible( $theme->requires );
		$theme->compatible_php = is_php_version_compatible( $theme->requires_php );
	}

	wp_send_json_success( $api );
}

/**
 * Applies [embed] Ajax handlers to a string.
 *
 * @since 4.0.0
 *
 * @global WP_Post    $post          Global post object.
 * @global WP_Embed   $wp_embed      WordPress Embed object.
 * @global WP_Scripts $wp_scripts
 * @global int        $content_width
 */
function wp_ajax_parse_embed() {
	global $post, $wp_embed, $content_width;

	if ( empty( $_POST['shortcode'] ) ) {
		wp_send_json_error();
	}

	$post_id = isset( $_POST['post_ID'] ) ? (int) $_POST['post_ID'] : 0;

	if ( $post_id > 0 ) {
		$post = get_post( $post_id );

		if ( ! $post || ! current_user_can( 'edit_post', $post->ID ) ) {
			wp_send_json_error();
		}
		setup_postdata( $post );
	} elseif ( ! current_user_can( 'edit_posts' ) ) { // See WP_oEmbed_Controller::get_proxy_item_permissions_check().
		wp_send_json_error();
	}

	$shortcode = wp_unslash( $_POST['shortcode'] );

	preg_match( '/' . get_shortcode_regex() . '/s', $shortcode, $matches );
	$atts = shortcode_parse_atts( $matches[3] );

	if ( ! empty( $matches[5] ) ) {
		$url = $matches[5];
	} elseif ( ! empty( $atts['src'] ) ) {
		$url = $atts['src'];
	} else {
		$url = '';
	}

	$parsed                         = false;
	$wp_embed->return_false_on_fail = true;

	if ( 0 === $post_id ) {
		/*
		 * Refresh oEmbeds cached outside of posts that are past their TTL.
		 * Posts are excluded because they have separate logic for refreshing
		 * their post meta caches. See WP_Embed::cache_oembed().
		 */
		$wp_embed->usecache = false;
	}

	if ( is_ssl() && str_starts_with( $url, 'http://' ) ) {
		/*
		 * Admin is ssl and the user pasted non-ssl URL.
		 * Check if the provider supports ssl embeds and use that for the preview.
		 */
		$ssl_shortcode = preg_replace( '%^(\\[embed[^\\]]*\\])http://%i', '$1https://', $shortcode );
		$parsed        = $wp_embed->run_shortcode( $ssl_shortcode );

		if ( ! $parsed ) {
			$no_ssl_support = true;
		}
	}

	// Set $content_width so any embeds fit in the destination iframe.
	if ( isset( $_POST['maxwidth'] ) && is_numeric( $_POST['maxwidth'] ) && $_POST['maxwidth'] > 0 ) {
		if ( ! isset( $content_width ) ) {
			$content_width = (int) $_POST['maxwidth'];
		} else {
			$content_width = min( $content_width, (int) $_POST['maxwidth'] );
		}
	}

	if ( $url && ! $parsed ) {
		$parsed = $wp_embed->run_shortcode( $shortcode );
	}

	if ( ! $parsed ) {
		wp_send_json_error(
			array(
				'type'    => 'not-embeddable',
				/* translators: %s: URL that could not be embedded. */
				'message' => sprintf( __( '%s failed to embed.' ), '<code>' . esc_html( $url ) . '</code>' ),
			)
		);
	}

	if ( has_shortcode( $parsed, 'audio' ) || has_shortcode( $parsed, 'video' ) ) {
		$styles     = '';
		$mce_styles = wpview_media_sandbox_styles();

		foreach ( $mce_styles as $style ) {
			$styles .= sprintf( '<link rel="stylesheet" href="%s" />', $style );
		}

		$html = do_shortcode( $parsed );

		global $wp_scripts;

		if ( ! empty( $wp_scripts ) ) {
			$wp_scripts->done = array();
		}

		ob_start();
		wp_print_scripts( array( 'mediaelement-vimeo', 'wp-mediaelement' ) );
		$scripts = ob_get_clean();

		$parsed = $styles . $html . $scripts;
	}

	if ( ! empty( $no_ssl_support ) || ( is_ssl() && ( preg_match( '%<(iframe|script|embed) [^>]*src="http://%', $parsed ) ||
		preg_match( '%<link [^>]*href="http://%', $parsed ) ) ) ) {
		// Admin is ssl and the embed is not. Iframes, scripts, and other "active content" will be blocked.
		wp_send_json_error(
			array(
				'type'    => 'not-ssl',
				'message' => __( 'This preview is unavailable in the editor.' ),
			)
		);
	}

	$return = array(
		'body' => $parsed,
		'attr' => $wp_embed->last_attr,
	);

	if ( str_contains( $parsed, 'class="wp-embedded-content' ) ) {
		if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
			$script_src = includes_url( 'js/wp-embed.js' );
		} else {
			$script_src = includes_url( 'js/wp-embed.min.js' );
		}

		$return['head']    = '<script src="' . $script_src . '"></script>';
		$return['sandbox'] = true;
	}

	wp_send_json_success( $return );
}

/**
 * @since 4.0.0
 *
 * @global WP_Post    $post       Global post object.
 * @global WP_Scripts $wp_scripts
 */
function wp_ajax_parse_media_shortcode() {
	global $post, $wp_scripts;

	if ( empty( $_POST['shortcode'] ) ) {
		wp_send_json_error();
	}

	$shortcode = wp_unslash( $_POST['shortcode'] );

	// Only process previews for media related shortcodes:
	$found_shortcodes = get_shortcode_tags_in_content( $shortcode );
	$media_shortcodes = array(
		'audio',
		'embed',
		'playlist',
		'video',
		'gallery',
	);

	$other_shortcodes = array_diff( $found_shortcodes, $media_shortcodes );

	if ( ! empty( $other_shortcodes ) ) {
		wp_send_json_error();
	}

	if ( ! empty( $_POST['post_ID'] ) ) {
		$post = get_post( (int) $_POST['post_ID'] );
	}

	// The embed shortcode requires a post.
	if ( ! $post || ! current_user_can( 'edit_post', $post->ID ) ) {
		if ( in_array( 'embed', $found_shortcodes, true ) ) {
			wp_send_json_error();
		}
	} else {
		setup_postdata( $post );
	}

	$parsed = do_shortcode( $shortcode );

	if ( empty( $parsed ) ) {
		wp_send_json_error(
			array(
				'type'    => 'no-items',
				'message' => __( 'No items found.' ),
			)
		);
	}

	$head   = '';
	$styles = wpview_media_sandbox_styles();

	foreach ( $styles as $style ) {
		$head .= '<link type="text/css" rel="stylesheet" href="' . $style . '">';
	}

	if ( ! empty( $wp_scripts ) ) {
		$wp_scripts->done = array();
	}

	ob_start();

	echo $parsed;

	if ( 'playlist' === $_REQUEST['type'] ) {
		wp_underscore_playlist_templates();

		wp_print_scripts( 'wp-playlist' );
	} else {
		wp_print_scripts( array( 'mediaelement-vimeo', 'wp-mediaelement' ) );
	}

	wp_send_json_success(
		array(
			'head' => $head,
			'body' => ob_get_clean(),
		)
	);
}

/**
 * Handles destroying multiple open sessions for a user via AJAX.
 *
 * @since 4.1.0
 */
function wp_ajax_destroy_sessions() {
	$user = get_userdata( (int) $_POST['user_id'] );

	if ( $user ) {
		if ( ! current_user_can( 'edit_user', $user->ID ) ) {
			$user = false;
		} elseif ( ! wp_verify_nonce( $_POST['nonce'], 'update-user_' . $user->ID ) ) {
			$user = false;
		}
	}

	if ( ! $user ) {
		wp_send_json_error(
			array(
				'message' => __( 'Could not log out user sessions. Please try again.' ),
			)
		);
	}

	$sessions = WP_Session_Tokens::get_instance( $user->ID );

	if ( get_current_user_id() === $user->ID ) {
		$sessions->destroy_others( wp_get_session_token() );
		$message = __( 'You are now logged out everywhere else.' );
	} else {
		$sessions->destroy_all();
		/* translators: %s: User's display name. */
		$message = sprintf( __( '%s has been logged out.' ), $user->display_name );
	}

	wp_send_json_success( array( 'message' => $message ) );
}

/**
 * Handles cropping an image via AJAX.
 *
 * @since 4.3.0
 */
function wp_ajax_crop_image() {
	$attachment_id = absint( $_POST['id'] );

	check_ajax_referer( 'image_editor-' . $attachment_id, 'nonce' );

	if ( empty( $attachment_id ) || ! current_user_can( 'edit_post', $attachment_id ) ) {
		wp_send_json_error();
	}

	$context = str_replace( '_', '-', $_POST['context'] );
	$data    = array_map( 'absint', $_POST['cropDetails'] );
	$cropped = wp_crop_image( $attachment_id, $data['x1'], $data['y1'], $data['width'], $data['height'], $data['dst_width'], $data['dst_height'] );

	if ( ! $cropped || is_wp_error( $cropped ) ) {
		wp_send_json_error( array( 'message' => __( 'Image could not be processed.' ) ) );
	}

	switch ( $context ) {
		case 'site-icon':
			require_once ABSPATH . 'wp-admin/includes/class-wp-site-icon.php';
			$wp_site_icon = new WP_Site_Icon();

			// Skip creating a new attachment if the attachment is a Site Icon.
			if ( get_post_meta( $attachment_id, '_wp_attachment_context', true ) === $context ) {

				// Delete the temporary cropped file, we don't need it.
				wp_delete_file( $cropped );

				// Additional sizes in wp_prepare_attachment_for_js().
				add_filter( 'image_size_names_choose', array( $wp_site_icon, 'additional_sizes' ) );
				break;
			}

			/** This filter is documented in wp-admin/includes/class-custom-image-header.php */
			$cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication.

			// Copy attachment properties.
			$attachment = wp_copy_parent_attachment_properties( $cropped, $attachment_id, $context );

			// Update the attachment.
			add_filter( 'intermediate_image_sizes_advanced', array( $wp_site_icon, 'additional_sizes' ) );
			$attachment_id = $wp_site_icon->insert_attachment( $attachment, $cropped );
			remove_filter( 'intermediate_image_sizes_advanced', array( $wp_site_icon, 'additional_sizes' ) );

			// Additional sizes in wp_prepare_attachment_for_js().
			add_filter( 'image_size_names_choose', array( $wp_site_icon, 'additional_sizes' ) );
			break;

		default:
			/**
			 * Fires before a cropped image is saved.
			 *
			 * Allows to add filters to modify the way a cropped image is saved.
			 *
			 * @since 4.3.0
			 *
			 * @param string $context       The Customizer control requesting the cropped image.
			 * @param int    $attachment_id The attachment ID of the original image.
			 * @param string $cropped       Path to the cropped image file.
			 */
			do_action( 'wp_ajax_crop_image_pre_save', $context, $attachment_id, $cropped );

			/** This filter is documented in wp-admin/includes/class-custom-image-header.php */
			$cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication.

			// Copy attachment properties.
			$attachment = wp_copy_parent_attachment_properties( $cropped, $attachment_id, $context );

			$attachment_id = wp_insert_attachment( $attachment, $cropped );
			$metadata      = wp_generate_attachment_metadata( $attachment_id, $cropped );

			/**
			 * Filters the cropped image attachment metadata.
			 *
			 * @since 4.3.0
			 *
			 * @see wp_generate_attachment_metadata()
			 *
			 * @param array $metadata Attachment metadata.
			 */
			$metadata = apply_filters( 'wp_ajax_cropped_attachment_metadata', $metadata );
			wp_update_attachment_metadata( $attachment_id, $metadata );

			/**
			 * Filters the attachment ID for a cropped image.
			 *
			 * @since 4.3.0
			 *
			 * @param int    $attachment_id The attachment ID of the cropped image.
			 * @param string $context       The Customizer control requesting the cropped image.
			 */
			$attachment_id = apply_filters( 'wp_ajax_cropped_attachment_id', $attachment_id, $context );
	}

	wp_send_json_success( wp_prepare_attachment_for_js( $attachment_id ) );
}

/**
 * Handles generating a password via AJAX.
 *
 * @since 4.4.0
 */
function wp_ajax_generate_password() {
	wp_send_json_success( wp_generate_password( 24 ) );
}

/**
 * Handles generating a password in the no-privilege context via AJAX.
 *
 * @since 5.7.0
 */
function wp_ajax_nopriv_generate_password() {
	wp_send_json_success( wp_generate_password( 24 ) );
}

/**
 * Handles saving the user's WordPress.org username via AJAX.
 *
 * @since 4.4.0
 */
function wp_ajax_save_wporg_username() {
	if ( ! current_user_can( 'install_themes' ) && ! current_user_can( 'install_plugins' ) ) {
		wp_send_json_error();
	}

	check_ajax_referer( 'save_wporg_username_' . get_current_user_id() );

	$username = isset( $_REQUEST['username'] ) ? wp_unslash( $_REQUEST['username'] ) : false;

	if ( ! $username ) {
		wp_send_json_error();
	}

	wp_send_json_success( update_user_meta( get_current_user_id(), 'wporg_favorites', $username ) );
}

/**
 * Handles installing a theme via AJAX.
 *
 * @since 4.6.0
 *
 * @see Theme_Upgrader
 *
 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
 */
function wp_ajax_install_theme() {
	check_ajax_referer( 'updates' );

	if ( empty( $_POST['slug'] ) ) {
		wp_send_json_error(
			array(
				'slug'         => '',
				'errorCode'    => 'no_theme_specified',
				'errorMessage' => __( 'No theme specified.' ),
			)
		);
	}

	$slug = sanitize_key( wp_unslash( $_POST['slug'] ) );

	$status = array(
		'install' => 'theme',
		'slug'    => $slug,
	);

	if ( ! current_user_can( 'install_themes' ) ) {
		$status['errorMessage'] = __( 'Sorry, you are not allowed to install themes on this site.' );
		wp_send_json_error( $status );
	}

	require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
	require_once ABSPATH . 'wp-admin/includes/theme.php';

	$api = themes_api(
		'theme_information',
		array(
			'slug'   => $slug,
			'fields' => array( 'sections' => false ),
		)
	);

	if ( is_wp_error( $api ) ) {
		$status['errorMessage'] = $api->get_error_message();
		wp_send_json_error( $status );
	}

	$skin     = new WP_Ajax_Upgrader_Skin();
	$upgrader = new Theme_Upgrader( $skin );
	$result   = $upgrader->install( $api->download_link );

	if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
		$status['debug'] = $skin->get_upgrade_messages();
	}

	if ( is_wp_error( $result ) ) {
		$status['errorCode']    = $result->get_error_code();
		$status['errorMessage'] = $result->get_error_message();
		wp_send_json_error( $status );
	} elseif ( is_wp_error( $skin->result ) ) {
		$status['errorCode']    = $skin->result->get_error_code();
		$status['errorMessage'] = $skin->result->get_error_message();
		wp_send_json_error( $status );
	} elseif ( $skin->get_errors()->has_errors() ) {
		$status['errorMessage'] = $skin->get_error_messages();
		wp_send_json_error( $status );
	} elseif ( is_null( $result ) ) {
		global $wp_filesystem;

		$status['errorCode']    = 'unable_to_connect_to_filesystem';
		$status['errorMessage'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );

		// Pass through the error from WP_Filesystem if one was raised.
		if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->has_errors() ) {
			$status['errorMessage'] = esc_html( $wp_filesystem->errors->get_error_message() );
		}

		wp_send_json_error( $status );
	}

	$status['themeName'] = wp_get_theme( $slug )->get( 'Name' );

	if ( current_user_can( 'switch_themes' ) ) {
		if ( is_multisite() ) {
			$status['activateUrl'] = add_query_arg(
				array(
					'action'   => 'enable',
					'_wpnonce' => wp_create_nonce( 'enable-theme_' . $slug ),
					'theme'    => $slug,
				),
				network_admin_url( 'themes.php' )
			);
		} else {
			$status['activateUrl'] = add_query_arg(
				array(
					'action'     => 'activate',
					'_wpnonce'   => wp_create_nonce( 'switch-theme_' . $slug ),
					'stylesheet' => $slug,
				),
				admin_url( 'themes.php' )
			);
		}
	}

	$theme                = wp_get_theme( $slug );
	$status['blockTheme'] = $theme->is_block_theme();

	if ( ! is_multisite() && current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) {
		$status['customizeUrl'] = add_query_arg(
			array(
				'return' => urlencode( network_admin_url( 'theme-install.php', 'relative' ) ),
			),
			wp_customize_url( $slug )
		);
	}

	/*
	 * See WP_Theme_Install_List_Table::_get_theme_status() if we wanted to check
	 * on post-installation status.
	 */
	wp_send_json_success( $status );
}

/**
 * Handles updating a theme via AJAX.
 *
 * @since 4.6.0
 *
 * @see Theme_Upgrader
 *
 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
 */
function wp_ajax_update_theme() {
	check_ajax_referer( 'updates' );

	if ( empty( $_POST['slug'] ) ) {
		wp_send_json_error(
			array(
				'slug'         => '',
				'errorCode'    => 'no_theme_specified',
				'errorMessage' => __( 'No theme specified.' ),
			)
		);
	}

	$stylesheet = preg_replace( '/[^A-z0-9_\-]/', '', wp_unslash( $_POST['slug'] ) );
	$status     = array(
		'update'     => 'theme',
		'slug'       => $stylesheet,
		'oldVersion' => '',
		'newVersion' => '',
	);

	if ( ! current_user_can( 'update_themes' ) ) {
		$status['errorMessage'] = __( 'Sorry, you are not allowed to update themes for this site.' );
		wp_send_json_error( $status );
	}

	$theme = wp_get_theme( $stylesheet );
	if ( $theme->exists() ) {
		$status['oldVersion'] = $theme->get( 'Version' );
	}

	require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';

	$current = get_site_transient( 'update_themes' );
	if ( empty( $current ) ) {
		wp_update_themes();
	}

	$skin     = new WP_Ajax_Upgrader_Skin();
	$upgrader = new Theme_Upgrader( $skin );
	$result   = $upgrader->bulk_upgrade( array( $stylesheet ) );

	if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
		$status['debug'] = $skin->get_upgrade_messages();
	}

	if ( is_wp_error( $skin->result ) ) {
		$status['errorCode']    = $skin->result->get_error_code();
		$status['errorMessage'] = $skin->result->get_error_message();
		wp_send_json_error( $status );
	} elseif ( $skin->get_errors()->has_errors() ) {
		$status['errorMessage'] = $skin->get_error_messages();
		wp_send_json_error( $status );
	} elseif ( is_array( $result ) && ! empty( $result[ $stylesheet ] ) ) {

		// Theme is already at the latest version.
		if ( true === $result[ $stylesheet ] ) {
			$status['errorMessage'] = $upgrader->strings['up_to_date'];
			wp_send_json_error( $status );
		}

		$theme = wp_get_theme( $stylesheet );
		if ( $theme->exists() ) {
			$status['newVersion'] = $theme->get( 'Version' );
		}

		wp_send_json_success( $status );
	} elseif ( false === $result ) {
		global $wp_filesystem;

		$status['errorCode']    = 'unable_to_connect_to_filesystem';
		$status['errorMessage'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );

		// Pass through the error from WP_Filesystem if one was raised.
		if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->has_errors() ) {
			$status['errorMessage'] = esc_html( $wp_filesystem->errors->get_error_message() );
		}

		wp_send_json_error( $status );
	}

	// An unhandled error occurred.
	$status['errorMessage'] = __( 'Theme update failed.' );
	wp_send_json_error( $status );
}

/**
 * Handles deleting a theme via AJAX.
 *
 * @since 4.6.0
 *
 * @see delete_theme()
 *
 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
 */
function wp_ajax_delete_theme() {
	check_ajax_referer( 'updates' );

	if ( empty( $_POST['slug'] ) ) {
		wp_send_json_error(
			array(
				'slug'         => '',
				'errorCode'    => 'no_theme_specified',
				'errorMessage' => __( 'No theme specified.' ),
			)
		);
	}

	$stylesheet = preg_replace( '/[^A-z0-9_\-]/', '', wp_unslash( $_POST['slug'] ) );
	$status     = array(
		'delete' => 'theme',
		'slug'   => $stylesheet,
	);

	if ( ! current_user_can( 'delete_themes' ) ) {
		$status['errorMessage'] = __( 'Sorry, you are not allowed to delete themes on this site.' );
		wp_send_json_error( $status );
	}

	if ( ! wp_get_theme( $stylesheet )->exists() ) {
		$status['errorMessage'] = __( 'The requested theme does not exist.' );
		wp_send_json_error( $status );
	}

	// Check filesystem credentials. `delete_theme()` will bail otherwise.
	$url = wp_nonce_url( 'themes.php?action=delete&stylesheet=' . urlencode( $stylesheet ), 'delete-theme_' . $stylesheet );

	ob_start();
	$credentials = request_filesystem_credentials( $url );
	ob_end_clean();

	if ( false === $credentials || ! WP_Filesystem( $credentials ) ) {
		global $wp_filesystem;

		$status['errorCode']    = 'unable_to_connect_to_filesystem';
		$status['errorMessage'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );

		// Pass through the error from WP_Filesystem if one was raised.
		if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->has_errors() ) {
			$status['errorMessage'] = esc_html( $wp_filesystem->errors->get_error_message() );
		}

		wp_send_json_error( $status );
	}

	require_once ABSPATH . 'wp-admin/includes/theme.php';

	$result = delete_theme( $stylesheet );

	if ( is_wp_error( $result ) ) {
		$status['errorMessage'] = $result->get_error_message();
		wp_send_json_error( $status );
	} elseif ( false === $result ) {
		$status['errorMessage'] = __( 'Theme could not be deleted.' );
		wp_send_json_error( $status );
	}

	wp_send_json_success( $status );
}

/**
 * Handles installing a plugin via AJAX.
 *
 * @since 4.6.0
 *
 * @see Plugin_Upgrader
 *
 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
 */
function wp_ajax_install_plugin() {
	check_ajax_referer( 'updates' );

	if ( empty( $_POST['slug'] ) ) {
		wp_send_json_error(
			array(
				'slug'         => '',
				'errorCode'    => 'no_plugin_specified',
				'errorMessage' => __( 'No plugin specified.' ),
			)
		);
	}

	$status = array(
		'install' => 'plugin',
		'slug'    => sanitize_key( wp_unslash( $_POST['slug'] ) ),
	);

	if ( ! current_user_can( 'install_plugins' ) ) {
		$status['errorMessage'] = __( 'Sorry, you are not allowed to install plugins on this site.' );
		wp_send_json_error( $status );
	}

	require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
	require_once ABSPATH . 'wp-admin/includes/plugin-install.php';

	$api = plugins_api(
		'plugin_information',
		array(
			'slug'   => sanitize_key( wp_unslash( $_POST['slug'] ) ),
			'fields' => array(
				'sections' => false,
			),
		)
	);

	if ( is_wp_error( $api ) ) {
		$status['errorMessage'] = $api->get_error_message();
		wp_send_json_error( $status );
	}

	$status['pluginName'] = $api->name;

	$skin     = new WP_Ajax_Upgrader_Skin();
	$upgrader = new Plugin_Upgrader( $skin );
	$result   = $upgrader->install( $api->download_link );

	if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
		$status['debug'] = $skin->get_upgrade_messages();
	}

	if ( is_wp_error( $result ) ) {
		$status['errorCode']    = $result->get_error_code();
		$status['errorMessage'] = $result->get_error_message();
		wp_send_json_error( $status );
	} elseif ( is_wp_error( $skin->result ) ) {
		$status['errorCode']    = $skin->result->get_error_code();
		$status['errorMessage'] = $skin->result->get_error_message();
		wp_send_json_error( $status );
	} elseif ( $skin->get_errors()->has_errors() ) {
		$status['errorMessage'] = $skin->get_error_messages();
		wp_send_json_error( $status );
	} elseif ( is_null( $result ) ) {
		global $wp_filesystem;

		$status['errorCode']    = 'unable_to_connect_to_filesystem';
		$status['errorMessage'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );

		// Pass through the error from WP_Filesystem if one was raised.
		if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->has_errors() ) {
			$status['errorMessage'] = esc_html( $wp_filesystem->errors->get_error_message() );
		}

		wp_send_json_error( $status );
	}

	$install_status = install_plugin_install_status( $api );
	$pagenow        = isset( $_POST['pagenow'] ) ? sanitize_key( $_POST['pagenow'] ) : '';

	// If installation request is coming from import page, do not return network activation link.
	$plugins_url = ( 'import' === $pagenow ) ? admin_url( 'plugins.php' ) : network_admin_url( 'plugins.php' );

	if ( current_user_can( 'activate_plugin', $install_status['file'] ) && is_plugin_inactive( $install_status['file'] ) ) {
		$status['activateUrl'] = add_query_arg(
			array(
				'_wpnonce' => wp_create_nonce( 'activate-plugin_' . $install_status['file'] ),
				'action'   => 'activate',
				'plugin'   => $install_status['file'],
			),
			$plugins_url
		);
	}

	if ( is_multisite() && current_user_can( 'manage_network_plugins' ) && 'import' !== $pagenow ) {
		$status['activateUrl'] = add_query_arg( array( 'networkwide' => 1 ), $status['activateUrl'] );
	}

	wp_send_json_success( $status );
}

/**
 * Handles activating a plugin via AJAX.
 *
 * @since 6.5.0
 */
function wp_ajax_activate_plugin() {
	check_ajax_referer( 'updates' );

	if ( empty( $_POST['name'] ) || empty( $_POST['slug'] ) || empty( $_POST['plugin'] ) ) {
		wp_send_json_error(
			array(
				'slug'         => '',
				'pluginName'   => '',
				'plugin'       => '',
				'errorCode'    => 'no_plugin_specified',
				'errorMessage' => __( 'No plugin specified.' ),
			)
		);
	}

	$status = array(
		'activate'   => 'plugin',
		'slug'       => wp_unslash( $_POST['slug'] ),
		'pluginName' => wp_unslash( $_POST['name'] ),
		'plugin'     => wp_unslash( $_POST['plugin'] ),
	);

	if ( ! current_user_can( 'activate_plugin', $status['plugin'] ) ) {
		$status['errorMessage'] = __( 'Sorry, you are not allowed to activate plugins on this site.' );
		wp_send_json_error( $status );
	}

	if ( is_plugin_active( $status['plugin'] ) ) {
		$status['errorMessage'] = sprintf(
			/* translators: %s: Plugin name. */
			__( '%s is already active.' ),
			$status['pluginName']
		);
	}

	$activated = activate_plugin( $status['plugin'] );

	if ( is_wp_error( $activated ) ) {
		$status['errorMessage'] = $activated->get_error_message();
		wp_send_json_error( $status );
	}

	wp_send_json_success( $status );
}

/**
 * Handles updating a plugin via AJAX.
 *
 * @since 4.2.0
 *
 * @see Plugin_Upgrader
 *
 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
 */
function wp_ajax_update_plugin() {
	check_ajax_referer( 'updates' );

	if ( empty( $_POST['plugin'] ) || empty( $_POST['slug'] ) ) {
		wp_send_json_error(
			array(
				'slug'         => '',
				'errorCode'    => 'no_plugin_specified',
				'errorMessage' => __( 'No plugin specified.' ),
			)
		);
	}

	$plugin = plugin_basename( sanitize_text_field( wp_unslash( $_POST['plugin'] ) ) );

	$status = array(
		'update'     => 'plugin',
		'slug'       => sanitize_key( wp_unslash( $_POST['slug'] ) ),
		'oldVersion' => '',
		'newVersion' => '',
	);

	if ( ! current_user_can( 'update_plugins' ) || 0 !== validate_file( $plugin ) ) {
		$status['errorMessage'] = __( 'Sorry, you are not allowed to update plugins for this site.' );
		wp_send_json_error( $status );
	}

	$plugin_data          = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
	$status['plugin']     = $plugin;
	$status['pluginName'] = $plugin_data['Name'];

	if ( $plugin_data['Version'] ) {
		/* translators: %s: Plugin version. */
		$status['oldVersion'] = sprintf( __( 'Version %s' ), $plugin_data['Version'] );
	}

	require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';

	wp_update_plugins();

	$skin     = new WP_Ajax_Upgrader_Skin();
	$upgrader = new Plugin_Upgrader( $skin );
	$result   = $upgrader->bulk_upgrade( array( $plugin ) );

	if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
		$status['debug'] = $skin->get_upgrade_messages();
	}

	if ( is_wp_error( $skin->result ) ) {
		$status['errorCode']    = $skin->result->get_error_code();
		$status['errorMessage'] = $skin->result->get_error_message();
		wp_send_json_error( $status );
	} elseif ( $skin->get_errors()->has_errors() ) {
		$status['errorMessage'] = $skin->get_error_messages();
		wp_send_json_error( $status );
	} elseif ( is_array( $result ) && ! empty( $result[ $plugin ] ) ) {

		/*
		 * Plugin is already at the latest version.
		 *
		 * This may also be the return value if the `update_plugins` site transient is empty,
		 * e.g. when you update two plugins in quick succession before the transient repopulates.
		 *
		 * Preferably something can be done to ensure `update_plugins` isn't empty.
		 * For now, surface some sort of error here.
		 */
		if ( true === $result[ $plugin ] ) {
			$status['errorMessage'] = $upgrader->strings['up_to_date'];
			wp_send_json_error( $status );
		}

		$plugin_data = get_plugins( '/' . $result[ $plugin ]['destination_name'] );
		$plugin_data = reset( $plugin_data );

		if ( $plugin_data['Version'] ) {
			/* translators: %s: Plugin version. */
			$status['newVersion'] = sprintf( __( 'Version %s' ), $plugin_data['Version'] );
		}

		wp_send_json_success( $status );
	} elseif ( false === $result ) {
		global $wp_filesystem;

		$status['errorCode']    = 'unable_to_connect_to_filesystem';
		$status['errorMessage'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );

		// Pass through the error from WP_Filesystem if one was raised.
		if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->has_errors() ) {
			$status['errorMessage'] = esc_html( $wp_filesystem->errors->get_error_message() );
		}

		wp_send_json_error( $status );
	}

	// An unhandled error occurred.
	$status['errorMessage'] = __( 'Plugin update failed.' );
	wp_send_json_error( $status );
}

/**
 * Handles deleting a plugin via AJAX.
 *
 * @since 4.6.0
 *
 * @see delete_plugins()
 *
 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
 */
function wp_ajax_delete_plugin() {
	check_ajax_referer( 'updates' );

	if ( empty( $_POST['slug'] ) || empty( $_POST['plugin'] ) ) {
		wp_send_json_error(
			array(
				'slug'         => '',
				'errorCode'    => 'no_plugin_specified',
				'errorMessage' => __( 'No plugin specified.' ),
			)
		);
	}

	$plugin = plugin_basename( sanitize_text_field( wp_unslash( $_POST['plugin'] ) ) );

	$status = array(
		'delete' => 'plugin',
		'slug'   => sanitize_key( wp_unslash( $_POST['slug'] ) ),
	);

	if ( ! current_user_can( 'delete_plugins' ) || 0 !== validate_file( $plugin ) ) {
		$status['errorMessage'] = __( 'Sorry, you are not allowed to delete plugins for this site.' );
		wp_send_json_error( $status );
	}

	$plugin_data          = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
	$status['plugin']     = $plugin;
	$status['pluginName'] = $plugin_data['Name'];

	if ( is_plugin_active( $plugin ) ) {
		$status['errorMessage'] = __( 'You cannot delete a plugin while it is active on the main site.' );
		wp_send_json_error( $status );
	}

	// Check filesystem credentials. `delete_plugins()` will bail otherwise.
	$url = wp_nonce_url( 'plugins.php?action=delete-selected&verify-delete=1&checked[]=' . $plugin, 'bulk-plugins' );

	ob_start();
	$credentials = request_filesystem_credentials( $url );
	ob_end_clean();

	if ( false === $credentials || ! WP_Filesystem( $credentials ) ) {
		global $wp_filesystem;

		$status['errorCode']    = 'unable_to_connect_to_filesystem';
		$status['errorMessage'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );

		// Pass through the error from WP_Filesystem if one was raised.
		if ( $wp_filesystem instanceof WP_Filesystem_Base && is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->has_errors() ) {
			$status['errorMessage'] = esc_html( $wp_filesystem->errors->get_error_message() );
		}

		wp_send_json_error( $status );
	}

	$result = delete_plugins( array( $plugin ) );

	if ( is_wp_error( $result ) ) {
		$status['errorMessage'] = $result->get_error_message();
		wp_send_json_error( $status );
	} elseif ( false === $result ) {
		$status['errorMessage'] = __( 'Plugin could not be deleted.' );
		wp_send_json_error( $status );
	}

	wp_send_json_success( $status );
}

/**
 * Handles searching plugins via AJAX.
 *
 * @since 4.6.0
 *
 * @global string $s Search term.
 */
function wp_ajax_search_plugins() {
	check_ajax_referer( 'updates' );

	// Ensure after_plugin_row_{$plugin_file} gets hooked.
	wp_plugin_update_rows();

	$pagenow = isset( $_POST['pagenow'] ) ? sanitize_key( $_POST['pagenow'] ) : '';
	if ( 'plugins-network' === $pagenow || 'plugins' === $pagenow ) {
		set_current_screen( $pagenow );
	}

	/** @var WP_Plugins_List_Table $wp_list_table */
	$wp_list_table = _get_list_table(
		'WP_Plugins_List_Table',
		array(
			'screen' => get_current_screen(),
		)
	);

	$status = array();

	if ( ! $wp_list_table->ajax_user_can() ) {
		$status['errorMessage'] = __( 'Sorry, you are not allowed to manage plugins for this site.' );
		wp_send_json_error( $status );
	}

	// Set the correct requester, so pagination works.
	$_SERVER['REQUEST_URI'] = add_query_arg(
		array_diff_key(
			$_POST,
			array(
				'_ajax_nonce' => null,
				'action'      => null,
			)
		),
		network_admin_url( 'plugins.php', 'relative' )
	);

	$GLOBALS['s'] = wp_unslash( $_POST['s'] );

	$wp_list_table->prepare_items();

	ob_start();
	$wp_list_table->display();
	$status['count'] = count( $wp_list_table->items );
	$status['items'] = ob_get_clean();

	wp_send_json_success( $status );
}

/**
 * Handles searching plugins to install via AJAX.
 *
 * @since 4.6.0
 */
function wp_ajax_search_install_plugins() {
	check_ajax_referer( 'updates' );

	$pagenow = isset( $_POST['pagenow'] ) ? sanitize_key( $_POST['pagenow'] ) : '';
	if ( 'plugin-install-network' === $pagenow || 'plugin-install' === $pagenow ) {
		set_current_screen( $pagenow );
	}

	/** @var WP_Plugin_Install_List_Table $wp_list_table */
	$wp_list_table = _get_list_table(
		'WP_Plugin_Install_List_Table',
		array(
			'screen' => get_current_screen(),
		)
	);

	$status = array();

	if ( ! $wp_list_table->ajax_user_can() ) {
		$status['errorMessage'] = __( 'Sorry, you are not allowed to manage plugins for this site.' );
		wp_send_json_error( $status );
	}

	// Set the correct requester, so pagination works.
	$_SERVER['REQUEST_URI'] = add_query_arg(
		array_diff_key(
			$_POST,
			array(
				'_ajax_nonce' => null,
				'action'      => null,
			)
		),
		network_admin_url( 'plugin-install.php', 'relative' )
	);

	$wp_list_table->prepare_items();

	ob_start();
	$wp_list_table->display();
	$status['count'] = (int) $wp_list_table->get_pagination_arg( 'total_items' );
	$status['items'] = ob_get_clean();

	wp_send_json_success( $status );
}

/**
 * Handles editing a theme or plugin file via AJAX.
 *
 * @since 4.9.0
 *
 * @see wp_edit_theme_plugin_file()
 */
function wp_ajax_edit_theme_plugin_file() {
	$r = wp_edit_theme_plugin_file( wp_unslash( $_POST ) ); // Validation of args is done in wp_edit_theme_plugin_file().

	if ( is_wp_error( $r ) ) {
		wp_send_json_error(
			array_merge(
				array(
					'code'    => $r->get_error_code(),
					'message' => $r->get_error_message(),
				),
				(array) $r->get_error_data()
			)
		);
	} else {
		wp_send_json_success(
			array(
				'message' => __( 'File edited successfully.' ),
			)
		);
	}
}

/**
 * Handles exporting a user's personal data via AJAX.
 *
 * @since 4.9.6
 */
function wp_ajax_wp_privacy_export_personal_data() {

	if ( empty( $_POST['id'] ) ) {
		wp_send_json_error( __( 'Missing request ID.' ) );
	}

	$request_id = (int) $_POST['id'];

	if ( $request_id < 1 ) {
		wp_send_json_error( __( 'Invalid request ID.' ) );
	}

	if ( ! current_user_can( 'export_others_personal_data' ) ) {
		wp_send_json_error( __( 'Sorry, you are not allowed to perform this action.' ) );
	}

	check_ajax_referer( 'wp-privacy-export-personal-data-' . $request_id, 'security' );

	// Get the request.
	$request = wp_get_user_request( $request_id );

	if ( ! $request || 'export_personal_data' !== $request->action_name ) {
		wp_send_json_error( __( 'Invalid request type.' ) );
	}

	$email_address = $request->email;
	if ( ! is_email( $email_address ) ) {
		wp_send_json_error( __( 'A valid email address must be given.' ) );
	}

	if ( ! isset( $_POST['exporter'] ) ) {
		wp_send_json_error( __( 'Missing exporter index.' ) );
	}

	$exporter_index = (int) $_POST['exporter'];

	if ( ! isset( $_POST['page'] ) ) {
		wp_send_json_error( __( 'Missing page index.' ) );
	}

	$page = (int) $_POST['page'];

	$send_as_email = isset( $_POST['sendAsEmail'] ) ? ( 'true' === $_POST['sendAsEmail'] ) : false;

	/**
	 * Filters the array of exporter callbacks.
	 *
	 * @since 4.9.6
	 *
	 * @param array $args {
	 *     An array of callable exporters of personal data. Default empty array.
	 *
	 *     @type array ...$0 {
	 *         Array of personal data exporters.
	 *
	 *         @type callable $callback               Callable exporter function that accepts an
	 *                                                email address and a page number and returns an
	 *                                                array of name => value pairs of personal data.
	 *         @type string   $exporter_friendly_name Translated user facing friendly name for the
	 *                                                exporter.
	 *     }
	 * }
	 */
	$exporters = apply_filters( 'wp_privacy_personal_data_exporters', array() );

	if ( ! is_array( $exporters ) ) {
		wp_send_json_error( __( 'An exporter has improperly used the registration filter.' ) );
	}

	// Do we have any registered exporters?
	if ( 0 < count( $exporters ) ) {
		if ( $exporter_index < 1 ) {
			wp_send_json_error( __( 'Exporter index cannot be negative.' ) );
		}

		if ( $exporter_index > count( $exporters ) ) {
			wp_send_json_error( __( 'Exporter index is out of range.' ) );
		}

		if ( $page < 1 ) {
			wp_send_json_error( __( 'Page index cannot be less than one.' ) );
		}

		$exporter_keys = array_keys( $exporters );
		$exporter_key  = $exporter_keys[ $exporter_index - 1 ];
		$exporter      = $exporters[ $exporter_key ];

		if ( ! is_array( $exporter ) ) {
			wp_send_json_error(
				/* translators: %s: Exporter array index. */
				sprintf( __( 'Expected an array describing the exporter at index %s.' ), $exporter_key )
			);
		}

		if ( ! array_key_exists( 'exporter_friendly_name', $exporter ) ) {
			wp_send_json_error(
				/* translators: %s: Exporter array index. */
				sprintf( __( 'Exporter array at index %s does not include a friendly name.' ), $exporter_key )
			);
		}

		$exporter_friendly_name = $exporter['exporter_friendly_name'];

		if ( ! array_key_exists( 'callback', $exporter ) ) {
			wp_send_json_error(
				/* translators: %s: Exporter friendly name. */
				sprintf( __( 'Exporter does not include a callback: %s.' ), esc_html( $exporter_friendly_name ) )
			);
		}

		if ( ! is_callable( $exporter['callback'] ) ) {
			wp_send_json_error(
				/* translators: %s: Exporter friendly name. */
				sprintf( __( 'Exporter callback is not a valid callback: %s.' ), esc_html( $exporter_friendly_name ) )
			);
		}

		$callback = $exporter['callback'];
		$response = call_user_func( $callback, $email_address, $page );

		if ( is_wp_error( $response ) ) {
			wp_send_json_error( $response );
		}

		if ( ! is_array( $response ) ) {
			wp_send_json_error(
				/* translators: %s: Exporter friendly name. */
				sprintf( __( 'Expected response as an array from exporter: %s.' ), esc_html( $exporter_friendly_name ) )
			);
		}

		if ( ! array_key_exists( 'data', $response ) ) {
			wp_send_json_error(
				/* translators: %s: Exporter friendly name. */
				sprintf( __( 'Expected data in response array from exporter: %s.' ), esc_html( $exporter_friendly_name ) )
			);
		}

		if ( ! is_array( $response['data'] ) ) {
			wp_send_json_error(
				/* translators: %s: Exporter friendly name. */
				sprintf( __( 'Expected data array in response array from exporter: %s.' ), esc_html( $exporter_friendly_name ) )
			);
		}

		if ( ! array_key_exists( 'done', $response ) ) {
			wp_send_json_error(
				/* translators: %s: Exporter friendly name. */
				sprintf( __( 'Expected done (boolean) in response array from exporter: %s.' ), esc_html( $exporter_friendly_name ) )
			);
		}
	} else {
		// No exporters, so we're done.
		$exporter_key = '';

		$response = array(
			'data' => array(),
			'done' => true,
		);
	}

	/**
	 * Filters a page of personal data exporter data. Used to build the export report.
	 *
	 * Allows the export response to be consumed by destinations in addition to Ajax.
	 *
	 * @since 4.9.6
	 *
	 * @param array  $response        The personal data for the given exporter and page number.
	 * @param int    $exporter_index  The index of the exporter that provided this data.
	 * @param string $email_address   The email address associated with this personal data.
	 * @param int    $page            The page number for this response.
	 * @param int    $request_id      The privacy request post ID associated with this request.
	 * @param bool   $send_as_email   Whether the final results of the export should be emailed to the user.
	 * @param string $exporter_key    The key (slug) of the exporter that provided this data.
	 */
	$response = apply_filters( 'wp_privacy_personal_data_export_page', $response, $exporter_index, $email_address, $page, $request_id, $send_as_email, $exporter_key );

	if ( is_wp_error( $response ) ) {
		wp_send_json_error( $response );
	}

	wp_send_json_success( $response );
}

/**
 * Handles erasing personal data via AJAX.
 *
 * @since 4.9.6
 */
function wp_ajax_wp_privacy_erase_personal_data() {

	if ( empty( $_POST['id'] ) ) {
		wp_send_json_error( __( 'Missing request ID.' ) );
	}

	$request_id = (int) $_POST['id'];

	if ( $request_id < 1 ) {
		wp_send_json_error( __( 'Invalid request ID.' ) );
	}

	// Both capabilities are required to avoid confusion, see `_wp_personal_data_removal_page()`.
	if ( ! current_user_can( 'erase_others_personal_data' ) || ! current_user_can( 'delete_users' ) ) {
		wp_send_json_error( __( 'Sorry, you are not allowed to perform this action.' ) );
	}

	check_ajax_referer( 'wp-privacy-erase-personal-data-' . $request_id, 'security' );

	// Get the request.
	$request = wp_get_user_request( $request_id );

	if ( ! $request || 'remove_personal_data' !== $request->action_name ) {
		wp_send_json_error( __( 'Invalid request type.' ) );
	}

	$email_address = $request->email;

	if ( ! is_email( $email_address ) ) {
		wp_send_json_error( __( 'Invalid email address in request.' ) );
	}

	if ( ! isset( $_POST['eraser'] ) ) {
		wp_send_json_error( __( 'Missing eraser index.' ) );
	}

	$eraser_index = (int) $_POST['eraser'];

	if ( ! isset( $_POST['page'] ) ) {
		wp_send_json_error( __( 'Missing page index.' ) );
	}

	$page = (int) $_POST['page'];

	/**
	 * Filters the array of personal data eraser callbacks.
	 *
	 * @since 4.9.6
	 *
	 * @param array $args {
	 *     An array of callable erasers of personal data. Default empty array.
	 *
	 *     @type array ...$0 {
	 *         Array of personal data exporters.
	 *
	 *         @type callable $callback               Callable eraser that accepts an email address and a page
	 *                                                number, and returns an array with boolean values for
	 *                                                whether items were removed or retained and any messages
	 *                                                from the eraser, as well as if additional pages are
	 *                                                available.
	 *         @type string   $exporter_friendly_name Translated user facing friendly name for the eraser.
	 *     }
	 * }
	 */
	$erasers = apply_filters( 'wp_privacy_personal_data_erasers', array() );

	// Do we have any registered erasers?
	if ( 0 < count( $erasers ) ) {

		if ( $eraser_index < 1 ) {
			wp_send_json_error( __( 'Eraser index cannot be less than one.' ) );
		}

		if ( $eraser_index > count( $erasers ) ) {
			wp_send_json_error( __( 'Eraser index is out of range.' ) );
		}

		if ( $page < 1 ) {
			wp_send_json_error( __( 'Page index cannot be less than one.' ) );
		}

		$eraser_keys = array_keys( $erasers );
		$eraser_key  = $eraser_keys[ $eraser_index - 1 ];
		$eraser      = $erasers[ $eraser_key ];

		if ( ! is_array( $eraser ) ) {
			/* translators: %d: Eraser array index. */
			wp_send_json_error( sprintf( __( 'Expected an array describing the eraser at index %d.' ), $eraser_index ) );
		}

		if ( ! array_key_exists( 'eraser_friendly_name', $eraser ) ) {
			/* translators: %d: Eraser array index. */
			wp_send_json_error( sprintf( __( 'Eraser array at index %d does not include a friendly name.' ), $eraser_index ) );
		}

		$eraser_friendly_name = $eraser['eraser_friendly_name'];

		if ( ! array_key_exists( 'callback', $eraser ) ) {
			wp_send_json_error(
				sprintf(
					/* translators: %s: Eraser friendly name. */
					__( 'Eraser does not include a callback: %s.' ),
					esc_html( $eraser_friendly_name )
				)
			);
		}

		if ( ! is_callable( $eraser['callback'] ) ) {
			wp_send_json_error(
				sprintf(
					/* translators: %s: Eraser friendly name. */
					__( 'Eraser callback is not valid: %s.' ),
					esc_html( $eraser_friendly_name )
				)
			);
		}

		$callback = $eraser['callback'];
		$response = call_user_func( $callback, $email_address, $page );

		if ( is_wp_error( $response ) ) {
			wp_send_json_error( $response );
		}

		if ( ! is_array( $response ) ) {
			wp_send_json_error(
				sprintf(
					/* translators: 1: Eraser friendly name, 2: Eraser array index. */
					__( 'Did not receive array from %1$s eraser (index %2$d).' ),
					esc_html( $eraser_friendly_name ),
					$eraser_index
				)
			);
		}

		if ( ! array_key_exists( 'items_removed', $response ) ) {
			wp_send_json_error(
				sprintf(
					/* translators: 1: Eraser friendly name, 2: Eraser array index. */
					__( 'Expected items_removed key in response array from %1$s eraser (index %2$d).' ),
					esc_html( $eraser_friendly_name ),
					$eraser_index
				)
			);
		}

		if ( ! array_key_exists( 'items_retained', $response ) ) {
			wp_send_json_error(
				sprintf(
					/* translators: 1: Eraser friendly name, 2: Eraser array index. */
					__( 'Expected items_retained key in response array from %1$s eraser (index %2$d).' ),
					esc_html( $eraser_friendly_name ),
					$eraser_index
				)
			);
		}

		if ( ! array_key_exists( 'messages', $response ) ) {
			wp_send_json_error(
				sprintf(
					/* translators: 1: Eraser friendly name, 2: Eraser array index. */
					__( 'Expected messages key in response array from %1$s eraser (index %2$d).' ),
					esc_html( $eraser_friendly_name ),
					$eraser_index
				)
			);
		}

		if ( ! is_array( $response['messages'] ) ) {
			wp_send_json_error(
				sprintf(
					/* translators: 1: Eraser friendly name, 2: Eraser array index. */
					__( 'Expected messages key to reference an array in response array from %1$s eraser (index %2$d).' ),
					esc_html( $eraser_friendly_name ),
					$eraser_index
				)
			);
		}

		if ( ! array_key_exists( 'done', $response ) ) {
			wp_send_json_error(
				sprintf(
					/* translators: 1: Eraser friendly name, 2: Eraser array index. */
					__( 'Expected done flag in response array from %1$s eraser (index %2$d).' ),
					esc_html( $eraser_friendly_name ),
					$eraser_index
				)
			);
		}
	} else {
		// No erasers, so we're done.
		$eraser_key = '';

		$response = array(
			'items_removed'  => false,
			'items_retained' => false,
			'messages'       => array(),
			'done'           => true,
		);
	}

	/**
	 * Filters a page of personal data eraser data.
	 *
	 * Allows the erasure response to be consumed by destinations in addition to Ajax.
	 *
	 * @since 4.9.6
	 *
	 * @param array  $response        {
	 *     The personal data for the given exporter and page number.
	 *
	 *     @type bool     $items_removed  Whether items were actually removed or not.
	 *     @type bool     $items_retained Whether items were retained or not.
	 *     @type string[] $messages       An array of messages to add to the personal data export file.
	 *     @type bool     $done           Whether the eraser is finished or not.
	 * }
	 * @param int    $eraser_index    The index of the eraser that provided this data.
	 * @param string $email_address   The email address associated with this personal data.
	 * @param int    $page            The page number for this response.
	 * @param int    $request_id      The privacy request post ID associated with this request.
	 * @param string $eraser_key      The key (slug) of the eraser that provided this data.
	 */
	$response = apply_filters( 'wp_privacy_personal_data_erasure_page', $response, $eraser_index, $email_address, $page, $request_id, $eraser_key );

	if ( is_wp_error( $response ) ) {
		wp_send_json_error( $response );
	}

	wp_send_json_success( $response );
}

/**
 * Handles site health checks on server communication via AJAX.
 *
 * @since 5.2.0
 * @deprecated 5.6.0 Use WP_REST_Site_Health_Controller::test_dotorg_communication()
 * @see WP_REST_Site_Health_Controller::test_dotorg_communication()
 */
function wp_ajax_health_check_dotorg_communication() {
	_doing_it_wrong(
		'wp_ajax_health_check_dotorg_communication',
		sprintf(
			/* translators: 1: The Site Health action that is no longer used by core. 2: The new function that replaces it. */
			__( 'The Site Health check for %1$s has been replaced with %2$s.' ),
			'wp_ajax_health_check_dotorg_communication',
			'WP_REST_Site_Health_Controller::test_dotorg_communication'
		),
		'5.6.0'
	);

	check_ajax_referer( 'health-check-site-status' );

	if ( ! current_user_can( 'view_site_health_checks' ) ) {
		wp_send_json_error();
	}

	if ( ! class_exists( 'WP_Site_Health' ) ) {
		require_once ABSPATH . 'wp-admin/includes/class-wp-site-health.php';
	}

	$site_health = WP_Site_Health::get_instance();
	wp_send_json_success( $site_health->get_test_dotorg_communication() );
}

/**
 * Handles site health checks on background updates via AJAX.
 *
 * @since 5.2.0
 * @deprecated 5.6.0 Use WP_REST_Site_Health_Controller::test_background_updates()
 * @see WP_REST_Site_Health_Controller::test_background_updates()
 */
function wp_ajax_health_check_background_updates() {
	_doing_it_wrong(
		'wp_ajax_health_check_background_updates',
		sprintf(
			/* translators: 1: The Site Health action that is no longer used by core. 2: The new function that replaces it. */
			__( 'The Site Health check for %1$s has been replaced with %2$s.' ),
			'wp_ajax_health_check_background_updates',
			'WP_REST_Site_Health_Controller::test_background_updates'
		),
		'5.6.0'
	);

	check_ajax_referer( 'health-check-site-status' );

	if ( ! current_user_can( 'view_site_health_checks' ) ) {
		wp_send_json_error();
	}

	if ( ! class_exists( 'WP_Site_Health' ) ) {
		require_once ABSPATH . 'wp-admin/includes/class-wp-site-health.php';
	}

	$site_health = WP_Site_Health::get_instance();
	wp_send_json_success( $site_health->get_test_background_updates() );
}

/**
 * Handles site health checks on loopback requests via AJAX.
 *
 * @since 5.2.0
 * @deprecated 5.6.0 Use WP_REST_Site_Health_Controller::test_loopback_requests()
 * @see WP_REST_Site_Health_Controller::test_loopback_requests()
 */
function wp_ajax_health_check_loopback_requests() {
	_doing_it_wrong(
		'wp_ajax_health_check_loopback_requests',
		sprintf(
			/* translators: 1: The Site Health action that is no longer used by core. 2: The new function that replaces it. */
			__( 'The Site Health check for %1$s has been replaced with %2$s.' ),
			'wp_ajax_health_check_loopback_requests',
			'WP_REST_Site_Health_Controller::test_loopback_requests'
		),
		'5.6.0'
	);

	check_ajax_referer( 'health-check-site-status' );

	if ( ! current_user_can( 'view_site_health_checks' ) ) {
		wp_send_json_error();
	}

	if ( ! class_exists( 'WP_Site_Health' ) ) {
		require_once ABSPATH . 'wp-admin/includes/class-wp-site-health.php';
	}

	$site_health = WP_Site_Health::get_instance();
	wp_send_json_success( $site_health->get_test_loopback_requests() );
}

/**
 * Handles site health check to update the result status via AJAX.
 *
 * @since 5.2.0
 */
function wp_ajax_health_check_site_status_result() {
	check_ajax_referer( 'health-check-site-status-result' );

	if ( ! current_user_can( 'view_site_health_checks' ) ) {
		wp_send_json_error();
	}

	set_transient( 'health-check-site-status-result', wp_json_encode( $_POST['counts'] ) );

	wp_send_json_success();
}

/**
 * Handles site health check to get directories and database sizes via AJAX.
 *
 * @since 5.2.0
 * @deprecated 5.6.0 Use WP_REST_Site_Health_Controller::get_directory_sizes()
 * @see WP_REST_Site_Health_Controller::get_directory_sizes()
 */
function wp_ajax_health_check_get_sizes() {
	_doing_it_wrong(
		'wp_ajax_health_check_get_sizes',
		sprintf(
			/* translators: 1: The Site Health action that is no longer used by core. 2: The new function that replaces it. */
			__( 'The Site Health check for %1$s has been replaced with %2$s.' ),
			'wp_ajax_health_check_get_sizes',
			'WP_REST_Site_Health_Controller::get_directory_sizes'
		),
		'5.6.0'
	);

	check_ajax_referer( 'health-check-site-status-result' );

	if ( ! current_user_can( 'view_site_health_checks' ) || is_multisite() ) {
		wp_send_json_error();
	}

	if ( ! class_exists( 'WP_Debug_Data' ) ) {
		require_once ABSPATH . 'wp-admin/includes/class-wp-debug-data.php';
	}

	$sizes_data = WP_Debug_Data::get_sizes();
	$all_sizes  = array( 'raw' => 0 );

	foreach ( $sizes_data as $name => $value ) {
		$name = sanitize_text_field( $name );
		$data = array();

		if ( isset( $value['size'] ) ) {
			if ( is_string( $value['size'] ) ) {
				$data['size'] = sanitize_text_field( $value['size'] );
			} else {
				$data['size'] = (int) $value['size'];
			}
		}

		if ( isset( $value['debug'] ) ) {
			if ( is_string( $value['debug'] ) ) {
				$data['debug'] = sanitize_text_field( $value['debug'] );
			} else {
				$data['debug'] = (int) $value['debug'];
			}
		}

		if ( ! empty( $value['raw'] ) ) {
			$data['raw'] = (int) $value['raw'];
		}

		$all_sizes[ $name ] = $data;
	}

	if ( isset( $all_sizes['total_size']['debug'] ) && 'not available' === $all_sizes['total_size']['debug'] ) {
		wp_send_json_error( $all_sizes );
	}

	wp_send_json_success( $all_sizes );
}

/**
 * Handles renewing the REST API nonce via AJAX.
 *
 * @since 5.3.0
 */
function wp_ajax_rest_nonce() {
	exit( wp_create_nonce( 'wp_rest' ) );
}

/**
 * Handles enabling or disable plugin and theme auto-updates via AJAX.
 *
 * @since 5.5.0
 */
function wp_ajax_toggle_auto_updates() {
	check_ajax_referer( 'updates' );

	if ( empty( $_POST['type'] ) || empty( $_POST['asset'] ) || empty( $_POST['state'] ) ) {
		wp_send_json_error( array( 'error' => __( 'Invalid data. No selected item.' ) ) );
	}

	$asset = sanitize_text_field( urldecode( $_POST['asset'] ) );

	if ( 'enable' !== $_POST['state'] && 'disable' !== $_POST['state'] ) {
		wp_send_json_error( array( 'error' => __( 'Invalid data. Unknown state.' ) ) );
	}
	$state = $_POST['state'];

	if ( 'plugin' !== $_POST['type'] && 'theme' !== $_POST['type'] ) {
		wp_send_json_error( array( 'error' => __( 'Invalid data. Unknown type.' ) ) );
	}
	$type = $_POST['type'];

	switch ( $type ) {
		case 'plugin':
			if ( ! current_user_can( 'update_plugins' ) ) {
				$error_message = __( 'Sorry, you are not allowed to modify plugins.' );
				wp_send_json_error( array( 'error' => $error_message ) );
			}

			$option = 'auto_update_plugins';
			/** This filter is documented in wp-admin/includes/class-wp-plugins-list-table.php */
			$all_items = apply_filters( 'all_plugins', get_plugins() );
			break;
		case 'theme':
			if ( ! current_user_can( 'update_themes' ) ) {
				$error_message = __( 'Sorry, you are not allowed to modify themes.' );
				wp_send_json_error( array( 'error' => $error_message ) );
			}

			$option    = 'auto_update_themes';
			$all_items = wp_get_themes();
			break;
		default:
			wp_send_json_error( array( 'error' => __( 'Invalid data. Unknown type.' ) ) );
	}

	if ( ! array_key_exists( $asset, $all_items ) ) {
		$error_message = __( 'Invalid data. The item does not exist.' );
		wp_send_json_error( array( 'error' => $error_message ) );
	}

	$auto_updates = (array) get_site_option( $option, array() );

	if ( 'disable' === $state ) {
		$auto_updates = array_diff( $auto_updates, array( $asset ) );
	} else {
		$auto_updates[] = $asset;
		$auto_updates   = array_unique( $auto_updates );
	}

	// Remove items that have been deleted since the site option was last updated.
	$auto_updates = array_intersect( $auto_updates, array_keys( $all_items ) );

	update_site_option( $option, $auto_updates );

	wp_send_json_success();
}

/**
 * Handles sending a password reset link via AJAX.
 *
 * @since 5.7.0
 */
function wp_ajax_send_password_reset() {

	// Validate the nonce for this action.
	$user_id = isset( $_POST['user_id'] ) ? (int) $_POST['user_id'] : 0;
	check_ajax_referer( 'reset-password-for-' . $user_id, 'nonce' );

	// Verify user capabilities.
	if ( ! current_user_can( 'edit_user', $user_id ) ) {
		wp_send_json_error( __( 'Cannot send password reset, permission denied.' ) );
	}

	// Send the password reset link.
	$user    = get_userdata( $user_id );
	$results = retrieve_password( $user->user_login );

	if ( true === $results ) {
		wp_send_json_success(
			/* translators: %s: User's display name. */
			sprintf( __( 'A password reset link was emailed to %s.' ), $user->display_name )
		);
	} else {
		wp_send_json_error( $results->get_error_message() );
	}
}
class-wp-upgrader.php000064400000135551151212616040010625 0ustar00<?php
/**
 * Upgrade API: WP_Upgrader class
 *
 * Requires skin classes and WP_Upgrader subclasses for backward compatibility.
 *
 * @package WordPress
 * @subpackage Upgrader
 * @since 2.8.0
 */

/** WP_Upgrader_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader-skin.php';

/** Plugin_Upgrader_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-plugin-upgrader-skin.php';

/** Theme_Upgrader_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-theme-upgrader-skin.php';

/** Bulk_Upgrader_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-bulk-upgrader-skin.php';

/** Bulk_Plugin_Upgrader_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-bulk-plugin-upgrader-skin.php';

/** Bulk_Theme_Upgrader_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-bulk-theme-upgrader-skin.php';

/** Plugin_Installer_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-plugin-installer-skin.php';

/** Theme_Installer_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-theme-installer-skin.php';

/** Language_Pack_Upgrader_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-language-pack-upgrader-skin.php';

/** Automatic_Upgrader_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-automatic-upgrader-skin.php';

/** WP_Ajax_Upgrader_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-wp-ajax-upgrader-skin.php';

/**
 * Core class used for upgrading/installing a local set of files via
 * the Filesystem Abstraction classes from a Zip file.
 *
 * @since 2.8.0
 */
#[AllowDynamicProperties]
class WP_Upgrader {

	/**
	 * The error/notification strings used to update the user on the progress.
	 *
	 * @since 2.8.0
	 * @var array $strings
	 */
	public $strings = array();

	/**
	 * The upgrader skin being used.
	 *
	 * @since 2.8.0
	 * @var Automatic_Upgrader_Skin|WP_Upgrader_Skin $skin
	 */
	public $skin = null;

	/**
	 * The result of the installation.
	 *
	 * This is set by WP_Upgrader::install_package(), only when the package is installed
	 * successfully. It will then be an array, unless a WP_Error is returned by the
	 * {@see 'upgrader_post_install'} filter. In that case, the WP_Error will be assigned to
	 * it.
	 *
	 * @since 2.8.0
	 *
	 * @var array|WP_Error $result {
	 *     @type string $source             The full path to the source the files were installed from.
	 *     @type string $source_files       List of all the files in the source directory.
	 *     @type string $destination        The full path to the installation destination folder.
	 *     @type string $destination_name   The name of the destination folder, or empty if `$destination`
	 *                                      and `$local_destination` are the same.
	 *     @type string $local_destination  The full local path to the destination folder. This is usually
	 *                                      the same as `$destination`.
	 *     @type string $remote_destination The full remote path to the destination folder
	 *                                      (i.e., from `$wp_filesystem`).
	 *     @type bool   $clear_destination  Whether the destination folder was cleared.
	 * }
	 */
	public $result = array();

	/**
	 * The total number of updates being performed.
	 *
	 * Set by the bulk update methods.
	 *
	 * @since 3.0.0
	 * @var int $update_count
	 */
	public $update_count = 0;

	/**
	 * The current update if multiple updates are being performed.
	 *
	 * Used by the bulk update methods, and incremented for each update.
	 *
	 * @since 3.0.0
	 * @var int
	 */
	public $update_current = 0;

	/**
	 * Stores the list of plugins or themes added to temporary backup directory.
	 *
	 * Used by the rollback functions.
	 *
	 * @since 6.3.0
	 * @var array
	 */
	private $temp_backups = array();

	/**
	 * Stores the list of plugins or themes to be restored from temporary backup directory.
	 *
	 * Used by the rollback functions.
	 *
	 * @since 6.3.0
	 * @var array
	 */
	private $temp_restores = array();

	/**
	 * Construct the upgrader with a skin.
	 *
	 * @since 2.8.0
	 *
	 * @param WP_Upgrader_Skin $skin The upgrader skin to use. Default is a WP_Upgrader_Skin
	 *                               instance.
	 */
	public function __construct( $skin = null ) {
		if ( null === $skin ) {
			$this->skin = new WP_Upgrader_Skin();
		} else {
			$this->skin = $skin;
		}
	}

	/**
	 * Initializes the upgrader.
	 *
	 * This will set the relationship between the skin being used and this upgrader,
	 * and also add the generic strings to `WP_Upgrader::$strings`.
	 *
	 * Additionally, it will schedule a weekly task to clean up the temporary backup directory.
	 *
	 * @since 2.8.0
	 * @since 6.3.0 Added the `schedule_temp_backup_cleanup()` task.
	 */
	public function init() {
		$this->skin->set_upgrader( $this );
		$this->generic_strings();

		if ( ! wp_installing() ) {
			$this->schedule_temp_backup_cleanup();
		}
	}

	/**
	 * Schedules the cleanup of the temporary backup directory.
	 *
	 * @since 6.3.0
	 */
	protected function schedule_temp_backup_cleanup() {
		if ( false === wp_next_scheduled( 'wp_delete_temp_updater_backups' ) ) {
			wp_schedule_event( time(), 'weekly', 'wp_delete_temp_updater_backups' );
		}
	}

	/**
	 * Adds the generic strings to WP_Upgrader::$strings.
	 *
	 * @since 2.8.0
	 */
	public function generic_strings() {
		$this->strings['bad_request']    = __( 'Invalid data provided.' );
		$this->strings['fs_unavailable'] = __( 'Could not access filesystem.' );
		$this->strings['fs_error']       = __( 'Filesystem error.' );
		$this->strings['fs_no_root_dir'] = __( 'Unable to locate WordPress root directory.' );
		/* translators: %s: Directory name. */
		$this->strings['fs_no_content_dir'] = sprintf( __( 'Unable to locate WordPress content directory (%s).' ), 'wp-content' );
		$this->strings['fs_no_plugins_dir'] = __( 'Unable to locate WordPress plugin directory.' );
		$this->strings['fs_no_themes_dir']  = __( 'Unable to locate WordPress theme directory.' );
		/* translators: %s: Directory name. */
		$this->strings['fs_no_folder'] = __( 'Unable to locate needed folder (%s).' );

		$this->strings['no_package']           = __( 'Package not available.' );
		$this->strings['download_failed']      = __( 'Download failed.' );
		$this->strings['installing_package']   = __( 'Installing the latest version&#8230;' );
		$this->strings['no_files']             = __( 'The package contains no files.' );
		$this->strings['folder_exists']        = __( 'Destination folder already exists.' );
		$this->strings['mkdir_failed']         = __( 'Could not create directory.' );
		$this->strings['incompatible_archive'] = __( 'The package could not be installed.' );
		$this->strings['files_not_writable']   = __( 'The update cannot be installed because some files could not be copied. This is usually due to inconsistent file permissions.' );
		$this->strings['dir_not_readable']     = __( 'A directory could not be read.' );

		$this->strings['maintenance_start'] = __( 'Enabling Maintenance mode&#8230;' );
		$this->strings['maintenance_end']   = __( 'Disabling Maintenance mode&#8230;' );

		/* translators: %s: upgrade-temp-backup */
		$this->strings['temp_backup_mkdir_failed'] = sprintf( __( 'Could not create the %s directory.' ), 'upgrade-temp-backup' );
		/* translators: %s: upgrade-temp-backup */
		$this->strings['temp_backup_move_failed'] = sprintf( __( 'Could not move the old version to the %s directory.' ), 'upgrade-temp-backup' );
		/* translators: %s: The plugin or theme slug. */
		$this->strings['temp_backup_restore_failed'] = __( 'Could not restore the original version of %s.' );
		/* translators: %s: The plugin or theme slug. */
		$this->strings['temp_backup_delete_failed'] = __( 'Could not delete the temporary backup directory for %s.' );
	}

	/**
	 * Connects to the filesystem.
	 *
	 * @since 2.8.0
	 *
	 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
	 *
	 * @param string[] $directories                  Optional. Array of directories. If any of these do
	 *                                               not exist, a WP_Error object will be returned.
	 *                                               Default empty array.
	 * @param bool     $allow_relaxed_file_ownership Whether to allow relaxed file ownership.
	 *                                               Default false.
	 * @return bool|WP_Error True if able to connect, false or a WP_Error otherwise.
	 */
	public function fs_connect( $directories = array(), $allow_relaxed_file_ownership = false ) {
		global $wp_filesystem;

		$credentials = $this->skin->request_filesystem_credentials( false, $directories[0], $allow_relaxed_file_ownership );
		if ( false === $credentials ) {
			return false;
		}

		if ( ! WP_Filesystem( $credentials, $directories[0], $allow_relaxed_file_ownership ) ) {
			$error = true;
			if ( is_object( $wp_filesystem ) && $wp_filesystem->errors->has_errors() ) {
				$error = $wp_filesystem->errors;
			}
			// Failed to connect. Error and request again.
			$this->skin->request_filesystem_credentials( $error, $directories[0], $allow_relaxed_file_ownership );
			return false;
		}

		if ( ! is_object( $wp_filesystem ) ) {
			return new WP_Error( 'fs_unavailable', $this->strings['fs_unavailable'] );
		}

		if ( is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->has_errors() ) {
			return new WP_Error( 'fs_error', $this->strings['fs_error'], $wp_filesystem->errors );
		}

		foreach ( (array) $directories as $dir ) {
			switch ( $dir ) {
				case ABSPATH:
					if ( ! $wp_filesystem->abspath() ) {
						return new WP_Error( 'fs_no_root_dir', $this->strings['fs_no_root_dir'] );
					}
					break;
				case WP_CONTENT_DIR:
					if ( ! $wp_filesystem->wp_content_dir() ) {
						return new WP_Error( 'fs_no_content_dir', $this->strings['fs_no_content_dir'] );
					}
					break;
				case WP_PLUGIN_DIR:
					if ( ! $wp_filesystem->wp_plugins_dir() ) {
						return new WP_Error( 'fs_no_plugins_dir', $this->strings['fs_no_plugins_dir'] );
					}
					break;
				case get_theme_root():
					if ( ! $wp_filesystem->wp_themes_dir() ) {
						return new WP_Error( 'fs_no_themes_dir', $this->strings['fs_no_themes_dir'] );
					}
					break;
				default:
					if ( ! $wp_filesystem->find_folder( $dir ) ) {
						return new WP_Error( 'fs_no_folder', sprintf( $this->strings['fs_no_folder'], esc_html( basename( $dir ) ) ) );
					}
					break;
			}
		}
		return true;
	}

	/**
	 * Downloads a package.
	 *
	 * @since 2.8.0
	 * @since 5.2.0 Added the `$check_signatures` parameter.
	 * @since 5.5.0 Added the `$hook_extra` parameter.
	 *
	 * @param string $package          The URI of the package. If this is the full path to an
	 *                                 existing local file, it will be returned untouched.
	 * @param bool   $check_signatures Whether to validate file signatures. Default false.
	 * @param array  $hook_extra       Extra arguments to pass to the filter hooks. Default empty array.
	 * @return string|WP_Error The full path to the downloaded package file, or a WP_Error object.
	 */
	public function download_package( $package, $check_signatures = false, $hook_extra = array() ) {
		/**
		 * Filters whether to return the package.
		 *
		 * @since 3.7.0
		 * @since 5.5.0 Added the `$hook_extra` parameter.
		 *
		 * @param bool        $reply      Whether to bail without returning the package.
		 *                                Default false.
		 * @param string      $package    The package file name.
		 * @param WP_Upgrader $upgrader   The WP_Upgrader instance.
		 * @param array       $hook_extra Extra arguments passed to hooked filters.
		 */
		$reply = apply_filters( 'upgrader_pre_download', false, $package, $this, $hook_extra );
		if ( false !== $reply ) {
			return $reply;
		}

		if ( ! preg_match( '!^(http|https|ftp)://!i', $package ) && file_exists( $package ) ) { // Local file or remote?
			return $package; // Must be a local file.
		}

		if ( empty( $package ) ) {
			return new WP_Error( 'no_package', $this->strings['no_package'] );
		}

		$this->skin->feedback( 'downloading_package', $package );

		$download_file = download_url( $package, 300, $check_signatures );

		if ( is_wp_error( $download_file ) && ! $download_file->get_error_data( 'softfail-filename' ) ) {
			return new WP_Error( 'download_failed', $this->strings['download_failed'], $download_file->get_error_message() );
		}

		return $download_file;
	}

	/**
	 * Unpacks a compressed package file.
	 *
	 * @since 2.8.0
	 *
	 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
	 *
	 * @param string $package        Full path to the package file.
	 * @param bool   $delete_package Optional. Whether to delete the package file after attempting
	 *                               to unpack it. Default true.
	 * @return string|WP_Error The path to the unpacked contents, or a WP_Error on failure.
	 */
	public function unpack_package( $package, $delete_package = true ) {
		global $wp_filesystem;

		$this->skin->feedback( 'unpack_package' );

		if ( ! $wp_filesystem->wp_content_dir() ) {
			return new WP_Error( 'fs_no_content_dir', $this->strings['fs_no_content_dir'] );
		}

		$upgrade_folder = $wp_filesystem->wp_content_dir() . 'upgrade/';

		// Clean up contents of upgrade directory beforehand.
		$upgrade_files = $wp_filesystem->dirlist( $upgrade_folder );
		if ( ! empty( $upgrade_files ) ) {
			foreach ( $upgrade_files as $file ) {
				$wp_filesystem->delete( $upgrade_folder . $file['name'], true );
			}
		}

		// We need a working directory - strip off any .tmp or .zip suffixes.
		$working_dir = $upgrade_folder . basename( basename( $package, '.tmp' ), '.zip' );

		// Clean up working directory.
		if ( $wp_filesystem->is_dir( $working_dir ) ) {
			$wp_filesystem->delete( $working_dir, true );
		}

		// Unzip package to working directory.
		$result = unzip_file( $package, $working_dir );

		// Once extracted, delete the package if required.
		if ( $delete_package ) {
			unlink( $package );
		}

		if ( is_wp_error( $result ) ) {
			$wp_filesystem->delete( $working_dir, true );
			if ( 'incompatible_archive' === $result->get_error_code() ) {
				return new WP_Error( 'incompatible_archive', $this->strings['incompatible_archive'], $result->get_error_data() );
			}
			return $result;
		}

		return $working_dir;
	}

	/**
	 * Flattens the results of WP_Filesystem_Base::dirlist() for iterating over.
	 *
	 * @since 4.9.0
	 *
	 * @param array  $nested_files Array of files as returned by WP_Filesystem_Base::dirlist().
	 * @param string $path         Relative path to prepend to child nodes. Optional.
	 * @return array A flattened array of the $nested_files specified.
	 */
	protected function flatten_dirlist( $nested_files, $path = '' ) {
		$files = array();

		foreach ( $nested_files as $name => $details ) {
			$files[ $path . $name ] = $details;

			// Append children recursively.
			if ( ! empty( $details['files'] ) ) {
				$children = $this->flatten_dirlist( $details['files'], $path . $name . '/' );

				// Merge keeping possible numeric keys, which array_merge() will reindex from 0..n.
				$files = $files + $children;
			}
		}

		return $files;
	}

	/**
	 * Clears the directory where this item is going to be installed into.
	 *
	 * @since 4.3.0
	 *
	 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
	 *
	 * @param string $remote_destination The location on the remote filesystem to be cleared.
	 * @return true|WP_Error True upon success, WP_Error on failure.
	 */
	public function clear_destination( $remote_destination ) {
		global $wp_filesystem;

		$files = $wp_filesystem->dirlist( $remote_destination, true, true );

		// False indicates that the $remote_destination doesn't exist.
		if ( false === $files ) {
			return true;
		}

		// Flatten the file list to iterate over.
		$files = $this->flatten_dirlist( $files );

		// Check all files are writable before attempting to clear the destination.
		$unwritable_files = array();

		// Check writability.
		foreach ( $files as $filename => $file_details ) {
			if ( ! $wp_filesystem->is_writable( $remote_destination . $filename ) ) {
				// Attempt to alter permissions to allow writes and try again.
				$wp_filesystem->chmod( $remote_destination . $filename, ( 'd' === $file_details['type'] ? FS_CHMOD_DIR : FS_CHMOD_FILE ) );
				if ( ! $wp_filesystem->is_writable( $remote_destination . $filename ) ) {
					$unwritable_files[] = $filename;
				}
			}
		}

		if ( ! empty( $unwritable_files ) ) {
			return new WP_Error( 'files_not_writable', $this->strings['files_not_writable'], implode( ', ', $unwritable_files ) );
		}

		if ( ! $wp_filesystem->delete( $remote_destination, true ) ) {
			return new WP_Error( 'remove_old_failed', $this->strings['remove_old_failed'] );
		}

		return true;
	}

	/**
	 * Install a package.
	 *
	 * Copies the contents of a package from a source directory, and installs them in
	 * a destination directory. Optionally removes the source. It can also optionally
	 * clear out the destination folder if it already exists.
	 *
	 * @since 2.8.0
	 * @since 6.2.0 Use move_dir() instead of copy_dir() when possible.
	 *
	 * @global WP_Filesystem_Base $wp_filesystem        WordPress filesystem subclass.
	 * @global string[]           $wp_theme_directories
	 *
	 * @param array|string $args {
	 *     Optional. Array or string of arguments for installing a package. Default empty array.
	 *
	 *     @type string $source                      Required path to the package source. Default empty.
	 *     @type string $destination                 Required path to a folder to install the package in.
	 *                                               Default empty.
	 *     @type bool   $clear_destination           Whether to delete any files already in the destination
	 *                                               folder. Default false.
	 *     @type bool   $clear_working               Whether to delete the files from the working directory
	 *                                               after copying them to the destination. Default false.
	 *     @type bool   $abort_if_destination_exists Whether to abort the installation if
	 *                                               the destination folder already exists. Default true.
	 *     @type array  $hook_extra                  Extra arguments to pass to the filter hooks called by
	 *                                               WP_Upgrader::install_package(). Default empty array.
	 * }
	 *
	 * @return array|WP_Error The result (also stored in `WP_Upgrader::$result`), or a WP_Error on failure.
	 */
	public function install_package( $args = array() ) {
		global $wp_filesystem, $wp_theme_directories;

		$defaults = array(
			'source'                      => '', // Please always pass this.
			'destination'                 => '', // ...and this.
			'clear_destination'           => false,
			'clear_working'               => false,
			'abort_if_destination_exists' => true,
			'hook_extra'                  => array(),
		);

		$args = wp_parse_args( $args, $defaults );

		// These were previously extract()'d.
		$source            = $args['source'];
		$destination       = $args['destination'];
		$clear_destination = $args['clear_destination'];

		/*
		 * Give the upgrade an additional 300 seconds (5 minutes) to ensure the install
		 * doesn't prematurely timeout having used up the maximum script execution time
		 * upacking and downloading in WP_Upgrader->run().
		 */
		if ( function_exists( 'set_time_limit' ) ) {
			set_time_limit( 300 );
		}

		if (
			( ! is_string( $source ) || '' === $source || trim( $source ) !== $source ) ||
			( ! is_string( $destination ) || '' === $destination || trim( $destination ) !== $destination )
		) {
			return new WP_Error( 'bad_request', $this->strings['bad_request'] );
		}
		$this->skin->feedback( 'installing_package' );

		/**
		 * Filters the installation response before the installation has started.
		 *
		 * Returning a value that could be evaluated as a `WP_Error` will effectively
		 * short-circuit the installation, returning that value instead.
		 *
		 * @since 2.8.0
		 *
		 * @param bool|WP_Error $response   Installation response.
		 * @param array         $hook_extra Extra arguments passed to hooked filters.
		 */
		$res = apply_filters( 'upgrader_pre_install', true, $args['hook_extra'] );

		if ( is_wp_error( $res ) ) {
			return $res;
		}

		// Retain the original source and destinations.
		$remote_source     = $args['source'];
		$local_destination = $destination;

		$dirlist = $wp_filesystem->dirlist( $remote_source );

		if ( false === $dirlist ) {
			return new WP_Error( 'source_read_failed', $this->strings['fs_error'], $this->strings['dir_not_readable'] );
		}

		$source_files       = array_keys( $dirlist );
		$remote_destination = $wp_filesystem->find_folder( $local_destination );

		// Locate which directory to copy to the new folder. This is based on the actual folder holding the files.
		if ( 1 === count( $source_files ) && $wp_filesystem->is_dir( trailingslashit( $args['source'] ) . $source_files[0] . '/' ) ) {
			// Only one folder? Then we want its contents.
			$source = trailingslashit( $args['source'] ) . trailingslashit( $source_files[0] );
		} elseif ( 0 === count( $source_files ) ) {
			// There are no files?
			return new WP_Error( 'incompatible_archive_empty', $this->strings['incompatible_archive'], $this->strings['no_files'] );
		} else {
			/*
			 * It's only a single file, the upgrader will use the folder name of this file as the destination folder.
			 * Folder name is based on zip filename.
			 */
			$source = trailingslashit( $args['source'] );
		}

		/**
		 * Filters the source file location for the upgrade package.
		 *
		 * @since 2.8.0
		 * @since 4.4.0 The $hook_extra parameter became available.
		 *
		 * @param string      $source        File source location.
		 * @param string      $remote_source Remote file source location.
		 * @param WP_Upgrader $upgrader      WP_Upgrader instance.
		 * @param array       $hook_extra    Extra arguments passed to hooked filters.
		 */
		$source = apply_filters( 'upgrader_source_selection', $source, $remote_source, $this, $args['hook_extra'] );

		if ( is_wp_error( $source ) ) {
			return $source;
		}

		if ( ! empty( $args['hook_extra']['temp_backup'] ) ) {
			$temp_backup = $this->move_to_temp_backup_dir( $args['hook_extra']['temp_backup'] );

			if ( is_wp_error( $temp_backup ) ) {
				return $temp_backup;
			}

			$this->temp_backups[] = $args['hook_extra']['temp_backup'];
		}

		// Has the source location changed? If so, we need a new source_files list.
		if ( $source !== $remote_source ) {
			$dirlist = $wp_filesystem->dirlist( $source );

			if ( false === $dirlist ) {
				return new WP_Error( 'new_source_read_failed', $this->strings['fs_error'], $this->strings['dir_not_readable'] );
			}

			$source_files = array_keys( $dirlist );
		}

		/*
		 * Protection against deleting files in any important base directories.
		 * Theme_Upgrader & Plugin_Upgrader also trigger this, as they pass the
		 * destination directory (WP_PLUGIN_DIR / wp-content/themes) intending
		 * to copy the directory into the directory, whilst they pass the source
		 * as the actual files to copy.
		 */
		$protected_directories = array( ABSPATH, WP_CONTENT_DIR, WP_PLUGIN_DIR, WP_CONTENT_DIR . '/themes' );

		if ( is_array( $wp_theme_directories ) ) {
			$protected_directories = array_merge( $protected_directories, $wp_theme_directories );
		}

		if ( in_array( $destination, $protected_directories, true ) ) {
			$remote_destination = trailingslashit( $remote_destination ) . trailingslashit( basename( $source ) );
			$destination        = trailingslashit( $destination ) . trailingslashit( basename( $source ) );
		}

		if ( $clear_destination ) {
			// We're going to clear the destination if there's something there.
			$this->skin->feedback( 'remove_old' );

			$removed = $this->clear_destination( $remote_destination );

			/**
			 * Filters whether the upgrader cleared the destination.
			 *
			 * @since 2.8.0
			 *
			 * @param true|WP_Error $removed            Whether the destination was cleared.
			 *                                          True upon success, WP_Error on failure.
			 * @param string        $local_destination  The local package destination.
			 * @param string        $remote_destination The remote package destination.
			 * @param array         $hook_extra         Extra arguments passed to hooked filters.
			 */
			$removed = apply_filters( 'upgrader_clear_destination', $removed, $local_destination, $remote_destination, $args['hook_extra'] );

			if ( is_wp_error( $removed ) ) {
				return $removed;
			}
		} elseif ( $args['abort_if_destination_exists'] && $wp_filesystem->exists( $remote_destination ) ) {
			/*
			 * If we're not clearing the destination folder and something exists there already, bail.
			 * But first check to see if there are actually any files in the folder.
			 */
			$_files = $wp_filesystem->dirlist( $remote_destination );
			if ( ! empty( $_files ) ) {
				$wp_filesystem->delete( $remote_source, true ); // Clear out the source files.
				return new WP_Error( 'folder_exists', $this->strings['folder_exists'], $remote_destination );
			}
		}

		/*
		 * If 'clear_working' is false, the source should not be removed, so use copy_dir() instead.
		 *
		 * Partial updates, like language packs, may want to retain the destination.
		 * If the destination exists or has contents, this may be a partial update,
		 * and the destination should not be removed, so use copy_dir() instead.
		 */
		if ( $args['clear_working']
			&& (
				// Destination does not exist or has no contents.
				! $wp_filesystem->exists( $remote_destination )
				|| empty( $wp_filesystem->dirlist( $remote_destination ) )
			)
		) {
			$result = move_dir( $source, $remote_destination, true );
		} else {
			// Create destination if needed.
			if ( ! $wp_filesystem->exists( $remote_destination ) ) {
				if ( ! $wp_filesystem->mkdir( $remote_destination, FS_CHMOD_DIR ) ) {
					return new WP_Error( 'mkdir_failed_destination', $this->strings['mkdir_failed'], $remote_destination );
				}
			}
			$result = copy_dir( $source, $remote_destination );
		}

		// Clear the working directory?
		if ( $args['clear_working'] ) {
			$wp_filesystem->delete( $remote_source, true );
		}

		if ( is_wp_error( $result ) ) {
			return $result;
		}

		$destination_name = basename( str_replace( $local_destination, '', $destination ) );
		if ( '.' === $destination_name ) {
			$destination_name = '';
		}

		$this->result = compact( 'source', 'source_files', 'destination', 'destination_name', 'local_destination', 'remote_destination', 'clear_destination' );

		/**
		 * Filters the installation response after the installation has finished.
		 *
		 * @since 2.8.0
		 *
		 * @param bool  $response   Installation response.
		 * @param array $hook_extra Extra arguments passed to hooked filters.
		 * @param array $result     Installation result data.
		 */
		$res = apply_filters( 'upgrader_post_install', true, $args['hook_extra'], $this->result );

		if ( is_wp_error( $res ) ) {
			$this->result = $res;
			return $res;
		}

		// Bombard the calling function will all the info which we've just used.
		return $this->result;
	}

	/**
	 * Runs an upgrade/installation.
	 *
	 * Attempts to download the package (if it is not a local file), unpack it, and
	 * install it in the destination folder.
	 *
	 * @since 2.8.0
	 *
	 * @param array $options {
	 *     Array or string of arguments for upgrading/installing a package.
	 *
	 *     @type string $package                     The full path or URI of the package to install.
	 *                                               Default empty.
	 *     @type string $destination                 The full path to the destination folder.
	 *                                               Default empty.
	 *     @type bool   $clear_destination           Whether to delete any files already in the
	 *                                               destination folder. Default false.
	 *     @type bool   $clear_working               Whether to delete the files from the working
	 *                                               directory after copying them to the destination.
	 *                                               Default true.
	 *     @type bool   $abort_if_destination_exists Whether to abort the installation if the destination
	 *                                               folder already exists. When true, `$clear_destination`
	 *                                               should be false. Default true.
	 *     @type bool   $is_multi                    Whether this run is one of multiple upgrade/installation
	 *                                               actions being performed in bulk. When true, the skin
	 *                                               WP_Upgrader::header() and WP_Upgrader::footer()
	 *                                               aren't called. Default false.
	 *     @type array  $hook_extra                  Extra arguments to pass to the filter hooks called by
	 *                                               WP_Upgrader::run().
	 * }
	 * @return array|false|WP_Error The result from self::install_package() on success, otherwise a WP_Error,
	 *                              or false if unable to connect to the filesystem.
	 */
	public function run( $options ) {

		$defaults = array(
			'package'                     => '', // Please always pass this.
			'destination'                 => '', // ...and this.
			'clear_destination'           => false,
			'clear_working'               => true,
			'abort_if_destination_exists' => true, // Abort if the destination directory exists. Pass clear_destination as false please.
			'is_multi'                    => false,
			'hook_extra'                  => array(), // Pass any extra $hook_extra args here, this will be passed to any hooked filters.
		);

		$options = wp_parse_args( $options, $defaults );

		/**
		 * Filters the package options before running an update.
		 *
		 * See also {@see 'upgrader_process_complete'}.
		 *
		 * @since 4.3.0
		 *
		 * @param array $options {
		 *     Options used by the upgrader.
		 *
		 *     @type string $package                     Package for update.
		 *     @type string $destination                 Update location.
		 *     @type bool   $clear_destination           Clear the destination resource.
		 *     @type bool   $clear_working               Clear the working resource.
		 *     @type bool   $abort_if_destination_exists Abort if the Destination directory exists.
		 *     @type bool   $is_multi                    Whether the upgrader is running multiple times.
		 *     @type array  $hook_extra {
		 *         Extra hook arguments.
		 *
		 *         @type string $action               Type of action. Default 'update'.
		 *         @type string $type                 Type of update process. Accepts 'plugin', 'theme', or 'core'.
		 *         @type bool   $bulk                 Whether the update process is a bulk update. Default true.
		 *         @type string $plugin               Path to the plugin file relative to the plugins directory.
		 *         @type string $theme                The stylesheet or template name of the theme.
		 *         @type string $language_update_type The language pack update type. Accepts 'plugin', 'theme',
		 *                                            or 'core'.
		 *         @type object $language_update      The language pack update offer.
		 *     }
		 * }
		 */
		$options = apply_filters( 'upgrader_package_options', $options );

		if ( ! $options['is_multi'] ) { // Call $this->header separately if running multiple times.
			$this->skin->header();
		}

		// Connect to the filesystem first.
		$res = $this->fs_connect( array( WP_CONTENT_DIR, $options['destination'] ) );
		// Mainly for non-connected filesystem.
		if ( ! $res ) {
			if ( ! $options['is_multi'] ) {
				$this->skin->footer();
			}
			return false;
		}

		$this->skin->before();

		if ( is_wp_error( $res ) ) {
			$this->skin->error( $res );
			$this->skin->after();
			if ( ! $options['is_multi'] ) {
				$this->skin->footer();
			}
			return $res;
		}

		/*
		 * Download the package. Note: If the package is the full path
		 * to an existing local file, it will be returned untouched.
		 */
		$download = $this->download_package( $options['package'], false, $options['hook_extra'] );

		/*
		 * Allow for signature soft-fail.
		 * WARNING: This may be removed in the future.
		 */
		if ( is_wp_error( $download ) && $download->get_error_data( 'softfail-filename' ) ) {

			// Don't output the 'no signature could be found' failure message for now.
			if ( 'signature_verification_no_signature' !== $download->get_error_code() || WP_DEBUG ) {
				// Output the failure error as a normal feedback, and not as an error.
				$this->skin->feedback( $download->get_error_message() );

				// Report this failure back to WordPress.org for debugging purposes.
				wp_version_check(
					array(
						'signature_failure_code' => $download->get_error_code(),
						'signature_failure_data' => $download->get_error_data(),
					)
				);
			}

			// Pretend this error didn't happen.
			$download = $download->get_error_data( 'softfail-filename' );
		}

		if ( is_wp_error( $download ) ) {
			$this->skin->error( $download );
			$this->skin->after();
			if ( ! $options['is_multi'] ) {
				$this->skin->footer();
			}
			return $download;
		}

		$delete_package = ( $download !== $options['package'] ); // Do not delete a "local" file.

		// Unzips the file into a temporary directory.
		$working_dir = $this->unpack_package( $download, $delete_package );
		if ( is_wp_error( $working_dir ) ) {
			$this->skin->error( $working_dir );
			$this->skin->after();
			if ( ! $options['is_multi'] ) {
				$this->skin->footer();
			}
			return $working_dir;
		}

		// With the given options, this installs it to the destination directory.
		$result = $this->install_package(
			array(
				'source'                      => $working_dir,
				'destination'                 => $options['destination'],
				'clear_destination'           => $options['clear_destination'],
				'abort_if_destination_exists' => $options['abort_if_destination_exists'],
				'clear_working'               => $options['clear_working'],
				'hook_extra'                  => $options['hook_extra'],
			)
		);

		/**
		 * Filters the result of WP_Upgrader::install_package().
		 *
		 * @since 5.7.0
		 *
		 * @param array|WP_Error $result     Result from WP_Upgrader::install_package().
		 * @param array          $hook_extra Extra arguments passed to hooked filters.
		 */
		$result = apply_filters( 'upgrader_install_package_result', $result, $options['hook_extra'] );

		$this->skin->set_result( $result );

		if ( is_wp_error( $result ) ) {
			// An automatic plugin update will have already performed its rollback.
			if ( ! empty( $options['hook_extra']['temp_backup'] ) ) {
				$this->temp_restores[] = $options['hook_extra']['temp_backup'];

				/*
				 * Restore the backup on shutdown.
				 * Actions running on `shutdown` are immune to PHP timeouts,
				 * so in case the failure was due to a PHP timeout,
				 * it will still be able to properly restore the previous version.
				 *
				 * Zero arguments are accepted as a string can sometimes be passed
				 * internally during actions, causing an error because
				 * `WP_Upgrader::restore_temp_backup()` expects an array.
				 */
				add_action( 'shutdown', array( $this, 'restore_temp_backup' ), 10, 0 );
			}
			$this->skin->error( $result );

			if ( ! method_exists( $this->skin, 'hide_process_failed' ) || ! $this->skin->hide_process_failed( $result ) ) {
				$this->skin->feedback( 'process_failed' );
			}
		} else {
			// Installation succeeded.
			$this->skin->feedback( 'process_success' );
		}

		$this->skin->after();

		// Clean up the backup kept in the temporary backup directory.
		if ( ! empty( $options['hook_extra']['temp_backup'] ) ) {
			// Delete the backup on `shutdown` to avoid a PHP timeout.
			add_action( 'shutdown', array( $this, 'delete_temp_backup' ), 100, 0 );
		}

		if ( ! $options['is_multi'] ) {

			/**
			 * Fires when the upgrader process is complete.
			 *
			 * See also {@see 'upgrader_package_options'}.
			 *
			 * @since 3.6.0
			 * @since 3.7.0 Added to WP_Upgrader::run().
			 * @since 4.6.0 `$translations` was added as a possible argument to `$hook_extra`.
			 *
			 * @param WP_Upgrader $upgrader   WP_Upgrader instance. In other contexts this might be a
			 *                                Theme_Upgrader, Plugin_Upgrader, Core_Upgrade, or Language_Pack_Upgrader instance.
			 * @param array       $hook_extra {
			 *     Array of bulk item update data.
			 *
			 *     @type string $action       Type of action. Default 'update'.
			 *     @type string $type         Type of update process. Accepts 'plugin', 'theme', 'translation', or 'core'.
			 *     @type bool   $bulk         Whether the update process is a bulk update. Default true.
			 *     @type array  $plugins      Array of the basename paths of the plugins' main files.
			 *     @type array  $themes       The theme slugs.
			 *     @type array  $translations {
			 *         Array of translations update data.
			 *
			 *         @type string $language The locale the translation is for.
			 *         @type string $type     Type of translation. Accepts 'plugin', 'theme', or 'core'.
			 *         @type string $slug     Text domain the translation is for. The slug of a theme/plugin or
			 *                                'default' for core translations.
			 *         @type string $version  The version of a theme, plugin, or core.
			 *     }
			 * }
			 */
			do_action( 'upgrader_process_complete', $this, $options['hook_extra'] );

			$this->skin->footer();
		}

		return $result;
	}

	/**
	 * Toggles maintenance mode for the site.
	 *
	 * Creates/deletes the maintenance file to enable/disable maintenance mode.
	 *
	 * @since 2.8.0
	 *
	 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
	 *
	 * @param bool $enable True to enable maintenance mode, false to disable.
	 */
	public function maintenance_mode( $enable = false ) {
		global $wp_filesystem;

		if ( ! $wp_filesystem ) {
			if ( ! function_exists( 'WP_Filesystem' ) ) {
				require_once ABSPATH . 'wp-admin/includes/file.php';
			}

			ob_start();
			$credentials = request_filesystem_credentials( '' );
			ob_end_clean();

			if ( false === $credentials || ! WP_Filesystem( $credentials ) ) {
				wp_trigger_error( __FUNCTION__, __( 'Could not access filesystem.' ) );
				return;
			}
		}

		$file = $wp_filesystem->abspath() . '.maintenance';

		if ( $enable ) {
			if ( ! wp_doing_cron() ) {
				$this->skin->feedback( 'maintenance_start' );
			}

			// Create maintenance file to signal that we are upgrading.
			$maintenance_string = '<?php $upgrading = ' . time() . '; ?>';
			$wp_filesystem->delete( $file );
			$wp_filesystem->put_contents( $file, $maintenance_string, FS_CHMOD_FILE );
		} elseif ( $wp_filesystem->exists( $file ) ) {
			if ( ! wp_doing_cron() ) {
				$this->skin->feedback( 'maintenance_end' );
			}

			$wp_filesystem->delete( $file );
		}
	}

	/**
	 * Creates a lock using WordPress options.
	 *
	 * @since 4.5.0
	 *
	 * @global wpdb $wpdb The WordPress database abstraction object.
	 *
	 * @param string $lock_name       The name of this unique lock.
	 * @param int    $release_timeout Optional. The duration in seconds to respect an existing lock.
	 *                                Default: 1 hour.
	 * @return bool False if a lock couldn't be created or if the lock is still valid. True otherwise.
	 */
	public static function create_lock( $lock_name, $release_timeout = null ) {
		global $wpdb;
		if ( ! $release_timeout ) {
			$release_timeout = HOUR_IN_SECONDS;
		}
		$lock_option = $lock_name . '.lock';

		// Try to lock.
		$lock_result = $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO `$wpdb->options` ( `option_name`, `option_value`, `autoload` ) VALUES (%s, %s, 'off') /* LOCK */", $lock_option, time() ) );

		if ( ! $lock_result ) {
			$lock_result = get_option( $lock_option );

			// If a lock couldn't be created, and there isn't a lock, bail.
			if ( ! $lock_result ) {
				return false;
			}

			// Check to see if the lock is still valid. If it is, bail.
			if ( $lock_result > ( time() - $release_timeout ) ) {
				return false;
			}

			// There must exist an expired lock, clear it and re-gain it.
			WP_Upgrader::release_lock( $lock_name );

			return WP_Upgrader::create_lock( $lock_name, $release_timeout );
		}

		// Update the lock, as by this point we've definitely got a lock, just need to fire the actions.
		update_option( $lock_option, time(), false );

		return true;
	}

	/**
	 * Releases an upgrader lock.
	 *
	 * @since 4.5.0
	 *
	 * @see WP_Upgrader::create_lock()
	 *
	 * @param string $lock_name The name of this unique lock.
	 * @return bool True if the lock was successfully released. False on failure.
	 */
	public static function release_lock( $lock_name ) {
		return delete_option( $lock_name . '.lock' );
	}

	/**
	 * Moves the plugin or theme being updated into a temporary backup directory.
	 *
	 * @since 6.3.0
	 *
	 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
	 *
	 * @param string[] $args {
	 *     Array of data for the temporary backup.
	 *
	 *     @type string $slug Plugin or theme slug.
	 *     @type string $src  Path to the root directory for plugins or themes.
	 *     @type string $dir  Destination subdirectory name. Accepts 'plugins' or 'themes'.
	 * }
	 *
	 * @return bool|WP_Error True on success, false on early exit, otherwise WP_Error.
	 */
	public function move_to_temp_backup_dir( $args ) {
		global $wp_filesystem;

		if ( empty( $args['slug'] ) || empty( $args['src'] ) || empty( $args['dir'] ) ) {
			return false;
		}

		/*
		 * Skip any plugin that has "." as its slug.
		 * A slug of "." will result in a `$src` value ending in a period.
		 *
		 * On Windows, this will cause the 'plugins' folder to be moved,
		 * and will cause a failure when attempting to call `mkdir()`.
		 */
		if ( '.' === $args['slug'] ) {
			return false;
		}

		if ( ! $wp_filesystem->wp_content_dir() ) {
			return new WP_Error( 'fs_no_content_dir', $this->strings['fs_no_content_dir'] );
		}

		$dest_dir = $wp_filesystem->wp_content_dir() . 'upgrade-temp-backup/';
		$sub_dir  = $dest_dir . $args['dir'] . '/';

		// Create the temporary backup directory if it does not exist.
		if ( ! $wp_filesystem->is_dir( $sub_dir ) ) {
			if ( ! $wp_filesystem->is_dir( $dest_dir ) ) {
				$wp_filesystem->mkdir( $dest_dir, FS_CHMOD_DIR );
			}

			if ( ! $wp_filesystem->mkdir( $sub_dir, FS_CHMOD_DIR ) ) {
				// Could not create the backup directory.
				return new WP_Error( 'fs_temp_backup_mkdir', $this->strings['temp_backup_mkdir_failed'] );
			}
		}

		$src_dir = $wp_filesystem->find_folder( $args['src'] );
		$src     = trailingslashit( $src_dir ) . $args['slug'];
		$dest    = $dest_dir . trailingslashit( $args['dir'] ) . $args['slug'];

		// Delete the temporary backup directory if it already exists.
		if ( $wp_filesystem->is_dir( $dest ) ) {
			$wp_filesystem->delete( $dest, true );
		}

		// Move to the temporary backup directory.
		$result = move_dir( $src, $dest, true );
		if ( is_wp_error( $result ) ) {
			return new WP_Error( 'fs_temp_backup_move', $this->strings['temp_backup_move_failed'] );
		}

		return true;
	}

	/**
	 * Restores the plugin or theme from temporary backup.
	 *
	 * @since 6.3.0
	 * @since 6.6.0 Added the `$temp_backups` parameter.
	 *
	 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
	 *
	 * @param array[] $temp_backups {
	 *     Optional. An array of temporary backups.
	 *
	 *     @type array ...$0 {
	 *         Information about the backup.
	 *
	 *         @type string $dir  The temporary backup location in the upgrade-temp-backup directory.
	 *         @type string $slug The item's slug.
	 *         @type string $src  The directory where the original is stored. For example, `WP_PLUGIN_DIR`.
	 *     }
	 * }
	 * @return bool|WP_Error True on success, false on early exit, otherwise WP_Error.
	 */
	public function restore_temp_backup( array $temp_backups = array() ) {
		global $wp_filesystem;

		$errors = new WP_Error();

		if ( empty( $temp_backups ) ) {
			$temp_backups = $this->temp_restores;
		}

		foreach ( $temp_backups as $args ) {
			if ( empty( $args['slug'] ) || empty( $args['src'] ) || empty( $args['dir'] ) ) {
				return false;
			}

			if ( ! $wp_filesystem->wp_content_dir() ) {
				$errors->add( 'fs_no_content_dir', $this->strings['fs_no_content_dir'] );
				return $errors;
			}

			$src      = $wp_filesystem->wp_content_dir() . 'upgrade-temp-backup/' . $args['dir'] . '/' . $args['slug'];
			$dest_dir = $wp_filesystem->find_folder( $args['src'] );
			$dest     = trailingslashit( $dest_dir ) . $args['slug'];

			if ( $wp_filesystem->is_dir( $src ) ) {
				// Cleanup.
				if ( $wp_filesystem->is_dir( $dest ) && ! $wp_filesystem->delete( $dest, true ) ) {
					$errors->add(
						'fs_temp_backup_delete',
						sprintf( $this->strings['temp_backup_restore_failed'], $args['slug'] )
					);
					continue;
				}

				// Move it.
				$result = move_dir( $src, $dest, true );
				if ( is_wp_error( $result ) ) {
					$errors->add(
						'fs_temp_backup_delete',
						sprintf( $this->strings['temp_backup_restore_failed'], $args['slug'] )
					);
					continue;
				}
			}
		}

		return $errors->has_errors() ? $errors : true;
	}

	/**
	 * Deletes a temporary backup.
	 *
	 * @since 6.3.0
	 * @since 6.6.0 Added the `$temp_backups` parameter.
	 *
	 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
	 *
	 * @param array[] $temp_backups {
	 *     Optional. An array of temporary backups.
	 *
	 *     @type array ...$0 {
	 *         Information about the backup.
	 *
	 *         @type string $dir  The temporary backup location in the upgrade-temp-backup directory.
	 *         @type string $slug The item's slug.
	 *         @type string $src  The directory where the original is stored. For example, `WP_PLUGIN_DIR`.
	 *     }
	 * }
	 * @return bool|WP_Error True on success, false on early exit, otherwise WP_Error.
	 */
	public function delete_temp_backup( array $temp_backups = array() ) {
		global $wp_filesystem;

		$errors = new WP_Error();

		if ( empty( $temp_backups ) ) {
			$temp_backups = $this->temp_backups;
		}

		foreach ( $temp_backups as $args ) {
			if ( empty( $args['slug'] ) || empty( $args['dir'] ) ) {
				return false;
			}

			if ( ! $wp_filesystem->wp_content_dir() ) {
				$errors->add( 'fs_no_content_dir', $this->strings['fs_no_content_dir'] );
				return $errors;
			}

			$temp_backup_dir = $wp_filesystem->wp_content_dir() . "upgrade-temp-backup/{$args['dir']}/{$args['slug']}";

			if ( ! $wp_filesystem->delete( $temp_backup_dir, true ) ) {
				$errors->add(
					'temp_backup_delete_failed',
					sprintf( $this->strings['temp_backup_delete_failed'], $args['slug'] )
				);
				continue;
			}
		}

		return $errors->has_errors() ? $errors : true;
	}
}

/** Plugin_Upgrader class */
require_once ABSPATH . 'wp-admin/includes/class-plugin-upgrader.php';

/** Theme_Upgrader class */
require_once ABSPATH . 'wp-admin/includes/class-theme-upgrader.php';

/** Language_Pack_Upgrader class */
require_once ABSPATH . 'wp-admin/includes/class-language-pack-upgrader.php';

/** Core_Upgrader class */
require_once ABSPATH . 'wp-admin/includes/class-core-upgrader.php';

/** File_Upload_Upgrader class */
require_once ABSPATH . 'wp-admin/includes/class-file-upload-upgrader.php';

/** WP_Automatic_Updater class */
require_once ABSPATH . 'wp-admin/includes/class-wp-automatic-updater.php';
class-wp-themes-list-table.php000064400000024224151212616040012331 0ustar00<?php
/**
 * List Table API: WP_Themes_List_Table class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 3.1.0
 */

/**
 * Core class used to implement displaying installed themes in a list table.
 *
 * @since 3.1.0
 *
 * @see WP_List_Table
 */
class WP_Themes_List_Table extends WP_List_Table {

	protected $search_terms = array();
	public $features        = array();

	/**
	 * Constructor.
	 *
	 * @since 3.1.0
	 *
	 * @see WP_List_Table::__construct() for more information on default arguments.
	 *
	 * @param array $args An associative array of arguments.
	 */
	public function __construct( $args = array() ) {
		parent::__construct(
			array(
				'ajax'   => true,
				'screen' => isset( $args['screen'] ) ? $args['screen'] : null,
			)
		);
	}

	/**
	 * @return bool
	 */
	public function ajax_user_can() {
		// Do not check edit_theme_options here. Ajax calls for available themes require switch_themes.
		return current_user_can( 'switch_themes' );
	}

	/**
	 */
	public function prepare_items() {
		$themes = wp_get_themes( array( 'allowed' => true ) );

		if ( ! empty( $_REQUEST['s'] ) ) {
			$this->search_terms = array_unique( array_filter( array_map( 'trim', explode( ',', strtolower( wp_unslash( $_REQUEST['s'] ) ) ) ) ) );
		}

		if ( ! empty( $_REQUEST['features'] ) ) {
			$this->features = $_REQUEST['features'];
		}

		if ( $this->search_terms || $this->features ) {
			foreach ( $themes as $key => $theme ) {
				if ( ! $this->search_theme( $theme ) ) {
					unset( $themes[ $key ] );
				}
			}
		}

		unset( $themes[ get_option( 'stylesheet' ) ] );
		WP_Theme::sort_by_name( $themes );

		$per_page = 36;
		$page     = $this->get_pagenum();

		$start = ( $page - 1 ) * $per_page;

		$this->items = array_slice( $themes, $start, $per_page, true );

		$this->set_pagination_args(
			array(
				'total_items'     => count( $themes ),
				'per_page'        => $per_page,
				'infinite_scroll' => true,
			)
		);
	}

	/**
	 */
	public function no_items() {
		if ( $this->search_terms || $this->features ) {
			_e( 'No items found.' );
			return;
		}

		$blog_id = get_current_blog_id();
		if ( is_multisite() ) {
			if ( current_user_can( 'install_themes' ) && current_user_can( 'manage_network_themes' ) ) {
				printf(
					/* translators: 1: URL to Themes tab on Edit Site screen, 2: URL to Add Themes screen. */
					__( 'You only have one theme enabled for this site right now. Visit the Network Admin to <a href="%1$s">enable</a> or <a href="%2$s">install</a> more themes.' ),
					network_admin_url( 'site-themes.php?id=' . $blog_id ),
					network_admin_url( 'theme-install.php' )
				);

				return;
			} elseif ( current_user_can( 'manage_network_themes' ) ) {
				printf(
					/* translators: %s: URL to Themes tab on Edit Site screen. */
					__( 'You only have one theme enabled for this site right now. Visit the Network Admin to <a href="%s">enable</a> more themes.' ),
					network_admin_url( 'site-themes.php?id=' . $blog_id )
				);

				return;
			}
			// Else, fallthrough. install_themes doesn't help if you can't enable it.
		} else {
			if ( current_user_can( 'install_themes' ) ) {
				printf(
					/* translators: %s: URL to Add Themes screen. */
					__( 'You only have one theme installed right now. Live a little! You can choose from over 1,000 free themes in the WordPress Theme Directory at any time: just click on the <a href="%s">Install Themes</a> tab above.' ),
					admin_url( 'theme-install.php' )
				);

				return;
			}
		}
		// Fallthrough.
		printf(
			/* translators: %s: Network title. */
			__( 'Only the active theme is available to you. Contact the %s administrator for information about accessing additional themes.' ),
			get_site_option( 'site_name' )
		);
	}

	/**
	 * @param string $which
	 */
	public function tablenav( $which = 'top' ) {
		if ( $this->get_pagination_arg( 'total_pages' ) <= 1 ) {
			return;
		}
		?>
		<div class="tablenav themes <?php echo $which; ?>">
			<?php $this->pagination( $which ); ?>
			<span class="spinner"></span>
			<br class="clear" />
		</div>
		<?php
	}

	/**
	 * Displays the themes table.
	 *
	 * Overrides the parent display() method to provide a different container.
	 *
	 * @since 3.1.0
	 */
	public function display() {
		wp_nonce_field( 'fetch-list-' . get_class( $this ), '_ajax_fetch_list_nonce' );
		?>
		<?php $this->tablenav( 'top' ); ?>

		<div id="availablethemes">
			<?php $this->display_rows_or_placeholder(); ?>
		</div>

		<?php $this->tablenav( 'bottom' ); ?>
		<?php
	}

	/**
	 * @return string[] Array of column titles keyed by their column name.
	 */
	public function get_columns() {
		return array();
	}

	/**
	 */
	public function display_rows_or_placeholder() {
		if ( $this->has_items() ) {
			$this->display_rows();
		} else {
			echo '<div class="no-items">';
			$this->no_items();
			echo '</div>';
		}
	}

	/**
	 * Generates the list table rows.
	 *
	 * @since 3.1.0
	 */
	public function display_rows() {
		$themes = $this->items;

		foreach ( $themes as $theme ) :
			?>
			<div class="available-theme">
			<?php

			$template   = $theme->get_template();
			$stylesheet = $theme->get_stylesheet();
			$title      = $theme->display( 'Name' );
			$version    = $theme->display( 'Version' );
			$author     = $theme->display( 'Author' );

			$activate_link = wp_nonce_url( 'themes.php?action=activate&amp;template=' . urlencode( $template ) . '&amp;stylesheet=' . urlencode( $stylesheet ), 'switch-theme_' . $stylesheet );

			$actions             = array();
			$actions['activate'] = sprintf(
				'<a href="%s" class="activatelink" aria-label="%s">%s</a>',
				$activate_link,
				/* translators: %s: Theme name. */
				esc_attr( sprintf( _x( 'Activate &#8220;%s&#8221;', 'theme' ), $title ) ),
				_x( 'Activate', 'theme' )
			);

			if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) {
				$actions['preview'] .= sprintf(
					'<a href="%s" class="load-customize hide-if-no-customize">%s</a>',
					wp_customize_url( $stylesheet ),
					__( 'Live Preview' )
				);
			}

			if ( ! is_multisite() && current_user_can( 'delete_themes' ) ) {
				$actions['delete'] = sprintf(
					'<a class="submitdelete deletion" href="%s" onclick="return confirm( \'%s\' );">%s</a>',
					wp_nonce_url( 'themes.php?action=delete&amp;stylesheet=' . urlencode( $stylesheet ), 'delete-theme_' . $stylesheet ),
					/* translators: %s: Theme name. */
					esc_js( sprintf( __( "You are about to delete this theme '%s'\n  'Cancel' to stop, 'OK' to delete." ), $title ) ),
					__( 'Delete' )
				);
			}

			/** This filter is documented in wp-admin/includes/class-wp-ms-themes-list-table.php */
			$actions = apply_filters( 'theme_action_links', $actions, $theme, 'all' );

			/** This filter is documented in wp-admin/includes/class-wp-ms-themes-list-table.php */
			$actions       = apply_filters( "theme_action_links_{$stylesheet}", $actions, $theme, 'all' );
			$delete_action = isset( $actions['delete'] ) ? '<div class="delete-theme">' . $actions['delete'] . '</div>' : '';
			unset( $actions['delete'] );

			$screenshot = $theme->get_screenshot();
			?>

			<span class="screenshot hide-if-customize">
				<?php if ( $screenshot ) : ?>
					<img src="<?php echo esc_url( $screenshot . '?ver=' . $theme->version ); ?>" alt="" />
				<?php endif; ?>
			</span>
			<a href="<?php echo wp_customize_url( $stylesheet ); ?>" class="screenshot load-customize hide-if-no-customize">
				<?php if ( $screenshot ) : ?>
					<img src="<?php echo esc_url( $screenshot . '?ver=' . $theme->version ); ?>" alt="" />
				<?php endif; ?>
			</a>

			<h3><?php echo $title; ?></h3>
			<div class="theme-author">
				<?php
					/* translators: %s: Theme author. */
					printf( __( 'By %s' ), $author );
				?>
			</div>
			<div class="action-links">
				<ul>
					<?php foreach ( $actions as $action ) : ?>
						<li><?php echo $action; ?></li>
					<?php endforeach; ?>
					<li class="hide-if-no-js"><a href="#" class="theme-detail"><?php _e( 'Details' ); ?></a></li>
				</ul>
				<?php echo $delete_action; ?>

				<?php theme_update_available( $theme ); ?>
			</div>

			<div class="themedetaildiv hide-if-js">
				<p><strong><?php _e( 'Version:' ); ?></strong> <?php echo $version; ?></p>
				<p><?php echo $theme->display( 'Description' ); ?></p>
				<?php
				if ( $theme->parent() ) {
					printf(
						/* translators: 1: Link to documentation on child themes, 2: Name of parent theme. */
						' <p class="howto">' . __( 'This <a href="%1$s">child theme</a> requires its parent theme, %2$s.' ) . '</p>',
						__( 'https://developer.wordpress.org/themes/advanced-topics/child-themes/' ),
						$theme->parent()->display( 'Name' )
					);
				}
				?>
			</div>

			</div>
			<?php
		endforeach;
	}

	/**
	 * @param WP_Theme $theme
	 * @return bool
	 */
	public function search_theme( $theme ) {
		// Search the features.
		foreach ( $this->features as $word ) {
			if ( ! in_array( $word, $theme->get( 'Tags' ), true ) ) {
				return false;
			}
		}

		// Match all phrases.
		foreach ( $this->search_terms as $word ) {
			if ( in_array( $word, $theme->get( 'Tags' ), true ) ) {
				continue;
			}

			foreach ( array( 'Name', 'Description', 'Author', 'AuthorURI' ) as $header ) {
				// Don't mark up; Do translate.
				if ( false !== stripos( strip_tags( $theme->display( $header, false, true ) ), $word ) ) {
					continue 2;
				}
			}

			if ( false !== stripos( $theme->get_stylesheet(), $word ) ) {
				continue;
			}

			if ( false !== stripos( $theme->get_template(), $word ) ) {
				continue;
			}

			return false;
		}

		return true;
	}

	/**
	 * Send required variables to JavaScript land
	 *
	 * @since 3.4.0
	 *
	 * @param array $extra_args
	 */
	public function _js_vars( $extra_args = array() ) {
		$search_string = isset( $_REQUEST['s'] ) ? esc_attr( wp_unslash( $_REQUEST['s'] ) ) : '';

		$args = array(
			'search'      => $search_string,
			'features'    => $this->features,
			'paged'       => $this->get_pagenum(),
			'total_pages' => ! empty( $this->_pagination_args['total_pages'] ) ? $this->_pagination_args['total_pages'] : 1,
		);

		if ( is_array( $extra_args ) ) {
			$args = array_merge( $args, $extra_args );
		}

		printf( "<script type='text/javascript'>var theme_list_args = %s;</script>\n", wp_json_encode( $args, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) );
		parent::_js_vars();
	}
}
class-wp-filesystem-ftpsockets.php000064400000044057151212616040013363 0ustar00<?php
/**
 * WordPress FTP Sockets Filesystem.
 *
 * @package WordPress
 * @subpackage Filesystem
 */

/**
 * WordPress Filesystem Class for implementing FTP Sockets.
 *
 * @since 2.5.0
 *
 * @see WP_Filesystem_Base
 */
class WP_Filesystem_ftpsockets extends WP_Filesystem_Base {

	/**
	 * @since 2.5.0
	 * @var ftp
	 */
	public $ftp;

	/**
	 * Constructor.
	 *
	 * @since 2.5.0
	 *
	 * @param array $opt
	 */
	public function __construct( $opt = '' ) {
		$this->method = 'ftpsockets';
		$this->errors = new WP_Error();

		// Check if possible to use ftp functions.
		if ( ! require_once ABSPATH . 'wp-admin/includes/class-ftp.php' ) {
			return;
		}

		$this->ftp = new ftp();

		if ( empty( $opt['port'] ) ) {
			$this->options['port'] = 21;
		} else {
			$this->options['port'] = (int) $opt['port'];
		}

		if ( empty( $opt['hostname'] ) ) {
			$this->errors->add( 'empty_hostname', __( 'FTP hostname is required' ) );
		} else {
			$this->options['hostname'] = $opt['hostname'];
		}

		// Check if the options provided are OK.
		if ( empty( $opt['username'] ) ) {
			$this->errors->add( 'empty_username', __( 'FTP username is required' ) );
		} else {
			$this->options['username'] = $opt['username'];
		}

		if ( empty( $opt['password'] ) ) {
			$this->errors->add( 'empty_password', __( 'FTP password is required' ) );
		} else {
			$this->options['password'] = $opt['password'];
		}
	}

	/**
	 * Connects filesystem.
	 *
	 * @since 2.5.0
	 *
	 * @return bool True on success, false on failure.
	 */
	public function connect() {
		if ( ! $this->ftp ) {
			return false;
		}

		$this->ftp->SetTimeout( FS_CONNECT_TIMEOUT );

		if ( ! $this->ftp->SetServer( $this->options['hostname'], $this->options['port'] ) ) {
			$this->errors->add(
				'connect',
				sprintf(
					/* translators: %s: hostname:port */
					__( 'Failed to connect to FTP Server %s' ),
					$this->options['hostname'] . ':' . $this->options['port']
				)
			);

			return false;
		}

		if ( ! $this->ftp->connect() ) {
			$this->errors->add(
				'connect',
				sprintf(
					/* translators: %s: hostname:port */
					__( 'Failed to connect to FTP Server %s' ),
					$this->options['hostname'] . ':' . $this->options['port']
				)
			);

			return false;
		}

		if ( ! $this->ftp->login( $this->options['username'], $this->options['password'] ) ) {
			$this->errors->add(
				'auth',
				sprintf(
					/* translators: %s: Username. */
					__( 'Username/Password incorrect for %s' ),
					$this->options['username']
				)
			);

			return false;
		}

		$this->ftp->SetType( FTP_BINARY );
		$this->ftp->Passive( true );
		$this->ftp->SetTimeout( FS_TIMEOUT );

		return true;
	}

	/**
	 * Reads entire file into a string.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Name of the file to read.
	 * @return string|false Read data on success, false if no temporary file could be opened,
	 *                      or if the file couldn't be retrieved.
	 */
	public function get_contents( $file ) {
		if ( ! $this->exists( $file ) ) {
			return false;
		}

		$tempfile   = wp_tempnam( $file );
		$temphandle = fopen( $tempfile, 'w+' );

		if ( ! $temphandle ) {
			unlink( $tempfile );
			return false;
		}

		mbstring_binary_safe_encoding();

		if ( ! $this->ftp->fget( $temphandle, $file ) ) {
			fclose( $temphandle );
			unlink( $tempfile );

			reset_mbstring_encoding();

			return ''; // Blank document. File does exist, it's just blank.
		}

		reset_mbstring_encoding();

		fseek( $temphandle, 0 ); // Skip back to the start of the file being written to.
		$contents = '';

		while ( ! feof( $temphandle ) ) {
			$contents .= fread( $temphandle, 8 * KB_IN_BYTES );
		}

		fclose( $temphandle );
		unlink( $tempfile );

		return $contents;
	}

	/**
	 * Reads entire file into an array.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to the file.
	 * @return array|false File contents in an array on success, false on failure.
	 */
	public function get_contents_array( $file ) {
		return explode( "\n", $this->get_contents( $file ) );
	}

	/**
	 * Writes a string to a file.
	 *
	 * @since 2.5.0
	 *
	 * @param string    $file     Remote path to the file where to write the data.
	 * @param string    $contents The data to write.
	 * @param int|false $mode     Optional. The file permissions as octal number, usually 0644.
	 *                            Default false.
	 * @return bool True on success, false on failure.
	 */
	public function put_contents( $file, $contents, $mode = false ) {
		$tempfile   = wp_tempnam( $file );
		$temphandle = @fopen( $tempfile, 'w+' );

		if ( ! $temphandle ) {
			unlink( $tempfile );
			return false;
		}

		// The FTP class uses string functions internally during file download/upload.
		mbstring_binary_safe_encoding();

		$bytes_written = fwrite( $temphandle, $contents );

		if ( false === $bytes_written || strlen( $contents ) !== $bytes_written ) {
			fclose( $temphandle );
			unlink( $tempfile );

			reset_mbstring_encoding();

			return false;
		}

		fseek( $temphandle, 0 ); // Skip back to the start of the file being written to.

		$ret = $this->ftp->fput( $file, $temphandle );

		reset_mbstring_encoding();

		fclose( $temphandle );
		unlink( $tempfile );

		$this->chmod( $file, $mode );

		return $ret;
	}

	/**
	 * Gets the current working directory.
	 *
	 * @since 2.5.0
	 *
	 * @return string|false The current working directory on success, false on failure.
	 */
	public function cwd() {
		$cwd = $this->ftp->pwd();

		if ( $cwd ) {
			$cwd = trailingslashit( $cwd );
		}

		return $cwd;
	}

	/**
	 * Changes current directory.
	 *
	 * @since 2.5.0
	 *
	 * @param string $dir The new current directory.
	 * @return bool True on success, false on failure.
	 */
	public function chdir( $dir ) {
		return $this->ftp->chdir( $dir );
	}

	/**
	 * Changes filesystem permissions.
	 *
	 * @since 2.5.0
	 *
	 * @param string    $file      Path to the file.
	 * @param int|false $mode      Optional. The permissions as octal number, usually 0644 for files,
	 *                             0755 for directories. Default false.
	 * @param bool      $recursive Optional. If set to true, changes file permissions recursively.
	 *                             Default false.
	 * @return bool True on success, false on failure.
	 */
	public function chmod( $file, $mode = false, $recursive = false ) {
		if ( ! $mode ) {
			if ( $this->is_file( $file ) ) {
				$mode = FS_CHMOD_FILE;
			} elseif ( $this->is_dir( $file ) ) {
				$mode = FS_CHMOD_DIR;
			} else {
				return false;
			}
		}

		// chmod any sub-objects if recursive.
		if ( $recursive && $this->is_dir( $file ) ) {
			$filelist = $this->dirlist( $file );

			foreach ( (array) $filelist as $filename => $filemeta ) {
				$this->chmod( $file . '/' . $filename, $mode, $recursive );
			}
		}

		// chmod the file or directory.
		return $this->ftp->chmod( $file, $mode );
	}

	/**
	 * Gets the file owner.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to the file.
	 * @return string|false Username of the owner on success, false on failure.
	 */
	public function owner( $file ) {
		$dir = $this->dirlist( $file );

		return $dir[ $file ]['owner'];
	}

	/**
	 * Gets the permissions of the specified file or filepath in their octal format.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to the file.
	 * @return string Mode of the file (the last 3 digits).
	 */
	public function getchmod( $file ) {
		$dir = $this->dirlist( $file );

		return $dir[ $file ]['permsn'];
	}

	/**
	 * Gets the file's group.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to the file.
	 * @return string|false The group on success, false on failure.
	 */
	public function group( $file ) {
		$dir = $this->dirlist( $file );

		return $dir[ $file ]['group'];
	}

	/**
	 * Copies a file.
	 *
	 * @since 2.5.0
	 *
	 * @param string    $source      Path to the source file.
	 * @param string    $destination Path to the destination file.
	 * @param bool      $overwrite   Optional. Whether to overwrite the destination file if it exists.
	 *                               Default false.
	 * @param int|false $mode        Optional. The permissions as octal number, usually 0644 for files,
	 *                               0755 for dirs. Default false.
	 * @return bool True on success, false on failure.
	 */
	public function copy( $source, $destination, $overwrite = false, $mode = false ) {
		if ( ! $overwrite && $this->exists( $destination ) ) {
			return false;
		}

		$content = $this->get_contents( $source );

		if ( false === $content ) {
			return false;
		}

		return $this->put_contents( $destination, $content, $mode );
	}

	/**
	 * Moves a file or directory.
	 *
	 * After moving files or directories, OPcache will need to be invalidated.
	 *
	 * If moving a directory fails, `copy_dir()` can be used for a recursive copy.
	 *
	 * Use `move_dir()` for moving directories with OPcache invalidation and a
	 * fallback to `copy_dir()`.
	 *
	 * @since 2.5.0
	 *
	 * @param string $source      Path to the source file or directory.
	 * @param string $destination Path to the destination file or directory.
	 * @param bool   $overwrite   Optional. Whether to overwrite the destination if it exists.
	 *                            Default false.
	 * @return bool True on success, false on failure.
	 */
	public function move( $source, $destination, $overwrite = false ) {
		return $this->ftp->rename( $source, $destination );
	}

	/**
	 * Deletes a file or directory.
	 *
	 * @since 2.5.0
	 *
	 * @param string       $file      Path to the file or directory.
	 * @param bool         $recursive Optional. If set to true, deletes files and folders recursively.
	 *                                Default false.
	 * @param string|false $type      Type of resource. 'f' for file, 'd' for directory.
	 *                                Default false.
	 * @return bool True on success, false on failure.
	 */
	public function delete( $file, $recursive = false, $type = false ) {
		if ( empty( $file ) ) {
			return false;
		}

		if ( 'f' === $type || $this->is_file( $file ) ) {
			return $this->ftp->delete( $file );
		}

		if ( ! $recursive ) {
			return $this->ftp->rmdir( $file );
		}

		return $this->ftp->mdel( $file );
	}

	/**
	 * Checks if a file or directory exists.
	 *
	 * @since 2.5.0
	 * @since 6.3.0 Returns false for an empty path.
	 *
	 * @param string $path Path to file or directory.
	 * @return bool Whether $path exists or not.
	 */
	public function exists( $path ) {
		/*
		 * Check for empty path. If ftp::nlist() receives an empty path,
		 * it checks the current working directory and may return true.
		 *
		 * See https://core.trac.wordpress.org/ticket/33058.
		 */
		if ( '' === $path ) {
			return false;
		}

		$list = $this->ftp->nlist( $path );

		if ( empty( $list ) && $this->is_dir( $path ) ) {
			return true; // File is an empty directory.
		}

		return ! empty( $list ); // Empty list = no file, so invert.
		// Return $this->ftp->is_exists($file); has issues with ABOR+426 responses on the ncFTPd server.
	}

	/**
	 * Checks if resource is a file.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file File path.
	 * @return bool Whether $file is a file.
	 */
	public function is_file( $file ) {
		if ( $this->is_dir( $file ) ) {
			return false;
		}

		if ( $this->exists( $file ) ) {
			return true;
		}

		return false;
	}

	/**
	 * Checks if resource is a directory.
	 *
	 * @since 2.5.0
	 *
	 * @param string $path Directory path.
	 * @return bool Whether $path is a directory.
	 */
	public function is_dir( $path ) {
		$cwd = $this->cwd();

		if ( $this->chdir( $path ) ) {
			$this->chdir( $cwd );
			return true;
		}

		return false;
	}

	/**
	 * Checks if a file is readable.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to file.
	 * @return bool Whether $file is readable.
	 */
	public function is_readable( $file ) {
		return true;
	}

	/**
	 * Checks if a file or directory is writable.
	 *
	 * @since 2.5.0
	 *
	 * @param string $path Path to file or directory.
	 * @return bool Whether $path is writable.
	 */
	public function is_writable( $path ) {
		return true;
	}

	/**
	 * Gets the file's last access time.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to file.
	 * @return int|false Unix timestamp representing last access time, false on failure.
	 */
	public function atime( $file ) {
		return false;
	}

	/**
	 * Gets the file modification time.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to file.
	 * @return int|false Unix timestamp representing modification time, false on failure.
	 */
	public function mtime( $file ) {
		return $this->ftp->mdtm( $file );
	}

	/**
	 * Gets the file size (in bytes).
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to file.
	 * @return int|false Size of the file in bytes on success, false on failure.
	 */
	public function size( $file ) {
		return $this->ftp->filesize( $file );
	}

	/**
	 * Sets the access and modification times of a file.
	 *
	 * Note: If $file doesn't exist, it will be created.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file  Path to file.
	 * @param int    $time  Optional. Modified time to set for file.
	 *                      Default 0.
	 * @param int    $atime Optional. Access time to set for file.
	 *                      Default 0.
	 * @return bool True on success, false on failure.
	 */
	public function touch( $file, $time = 0, $atime = 0 ) {
		return false;
	}

	/**
	 * Creates a directory.
	 *
	 * @since 2.5.0
	 *
	 * @param string           $path  Path for new directory.
	 * @param int|false        $chmod Optional. The permissions as octal number (or false to skip chmod).
	 *                                Default false.
	 * @param string|int|false $chown Optional. A user name or number (or false to skip chown).
	 *                                Default false.
	 * @param string|int|false $chgrp Optional. A group name or number (or false to skip chgrp).
	 *                                Default false.
	 * @return bool True on success, false on failure.
	 */
	public function mkdir( $path, $chmod = false, $chown = false, $chgrp = false ) {
		$path = untrailingslashit( $path );

		if ( empty( $path ) ) {
			return false;
		}

		if ( ! $this->ftp->mkdir( $path ) ) {
			return false;
		}

		if ( ! $chmod ) {
			$chmod = FS_CHMOD_DIR;
		}

		$this->chmod( $path, $chmod );

		return true;
	}

	/**
	 * Deletes a directory.
	 *
	 * @since 2.5.0
	 *
	 * @param string $path      Path to directory.
	 * @param bool   $recursive Optional. Whether to recursively remove files/directories.
	 *                          Default false.
	 * @return bool True on success, false on failure.
	 */
	public function rmdir( $path, $recursive = false ) {
		return $this->delete( $path, $recursive );
	}

	/**
	 * Gets details for files in a directory or a specific file.
	 *
	 * @since 2.5.0
	 *
	 * @param string $path           Path to directory or file.
	 * @param bool   $include_hidden Optional. Whether to include details of hidden ("." prefixed) files.
	 *                               Default true.
	 * @param bool   $recursive      Optional. Whether to recursively include file details in nested directories.
	 *                               Default false.
	 * @return array|false {
	 *     Array of arrays containing file information. False if unable to list directory contents.
	 *
	 *     @type array ...$0 {
	 *         Array of file information. Note that some elements may not be available on all filesystems.
	 *
	 *         @type string           $name        Name of the file or directory.
	 *         @type string           $perms       *nix representation of permissions.
	 *         @type string           $permsn      Octal representation of permissions.
	 *         @type int|string|false $number      File number. May be a numeric string. False if not available.
	 *         @type string|false     $owner       Owner name or ID, or false if not available.
	 *         @type string|false     $group       File permissions group, or false if not available.
	 *         @type int|string|false $size        Size of file in bytes. May be a numeric string.
	 *                                             False if not available.
	 *         @type int|string|false $lastmodunix Last modified unix timestamp. May be a numeric string.
	 *                                             False if not available.
	 *         @type string|false     $lastmod     Last modified month (3 letters) and day (without leading 0), or
	 *                                             false if not available.
	 *         @type string|false     $time        Last modified time, or false if not available.
	 *         @type string           $type        Type of resource. 'f' for file, 'd' for directory, 'l' for link.
	 *         @type array|false      $files       If a directory and `$recursive` is true, contains another array of
	 *                                             files. False if unable to list directory contents.
	 *     }
	 * }
	 */
	public function dirlist( $path = '.', $include_hidden = true, $recursive = false ) {
		if ( $this->is_file( $path ) ) {
			$limit_file = basename( $path );
			$path       = dirname( $path ) . '/';
		} else {
			$limit_file = false;
		}

		mbstring_binary_safe_encoding();

		$list = $this->ftp->dirlist( $path );

		if ( empty( $list ) && ! $this->exists( $path ) ) {

			reset_mbstring_encoding();

			return false;
		}

		$path = trailingslashit( $path );
		$ret  = array();

		foreach ( $list as $struc ) {

			if ( '.' === $struc['name'] || '..' === $struc['name'] ) {
				continue;
			}

			if ( ! $include_hidden && '.' === $struc['name'][0] ) {
				continue;
			}

			if ( $limit_file && $struc['name'] !== $limit_file ) {
				continue;
			}

			if ( 'd' === $struc['type'] ) {
				if ( $recursive ) {
					$struc['files'] = $this->dirlist( $path . $struc['name'], $include_hidden, $recursive );
				} else {
					$struc['files'] = array();
				}
			}

			// Replace symlinks formatted as "source -> target" with just the source name.
			if ( $struc['islink'] ) {
				$struc['name'] = preg_replace( '/(\s*->\s*.*)$/', '', $struc['name'] );
			}

			// Add the octal representation of the file permissions.
			$struc['permsn'] = $this->getnumchmodfromh( $struc['perms'] );

			$ret[ $struc['name'] ] = $struc;
		}

		reset_mbstring_encoding();

		return $ret;
	}

	/**
	 * Destructor.
	 *
	 * @since 2.5.0
	 */
	public function __destruct() {
		$this->ftp->quit();
	}
}
nav-menu.php000064400000141541151212616040007007 0ustar00<?php
/**
 * Core Navigation Menu API
 *
 * @package WordPress
 * @subpackage Nav_Menus
 * @since 3.0.0
 */

/** Walker_Nav_Menu_Edit class */
require_once ABSPATH . 'wp-admin/includes/class-walker-nav-menu-edit.php';

/** Walker_Nav_Menu_Checklist class */
require_once ABSPATH . 'wp-admin/includes/class-walker-nav-menu-checklist.php';

/**
 * Prints the appropriate response to a menu quick search.
 *
 * @since 3.0.0
 *
 * @param array $request The unsanitized request values.
 */
function _wp_ajax_menu_quick_search( $request = array() ) {
	$args            = array();
	$type            = isset( $request['type'] ) ? $request['type'] : '';
	$object_type     = isset( $request['object_type'] ) ? $request['object_type'] : '';
	$query           = isset( $request['q'] ) ? $request['q'] : '';
	$response_format = isset( $request['response-format'] ) ? $request['response-format'] : '';

	if ( ! $response_format || ! in_array( $response_format, array( 'json', 'markup' ), true ) ) {
		$response_format = 'json';
	}

	if ( 'markup' === $response_format ) {
		$args['walker'] = new Walker_Nav_Menu_Checklist();
	}

	if ( 'get-post-item' === $type ) {
		if ( post_type_exists( $object_type ) ) {
			if ( isset( $request['ID'] ) ) {
				$object_id = (int) $request['ID'];

				if ( 'markup' === $response_format ) {
					echo walk_nav_menu_tree(
						array_map( 'wp_setup_nav_menu_item', array( get_post( $object_id ) ) ),
						0,
						(object) $args
					);
				} elseif ( 'json' === $response_format ) {
					echo wp_json_encode(
						array(
							'ID'         => $object_id,
							'post_title' => get_the_title( $object_id ),
							'post_type'  => get_post_type( $object_id ),
						)
					);
					echo "\n";
				}
			}
		} elseif ( taxonomy_exists( $object_type ) ) {
			if ( isset( $request['ID'] ) ) {
				$object_id = (int) $request['ID'];

				if ( 'markup' === $response_format ) {
					echo walk_nav_menu_tree(
						array_map( 'wp_setup_nav_menu_item', array( get_term( $object_id, $object_type ) ) ),
						0,
						(object) $args
					);
				} elseif ( 'json' === $response_format ) {
					$post_obj = get_term( $object_id, $object_type );
					echo wp_json_encode(
						array(
							'ID'         => $object_id,
							'post_title' => $post_obj->name,
							'post_type'  => $object_type,
						)
					);
					echo "\n";
				}
			}
		}
	} elseif ( preg_match( '/quick-search-(posttype|taxonomy)-([a-zA-Z0-9_-]*\b)/', $type, $matches ) ) {
		if ( 'posttype' === $matches[1] && get_post_type_object( $matches[2] ) ) {
			$post_type_obj = _wp_nav_menu_meta_box_object( get_post_type_object( $matches[2] ) );
			$query_args    = array(
				'no_found_rows'          => true,
				'update_post_meta_cache' => false,
				'update_post_term_cache' => false,
				'posts_per_page'         => 10,
				'post_type'              => $matches[2],
				's'                      => $query,
				'search_columns'         => array( 'post_title' ),
			);
			/**
			 * Filter the menu quick search arguments.
			 *
			 * @since 6.9.0
			 *
			 * @param array $args {
			 *     Menu quick search arguments.
			 *
			 *     @type boolean      $no_found_rows          Whether to return found rows data. Default true.
			 *     @type boolean      $update_post_meta_cache Whether to update post meta cache. Default false.
			 *     @type boolean      $update_post_term_cache Whether to update post term cache. Default false.
			 *     @type int          $posts_per_page         Number of posts to return. Default 10.
			 *     @type string       $post_type              Type of post to return.
			 *     @type string       $s                      Search query.
			 *     @type array        $search_columns         Which post table columns to query.
			 * }
			*/
			$query_args = apply_filters( 'wp_ajax_menu_quick_search_args', $query_args );
			$args       = array_merge( $args, $query_args );

			if ( isset( $post_type_obj->_default_query ) ) {
				$args = array_merge( $args, (array) $post_type_obj->_default_query );
			}

			$search_results_query = new WP_Query( $args );
			if ( ! $search_results_query->have_posts() ) {
				return;
			}

			while ( $search_results_query->have_posts() ) {
				$post = $search_results_query->next_post();

				if ( 'markup' === $response_format ) {
					$var_by_ref = $post->ID;
					echo walk_nav_menu_tree(
						array_map( 'wp_setup_nav_menu_item', array( get_post( $var_by_ref ) ) ),
						0,
						(object) $args
					);
				} elseif ( 'json' === $response_format ) {
					echo wp_json_encode(
						array(
							'ID'         => $post->ID,
							'post_title' => get_the_title( $post->ID ),
							'post_type'  => $matches[2],
						)
					);
					echo "\n";
				}
			}
		} elseif ( 'taxonomy' === $matches[1] ) {
			$terms = get_terms(
				array(
					'taxonomy'   => $matches[2],
					'name__like' => $query,
					'number'     => 10,
					'hide_empty' => false,
				)
			);

			if ( empty( $terms ) || is_wp_error( $terms ) ) {
				return;
			}

			foreach ( (array) $terms as $term ) {
				if ( 'markup' === $response_format ) {
					echo walk_nav_menu_tree(
						array_map( 'wp_setup_nav_menu_item', array( $term ) ),
						0,
						(object) $args
					);
				} elseif ( 'json' === $response_format ) {
					echo wp_json_encode(
						array(
							'ID'         => $term->term_id,
							'post_title' => $term->name,
							'post_type'  => $matches[2],
						)
					);
					echo "\n";
				}
			}
		}
	}
}

/**
 * Register nav menu meta boxes and advanced menu items.
 *
 * @since 3.0.0
 */
function wp_nav_menu_setup() {
	// Register meta boxes.
	wp_nav_menu_post_type_meta_boxes();
	add_meta_box(
		'add-custom-links',
		__( 'Custom Links' ),
		'wp_nav_menu_item_link_meta_box',
		'nav-menus',
		'side',
		'default'
	);
	wp_nav_menu_taxonomy_meta_boxes();

	// Register advanced menu items (columns).
	add_filter( 'manage_nav-menus_columns', 'wp_nav_menu_manage_columns' );

	// If first time editing, disable advanced items by default.
	if ( false === get_user_option( 'managenav-menuscolumnshidden' ) ) {
		$user = wp_get_current_user();
		update_user_meta(
			$user->ID,
			'managenav-menuscolumnshidden',
			array(
				0 => 'link-target',
				1 => 'css-classes',
				2 => 'xfn',
				3 => 'description',
				4 => 'title-attribute',
			)
		);
	}
}

/**
 * Limit the amount of meta boxes to pages, posts, links, and categories for first time users.
 *
 * @since 3.0.0
 *
 * @global array $wp_meta_boxes Global meta box state.
 */
function wp_initial_nav_menu_meta_boxes() {
	global $wp_meta_boxes;

	if ( get_user_option( 'metaboxhidden_nav-menus' ) !== false || ! is_array( $wp_meta_boxes ) ) {
		return;
	}

	$initial_meta_boxes = array( 'add-post-type-page', 'add-post-type-post', 'add-custom-links', 'add-category' );
	$hidden_meta_boxes  = array();

	foreach ( array_keys( $wp_meta_boxes['nav-menus'] ) as $context ) {
		foreach ( array_keys( $wp_meta_boxes['nav-menus'][ $context ] ) as $priority ) {
			foreach ( $wp_meta_boxes['nav-menus'][ $context ][ $priority ] as $box ) {
				if ( in_array( $box['id'], $initial_meta_boxes, true ) ) {
					unset( $box['id'] );
				} else {
					$hidden_meta_boxes[] = $box['id'];
				}
			}
		}
	}

	$user = wp_get_current_user();
	update_user_meta( $user->ID, 'metaboxhidden_nav-menus', $hidden_meta_boxes );
}

/**
 * Creates meta boxes for any post type menu item..
 *
 * @since 3.0.0
 */
function wp_nav_menu_post_type_meta_boxes() {
	$post_types = get_post_types( array( 'show_in_nav_menus' => true ), 'object' );

	if ( ! $post_types ) {
		return;
	}

	foreach ( $post_types as $post_type ) {
		/**
		 * Filters whether a menu items meta box will be added for the current
		 * object type.
		 *
		 * If a falsey value is returned instead of an object, the menu items
		 * meta box for the current meta box object will not be added.
		 *
		 * @since 3.0.0
		 *
		 * @param WP_Post_Type|false $post_type The current object to add a menu items
		 *                                      meta box for.
		 */
		$post_type = apply_filters( 'nav_menu_meta_box_object', $post_type );

		if ( $post_type ) {
			$id = $post_type->name;
			// Give pages a higher priority.
			$priority = ( 'page' === $post_type->name ? 'core' : 'default' );
			add_meta_box(
				"add-post-type-{$id}",
				$post_type->labels->name,
				'wp_nav_menu_item_post_type_meta_box',
				'nav-menus',
				'side',
				$priority,
				$post_type
			);
		}
	}
}

/**
 * Creates meta boxes for any taxonomy menu item.
 *
 * @since 3.0.0
 */
function wp_nav_menu_taxonomy_meta_boxes() {
	$taxonomies = get_taxonomies( array( 'show_in_nav_menus' => true ), 'object' );

	if ( ! $taxonomies ) {
		return;
	}

	foreach ( $taxonomies as $tax ) {
		/** This filter is documented in wp-admin/includes/nav-menu.php */
		$tax = apply_filters( 'nav_menu_meta_box_object', $tax );

		if ( $tax ) {
			$id = $tax->name;
			add_meta_box(
				"add-{$id}",
				$tax->labels->name,
				'wp_nav_menu_item_taxonomy_meta_box',
				'nav-menus',
				'side',
				'default',
				$tax
			);
		}
	}
}

/**
 * Check whether to disable the Menu Locations meta box submit button and inputs.
 *
 * @since 3.6.0
 * @since 5.3.1 The `$display` parameter was added.
 *
 * @global bool $one_theme_location_no_menus to determine if no menus exist
 *
 * @param int|string $nav_menu_selected_id ID, name, or slug of the currently selected menu.
 * @param bool       $display              Whether to display or just return the string.
 * @return string|false Disabled attribute if at least one menu exists, false if not.
 */
function wp_nav_menu_disabled_check( $nav_menu_selected_id, $display = true ) {
	global $one_theme_location_no_menus;

	if ( $one_theme_location_no_menus ) {
		return false;
	}

	return disabled( $nav_menu_selected_id, 0, $display );
}

/**
 * Displays a meta box for the custom links menu item.
 *
 * @since 3.0.0
 *
 * @global int        $_nav_menu_placeholder
 * @global int|string $nav_menu_selected_id
 */
function wp_nav_menu_item_link_meta_box() {
	global $_nav_menu_placeholder, $nav_menu_selected_id;

	$_nav_menu_placeholder = 0 > $_nav_menu_placeholder ? $_nav_menu_placeholder - 1 : -1;

	?>
	<div class="customlinkdiv" id="customlinkdiv">
		<input type="hidden" value="custom" name="menu-item[<?php echo $_nav_menu_placeholder; ?>][menu-item-type]" />
		<p id="menu-item-url-wrap" class="wp-clearfix">
			<label class="howto" for="custom-menu-item-url"><?php _e( 'URL' ); ?></label>
			<input id="custom-menu-item-url" name="menu-item[<?php echo $_nav_menu_placeholder; ?>][menu-item-url]"
				type="text"<?php wp_nav_menu_disabled_check( $nav_menu_selected_id ); ?>
				class="code menu-item-textbox form-required" placeholder="https://"
			/>
			<span id="custom-url-error" class="error-message" style="display: none;"><?php _e( 'Please provide a valid link.' ); ?></span>
		</p>

		<p id="menu-item-name-wrap" class="wp-clearfix">
			<label class="howto" for="custom-menu-item-name"><?php _e( 'Link Text' ); ?></label>
			<input id="custom-menu-item-name" name="menu-item[<?php echo $_nav_menu_placeholder; ?>][menu-item-title]"
				type="text"<?php wp_nav_menu_disabled_check( $nav_menu_selected_id ); ?>
				class="regular-text menu-item-textbox"
			/>
		</p>

		<p class="button-controls wp-clearfix">
			<span class="add-to-menu">
				<input id="submit-customlinkdiv" name="add-custom-menu-item"
					type="submit"<?php wp_nav_menu_disabled_check( $nav_menu_selected_id ); ?>
					class="button submit-add-to-menu right" value="<?php esc_attr_e( 'Add to Menu' ); ?>"
				/>
				<span class="spinner"></span>
			</span>
		</p>

	</div><!-- /.customlinkdiv -->
	<?php
}

/**
 * Displays a meta box for a post type menu item.
 *
 * @since 3.0.0
 *
 * @global int        $_nav_menu_placeholder
 * @global int|string $nav_menu_selected_id
 *
 * @param string $data_object Not used.
 * @param array  $box {
 *     Post type menu item meta box arguments.
 *
 *     @type string       $id       Meta box 'id' attribute.
 *     @type string       $title    Meta box title.
 *     @type callable     $callback Meta box display callback.
 *     @type WP_Post_Type $args     Extra meta box arguments (the post type object for this meta box).
 * }
 */
function wp_nav_menu_item_post_type_meta_box( $data_object, $box ) {
	global $_nav_menu_placeholder, $nav_menu_selected_id;

	$post_type_name = $box['args']->name;
	$post_type      = get_post_type_object( $post_type_name );
	$tab_name       = $post_type_name . '-tab';

	// Paginate browsing for large numbers of post objects.
	$per_page = 50;
	$pagenum  = isset( $_REQUEST[ $tab_name ] ) && isset( $_REQUEST['paged'] ) ? absint( $_REQUEST['paged'] ) : 1;
	$offset   = 0 < $pagenum ? $per_page * ( $pagenum - 1 ) : 0;

	$args = array(
		'offset'                 => $offset,
		'order'                  => 'ASC',
		'orderby'                => 'title',
		'posts_per_page'         => $per_page,
		'post_type'              => $post_type_name,
		'suppress_filters'       => true,
		'update_post_term_cache' => false,
		'update_post_meta_cache' => false,
	);

	if ( isset( $box['args']->_default_query ) ) {
		$args = array_merge( $args, (array) $box['args']->_default_query );
	}

	/*
	 * If we're dealing with pages, let's prioritize the Front Page,
	 * Posts Page and Privacy Policy Page at the top of the list.
	 */
	$important_pages = array();
	if ( 'page' === $post_type_name ) {
		$suppress_page_ids = array();

		// Insert Front Page or custom Home link.
		$front_page = 'page' === get_option( 'show_on_front' ) ? (int) get_option( 'page_on_front' ) : 0;

		$front_page_obj = null;

		if ( ! empty( $front_page ) ) {
			$front_page_obj = get_post( $front_page );
		}

		if ( $front_page_obj ) {
			$front_page_obj->front_or_home = true;

			$important_pages[]   = $front_page_obj;
			$suppress_page_ids[] = $front_page_obj->ID;
		} else {
			$_nav_menu_placeholder = ( 0 > $_nav_menu_placeholder ) ? (int) $_nav_menu_placeholder - 1 : -1;
			$front_page_obj        = (object) array(
				'front_or_home' => true,
				'ID'            => 0,
				'object_id'     => $_nav_menu_placeholder,
				'post_content'  => '',
				'post_excerpt'  => '',
				'post_parent'   => '',
				'post_title'    => _x( 'Home', 'nav menu home label' ),
				'post_type'     => 'nav_menu_item',
				'type'          => 'custom',
				'url'           => home_url( '/' ),
			);

			$important_pages[] = $front_page_obj;
		}

		// Insert Posts Page.
		$posts_page = 'page' === get_option( 'show_on_front' ) ? (int) get_option( 'page_for_posts' ) : 0;

		if ( ! empty( $posts_page ) ) {
			$posts_page_obj = get_post( $posts_page );

			if ( $posts_page_obj ) {
				$front_page_obj->posts_page = true;

				$important_pages[]   = $posts_page_obj;
				$suppress_page_ids[] = $posts_page_obj->ID;
			}
		}

		// Insert Privacy Policy Page.
		$privacy_policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' );

		if ( ! empty( $privacy_policy_page_id ) ) {
			$privacy_policy_page = get_post( $privacy_policy_page_id );

			if ( $privacy_policy_page instanceof WP_Post && 'publish' === $privacy_policy_page->post_status ) {
				$privacy_policy_page->privacy_policy_page = true;

				$important_pages[]   = $privacy_policy_page;
				$suppress_page_ids[] = $privacy_policy_page->ID;
			}
		}

		// Add suppression array to arguments for WP_Query.
		if ( ! empty( $suppress_page_ids ) ) {
			$args['post__not_in'] = $suppress_page_ids;
		}
	}

	$get_posts = new WP_Query();
	$posts     = $get_posts->query( $args );

	// Only suppress and insert when more than just suppression pages available.
	if ( ! $get_posts->post_count ) {
		if ( ! empty( $suppress_page_ids ) ) {
			unset( $args['post__not_in'] );
			$get_posts = new WP_Query();
			$posts     = $get_posts->query( $args );
		} else {
			echo '<p>' . __( 'No items.' ) . '</p>';
			return;
		}
	} elseif ( ! empty( $important_pages ) ) {
		$posts = array_merge( $important_pages, $posts );
	}

	$num_pages = $get_posts->max_num_pages;

	$page_links = paginate_links(
		array(
			'base'               => add_query_arg(
				array(
					$tab_name     => 'all',
					'paged'       => '%#%',
					'item-type'   => 'post_type',
					'item-object' => $post_type_name,
				)
			),
			'format'             => '',
			'prev_text'          => '<span aria-label="' . esc_attr__( 'Previous page' ) . '">' . __( '&laquo;' ) . '</span>',
			'next_text'          => '<span aria-label="' . esc_attr__( 'Next page' ) . '">' . __( '&raquo;' ) . '</span>',
			/* translators: Hidden accessibility text. */
			'before_page_number' => '<span class="screen-reader-text">' . __( 'Page' ) . '</span> ',
			'total'              => $num_pages,
			'current'            => $pagenum,
		)
	);

	$db_fields = false;
	if ( is_post_type_hierarchical( $post_type_name ) ) {
		$db_fields = array(
			'parent' => 'post_parent',
			'id'     => 'ID',
		);
	}

	$walker = new Walker_Nav_Menu_Checklist( $db_fields );

	$current_tab = 'most-recent';

	if ( isset( $_REQUEST[ $tab_name ] ) && in_array( $_REQUEST[ $tab_name ], array( 'all', 'search' ), true ) ) {
		$current_tab = $_REQUEST[ $tab_name ];
	}

	if ( ! empty( $_REQUEST[ "quick-search-posttype-{$post_type_name}" ] ) ) {
		$current_tab = 'search';
	}

	$removed_args = array(
		'action',
		'customlink-tab',
		'edit-menu-item',
		'menu-item',
		'page-tab',
		'_wpnonce',
	);

	$most_recent_url = '';
	$view_all_url    = '';
	$search_url      = '';

	if ( $nav_menu_selected_id ) {
		$most_recent_url = add_query_arg( $tab_name, 'most-recent', remove_query_arg( $removed_args ) );
		$view_all_url    = add_query_arg( $tab_name, 'all', remove_query_arg( $removed_args ) );
		$search_url      = add_query_arg( $tab_name, 'search', remove_query_arg( $removed_args ) );
	}
	?>
	<div id="<?php echo esc_attr( "posttype-{$post_type_name}" ); ?>" class="posttypediv">
		<ul id="<?php echo esc_attr( "posttype-{$post_type_name}-tabs" ); ?>" class="posttype-tabs add-menu-item-tabs">
			<li <?php echo ( 'most-recent' === $current_tab ? ' class="tabs"' : '' ); ?>>
				<a class="nav-tab-link"
					data-type="<?php echo esc_attr( "tabs-panel-posttype-{$post_type_name}-most-recent" ); ?>"
					href="<?php echo esc_url( $most_recent_url . "#tabs-panel-posttype-{$post_type_name}-most-recent" ); ?>"
				>
					<?php _e( 'Most Recent' ); ?>
				</a>
			</li>
			<li <?php echo ( 'all' === $current_tab ? ' class="tabs"' : '' ); ?>>
				<a class="nav-tab-link"
					data-type="<?php echo esc_attr( "{$post_type_name}-all" ); ?>"
					href="<?php echo esc_url( $view_all_url . "#{$post_type_name}-all" ); ?>"
				>
					<?php _e( 'View All' ); ?>
				</a>
			</li>
			<li <?php echo ( 'search' === $current_tab ? ' class="tabs"' : '' ); ?>>
				<a class="nav-tab-link"
					data-type="<?php echo esc_attr( "tabs-panel-posttype-{$post_type_name}-search" ); ?>"
					href="<?php echo esc_url( $search_url . "#tabs-panel-posttype-{$post_type_name}-search" ); ?>"
				>
					<?php _e( 'Search' ); ?>
				</a>
			</li>
		</ul><!-- .posttype-tabs -->

		<div id="<?php echo esc_attr( "tabs-panel-posttype-{$post_type_name}-most-recent" ); ?>"
			class="tabs-panel <?php echo ( 'most-recent' === $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive' ); ?>"
			role="region" aria-label="<?php esc_attr_e( 'Most Recent' ); ?>" tabindex="0"
		>
			<ul id="<?php echo esc_attr( "{$post_type_name}checklist-most-recent" ); ?>"
				class="categorychecklist form-no-clear"
			>
				<?php
				$recent_args = array_merge(
					$args,
					array(
						'orderby'        => 'post_date',
						'order'          => 'DESC',
						'posts_per_page' => 15,
					)
				);
				$most_recent = $get_posts->query( $recent_args );

				$args['walker'] = $walker;

				/**
				 * Filters the posts displayed in the 'Most Recent' tab of the current
				 * post type's menu items meta box.
				 *
				 * The dynamic portion of the hook name, `$post_type_name`, refers to the post type name.
				 *
				 * Possible hook names include:
				 *
				 *  - `nav_menu_items_post_recent`
				 *  - `nav_menu_items_page_recent`
				 *
				 * @since 4.3.0
				 * @since 4.9.0 Added the `$recent_args` parameter.
				 *
				 * @param WP_Post[] $most_recent An array of post objects being listed.
				 * @param array     $args        An array of `WP_Query` arguments for the meta box.
				 * @param array     $box         Arguments passed to `wp_nav_menu_item_post_type_meta_box()`.
				 * @param array     $recent_args An array of `WP_Query` arguments for 'Most Recent' tab.
				 */
				$most_recent = apply_filters(
					"nav_menu_items_{$post_type_name}_recent",
					$most_recent,
					$args,
					$box,
					$recent_args
				);

				echo walk_nav_menu_tree(
					array_map( 'wp_setup_nav_menu_item', $most_recent ),
					0,
					(object) $args
				);
				?>
			</ul>
		</div><!-- /.tabs-panel -->

		<div id="<?php echo esc_attr( "tabs-panel-posttype-{$post_type_name}-search" ); ?>"
			class="tabs-panel <?php echo ( 'search' === $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive' ); ?>"
			role="region" aria-label="<?php echo esc_attr( $post_type->labels->search_items ); ?>" tabindex="0"
		>
			<?php
			if ( isset( $_REQUEST[ "quick-search-posttype-{$post_type_name}" ] ) ) {
				$searched       = esc_attr( $_REQUEST[ "quick-search-posttype-{$post_type_name}" ] );
				$search_results = get_posts(
					array(
						's'         => $searched,
						'post_type' => $post_type_name,
						'fields'    => 'all',
						'order'     => 'DESC',
					)
				);
			} else {
				$searched       = '';
				$search_results = array();
			}
			?>
			<p class="quick-search-wrap">
				<label for="<?php echo esc_attr( "quick-search-posttype-{$post_type_name}" ); ?>" class="screen-reader-text">
					<?php
					/* translators: Hidden accessibility text. */
					_e( 'Search' );
					?>
				</label>
				<input type="search"<?php wp_nav_menu_disabled_check( $nav_menu_selected_id ); ?>
					class="quick-search" value="<?php echo $searched; ?>"
					name="<?php echo esc_attr( "quick-search-posttype-{$post_type_name}" ); ?>"
					id="<?php echo esc_attr( "quick-search-posttype-{$post_type_name}" ); ?>"
				/>
				<span class="spinner"></span>
				<?php
				submit_button(
					__( 'Search' ),
					'small quick-search-submit hide-if-js',
					'submit',
					false,
					array( 'id' => "submit-quick-search-posttype-{$post_type_name}" )
				);
				?>
			</p>

			<ul id="<?php echo esc_attr( "{$post_type_name}-search-checklist" ); ?>"
				data-wp-lists="<?php echo esc_attr( "list:{$post_type_name}" ); ?>"
				class="categorychecklist form-no-clear"
			>
			<?php if ( ! empty( $search_results ) && ! is_wp_error( $search_results ) ) : ?>
				<?php
				$args['walker'] = $walker;
				echo walk_nav_menu_tree(
					array_map( 'wp_setup_nav_menu_item', $search_results ),
					0,
					(object) $args
				);
				?>
			<?php elseif ( is_wp_error( $search_results ) ) : ?>
				<li><?php echo $search_results->get_error_message(); ?></li>
			<?php elseif ( ! empty( $searched ) ) : ?>
				<li><?php _e( 'No results found.' ); ?></li>
			<?php endif; ?>
			</ul>
		</div><!-- /.tabs-panel -->

		<div id="<?php echo esc_attr( "{$post_type_name}-all" ); ?>"
			class="tabs-panel tabs-panel-view-all <?php echo ( 'all' === $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive' ); ?>"
			role="region" aria-label="<?php echo esc_attr( $post_type->labels->all_items ); ?>" tabindex="0"
		>
			<?php if ( ! empty( $page_links ) ) : ?>
				<div class="add-menu-item-pagelinks">
					<?php echo $page_links; ?>
				</div>
			<?php endif; ?>

			<ul id="<?php echo esc_attr( "{$post_type_name}checklist" ); ?>"
				data-wp-lists="<?php echo esc_attr( "list:{$post_type_name}" ); ?>"
				class="categorychecklist form-no-clear"
			>
				<?php
				$args['walker'] = $walker;

				if ( $post_type->has_archive ) {
					$_nav_menu_placeholder = ( 0 > $_nav_menu_placeholder ) ? (int) $_nav_menu_placeholder - 1 : -1;
					array_unshift(
						$posts,
						(object) array(
							'ID'           => 0,
							'object_id'    => $_nav_menu_placeholder,
							'object'       => $post_type_name,
							'post_content' => '',
							'post_excerpt' => '',
							'post_title'   => $post_type->labels->archives,
							'post_type'    => 'nav_menu_item',
							'type'         => 'post_type_archive',
							'url'          => get_post_type_archive_link( $post_type_name ),
						)
					);
				}

				/**
				 * Filters the posts displayed in the 'View All' tab of the current
				 * post type's menu items meta box.
				 *
				 * The dynamic portion of the hook name, `$post_type_name`, refers
				 * to the slug of the current post type.
				 *
				 * Possible hook names include:
				 *
				 *  - `nav_menu_items_post`
				 *  - `nav_menu_items_page`
				 *
				 * @since 3.2.0
				 * @since 4.6.0 Converted the `$post_type` parameter to accept a WP_Post_Type object.
				 *
				 * @see WP_Query::query()
				 *
				 * @param object[]     $posts     The posts for the current post type. Mostly `WP_Post` objects, but
				 *                                can also contain "fake" post objects to represent other menu items.
				 * @param array        $args      An array of `WP_Query` arguments.
				 * @param WP_Post_Type $post_type The current post type object for this menu item meta box.
				 */
				$posts = apply_filters(
					"nav_menu_items_{$post_type_name}",
					$posts,
					$args,
					$post_type
				);

				$checkbox_items = walk_nav_menu_tree(
					array_map( 'wp_setup_nav_menu_item', $posts ),
					0,
					(object) $args
				);

				echo $checkbox_items;
				?>
			</ul>

			<?php if ( ! empty( $page_links ) ) : ?>
				<div class="add-menu-item-pagelinks">
					<?php echo $page_links; ?>
				</div>
			<?php endif; ?>
		</div><!-- /.tabs-panel -->

		<p class="button-controls wp-clearfix" data-items-type="<?php echo esc_attr( "posttype-{$post_type_name}" ); ?>">
			<span class="list-controls hide-if-no-js">
				<input type="checkbox"<?php wp_nav_menu_disabled_check( $nav_menu_selected_id ); ?>
					id="<?php echo esc_attr( $tab_name ); ?>" class="select-all"
				/>
				<label for="<?php echo esc_attr( $tab_name ); ?>"><?php _e( 'Select All' ); ?></label>
			</span>

			<span class="add-to-menu">
				<input type="submit"<?php wp_nav_menu_disabled_check( $nav_menu_selected_id ); ?>
					class="button submit-add-to-menu right" value="<?php esc_attr_e( 'Add to Menu' ); ?>"
					name="add-post-type-menu-item" id="<?php echo esc_attr( "submit-posttype-{$post_type_name}" ); ?>"
				/>
				<span class="spinner"></span>
			</span>
		</p>

	</div><!-- /.posttypediv -->
	<?php
}

/**
 * Displays a meta box for a taxonomy menu item.
 *
 * @since 3.0.0
 *
 * @global int|string $nav_menu_selected_id
 *
 * @param string $data_object Not used.
 * @param array  $box {
 *     Taxonomy menu item meta box arguments.
 *
 *     @type string   $id       Meta box 'id' attribute.
 *     @type string   $title    Meta box title.
 *     @type callable $callback Meta box display callback.
 *     @type object   $args     Extra meta box arguments (the taxonomy object for this meta box).
 * }
 */
function wp_nav_menu_item_taxonomy_meta_box( $data_object, $box ) {
	global $nav_menu_selected_id;

	$taxonomy_name = $box['args']->name;
	$taxonomy      = get_taxonomy( $taxonomy_name );
	$tab_name      = $taxonomy_name . '-tab';

	// Paginate browsing for large numbers of objects.
	$per_page = 50;
	$pagenum  = isset( $_REQUEST[ $tab_name ] ) && isset( $_REQUEST['paged'] ) ? absint( $_REQUEST['paged'] ) : 1;
	$offset   = 0 < $pagenum ? $per_page * ( $pagenum - 1 ) : 0;

	$args = array(
		'taxonomy'     => $taxonomy_name,
		'child_of'     => 0,
		'exclude'      => '',
		'hide_empty'   => false,
		'hierarchical' => 1,
		'include'      => '',
		'number'       => $per_page,
		'offset'       => $offset,
		'order'        => 'ASC',
		'orderby'      => 'name',
		'pad_counts'   => false,
	);

	$terms = get_terms( $args );

	if ( ! $terms || is_wp_error( $terms ) ) {
		echo '<p>' . __( 'No items.' ) . '</p>';
		return;
	}

	$num_pages = (int) ceil(
		(int) wp_count_terms(
			array_merge(
				$args,
				array(
					'number' => '',
					'offset' => '',
				)
			)
		) / $per_page
	);

	$page_links = paginate_links(
		array(
			'base'               => add_query_arg(
				array(
					$tab_name     => 'all',
					'paged'       => '%#%',
					'item-type'   => 'taxonomy',
					'item-object' => $taxonomy_name,
				)
			),
			'format'             => '',
			'prev_text'          => '<span aria-label="' . esc_attr__( 'Previous page' ) . '">' . __( '&laquo;' ) . '</span>',
			'next_text'          => '<span aria-label="' . esc_attr__( 'Next page' ) . '">' . __( '&raquo;' ) . '</span>',
			/* translators: Hidden accessibility text. */
			'before_page_number' => '<span class="screen-reader-text">' . __( 'Page' ) . '</span> ',
			'total'              => $num_pages,
			'current'            => $pagenum,
		)
	);

	$db_fields = false;
	if ( is_taxonomy_hierarchical( $taxonomy_name ) ) {
		$db_fields = array(
			'parent' => 'parent',
			'id'     => 'term_id',
		);
	}

	$walker = new Walker_Nav_Menu_Checklist( $db_fields );

	$current_tab = 'most-used';

	if ( isset( $_REQUEST[ $tab_name ] ) && in_array( $_REQUEST[ $tab_name ], array( 'all', 'most-used', 'search' ), true ) ) {
		$current_tab = $_REQUEST[ $tab_name ];
	}

	if ( ! empty( $_REQUEST[ "quick-search-taxonomy-{$taxonomy_name}" ] ) ) {
		$current_tab = 'search';
	}

	$removed_args = array(
		'action',
		'customlink-tab',
		'edit-menu-item',
		'menu-item',
		'page-tab',
		'_wpnonce',
	);

	$most_used_url = '';
	$view_all_url  = '';
	$search_url    = '';

	if ( $nav_menu_selected_id ) {
		$most_used_url = add_query_arg( $tab_name, 'most-used', remove_query_arg( $removed_args ) );
		$view_all_url  = add_query_arg( $tab_name, 'all', remove_query_arg( $removed_args ) );
		$search_url    = add_query_arg( $tab_name, 'search', remove_query_arg( $removed_args ) );
	}
	?>
	<div id="<?php echo esc_attr( "taxonomy-{$taxonomy_name}" ); ?>" class="taxonomydiv">
		<ul id="<?php echo esc_attr( "taxonomy-{$taxonomy_name}-tabs" ); ?>" class="taxonomy-tabs add-menu-item-tabs">
			<li <?php echo ( 'most-used' === $current_tab ? ' class="tabs"' : '' ); ?>>
				<a class="nav-tab-link"
					data-type="<?php echo esc_attr( "tabs-panel-{$taxonomy_name}-pop" ); ?>"
					href="<?php echo esc_url( $most_used_url . "#tabs-panel-{$taxonomy_name}-pop" ); ?>"
				>
					<?php echo esc_html( $taxonomy->labels->most_used ); ?>
				</a>
			</li>
			<li <?php echo ( 'all' === $current_tab ? ' class="tabs"' : '' ); ?>>
				<a class="nav-tab-link"
					data-type="<?php echo esc_attr( "tabs-panel-{$taxonomy_name}-all" ); ?>"
					href="<?php echo esc_url( $view_all_url . "#tabs-panel-{$taxonomy_name}-all" ); ?>"
				>
					<?php _e( 'View All' ); ?>
				</a>
			</li>
			<li <?php echo ( 'search' === $current_tab ? ' class="tabs"' : '' ); ?>>
				<a class="nav-tab-link"
					data-type="<?php echo esc_attr( "tabs-panel-search-taxonomy-{$taxonomy_name}" ); ?>"
					href="<?php echo esc_url( $search_url . "#tabs-panel-search-taxonomy-{$taxonomy_name}" ); ?>"
				>
					<?php _e( 'Search' ); ?>
				</a>
			</li>
		</ul><!-- .taxonomy-tabs -->

		<div id="<?php echo esc_attr( "tabs-panel-{$taxonomy_name}-pop" ); ?>"
			class="tabs-panel <?php echo ( 'most-used' === $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive' ); ?>"
			role="region" aria-label="<?php echo esc_attr( $taxonomy->labels->most_used ); ?>" tabindex="0"
		>
			<ul id="<?php echo esc_attr( "{$taxonomy_name}checklist-pop" ); ?>"
				class="categorychecklist form-no-clear"
			>
				<?php
				$popular_terms = get_terms(
					array(
						'taxonomy'     => $taxonomy_name,
						'orderby'      => 'count',
						'order'        => 'DESC',
						'number'       => 10,
						'hierarchical' => false,
					)
				);

				$args['walker'] = $walker;
				echo walk_nav_menu_tree(
					array_map( 'wp_setup_nav_menu_item', $popular_terms ),
					0,
					(object) $args
				);
				?>
			</ul>
		</div><!-- /.tabs-panel -->

		<div id="<?php echo esc_attr( "tabs-panel-{$taxonomy_name}-all" ); ?>"
			class="tabs-panel tabs-panel-view-all <?php echo ( 'all' === $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive' ); ?>"
			role="region" aria-label="<?php echo esc_attr( $taxonomy->labels->all_items ); ?>" tabindex="0"
		>
			<?php if ( ! empty( $page_links ) ) : ?>
				<div class="add-menu-item-pagelinks">
					<?php echo $page_links; ?>
				</div>
			<?php endif; ?>

			<ul id="<?php echo esc_attr( "{$taxonomy_name}checklist" ); ?>"
				data-wp-lists="<?php echo esc_attr( "list:{$taxonomy_name}" ); ?>"
				class="categorychecklist form-no-clear"
			>
				<?php
				$args['walker'] = $walker;
				echo walk_nav_menu_tree(
					array_map( 'wp_setup_nav_menu_item', $terms ),
					0,
					(object) $args
				);
				?>
			</ul>

			<?php if ( ! empty( $page_links ) ) : ?>
				<div class="add-menu-item-pagelinks">
					<?php echo $page_links; ?>
				</div>
			<?php endif; ?>
		</div><!-- /.tabs-panel -->

		<div id="<?php echo esc_attr( "tabs-panel-search-taxonomy-{$taxonomy_name}" ); ?>"
			class="tabs-panel <?php echo ( 'search' === $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive' ); ?>"
			role="region" aria-label="<?php echo esc_attr( $taxonomy->labels->search_items ); ?>" tabindex="0">
			<?php
			if ( isset( $_REQUEST[ "quick-search-taxonomy-{$taxonomy_name}" ] ) ) {
				$searched       = esc_attr( $_REQUEST[ "quick-search-taxonomy-{$taxonomy_name}" ] );
				$search_results = get_terms(
					array(
						'taxonomy'     => $taxonomy_name,
						'name__like'   => $searched,
						'fields'       => 'all',
						'orderby'      => 'count',
						'order'        => 'DESC',
						'hierarchical' => false,
					)
				);
			} else {
				$searched       = '';
				$search_results = array();
			}
			?>
			<p class="quick-search-wrap">
				<label for="<?php echo esc_attr( "quick-search-taxonomy-{$taxonomy_name}" ); ?>" class="screen-reader-text">
					<?php
					/* translators: Hidden accessibility text. */
					_e( 'Search' );
					?>
				</label>
				<input type="search"
					class="quick-search" value="<?php echo $searched; ?>"
					name="<?php echo esc_attr( "quick-search-taxonomy-{$taxonomy_name}" ); ?>"
					id="<?php echo esc_attr( "quick-search-taxonomy-{$taxonomy_name}" ); ?>"
				/>
				<span class="spinner"></span>
				<?php
				submit_button(
					__( 'Search' ),
					'small quick-search-submit hide-if-js',
					'submit',
					false,
					array( 'id' => "submit-quick-search-taxonomy-{$taxonomy_name}" )
				);
				?>
			</p>

			<ul id="<?php echo esc_attr( "{$taxonomy_name}-search-checklist" ); ?>"
				data-wp-lists="<?php echo esc_attr( "list:{$taxonomy_name}" ); ?>"
				class="categorychecklist form-no-clear"
			>
			<?php if ( ! empty( $search_results ) && ! is_wp_error( $search_results ) ) : ?>
				<?php
				$args['walker'] = $walker;
				echo walk_nav_menu_tree(
					array_map( 'wp_setup_nav_menu_item', $search_results ),
					0,
					(object) $args
				);
				?>
			<?php elseif ( is_wp_error( $search_results ) ) : ?>
				<li><?php echo $search_results->get_error_message(); ?></li>
			<?php elseif ( ! empty( $searched ) ) : ?>
				<li><?php _e( 'No results found.' ); ?></li>
			<?php endif; ?>
			</ul>
		</div><!-- /.tabs-panel -->

		<p class="button-controls wp-clearfix" data-items-type="<?php echo esc_attr( "taxonomy-{$taxonomy_name}" ); ?>">
			<span class="list-controls hide-if-no-js">
				<input type="checkbox"<?php wp_nav_menu_disabled_check( $nav_menu_selected_id ); ?>
					id="<?php echo esc_attr( $tab_name ); ?>" class="select-all"
				/>
				<label for="<?php echo esc_attr( $tab_name ); ?>"><?php _e( 'Select All' ); ?></label>
			</span>

			<span class="add-to-menu">
				<input type="submit"<?php wp_nav_menu_disabled_check( $nav_menu_selected_id ); ?>
					class="button submit-add-to-menu right" value="<?php esc_attr_e( 'Add to Menu' ); ?>"
					name="add-taxonomy-menu-item" id="<?php echo esc_attr( "submit-taxonomy-{$taxonomy_name}" ); ?>"
				/>
				<span class="spinner"></span>
			</span>
		</p>

	</div><!-- /.taxonomydiv -->
	<?php
}

/**
 * Save posted nav menu item data.
 *
 * @since 3.0.0
 *
 * @param int     $menu_id   The menu ID for which to save this item. Value of 0 makes a draft, orphaned menu item. Default 0.
 * @param array[] $menu_data The unsanitized POSTed menu item data.
 * @return int[] The database IDs of the items saved
 */
function wp_save_nav_menu_items( $menu_id = 0, $menu_data = array() ) {
	$menu_id     = (int) $menu_id;
	$items_saved = array();

	if ( 0 === $menu_id || is_nav_menu( $menu_id ) ) {

		// Loop through all the menu items' POST values.
		foreach ( (array) $menu_data as $_possible_db_id => $_item_object_data ) {
			if (
				// Checkbox is not checked.
				empty( $_item_object_data['menu-item-object-id'] ) &&
				(
					// And item type either isn't set.
					! isset( $_item_object_data['menu-item-type'] ) ||
					// Or URL is the default.
					in_array( $_item_object_data['menu-item-url'], array( 'https://', 'http://', '' ), true ) ||
					// Or it's not a custom menu item (but not the custom home page).
					! ( 'custom' === $_item_object_data['menu-item-type'] && ! isset( $_item_object_data['menu-item-db-id'] ) ) ||
					// Or it *is* a custom menu item that already exists.
					! empty( $_item_object_data['menu-item-db-id'] )
				)
			) {
				// Then this potential menu item is not getting added to this menu.
				continue;
			}

			// If this possible menu item doesn't actually have a menu database ID yet.
			if (
				empty( $_item_object_data['menu-item-db-id'] ) ||
				( 0 > $_possible_db_id ) ||
				$_possible_db_id !== (int) $_item_object_data['menu-item-db-id']
			) {
				$_actual_db_id = 0;
			} else {
				$_actual_db_id = (int) $_item_object_data['menu-item-db-id'];
			}

			$args = array(
				'menu-item-db-id'       => ( isset( $_item_object_data['menu-item-db-id'] ) ? $_item_object_data['menu-item-db-id'] : '' ),
				'menu-item-object-id'   => ( isset( $_item_object_data['menu-item-object-id'] ) ? $_item_object_data['menu-item-object-id'] : '' ),
				'menu-item-object'      => ( isset( $_item_object_data['menu-item-object'] ) ? $_item_object_data['menu-item-object'] : '' ),
				'menu-item-parent-id'   => ( isset( $_item_object_data['menu-item-parent-id'] ) ? $_item_object_data['menu-item-parent-id'] : '' ),
				'menu-item-position'    => ( isset( $_item_object_data['menu-item-position'] ) ? $_item_object_data['menu-item-position'] : '' ),
				'menu-item-type'        => ( isset( $_item_object_data['menu-item-type'] ) ? $_item_object_data['menu-item-type'] : '' ),
				'menu-item-title'       => ( isset( $_item_object_data['menu-item-title'] ) ? $_item_object_data['menu-item-title'] : '' ),
				'menu-item-url'         => ( isset( $_item_object_data['menu-item-url'] ) ? $_item_object_data['menu-item-url'] : '' ),
				'menu-item-description' => ( isset( $_item_object_data['menu-item-description'] ) ? $_item_object_data['menu-item-description'] : '' ),
				'menu-item-attr-title'  => ( isset( $_item_object_data['menu-item-attr-title'] ) ? $_item_object_data['menu-item-attr-title'] : '' ),
				'menu-item-target'      => ( isset( $_item_object_data['menu-item-target'] ) ? $_item_object_data['menu-item-target'] : '' ),
				'menu-item-classes'     => ( isset( $_item_object_data['menu-item-classes'] ) ? $_item_object_data['menu-item-classes'] : '' ),
				'menu-item-xfn'         => ( isset( $_item_object_data['menu-item-xfn'] ) ? $_item_object_data['menu-item-xfn'] : '' ),
			);

			$items_saved[] = wp_update_nav_menu_item( $menu_id, $_actual_db_id, $args );

		}
	}

	return $items_saved;
}

/**
 * Adds custom arguments to some of the meta box object types.
 *
 * @since 3.0.0
 *
 * @access private
 *
 * @param object $data_object The post type or taxonomy meta-object.
 * @return object The post type or taxonomy object.
 */
function _wp_nav_menu_meta_box_object( $data_object = null ) {
	if ( isset( $data_object->name ) ) {

		if ( 'page' === $data_object->name ) {
			$data_object->_default_query = array(
				'orderby'     => 'menu_order title',
				'post_status' => 'publish',
			);

			// Posts should show only published items.
		} elseif ( 'post' === $data_object->name ) {
			$data_object->_default_query = array(
				'post_status' => 'publish',
			);

			// Categories should be in reverse chronological order.
		} elseif ( 'category' === $data_object->name ) {
			$data_object->_default_query = array(
				'orderby' => 'id',
				'order'   => 'DESC',
			);

			// Custom post types should show only published items.
		} else {
			$data_object->_default_query = array(
				'post_status' => 'publish',
			);
		}
	}

	return $data_object;
}

/**
 * Returns the menu formatted to edit.
 *
 * @since 3.0.0
 *
 * @param int $menu_id Optional. The ID of the menu to format. Default 0.
 * @return string|WP_Error|null The menu formatted to edit or error object on failure.
 *                              Null if the `$menu_id` parameter is not supplied or the term does not exist.
 */
function wp_get_nav_menu_to_edit( $menu_id = 0 ) {
	$menu = wp_get_nav_menu_object( $menu_id );

	// If the menu exists, get its items.
	if ( is_nav_menu( $menu ) ) {
		$menu_items = wp_get_nav_menu_items( $menu->term_id, array( 'post_status' => 'any' ) );
		$result     = '<div id="menu-instructions" class="post-body-plain';
		$result    .= ( ! empty( $menu_items ) ) ? ' menu-instructions-inactive">' : '">';
		$result    .= '<p>' . __( 'Add menu items from the column on the left.' ) . '</p>';
		$result    .= '</div>';

		if ( empty( $menu_items ) ) {
			return $result . ' <ul class="menu" id="menu-to-edit"> </ul>';
		}

		/**
		 * Filters the Walker class used when adding nav menu items.
		 *
		 * @since 3.0.0
		 *
		 * @param string $class   The walker class to use. Default 'Walker_Nav_Menu_Edit'.
		 * @param int    $menu_id ID of the menu being rendered.
		 */
		$walker_class_name = apply_filters( 'wp_edit_nav_menu_walker', 'Walker_Nav_Menu_Edit', $menu_id );

		if ( class_exists( $walker_class_name ) ) {
			$walker = new $walker_class_name();
		} else {
			return new WP_Error(
				'menu_walker_not_exist',
				sprintf(
					/* translators: %s: Walker class name. */
					__( 'The Walker class named %s does not exist.' ),
					'<strong>' . $walker_class_name . '</strong>'
				)
			);
		}

		$some_pending_menu_items = false;
		$some_invalid_menu_items = false;

		foreach ( (array) $menu_items as $menu_item ) {
			if ( isset( $menu_item->post_status ) && 'draft' === $menu_item->post_status ) {
				$some_pending_menu_items = true;
			}
			if ( ! empty( $menu_item->_invalid ) ) {
				$some_invalid_menu_items = true;
			}
		}

		if ( $some_pending_menu_items ) {
			$message     = __( 'Click Save Menu to make pending menu items public.' );
			$notice_args = array(
				'type'               => 'info',
				'additional_classes' => array( 'notice-alt', 'inline' ),
			);
			$result     .= wp_get_admin_notice( $message, $notice_args );
		}

		if ( $some_invalid_menu_items ) {
			$message     = __( 'There are some invalid menu items. Please check or delete them.' );
			$notice_args = array(
				'type'               => 'error',
				'additional_classes' => array( 'notice-alt', 'inline' ),
			);
			$result     .= wp_get_admin_notice( $message, $notice_args );
		}

		$result .= '<ul class="menu" id="menu-to-edit"> ';
		$result .= walk_nav_menu_tree(
			array_map( 'wp_setup_nav_menu_item', $menu_items ),
			0,
			(object) array( 'walker' => $walker )
		);
		$result .= ' </ul> ';

		return $result;
	} elseif ( is_wp_error( $menu ) ) {
		return $menu;
	}

	return null;
}

/**
 * Returns the columns for the nav menus page.
 *
 * @since 3.0.0
 *
 * @return string[] Array of column titles keyed by their column name.
 */
function wp_nav_menu_manage_columns() {
	return array(
		'_title'          => __( 'Show advanced menu properties' ),
		'cb'              => '<input type="checkbox" />',
		'link-target'     => __( 'Link Target' ),
		'title-attribute' => __( 'Title Attribute' ),
		'css-classes'     => __( 'CSS Classes' ),
		'xfn'             => __( 'Link Relationship (XFN)' ),
		'description'     => __( 'Description' ),
	);
}

/**
 * Deletes orphaned draft menu items
 *
 * @access private
 * @since 3.0.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 */
function _wp_delete_orphaned_draft_menu_items() {
	global $wpdb;

	$delete_timestamp = time() - ( DAY_IN_SECONDS * EMPTY_TRASH_DAYS );

	// Delete orphaned draft menu items.
	$menu_items_to_delete = $wpdb->get_col(
		$wpdb->prepare(
			"SELECT ID FROM $wpdb->posts AS p
			LEFT JOIN $wpdb->postmeta AS m ON p.ID = m.post_id
			WHERE post_type = 'nav_menu_item' AND post_status = 'draft'
			AND meta_key = '_menu_item_orphaned' AND meta_value < %d",
			$delete_timestamp
		)
	);

	foreach ( (array) $menu_items_to_delete as $menu_item_id ) {
		wp_delete_post( $menu_item_id, true );
	}
}

/**
 * Saves nav menu items.
 *
 * @since 3.6.0
 *
 * @param int|string $nav_menu_selected_id    ID, slug, or name of the currently-selected menu.
 * @param string     $nav_menu_selected_title Title of the currently-selected menu.
 * @return string[] The menu updated messages.
 */
function wp_nav_menu_update_menu_items( $nav_menu_selected_id, $nav_menu_selected_title ) {
	$unsorted_menu_items = wp_get_nav_menu_items(
		$nav_menu_selected_id,
		array(
			'orderby'     => 'ID',
			'output'      => ARRAY_A,
			'output_key'  => 'ID',
			'post_status' => 'draft,publish',
		)
	);

	$messages   = array();
	$menu_items = array();

	// Index menu items by DB ID.
	foreach ( $unsorted_menu_items as $_item ) {
		$menu_items[ $_item->db_id ] = $_item;
	}

	$post_fields = array(
		'menu-item-db-id',
		'menu-item-object-id',
		'menu-item-object',
		'menu-item-parent-id',
		'menu-item-position',
		'menu-item-type',
		'menu-item-title',
		'menu-item-url',
		'menu-item-description',
		'menu-item-attr-title',
		'menu-item-target',
		'menu-item-classes',
		'menu-item-xfn',
	);

	wp_defer_term_counting( true );

	// Loop through all the menu items' POST variables.
	if ( ! empty( $_POST['menu-item-db-id'] ) ) {
		foreach ( (array) $_POST['menu-item-db-id'] as $_key => $k ) {

			// Menu item title can't be blank.
			if ( ! isset( $_POST['menu-item-title'][ $_key ] ) || '' === $_POST['menu-item-title'][ $_key ] ) {
				continue;
			}

			$args = array();
			foreach ( $post_fields as $field ) {
				$args[ $field ] = isset( $_POST[ $field ][ $_key ] ) ? $_POST[ $field ][ $_key ] : '';
			}

			$menu_item_db_id = wp_update_nav_menu_item(
				$nav_menu_selected_id,
				( (int) $_POST['menu-item-db-id'][ $_key ] !== $_key ? 0 : $_key ),
				$args
			);

			if ( is_wp_error( $menu_item_db_id ) ) {
				$messages[] = wp_get_admin_notice(
					$menu_item_db_id->get_error_message(),
					array(
						'id'                 => 'message',
						'additional_classes' => array( 'error' ),
					)
				);
			} else {
				unset( $menu_items[ $menu_item_db_id ] );
			}
		}
	}

	// Remove menu items from the menu that weren't in $_POST.
	if ( ! empty( $menu_items ) ) {
		foreach ( array_keys( $menu_items ) as $menu_item_id ) {
			if ( is_nav_menu_item( $menu_item_id ) ) {
				wp_delete_post( $menu_item_id );
			}
		}
	}

	// Store 'auto-add' pages.
	$auto_add        = ! empty( $_POST['auto-add-pages'] );
	$nav_menu_option = (array) get_option( 'nav_menu_options' );

	if ( ! isset( $nav_menu_option['auto_add'] ) ) {
		$nav_menu_option['auto_add'] = array();
	}

	if ( $auto_add ) {
		if ( ! in_array( $nav_menu_selected_id, $nav_menu_option['auto_add'], true ) ) {
			$nav_menu_option['auto_add'][] = $nav_menu_selected_id;
		}
	} else {
		$key = array_search( $nav_menu_selected_id, $nav_menu_option['auto_add'], true );
		if ( false !== $key ) {
			unset( $nav_menu_option['auto_add'][ $key ] );
		}
	}

	// Remove non-existent/deleted menus.
	$nav_menu_option['auto_add'] = array_intersect(
		$nav_menu_option['auto_add'],
		wp_get_nav_menus( array( 'fields' => 'ids' ) )
	);

	update_option( 'nav_menu_options', $nav_menu_option, false );

	wp_defer_term_counting( false );

	/** This action is documented in wp-includes/nav-menu.php */
	do_action( 'wp_update_nav_menu', $nav_menu_selected_id );

	/* translators: %s: Nav menu title. */
	$message     = sprintf( __( '%s has been updated.' ), '<strong>' . $nav_menu_selected_title . '</strong>' );
	$notice_args = array(
		'id'                 => 'message',
		'dismissible'        => true,
		'additional_classes' => array( 'updated' ),
	);

	$messages[] = wp_get_admin_notice( $message, $notice_args );

	unset( $menu_items, $unsorted_menu_items );

	return $messages;
}

/**
 * If a JSON blob of navigation menu data is in POST data, expand it and inject
 * it into `$_POST` to avoid PHP `max_input_vars` limitations. See #14134.
 *
 * @ignore
 * @since 4.5.3
 * @access private
 */
function _wp_expand_nav_menu_post_data() {
	if ( ! isset( $_POST['nav-menu-data'] ) ) {
		return;
	}

	$data = json_decode( stripslashes( $_POST['nav-menu-data'] ) );

	if ( ! is_null( $data ) && $data ) {
		foreach ( $data as $post_input_data ) {
			/*
			 * For input names that are arrays (e.g. `menu-item-db-id[3][4][5]`),
			 * derive the array path keys via regex and set the value in $_POST.
			 */
			preg_match( '#([^\[]*)(\[(.+)\])?#', $post_input_data->name, $matches );

			$array_bits = array( $matches[1] );

			if ( isset( $matches[3] ) ) {
				$array_bits = array_merge( $array_bits, explode( '][', $matches[3] ) );
			}

			$new_post_data = array();

			// Build the new array value from leaf to trunk.
			for ( $i = count( $array_bits ) - 1; $i >= 0; $i-- ) {
				if ( count( $array_bits ) - 1 === $i ) {
					$new_post_data[ $array_bits[ $i ] ] = wp_slash( $post_input_data->value );
				} else {
					$new_post_data = array( $array_bits[ $i ] => $new_post_data );
				}
			}

			$_POST = array_replace_recursive( $_POST, $new_post_data );
		}
	}
}
plugin.php000064400000266517151212616040006572 0ustar00<?php
/**
 * WordPress Plugin Administration API
 *
 * @package WordPress
 * @subpackage Administration
 */

/**
 * Parses the plugin contents to retrieve plugin's metadata.
 *
 * All plugin headers must be on their own line. Plugin description must not have
 * any newlines, otherwise only parts of the description will be displayed.
 * The below is formatted for printing.
 *
 *     /*
 *     Plugin Name: Name of the plugin.
 *     Plugin URI: The home page of the plugin.
 *     Description: Plugin description.
 *     Author: Plugin author's name.
 *     Author URI: Link to the author's website.
 *     Version: Plugin version.
 *     Text Domain: Optional. Unique identifier, should be same as the one used in
 *          load_plugin_textdomain().
 *     Domain Path: Optional. Only useful if the translations are located in a
 *          folder above the plugin's base path. For example, if .mo files are
 *          located in the locale folder then Domain Path will be "/locale/" and
 *          must have the first slash. Defaults to the base folder the plugin is
 *          located in.
 *     Network: Optional. Specify "Network: true" to require that a plugin is activated
 *          across all sites in an installation. This will prevent a plugin from being
 *          activated on a single site when Multisite is enabled.
 *     Requires at least: Optional. Specify the minimum required WordPress version.
 *     Requires PHP: Optional. Specify the minimum required PHP version.
 *     * / # Remove the space to close comment.
 *
 * The first 8 KB of the file will be pulled in and if the plugin data is not
 * within that first 8 KB, then the plugin author should correct their plugin
 * and move the plugin data headers to the top.
 *
 * The plugin file is assumed to have permissions to allow for scripts to read
 * the file. This is not checked however and the file is only opened for
 * reading.
 *
 * @since 1.5.0
 * @since 5.3.0 Added support for `Requires at least` and `Requires PHP` headers.
 * @since 5.8.0 Added support for `Update URI` header.
 * @since 6.5.0 Added support for `Requires Plugins` header.
 *
 * @param string $plugin_file Absolute path to the main plugin file.
 * @param bool   $markup      Optional. If the returned data should have HTML markup applied.
 *                            Default true.
 * @param bool   $translate   Optional. If the returned data should be translated. Default true.
 * @return array {
 *     Plugin data. Values will be empty if not supplied by the plugin.
 *
 *     @type string $Name            Name of the plugin. Should be unique.
 *     @type string $PluginURI       Plugin URI.
 *     @type string $Version         Plugin version.
 *     @type string $Description     Plugin description.
 *     @type string $Author          Plugin author's name.
 *     @type string $AuthorURI       Plugin author's website address (if set).
 *     @type string $TextDomain      Plugin textdomain.
 *     @type string $DomainPath      Plugin's relative directory path to .mo files.
 *     @type bool   $Network         Whether the plugin can only be activated network-wide.
 *     @type string $RequiresWP      Minimum required version of WordPress.
 *     @type string $RequiresPHP     Minimum required version of PHP.
 *     @type string $UpdateURI       ID of the plugin for update purposes, should be a URI.
 *     @type string $RequiresPlugins Comma separated list of dot org plugin slugs.
 *     @type string $Title           Title of the plugin and link to the plugin's site (if set).
 *     @type string $AuthorName      Plugin author's name.
 * }
 */
function get_plugin_data( $plugin_file, $markup = true, $translate = true ) {

	$default_headers = array(
		'Name'            => 'Plugin Name',
		'PluginURI'       => 'Plugin URI',
		'Version'         => 'Version',
		'Description'     => 'Description',
		'Author'          => 'Author',
		'AuthorURI'       => 'Author URI',
		'TextDomain'      => 'Text Domain',
		'DomainPath'      => 'Domain Path',
		'Network'         => 'Network',
		'RequiresWP'      => 'Requires at least',
		'RequiresPHP'     => 'Requires PHP',
		'UpdateURI'       => 'Update URI',
		'RequiresPlugins' => 'Requires Plugins',
		// Site Wide Only is deprecated in favor of Network.
		'_sitewide'       => 'Site Wide Only',
	);

	$plugin_data = get_file_data( $plugin_file, $default_headers, 'plugin' );

	// Site Wide Only is the old header for Network.
	if ( ! $plugin_data['Network'] && $plugin_data['_sitewide'] ) {
		/* translators: 1: Site Wide Only: true, 2: Network: true */
		_deprecated_argument( __FUNCTION__, '3.0.0', sprintf( __( 'The %1$s plugin header is deprecated. Use %2$s instead.' ), '<code>Site Wide Only: true</code>', '<code>Network: true</code>' ) );
		$plugin_data['Network'] = $plugin_data['_sitewide'];
	}
	$plugin_data['Network'] = ( 'true' === strtolower( $plugin_data['Network'] ) );
	unset( $plugin_data['_sitewide'] );

	// If no text domain is defined fall back to the plugin slug.
	if ( ! $plugin_data['TextDomain'] ) {
		$plugin_slug = dirname( plugin_basename( $plugin_file ) );
		if ( '.' !== $plugin_slug && ! str_contains( $plugin_slug, '/' ) ) {
			$plugin_data['TextDomain'] = $plugin_slug;
		}
	}

	if ( $markup || $translate ) {
		$plugin_data = _get_plugin_data_markup_translate( $plugin_file, $plugin_data, $markup, $translate );
	} else {
		$plugin_data['Title']      = $plugin_data['Name'];
		$plugin_data['AuthorName'] = $plugin_data['Author'];
	}

	return $plugin_data;
}

/**
 * Sanitizes plugin data, optionally adds markup, optionally translates.
 *
 * @since 2.7.0
 *
 * @see get_plugin_data()
 *
 * @access private
 *
 * @param string $plugin_file Path to the main plugin file.
 * @param array  $plugin_data An array of plugin data. See get_plugin_data().
 * @param bool   $markup      Optional. If the returned data should have HTML markup applied.
 *                            Default true.
 * @param bool   $translate   Optional. If the returned data should be translated. Default true.
 * @return array Plugin data. Values will be empty if not supplied by the plugin.
 *               See get_plugin_data() for the list of possible values.
 */
function _get_plugin_data_markup_translate( $plugin_file, $plugin_data, $markup = true, $translate = true ) {

	// Sanitize the plugin filename to a WP_PLUGIN_DIR relative path.
	$plugin_file = plugin_basename( $plugin_file );

	// Translate fields.
	if ( $translate ) {
		$textdomain = $plugin_data['TextDomain'];
		if ( $textdomain ) {
			if ( ! is_textdomain_loaded( $textdomain ) ) {
				if ( $plugin_data['DomainPath'] ) {
					load_plugin_textdomain( $textdomain, false, dirname( $plugin_file ) . $plugin_data['DomainPath'] );
				} else {
					load_plugin_textdomain( $textdomain, false, dirname( $plugin_file ) );
				}
			}
		} elseif ( 'hello.php' === basename( $plugin_file ) ) {
			$textdomain = 'default';
		}
		if ( $textdomain ) {
			foreach ( array( 'Name', 'PluginURI', 'Description', 'Author', 'AuthorURI', 'Version' ) as $field ) {
				if ( ! empty( $plugin_data[ $field ] ) ) {
					// phpcs:ignore WordPress.WP.I18n.LowLevelTranslationFunction,WordPress.WP.I18n.NonSingularStringLiteralText,WordPress.WP.I18n.NonSingularStringLiteralDomain
					$plugin_data[ $field ] = translate( $plugin_data[ $field ], $textdomain );
				}
			}
		}
	}

	// Sanitize fields.
	$allowed_tags_in_links = array(
		'abbr'    => array( 'title' => true ),
		'acronym' => array( 'title' => true ),
		'code'    => true,
		'em'      => true,
		'strong'  => true,
	);

	$allowed_tags      = $allowed_tags_in_links;
	$allowed_tags['a'] = array(
		'href'  => true,
		'title' => true,
	);

	/*
	 * Name is marked up inside <a> tags. Don't allow these.
	 * Author is too, but some plugins have used <a> here (omitting Author URI).
	 */
	$plugin_data['Name']   = wp_kses( $plugin_data['Name'], $allowed_tags_in_links );
	$plugin_data['Author'] = wp_kses( $plugin_data['Author'], $allowed_tags );

	$plugin_data['Description'] = wp_kses( $plugin_data['Description'], $allowed_tags );
	$plugin_data['Version']     = wp_kses( $plugin_data['Version'], $allowed_tags );

	$plugin_data['PluginURI'] = esc_url( $plugin_data['PluginURI'] );
	$plugin_data['AuthorURI'] = esc_url( $plugin_data['AuthorURI'] );

	$plugin_data['Title']      = $plugin_data['Name'];
	$plugin_data['AuthorName'] = $plugin_data['Author'];

	// Apply markup.
	if ( $markup ) {
		if ( $plugin_data['PluginURI'] && $plugin_data['Name'] ) {
			$plugin_data['Title'] = '<a href="' . $plugin_data['PluginURI'] . '">' . $plugin_data['Name'] . '</a>';
		}

		if ( $plugin_data['AuthorURI'] && $plugin_data['Author'] ) {
			$plugin_data['Author'] = '<a href="' . $plugin_data['AuthorURI'] . '">' . $plugin_data['Author'] . '</a>';
		}

		$plugin_data['Description'] = wptexturize( $plugin_data['Description'] );

		if ( $plugin_data['Author'] ) {
			$plugin_data['Description'] .= sprintf(
				/* translators: %s: Plugin author. */
				' <cite>' . __( 'By %s.' ) . '</cite>',
				$plugin_data['Author']
			);
		}
	}

	return $plugin_data;
}

/**
 * Gets a list of a plugin's files.
 *
 * @since 2.8.0
 *
 * @param string $plugin Path to the plugin file relative to the plugins directory.
 * @return string[] Array of file names relative to the plugin root.
 */
function get_plugin_files( $plugin ) {
	$plugin_file = WP_PLUGIN_DIR . '/' . $plugin;
	$dir         = dirname( $plugin_file );

	$plugin_files = array( plugin_basename( $plugin_file ) );

	if ( is_dir( $dir ) && WP_PLUGIN_DIR !== $dir ) {

		/**
		 * Filters the array of excluded directories and files while scanning the folder.
		 *
		 * @since 4.9.0
		 *
		 * @param string[] $exclusions Array of excluded directories and files.
		 */
		$exclusions = (array) apply_filters( 'plugin_files_exclusions', array( 'CVS', 'node_modules', 'vendor', 'bower_components' ) );

		$list_files = list_files( $dir, 100, $exclusions );
		$list_files = array_map( 'plugin_basename', $list_files );

		$plugin_files = array_merge( $plugin_files, $list_files );
		$plugin_files = array_values( array_unique( $plugin_files ) );
	}

	return $plugin_files;
}

/**
 * Checks the plugins directory and retrieve all plugin files with plugin data.
 *
 * WordPress only supports plugin files in the base plugins directory
 * (wp-content/plugins) and in one directory above the plugins directory
 * (wp-content/plugins/my-plugin). The file it looks for has the plugin data
 * and must be found in those two locations. It is recommended to keep your
 * plugin files in their own directories.
 *
 * The file with the plugin data is the file that will be included and therefore
 * needs to have the main execution for the plugin. This does not mean
 * everything must be contained in the file and it is recommended that the file
 * be split for maintainability. Keep everything in one file for extreme
 * optimization purposes.
 *
 * @since 1.5.0
 *
 * @param string $plugin_folder Optional. Relative path to single plugin folder.
 * @return array[] Array of arrays of plugin data, keyed by plugin file name. See get_plugin_data().
 */
function get_plugins( $plugin_folder = '' ) {

	$cache_plugins = wp_cache_get( 'plugins', 'plugins' );
	if ( ! $cache_plugins ) {
		$cache_plugins = array();
	}

	if ( isset( $cache_plugins[ $plugin_folder ] ) ) {
		return $cache_plugins[ $plugin_folder ];
	}

	$wp_plugins  = array();
	$plugin_root = WP_PLUGIN_DIR;
	if ( ! empty( $plugin_folder ) ) {
		$plugin_root .= $plugin_folder;
	}

	// Files in wp-content/plugins directory.
	$plugins_dir  = @opendir( $plugin_root );
	$plugin_files = array();

	if ( $plugins_dir ) {
		while ( ( $file = readdir( $plugins_dir ) ) !== false ) {
			if ( str_starts_with( $file, '.' ) ) {
				continue;
			}

			if ( is_dir( $plugin_root . '/' . $file ) ) {
				$plugins_subdir = @opendir( $plugin_root . '/' . $file );

				if ( $plugins_subdir ) {
					while ( ( $subfile = readdir( $plugins_subdir ) ) !== false ) {
						if ( str_starts_with( $subfile, '.' ) ) {
							continue;
						}

						if ( str_ends_with( $subfile, '.php' ) ) {
							$plugin_files[] = "$file/$subfile";
						}
					}

					closedir( $plugins_subdir );
				}
			} elseif ( str_ends_with( $file, '.php' ) ) {
				$plugin_files[] = $file;
			}
		}

		closedir( $plugins_dir );
	}

	if ( empty( $plugin_files ) ) {
		return $wp_plugins;
	}

	foreach ( $plugin_files as $plugin_file ) {
		if ( ! is_readable( "$plugin_root/$plugin_file" ) ) {
			continue;
		}

		// Do not apply markup/translate as it will be cached.
		$plugin_data = get_plugin_data( "$plugin_root/$plugin_file", false, false );

		if ( empty( $plugin_data['Name'] ) ) {
			continue;
		}

		$wp_plugins[ plugin_basename( $plugin_file ) ] = $plugin_data;
	}

	uasort( $wp_plugins, '_sort_uname_callback' );

	$cache_plugins[ $plugin_folder ] = $wp_plugins;
	wp_cache_set( 'plugins', $cache_plugins, 'plugins' );

	return $wp_plugins;
}

/**
 * Checks the mu-plugins directory and retrieve all mu-plugin files with any plugin data.
 *
 * WordPress only includes mu-plugin files in the base mu-plugins directory (wp-content/mu-plugins).
 *
 * @since 3.0.0
 * @return array[] Array of arrays of mu-plugin data, keyed by plugin file name. See get_plugin_data().
 */
function get_mu_plugins() {
	$wp_plugins   = array();
	$plugin_files = array();

	if ( ! is_dir( WPMU_PLUGIN_DIR ) ) {
		return $wp_plugins;
	}

	// Files in wp-content/mu-plugins directory.
	$plugins_dir = @opendir( WPMU_PLUGIN_DIR );
	if ( $plugins_dir ) {
		while ( ( $file = readdir( $plugins_dir ) ) !== false ) {
			if ( str_ends_with( $file, '.php' ) ) {
				$plugin_files[] = $file;
			}
		}
	} else {
		return $wp_plugins;
	}

	closedir( $plugins_dir );

	if ( empty( $plugin_files ) ) {
		return $wp_plugins;
	}

	foreach ( $plugin_files as $plugin_file ) {
		if ( ! is_readable( WPMU_PLUGIN_DIR . "/$plugin_file" ) ) {
			continue;
		}

		// Do not apply markup/translate as it will be cached.
		$plugin_data = get_plugin_data( WPMU_PLUGIN_DIR . "/$plugin_file", false, false );

		if ( empty( $plugin_data['Name'] ) ) {
			$plugin_data['Name'] = $plugin_file;
		}

		$wp_plugins[ $plugin_file ] = $plugin_data;
	}

	if ( isset( $wp_plugins['index.php'] ) && filesize( WPMU_PLUGIN_DIR . '/index.php' ) <= 30 ) {
		// Silence is golden.
		unset( $wp_plugins['index.php'] );
	}

	uasort( $wp_plugins, '_sort_uname_callback' );

	return $wp_plugins;
}

/**
 * Declares a callback to sort array by a 'Name' key.
 *
 * @since 3.1.0
 *
 * @access private
 *
 * @param array $a array with 'Name' key.
 * @param array $b array with 'Name' key.
 * @return int Return 0 or 1 based on two string comparison.
 */
function _sort_uname_callback( $a, $b ) {
	return strnatcasecmp( $a['Name'], $b['Name'] );
}

/**
 * Checks the wp-content directory and retrieve all drop-ins with any plugin data.
 *
 * @since 3.0.0
 * @return array[] Array of arrays of dropin plugin data, keyed by plugin file name. See get_plugin_data().
 */
function get_dropins() {
	$dropins      = array();
	$plugin_files = array();

	$_dropins = _get_dropins();

	// Files in wp-content directory.
	$plugins_dir = @opendir( WP_CONTENT_DIR );
	if ( $plugins_dir ) {
		while ( ( $file = readdir( $plugins_dir ) ) !== false ) {
			if ( isset( $_dropins[ $file ] ) ) {
				$plugin_files[] = $file;
			}
		}
	} else {
		return $dropins;
	}

	closedir( $plugins_dir );

	if ( empty( $plugin_files ) ) {
		return $dropins;
	}

	foreach ( $plugin_files as $plugin_file ) {
		if ( ! is_readable( WP_CONTENT_DIR . "/$plugin_file" ) ) {
			continue;
		}

		// Do not apply markup/translate as it will be cached.
		$plugin_data = get_plugin_data( WP_CONTENT_DIR . "/$plugin_file", false, false );

		if ( empty( $plugin_data['Name'] ) ) {
			$plugin_data['Name'] = $plugin_file;
		}

		$dropins[ $plugin_file ] = $plugin_data;
	}

	uksort( $dropins, 'strnatcasecmp' );

	return $dropins;
}

/**
 * Returns drop-in plugins that WordPress uses.
 *
 * Includes Multisite drop-ins only when is_multisite()
 *
 * @since 3.0.0
 *
 * @return array[] {
 *     Key is file name. The value is an array of data about the drop-in.
 *
 *     @type array ...$0 {
 *         Data about the drop-in.
 *
 *         @type string      $0 The purpose of the drop-in.
 *         @type string|true $1 Name of the constant that must be true for the drop-in
 *                              to be used, or true if no constant is required.
 *     }
 * }
 */
function _get_dropins() {
	$dropins = array(
		'advanced-cache.php'      => array( __( 'Advanced caching plugin.' ), 'WP_CACHE' ),  // WP_CACHE
		'db.php'                  => array( __( 'Custom database class.' ), true ),          // Auto on load.
		'db-error.php'            => array( __( 'Custom database error message.' ), true ),  // Auto on error.
		'install.php'             => array( __( 'Custom installation script.' ), true ),     // Auto on installation.
		'maintenance.php'         => array( __( 'Custom maintenance message.' ), true ),     // Auto on maintenance.
		'object-cache.php'        => array( __( 'External object cache.' ), true ),          // Auto on load.
		'php-error.php'           => array( __( 'Custom PHP error message.' ), true ),       // Auto on error.
		'fatal-error-handler.php' => array( __( 'Custom PHP fatal error handler.' ), true ), // Auto on error.
	);

	if ( is_multisite() ) {
		$dropins['sunrise.php']        = array( __( 'Executed before Multisite is loaded.' ), 'SUNRISE' ); // SUNRISE
		$dropins['blog-deleted.php']   = array( __( 'Custom site deleted message.' ), true );   // Auto on deleted blog.
		$dropins['blog-inactive.php']  = array( __( 'Custom site inactive message.' ), true );  // Auto on inactive blog.
		$dropins['blog-suspended.php'] = array( __( 'Custom site suspended message.' ), true ); // Auto on archived or spammed blog.
	}

	return $dropins;
}

/**
 * Determines whether a plugin is active.
 *
 * Only plugins installed in the plugins/ folder can be active.
 *
 * Plugins in the mu-plugins/ folder can't be "activated," so this function will
 * return false for those plugins.
 *
 * For more information on this and similar theme functions, check out
 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
 * Conditional Tags} article in the Theme Developer Handbook.
 *
 * @since 2.5.0
 *
 * @param string $plugin Path to the plugin file relative to the plugins directory.
 * @return bool True, if in the active plugins list. False, not in the list.
 */
function is_plugin_active( $plugin ) {
	return in_array( $plugin, (array) get_option( 'active_plugins', array() ), true ) || is_plugin_active_for_network( $plugin );
}

/**
 * Determines whether the plugin is inactive.
 *
 * Reverse of is_plugin_active(). Used as a callback.
 *
 * For more information on this and similar theme functions, check out
 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
 * Conditional Tags} article in the Theme Developer Handbook.
 *
 * @since 3.1.0
 *
 * @see is_plugin_active()
 *
 * @param string $plugin Path to the plugin file relative to the plugins directory.
 * @return bool True if inactive. False if active.
 */
function is_plugin_inactive( $plugin ) {
	return ! is_plugin_active( $plugin );
}

/**
 * Determines whether the plugin is active for the entire network.
 *
 * Only plugins installed in the plugins/ folder can be active.
 *
 * Plugins in the mu-plugins/ folder can't be "activated," so this function will
 * return false for those plugins.
 *
 * For more information on this and similar theme functions, check out
 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
 * Conditional Tags} article in the Theme Developer Handbook.
 *
 * @since 3.0.0
 *
 * @param string $plugin Path to the plugin file relative to the plugins directory.
 * @return bool True if active for the network, otherwise false.
 */
function is_plugin_active_for_network( $plugin ) {
	if ( ! is_multisite() ) {
		return false;
	}

	$plugins = get_site_option( 'active_sitewide_plugins' );
	if ( isset( $plugins[ $plugin ] ) ) {
		return true;
	}

	return false;
}

/**
 * Checks for "Network: true" in the plugin header to see if this should
 * be activated only as a network wide plugin. The plugin would also work
 * when Multisite is not enabled.
 *
 * Checks for "Site Wide Only: true" for backward compatibility.
 *
 * @since 3.0.0
 *
 * @param string $plugin Path to the plugin file relative to the plugins directory.
 * @return bool True if plugin is network only, false otherwise.
 */
function is_network_only_plugin( $plugin ) {
	$plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
	if ( $plugin_data ) {
		return $plugin_data['Network'];
	}
	return false;
}

/**
 * Attempts activation of plugin in a "sandbox" and redirects on success.
 *
 * A plugin that is already activated will not attempt to be activated again.
 *
 * The way it works is by setting the redirection to the error before trying to
 * include the plugin file. If the plugin fails, then the redirection will not
 * be overwritten with the success message. Also, the options will not be
 * updated and the activation hook will not be called on plugin error.
 *
 * It should be noted that in no way the below code will actually prevent errors
 * within the file. The code should not be used elsewhere to replicate the
 * "sandbox", which uses redirection to work.
 * {@source 13 1}
 *
 * If any errors are found or text is outputted, then it will be captured to
 * ensure that the success redirection will update the error redirection.
 *
 * @since 2.5.0
 * @since 5.2.0 Test for WordPress version and PHP version compatibility.
 *
 * @param string $plugin       Path to the plugin file relative to the plugins directory.
 * @param string $redirect     Optional. URL to redirect to.
 * @param bool   $network_wide Optional. Whether to enable the plugin for all sites in the network
 *                             or just the current site. Multisite only. Default false.
 * @param bool   $silent       Optional. Whether to prevent calling activation hooks. Default false.
 * @return null|WP_Error Null on success, WP_Error on invalid file.
 */
function activate_plugin( $plugin, $redirect = '', $network_wide = false, $silent = false ) {
	$plugin = plugin_basename( trim( $plugin ) );

	if ( is_multisite() && ( $network_wide || is_network_only_plugin( $plugin ) ) ) {
		$network_wide        = true;
		$current             = get_site_option( 'active_sitewide_plugins', array() );
		$_GET['networkwide'] = 1; // Back compat for plugins looking for this value.
	} else {
		$current = get_option( 'active_plugins', array() );
	}

	$valid = validate_plugin( $plugin );
	if ( is_wp_error( $valid ) ) {
		return $valid;
	}

	$requirements = validate_plugin_requirements( $plugin );
	if ( is_wp_error( $requirements ) ) {
		return $requirements;
	}

	if ( $network_wide && ! isset( $current[ $plugin ] )
		|| ! $network_wide && ! in_array( $plugin, $current, true )
	) {
		if ( ! empty( $redirect ) ) {
			// We'll override this later if the plugin can be included without fatal error.
			wp_redirect( add_query_arg( '_error_nonce', wp_create_nonce( 'plugin-activation-error_' . $plugin ), $redirect ) );
		}

		ob_start();

		// Load the plugin to test whether it throws any errors.
		plugin_sandbox_scrape( $plugin );

		if ( ! $silent ) {
			/**
			 * Fires before a plugin is activated.
			 *
			 * If a plugin is silently activated (such as during an update),
			 * this hook does not fire.
			 *
			 * @since 2.9.0
			 *
			 * @param string $plugin       Path to the plugin file relative to the plugins directory.
			 * @param bool   $network_wide Whether to enable the plugin for all sites in the network
			 *                             or just the current site. Multisite only. Default false.
			 */
			do_action( 'activate_plugin', $plugin, $network_wide );

			/**
			 * Fires as a specific plugin is being activated.
			 *
			 * This hook is the "activation" hook used internally by register_activation_hook().
			 * The dynamic portion of the hook name, `$plugin`, refers to the plugin basename.
			 *
			 * If a plugin is silently activated (such as during an update), this hook does not fire.
			 *
			 * @since 2.0.0
			 *
			 * @param bool $network_wide Whether to enable the plugin for all sites in the network
			 *                           or just the current site. Multisite only. Default false.
			 */
			do_action( "activate_{$plugin}", $network_wide );
		}

		if ( $network_wide ) {
			$current            = get_site_option( 'active_sitewide_plugins', array() );
			$current[ $plugin ] = time();
			update_site_option( 'active_sitewide_plugins', $current );
		} else {
			$current   = get_option( 'active_plugins', array() );
			$current[] = $plugin;
			sort( $current );
			update_option( 'active_plugins', $current );
		}

		if ( ! $silent ) {
			/**
			 * Fires after a plugin has been activated.
			 *
			 * If a plugin is silently activated (such as during an update),
			 * this hook does not fire.
			 *
			 * @since 2.9.0
			 *
			 * @param string $plugin       Path to the plugin file relative to the plugins directory.
			 * @param bool   $network_wide Whether to enable the plugin for all sites in the network
			 *                             or just the current site. Multisite only. Default false.
			 */
			do_action( 'activated_plugin', $plugin, $network_wide );
		}

		if ( ob_get_length() > 0 ) {
			$output = ob_get_clean();
			return new WP_Error( 'unexpected_output', __( 'The plugin generated unexpected output.' ), $output );
		}

		ob_end_clean();
	}

	return null;
}

/**
 * Deactivates a single plugin or multiple plugins.
 *
 * The deactivation hook is disabled by the plugin upgrader by using the $silent
 * parameter.
 *
 * @since 2.5.0
 *
 * @param string|string[] $plugins      Single plugin or list of plugins to deactivate.
 * @param bool            $silent       Prevent calling deactivation hooks. Default false.
 * @param bool|null       $network_wide Whether to deactivate the plugin for all sites in the network.
 *                                      A value of null will deactivate plugins for both the network
 *                                      and the current site. Multisite only. Default null.
 */
function deactivate_plugins( $plugins, $silent = false, $network_wide = null ) {
	if ( is_multisite() ) {
		$network_current = get_site_option( 'active_sitewide_plugins', array() );
	}
	$current    = get_option( 'active_plugins', array() );
	$do_blog    = false;
	$do_network = false;

	foreach ( (array) $plugins as $plugin ) {
		$plugin = plugin_basename( trim( $plugin ) );
		if ( ! is_plugin_active( $plugin ) ) {
			continue;
		}

		$network_deactivating = ( false !== $network_wide ) && is_plugin_active_for_network( $plugin );

		if ( ! $silent ) {
			/**
			 * Fires before a plugin is deactivated.
			 *
			 * If a plugin is silently deactivated (such as during an update),
			 * this hook does not fire.
			 *
			 * @since 2.9.0
			 *
			 * @param string $plugin               Path to the plugin file relative to the plugins directory.
			 * @param bool   $network_deactivating Whether the plugin is deactivated for all sites in the network
			 *                                     or just the current site. Multisite only. Default false.
			 */
			do_action( 'deactivate_plugin', $plugin, $network_deactivating );
		}

		if ( false !== $network_wide ) {
			if ( is_plugin_active_for_network( $plugin ) ) {
				$do_network = true;
				unset( $network_current[ $plugin ] );
			} elseif ( $network_wide ) {
				continue;
			}
		}

		if ( true !== $network_wide ) {
			$key = array_search( $plugin, $current, true );
			if ( false !== $key ) {
				$do_blog = true;
				unset( $current[ $key ] );
			}
		}

		if ( $do_blog && wp_is_recovery_mode() ) {
			list( $extension ) = explode( '/', $plugin );
			wp_paused_plugins()->delete( $extension );
		}

		if ( ! $silent ) {
			/**
			 * Fires as a specific plugin is being deactivated.
			 *
			 * This hook is the "deactivation" hook used internally by register_deactivation_hook().
			 * The dynamic portion of the hook name, `$plugin`, refers to the plugin basename.
			 *
			 * If a plugin is silently deactivated (such as during an update), this hook does not fire.
			 *
			 * @since 2.0.0
			 *
			 * @param bool $network_deactivating Whether the plugin is deactivated for all sites in the network
			 *                                   or just the current site. Multisite only. Default false.
			 */
			do_action( "deactivate_{$plugin}", $network_deactivating );

			/**
			 * Fires after a plugin is deactivated.
			 *
			 * If a plugin is silently deactivated (such as during an update),
			 * this hook does not fire.
			 *
			 * @since 2.9.0
			 *
			 * @param string $plugin               Path to the plugin file relative to the plugins directory.
			 * @param bool   $network_deactivating Whether the plugin is deactivated for all sites in the network
			 *                                     or just the current site. Multisite only. Default false.
			 */
			do_action( 'deactivated_plugin', $plugin, $network_deactivating );
		}
	}

	if ( $do_blog ) {
		update_option( 'active_plugins', $current );
	}
	if ( $do_network ) {
		update_site_option( 'active_sitewide_plugins', $network_current );
	}
}

/**
 * Activates multiple plugins.
 *
 * When WP_Error is returned, it does not mean that one of the plugins had
 * errors. It means that one or more of the plugin file paths were invalid.
 *
 * The execution will be halted as soon as one of the plugins has an error.
 *
 * @since 2.6.0
 *
 * @param string|string[] $plugins      Single plugin or list of plugins to activate.
 * @param string          $redirect     Redirect to page after successful activation.
 * @param bool            $network_wide Whether to enable the plugin for all sites in the network.
 *                                      Default false.
 * @param bool            $silent       Prevent calling activation hooks. Default false.
 * @return true|WP_Error True when finished or WP_Error if there were errors during a plugin activation.
 */
function activate_plugins( $plugins, $redirect = '', $network_wide = false, $silent = false ) {
	if ( ! is_array( $plugins ) ) {
		$plugins = array( $plugins );
	}

	$errors = array();
	foreach ( $plugins as $plugin ) {
		if ( ! empty( $redirect ) ) {
			$redirect = add_query_arg( 'plugin', $plugin, $redirect );
		}
		$result = activate_plugin( $plugin, $redirect, $network_wide, $silent );
		if ( is_wp_error( $result ) ) {
			$errors[ $plugin ] = $result;
		}
	}

	if ( ! empty( $errors ) ) {
		return new WP_Error( 'plugins_invalid', __( 'One of the plugins is invalid.' ), $errors );
	}

	return true;
}

/**
 * Removes directory and files of a plugin for a list of plugins.
 *
 * @since 2.6.0
 *
 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
 *
 * @param string[] $plugins    List of plugin paths to delete, relative to the plugins directory.
 * @param string   $deprecated Not used.
 * @return bool|null|WP_Error True on success, false if `$plugins` is empty, `WP_Error` on failure.
 *                            `null` if filesystem credentials are required to proceed.
 */
function delete_plugins( $plugins, $deprecated = '' ) {
	global $wp_filesystem;

	if ( empty( $plugins ) ) {
		return false;
	}

	$checked = array();
	foreach ( $plugins as $plugin ) {
		$checked[] = 'checked[]=' . $plugin;
	}

	$url = wp_nonce_url( 'plugins.php?action=delete-selected&verify-delete=1&' . implode( '&', $checked ), 'bulk-plugins' );

	ob_start();
	$credentials = request_filesystem_credentials( $url );
	$data        = ob_get_clean();

	if ( false === $credentials ) {
		if ( ! empty( $data ) ) {
			require_once ABSPATH . 'wp-admin/admin-header.php';
			echo $data;
			require_once ABSPATH . 'wp-admin/admin-footer.php';
			exit;
		}
		return;
	}

	if ( ! WP_Filesystem( $credentials ) ) {
		ob_start();
		// Failed to connect. Error and request again.
		request_filesystem_credentials( $url, '', true );
		$data = ob_get_clean();

		if ( ! empty( $data ) ) {
			require_once ABSPATH . 'wp-admin/admin-header.php';
			echo $data;
			require_once ABSPATH . 'wp-admin/admin-footer.php';
			exit;
		}
		return;
	}

	if ( ! is_object( $wp_filesystem ) ) {
		return new WP_Error( 'fs_unavailable', __( 'Could not access filesystem.' ) );
	}

	if ( is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->has_errors() ) {
		return new WP_Error( 'fs_error', __( 'Filesystem error.' ), $wp_filesystem->errors );
	}

	// Get the base plugin folder.
	$plugins_dir = $wp_filesystem->wp_plugins_dir();
	if ( empty( $plugins_dir ) ) {
		return new WP_Error( 'fs_no_plugins_dir', __( 'Unable to locate WordPress plugin directory.' ) );
	}

	$plugins_dir = trailingslashit( $plugins_dir );

	$plugin_translations = wp_get_installed_translations( 'plugins' );

	$errors = array();

	foreach ( $plugins as $plugin_file ) {
		// Run Uninstall hook.
		if ( is_uninstallable_plugin( $plugin_file ) ) {
			uninstall_plugin( $plugin_file );
		}

		/**
		 * Fires immediately before a plugin deletion attempt.
		 *
		 * @since 4.4.0
		 *
		 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
		 */
		do_action( 'delete_plugin', $plugin_file );

		$this_plugin_dir = trailingslashit( dirname( $plugins_dir . $plugin_file ) );

		/*
		 * If plugin is in its own directory, recursively delete the directory.
		 * Base check on if plugin includes directory separator AND that it's not the root plugin folder.
		 */
		if ( strpos( $plugin_file, '/' ) && $this_plugin_dir !== $plugins_dir ) {
			$deleted = $wp_filesystem->delete( $this_plugin_dir, true );
		} else {
			$deleted = $wp_filesystem->delete( $plugins_dir . $plugin_file );
		}

		/**
		 * Fires immediately after a plugin deletion attempt.
		 *
		 * @since 4.4.0
		 *
		 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
		 * @param bool   $deleted     Whether the plugin deletion was successful.
		 */
		do_action( 'deleted_plugin', $plugin_file, $deleted );

		if ( ! $deleted ) {
			$errors[] = $plugin_file;
			continue;
		}

		$plugin_slug = dirname( $plugin_file );

		if ( 'hello.php' === $plugin_file ) {
			$plugin_slug = 'hello-dolly';
		}

		// Remove language files, silently.
		if ( '.' !== $plugin_slug && ! empty( $plugin_translations[ $plugin_slug ] ) ) {
			$translations = $plugin_translations[ $plugin_slug ];

			foreach ( $translations as $translation => $data ) {
				$wp_filesystem->delete( WP_LANG_DIR . '/plugins/' . $plugin_slug . '-' . $translation . '.po' );
				$wp_filesystem->delete( WP_LANG_DIR . '/plugins/' . $plugin_slug . '-' . $translation . '.mo' );
				$wp_filesystem->delete( WP_LANG_DIR . '/plugins/' . $plugin_slug . '-' . $translation . '.l10n.php' );

				$json_translation_files = glob( WP_LANG_DIR . '/plugins/' . $plugin_slug . '-' . $translation . '-*.json' );
				if ( $json_translation_files ) {
					array_map( array( $wp_filesystem, 'delete' ), $json_translation_files );
				}
			}
		}
	}

	// Remove deleted plugins from the plugin updates list.
	$current = get_site_transient( 'update_plugins' );
	if ( $current ) {
		// Don't remove the plugins that weren't deleted.
		$deleted = array_diff( $plugins, $errors );

		foreach ( $deleted as $plugin_file ) {
			unset( $current->response[ $plugin_file ] );
		}

		set_site_transient( 'update_plugins', $current );
	}

	if ( ! empty( $errors ) ) {
		if ( 1 === count( $errors ) ) {
			/* translators: %s: Plugin filename. */
			$message = __( 'Could not fully remove the plugin %s.' );
		} else {
			/* translators: %s: Comma-separated list of plugin filenames. */
			$message = __( 'Could not fully remove the plugins %s.' );
		}

		return new WP_Error( 'could_not_remove_plugin', sprintf( $message, implode( ', ', $errors ) ) );
	}

	return true;
}

/**
 * Validates active plugins.
 *
 * Validate all active plugins, deactivates invalid and
 * returns an array of deactivated ones.
 *
 * @since 2.5.0
 * @return WP_Error[] Array of plugin errors keyed by plugin file name.
 */
function validate_active_plugins() {
	$plugins = get_option( 'active_plugins', array() );
	// Validate vartype: array.
	if ( ! is_array( $plugins ) ) {
		update_option( 'active_plugins', array() );
		$plugins = array();
	}

	if ( is_multisite() && current_user_can( 'manage_network_plugins' ) ) {
		$network_plugins = (array) get_site_option( 'active_sitewide_plugins', array() );
		$plugins         = array_merge( $plugins, array_keys( $network_plugins ) );
	}

	if ( empty( $plugins ) ) {
		return array();
	}

	$invalid = array();

	// Invalid plugins get deactivated.
	foreach ( $plugins as $plugin ) {
		$result = validate_plugin( $plugin );
		if ( is_wp_error( $result ) ) {
			$invalid[ $plugin ] = $result;
			deactivate_plugins( $plugin, true );
		}
	}
	return $invalid;
}

/**
 * Validates the plugin path.
 *
 * Checks that the main plugin file exists and is a valid plugin. See validate_file().
 *
 * @since 2.5.0
 *
 * @param string $plugin Path to the plugin file relative to the plugins directory.
 * @return int|WP_Error 0 on success, WP_Error on failure.
 */
function validate_plugin( $plugin ) {
	if ( validate_file( $plugin ) ) {
		return new WP_Error( 'plugin_invalid', __( 'Invalid plugin path.' ) );
	}
	if ( ! file_exists( WP_PLUGIN_DIR . '/' . $plugin ) ) {
		return new WP_Error( 'plugin_not_found', __( 'Plugin file does not exist.' ) );
	}

	$installed_plugins = get_plugins();
	if ( ! isset( $installed_plugins[ $plugin ] ) ) {
		return new WP_Error( 'no_plugin_header', __( 'The plugin does not have a valid header.' ) );
	}
	return 0;
}

/**
 * Validates the plugin requirements for WordPress version and PHP version.
 *
 * Uses the information from `Requires at least`, `Requires PHP` and `Requires Plugins` headers
 * defined in the plugin's main PHP file.
 *
 * @since 5.2.0
 * @since 5.3.0 Added support for reading the headers from the plugin's
 *              main PHP file, with `readme.txt` as a fallback.
 * @since 5.8.0 Removed support for using `readme.txt` as a fallback.
 * @since 6.5.0 Added support for the 'Requires Plugins' header.
 *
 * @param string $plugin Path to the plugin file relative to the plugins directory.
 * @return true|WP_Error True if requirements are met, WP_Error on failure.
 */
function validate_plugin_requirements( $plugin ) {
	$plugin_headers = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );

	$requirements = array(
		'requires'         => ! empty( $plugin_headers['RequiresWP'] ) ? $plugin_headers['RequiresWP'] : '',
		'requires_php'     => ! empty( $plugin_headers['RequiresPHP'] ) ? $plugin_headers['RequiresPHP'] : '',
		'requires_plugins' => ! empty( $plugin_headers['RequiresPlugins'] ) ? $plugin_headers['RequiresPlugins'] : '',
	);

	$compatible_wp  = is_wp_version_compatible( $requirements['requires'] );
	$compatible_php = is_php_version_compatible( $requirements['requires_php'] );

	$php_update_message = '</p><p>' . sprintf(
		/* translators: %s: URL to Update PHP page. */
		__( '<a href="%s">Learn more about updating PHP</a>.' ),
		esc_url( wp_get_update_php_url() )
	);

	$annotation = wp_get_update_php_annotation();

	if ( $annotation ) {
		$php_update_message .= '</p><p><em>' . $annotation . '</em>';
	}

	if ( ! $compatible_wp && ! $compatible_php ) {
		return new WP_Error(
			'plugin_wp_php_incompatible',
			'<p>' . sprintf(
				/* translators: 1: Current WordPress version, 2: Current PHP version, 3: Plugin name, 4: Required WordPress version, 5: Required PHP version. */
				_x( '<strong>Error:</strong> Current versions of WordPress (%1$s) and PHP (%2$s) do not meet minimum requirements for %3$s. The plugin requires WordPress %4$s and PHP %5$s.', 'plugin' ),
				get_bloginfo( 'version' ),
				PHP_VERSION,
				$plugin_headers['Name'],
				$requirements['requires'],
				$requirements['requires_php']
			) . $php_update_message . '</p>'
		);
	} elseif ( ! $compatible_php ) {
		return new WP_Error(
			'plugin_php_incompatible',
			'<p>' . sprintf(
				/* translators: 1: Current PHP version, 2: Plugin name, 3: Required PHP version. */
				_x( '<strong>Error:</strong> Current PHP version (%1$s) does not meet minimum requirements for %2$s. The plugin requires PHP %3$s.', 'plugin' ),
				PHP_VERSION,
				$plugin_headers['Name'],
				$requirements['requires_php']
			) . $php_update_message . '</p>'
		);
	} elseif ( ! $compatible_wp ) {
		return new WP_Error(
			'plugin_wp_incompatible',
			'<p>' . sprintf(
				/* translators: 1: Current WordPress version, 2: Plugin name, 3: Required WordPress version. */
				_x( '<strong>Error:</strong> Current WordPress version (%1$s) does not meet minimum requirements for %2$s. The plugin requires WordPress %3$s.', 'plugin' ),
				get_bloginfo( 'version' ),
				$plugin_headers['Name'],
				$requirements['requires']
			) . '</p>'
		);
	}

	WP_Plugin_Dependencies::initialize();

	if ( WP_Plugin_Dependencies::has_unmet_dependencies( $plugin ) ) {
		$dependency_names       = WP_Plugin_Dependencies::get_dependency_names( $plugin );
		$unmet_dependencies     = array();
		$unmet_dependency_names = array();

		foreach ( $dependency_names as $dependency => $dependency_name ) {
			$dependency_file = WP_Plugin_Dependencies::get_dependency_filepath( $dependency );

			if ( false === $dependency_file ) {
				$unmet_dependencies['not_installed'][ $dependency ] = $dependency_name;
				$unmet_dependency_names[]                           = $dependency_name;
			} elseif ( is_plugin_inactive( $dependency_file ) ) {
				$unmet_dependencies['inactive'][ $dependency ] = $dependency_name;
				$unmet_dependency_names[]                      = $dependency_name;
			}
		}

		$error_message = sprintf(
			/* translators: 1: Plugin name, 2: Number of plugins, 3: A comma-separated list of plugin names. */
			_n(
				'<strong>Error:</strong> %1$s requires %2$d plugin to be installed and activated: %3$s.',
				'<strong>Error:</strong> %1$s requires %2$d plugins to be installed and activated: %3$s.',
				count( $unmet_dependency_names )
			),
			$plugin_headers['Name'],
			count( $unmet_dependency_names ),
			implode( wp_get_list_item_separator(), $unmet_dependency_names )
		);

		if ( is_multisite() ) {
			if ( current_user_can( 'manage_network_plugins' ) ) {
				$error_message .= ' ' . sprintf(
					/* translators: %s: Link to the plugins page. */
					__( '<a href="%s">Manage plugins</a>.' ),
					esc_url( network_admin_url( 'plugins.php' ) )
				);
			} else {
				$error_message .= ' ' . __( 'Please contact your network administrator.' );
			}
		} else {
			$error_message .= ' ' . sprintf(
				/* translators: %s: Link to the plugins page. */
				__( '<a href="%s">Manage plugins</a>.' ),
				esc_url( admin_url( 'plugins.php' ) )
			);
		}

		return new WP_Error(
			'plugin_missing_dependencies',
			"<p>{$error_message}</p>",
			$unmet_dependencies
		);
	}

	/**
	 * Filters the plugin requirement validation response.
	 *
	 * If a plugin fails due to a Core-provided validation (incompatible WP, PHP versions), this
	 * filter will not fire. A WP_Error response will already be returned.
	 *
	 * This filter is intended to add additional validation steps by site administrators.
	 *
	 * @since 6.9.0
	 *
	 * @param bool|WP_Error $met_requirements True if the plugin meets requirements, WP_Error if not.
	 * @param string $plugin Path to the plugin file relative to the plugins directory.
	 */
	return apply_filters( 'validate_plugin_requirements', true, $plugin );
}

/**
 * Determines whether the plugin can be uninstalled.
 *
 * @since 2.7.0
 *
 * @param string $plugin Path to the plugin file relative to the plugins directory.
 * @return bool Whether plugin can be uninstalled.
 */
function is_uninstallable_plugin( $plugin ) {
	$file = plugin_basename( $plugin );

	$uninstallable_plugins = (array) get_option( 'uninstall_plugins' );
	if ( isset( $uninstallable_plugins[ $file ] ) || file_exists( WP_PLUGIN_DIR . '/' . dirname( $file ) . '/uninstall.php' ) ) {
		return true;
	}

	return false;
}

/**
 * Uninstalls a single plugin.
 *
 * Calls the uninstall hook, if it is available.
 *
 * @since 2.7.0
 *
 * @param string $plugin Path to the plugin file relative to the plugins directory.
 * @return true|void True if a plugin's uninstall.php file has been found and included.
 *                   Void otherwise.
 */
function uninstall_plugin( $plugin ) {
	$file = plugin_basename( $plugin );

	$uninstallable_plugins = (array) get_option( 'uninstall_plugins' );

	/**
	 * Fires in uninstall_plugin() immediately before the plugin is uninstalled.
	 *
	 * @since 4.5.0
	 *
	 * @param string $plugin                Path to the plugin file relative to the plugins directory.
	 * @param array  $uninstallable_plugins Uninstallable plugins.
	 */
	do_action( 'pre_uninstall_plugin', $plugin, $uninstallable_plugins );

	if ( file_exists( WP_PLUGIN_DIR . '/' . dirname( $file ) . '/uninstall.php' ) ) {
		if ( isset( $uninstallable_plugins[ $file ] ) ) {
			unset( $uninstallable_plugins[ $file ] );
			update_option( 'uninstall_plugins', $uninstallable_plugins );
		}
		unset( $uninstallable_plugins );

		define( 'WP_UNINSTALL_PLUGIN', $file );

		wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . $file );
		include_once WP_PLUGIN_DIR . '/' . dirname( $file ) . '/uninstall.php';

		return true;
	}

	if ( isset( $uninstallable_plugins[ $file ] ) ) {
		$callable = $uninstallable_plugins[ $file ];
		unset( $uninstallable_plugins[ $file ] );
		update_option( 'uninstall_plugins', $uninstallable_plugins );
		unset( $uninstallable_plugins );

		wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . $file );
		include_once WP_PLUGIN_DIR . '/' . $file;

		add_action( "uninstall_{$file}", $callable );

		/**
		 * Fires in uninstall_plugin() once the plugin has been uninstalled.
		 *
		 * The action concatenates the 'uninstall_' prefix with the basename of the
		 * plugin passed to uninstall_plugin() to create a dynamically-named action.
		 *
		 * @since 2.7.0
		 */
		do_action( "uninstall_{$file}" );
	}
}

//
// Menu.
//

/**
 * Adds a top-level menu page.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 1.5.0
 *
 * @global array $menu
 * @global array $admin_page_hooks
 * @global array $_registered_pages
 * @global array $_parent_pages
 *
 * @param string    $page_title The text to be displayed in the title tags of the page when the menu is selected.
 * @param string    $menu_title The text to be used for the menu.
 * @param string    $capability The capability required for this menu to be displayed to the user.
 * @param string    $menu_slug  The slug name to refer to this menu by. Should be unique for this menu page and only
 *                              include lowercase alphanumeric, dashes, and underscores characters to be compatible
 *                              with sanitize_key().
 * @param callable  $callback   Optional. The function to be called to output the content for this page.
 * @param string    $icon_url   Optional. The URL to the icon to be used for this menu.
 *                              * Pass a base64-encoded SVG using a data URI, which will be colored to match
 *                                the color scheme. This should begin with 'data:image/svg+xml;base64,'.
 *                              * Pass the name of a Dashicons helper class to use a font icon,
 *                                e.g. 'dashicons-chart-pie'.
 *                              * Pass 'none' to leave div.wp-menu-image empty so an icon can be added via CSS.
 * @param int|float $position   Optional. The position in the menu order this item should appear.
 * @return string The resulting page's hook_suffix.
 */
function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $icon_url = '', $position = null ) {
	global $menu, $admin_page_hooks, $_registered_pages, $_parent_pages;

	$menu_slug = plugin_basename( $menu_slug );

	$admin_page_hooks[ $menu_slug ] = sanitize_title( $menu_title );

	$hookname = get_plugin_page_hookname( $menu_slug, '' );

	if ( ! empty( $callback ) && ! empty( $hookname ) && current_user_can( $capability ) ) {
		add_action( $hookname, $callback );
	}

	if ( empty( $icon_url ) ) {
		$icon_url   = 'dashicons-admin-generic';
		$icon_class = 'menu-icon-generic ';
	} else {
		$icon_url   = set_url_scheme( $icon_url );
		$icon_class = '';
	}

	$new_menu = array( $menu_title, $capability, $menu_slug, $page_title, 'menu-top ' . $icon_class . $hookname, $hookname, $icon_url );

	if ( null !== $position && ! is_numeric( $position ) ) {
		_doing_it_wrong(
			__FUNCTION__,
			sprintf(
				/* translators: %s: add_menu_page() */
				__( 'The seventh parameter passed to %s should be numeric representing menu position.' ),
				'<code>add_menu_page()</code>'
			),
			'6.0.0'
		);
		$position = null;
	}

	if ( null === $position || ! is_numeric( $position ) ) {
		$menu[] = $new_menu;
	} elseif ( isset( $menu[ (string) $position ] ) ) {
		$collision_avoider = base_convert( substr( md5( $menu_slug . $menu_title ), -4 ), 16, 10 ) * 0.00001;
		$position          = (string) ( $position + $collision_avoider );
		$menu[ $position ] = $new_menu;
	} else {
		/*
		 * Cast menu position to a string.
		 *
		 * This allows for floats to be passed as the position. PHP will normally cast a float to an
		 * integer value, this ensures the float retains its mantissa (positive fractional part).
		 *
		 * A string containing an integer value, eg "10", is treated as a numeric index.
		 */
		$position          = (string) $position;
		$menu[ $position ] = $new_menu;
	}

	$_registered_pages[ $hookname ] = true;

	// No parent as top level.
	$_parent_pages[ $menu_slug ] = false;

	return $hookname;
}

/**
 * Adds a submenu page.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 1.5.0
 * @since 5.3.0 Added the `$position` parameter.
 *
 * @global array $submenu
 * @global array $menu
 * @global array $_wp_real_parent_file
 * @global bool  $_wp_submenu_nopriv
 * @global array $_registered_pages
 * @global array $_parent_pages
 *
 * @param string    $parent_slug The slug name for the parent menu (or the file name of a standard
 *                               WordPress admin page).
 * @param string    $page_title  The text to be displayed in the title tags of the page when the menu
 *                               is selected.
 * @param string    $menu_title  The text to be used for the menu.
 * @param string    $capability  The capability required for this menu to be displayed to the user.
 * @param string    $menu_slug   The slug name to refer to this menu by. Should be unique for this menu
 *                               and only include lowercase alphanumeric, dashes, and underscores characters
 *                               to be compatible with sanitize_key().
 * @param callable  $callback    Optional. The function to be called to output the content for this page.
 * @param int|float $position    Optional. The position in the menu order this item should appear.
 * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) {
	global $submenu, $menu, $_wp_real_parent_file, $_wp_submenu_nopriv,
		$_registered_pages, $_parent_pages;

	$menu_slug   = plugin_basename( $menu_slug );
	$parent_slug = plugin_basename( $parent_slug );

	if ( isset( $_wp_real_parent_file[ $parent_slug ] ) ) {
		$parent_slug = $_wp_real_parent_file[ $parent_slug ];
	}

	if ( ! current_user_can( $capability ) ) {
		$_wp_submenu_nopriv[ $parent_slug ][ $menu_slug ] = true;
		return false;
	}

	/*
	 * If the parent doesn't already have a submenu, add a link to the parent
	 * as the first item in the submenu. If the submenu file is the same as the
	 * parent file someone is trying to link back to the parent manually. In
	 * this case, don't automatically add a link back to avoid duplication.
	 */
	if ( ! isset( $submenu[ $parent_slug ] ) && $menu_slug !== $parent_slug ) {
		foreach ( (array) $menu as $parent_menu ) {
			if ( $parent_menu[2] === $parent_slug && current_user_can( $parent_menu[1] ) ) {
				$submenu[ $parent_slug ][] = array_slice( $parent_menu, 0, 4 );
			}
		}
	}

	$new_sub_menu = array( $menu_title, $capability, $menu_slug, $page_title );

	if ( null !== $position && ! is_numeric( $position ) ) {
		_doing_it_wrong(
			__FUNCTION__,
			sprintf(
				/* translators: %s: add_submenu_page() */
				__( 'The seventh parameter passed to %s should be numeric representing menu position.' ),
				'<code>add_submenu_page()</code>'
			),
			'5.3.0'
		);
		$position = null;
	}

	if (
		null === $position ||
		( ! isset( $submenu[ $parent_slug ] ) || $position >= count( $submenu[ $parent_slug ] ) )
	) {
		$submenu[ $parent_slug ][] = $new_sub_menu;
	} else {
		// Test for a negative position.
		$position = max( $position, 0 );
		if ( 0 === $position ) {
			// For negative or `0` positions, prepend the submenu.
			array_unshift( $submenu[ $parent_slug ], $new_sub_menu );
		} else {
			$position = absint( $position );
			// Grab all of the items before the insertion point.
			$before_items = array_slice( $submenu[ $parent_slug ], 0, $position, true );
			// Grab all of the items after the insertion point.
			$after_items = array_slice( $submenu[ $parent_slug ], $position, null, true );
			// Add the new item.
			$before_items[] = $new_sub_menu;
			// Merge the items.
			$submenu[ $parent_slug ] = array_merge( $before_items, $after_items );
		}
	}

	// Sort the parent array.
	ksort( $submenu[ $parent_slug ] );

	$hookname = get_plugin_page_hookname( $menu_slug, $parent_slug );
	if ( ! empty( $callback ) && ! empty( $hookname ) ) {
		add_action( $hookname, $callback );
	}

	$_registered_pages[ $hookname ] = true;

	/*
	 * Backward-compatibility for plugins using add_management_page().
	 * See wp-admin/admin.php for redirect from edit.php to tools.php.
	 */
	if ( 'tools.php' === $parent_slug ) {
		$_registered_pages[ get_plugin_page_hookname( $menu_slug, 'edit.php' ) ] = true;
	}

	// No parent as top level.
	$_parent_pages[ $menu_slug ] = $parent_slug;

	return $hookname;
}

/**
 * Adds a submenu page to the Tools main menu.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 1.5.0
 * @since 5.3.0 Added the `$position` parameter.
 *
 * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
 * @param string   $menu_title The text to be used for the menu.
 * @param string   $capability The capability required for this menu to be displayed to the user.
 * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
 * @param callable $callback   Optional. The function to be called to output the content for this page.
 * @param int      $position   Optional. The position in the menu order this item should appear.
 * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_management_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) {
	return add_submenu_page( 'tools.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position );
}

/**
 * Adds a submenu page to the Settings main menu.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 1.5.0
 * @since 5.3.0 Added the `$position` parameter.
 *
 * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
 * @param string   $menu_title The text to be used for the menu.
 * @param string   $capability The capability required for this menu to be displayed to the user.
 * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
 * @param callable $callback   Optional. The function to be called to output the content for this page.
 * @param int      $position   Optional. The position in the menu order this item should appear.
 * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_options_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) {
	return add_submenu_page( 'options-general.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position );
}

/**
 * Adds a submenu page to the Appearance main menu.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 2.0.0
 * @since 5.3.0 Added the `$position` parameter.
 *
 * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
 * @param string   $menu_title The text to be used for the menu.
 * @param string   $capability The capability required for this menu to be displayed to the user.
 * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
 * @param callable $callback   Optional. The function to be called to output the content for this page.
 * @param int      $position   Optional. The position in the menu order this item should appear.
 * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_theme_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) {
	return add_submenu_page( 'themes.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position );
}

/**
 * Adds a submenu page to the Plugins main menu.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 3.0.0
 * @since 5.3.0 Added the `$position` parameter.
 *
 * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
 * @param string   $menu_title The text to be used for the menu.
 * @param string   $capability The capability required for this menu to be displayed to the user.
 * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
 * @param callable $callback   Optional. The function to be called to output the content for this page.
 * @param int      $position   Optional. The position in the menu order this item should appear.
 * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_plugins_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) {
	return add_submenu_page( 'plugins.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position );
}

/**
 * Adds a submenu page to the Users/Profile main menu.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 2.1.3
 * @since 5.3.0 Added the `$position` parameter.
 *
 * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
 * @param string   $menu_title The text to be used for the menu.
 * @param string   $capability The capability required for this menu to be displayed to the user.
 * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
 * @param callable $callback   Optional. The function to be called to output the content for this page.
 * @param int      $position   Optional. The position in the menu order this item should appear.
 * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_users_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) {
	if ( current_user_can( 'edit_users' ) ) {
		$parent = 'users.php';
	} else {
		$parent = 'profile.php';
	}
	return add_submenu_page( $parent, $page_title, $menu_title, $capability, $menu_slug, $callback, $position );
}

/**
 * Adds a submenu page to the Dashboard main menu.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 2.7.0
 * @since 5.3.0 Added the `$position` parameter.
 *
 * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
 * @param string   $menu_title The text to be used for the menu.
 * @param string   $capability The capability required for this menu to be displayed to the user.
 * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
 * @param callable $callback   Optional. The function to be called to output the content for this page.
 * @param int      $position   Optional. The position in the menu order this item should appear.
 * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_dashboard_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) {
	return add_submenu_page( 'index.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position );
}

/**
 * Adds a submenu page to the Posts main menu.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 2.7.0
 * @since 5.3.0 Added the `$position` parameter.
 *
 * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
 * @param string   $menu_title The text to be used for the menu.
 * @param string   $capability The capability required for this menu to be displayed to the user.
 * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
 * @param callable $callback   Optional. The function to be called to output the content for this page.
 * @param int      $position   Optional. The position in the menu order this item should appear.
 * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_posts_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) {
	return add_submenu_page( 'edit.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position );
}

/**
 * Adds a submenu page to the Media main menu.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 2.7.0
 * @since 5.3.0 Added the `$position` parameter.
 *
 * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
 * @param string   $menu_title The text to be used for the menu.
 * @param string   $capability The capability required for this menu to be displayed to the user.
 * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
 * @param callable $callback   Optional. The function to be called to output the content for this page.
 * @param int      $position   Optional. The position in the menu order this item should appear.
 * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_media_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) {
	return add_submenu_page( 'upload.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position );
}

/**
 * Adds a submenu page to the Links main menu.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 2.7.0
 * @since 5.3.0 Added the `$position` parameter.
 *
 * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
 * @param string   $menu_title The text to be used for the menu.
 * @param string   $capability The capability required for this menu to be displayed to the user.
 * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
 * @param callable $callback   Optional. The function to be called to output the content for this page.
 * @param int      $position   Optional. The position in the menu order this item should appear.
 * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_links_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) {
	return add_submenu_page( 'link-manager.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position );
}

/**
 * Adds a submenu page to the Pages main menu.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 2.7.0
 * @since 5.3.0 Added the `$position` parameter.
 *
 * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
 * @param string   $menu_title The text to be used for the menu.
 * @param string   $capability The capability required for this menu to be displayed to the user.
 * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
 * @param callable $callback   Optional. The function to be called to output the content for this page.
 * @param int      $position   Optional. The position in the menu order this item should appear.
 * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_pages_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) {
	return add_submenu_page( 'edit.php?post_type=page', $page_title, $menu_title, $capability, $menu_slug, $callback, $position );
}

/**
 * Adds a submenu page to the Comments main menu.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 2.7.0
 * @since 5.3.0 Added the `$position` parameter.
 *
 * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
 * @param string   $menu_title The text to be used for the menu.
 * @param string   $capability The capability required for this menu to be displayed to the user.
 * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
 * @param callable $callback   Optional. The function to be called to output the content for this page.
 * @param int      $position   Optional. The position in the menu order this item should appear.
 * @return string|false The resulting page's hook_suffix, or false if the user does not have the capability required.
 */
function add_comments_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) {
	return add_submenu_page( 'edit-comments.php', $page_title, $menu_title, $capability, $menu_slug, $callback, $position );
}

/**
 * Removes a top-level admin menu.
 *
 * Example usage:
 *
 *  - `remove_menu_page( 'tools.php' )`
 *  - `remove_menu_page( 'plugin_menu_slug' )`
 *
 * @since 3.1.0
 *
 * @global array $menu
 *
 * @param string $menu_slug The slug of the menu.
 * @return array|false The removed menu on success, false if not found.
 */
function remove_menu_page( $menu_slug ) {
	global $menu;

	foreach ( $menu as $i => $item ) {
		if ( $menu_slug === $item[2] ) {
			unset( $menu[ $i ] );
			return $item;
		}
	}

	return false;
}

/**
 * Removes an admin submenu.
 *
 * Example usage:
 *
 *  - `remove_submenu_page( 'themes.php', 'nav-menus.php' )`
 *  - `remove_submenu_page( 'tools.php', 'plugin_submenu_slug' )`
 *  - `remove_submenu_page( 'plugin_menu_slug', 'plugin_submenu_slug' )`
 *
 * @since 3.1.0
 *
 * @global array $submenu
 *
 * @param string $menu_slug    The slug for the parent menu.
 * @param string $submenu_slug The slug of the submenu.
 * @return array|false The removed submenu on success, false if not found.
 */
function remove_submenu_page( $menu_slug, $submenu_slug ) {
	global $submenu;

	if ( ! isset( $submenu[ $menu_slug ] ) ) {
		return false;
	}

	foreach ( $submenu[ $menu_slug ] as $i => $item ) {
		if ( $submenu_slug === $item[2] ) {
			unset( $submenu[ $menu_slug ][ $i ] );
			return $item;
		}
	}

	return false;
}

/**
 * Gets the URL to access a particular menu page based on the slug it was registered with.
 *
 * If the slug hasn't been registered properly, no URL will be returned.
 *
 * @since 3.0.0
 *
 * @global array $_parent_pages
 *
 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu).
 * @param bool   $display   Optional. Whether or not to display the URL. Default true.
 * @return string The menu page URL.
 */
function menu_page_url( $menu_slug, $display = true ) {
	global $_parent_pages;

	if ( isset( $_parent_pages[ $menu_slug ] ) ) {
		$parent_slug = $_parent_pages[ $menu_slug ];

		if ( $parent_slug && ! isset( $_parent_pages[ $parent_slug ] ) ) {
			$url = admin_url( add_query_arg( 'page', $menu_slug, $parent_slug ) );
		} else {
			$url = admin_url( 'admin.php?page=' . $menu_slug );
		}
	} else {
		$url = '';
	}

	$url = esc_url( $url );

	if ( $display ) {
		echo $url;
	}

	return $url;
}

//
// Pluggable Menu Support -- Private.
//
/**
 * Gets the parent file of the current admin page.
 *
 * @since 1.5.0
 *
 * @global string $parent_file
 * @global array  $menu
 * @global array  $submenu
 * @global string $pagenow              The filename of the current screen.
 * @global string $typenow              The post type of the current screen.
 * @global string $plugin_page
 * @global array  $_wp_real_parent_file
 * @global array  $_wp_menu_nopriv
 * @global array  $_wp_submenu_nopriv
 *
 * @param string $parent_page Optional. The slug name for the parent menu (or the file name
 *                            of a standard WordPress admin page). Default empty string.
 * @return string The parent file of the current admin page.
 */
function get_admin_page_parent( $parent_page = '' ) {
	global $parent_file, $menu, $submenu, $pagenow, $typenow,
		$plugin_page, $_wp_real_parent_file, $_wp_menu_nopriv, $_wp_submenu_nopriv;

	if ( ! empty( $parent_page ) && 'admin.php' !== $parent_page ) {
		if ( isset( $_wp_real_parent_file[ $parent_page ] ) ) {
			$parent_page = $_wp_real_parent_file[ $parent_page ];
		}

		return $parent_page;
	}

	if ( 'admin.php' === $pagenow && isset( $plugin_page ) ) {
		foreach ( (array) $menu as $parent_menu ) {
			if ( $parent_menu[2] === $plugin_page ) {
				$parent_file = $plugin_page;

				if ( isset( $_wp_real_parent_file[ $parent_file ] ) ) {
					$parent_file = $_wp_real_parent_file[ $parent_file ];
				}

				return $parent_file;
			}
		}
		if ( isset( $_wp_menu_nopriv[ $plugin_page ] ) ) {
			$parent_file = $plugin_page;

			if ( isset( $_wp_real_parent_file[ $parent_file ] ) ) {
					$parent_file = $_wp_real_parent_file[ $parent_file ];
			}

			return $parent_file;
		}
	}

	if ( isset( $plugin_page ) && isset( $_wp_submenu_nopriv[ $pagenow ][ $plugin_page ] ) ) {
		$parent_file = $pagenow;

		if ( isset( $_wp_real_parent_file[ $parent_file ] ) ) {
			$parent_file = $_wp_real_parent_file[ $parent_file ];
		}

		return $parent_file;
	}

	foreach ( array_keys( (array) $submenu ) as $parent_page ) {
		foreach ( $submenu[ $parent_page ] as $submenu_array ) {
			if ( isset( $_wp_real_parent_file[ $parent_page ] ) ) {
				$parent_page = $_wp_real_parent_file[ $parent_page ];
			}

			if ( ! empty( $typenow ) && "$pagenow?post_type=$typenow" === $submenu_array[2] ) {
				$parent_file = $parent_page;
				return $parent_page;
			} elseif ( empty( $typenow ) && $pagenow === $submenu_array[2]
				&& ( empty( $parent_file ) || ! str_contains( $parent_file, '?' ) )
			) {
				$parent_file = $parent_page;
				return $parent_page;
			} elseif ( isset( $plugin_page ) && $plugin_page === $submenu_array[2] ) {
				$parent_file = $parent_page;
				return $parent_page;
			}
		}
	}

	if ( empty( $parent_file ) ) {
		$parent_file = '';
	}
	return '';
}

/**
 * Gets the title of the current admin page.
 *
 * @since 1.5.0
 *
 * @global string $title       The title of the current screen.
 * @global array  $menu
 * @global array  $submenu
 * @global string $pagenow     The filename of the current screen.
 * @global string $typenow     The post type of the current screen.
 * @global string $plugin_page
 *
 * @return string The title of the current admin page.
 */
function get_admin_page_title() {
	global $title, $menu, $submenu, $pagenow, $typenow, $plugin_page;

	if ( ! empty( $title ) ) {
		return $title;
	}

	$hook = get_plugin_page_hook( $plugin_page, $pagenow );

	$parent  = get_admin_page_parent();
	$parent1 = $parent;

	if ( empty( $parent ) ) {
		foreach ( (array) $menu as $menu_array ) {
			if ( isset( $menu_array[3] ) ) {
				if ( $menu_array[2] === $pagenow ) {
					$title = $menu_array[3];
					return $menu_array[3];
				} elseif ( isset( $plugin_page ) && $plugin_page === $menu_array[2] && $hook === $menu_array[5] ) {
					$title = $menu_array[3];
					return $menu_array[3];
				}
			} else {
				$title = $menu_array[0];
				return $title;
			}
		}
	} else {
		foreach ( array_keys( $submenu ) as $parent ) {
			foreach ( $submenu[ $parent ] as $submenu_array ) {
				if ( isset( $plugin_page )
					&& $plugin_page === $submenu_array[2]
					&& ( $pagenow === $parent
						|| $plugin_page === $parent
						|| $plugin_page === $hook
						|| 'admin.php' === $pagenow && $parent1 !== $submenu_array[2]
						|| ! empty( $typenow ) && "$pagenow?post_type=$typenow" === $parent )
					) {
						$title = $submenu_array[3];
						return $submenu_array[3];
				}

				if ( $submenu_array[2] !== $pagenow || isset( $_GET['page'] ) ) { // Not the current page.
					continue;
				}

				if ( isset( $submenu_array[3] ) ) {
					$title = $submenu_array[3];
					return $submenu_array[3];
				} else {
					$title = $submenu_array[0];
					return $title;
				}
			}
		}
		if ( empty( $title ) ) {
			foreach ( $menu as $menu_array ) {
				if ( isset( $plugin_page )
					&& $plugin_page === $menu_array[2]
					&& 'admin.php' === $pagenow
					&& $parent1 === $menu_array[2]
				) {
						$title = $menu_array[3];
						return $menu_array[3];
				}
			}
		}
	}

	return $title;
}

/**
 * Gets the hook attached to the administrative page of a plugin.
 *
 * @since 1.5.0
 *
 * @param string $plugin_page The slug name of the plugin page.
 * @param string $parent_page The slug name for the parent menu (or the file name of a standard
 *                            WordPress admin page).
 * @return string|null Hook attached to the plugin page, null otherwise.
 */
function get_plugin_page_hook( $plugin_page, $parent_page ) {
	$hook = get_plugin_page_hookname( $plugin_page, $parent_page );
	if ( has_action( $hook ) ) {
		return $hook;
	} else {
		return null;
	}
}

/**
 * Gets the hook name for the administrative page of a plugin.
 *
 * @since 1.5.0
 *
 * @global array $admin_page_hooks
 *
 * @param string $plugin_page The slug name of the plugin page.
 * @param string $parent_page The slug name for the parent menu (or the file name of a standard
 *                            WordPress admin page).
 * @return string Hook name for the plugin page.
 */
function get_plugin_page_hookname( $plugin_page, $parent_page ) {
	global $admin_page_hooks;

	$parent = get_admin_page_parent( $parent_page );

	$page_type = 'admin';
	if ( empty( $parent_page ) || 'admin.php' === $parent_page || isset( $admin_page_hooks[ $plugin_page ] ) ) {
		if ( isset( $admin_page_hooks[ $plugin_page ] ) ) {
			$page_type = 'toplevel';
		} elseif ( isset( $admin_page_hooks[ $parent ] ) ) {
			$page_type = $admin_page_hooks[ $parent ];
		}
	} elseif ( isset( $admin_page_hooks[ $parent ] ) ) {
		$page_type = $admin_page_hooks[ $parent ];
	}

	$plugin_name = preg_replace( '!\.php!', '', $plugin_page );

	return $page_type . '_page_' . $plugin_name;
}

/**
 * Determines whether the current user can access the current admin page.
 *
 * @since 1.5.0
 *
 * @global string $pagenow            The filename of the current screen.
 * @global array  $menu
 * @global array  $submenu
 * @global array  $_wp_menu_nopriv
 * @global array  $_wp_submenu_nopriv
 * @global string $plugin_page
 * @global array  $_registered_pages
 *
 * @return bool True if the current user can access the admin page, false otherwise.
 */
function user_can_access_admin_page() {
	global $pagenow, $menu, $submenu, $_wp_menu_nopriv, $_wp_submenu_nopriv,
		$plugin_page, $_registered_pages;

	$parent = get_admin_page_parent();

	if ( ! isset( $plugin_page ) && isset( $_wp_submenu_nopriv[ $parent ][ $pagenow ] ) ) {
		return false;
	}

	if ( isset( $plugin_page ) ) {
		if ( isset( $_wp_submenu_nopriv[ $parent ][ $plugin_page ] ) ) {
			return false;
		}

		$hookname = get_plugin_page_hookname( $plugin_page, $parent );

		if ( ! isset( $_registered_pages[ $hookname ] ) ) {
			return false;
		}
	}

	if ( empty( $parent ) ) {
		if ( isset( $_wp_menu_nopriv[ $pagenow ] ) ) {
			return false;
		}
		if ( isset( $_wp_submenu_nopriv[ $pagenow ][ $pagenow ] ) ) {
			return false;
		}
		if ( isset( $plugin_page ) && isset( $_wp_submenu_nopriv[ $pagenow ][ $plugin_page ] ) ) {
			return false;
		}
		if ( isset( $plugin_page ) && isset( $_wp_menu_nopriv[ $plugin_page ] ) ) {
			return false;
		}

		foreach ( array_keys( $_wp_submenu_nopriv ) as $key ) {
			if ( isset( $_wp_submenu_nopriv[ $key ][ $pagenow ] ) ) {
				return false;
			}
			if ( isset( $plugin_page ) && isset( $_wp_submenu_nopriv[ $key ][ $plugin_page ] ) ) {
				return false;
			}
		}

		return true;
	}

	if ( isset( $plugin_page ) && $plugin_page === $parent && isset( $_wp_menu_nopriv[ $plugin_page ] ) ) {
		return false;
	}

	if ( isset( $submenu[ $parent ] ) ) {
		foreach ( $submenu[ $parent ] as $submenu_array ) {
			if ( isset( $plugin_page ) && $submenu_array[2] === $plugin_page ) {
				return current_user_can( $submenu_array[1] );
			} elseif ( $submenu_array[2] === $pagenow ) {
				return current_user_can( $submenu_array[1] );
			}
		}
	}

	foreach ( $menu as $menu_array ) {
		if ( $menu_array[2] === $parent ) {
			return current_user_can( $menu_array[1] );
		}
	}

	return true;
}

/* Allowed list functions */

/**
 * Refreshes the value of the allowed options list available via the 'allowed_options' hook.
 *
 * See the {@see 'allowed_options'} filter.
 *
 * @since 2.7.0
 * @since 5.5.0 `$new_whitelist_options` was renamed to `$new_allowed_options`.
 *              Please consider writing more inclusive code.
 *
 * @global array $new_allowed_options
 *
 * @param array $options
 * @return array
 */
function option_update_filter( $options ) {
	global $new_allowed_options;

	if ( is_array( $new_allowed_options ) ) {
		$options = add_allowed_options( $new_allowed_options, $options );
	}

	return $options;
}

/**
 * Adds an array of options to the list of allowed options.
 *
 * @since 5.5.0
 *
 * @global array $allowed_options
 *
 * @param array        $new_options
 * @param string|array $options
 * @return array
 */
function add_allowed_options( $new_options, $options = '' ) {
	if ( '' === $options ) {
		global $allowed_options;
	} else {
		$allowed_options = $options;
	}

	foreach ( $new_options as $page => $keys ) {
		foreach ( $keys as $key ) {
			if ( ! isset( $allowed_options[ $page ] ) || ! is_array( $allowed_options[ $page ] ) ) {
				$allowed_options[ $page ]   = array();
				$allowed_options[ $page ][] = $key;
			} else {
				$pos = array_search( $key, $allowed_options[ $page ], true );
				if ( false === $pos ) {
					$allowed_options[ $page ][] = $key;
				}
			}
		}
	}

	return $allowed_options;
}

/**
 * Removes a list of options from the allowed options list.
 *
 * @since 5.5.0
 *
 * @global array $allowed_options
 *
 * @param array        $del_options
 * @param string|array $options
 * @return array
 */
function remove_allowed_options( $del_options, $options = '' ) {
	if ( '' === $options ) {
		global $allowed_options;
	} else {
		$allowed_options = $options;
	}

	foreach ( $del_options as $page => $keys ) {
		foreach ( $keys as $key ) {
			if ( isset( $allowed_options[ $page ] ) && is_array( $allowed_options[ $page ] ) ) {
				$pos = array_search( $key, $allowed_options[ $page ], true );
				if ( false !== $pos ) {
					unset( $allowed_options[ $page ][ $pos ] );
				}
			}
		}
	}

	return $allowed_options;
}

/**
 * Outputs nonce, action, and option_page fields for a settings page.
 *
 * @since 2.7.0
 *
 * @param string $option_group A settings group name. This should match the group name
 *                             used in register_setting().
 */
function settings_fields( $option_group ) {
	echo "<input type='hidden' name='option_page' value='" . esc_attr( $option_group ) . "' />";
	echo '<input type="hidden" name="action" value="update" />';
	wp_nonce_field( "$option_group-options" );
}

/**
 * Clears the plugins cache used by get_plugins() and by default, the plugin updates cache.
 *
 * @since 3.7.0
 *
 * @param bool $clear_update_cache Whether to clear the plugin updates cache. Default true.
 */
function wp_clean_plugins_cache( $clear_update_cache = true ) {
	if ( $clear_update_cache ) {
		delete_site_transient( 'update_plugins' );
	}
	wp_cache_delete( 'plugins', 'plugins' );
}

/**
 * Loads a given plugin attempt to generate errors.
 *
 * @since 3.0.0
 * @since 4.4.0 Function was moved into the `wp-admin/includes/plugin.php` file.
 *
 * @param string $plugin Path to the plugin file relative to the plugins directory.
 */
function plugin_sandbox_scrape( $plugin ) {
	if ( ! defined( 'WP_SANDBOX_SCRAPING' ) ) {
		define( 'WP_SANDBOX_SCRAPING', true );
	}

	wp_register_plugin_realpath( WP_PLUGIN_DIR . '/' . $plugin );
	include_once WP_PLUGIN_DIR . '/' . $plugin;
}

/**
 * Declares a helper function for adding content to the Privacy Policy Guide.
 *
 * Plugins and themes should suggest text for inclusion in the site's privacy policy.
 * The suggested text should contain information about any functionality that affects user privacy,
 * and will be shown on the Privacy Policy Guide screen.
 *
 * A plugin or theme can use this function multiple times as long as it will help to better present
 * the suggested policy content. For example modular plugins such as WooCommerse or Jetpack
 * can add or remove suggested content depending on the modules/extensions that are enabled.
 * For more information see the Plugin Handbook:
 * https://developer.wordpress.org/plugins/privacy/suggesting-text-for-the-site-privacy-policy/.
 *
 * The HTML contents of the `$policy_text` supports use of a specialized `.privacy-policy-tutorial`
 * CSS class which can be used to provide supplemental information. Any content contained within
 * HTML elements that have the `.privacy-policy-tutorial` CSS class applied will be omitted
 * from the clipboard when the section content is copied.
 *
 * Intended for use with the `'admin_init'` action.
 *
 * @since 4.9.6
 *
 * @param string $plugin_name The name of the plugin or theme that is suggesting content
 *                            for the site's privacy policy.
 * @param string $policy_text The suggested content for inclusion in the policy.
 */
function wp_add_privacy_policy_content( $plugin_name, $policy_text ) {
	if ( ! is_admin() ) {
		_doing_it_wrong(
			__FUNCTION__,
			sprintf(
				/* translators: %s: admin_init */
				__( 'The suggested privacy policy content should be added only in wp-admin by using the %s (or later) action.' ),
				'<code>admin_init</code>'
			),
			'4.9.7'
		);
		return;
	} elseif ( ! doing_action( 'admin_init' ) && ! did_action( 'admin_init' ) ) {
		_doing_it_wrong(
			__FUNCTION__,
			sprintf(
				/* translators: %s: admin_init */
				__( 'The suggested privacy policy content should be added by using the %s (or later) action. Please see the inline documentation.' ),
				'<code>admin_init</code>'
			),
			'4.9.7'
		);
		return;
	}

	if ( ! class_exists( 'WP_Privacy_Policy_Content' ) ) {
		require_once ABSPATH . 'wp-admin/includes/class-wp-privacy-policy-content.php';
	}

	WP_Privacy_Policy_Content::add( $plugin_name, $policy_text );
}

/**
 * Determines whether a plugin is technically active but was paused while
 * loading.
 *
 * For more information on this and similar theme functions, check out
 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
 * Conditional Tags} article in the Theme Developer Handbook.
 *
 * @since 5.2.0
 *
 * @global WP_Paused_Extensions_Storage $_paused_plugins
 *
 * @param string $plugin Path to the plugin file relative to the plugins directory.
 * @return bool True, if in the list of paused plugins. False, if not in the list.
 */
function is_plugin_paused( $plugin ) {
	if ( ! isset( $GLOBALS['_paused_plugins'] ) ) {
		return false;
	}

	if ( ! is_plugin_active( $plugin ) ) {
		return false;
	}

	list( $plugin ) = explode( '/', $plugin );

	return array_key_exists( $plugin, $GLOBALS['_paused_plugins'] );
}

/**
 * Gets the error that was recorded for a paused plugin.
 *
 * @since 5.2.0
 *
 * @global WP_Paused_Extensions_Storage $_paused_plugins
 *
 * @param string $plugin Path to the plugin file relative to the plugins directory.
 * @return array|false Array of error information as returned by `error_get_last()`,
 *                     or false if none was recorded.
 */
function wp_get_plugin_error( $plugin ) {
	if ( ! isset( $GLOBALS['_paused_plugins'] ) ) {
		return false;
	}

	list( $plugin ) = explode( '/', $plugin );

	if ( ! array_key_exists( $plugin, $GLOBALS['_paused_plugins'] ) ) {
		return false;
	}

	return $GLOBALS['_paused_plugins'][ $plugin ];
}

/**
 * Tries to resume a single plugin.
 *
 * If a redirect was provided, we first ensure the plugin does not throw fatal
 * errors anymore.
 *
 * The way it works is by setting the redirection to the error before trying to
 * include the plugin file. If the plugin fails, then the redirection will not
 * be overwritten with the success message and the plugin will not be resumed.
 *
 * @since 5.2.0
 *
 * @param string $plugin   Single plugin to resume.
 * @param string $redirect Optional. URL to redirect to. Default empty string.
 * @return true|WP_Error True on success, false if `$plugin` was not paused,
 *                       `WP_Error` on failure.
 */
function resume_plugin( $plugin, $redirect = '' ) {
	/*
	 * We'll override this later if the plugin could be resumed without
	 * creating a fatal error.
	 */
	if ( ! empty( $redirect ) ) {
		wp_redirect(
			add_query_arg(
				'_error_nonce',
				wp_create_nonce( 'plugin-resume-error_' . $plugin ),
				$redirect
			)
		);

		// Load the plugin to test whether it throws a fatal error.
		ob_start();
		plugin_sandbox_scrape( $plugin );
		ob_clean();
	}

	list( $extension ) = explode( '/', $plugin );

	$result = wp_paused_plugins()->delete( $extension );

	if ( ! $result ) {
		return new WP_Error(
			'could_not_resume_plugin',
			__( 'Could not resume the plugin.' )
		);
	}

	return true;
}

/**
 * Renders an admin notice in case some plugins have been paused due to errors.
 *
 * @since 5.2.0
 *
 * @global string                       $pagenow         The filename of the current screen.
 * @global WP_Paused_Extensions_Storage $_paused_plugins
 */
function paused_plugins_notice() {
	if ( 'plugins.php' === $GLOBALS['pagenow'] ) {
		return;
	}

	if ( ! current_user_can( 'resume_plugins' ) ) {
		return;
	}

	if ( ! isset( $GLOBALS['_paused_plugins'] ) || empty( $GLOBALS['_paused_plugins'] ) ) {
		return;
	}

	$message = sprintf(
		'<strong>%s</strong><br>%s</p><p><a href="%s">%s</a>',
		__( 'One or more plugins failed to load properly.' ),
		__( 'You can find more details and make changes on the Plugins screen.' ),
		esc_url( admin_url( 'plugins.php?plugin_status=paused' ) ),
		__( 'Go to the Plugins screen' )
	);
	wp_admin_notice(
		$message,
		array( 'type' => 'error' )
	);
}

/**
 * Renders an admin notice when a plugin was deactivated during an update.
 *
 * Displays an admin notice in case a plugin has been deactivated during an
 * upgrade due to incompatibility with the current version of WordPress.
 *
 * @since 5.8.0
 * @access private
 *
 * @global string $pagenow    The filename of the current screen.
 * @global string $wp_version The WordPress version string.
 */
function deactivated_plugins_notice() {
	if ( 'plugins.php' === $GLOBALS['pagenow'] ) {
		return;
	}

	if ( ! current_user_can( 'activate_plugins' ) ) {
		return;
	}

	$blog_deactivated_plugins = get_option( 'wp_force_deactivated_plugins' );
	$site_deactivated_plugins = array();

	if ( false === $blog_deactivated_plugins ) {
		// Option not in database, add an empty array to avoid extra DB queries on subsequent loads.
		update_option( 'wp_force_deactivated_plugins', array(), false );
	}

	if ( is_multisite() ) {
		$site_deactivated_plugins = get_site_option( 'wp_force_deactivated_plugins' );
		if ( false === $site_deactivated_plugins ) {
			// Option not in database, add an empty array to avoid extra DB queries on subsequent loads.
			update_site_option( 'wp_force_deactivated_plugins', array() );
		}
	}

	if ( empty( $blog_deactivated_plugins ) && empty( $site_deactivated_plugins ) ) {
		// No deactivated plugins.
		return;
	}

	$deactivated_plugins = array_merge( $blog_deactivated_plugins, $site_deactivated_plugins );

	foreach ( $deactivated_plugins as $plugin ) {
		if ( ! empty( $plugin['version_compatible'] ) && ! empty( $plugin['version_deactivated'] ) ) {
			$explanation = sprintf(
				/* translators: 1: Name of deactivated plugin, 2: Plugin version deactivated, 3: Current WP version, 4: Compatible plugin version. */
				__( '%1$s %2$s was deactivated due to incompatibility with WordPress %3$s, please upgrade to %1$s %4$s or later.' ),
				$plugin['plugin_name'],
				$plugin['version_deactivated'],
				$GLOBALS['wp_version'],
				$plugin['version_compatible']
			);
		} else {
			$explanation = sprintf(
				/* translators: 1: Name of deactivated plugin, 2: Plugin version deactivated, 3: Current WP version. */
				__( '%1$s %2$s was deactivated due to incompatibility with WordPress %3$s.' ),
				$plugin['plugin_name'],
				! empty( $plugin['version_deactivated'] ) ? $plugin['version_deactivated'] : '',
				$GLOBALS['wp_version'],
				$plugin['version_compatible']
			);
		}

		$message = sprintf(
			'<strong>%s</strong><br>%s</p><p><a href="%s">%s</a>',
			sprintf(
				/* translators: %s: Name of deactivated plugin. */
				__( '%s plugin deactivated during WordPress upgrade.' ),
				$plugin['plugin_name']
			),
			$explanation,
			esc_url( admin_url( 'plugins.php?plugin_status=inactive' ) ),
			__( 'Go to the Plugins screen' )
		);
		wp_admin_notice( $message, array( 'type' => 'warning' ) );
	}

	// Empty the options.
	update_option( 'wp_force_deactivated_plugins', array(), false );
	if ( is_multisite() ) {
		update_site_option( 'wp_force_deactivated_plugins', array() );
	}
}
class-wp-media-list-table.php000064400000062453151212616040012131 0ustar00<?php
/**
 * List Table API: WP_Media_List_Table class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 3.1.0
 */

/**
 * Core class used to implement displaying media items in a list table.
 *
 * @since 3.1.0
 *
 * @see WP_List_Table
 */
class WP_Media_List_Table extends WP_List_Table {
	/**
	 * Holds the number of pending comments for each post.
	 *
	 * @since 4.4.0
	 * @var array
	 */
	protected $comment_pending_count = array();

	private $detached;

	private $is_trash;

	/**
	 * Constructor.
	 *
	 * @since 3.1.0
	 *
	 * @see WP_List_Table::__construct() for more information on default arguments.
	 *
	 * @param array $args An associative array of arguments.
	 */
	public function __construct( $args = array() ) {
		$this->detached = ( isset( $_REQUEST['attachment-filter'] ) && 'detached' === $_REQUEST['attachment-filter'] );

		$this->modes = array(
			'list' => __( 'List view' ),
			'grid' => __( 'Grid view' ),
		);

		parent::__construct(
			array(
				'plural' => 'media',
				'screen' => isset( $args['screen'] ) ? $args['screen'] : null,
			)
		);
	}

	/**
	 * @return bool
	 */
	public function ajax_user_can() {
		return current_user_can( 'upload_files' );
	}

	/**
	 * @global string   $mode                  List table view mode.
	 * @global WP_Query $wp_query              WordPress Query object.
	 * @global array    $post_mime_types
	 * @global array    $avail_post_mime_types
	 */
	public function prepare_items() {
		global $mode, $wp_query, $post_mime_types, $avail_post_mime_types;

		$mode = empty( $_REQUEST['mode'] ) ? 'list' : $_REQUEST['mode'];

		/*
		 * Exclude attachments scheduled for deletion in the next two hours
		 * if they are for zip packages for interrupted or failed updates.
		 * See File_Upload_Upgrader class.
		 */
		$not_in = array();

		$crons = _get_cron_array();

		if ( is_array( $crons ) ) {
			foreach ( $crons as $cron ) {
				if ( isset( $cron['upgrader_scheduled_cleanup'] ) ) {
					$details = reset( $cron['upgrader_scheduled_cleanup'] );

					if ( ! empty( $details['args'][0] ) ) {
						$not_in[] = (int) $details['args'][0];
					}
				}
			}
		}

		if ( ! empty( $_REQUEST['post__not_in'] ) && is_array( $_REQUEST['post__not_in'] ) ) {
			$not_in = array_merge( array_values( $_REQUEST['post__not_in'] ), $not_in );
		}

		if ( ! empty( $not_in ) ) {
			$_REQUEST['post__not_in'] = $not_in;
		}

		list( $post_mime_types, $avail_post_mime_types ) = wp_edit_attachments_query( $_REQUEST );

		$this->is_trash = isset( $_REQUEST['attachment-filter'] ) && 'trash' === $_REQUEST['attachment-filter'];

		$this->set_pagination_args(
			array(
				'total_items' => $wp_query->found_posts,
				'total_pages' => $wp_query->max_num_pages,
				'per_page'    => $wp_query->query_vars['posts_per_page'],
			)
		);
		if ( $wp_query->posts ) {
			update_post_thumbnail_cache( $wp_query );
			update_post_parent_caches( $wp_query->posts );
		}
	}

	/**
	 * @global array $post_mime_types
	 * @global array $avail_post_mime_types
	 * @return array
	 */
	protected function get_views() {
		global $post_mime_types, $avail_post_mime_types;

		$type_links = array();

		$filter = empty( $_GET['attachment-filter'] ) ? '' : $_GET['attachment-filter'];

		$type_links['all'] = sprintf(
			'<option value=""%s>%s</option>',
			selected( $filter, true, false ),
			__( 'All media items' )
		);

		foreach ( $post_mime_types as $mime_type => $label ) {
			if ( ! wp_match_mime_types( $mime_type, $avail_post_mime_types ) ) {
				continue;
			}

			$selected = selected(
				$filter && str_starts_with( $filter, 'post_mime_type:' ) &&
					wp_match_mime_types( $mime_type, str_replace( 'post_mime_type:', '', $filter ) ),
				true,
				false
			);

			$type_links[ $mime_type ] = sprintf(
				'<option value="post_mime_type:%s"%s>%s</option>',
				esc_attr( $mime_type ),
				$selected,
				$label[0]
			);
		}

		$type_links['detached'] = '<option value="detached"' . ( $this->detached ? ' selected="selected"' : '' ) . '>' . _x( 'Unattached', 'media items' ) . '</option>';

		$type_links['mine'] = sprintf(
			'<option value="mine"%s>%s</option>',
			selected( 'mine' === $filter, true, false ),
			_x( 'Mine', 'media items' )
		);

		if ( $this->is_trash || ( defined( 'MEDIA_TRASH' ) && MEDIA_TRASH ) ) {
			$type_links['trash'] = sprintf(
				'<option value="trash"%s>%s</option>',
				selected( 'trash' === $filter, true, false ),
				_x( 'Trash', 'attachment filter' )
			);
		}

		return $type_links;
	}

	/**
	 * @return array
	 */
	protected function get_bulk_actions() {
		$actions = array();

		if ( MEDIA_TRASH ) {
			if ( $this->is_trash ) {
				$actions['untrash'] = __( 'Restore' );
				$actions['delete']  = __( 'Delete permanently' );
			} else {
				$actions['trash'] = __( 'Move to Trash' );
			}
		} else {
			$actions['delete'] = __( 'Delete permanently' );
		}

		if ( $this->detached ) {
			$actions['attach'] = __( 'Attach' );
		}

		return $actions;
	}

	/**
	 * @param string $which
	 */
	protected function extra_tablenav( $which ) {
		if ( 'bar' !== $which ) {
			return;
		}
		?>
		<div class="actions">
			<?php
			if ( ! $this->is_trash ) {
				$this->months_dropdown( 'attachment' );
			}

			/** This action is documented in wp-admin/includes/class-wp-posts-list-table.php */
			do_action( 'restrict_manage_posts', $this->screen->post_type, $which );

			submit_button( __( 'Filter' ), '', 'filter_action', false, array( 'id' => 'post-query-submit' ) );

			if ( $this->is_trash && $this->has_items()
				&& current_user_can( 'edit_others_posts' )
			) {
				submit_button( __( 'Empty Trash' ), 'apply', 'delete_all', false );
			}
			?>
		</div>
		<?php
	}

	/**
	 * @return string
	 */
	public function current_action() {
		if ( isset( $_REQUEST['found_post_id'] ) && isset( $_REQUEST['media'] ) ) {
			return 'attach';
		}

		if ( isset( $_REQUEST['parent_post_id'] ) && isset( $_REQUEST['media'] ) ) {
			return 'detach';
		}

		if ( isset( $_REQUEST['delete_all'] ) || isset( $_REQUEST['delete_all2'] ) ) {
			return 'delete_all';
		}

		return parent::current_action();
	}

	/**
	 * @return bool
	 */
	public function has_items() {
		return have_posts();
	}

	/**
	 */
	public function no_items() {
		if ( $this->is_trash ) {
			_e( 'No media files found in Trash.' );
		} else {
			_e( 'No media files found.' );
		}
	}

	/**
	 * Overrides parent views to use the filter bar display.
	 *
	 * @global string $mode List table view mode.
	 */
	public function views() {
		global $mode;

		$views = $this->get_views();

		$this->screen->render_screen_reader_content( 'heading_views' );
		?>
		<div class="wp-filter">
			<div class="filter-items">
				<?php $this->view_switcher( $mode ); ?>

				<label for="attachment-filter" class="screen-reader-text">
					<?php
					/* translators: Hidden accessibility text. */
					_e( 'Filter by type' );
					?>
				</label>
				<select class="attachment-filters" name="attachment-filter" id="attachment-filter">
					<?php
					if ( ! empty( $views ) ) {
						foreach ( $views as $class => $view ) {
							echo "\t$view\n";
						}
					}
					?>
				</select>

				<?php
				$this->extra_tablenav( 'bar' );

				/** This filter is documented in wp-admin/includes/class-wp-list-table.php */
				$views = apply_filters( "views_{$this->screen->id}", array() );

				// Back compat for pre-4.0 view links.
				if ( ! empty( $views ) ) {
					echo '<ul class="filter-links">';
					foreach ( $views as $class => $view ) {
						echo "<li class='$class'>$view</li>";
					}
					echo '</ul>';
				}
				?>
			</div>

			<div class="search-form">
				<p class="search-box">
					<label class="screen-reader-text" for="media-search-input">
					<?php
					/* translators: Hidden accessibility text. */
					esc_html_e( 'Search Media' );
					?>
					</label>
					<input type="search" id="media-search-input" class="search" name="s" value="<?php _admin_search_query(); ?>">
					<input id="search-submit" type="submit" class="button" value="<?php esc_attr_e( 'Search Media' ); ?>">
				</p>
			</div>
		</div>
		<?php
	}

	/**
	 * @return string[] Array of column titles keyed by their column name.
	 */
	public function get_columns() {
		$posts_columns       = array();
		$posts_columns['cb'] = '<input type="checkbox" />';
		/* translators: Column name. */
		$posts_columns['title']  = _x( 'File', 'column name' );
		$posts_columns['author'] = __( 'Author' );

		$taxonomies = get_taxonomies_for_attachments( 'objects' );
		$taxonomies = wp_filter_object_list( $taxonomies, array( 'show_admin_column' => true ), 'and', 'name' );

		/**
		 * Filters the taxonomy columns for attachments in the Media list table.
		 *
		 * @since 3.5.0
		 *
		 * @param string[] $taxonomies An array of registered taxonomy names to show for attachments.
		 * @param string   $post_type  The post type. Default 'attachment'.
		 */
		$taxonomies = apply_filters( 'manage_taxonomies_for_attachment_columns', $taxonomies, 'attachment' );
		$taxonomies = array_filter( $taxonomies, 'taxonomy_exists' );

		foreach ( $taxonomies as $taxonomy ) {
			if ( 'category' === $taxonomy ) {
				$column_key = 'categories';
			} elseif ( 'post_tag' === $taxonomy ) {
				$column_key = 'tags';
			} else {
				$column_key = 'taxonomy-' . $taxonomy;
			}

			$posts_columns[ $column_key ] = get_taxonomy( $taxonomy )->labels->name;
		}

		/* translators: Column name. */
		if ( ! $this->detached ) {
			$posts_columns['parent'] = _x( 'Uploaded to', 'column name' );

			if ( post_type_supports( 'attachment', 'comments' ) ) {
				$posts_columns['comments'] = sprintf(
					'<span class="vers comment-grey-bubble" title="%1$s" aria-hidden="true"></span><span class="screen-reader-text">%2$s</span>',
					esc_attr__( 'Comments' ),
					/* translators: Hidden accessibility text. */
					__( 'Comments' )
				);
			}
		}

		/* translators: Column name. */
		$posts_columns['date'] = _x( 'Date', 'column name' );

		/**
		 * Filters the Media list table columns.
		 *
		 * @since 2.5.0
		 *
		 * @param string[] $posts_columns An array of columns displayed in the Media list table.
		 * @param bool     $detached      Whether the list table contains media not attached
		 *                                to any posts. Default true.
		 */
		return apply_filters( 'manage_media_columns', $posts_columns, $this->detached );
	}

	/**
	 * @return array
	 */
	protected function get_sortable_columns() {
		return array(
			'title'    => array( 'title', false, _x( 'File', 'column name' ), __( 'Table ordered by File Name.' ) ),
			'author'   => array( 'author', false, __( 'Author' ), __( 'Table ordered by Author.' ) ),
			'parent'   => array( 'parent', false, _x( 'Uploaded to', 'column name' ), __( 'Table ordered by Uploaded To.' ) ),
			'comments' => array( 'comment_count', __( 'Comments' ), false, __( 'Table ordered by Comments.' ) ),
			'date'     => array( 'date', true, __( 'Date' ), __( 'Table ordered by Date.' ), 'desc' ),
		);
	}

	/**
	 * Handles the checkbox column output.
	 *
	 * @since 4.3.0
	 * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support.
	 *
	 * @param WP_Post $item The current WP_Post object.
	 */
	public function column_cb( $item ) {
		// Restores the more descriptive, specific name for use within this method.
		$post = $item;

		if ( current_user_can( 'edit_post', $post->ID ) ) {
			?>
			<input type="checkbox" name="media[]" id="cb-select-<?php echo $post->ID; ?>" value="<?php echo $post->ID; ?>" />
			<label for="cb-select-<?php echo $post->ID; ?>">
				<span class="screen-reader-text">
				<?php
				/* translators: Hidden accessibility text. %s: Attachment title. */
				printf( __( 'Select %s' ), _draft_or_post_title() );
				?>
				</span>
			</label>
			<?php
		}
	}

	/**
	 * Handles the title column output.
	 *
	 * @since 4.3.0
	 *
	 * @param WP_Post $post The current WP_Post object.
	 */
	public function column_title( $post ) {
		list( $mime ) = explode( '/', $post->post_mime_type );

		$attachment_id = $post->ID;

		if ( has_post_thumbnail( $post ) ) {
			$thumbnail_id = get_post_thumbnail_id( $post );

			if ( ! empty( $thumbnail_id ) ) {
				$attachment_id = $thumbnail_id;
			}
		}

		$title      = _draft_or_post_title();
		$thumb      = wp_get_attachment_image( $attachment_id, array( 60, 60 ), true, array( 'alt' => '' ) );
		$link_start = '';
		$link_end   = '';

		if ( current_user_can( 'edit_post', $post->ID ) && ! $this->is_trash ) {
			$link_start = sprintf(
				'<a href="%s" aria-label="%s">',
				get_edit_post_link( $post->ID ),
				/* translators: %s: Attachment title. */
				esc_attr( sprintf( __( '&#8220;%s&#8221; (Edit)' ), $title ) )
			);
			$link_end = '</a>';
		}

		$class = $thumb ? ' class="has-media-icon"' : '';
		?>
		<strong<?php echo $class; ?>>
			<?php
			echo $link_start;

			if ( $thumb ) :
				?>
				<span class="media-icon <?php echo sanitize_html_class( $mime . '-icon' ); ?>"><?php echo $thumb; ?></span>
				<?php
			endif;

			echo $title . $link_end;

			_media_states( $post );
			?>
		</strong>
		<p class="filename">
			<span class="screen-reader-text">
				<?php
				/* translators: Hidden accessibility text. */
				_e( 'File name:' );
				?>
			</span>
			<?php
			$file = get_attached_file( $post->ID );
			echo esc_html( wp_basename( $file ) );
			?>
		</p>
		<?php
	}

	/**
	 * Handles the author column output.
	 *
	 * @since 4.3.0
	 * @since 6.8.0 Added fallback text when author's name is unknown.
	 *
	 * @param WP_Post $post The current WP_Post object.
	 */
	public function column_author( $post ) {
		$author = get_the_author();

		if ( ! empty( $author ) ) {
			printf(
				'<a href="%s">%s</a>',
				esc_url( add_query_arg( array( 'author' => get_the_author_meta( 'ID' ) ), 'upload.php' ) ),
				esc_html( $author )
			);
		} else {
			echo '<span aria-hidden="true">&#8212;</span><span class="screen-reader-text">' . __( '(no author)' ) . '</span>';
		}
	}

	/**
	 * Handles the description column output.
	 *
	 * @since 4.3.0
	 * @deprecated 6.2.0
	 *
	 * @param WP_Post $post The current WP_Post object.
	 */
	public function column_desc( $post ) {
		_deprecated_function( __METHOD__, '6.2.0' );

		echo has_excerpt() ? $post->post_excerpt : '';
	}

	/**
	 * Handles the date column output.
	 *
	 * @since 4.3.0
	 *
	 * @param WP_Post $post The current WP_Post object.
	 */
	public function column_date( $post ) {
		if ( '0000-00-00 00:00:00' === $post->post_date ) {
			$h_time = __( 'Unpublished' );
		} else {
			$time      = get_post_timestamp( $post );
			$time_diff = time() - $time;

			if ( $time && $time_diff > 0 && $time_diff < DAY_IN_SECONDS ) {
				/* translators: %s: Human-readable time difference. */
				$h_time = sprintf( __( '%s ago' ), human_time_diff( $time ) );
			} else {
				$h_time = get_the_time( __( 'Y/m/d' ), $post );
			}
		}

		/**
		 * Filters the published time of an attachment displayed in the Media list table.
		 *
		 * @since 6.0.0
		 *
		 * @param string  $h_time      The published time.
		 * @param WP_Post $post        Attachment object.
		 * @param string  $column_name The column name.
		 */
		echo apply_filters( 'media_date_column_time', $h_time, $post, 'date' );
	}

	/**
	 * Handles the parent column output.
	 *
	 * @since 4.3.0
	 *
	 * @param WP_Post $post The current WP_Post object.
	 */
	public function column_parent( $post ) {
		$user_can_edit = current_user_can( 'edit_post', $post->ID );

		if ( $post->post_parent > 0 ) {
			$parent = get_post( $post->post_parent );
		} else {
			$parent = false;
		}

		if ( $parent ) {
			$title       = _draft_or_post_title( $post->post_parent );
			$parent_type = get_post_type_object( $parent->post_type );

			if ( $parent_type && $parent_type->show_ui && current_user_can( 'edit_post', $post->post_parent ) ) {
				printf( '<strong><a href="%s">%s</a></strong>', get_edit_post_link( $post->post_parent ), $title );
			} elseif ( $parent_type && current_user_can( 'read_post', $post->post_parent ) ) {
				printf( '<strong>%s</strong>', $title );
			} else {
				_e( '(Private post)' );
			}

			if ( $user_can_edit ) :
				$detach_url = add_query_arg(
					array(
						'parent_post_id' => $post->post_parent,
						'media[]'        => $post->ID,
						'_wpnonce'       => wp_create_nonce( 'bulk-' . $this->_args['plural'] ),
					),
					'upload.php'
				);
				printf(
					'<br /><a href="%s" class="hide-if-no-js detach-from-parent" aria-label="%s">%s</a>',
					$detach_url,
					/* translators: %s: Title of the post the attachment is attached to. */
					esc_attr( sprintf( __( 'Detach from &#8220;%s&#8221;' ), $title ) ),
					__( 'Detach' )
				);
			endif;
		} else {
			_e( '(Unattached)' );
			?>
			<?php
			if ( $user_can_edit ) {
				$title = _draft_or_post_title( $post->post_parent );
				printf(
					'<br /><a href="#the-list" onclick="findPosts.open( \'media[]\', \'%s\' ); return false;" class="hide-if-no-js aria-button-if-js" aria-label="%s">%s</a>',
					$post->ID,
					/* translators: %s: Attachment title. */
					esc_attr( sprintf( __( 'Attach &#8220;%s&#8221; to existing content' ), $title ) ),
					__( 'Attach' )
				);
			}
		}
	}

	/**
	 * Handles the comments column output.
	 *
	 * @since 4.3.0
	 *
	 * @param WP_Post $post The current WP_Post object.
	 */
	public function column_comments( $post ) {
		echo '<div class="post-com-count-wrapper">';

		if ( isset( $this->comment_pending_count[ $post->ID ] ) ) {
			$pending_comments = $this->comment_pending_count[ $post->ID ];
		} else {
			$pending_comments = get_pending_comments_num( $post->ID );
		}

		$this->comments_bubble( $post->ID, $pending_comments );

		echo '</div>';
	}

	/**
	 * Handles output for the default column.
	 *
	 * @since 4.3.0
	 * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support.
	 *
	 * @param WP_Post $item        The current WP_Post object.
	 * @param string  $column_name Current column name.
	 */
	public function column_default( $item, $column_name ) {
		// Restores the more descriptive, specific name for use within this method.
		$post = $item;

		if ( 'categories' === $column_name ) {
			$taxonomy = 'category';
		} elseif ( 'tags' === $column_name ) {
			$taxonomy = 'post_tag';
		} elseif ( str_starts_with( $column_name, 'taxonomy-' ) ) {
			$taxonomy = substr( $column_name, 9 );
		} else {
			$taxonomy = false;
		}

		if ( $taxonomy ) {
			$terms = get_the_terms( $post->ID, $taxonomy );

			if ( is_array( $terms ) ) {
				$output = array();

				foreach ( $terms as $t ) {
					$posts_in_term_qv             = array();
					$posts_in_term_qv['taxonomy'] = $taxonomy;
					$posts_in_term_qv['term']     = $t->slug;

					$output[] = sprintf(
						'<a href="%s">%s</a>',
						esc_url( add_query_arg( $posts_in_term_qv, 'upload.php' ) ),
						esc_html( sanitize_term_field( 'name', $t->name, $t->term_id, $taxonomy, 'display' ) )
					);
				}

				echo implode( wp_get_list_item_separator(), $output );
			} else {
				echo '<span aria-hidden="true">&#8212;</span><span class="screen-reader-text">' . get_taxonomy( $taxonomy )->labels->no_terms . '</span>';
			}

			return;
		}

		/**
		 * Fires for each custom column in the Media list table.
		 *
		 * Custom columns are registered using the {@see 'manage_media_columns'} filter.
		 *
		 * @since 2.5.0
		 *
		 * @param string $column_name Name of the custom column.
		 * @param int    $post_id     Attachment ID.
		 */
		do_action( 'manage_media_custom_column', $column_name, $post->ID );
	}

	/**
	 * Generates the list table rows.
	 *
	 * @since 3.1.0
	 *
	 * @global WP_Post  $post     Global post object.
	 * @global WP_Query $wp_query WordPress Query object.
	 */
	public function display_rows() {
		global $post, $wp_query;

		$post_ids = wp_list_pluck( $wp_query->posts, 'ID' );
		reset( $wp_query->posts );

		$this->comment_pending_count = get_pending_comments_num( $post_ids );

		add_filter( 'the_title', 'esc_html' );

		while ( have_posts() ) :
			the_post();

			if ( $this->is_trash && 'trash' !== $post->post_status
				|| ! $this->is_trash && 'trash' === $post->post_status
			) {
				continue;
			}

			$post_owner = ( get_current_user_id() === (int) $post->post_author ) ? 'self' : 'other';
			?>
			<tr id="post-<?php echo $post->ID; ?>" class="<?php echo trim( ' author-' . $post_owner . ' status-' . $post->post_status ); ?>">
				<?php $this->single_row_columns( $post ); ?>
			</tr>
			<?php
		endwhile;
	}

	/**
	 * Gets the name of the default primary column.
	 *
	 * @since 4.3.0
	 *
	 * @return string Name of the default primary column, in this case, 'title'.
	 */
	protected function get_default_primary_column_name() {
		return 'title';
	}

	/**
	 * @param WP_Post $post
	 * @param string  $att_title
	 * @return array
	 */
	private function _get_row_actions( $post, $att_title ) {
		$actions = array();

		if ( ! $this->is_trash && current_user_can( 'edit_post', $post->ID ) ) {
			$actions['edit'] = sprintf(
				'<a href="%s" aria-label="%s">%s</a>',
				esc_url( get_edit_post_link( $post->ID ) ),
				/* translators: %s: Attachment title. */
				esc_attr( sprintf( __( 'Edit &#8220;%s&#8221;' ), $att_title ) ),
				__( 'Edit' )
			);
		}

		if ( current_user_can( 'delete_post', $post->ID ) ) {
			if ( $this->is_trash ) {
				$actions['untrash'] = sprintf(
					'<a href="%s" class="submitdelete aria-button-if-js" aria-label="%s">%s</a>',
					esc_url( wp_nonce_url( "post.php?action=untrash&amp;post=$post->ID", 'untrash-post_' . $post->ID ) ),
					/* translators: %s: Attachment title. */
					esc_attr( sprintf( __( 'Restore &#8220;%s&#8221; from the Trash' ), $att_title ) ),
					__( 'Restore' )
				);
			} elseif ( EMPTY_TRASH_DAYS && MEDIA_TRASH ) {
				$actions['trash'] = sprintf(
					'<a href="%s" class="submitdelete aria-button-if-js" aria-label="%s">%s</a>',
					esc_url( wp_nonce_url( "post.php?action=trash&amp;post=$post->ID", 'trash-post_' . $post->ID ) ),
					/* translators: %s: Attachment title. */
					esc_attr( sprintf( __( 'Move &#8220;%s&#8221; to the Trash' ), $att_title ) ),
					_x( 'Trash', 'verb' )
				);
			}

			if ( $this->is_trash || ! EMPTY_TRASH_DAYS || ! MEDIA_TRASH ) {
				$show_confirmation = ( ! $this->is_trash && ! MEDIA_TRASH ) ? " onclick='return showNotice.warn();'" : '';

				$actions['delete'] = sprintf(
					'<a href="%s" class="submitdelete aria-button-if-js"%s aria-label="%s">%s</a>',
					esc_url( wp_nonce_url( "post.php?action=delete&amp;post=$post->ID", 'delete-post_' . $post->ID ) ),
					$show_confirmation,
					/* translators: %s: Attachment title. */
					esc_attr( sprintf( __( 'Delete &#8220;%s&#8221; permanently' ), $att_title ) ),
					__( 'Delete Permanently' )
				);
			}
		}

		$attachment_url = wp_get_attachment_url( $post->ID );

		if ( ! $this->is_trash ) {
			$permalink = get_permalink( $post->ID );

			if ( $permalink ) {
				$actions['view'] = sprintf(
					'<a href="%s" aria-label="%s" rel="bookmark">%s</a>',
					esc_url( $permalink ),
					/* translators: %s: Attachment title. */
					esc_attr( sprintf( __( 'View &#8220;%s&#8221;' ), $att_title ) ),
					__( 'View' )
				);
			}

			if ( $attachment_url ) {
				$actions['copy'] = sprintf(
					'<span class="copy-to-clipboard-container"><button type="button" class="button-link copy-attachment-url media-library" data-clipboard-text="%s" aria-label="%s">%s</button><span class="success hidden" aria-hidden="true">%s</span></span>',
					esc_url( $attachment_url ),
					/* translators: %s: Attachment title. */
					esc_attr( sprintf( __( 'Copy &#8220;%s&#8221; URL to clipboard' ), $att_title ) ),
					__( 'Copy URL' ),
					__( 'Copied!' )
				);
			}
		}

		if ( $attachment_url ) {
			$actions['download'] = sprintf(
				'<a href="%s" aria-label="%s" download>%s</a>',
				esc_url( $attachment_url ),
				/* translators: %s: Attachment title. */
				esc_attr( sprintf( __( 'Download &#8220;%s&#8221;' ), $att_title ) ),
				__( 'Download file' )
			);
		}

		if ( $this->detached && current_user_can( 'edit_post', $post->ID ) ) {
			$actions['attach'] = sprintf(
				'<a href="#the-list" onclick="findPosts.open( \'media[]\', \'%s\' ); return false;" class="hide-if-no-js aria-button-if-js" aria-label="%s">%s</a>',
				$post->ID,
				/* translators: %s: Attachment title. */
				esc_attr( sprintf( __( 'Attach &#8220;%s&#8221; to existing content' ), $att_title ) ),
				__( 'Attach' )
			);
		}

		/**
		 * Filters the action links for each attachment in the Media list table.
		 *
		 * @since 2.8.0
		 *
		 * @param string[] $actions  An array of action links for each attachment.
		 *                           Includes 'Edit', 'Delete Permanently', 'View',
		 *                           'Copy URL' and 'Download file'.
		 * @param WP_Post  $post     WP_Post object for the current attachment.
		 * @param bool     $detached Whether the list table contains media not attached
		 *                           to any posts. Default true.
		 */
		return apply_filters( 'media_row_actions', $actions, $post, $this->detached );
	}

	/**
	 * Generates and displays row action links.
	 *
	 * @since 4.3.0
	 * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support.
	 *
	 * @param WP_Post $item        Attachment being acted upon.
	 * @param string  $column_name Current column name.
	 * @param string  $primary     Primary column name.
	 * @return string Row actions output for media attachments, or an empty string
	 *                if the current column is not the primary column.
	 */
	protected function handle_row_actions( $item, $column_name, $primary ) {
		if ( $primary !== $column_name ) {
			return '';
		}

		// Restores the more descriptive, specific name for use within this method.
		$post = $item;

		$att_title = _draft_or_post_title();
		$actions   = $this->_get_row_actions( $post, $att_title );

		return $this->row_actions( $actions );
	}
}
plugin-install.php000064400000114411151212616040010217 0ustar00<?php
/**
 * WordPress Plugin Install Administration API
 *
 * @package WordPress
 * @subpackage Administration
 */

/**
 * Retrieves plugin installer pages from the WordPress.org Plugins API.
 *
 * It is possible for a plugin to override the Plugin API result with three
 * filters. Assume this is for plugins, which can extend on the Plugin Info to
 * offer more choices. This is very powerful and must be used with care when
 * overriding the filters.
 *
 * The first filter, {@see 'plugins_api_args'}, is for the args and gives the action
 * as the second parameter. The hook for {@see 'plugins_api_args'} must ensure that
 * an object is returned.
 *
 * The second filter, {@see 'plugins_api'}, allows a plugin to override the WordPress.org
 * Plugin Installation API entirely. If `$action` is 'query_plugins' or 'plugin_information',
 * an object MUST be passed. If `$action` is 'hot_tags', an array MUST be passed.
 *
 * Finally, the third filter, {@see 'plugins_api_result'}, makes it possible to filter the
 * response object or array, depending on the `$action` type.
 *
 * Supported arguments per action:
 *
 * | Argument Name        | query_plugins | plugin_information | hot_tags |
 * | -------------------- | :-----------: | :----------------: | :------: |
 * | `$slug`              | No            |  Yes               | No       |
 * | `$per_page`          | Yes           |  No                | No       |
 * | `$page`              | Yes           |  No                | No       |
 * | `$number`            | No            |  No                | Yes      |
 * | `$search`            | Yes           |  No                | No       |
 * | `$tag`               | Yes           |  No                | No       |
 * | `$author`            | Yes           |  No                | No       |
 * | `$user`              | Yes           |  No                | No       |
 * | `$browse`            | Yes           |  No                | No       |
 * | `$locale`            | Yes           |  Yes               | No       |
 * | `$installed_plugins` | Yes           |  No                | No       |
 * | `$is_ssl`            | Yes           |  Yes               | No       |
 * | `$fields`            | Yes           |  Yes               | No       |
 *
 * @since 2.7.0
 *
 * @param string       $action API action to perform: 'query_plugins', 'plugin_information',
 *                             or 'hot_tags'.
 * @param array|object $args   {
 *     Optional. Array or object of arguments to serialize for the Plugin Info API.
 *
 *     @type string  $slug              The plugin slug. Default empty.
 *     @type int     $per_page          Number of plugins per page. Default 24.
 *     @type int     $page              Number of current page. Default 1.
 *     @type int     $number            Number of tags or categories to be queried.
 *     @type string  $search            A search term. Default empty.
 *     @type string  $tag               Tag to filter plugins. Default empty.
 *     @type string  $author            Username of an plugin author to filter plugins. Default empty.
 *     @type string  $user              Username to query for their favorites. Default empty.
 *     @type string  $browse            Browse view: 'popular', 'new', 'beta', 'recommended'.
 *     @type string  $locale            Locale to provide context-sensitive results. Default is the value
 *                                      of get_locale().
 *     @type string  $installed_plugins Installed plugins to provide context-sensitive results.
 *     @type bool    $is_ssl            Whether links should be returned with https or not. Default false.
 *     @type array   $fields            {
 *         Array of fields which should or should not be returned.
 *
 *         @type bool $short_description Whether to return the plugin short description. Default true.
 *         @type bool $description       Whether to return the plugin full description. Default false.
 *         @type bool $sections          Whether to return the plugin readme sections: description, installation,
 *                                       FAQ, screenshots, other notes, and changelog. Default false.
 *         @type bool $tested            Whether to return the 'Compatible up to' value. Default true.
 *         @type bool $requires          Whether to return the required WordPress version. Default true.
 *         @type bool $requires_php      Whether to return the required PHP version. Default true.
 *         @type bool $rating            Whether to return the rating in percent and total number of ratings.
 *                                       Default true.
 *         @type bool $ratings           Whether to return the number of rating for each star (1-5). Default true.
 *         @type bool $downloaded        Whether to return the download count. Default true.
 *         @type bool $downloadlink      Whether to return the download link for the package. Default true.
 *         @type bool $last_updated      Whether to return the date of the last update. Default true.
 *         @type bool $added             Whether to return the date when the plugin was added to the wordpress.org
 *                                       repository. Default true.
 *         @type bool $tags              Whether to return the assigned tags. Default true.
 *         @type bool $compatibility     Whether to return the WordPress compatibility list. Default true.
 *         @type bool $homepage          Whether to return the plugin homepage link. Default true.
 *         @type bool $versions          Whether to return the list of all available versions. Default false.
 *         @type bool $donate_link       Whether to return the donation link. Default true.
 *         @type bool $reviews           Whether to return the plugin reviews. Default false.
 *         @type bool $banners           Whether to return the banner images links. Default false.
 *         @type bool $icons             Whether to return the icon links. Default false.
 *         @type bool $active_installs   Whether to return the number of active installations. Default false.
 *         @type bool $contributors      Whether to return the list of contributors. Default false.
 *     }
 * }
 * @return object|array|WP_Error Response object or array on success, WP_Error on failure. See the
 *         {@link https://developer.wordpress.org/reference/functions/plugins_api/ function reference article}
 *         for more information on the make-up of possible return values depending on the value of `$action`.
 */
function plugins_api( $action, $args = array() ) {
	if ( is_array( $args ) ) {
		$args = (object) $args;
	}

	if ( 'query_plugins' === $action ) {
		if ( ! isset( $args->per_page ) ) {
			$args->per_page = 24;
		}
	}

	if ( ! isset( $args->locale ) ) {
		$args->locale = get_user_locale();
	}

	if ( ! isset( $args->wp_version ) ) {
		$args->wp_version = substr( wp_get_wp_version(), 0, 3 ); // x.y
	}

	/**
	 * Filters the WordPress.org Plugin Installation API arguments.
	 *
	 * Important: An object MUST be returned to this filter.
	 *
	 * @since 2.7.0
	 *
	 * @param object $args   Plugin API arguments.
	 * @param string $action The type of information being requested from the Plugin Installation API.
	 */
	$args = apply_filters( 'plugins_api_args', $args, $action );

	/**
	 * Filters the response for the current WordPress.org Plugin Installation API request.
	 *
	 * Returning a non-false value will effectively short-circuit the WordPress.org API request.
	 *
	 * If `$action` is 'query_plugins' or 'plugin_information', an object MUST be passed.
	 * If `$action` is 'hot_tags', an array should be passed.
	 *
	 * @since 2.7.0
	 *
	 * @param false|object|array $result The result object or array. Default false.
	 * @param string             $action The type of information being requested from the Plugin Installation API.
	 * @param object             $args   Plugin API arguments.
	 */
	$res = apply_filters( 'plugins_api', false, $action, $args );

	if ( false === $res ) {

		$url = 'http://api.wordpress.org/plugins/info/1.2/';
		$url = add_query_arg(
			array(
				'action'  => $action,
				'request' => $args,
			),
			$url
		);

		$http_url = $url;
		$ssl      = wp_http_supports( array( 'ssl' ) );
		if ( $ssl ) {
			$url = set_url_scheme( $url, 'https' );
		}

		$http_args = array(
			'timeout'    => 15,
			'user-agent' => 'WordPress/' . wp_get_wp_version() . '; ' . home_url( '/' ),
		);
		$request   = wp_remote_get( $url, $http_args );

		if ( $ssl && is_wp_error( $request ) ) {
			if ( ! wp_is_json_request() ) {
				wp_trigger_error(
					__FUNCTION__,
					sprintf(
						/* translators: %s: Support forums URL. */
						__( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ),
						__( 'https://wordpress.org/support/forums/' )
					) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ),
					headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE
				);
			}

			$request = wp_remote_get( $http_url, $http_args );
		}

		if ( is_wp_error( $request ) ) {
			$res = new WP_Error(
				'plugins_api_failed',
				sprintf(
					/* translators: %s: Support forums URL. */
					__( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ),
					__( 'https://wordpress.org/support/forums/' )
				),
				$request->get_error_message()
			);
		} else {
			$res = json_decode( wp_remote_retrieve_body( $request ), true );
			if ( is_array( $res ) ) {
				// Object casting is required in order to match the info/1.0 format.
				$res = (object) $res;
			} elseif ( null === $res ) {
				$res = new WP_Error(
					'plugins_api_failed',
					sprintf(
						/* translators: %s: Support forums URL. */
						__( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ),
						__( 'https://wordpress.org/support/forums/' )
					),
					wp_remote_retrieve_body( $request )
				);
			}

			if ( isset( $res->error ) ) {
				$res = new WP_Error( 'plugins_api_failed', $res->error );
			}
		}
	} elseif ( ! is_wp_error( $res ) ) {
		$res->external = true;
	}

	/**
	 * Filters the Plugin Installation API response results.
	 *
	 * @since 2.7.0
	 *
	 * @param object|WP_Error $res    Response object or WP_Error.
	 * @param string          $action The type of information being requested from the Plugin Installation API.
	 * @param object          $args   Plugin API arguments.
	 */
	return apply_filters( 'plugins_api_result', $res, $action, $args );
}

/**
 * Retrieves popular WordPress plugin tags.
 *
 * @since 2.7.0
 *
 * @param array $args
 * @return array|WP_Error
 */
function install_popular_tags( $args = array() ) {
	$key  = md5( serialize( $args ) );
	$tags = get_site_transient( 'poptags_' . $key );
	if ( false !== $tags ) {
		return $tags;
	}

	$tags = plugins_api( 'hot_tags', $args );

	if ( is_wp_error( $tags ) ) {
		return $tags;
	}

	set_site_transient( 'poptags_' . $key, $tags, 3 * HOUR_IN_SECONDS );

	return $tags;
}

/**
 * Displays the Featured tab of Add Plugins screen.
 *
 * @since 2.7.0
 */
function install_dashboard() {
	display_plugins_table();
	?>

	<div class="plugins-popular-tags-wrapper">
	<h2><?php _e( 'Popular tags' ); ?></h2>
	<p><?php _e( 'You may also browse based on the most popular tags in the Plugin Directory:' ); ?></p>
	<?php

	$api_tags = install_popular_tags();

	echo '<p class="popular-tags">';
	if ( is_wp_error( $api_tags ) ) {
		echo $api_tags->get_error_message();
	} else {
		// Set up the tags in a way which can be interpreted by wp_generate_tag_cloud().
		$tags = array();
		foreach ( (array) $api_tags as $tag ) {
			$url                  = self_admin_url( 'plugin-install.php?tab=search&type=tag&s=' . urlencode( $tag['name'] ) );
			$data                 = array(
				'link'  => esc_url( $url ),
				'name'  => $tag['name'],
				'slug'  => $tag['slug'],
				'id'    => sanitize_title_with_dashes( $tag['name'] ),
				'count' => $tag['count'],
			);
			$tags[ $tag['name'] ] = (object) $data;
		}
		echo wp_generate_tag_cloud(
			$tags,
			array(
				/* translators: %s: Number of plugins. */
				'single_text'   => __( '%s plugin' ),
				/* translators: %s: Number of plugins. */
				'multiple_text' => __( '%s plugins' ),
			)
		);
	}
	echo '</p><br class="clear" /></div>';
}

/**
 * Displays a search form for searching plugins.
 *
 * @since 2.7.0
 * @since 4.6.0 The `$type_selector` parameter was deprecated.
 *
 * @param bool $deprecated Not used.
 */
function install_search_form( $deprecated = true ) {
	$type = isset( $_REQUEST['type'] ) ? wp_unslash( $_REQUEST['type'] ) : 'term';
	$term = isset( $_REQUEST['s'] ) ? urldecode( wp_unslash( $_REQUEST['s'] ) ) : '';
	?>
	<form class="search-form search-plugins" method="get">
		<input type="hidden" name="tab" value="search" />
		<label for="search-plugins"><?php _e( 'Search Plugins' ); ?></label>
		<input type="search" name="s" id="search-plugins" value="<?php echo esc_attr( $term ); ?>" class="wp-filter-search" />
		<label class="screen-reader-text" for="typeselector">
			<?php
			/* translators: Hidden accessibility text. */
			_e( 'Search plugins by:' );
			?>
		</label>
		<select name="type" id="typeselector">
			<option value="term"<?php selected( 'term', $type ); ?>><?php _e( 'Keyword' ); ?></option>
			<option value="author"<?php selected( 'author', $type ); ?>><?php _e( 'Author' ); ?></option>
			<option value="tag"<?php selected( 'tag', $type ); ?>><?php _ex( 'Tag', 'Plugin Installer' ); ?></option>
		</select>
		<?php submit_button( __( 'Search Plugins' ), 'hide-if-js', false, false, array( 'id' => 'search-submit' ) ); ?>
	</form>
	<?php
}

/**
 * Displays a form to upload plugins from zip files.
 *
 * @since 2.8.0
 */
function install_plugins_upload() {
	?>
<div class="upload-plugin">
	<p class="install-help"><?php _e( 'If you have a plugin in a .zip format, you may install or update it by uploading it here.' ); ?></p>
	<form method="post" enctype="multipart/form-data" class="wp-upload-form" action="<?php echo esc_url( self_admin_url( 'update.php?action=upload-plugin' ) ); ?>">
		<?php wp_nonce_field( 'plugin-upload' ); ?>
		<label class="screen-reader-text" for="pluginzip">
			<?php
			/* translators: Hidden accessibility text. */
			_e( 'Plugin zip file' );
			?>
		</label>
		<input type="file" id="pluginzip" name="pluginzip" accept=".zip" />
		<?php submit_button( _x( 'Install Now', 'plugin' ), '', 'install-plugin-submit', false ); ?>
	</form>
</div>
	<?php
}

/**
 * Shows a username form for the favorites page.
 *
 * @since 3.5.0
 */
function install_plugins_favorites_form() {
	$user   = get_user_option( 'wporg_favorites' );
	$action = 'save_wporg_username_' . get_current_user_id();
	?>
	<p><?php _e( 'If you have marked plugins as favorites on WordPress.org, you can browse them here.' ); ?></p>
	<form method="get">
		<input type="hidden" name="tab" value="favorites" />
		<p>
			<label for="user"><?php _e( 'Your WordPress.org username:' ); ?></label>
			<input type="search" id="user" name="user" value="<?php echo esc_attr( $user ); ?>" />
			<input type="submit" class="button" value="<?php esc_attr_e( 'Get Favorites' ); ?>" />
			<input type="hidden" id="wporg-username-nonce" name="_wpnonce" value="<?php echo esc_attr( wp_create_nonce( $action ) ); ?>" />
		</p>
	</form>
	<?php
}

/**
 * Displays plugin content based on plugin list.
 *
 * @since 2.7.0
 *
 * @global WP_List_Table $wp_list_table
 */
function display_plugins_table() {
	global $wp_list_table;

	switch ( current_filter() ) {
		case 'install_plugins_beta':
			printf(
				/* translators: %s: URL to "Features as Plugins" page. */
				'<p>' . __( 'You are using a development version of WordPress. These feature plugins are also under development. <a href="%s">Learn more</a>.' ) . '</p>',
				'https://make.wordpress.org/core/handbook/about/release-cycle/features-as-plugins/'
			);
			break;
		case 'install_plugins_featured':
			break;
		case 'install_plugins_recommended':
			echo '<p>' . __( 'These suggestions are based on the plugins you and other users have installed.' ) . '</p>';
			break;
		case 'install_plugins_favorites':
			if ( empty( $_GET['user'] ) && ! get_user_option( 'wporg_favorites' ) ) {
				return;
			}
			break;
	}
	if ( isset( $_GET['tab'] ) && 'featured' === $_GET['tab'] ) {
		echo '<br />';
	}
	?>
	<form id="plugin-filter" method="post">
		<?php $wp_list_table->display(); ?>
	</form>
	<?php
}

/**
 * Determines the status we can perform on a plugin.
 *
 * @since 3.0.0
 *
 * @param array|object $api  Data about the plugin retrieved from the API.
 * @param bool         $loop Optional. Disable further loops. Default false.
 * @return array {
 *     Plugin installation status data.
 *
 *     @type string $status  Status of a plugin. Could be one of 'install', 'update_available', 'latest_installed' or 'newer_installed'.
 *     @type string $url     Plugin installation URL.
 *     @type string $version The most recent version of the plugin.
 *     @type string $file    Plugin filename relative to the plugins directory.
 * }
 */
function install_plugin_install_status( $api, $loop = false ) {
	// This function is called recursively, $loop prevents further loops.
	if ( is_array( $api ) ) {
		$api = (object) $api;
	}

	// Default to a "new" plugin.
	$status      = 'install';
	$url         = false;
	$update_file = false;
	$version     = '';

	/*
	 * Check to see if this plugin is known to be installed,
	 * and has an update awaiting it.
	 */
	$update_plugins = get_site_transient( 'update_plugins' );
	if ( isset( $update_plugins->response ) ) {
		foreach ( (array) $update_plugins->response as $file => $plugin ) {
			if ( $plugin->slug === $api->slug ) {
				$status      = 'update_available';
				$update_file = $file;
				$version     = $plugin->new_version;
				if ( current_user_can( 'update_plugins' ) ) {
					$url = wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' . $update_file ), 'upgrade-plugin_' . $update_file );
				}
				break;
			}
		}
	}

	if ( 'install' === $status ) {
		if ( is_dir( WP_PLUGIN_DIR . '/' . $api->slug ) ) {
			$installed_plugin = get_plugins( '/' . $api->slug );
			if ( empty( $installed_plugin ) ) {
				if ( current_user_can( 'install_plugins' ) ) {
					$url = wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=' . $api->slug ), 'install-plugin_' . $api->slug );
				}
			} else {
				$key = array_keys( $installed_plugin );
				/*
				 * Use the first plugin regardless of the name.
				 * Could have issues for multiple plugins in one directory if they share different version numbers.
				 */
				$key = reset( $key );

				$update_file = $api->slug . '/' . $key;
				if ( version_compare( $api->version, $installed_plugin[ $key ]['Version'], '=' ) ) {
					$status = 'latest_installed';
				} elseif ( version_compare( $api->version, $installed_plugin[ $key ]['Version'], '<' ) ) {
					$status  = 'newer_installed';
					$version = $installed_plugin[ $key ]['Version'];
				} else {
					// If the above update check failed, then that probably means that the update checker has out-of-date information, force a refresh.
					if ( ! $loop ) {
						delete_site_transient( 'update_plugins' );
						wp_update_plugins();
						return install_plugin_install_status( $api, true );
					}
				}
			}
		} else {
			// "install" & no directory with that slug.
			if ( current_user_can( 'install_plugins' ) ) {
				$url = wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=' . $api->slug ), 'install-plugin_' . $api->slug );
			}
		}
	}
	if ( isset( $_GET['from'] ) ) {
		$url .= '&amp;from=' . urlencode( wp_unslash( $_GET['from'] ) );
	}

	$file = $update_file;
	return compact( 'status', 'url', 'version', 'file' );
}

/**
 * Displays plugin information in dialog box form.
 *
 * @since 2.7.0
 *
 * @global string $tab
 */
function install_plugin_information() {
	global $tab;

	if ( empty( $_REQUEST['plugin'] ) ) {
		return;
	}

	$api = plugins_api(
		'plugin_information',
		array(
			'slug' => wp_unslash( $_REQUEST['plugin'] ),
		)
	);

	if ( is_wp_error( $api ) ) {
		wp_die( $api );
	}

	$plugins_allowedtags = array(
		'a'          => array(
			'href'   => array(),
			'title'  => array(),
			'target' => array(),
		),
		'abbr'       => array( 'title' => array() ),
		'acronym'    => array( 'title' => array() ),
		'code'       => array(),
		'pre'        => array(),
		'em'         => array(),
		'strong'     => array(),
		'div'        => array( 'class' => array() ),
		'span'       => array( 'class' => array() ),
		'p'          => array(),
		'br'         => array(),
		'ul'         => array(),
		'ol'         => array(),
		'li'         => array(),
		'h1'         => array(),
		'h2'         => array(),
		'h3'         => array(),
		'h4'         => array(),
		'h5'         => array(),
		'h6'         => array(),
		'img'        => array(
			'src'   => array(),
			'class' => array(),
			'alt'   => array(),
		),
		'blockquote' => array( 'cite' => true ),
	);

	$plugins_section_titles = array(
		'description'  => _x( 'Description', 'Plugin installer section title' ),
		'installation' => _x( 'Installation', 'Plugin installer section title' ),
		'faq'          => _x( 'FAQ', 'Plugin installer section title' ),
		'screenshots'  => _x( 'Screenshots', 'Plugin installer section title' ),
		'changelog'    => _x( 'Changelog', 'Plugin installer section title' ),
		'reviews'      => _x( 'Reviews', 'Plugin installer section title' ),
		'other_notes'  => _x( 'Other Notes', 'Plugin installer section title' ),
	);

	// Sanitize HTML.
	foreach ( (array) $api->sections as $section_name => $content ) {
		$api->sections[ $section_name ] = wp_kses( $content, $plugins_allowedtags );
	}

	foreach ( array( 'version', 'author', 'requires', 'tested', 'homepage', 'downloaded', 'slug' ) as $key ) {
		if ( isset( $api->$key ) ) {
			$api->$key = wp_kses( $api->$key, $plugins_allowedtags );
		}
	}

	$_tab = esc_attr( $tab );

	// Default to the Description tab, Do not translate, API returns English.
	$section = isset( $_REQUEST['section'] ) ? wp_unslash( $_REQUEST['section'] ) : 'description';
	if ( empty( $section ) || ! isset( $api->sections[ $section ] ) ) {
		$section_titles = array_keys( (array) $api->sections );
		$section        = reset( $section_titles );
	}

	iframe_header( __( 'Plugin Installation' ) );

	$_with_banner = '';

	if ( ! empty( $api->banners ) && ( ! empty( $api->banners['low'] ) || ! empty( $api->banners['high'] ) ) ) {
		$_with_banner = 'with-banner';
		$low          = empty( $api->banners['low'] ) ? $api->banners['high'] : $api->banners['low'];
		$high         = empty( $api->banners['high'] ) ? $api->banners['low'] : $api->banners['high'];
		?>
		<style type="text/css">
			#plugin-information-title.with-banner {
				background-image: url( <?php echo esc_url( $low ); ?> );
			}
			@media only screen and ( -webkit-min-device-pixel-ratio: 1.5 ) {
				#plugin-information-title.with-banner {
					background-image: url( <?php echo esc_url( $high ); ?> );
				}
			}
		</style>
		<?php
	}

	echo '<div id="plugin-information-scrollable">';
	echo "<div id='{$_tab}-title' class='{$_with_banner}'><div class='vignette'></div><h2>{$api->name}</h2></div>";
	echo "<div id='{$_tab}-tabs' class='{$_with_banner}'>\n";

	foreach ( (array) $api->sections as $section_name => $content ) {
		if ( 'reviews' === $section_name && ( empty( $api->ratings ) || 0 === array_sum( (array) $api->ratings ) ) ) {
			continue;
		}

		if ( isset( $plugins_section_titles[ $section_name ] ) ) {
			$title = $plugins_section_titles[ $section_name ];
		} else {
			$title = ucwords( str_replace( '_', ' ', $section_name ) );
		}

		$class       = ( $section_name === $section ) ? ' class="current"' : '';
		$href        = add_query_arg(
			array(
				'tab'     => $tab,
				'section' => $section_name,
			)
		);
		$href        = esc_url( $href );
		$san_section = esc_attr( $section_name );
		echo "\t<a name='$san_section' href='$href' $class>$title</a>\n";
	}

	echo "</div>\n";

	?>
<div id="<?php echo $_tab; ?>-content" class='<?php echo $_with_banner; ?>'>
	<div class="fyi">
		<ul>
			<?php if ( ! empty( $api->version ) ) { ?>
				<li><strong><?php _e( 'Version:' ); ?></strong> <?php echo $api->version; ?></li>
			<?php } if ( ! empty( $api->author ) ) { ?>
				<li><strong><?php _e( 'Author:' ); ?></strong> <?php echo links_add_target( $api->author, '_blank' ); ?></li>
			<?php } if ( ! empty( $api->last_updated ) ) { ?>
				<li><strong><?php _e( 'Last Updated:' ); ?></strong>
					<?php
					/* translators: %s: Human-readable time difference. */
					printf( __( '%s ago' ), human_time_diff( strtotime( $api->last_updated ) ) );
					?>
				</li>
			<?php } if ( ! empty( $api->requires ) ) { ?>
				<li>
					<strong><?php _e( 'Requires WordPress Version:' ); ?></strong>
					<?php
					/* translators: %s: Version number. */
					printf( __( '%s or higher' ), $api->requires );
					?>
				</li>
			<?php } if ( ! empty( $api->tested ) ) { ?>
				<li><strong><?php _e( 'Compatible up to:' ); ?></strong> <?php echo $api->tested; ?></li>
			<?php } if ( ! empty( $api->requires_php ) ) { ?>
				<li>
					<strong><?php _e( 'Requires PHP Version:' ); ?></strong>
					<?php
					/* translators: %s: Version number. */
					printf( __( '%s or higher' ), $api->requires_php );
					?>
				</li>
			<?php } if ( isset( $api->active_installs ) ) { ?>
				<li><strong><?php _e( 'Active Installations:' ); ?></strong>
				<?php
				if ( $api->active_installs >= 1000000 ) {
					$active_installs_millions = floor( $api->active_installs / 1000000 );
					printf(
						/* translators: %s: Number of millions. */
						_nx( '%s+ Million', '%s+ Million', $active_installs_millions, 'Active plugin installations' ),
						number_format_i18n( $active_installs_millions )
					);
				} elseif ( $api->active_installs < 10 ) {
					_ex( 'Less Than 10', 'Active plugin installations' );
				} else {
					echo number_format_i18n( $api->active_installs ) . '+';
				}
				?>
				</li>
			<?php } if ( ! empty( $api->slug ) && empty( $api->external ) ) { ?>
				<li><a target="_blank" href="<?php echo esc_url( __( 'https://wordpress.org/plugins/' ) . $api->slug ); ?>/"><?php _e( 'WordPress.org Plugin Page &#187;' ); ?></a></li>
			<?php } if ( ! empty( $api->homepage ) ) { ?>
				<li><a target="_blank" href="<?php echo esc_url( $api->homepage ); ?>"><?php _e( 'Plugin Homepage &#187;' ); ?></a></li>
			<?php } if ( ! empty( $api->donate_link ) && empty( $api->contributors ) ) { ?>
				<li><a target="_blank" href="<?php echo esc_url( $api->donate_link ); ?>"><?php _e( 'Donate to this plugin &#187;' ); ?></a></li>
			<?php } ?>
		</ul>
		<?php if ( ! empty( $api->rating ) ) { ?>
			<h3><?php _e( 'Average Rating' ); ?></h3>
			<?php
			wp_star_rating(
				array(
					'rating' => $api->rating,
					'type'   => 'percent',
					'number' => $api->num_ratings,
				)
			);
			?>
			<p aria-hidden="true" class="fyi-description">
				<?php
				printf(
					/* translators: %s: Number of ratings. */
					_n( '(based on %s rating)', '(based on %s ratings)', $api->num_ratings ),
					number_format_i18n( $api->num_ratings )
				);
				?>
			</p>
			<?php
		}

		if ( ! empty( $api->ratings ) && array_sum( (array) $api->ratings ) > 0 ) {
			?>
			<h3><?php _e( 'Reviews' ); ?></h3>
			<p class="fyi-description"><?php _e( 'Read all reviews on WordPress.org or write your own!' ); ?></p>
			<?php
			foreach ( $api->ratings as $key => $ratecount ) {
				// Avoid div-by-zero.
				$_rating    = $api->num_ratings ? ( $ratecount / $api->num_ratings ) : 0;
				$aria_label = esc_attr(
					sprintf(
						/* translators: 1: Number of stars (used to determine singular/plural), 2: Number of reviews. */
						_n(
							'Reviews with %1$d star: %2$s. Opens in a new tab.',
							'Reviews with %1$d stars: %2$s. Opens in a new tab.',
							$key
						),
						$key,
						number_format_i18n( $ratecount )
					)
				);
				?>
				<div class="counter-container">
						<span class="counter-label">
							<?php
							printf(
								'<a href="%s" target="_blank" aria-label="%s">%s</a>',
								"https://wordpress.org/support/plugin/{$api->slug}/reviews/?filter={$key}",
								$aria_label,
								/* translators: %s: Number of stars. */
								sprintf( _n( '%d star', '%d stars', $key ), $key )
							);
							?>
						</span>
						<span class="counter-back">
							<span class="counter-bar" style="width: <?php echo 92 * $_rating; ?>px;"></span>
						</span>
					<span class="counter-count" aria-hidden="true"><?php echo number_format_i18n( $ratecount ); ?></span>
				</div>
				<?php
			}
		}
		if ( ! empty( $api->contributors ) ) {
			?>
			<h3><?php _e( 'Contributors' ); ?></h3>
			<ul class="contributors">
				<?php
				foreach ( (array) $api->contributors as $contrib_username => $contrib_details ) {
					$contrib_name = $contrib_details['display_name'];
					if ( ! $contrib_name ) {
						$contrib_name = $contrib_username;
					}
					$contrib_name = esc_html( $contrib_name );

					$contrib_profile = esc_url( $contrib_details['profile'] );
					$contrib_avatar  = esc_url( add_query_arg( 's', '36', $contrib_details['avatar'] ) );

					echo "<li><a href='{$contrib_profile}' target='_blank'><img src='{$contrib_avatar}' width='18' height='18' alt='' />{$contrib_name}</a></li>";
				}
				?>
			</ul>
					<?php if ( ! empty( $api->donate_link ) ) { ?>
				<a target="_blank" href="<?php echo esc_url( $api->donate_link ); ?>"><?php _e( 'Donate to this plugin &#187;' ); ?></a>
			<?php } ?>
				<?php } ?>
	</div>
	<div id="section-holder">
	<?php
	$requires_php = isset( $api->requires_php ) ? $api->requires_php : null;
	$requires_wp  = isset( $api->requires ) ? $api->requires : null;

	$compatible_php = is_php_version_compatible( $requires_php );
	$compatible_wp  = is_wp_version_compatible( $requires_wp );
	$tested_wp      = ( empty( $api->tested ) || version_compare( get_bloginfo( 'version' ), $api->tested, '<=' ) );

	if ( ! $compatible_php ) {
		$compatible_php_notice_message  = '<p>';
		$compatible_php_notice_message .= __( '<strong>Error:</strong> This plugin <strong>requires a newer version of PHP</strong>.' );

		if ( current_user_can( 'update_php' ) ) {
			$compatible_php_notice_message .= sprintf(
				/* translators: %s: URL to Update PHP page. */
				' ' . __( '<a href="%s" target="_blank">Click here to learn more about updating PHP</a>.' ),
				esc_url( wp_get_update_php_url() )
			) . wp_update_php_annotation( '</p><p><em>', '</em>', false );
		} else {
			$compatible_php_notice_message .= '</p>';
		}

		wp_admin_notice(
			$compatible_php_notice_message,
			array(
				'type'               => 'error',
				'additional_classes' => array( 'notice-alt' ),
				'paragraph_wrap'     => false,
			)
		);
	}

	if ( ! $tested_wp ) {
		wp_admin_notice(
			__( '<strong>Warning:</strong> This plugin <strong>has not been tested</strong> with your current version of WordPress.' ),
			array(
				'type'               => 'warning',
				'additional_classes' => array( 'notice-alt' ),
			)
		);
	} elseif ( ! $compatible_wp ) {
		$compatible_wp_notice_message = __( '<strong>Error:</strong> This plugin <strong>requires a newer version of WordPress</strong>.' );
		if ( current_user_can( 'update_core' ) ) {
			$compatible_wp_notice_message .= sprintf(
				/* translators: %s: URL to WordPress Updates screen. */
				' ' . __( '<a href="%s" target="_parent">Click here to update WordPress</a>.' ),
				esc_url( self_admin_url( 'update-core.php' ) )
			);
		}

		wp_admin_notice(
			$compatible_wp_notice_message,
			array(
				'type'               => 'error',
				'additional_classes' => array( 'notice-alt' ),
			)
		);
	}

	foreach ( (array) $api->sections as $section_name => $content ) {
		$content = links_add_base_url( $content, 'https://wordpress.org/plugins/' . $api->slug . '/' );
		$content = links_add_target( $content, '_blank' );

		$san_section = esc_attr( $section_name );

		$display = ( $section_name === $section ) ? 'block' : 'none';

		echo "\t<div id='section-{$san_section}' class='section' style='display: {$display};'>\n";
		echo $content;
		echo "\t</div>\n";
	}
	echo "</div>\n";
	echo "</div>\n";
	echo "</div>\n"; // #plugin-information-scrollable
	echo "<div id='$tab-footer'>\n";
	if ( ! empty( $api->download_link ) && ( current_user_can( 'install_plugins' ) || current_user_can( 'update_plugins' ) ) ) {
		$button = wp_get_plugin_action_button( $api->name, $api, $compatible_php, $compatible_wp );
		$button = str_replace( 'class="', 'class="right ', $button );

		if ( ! str_contains( $button, _x( 'Activate', 'plugin' ) ) ) {
			$button = str_replace( 'class="', 'id="plugin_install_from_iframe" class="', $button );
		}

		echo wp_kses_post( $button );
	}
	echo "</div>\n";

	wp_print_request_filesystem_credentials_modal();
	wp_print_admin_notice_templates();

	iframe_footer();
	exit;
}

/**
 * Gets the markup for the plugin install action button.
 *
 * @since 6.5.0
 *
 * @param string       $name           Plugin name.
 * @param array|object $data           {
 *     An array or object of plugin data. Can be retrieved from the API.
 *
 *     @type string   $slug             The plugin slug.
 *     @type string[] $requires_plugins An array of plugin dependency slugs.
 *     @type string   $version          The plugin's version string. Used when getting the install status.
 * }
 * @param bool         $compatible_php   The result of a PHP compatibility check.
 * @param bool         $compatible_wp    The result of a WP compatibility check.
 * @return string The markup for the dependency row button. An empty string if the user does not have capabilities.
 */
function wp_get_plugin_action_button( $name, $data, $compatible_php, $compatible_wp ) {
	$button           = '';
	$data             = (object) $data;
	$status           = install_plugin_install_status( $data );
	$requires_plugins = $data->requires_plugins ?? array();

	// Determine the status of plugin dependencies.
	$installed_plugins                   = get_plugins();
	$active_plugins                      = get_option( 'active_plugins', array() );
	$plugin_dependencies_count           = count( $requires_plugins );
	$installed_plugin_dependencies_count = 0;
	$active_plugin_dependencies_count    = 0;
	foreach ( $requires_plugins as $dependency ) {
		foreach ( array_keys( $installed_plugins ) as $installed_plugin_file ) {
			if ( str_contains( $installed_plugin_file, '/' ) && explode( '/', $installed_plugin_file )[0] === $dependency ) {
				++$installed_plugin_dependencies_count;
			}
		}

		foreach ( $active_plugins as $active_plugin_file ) {
			if ( str_contains( $active_plugin_file, '/' ) && explode( '/', $active_plugin_file )[0] === $dependency ) {
				++$active_plugin_dependencies_count;
			}
		}
	}
	$all_plugin_dependencies_installed = $installed_plugin_dependencies_count === $plugin_dependencies_count;
	$all_plugin_dependencies_active    = $active_plugin_dependencies_count === $plugin_dependencies_count;

	if ( current_user_can( 'install_plugins' ) || current_user_can( 'update_plugins' ) ) {
		switch ( $status['status'] ) {
			case 'install':
				if ( $status['url'] ) {
					if ( $compatible_php && $compatible_wp && $all_plugin_dependencies_installed && ! empty( $data->download_link ) ) {
						$button = sprintf(
							'<a class="install-now button" data-slug="%s" href="%s" aria-label="%s" data-name="%s" role="button">%s</a>',
							esc_attr( $data->slug ),
							esc_url( $status['url'] ),
							/* translators: %s: Plugin name and version. */
							esc_attr( sprintf( _x( 'Install %s now', 'plugin' ), $name ) ),
							esc_attr( $name ),
							_x( 'Install Now', 'plugin' )
						);
					} else {
						$button = sprintf(
							'<button type="button" class="install-now button button-disabled" disabled="disabled">%s</button>',
							_x( 'Install Now', 'plugin' )
						);
					}
				}
				break;

			case 'update_available':
				if ( $status['url'] ) {
					if ( $compatible_php && $compatible_wp ) {
						$button = sprintf(
							'<a class="update-now button aria-button-if-js" data-plugin="%s" data-slug="%s" href="%s" aria-label="%s" data-name="%s" role="button">%s</a>',
							esc_attr( $status['file'] ),
							esc_attr( $data->slug ),
							esc_url( $status['url'] ),
							/* translators: %s: Plugin name and version. */
							esc_attr( sprintf( _x( 'Update %s now', 'plugin' ), $name ) ),
							esc_attr( $name ),
							_x( 'Update Now', 'plugin' )
						);
					} else {
						$button = sprintf(
							'<button type="button" class="button button-disabled" disabled="disabled">%s</button>',
							_x( 'Update Now', 'plugin' )
						);
					}
				}
				break;

			case 'latest_installed':
			case 'newer_installed':
				if ( is_plugin_active( $status['file'] ) ) {
					$button = sprintf(
						'<button type="button" class="button button-disabled" disabled="disabled">%s</button>',
						_x( 'Active', 'plugin' )
					);
				} elseif ( current_user_can( 'activate_plugin', $status['file'] ) ) {
					if ( $compatible_php && $compatible_wp && $all_plugin_dependencies_active ) {
						$button_text = _x( 'Activate', 'plugin' );
						/* translators: %s: Plugin name. */
						$button_label = _x( 'Activate %s', 'plugin' );
						$activate_url = add_query_arg(
							array(
								'_wpnonce' => wp_create_nonce( 'activate-plugin_' . $status['file'] ),
								'action'   => 'activate',
								'plugin'   => $status['file'],
							),
							network_admin_url( 'plugins.php' )
						);

						if ( is_network_admin() ) {
							$button_text = _x( 'Network Activate', 'plugin' );
							/* translators: %s: Plugin name. */
							$button_label = _x( 'Network Activate %s', 'plugin' );
							$activate_url = add_query_arg( array( 'networkwide' => 1 ), $activate_url );
						}

						$button = sprintf(
							'<a href="%1$s" data-name="%2$s" data-slug="%3$s" data-plugin="%4$s" class="button button-primary activate-now" aria-label="%5$s" role="button">%6$s</a>',
							esc_url( $activate_url ),
							esc_attr( $name ),
							esc_attr( $data->slug ),
							esc_attr( $status['file'] ),
							esc_attr( sprintf( $button_label, $name ) ),
							$button_text
						);
					} else {
						$button = sprintf(
							'<button type="button" class="button button-disabled" disabled="disabled">%s</button>',
							is_network_admin() ? _x( 'Network Activate', 'plugin' ) : _x( 'Activate', 'plugin' )
						);
					}
				} else {
					$button = sprintf(
						'<button type="button" class="button button-disabled" disabled="disabled">%s</button>',
						_x( 'Installed', 'plugin' )
					);
				}
				break;
		}
	}

	return $button;
}
class-wp-automatic-updater.php000064400000170716151212616040012446 0ustar00<?php
/**
 * Upgrade API: WP_Automatic_Updater class
 *
 * @package WordPress
 * @subpackage Upgrader
 * @since 4.6.0
 */

/**
 * Core class used for handling automatic background updates.
 *
 * @since 3.7.0
 * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader.php.
 */
#[AllowDynamicProperties]
class WP_Automatic_Updater {

	/**
	 * Tracks update results during processing.
	 *
	 * @var array
	 */
	protected $update_results = array();

	/**
	 * Determines whether the entire automatic updater is disabled.
	 *
	 * @since 3.7.0
	 *
	 * @return bool True if the automatic updater is disabled, false otherwise.
	 */
	public function is_disabled() {
		// Background updates are disabled if you don't want file changes.
		if ( ! wp_is_file_mod_allowed( 'automatic_updater' ) ) {
			return true;
		}

		if ( wp_installing() ) {
			return true;
		}

		// More fine grained control can be done through the WP_AUTO_UPDATE_CORE constant and filters.
		$disabled = defined( 'AUTOMATIC_UPDATER_DISABLED' ) && AUTOMATIC_UPDATER_DISABLED;

		/**
		 * Filters whether to entirely disable background updates.
		 *
		 * There are more fine-grained filters and controls for selective disabling.
		 * This filter parallels the AUTOMATIC_UPDATER_DISABLED constant in name.
		 *
		 * This also disables update notification emails. That may change in the future.
		 *
		 * @since 3.7.0
		 *
		 * @param bool $disabled Whether the updater should be disabled.
		 */
		return apply_filters( 'automatic_updater_disabled', $disabled );
	}

	/**
	 * Checks whether access to a given directory is allowed.
	 *
	 * This is used when detecting version control checkouts. Takes into account
	 * the PHP `open_basedir` restrictions, so that WordPress does not try to access
	 * directories it is not allowed to.
	 *
	 * @since 6.2.0
	 *
	 * @param string $dir The directory to check.
	 * @return bool True if access to the directory is allowed, false otherwise.
	 */
	public function is_allowed_dir( $dir ) {
		if ( is_string( $dir ) ) {
			$dir = trim( $dir );
		}

		if ( ! is_string( $dir ) || '' === $dir ) {
			_doing_it_wrong(
				__METHOD__,
				sprintf(
					/* translators: %s: The "$dir" argument. */
					__( 'The "%s" argument must be a non-empty string.' ),
					'$dir'
				),
				'6.2.0'
			);

			return false;
		}

		$open_basedir = ini_get( 'open_basedir' );

		if ( empty( $open_basedir ) ) {
			return true;
		}

		$open_basedir_list = explode( PATH_SEPARATOR, $open_basedir );

		foreach ( $open_basedir_list as $basedir ) {
			if ( '' !== trim( $basedir ) && str_starts_with( $dir, $basedir ) ) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Checks for version control checkouts.
	 *
	 * Checks for Subversion, Git, Mercurial, and Bazaar. It recursively looks up the
	 * filesystem to the top of the drive, erring on the side of detecting a VCS
	 * checkout somewhere.
	 *
	 * ABSPATH is always checked in addition to whatever `$context` is (which may be the
	 * wp-content directory, for example). The underlying assumption is that if you are
	 * using version control *anywhere*, then you should be making decisions for
	 * how things get updated.
	 *
	 * @since 3.7.0
	 *
	 * @param string $context The filesystem path to check, in addition to ABSPATH.
	 * @return bool True if a VCS checkout was discovered at `$context` or ABSPATH,
	 *              or anywhere higher. False otherwise.
	 */
	public function is_vcs_checkout( $context ) {
		$context_dirs = array( untrailingslashit( $context ) );
		if ( ABSPATH !== $context ) {
			$context_dirs[] = untrailingslashit( ABSPATH );
		}

		$vcs_dirs   = array( '.svn', '.git', '.hg', '.bzr' );
		$check_dirs = array();

		foreach ( $context_dirs as $context_dir ) {
			// Walk up from $context_dir to the root.
			do {
				$check_dirs[] = $context_dir;

				// Once we've hit '/' or 'C:\', we need to stop. dirname will keep returning the input here.
				if ( dirname( $context_dir ) === $context_dir ) {
					break;
				}

				// Continue one level at a time.
			} while ( $context_dir = dirname( $context_dir ) );
		}

		$check_dirs = array_unique( $check_dirs );
		$checkout   = false;

		// Search all directories we've found for evidence of version control.
		foreach ( $vcs_dirs as $vcs_dir ) {
			foreach ( $check_dirs as $check_dir ) {
				if ( ! $this->is_allowed_dir( $check_dir ) ) {
					continue;
				}

				$checkout = is_dir( rtrim( $check_dir, '\\/' ) . "/$vcs_dir" );
				if ( $checkout ) {
					break 2;
				}
			}
		}

		/**
		 * Filters whether the automatic updater should consider a filesystem
		 * location to be potentially managed by a version control system.
		 *
		 * @since 3.7.0
		 *
		 * @param bool $checkout  Whether a VCS checkout was discovered at `$context`
		 *                        or ABSPATH, or anywhere higher.
		 * @param string $context The filesystem context (a path) against which
		 *                        filesystem status should be checked.
		 */
		return apply_filters( 'automatic_updates_is_vcs_checkout', $checkout, $context );
	}

	/**
	 * Tests to see if we can and should update a specific item.
	 *
	 * @since 3.7.0
	 *
	 * @global wpdb $wpdb WordPress database abstraction object.
	 *
	 * @param string $type    The type of update being checked: 'core', 'theme',
	 *                        'plugin', 'translation'.
	 * @param object $item    The update offer.
	 * @param string $context The filesystem context (a path) against which filesystem
	 *                        access and status should be checked.
	 * @return bool True if the item should be updated, false otherwise.
	 */
	public function should_update( $type, $item, $context ) {
		// Used to see if WP_Filesystem is set up to allow unattended updates.
		$skin = new Automatic_Upgrader_Skin();

		if ( $this->is_disabled() ) {
			return false;
		}

		// Only relax the filesystem checks when the update doesn't include new files.
		$allow_relaxed_file_ownership = false;
		if ( 'core' === $type && isset( $item->new_files ) && ! $item->new_files ) {
			$allow_relaxed_file_ownership = true;
		}

		// If we can't do an auto core update, we may still be able to email the user.
		if ( ! $skin->request_filesystem_credentials( false, $context, $allow_relaxed_file_ownership )
			|| $this->is_vcs_checkout( $context )
		) {
			if ( 'core' === $type ) {
				$this->send_core_update_notification_email( $item );
			}
			return false;
		}

		// Next up, is this an item we can update?
		if ( 'core' === $type ) {
			$update = Core_Upgrader::should_update_to_version( $item->current );
		} elseif ( 'plugin' === $type || 'theme' === $type ) {
			$update = ! empty( $item->autoupdate );

			if ( ! $update && wp_is_auto_update_enabled_for_type( $type ) ) {
				// Check if the site admin has enabled auto-updates by default for the specific item.
				$auto_updates = (array) get_site_option( "auto_update_{$type}s", array() );
				$update       = in_array( $item->{$type}, $auto_updates, true );
			}
		} else {
			$update = ! empty( $item->autoupdate );
		}

		// If the `disable_autoupdate` flag is set, override any user-choice, but allow filters.
		if ( ! empty( $item->disable_autoupdate ) ) {
			$update = false;
		}

		/**
		 * Filters whether to automatically update core, a plugin, a theme, or a language.
		 *
		 * The dynamic portion of the hook name, `$type`, refers to the type of update
		 * being checked.
		 *
		 * Possible hook names include:
		 *
		 *  - `auto_update_core`
		 *  - `auto_update_plugin`
		 *  - `auto_update_theme`
		 *  - `auto_update_translation`
		 *
		 * Since WordPress 3.7, minor and development versions of core, and translations have
		 * been auto-updated by default. New installs on WordPress 5.6 or higher will also
		 * auto-update major versions by default. Starting in 5.6, older sites can opt-in to
		 * major version auto-updates, and auto-updates for plugins and themes.
		 *
		 * See the {@see 'allow_dev_auto_core_updates'}, {@see 'allow_minor_auto_core_updates'},
		 * and {@see 'allow_major_auto_core_updates'} filters for a more straightforward way to
		 * adjust core updates.
		 *
		 * @since 3.7.0
		 * @since 5.5.0 The `$update` parameter accepts the value of null.
		 *
		 * @param bool|null $update Whether to update. The value of null is internally used
		 *                          to detect whether nothing has hooked into this filter.
		 * @param object    $item   The update offer.
		 */
		$update = apply_filters( "auto_update_{$type}", $update, $item );

		if ( ! $update ) {
			if ( 'core' === $type ) {
				$this->send_core_update_notification_email( $item );
			}
			return false;
		}

		// If it's a core update, are we actually compatible with its requirements?
		if ( 'core' === $type ) {
			global $wpdb;

			$php_compat = version_compare( PHP_VERSION, $item->php_version, '>=' );
			if ( file_exists( WP_CONTENT_DIR . '/db.php' ) && empty( $wpdb->is_mysql ) ) {
				$mysql_compat = true;
			} else {
				$mysql_compat = version_compare( $wpdb->db_version(), $item->mysql_version, '>=' );
			}

			if ( ! $php_compat || ! $mysql_compat ) {
				return false;
			}
		}

		// If updating a plugin or theme, ensure the minimum PHP version requirements are satisfied.
		if ( in_array( $type, array( 'plugin', 'theme' ), true ) ) {
			if ( ! empty( $item->requires_php ) && version_compare( PHP_VERSION, $item->requires_php, '<' ) ) {
				return false;
			}
		}

		return true;
	}

	/**
	 * Notifies an administrator of a core update.
	 *
	 * @since 3.7.0
	 *
	 * @param object $item The update offer.
	 * @return bool True if the site administrator is notified of a core update,
	 *              false otherwise.
	 */
	protected function send_core_update_notification_email( $item ) {
		$notified = get_site_option( 'auto_core_update_notified' );

		// Don't notify if we've already notified the same email address of the same version.
		if ( $notified
			&& get_site_option( 'admin_email' ) === $notified['email']
			&& $notified['version'] === $item->current
		) {
			return false;
		}

		// See if we need to notify users of a core update.
		$notify = ! empty( $item->notify_email );

		/**
		 * Filters whether to notify the site administrator of a new core update.
		 *
		 * By default, administrators are notified when the update offer received
		 * from WordPress.org sets a particular flag. This allows some discretion
		 * in if and when to notify.
		 *
		 * This filter is only evaluated once per release. If the same email address
		 * was already notified of the same new version, WordPress won't repeatedly
		 * email the administrator.
		 *
		 * This filter is also used on about.php to check if a plugin has disabled
		 * these notifications.
		 *
		 * @since 3.7.0
		 *
		 * @param bool   $notify Whether the site administrator is notified.
		 * @param object $item   The update offer.
		 */
		if ( ! apply_filters( 'send_core_update_notification_email', $notify, $item ) ) {
			return false;
		}

		$this->send_email( 'manual', $item );
		return true;
	}

	/**
	 * Updates an item, if appropriate.
	 *
	 * @since 3.7.0
	 *
	 * @param string $type The type of update being checked: 'core', 'theme', 'plugin', 'translation'.
	 * @param object $item The update offer.
	 * @return null|WP_Error
	 */
	public function update( $type, $item ) {
		$skin = new Automatic_Upgrader_Skin();

		switch ( $type ) {
			case 'core':
				// The Core upgrader doesn't use the Upgrader's skin during the actual main part of the upgrade, instead, firing a filter.
				add_filter( 'update_feedback', array( $skin, 'feedback' ) );
				$upgrader = new Core_Upgrader( $skin );
				$context  = ABSPATH;
				break;
			case 'plugin':
				$upgrader = new Plugin_Upgrader( $skin );
				$context  = WP_PLUGIN_DIR; // We don't support custom Plugin directories, or updates for WPMU_PLUGIN_DIR.
				break;
			case 'theme':
				$upgrader = new Theme_Upgrader( $skin );
				$context  = get_theme_root( $item->theme );
				break;
			case 'translation':
				$upgrader = new Language_Pack_Upgrader( $skin );
				$context  = WP_CONTENT_DIR; // WP_LANG_DIR;
				break;
		}

		// Determine whether we can and should perform this update.
		if ( ! $this->should_update( $type, $item, $context ) ) {
			return false;
		}

		/**
		 * Fires immediately prior to an auto-update.
		 *
		 * @since 4.4.0
		 *
		 * @param string $type    The type of update being checked: 'core', 'theme', 'plugin', or 'translation'.
		 * @param object $item    The update offer.
		 * @param string $context The filesystem context (a path) against which filesystem access and status
		 *                        should be checked.
		 */
		do_action( 'pre_auto_update', $type, $item, $context );

		$upgrader_item = $item;
		switch ( $type ) {
			case 'core':
				/* translators: %s: WordPress version. */
				$skin->feedback( __( 'Updating to WordPress %s' ), $item->version );
				/* translators: %s: WordPress version. */
				$item_name = sprintf( __( 'WordPress %s' ), $item->version );
				break;
			case 'theme':
				$upgrader_item = $item->theme;
				$theme         = wp_get_theme( $upgrader_item );
				$item_name     = $theme->get( 'Name' );
				// Add the current version so that it can be reported in the notification email.
				$item->current_version = $theme->get( 'Version' );
				if ( empty( $item->current_version ) ) {
					$item->current_version = false;
				}
				/* translators: %s: Theme name. */
				$skin->feedback( __( 'Updating theme: %s' ), $item_name );
				break;
			case 'plugin':
				$upgrader_item = $item->plugin;
				$plugin_data   = get_plugin_data( $context . '/' . $upgrader_item );
				$item_name     = $plugin_data['Name'];
				// Add the current version so that it can be reported in the notification email.
				$item->current_version = $plugin_data['Version'];
				if ( empty( $item->current_version ) ) {
					$item->current_version = false;
				}
				/* translators: %s: Plugin name. */
				$skin->feedback( __( 'Updating plugin: %s' ), $item_name );
				break;
			case 'translation':
				$language_item_name = $upgrader->get_name_for_update( $item );
				/* translators: %s: Project name (plugin, theme, or WordPress). */
				$item_name = sprintf( __( 'Translations for %s' ), $language_item_name );
				/* translators: 1: Project name (plugin, theme, or WordPress), 2: Language. */
				$skin->feedback( sprintf( __( 'Updating translations for %1$s (%2$s)&#8230;' ), $language_item_name, $item->language ) );
				break;
		}

		$allow_relaxed_file_ownership = false;
		if ( 'core' === $type && isset( $item->new_files ) && ! $item->new_files ) {
			$allow_relaxed_file_ownership = true;
		}

		$is_debug = WP_DEBUG && WP_DEBUG_LOG;
		if ( 'plugin' === $type ) {
			$was_active = is_plugin_active( $upgrader_item );
			if ( $is_debug ) {
				error_log( '    Upgrading plugin ' . var_export( $item->slug, true ) . '...' );
			}
		}

		if ( 'theme' === $type && $is_debug ) {
			error_log( '    Upgrading theme ' . var_export( $item->theme, true ) . '...' );
		}

		/*
		 * Enable maintenance mode before upgrading the plugin or theme.
		 *
		 * This avoids potential non-fatal errors being detected
		 * while scraping for a fatal error if some files are still
		 * being moved.
		 *
		 * While these checks are intended only for plugins,
		 * maintenance mode is enabled for all upgrade types as any
		 * update could contain an error or warning, which could cause
		 * the scrape to miss a fatal error in the plugin update.
		 */
		if ( 'translation' !== $type ) {
			$upgrader->maintenance_mode( true );
		}

		// Boom, this site's about to get a whole new splash of paint!
		$upgrade_result = $upgrader->upgrade(
			$upgrader_item,
			array(
				'clear_update_cache'           => false,
				// Always use partial builds if possible for core updates.
				'pre_check_md5'                => false,
				// Only available for core updates.
				'attempt_rollback'             => true,
				// Allow relaxed file ownership in some scenarios.
				'allow_relaxed_file_ownership' => $allow_relaxed_file_ownership,
			)
		);

		/*
		 * After WP_Upgrader::upgrade() completes, maintenance mode is disabled.
		 *
		 * Re-enable maintenance mode while attempting to detect fatal errors
		 * and potentially rolling back.
		 *
		 * This avoids errors if the site is visited while fatal errors exist
		 * or while files are still being moved.
		 */
		if ( 'translation' !== $type ) {
			$upgrader->maintenance_mode( true );
		}

		// If the filesystem is unavailable, false is returned.
		if ( false === $upgrade_result ) {
			$upgrade_result = new WP_Error( 'fs_unavailable', __( 'Could not access filesystem.' ) );
		}

		if ( 'core' === $type ) {
			if ( is_wp_error( $upgrade_result )
				&& ( 'up_to_date' === $upgrade_result->get_error_code()
					|| 'locked' === $upgrade_result->get_error_code() )
			) {
				// Allow visitors to browse the site again.
				$upgrader->maintenance_mode( false );

				/*
				 * These aren't actual errors, treat it as a skipped-update instead
				 * to avoid triggering the post-core update failure routines.
				 */
				return false;
			}

			// Core doesn't output this, so let's append it, so we don't get confused.
			if ( is_wp_error( $upgrade_result ) ) {
				$upgrade_result->add( 'installation_failed', __( 'Installation failed.' ) );
				$skin->error( $upgrade_result );
			} else {
				$skin->feedback( __( 'WordPress updated successfully.' ) );
			}
		}

		$is_debug = WP_DEBUG && WP_DEBUG_LOG;

		if ( 'theme' === $type && $is_debug ) {
			error_log( '    Theme ' . var_export( $item->theme, true ) . ' has been upgraded.' );
		}

		if ( 'plugin' === $type ) {
			if ( $is_debug ) {
				error_log( '    Plugin ' . var_export( $item->slug, true ) . ' has been upgraded.' );
				if ( is_plugin_inactive( $upgrader_item ) ) {
					error_log( '    ' . var_export( $upgrader_item, true ) . ' is inactive and will not be checked for fatal errors.' );
				}
			}

			if ( $was_active && ! is_wp_error( $upgrade_result ) ) {

				/*
				 * The usual time limit is five minutes. However, as a loopback request
				 * is about to be performed, increase the time limit to account for this.
				 */
				if ( function_exists( 'set_time_limit' ) ) {
					set_time_limit( 10 * MINUTE_IN_SECONDS );
				}

				/*
				 * Avoids a race condition when there are 2 sequential plugins that have
				 * fatal errors. It seems a slight delay is required for the loopback to
				 * use the updated plugin code in the request. This can cause the second
				 * plugin's fatal error checking to be inaccurate, and may also affect
				 * subsequent plugin checks.
				 */
				sleep( 2 );

				if ( $this->has_fatal_error() ) {
					$upgrade_result = new WP_Error();
					$temp_backup    = array(
						array(
							'dir'  => 'plugins',
							'slug' => $item->slug,
							'src'  => WP_PLUGIN_DIR,
						),
					);

					$backup_restored = $upgrader->restore_temp_backup( $temp_backup );
					if ( is_wp_error( $backup_restored ) ) {
						$upgrade_result->add(
							'plugin_update_fatal_error_rollback_failed',
							sprintf(
								/* translators: %s: The plugin's slug. */
								__( "The update for '%s' contained a fatal error. The previously installed version could not be restored." ),
								$item->slug
							)
						);

						$upgrade_result->merge_from( $backup_restored );
					} else {
						$upgrade_result->add(
							'plugin_update_fatal_error_rollback_successful',
							sprintf(
								/* translators: %s: The plugin's slug. */
								__( "The update for '%s' contained a fatal error. The previously installed version has been restored." ),
								$item->slug
							)
						);

						$backup_deleted = $upgrader->delete_temp_backup( $temp_backup );
						if ( is_wp_error( $backup_deleted ) ) {
							$upgrade_result->merge_from( $backup_deleted );
						}
					}

					/*
					 * Should emails not be working, log the message(s) so that
					 * the log file contains context for the fatal error,
					 * and whether a rollback was performed.
					 *
					 * `trigger_error()` is not used as it outputs a stack trace
					 * to this location rather than to the fatal error, which will
					 * appear above this entry in the log file.
					 */
					if ( $is_debug ) {
						error_log( '    ' . implode( "\n", $upgrade_result->get_error_messages() ) );
					}
				} elseif ( $is_debug ) {
					error_log( '    The update for ' . var_export( $item->slug, true ) . ' has no fatal errors.' );
				}
			}
		}

		// All processes are complete. Allow visitors to browse the site again.
		if ( 'translation' !== $type ) {
			$upgrader->maintenance_mode( false );
		}

		$this->update_results[ $type ][] = (object) array(
			'item'     => $item,
			'result'   => $upgrade_result,
			'name'     => $item_name,
			'messages' => $skin->get_upgrade_messages(),
		);

		return $upgrade_result;
	}

	/**
	 * Kicks off the background update process, looping through all pending updates.
	 *
	 * @since 3.7.0
	 */
	public function run() {
		if ( $this->is_disabled() ) {
			return;
		}

		if ( ! is_main_network() || ! is_main_site() ) {
			return;
		}

		if ( ! WP_Upgrader::create_lock( 'auto_updater' ) ) {
			return;
		}

		$is_debug = WP_DEBUG && WP_DEBUG_LOG;

		if ( $is_debug ) {
			error_log( 'Automatic updates starting...' );
		}

		// Don't automatically run these things, as we'll handle it ourselves.
		remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
		remove_action( 'upgrader_process_complete', 'wp_version_check' );
		remove_action( 'upgrader_process_complete', 'wp_update_plugins' );
		remove_action( 'upgrader_process_complete', 'wp_update_themes' );

		// Next, plugins.
		wp_update_plugins(); // Check for plugin updates.
		$plugin_updates = get_site_transient( 'update_plugins' );
		if ( $plugin_updates && ! empty( $plugin_updates->response ) ) {
			if ( $is_debug ) {
				error_log( '  Automatic plugin updates starting...' );
			}

			foreach ( $plugin_updates->response as $plugin ) {
				$this->update( 'plugin', $plugin );
			}

			// Force refresh of plugin update information.
			wp_clean_plugins_cache();

			if ( $is_debug ) {
				error_log( '  Automatic plugin updates complete.' );
			}
		}

		// Next, those themes we all love.
		wp_update_themes();  // Check for theme updates.
		$theme_updates = get_site_transient( 'update_themes' );
		if ( $theme_updates && ! empty( $theme_updates->response ) ) {
			if ( $is_debug ) {
				error_log( '  Automatic theme updates starting...' );
			}

			foreach ( $theme_updates->response as $theme ) {
				$this->update( 'theme', (object) $theme );
			}
			// Force refresh of theme update information.
			wp_clean_themes_cache();

			if ( $is_debug ) {
				error_log( '  Automatic theme updates complete.' );
			}
		}

		if ( $is_debug ) {
			error_log( 'Automatic updates complete.' );
		}

		// Next, process any core update.
		wp_version_check(); // Check for core updates.
		$core_update = find_core_auto_update();

		if ( $core_update ) {
			$this->update( 'core', $core_update );
		}

		/*
		 * Clean up, and check for any pending translations.
		 * (Core_Upgrader checks for core updates.)
		 */
		$theme_stats = array();
		if ( isset( $this->update_results['theme'] ) ) {
			foreach ( $this->update_results['theme'] as $upgrade ) {
				$theme_stats[ $upgrade->item->theme ] = ( true === $upgrade->result );
			}
		}
		wp_update_themes( $theme_stats ); // Check for theme updates.

		$plugin_stats = array();
		if ( isset( $this->update_results['plugin'] ) ) {
			foreach ( $this->update_results['plugin'] as $upgrade ) {
				$plugin_stats[ $upgrade->item->plugin ] = ( true === $upgrade->result );
			}
		}
		wp_update_plugins( $plugin_stats ); // Check for plugin updates.

		// Finally, process any new translations.
		$language_updates = wp_get_translation_updates();
		if ( $language_updates ) {
			foreach ( $language_updates as $update ) {
				$this->update( 'translation', $update );
			}

			// Clear existing caches.
			wp_clean_update_cache();

			wp_version_check();  // Check for core updates.
			wp_update_themes();  // Check for theme updates.
			wp_update_plugins(); // Check for plugin updates.
		}

		// Send debugging email to admin for all development installations.
		if ( ! empty( $this->update_results ) ) {
			$development_version = str_contains( wp_get_wp_version(), '-' );

			/**
			 * Filters whether to send a debugging email for each automatic background update.
			 *
			 * @since 3.7.0
			 *
			 * @param bool $development_version By default, emails are sent if the
			 *                                  install is a development version.
			 *                                  Return false to avoid the email.
			 */
			if ( apply_filters( 'automatic_updates_send_debug_email', $development_version ) ) {
				$this->send_debug_email();
			}

			if ( ! empty( $this->update_results['core'] ) ) {
				$this->after_core_update( $this->update_results['core'][0] );
			} elseif ( ! empty( $this->update_results['plugin'] ) || ! empty( $this->update_results['theme'] ) ) {
				$this->after_plugin_theme_update( $this->update_results );
			}

			/**
			 * Fires after all automatic updates have run.
			 *
			 * @since 3.8.0
			 *
			 * @param array $update_results The results of all attempted updates.
			 */
			do_action( 'automatic_updates_complete', $this->update_results );
		}

		WP_Upgrader::release_lock( 'auto_updater' );
	}

	/**
	 * Checks whether to send an email and avoid processing future updates after
	 * attempting a core update.
	 *
	 * @since 3.7.0
	 *
	 * @param object $update_result The result of the core update. Includes the update offer and result.
	 */
	protected function after_core_update( $update_result ) {
		$wp_version = wp_get_wp_version();

		$core_update = $update_result->item;
		$result      = $update_result->result;

		if ( ! is_wp_error( $result ) ) {
			$this->send_email( 'success', $core_update );
			return;
		}

		$error_code = $result->get_error_code();

		/*
		 * Any of these WP_Error codes are critical failures, as in they occurred after we started to copy core files.
		 * We should not try to perform a background update again until there is a successful one-click update performed by the user.
		 */
		$critical = false;
		if ( 'disk_full' === $error_code || str_contains( $error_code, '__copy_dir' ) ) {
			$critical = true;
		} elseif ( 'rollback_was_required' === $error_code && is_wp_error( $result->get_error_data()->rollback ) ) {
			// A rollback is only critical if it failed too.
			$critical        = true;
			$rollback_result = $result->get_error_data()->rollback;
		} elseif ( str_contains( $error_code, 'do_rollback' ) ) {
			$critical = true;
		}

		if ( $critical ) {
			$critical_data = array(
				'attempted'  => $core_update->current,
				'current'    => $wp_version,
				'error_code' => $error_code,
				'error_data' => $result->get_error_data(),
				'timestamp'  => time(),
				'critical'   => true,
			);
			if ( isset( $rollback_result ) ) {
				$critical_data['rollback_code'] = $rollback_result->get_error_code();
				$critical_data['rollback_data'] = $rollback_result->get_error_data();
			}
			update_site_option( 'auto_core_update_failed', $critical_data );
			$this->send_email( 'critical', $core_update, $result );
			return;
		}

		/*
		 * Any other WP_Error code (like download_failed or files_not_writable) occurs before
		 * we tried to copy over core files. Thus, the failures are early and graceful.
		 *
		 * We should avoid trying to perform a background update again for the same version.
		 * But we can try again if another version is released.
		 *
		 * For certain 'transient' failures, like download_failed, we should allow retries.
		 * In fact, let's schedule a special update for an hour from now. (It's possible
		 * the issue could actually be on WordPress.org's side.) If that one fails, then email.
		 */
		$send               = true;
		$transient_failures = array( 'incompatible_archive', 'download_failed', 'insane_distro', 'locked' );
		if ( in_array( $error_code, $transient_failures, true ) && ! get_site_option( 'auto_core_update_failed' ) ) {
			wp_schedule_single_event( time() + HOUR_IN_SECONDS, 'wp_maybe_auto_update' );
			$send = false;
		}

		$notified = get_site_option( 'auto_core_update_notified' );

		// Don't notify if we've already notified the same email address of the same version of the same notification type.
		if ( $notified
			&& 'fail' === $notified['type']
			&& get_site_option( 'admin_email' ) === $notified['email']
			&& $notified['version'] === $core_update->current
		) {
			$send = false;
		}

		update_site_option(
			'auto_core_update_failed',
			array(
				'attempted'  => $core_update->current,
				'current'    => $wp_version,
				'error_code' => $error_code,
				'error_data' => $result->get_error_data(),
				'timestamp'  => time(),
				'retry'      => in_array( $error_code, $transient_failures, true ),
			)
		);

		if ( $send ) {
			$this->send_email( 'fail', $core_update, $result );
		}
	}

	/**
	 * Sends an email upon the completion or failure of a background core update.
	 *
	 * @since 3.7.0
	 *
	 * @param string $type        The type of email to send. Can be one of 'success', 'fail', 'manual', 'critical'.
	 * @param object $core_update The update offer that was attempted.
	 * @param mixed  $result      Optional. The result for the core update. Can be WP_Error.
	 */
	protected function send_email( $type, $core_update, $result = null ) {
		update_site_option(
			'auto_core_update_notified',
			array(
				'type'      => $type,
				'email'     => get_site_option( 'admin_email' ),
				'version'   => $core_update->current,
				'timestamp' => time(),
			)
		);

		$next_user_core_update = get_preferred_from_update_core();

		// If the update transient is empty, use the update we just performed.
		if ( ! $next_user_core_update ) {
			$next_user_core_update = $core_update;
		}

		if ( 'upgrade' === $next_user_core_update->response
			&& version_compare( $next_user_core_update->version, $core_update->version, '>' )
		) {
			$newer_version_available = true;
		} else {
			$newer_version_available = false;
		}

		/**
		 * Filters whether to send an email following an automatic background core update.
		 *
		 * @since 3.7.0
		 *
		 * @param bool   $send        Whether to send the email. Default true.
		 * @param string $type        The type of email to send. Can be one of
		 *                            'success', 'fail', 'critical'.
		 * @param object $core_update The update offer that was attempted.
		 * @param mixed  $result      The result for the core update. Can be WP_Error.
		 */
		if ( 'manual' !== $type && ! apply_filters( 'auto_core_update_send_email', true, $type, $core_update, $result ) ) {
			return;
		}

		$admin_user = get_user_by( 'email', get_site_option( 'admin_email' ) );

		if ( $admin_user ) {
			$switched_locale = switch_to_user_locale( $admin_user->ID );
		} else {
			$switched_locale = switch_to_locale( get_locale() );
		}

		switch ( $type ) {
			case 'success': // We updated.
				/* translators: Site updated notification email subject. 1: Site title, 2: WordPress version. */
				$subject = __( '[%1$s] Your site has updated to WordPress %2$s' );
				break;

			case 'fail':   // We tried to update but couldn't.
			case 'manual': // We can't update (and made no attempt).
				/* translators: Update available notification email subject. 1: Site title, 2: WordPress version. */
				$subject = __( '[%1$s] WordPress %2$s is available. Please update!' );
				break;

			case 'critical': // We tried to update, started to copy files, then things went wrong.
				/* translators: Site down notification email subject. 1: Site title. */
				$subject = __( '[%1$s] URGENT: Your site may be down due to a failed update' );
				break;

			default:
				return;
		}

		// If the auto-update is not to the latest version, say that the current version of WP is available instead.
		$version = 'success' === $type ? $core_update->current : $next_user_core_update->current;
		$subject = sprintf( $subject, wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ), $version );

		$body = '';

		switch ( $type ) {
			case 'success':
				$body .= sprintf(
					/* translators: 1: Home URL, 2: WordPress version. */
					__( 'Howdy! Your site at %1$s has been updated automatically to WordPress %2$s.' ),
					home_url(),
					$core_update->current
				);
				$body .= "\n\n";
				if ( ! $newer_version_available ) {
					$body .= __( 'No further action is needed on your part.' ) . ' ';
				}

				// Can only reference the About screen if their update was successful.
				list( $about_version ) = explode( '-', $core_update->current, 2 );
				/* translators: %s: WordPress version. */
				$body .= sprintf( __( 'For more on version %s, see the About WordPress screen:' ), $about_version );
				$body .= "\n" . admin_url( 'about.php' );

				if ( $newer_version_available ) {
					/* translators: %s: WordPress latest version. */
					$body .= "\n\n" . sprintf( __( 'WordPress %s is also now available.' ), $next_user_core_update->current ) . ' ';
					$body .= __( 'Updating is easy and only takes a few moments:' );
					$body .= "\n" . network_admin_url( 'update-core.php' );
				}

				break;

			case 'fail':
			case 'manual':
				$body .= sprintf(
					/* translators: 1: Home URL, 2: WordPress version. */
					__( 'Please update your site at %1$s to WordPress %2$s.' ),
					home_url(),
					$next_user_core_update->current
				);

				$body .= "\n\n";

				/*
				 * Don't show this message if there is a newer version available.
				 * Potential for confusion, and also not useful for them to know at this point.
				 */
				if ( 'fail' === $type && ! $newer_version_available ) {
					$body .= __( 'An attempt was made, but your site could not be updated automatically.' ) . ' ';
				}

				$body .= __( 'Updating is easy and only takes a few moments:' );
				$body .= "\n" . network_admin_url( 'update-core.php' );
				break;

			case 'critical':
				if ( $newer_version_available ) {
					$body .= sprintf(
						/* translators: 1: Home URL, 2: WordPress version. */
						__( 'Your site at %1$s experienced a critical failure while trying to update WordPress to version %2$s.' ),
						home_url(),
						$core_update->current
					);
				} else {
					$body .= sprintf(
						/* translators: 1: Home URL, 2: WordPress latest version. */
						__( 'Your site at %1$s experienced a critical failure while trying to update to the latest version of WordPress, %2$s.' ),
						home_url(),
						$core_update->current
					);
				}

				$body .= "\n\n" . __( "This means your site may be offline or broken. Don't panic; this can be fixed." );

				$body .= "\n\n" . __( "Please check out your site now. It's possible that everything is working. If it says you need to update, you should do so:" );
				$body .= "\n" . network_admin_url( 'update-core.php' );
				break;
		}

		$critical_support = 'critical' === $type && ! empty( $core_update->support_email );
		if ( $critical_support ) {
			// Support offer if available.
			$body .= "\n\n" . sprintf(
				/* translators: %s: Support email address. */
				__( 'The WordPress team is willing to help you. Forward this email to %s and the team will work with you to make sure your site is working.' ),
				$core_update->support_email
			);
		} else {
			// Add a note about the support forums.
			$body .= "\n\n" . __( 'If you experience any issues or need support, the volunteers in the WordPress.org support forums may be able to help.' );
			$body .= "\n" . __( 'https://wordpress.org/support/forums/' );
		}

		// Updates are important!
		if ( 'success' !== $type || $newer_version_available ) {
			$body .= "\n\n" . __( 'Keeping your site updated is important for security. It also makes the internet a safer place for you and your readers.' );
		}

		if ( $critical_support ) {
			$body .= ' ' . __( "Reach out to WordPress Core developers to ensure you'll never have this problem again." );
		}

		// If things are successful and we're now on the latest, mention plugins and themes if any are out of date.
		if ( 'success' === $type && ! $newer_version_available && ( get_plugin_updates() || get_theme_updates() ) ) {
			$body .= "\n\n" . __( 'You also have some plugins or themes with updates available. Update them now:' );
			$body .= "\n" . network_admin_url();
		}

		$body .= "\n\n" . __( 'The WordPress Team' ) . "\n";

		if ( 'critical' === $type && is_wp_error( $result ) ) {
			$body .= "\n***\n\n";
			/* translators: %s: WordPress version. */
			$body .= sprintf( __( 'Your site was running version %s.' ), get_bloginfo( 'version' ) );
			$body .= ' ' . __( 'Some data that describes the error your site encountered has been put together.' );
			$body .= ' ' . __( 'Your hosting company, support forum volunteers, or a friendly developer may be able to use this information to help you:' );

			/*
			 * If we had a rollback and we're still critical, then the rollback failed too.
			 * Loop through all errors (the main WP_Error, the update result, the rollback result) for code, data, etc.
			 */
			if ( 'rollback_was_required' === $result->get_error_code() ) {
				$errors = array( $result, $result->get_error_data()->update, $result->get_error_data()->rollback );
			} else {
				$errors = array( $result );
			}

			foreach ( $errors as $error ) {
				if ( ! is_wp_error( $error ) ) {
					continue;
				}

				$error_code = $error->get_error_code();
				/* translators: %s: Error code. */
				$body .= "\n\n" . sprintf( __( 'Error code: %s' ), $error_code );

				if ( 'rollback_was_required' === $error_code ) {
					continue;
				}

				if ( $error->get_error_message() ) {
					$body .= "\n" . $error->get_error_message();
				}

				$error_data = $error->get_error_data();
				if ( $error_data ) {
					$body .= "\n" . implode( ', ', (array) $error_data );
				}
			}

			$body .= "\n";
		}

		$to      = get_site_option( 'admin_email' );
		$headers = '';

		$email = compact( 'to', 'subject', 'body', 'headers' );

		/**
		 * Filters the email sent following an automatic background core update.
		 *
		 * @since 3.7.0
		 *
		 * @param array $email {
		 *     Array of email arguments that will be passed to wp_mail().
		 *
		 *     @type string $to      The email recipient. An array of emails
		 *                            can be returned, as handled by wp_mail().
		 *     @type string $subject The email's subject.
		 *     @type string $body    The email message body.
		 *     @type string $headers Any email headers, defaults to no headers.
		 * }
		 * @param string $type        The type of email being sent. Can be one of
		 *                            'success', 'fail', 'manual', 'critical'.
		 * @param object $core_update The update offer that was attempted.
		 * @param mixed  $result      The result for the core update. Can be WP_Error.
		 */
		$email = apply_filters( 'auto_core_update_email', $email, $type, $core_update, $result );

		wp_mail( $email['to'], wp_specialchars_decode( $email['subject'] ), $email['body'], $email['headers'] );

		if ( $switched_locale ) {
			restore_previous_locale();
		}
	}

	/**
	 * Checks whether an email should be sent after attempting plugin or theme updates.
	 *
	 * @since 5.5.0
	 *
	 * @param array $update_results The results of update tasks.
	 */
	protected function after_plugin_theme_update( $update_results ) {
		$successful_updates = array();
		$failed_updates     = array();

		if ( ! empty( $update_results['plugin'] ) ) {
			/**
			 * Filters whether to send an email following an automatic background plugin update.
			 *
			 * @since 5.5.0
			 * @since 5.5.1 Added the `$update_results` parameter.
			 *
			 * @param bool  $enabled        True if plugin update notifications are enabled, false otherwise.
			 * @param array $update_results The results of plugins update tasks.
			 */
			$notifications_enabled = apply_filters( 'auto_plugin_update_send_email', true, $update_results['plugin'] );

			if ( $notifications_enabled ) {
				foreach ( $update_results['plugin'] as $update_result ) {
					if ( true === $update_result->result ) {
						$successful_updates['plugin'][] = $update_result;
					} else {
						$failed_updates['plugin'][] = $update_result;
					}
				}
			}
		}

		if ( ! empty( $update_results['theme'] ) ) {
			/**
			 * Filters whether to send an email following an automatic background theme update.
			 *
			 * @since 5.5.0
			 * @since 5.5.1 Added the `$update_results` parameter.
			 *
			 * @param bool  $enabled        True if theme update notifications are enabled, false otherwise.
			 * @param array $update_results The results of theme update tasks.
			 */
			$notifications_enabled = apply_filters( 'auto_theme_update_send_email', true, $update_results['theme'] );

			if ( $notifications_enabled ) {
				foreach ( $update_results['theme'] as $update_result ) {
					if ( true === $update_result->result ) {
						$successful_updates['theme'][] = $update_result;
					} else {
						$failed_updates['theme'][] = $update_result;
					}
				}
			}
		}

		if ( empty( $successful_updates ) && empty( $failed_updates ) ) {
			return;
		}

		if ( empty( $failed_updates ) ) {
			$this->send_plugin_theme_email( 'success', $successful_updates, $failed_updates );
		} elseif ( empty( $successful_updates ) ) {
			$this->send_plugin_theme_email( 'fail', $successful_updates, $failed_updates );
		} else {
			$this->send_plugin_theme_email( 'mixed', $successful_updates, $failed_updates );
		}
	}

	/**
	 * Sends an email upon the completion or failure of a plugin or theme background update.
	 *
	 * @since 5.5.0
	 *
	 * @param string $type               The type of email to send. Can be one of 'success', 'fail', 'mixed'.
	 * @param array  $successful_updates A list of updates that succeeded.
	 * @param array  $failed_updates     A list of updates that failed.
	 */
	protected function send_plugin_theme_email( $type, $successful_updates, $failed_updates ) {
		// No updates were attempted.
		if ( empty( $successful_updates ) && empty( $failed_updates ) ) {
			return;
		}

		$unique_failures     = false;
		$past_failure_emails = get_option( 'auto_plugin_theme_update_emails', array() );

		/*
		 * When only failures have occurred, an email should only be sent if there are unique failures.
		 * A failure is considered unique if an email has not been sent for an update attempt failure
		 * to a plugin or theme with the same new_version.
		 */
		if ( 'fail' === $type ) {
			foreach ( $failed_updates as $update_type => $failures ) {
				foreach ( $failures as $failed_update ) {
					if ( ! isset( $past_failure_emails[ $failed_update->item->{$update_type} ] ) ) {
						$unique_failures = true;
						continue;
					}

					// Check that the failure represents a new failure based on the new_version.
					if ( version_compare( $past_failure_emails[ $failed_update->item->{$update_type} ], $failed_update->item->new_version, '<' ) ) {
						$unique_failures = true;
					}
				}
			}

			if ( ! $unique_failures ) {
				return;
			}
		}

		$admin_user = get_user_by( 'email', get_site_option( 'admin_email' ) );

		if ( $admin_user ) {
			$switched_locale = switch_to_user_locale( $admin_user->ID );
		} else {
			$switched_locale = switch_to_locale( get_locale() );
		}

		$body               = array();
		$successful_plugins = ( ! empty( $successful_updates['plugin'] ) );
		$successful_themes  = ( ! empty( $successful_updates['theme'] ) );
		$failed_plugins     = ( ! empty( $failed_updates['plugin'] ) );
		$failed_themes      = ( ! empty( $failed_updates['theme'] ) );

		switch ( $type ) {
			case 'success':
				if ( $successful_plugins && $successful_themes ) {
					/* translators: %s: Site title. */
					$subject = __( '[%s] Some plugins and themes have automatically updated' );
					$body[]  = sprintf(
						/* translators: %s: Home URL. */
						__( 'Howdy! Some plugins and themes have automatically updated to their latest versions on your site at %s. No further action is needed on your part.' ),
						home_url()
					);
				} elseif ( $successful_plugins ) {
					/* translators: %s: Site title. */
					$subject = __( '[%s] Some plugins were automatically updated' );
					$body[]  = sprintf(
						/* translators: %s: Home URL. */
						__( 'Howdy! Some plugins have automatically updated to their latest versions on your site at %s. No further action is needed on your part.' ),
						home_url()
					);
				} else {
					/* translators: %s: Site title. */
					$subject = __( '[%s] Some themes were automatically updated' );
					$body[]  = sprintf(
						/* translators: %s: Home URL. */
						__( 'Howdy! Some themes have automatically updated to their latest versions on your site at %s. No further action is needed on your part.' ),
						home_url()
					);
				}

				break;
			case 'fail':
			case 'mixed':
				if ( $failed_plugins && $failed_themes ) {
					/* translators: %s: Site title. */
					$subject = __( '[%s] Some plugins and themes have failed to update' );
					$body[]  = sprintf(
						/* translators: %s: Home URL. */
						__( 'Howdy! Plugins and themes failed to update on your site at %s.' ),
						home_url()
					);
				} elseif ( $failed_plugins ) {
					/* translators: %s: Site title. */
					$subject = __( '[%s] Some plugins have failed to update' );
					$body[]  = sprintf(
						/* translators: %s: Home URL. */
						__( 'Howdy! Plugins failed to update on your site at %s.' ),
						home_url()
					);
				} else {
					/* translators: %s: Site title. */
					$subject = __( '[%s] Some themes have failed to update' );
					$body[]  = sprintf(
						/* translators: %s: Home URL. */
						__( 'Howdy! Themes failed to update on your site at %s.' ),
						home_url()
					);
				}

				break;
		}

		if ( in_array( $type, array( 'fail', 'mixed' ), true ) ) {
			$body[] = "\n";
			$body[] = __( 'Please check your site now. It’s possible that everything is working. If there are updates available, you should update.' );
			$body[] = "\n";

			// List failed plugin updates.
			if ( ! empty( $failed_updates['plugin'] ) ) {
				$body[] = __( 'The following plugins failed to update. If there was a fatal error in the update, the previously installed version has been restored.' );

				foreach ( $failed_updates['plugin'] as $item ) {
					$body_message = '';
					$item_url     = '';

					if ( ! empty( $item->item->url ) ) {
						$item_url = ' : ' . esc_url( $item->item->url );
					}

					if ( $item->item->current_version ) {
						$body_message .= sprintf(
							/* translators: 1: Plugin name, 2: Current version number, 3: New version number, 4: Plugin URL. */
							__( '- %1$s (from version %2$s to %3$s)%4$s' ),
							html_entity_decode( $item->name ),
							$item->item->current_version,
							$item->item->new_version,
							$item_url
						);
					} else {
						$body_message .= sprintf(
							/* translators: 1: Plugin name, 2: Version number, 3: Plugin URL. */
							__( '- %1$s version %2$s%3$s' ),
							html_entity_decode( $item->name ),
							$item->item->new_version,
							$item_url
						);
					}

					$body[] = $body_message;

					$past_failure_emails[ $item->item->plugin ] = $item->item->new_version;
				}

				$body[] = "\n";
			}

			// List failed theme updates.
			if ( ! empty( $failed_updates['theme'] ) ) {
				$body[] = __( 'These themes failed to update:' );

				foreach ( $failed_updates['theme'] as $item ) {
					if ( $item->item->current_version ) {
						$body[] = sprintf(
							/* translators: 1: Theme name, 2: Current version number, 3: New version number. */
							__( '- %1$s (from version %2$s to %3$s)' ),
							html_entity_decode( $item->name ),
							$item->item->current_version,
							$item->item->new_version
						);
					} else {
						$body[] = sprintf(
							/* translators: 1: Theme name, 2: Version number. */
							__( '- %1$s version %2$s' ),
							html_entity_decode( $item->name ),
							$item->item->new_version
						);
					}

					$past_failure_emails[ $item->item->theme ] = $item->item->new_version;
				}

				$body[] = "\n";
			}
		}

		// List successful updates.
		if ( in_array( $type, array( 'success', 'mixed' ), true ) ) {
			$body[] = "\n";

			// List successful plugin updates.
			if ( ! empty( $successful_updates['plugin'] ) ) {
				$body[] = __( 'These plugins are now up to date:' );

				foreach ( $successful_updates['plugin'] as $item ) {
					$body_message = '';
					$item_url     = '';

					if ( ! empty( $item->item->url ) ) {
						$item_url = ' : ' . esc_url( $item->item->url );
					}

					if ( $item->item->current_version ) {
						$body_message .= sprintf(
							/* translators: 1: Plugin name, 2: Current version number, 3: New version number, 4: Plugin URL. */
							__( '- %1$s (from version %2$s to %3$s)%4$s' ),
							html_entity_decode( $item->name ),
							$item->item->current_version,
							$item->item->new_version,
							$item_url
						);
					} else {
						$body_message .= sprintf(
							/* translators: 1: Plugin name, 2: Version number, 3: Plugin URL. */
							__( '- %1$s version %2$s%3$s' ),
							html_entity_decode( $item->name ),
							$item->item->new_version,
							$item_url
						);
					}
					$body[] = $body_message;

					unset( $past_failure_emails[ $item->item->plugin ] );
				}

				$body[] = "\n";
			}

			// List successful theme updates.
			if ( ! empty( $successful_updates['theme'] ) ) {
				$body[] = __( 'These themes are now up to date:' );

				foreach ( $successful_updates['theme'] as $item ) {
					if ( $item->item->current_version ) {
						$body[] = sprintf(
							/* translators: 1: Theme name, 2: Current version number, 3: New version number. */
							__( '- %1$s (from version %2$s to %3$s)' ),
							html_entity_decode( $item->name ),
							$item->item->current_version,
							$item->item->new_version
						);
					} else {
						$body[] = sprintf(
							/* translators: 1: Theme name, 2: Version number. */
							__( '- %1$s version %2$s' ),
							html_entity_decode( $item->name ),
							$item->item->new_version
						);
					}

					unset( $past_failure_emails[ $item->item->theme ] );
				}

				$body[] = "\n";
			}
		}

		if ( $failed_plugins ) {
			$body[] = sprintf(
				/* translators: %s: Plugins screen URL. */
				__( 'To manage plugins on your site, visit the Plugins page: %s' ),
				admin_url( 'plugins.php' )
			);
			$body[] = "\n";
		}

		if ( $failed_themes ) {
			$body[] = sprintf(
				/* translators: %s: Themes screen URL. */
				__( 'To manage themes on your site, visit the Themes page: %s' ),
				admin_url( 'themes.php' )
			);
			$body[] = "\n";
		}

		// Add a note about the support forums.
		$body[] = __( 'If you experience any issues or need support, the volunteers in the WordPress.org support forums may be able to help.' );
		$body[] = __( 'https://wordpress.org/support/forums/' );
		$body[] = "\n" . __( 'The WordPress Team' );

		if ( '' !== get_option( 'blogname' ) ) {
			$site_title = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
		} else {
			$site_title = parse_url( home_url(), PHP_URL_HOST );
		}

		$body    = implode( "\n", $body );
		$to      = get_site_option( 'admin_email' );
		$subject = sprintf( $subject, $site_title );
		$headers = '';

		$email = compact( 'to', 'subject', 'body', 'headers' );

		/**
		 * Filters the email sent following an automatic background update for plugins and themes.
		 *
		 * @since 5.5.0
		 *
		 * @param array  $email {
		 *     Array of email arguments that will be passed to wp_mail().
		 *
		 *     @type string $to      The email recipient. An array of emails
		 *                           can be returned, as handled by wp_mail().
		 *     @type string $subject The email's subject.
		 *     @type string $body    The email message body.
		 *     @type string $headers Any email headers, defaults to no headers.
		 * }
		 * @param string $type               The type of email being sent. Can be one of 'success', 'fail', 'mixed'.
		 * @param array  $successful_updates A list of updates that succeeded.
		 * @param array  $failed_updates     A list of updates that failed.
		 */
		$email = apply_filters( 'auto_plugin_theme_update_email', $email, $type, $successful_updates, $failed_updates );

		$result = wp_mail( $email['to'], wp_specialchars_decode( $email['subject'] ), $email['body'], $email['headers'] );

		if ( $result ) {
			update_option( 'auto_plugin_theme_update_emails', $past_failure_emails );
		}

		if ( $switched_locale ) {
			restore_previous_locale();
		}
	}

	/**
	 * Prepares and sends an email of a full log of background update results, useful for debugging and geekery.
	 *
	 * @since 3.7.0
	 */
	protected function send_debug_email() {
		$admin_user = get_user_by( 'email', get_site_option( 'admin_email' ) );

		if ( $admin_user ) {
			$switched_locale = switch_to_user_locale( $admin_user->ID );
		} else {
			$switched_locale = switch_to_locale( get_locale() );
		}

		$body     = array();
		$failures = 0;

		/* translators: %s: Network home URL. */
		$body[] = sprintf( __( 'WordPress site: %s' ), network_home_url( '/' ) );

		// Core.
		if ( isset( $this->update_results['core'] ) ) {
			$result = $this->update_results['core'][0];

			if ( $result->result && ! is_wp_error( $result->result ) ) {
				/* translators: %s: WordPress version. */
				$body[] = sprintf( __( 'SUCCESS: WordPress was successfully updated to %s' ), $result->name );
			} else {
				/* translators: %s: WordPress version. */
				$body[] = sprintf( __( 'FAILED: WordPress failed to update to %s' ), $result->name );
				++$failures;
			}

			$body[] = '';
		}

		// Plugins, Themes, Translations.
		foreach ( array( 'plugin', 'theme', 'translation' ) as $type ) {
			if ( ! isset( $this->update_results[ $type ] ) ) {
				continue;
			}

			$success_items = wp_list_filter( $this->update_results[ $type ], array( 'result' => true ) );

			if ( $success_items ) {
				$messages = array(
					'plugin'      => __( 'The following plugins were successfully updated:' ),
					'theme'       => __( 'The following themes were successfully updated:' ),
					'translation' => __( 'The following translations were successfully updated:' ),
				);

				$body[] = $messages[ $type ];
				foreach ( wp_list_pluck( $success_items, 'name' ) as $name ) {
					/* translators: %s: Name of plugin / theme / translation. */
					$body[] = ' * ' . sprintf( __( 'SUCCESS: %s' ), $name );
				}
			}

			if ( $success_items !== $this->update_results[ $type ] ) {
				// Failed updates.
				$messages = array(
					'plugin'      => __( 'The following plugins failed to update:' ),
					'theme'       => __( 'The following themes failed to update:' ),
					'translation' => __( 'The following translations failed to update:' ),
				);

				$body[] = $messages[ $type ];

				foreach ( $this->update_results[ $type ] as $item ) {
					if ( ! $item->result || is_wp_error( $item->result ) ) {
						/* translators: %s: Name of plugin / theme / translation. */
						$body[] = ' * ' . sprintf( __( 'FAILED: %s' ), $item->name );
						++$failures;
					}
				}
			}

			$body[] = '';
		}

		if ( '' !== get_bloginfo( 'name' ) ) {
			$site_title = wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES );
		} else {
			$site_title = parse_url( home_url(), PHP_URL_HOST );
		}

		if ( $failures ) {
			$body[] = trim(
				__(
					"BETA TESTING?
=============

This debugging email is sent when you are using a development version of WordPress.

If you think these failures might be due to a bug in WordPress, could you report it?
 * Open a thread in the support forums: https://wordpress.org/support/forum/alphabeta
 * Or, if you're comfortable writing a bug report: https://core.trac.wordpress.org/

Thanks! -- The WordPress Team"
				)
			);
			$body[] = '';

			/* translators: Background update failed notification email subject. %s: Site title. */
			$subject = sprintf( __( '[%s] Background Update Failed' ), $site_title );
		} else {
			/* translators: Background update finished notification email subject. %s: Site title. */
			$subject = sprintf( __( '[%s] Background Update Finished' ), $site_title );
		}

		$body[] = trim(
			__(
				'UPDATE LOG
=========='
			)
		);
		$body[] = '';

		foreach ( array( 'core', 'plugin', 'theme', 'translation' ) as $type ) {
			if ( ! isset( $this->update_results[ $type ] ) ) {
				continue;
			}

			foreach ( $this->update_results[ $type ] as $update ) {
				$body[] = $update->name;
				$body[] = str_repeat( '-', strlen( $update->name ) );

				foreach ( $update->messages as $message ) {
					$body[] = '  ' . html_entity_decode( str_replace( '&#8230;', '...', $message ) );
				}

				if ( is_wp_error( $update->result ) ) {
					$results = array( 'update' => $update->result );

					// If we rolled back, we want to know an error that occurred then too.
					if ( 'rollback_was_required' === $update->result->get_error_code() ) {
						$results = (array) $update->result->get_error_data();
					}

					foreach ( $results as $result_type => $result ) {
						if ( ! is_wp_error( $result ) ) {
							continue;
						}

						if ( 'rollback' === $result_type ) {
							/* translators: 1: Error code, 2: Error message. */
							$body[] = '  ' . sprintf( __( 'Rollback Error: [%1$s] %2$s' ), $result->get_error_code(), $result->get_error_message() );
						} else {
							/* translators: 1: Error code, 2: Error message. */
							$body[] = '  ' . sprintf( __( 'Error: [%1$s] %2$s' ), $result->get_error_code(), $result->get_error_message() );
						}

						if ( $result->get_error_data() ) {
							$body[] = '         ' . implode( ', ', (array) $result->get_error_data() );
						}
					}
				}

				$body[] = '';
			}
		}

		$email = array(
			'to'      => get_site_option( 'admin_email' ),
			'subject' => $subject,
			'body'    => implode( "\n", $body ),
			'headers' => '',
		);

		/**
		 * Filters the debug email that can be sent following an automatic
		 * background core update.
		 *
		 * @since 3.8.0
		 *
		 * @param array $email {
		 *     Array of email arguments that will be passed to wp_mail().
		 *
		 *     @type string $to      The email recipient. An array of emails
		 *                           can be returned, as handled by wp_mail().
		 *     @type string $subject Email subject.
		 *     @type string $body    Email message body.
		 *     @type string $headers Any email headers. Default empty.
		 * }
		 * @param int   $failures The number of failures encountered while upgrading.
		 * @param mixed $results  The results of all attempted updates.
		 */
		$email = apply_filters( 'automatic_updates_debug_email', $email, $failures, $this->update_results );

		wp_mail( $email['to'], wp_specialchars_decode( $email['subject'] ), $email['body'], $email['headers'] );

		if ( $switched_locale ) {
			restore_previous_locale();
		}
	}

	/**
	 * Performs a loopback request to check for potential fatal errors.
	 *
	 * Fatal errors cannot be detected unless maintenance mode is enabled.
	 *
	 * @since 6.6.0
	 *
	 * @global int $upgrading The Unix timestamp marking when upgrading WordPress began.
	 *
	 * @return bool Whether a fatal error was detected.
	 */
	protected function has_fatal_error() {
		global $upgrading;

		$maintenance_file = ABSPATH . '.maintenance';
		if ( ! file_exists( $maintenance_file ) ) {
			return false;
		}

		require $maintenance_file;
		if ( ! is_int( $upgrading ) ) {
			return false;
		}

		$scrape_key   = md5( $upgrading );
		$scrape_nonce = (string) $upgrading;
		$transient    = 'scrape_key_' . $scrape_key;
		set_transient( $transient, $scrape_nonce, 30 );

		$cookies       = wp_unslash( $_COOKIE );
		$scrape_params = array(
			'wp_scrape_key'   => $scrape_key,
			'wp_scrape_nonce' => $scrape_nonce,
		);
		$headers       = array(
			'Cache-Control' => 'no-cache',
		);

		/** This filter is documented in wp-includes/class-wp-http-streams.php */
		$sslverify = apply_filters( 'https_local_ssl_verify', false );

		// Include Basic auth in the loopback request.
		if ( isset( $_SERVER['PHP_AUTH_USER'] ) && isset( $_SERVER['PHP_AUTH_PW'] ) ) {
			$headers['Authorization'] = 'Basic ' . base64_encode( wp_unslash( $_SERVER['PHP_AUTH_USER'] ) . ':' . wp_unslash( $_SERVER['PHP_AUTH_PW'] ) );
		}

		// Time to wait for loopback request to finish.
		$timeout = 50; // 50 seconds.

		$is_debug = WP_DEBUG && WP_DEBUG_LOG;
		if ( $is_debug ) {
			error_log( '    Scraping home page...' );
		}

		$needle_start = "###### wp_scraping_result_start:$scrape_key ######";
		$needle_end   = "###### wp_scraping_result_end:$scrape_key ######";
		$url          = add_query_arg( $scrape_params, home_url( '/' ) );
		$response     = wp_remote_get( $url, compact( 'cookies', 'headers', 'timeout', 'sslverify' ) );

		if ( is_wp_error( $response ) ) {
			if ( $is_debug ) {
				error_log( 'Loopback request failed: ' . $response->get_error_message() );
			}
			return true;
		}

		// If this outputs `true` in the log, it means there were no fatal errors detected.
		if ( $is_debug ) {
			error_log( var_export( substr( $response['body'], strpos( $response['body'], '###### wp_scraping_result_start:' ) ), true ) );
		}

		$body                   = wp_remote_retrieve_body( $response );
		$scrape_result_position = strpos( $body, $needle_start );
		$result                 = null;

		if ( false !== $scrape_result_position ) {
			$error_output = substr( $body, $scrape_result_position + strlen( $needle_start ) );
			$error_output = substr( $error_output, 0, strpos( $error_output, $needle_end ) );
			$result       = json_decode( trim( $error_output ), true );
		}

		delete_transient( $transient );

		// Only fatal errors will result in a 'type' key.
		return isset( $result['type'] );
	}
}
class-wp-site-health-auto-updates.php000064400000034001151212616040013620 0ustar00<?php
/**
 * Class for testing automatic updates in the WordPress code.
 *
 * @package WordPress
 * @subpackage Site_Health
 * @since 5.2.0
 */

#[AllowDynamicProperties]
class WP_Site_Health_Auto_Updates {
	/**
	 * WP_Site_Health_Auto_Updates constructor.
	 *
	 * @since 5.2.0
	 */
	public function __construct() {
		require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
	}


	/**
	 * Runs tests to determine if auto-updates can run.
	 *
	 * @since 5.2.0
	 *
	 * @return array The test results.
	 */
	public function run_tests() {
		$tests = array(
			$this->test_constants( 'WP_AUTO_UPDATE_CORE', array( true, 'beta', 'rc', 'development', 'branch-development', 'minor' ) ),
			$this->test_wp_version_check_attached(),
			$this->test_filters_automatic_updater_disabled(),
			$this->test_wp_automatic_updates_disabled(),
			$this->test_if_failed_update(),
			$this->test_vcs_abspath(),
			$this->test_check_wp_filesystem_method(),
			$this->test_all_files_writable(),
			$this->test_accepts_dev_updates(),
			$this->test_accepts_minor_updates(),
		);

		$tests = array_filter( $tests );
		$tests = array_map(
			static function ( $test ) {
				$test = (object) $test;

				if ( empty( $test->severity ) ) {
					$test->severity = 'warning';
				}

				return $test;
			},
			$tests
		);

		return $tests;
	}

	/**
	 * Tests if auto-updates related constants are set correctly.
	 *
	 * @since 5.2.0
	 * @since 5.5.1 The `$value` parameter can accept an array.
	 *
	 * @param string $constant         The name of the constant to check.
	 * @param bool|string|array $value The value that the constant should be, if set,
	 *                                 or an array of acceptable values.
	 * @return array|null The test results if there are any constants set incorrectly,
	 *                    or null if the test passed.
	 */
	public function test_constants( $constant, $value ) {
		$acceptable_values = (array) $value;

		if ( defined( $constant ) && ! in_array( constant( $constant ), $acceptable_values, true ) ) {
			return array(
				'description' => sprintf(
					/* translators: 1: Name of the constant used. 2: Value of the constant used. */
					__( 'The %1$s constant is defined as %2$s' ),
					"<code>$constant</code>",
					'<code>' . esc_html( var_export( constant( $constant ), true ) ) . '</code>'
				),
				'severity'    => 'fail',
			);
		}

		return null;
	}

	/**
	 * Checks if updates are intercepted by a filter.
	 *
	 * @since 5.2.0
	 *
	 * @return array|null The test results if wp_version_check() is disabled,
	 *                    or null if the test passed.
	 */
	public function test_wp_version_check_attached() {
		if ( ( ! is_multisite() || is_main_site() && is_network_admin() )
			&& ! has_filter( 'wp_version_check', 'wp_version_check' )
		) {
			return array(
				'description' => sprintf(
					/* translators: %s: Name of the filter used. */
					__( 'A plugin has prevented updates by disabling %s.' ),
					'<code>wp_version_check()</code>'
				),
				'severity'    => 'fail',
			);
		}

		return null;
	}

	/**
	 * Checks if automatic updates are disabled by a filter.
	 *
	 * @since 5.2.0
	 *
	 * @return array|null The test results if the {@see 'automatic_updater_disabled'} filter is set,
	 *                    or null if the test passed.
	 */
	public function test_filters_automatic_updater_disabled() {
		/** This filter is documented in wp-admin/includes/class-wp-automatic-updater.php */
		if ( apply_filters( 'automatic_updater_disabled', false ) ) {
			return array(
				'description' => sprintf(
					/* translators: %s: Name of the filter used. */
					__( 'The %s filter is enabled.' ),
					'<code>automatic_updater_disabled</code>'
				),
				'severity'    => 'fail',
			);
		}

		return null;
	}

	/**
	 * Checks if automatic updates are disabled.
	 *
	 * @since 5.3.0
	 *
	 * @return array|false The test results if auto-updates are disabled, false otherwise.
	 */
	public function test_wp_automatic_updates_disabled() {
		if ( ! class_exists( 'WP_Automatic_Updater' ) ) {
			require_once ABSPATH . 'wp-admin/includes/class-wp-automatic-updater.php';
		}

		$auto_updates = new WP_Automatic_Updater();

		if ( ! $auto_updates->is_disabled() ) {
			return false;
		}

		return array(
			'description' => __( 'All automatic updates are disabled.' ),
			'severity'    => 'fail',
		);
	}

	/**
	 * Checks if automatic updates have tried to run, but failed, previously.
	 *
	 * @since 5.2.0
	 *
	 * @return array|false The test results if auto-updates previously failed, false otherwise.
	 */
	public function test_if_failed_update() {
		$failed = get_site_option( 'auto_core_update_failed' );

		if ( ! $failed ) {
			return false;
		}

		if ( ! empty( $failed['critical'] ) ) {
			$description  = __( 'A previous automatic background update ended with a critical failure, so updates are now disabled.' );
			$description .= ' ' . __( 'You would have received an email because of this.' );
			$description .= ' ' . __( "When you've been able to update using the \"Update now\" button on Dashboard > Updates, this error will be cleared for future update attempts." );
			$description .= ' ' . sprintf(
				/* translators: %s: Code of error shown. */
				__( 'The error code was %s.' ),
				'<code>' . $failed['error_code'] . '</code>'
			);
			return array(
				'description' => $description,
				'severity'    => 'warning',
			);
		}

		$description = __( 'A previous automatic background update could not occur.' );
		if ( empty( $failed['retry'] ) ) {
			$description .= ' ' . __( 'You would have received an email because of this.' );
		}

		$description .= ' ' . __( 'Another attempt will be made with the next release.' );
		$description .= ' ' . sprintf(
			/* translators: %s: Code of error shown. */
			__( 'The error code was %s.' ),
			'<code>' . $failed['error_code'] . '</code>'
		);
		return array(
			'description' => $description,
			'severity'    => 'warning',
		);
	}

	/**
	 * Checks if WordPress is controlled by a VCS (Git, Subversion etc).
	 *
	 * @since 5.2.0
	 *
	 * @return array The test results.
	 */
	public function test_vcs_abspath() {
		$context_dirs = array( ABSPATH );
		$vcs_dirs     = array( '.svn', '.git', '.hg', '.bzr' );
		$check_dirs   = array();

		foreach ( $context_dirs as $context_dir ) {
			// Walk up from $context_dir to the root.
			do {
				$check_dirs[] = $context_dir;

				// Once we've hit '/' or 'C:\', we need to stop. dirname will keep returning the input here.
				if ( dirname( $context_dir ) === $context_dir ) {
					break;
				}

				// Continue one level at a time.
			} while ( $context_dir = dirname( $context_dir ) );
		}

		$check_dirs = array_unique( $check_dirs );
		$updater    = new WP_Automatic_Updater();
		$checkout   = false;

		// Search all directories we've found for evidence of version control.
		foreach ( $vcs_dirs as $vcs_dir ) {
			foreach ( $check_dirs as $check_dir ) {
				if ( ! $updater->is_allowed_dir( $check_dir ) ) {
					continue;
				}

				$checkout = is_dir( rtrim( $check_dir, '\\/' ) . "/$vcs_dir" );
				if ( $checkout ) {
					break 2;
				}
			}
		}

		/** This filter is documented in wp-admin/includes/class-wp-automatic-updater.php */
		if ( $checkout && ! apply_filters( 'automatic_updates_is_vcs_checkout', true, ABSPATH ) ) {
			return array(
				'description' => sprintf(
					/* translators: 1: Folder name. 2: Version control directory. 3: Filter name. */
					__( 'The folder %1$s was detected as being under version control (%2$s), but the %3$s filter is allowing updates.' ),
					'<code>' . $check_dir . '</code>',
					"<code>$vcs_dir</code>",
					'<code>automatic_updates_is_vcs_checkout</code>'
				),
				'severity'    => 'info',
			);
		}

		if ( $checkout ) {
			return array(
				'description' => sprintf(
					/* translators: 1: Folder name. 2: Version control directory. */
					__( 'The folder %1$s was detected as being under version control (%2$s).' ),
					'<code>' . $check_dir . '</code>',
					"<code>$vcs_dir</code>"
				),
				'severity'    => 'warning',
			);
		}

		return array(
			'description' => __( 'No version control systems were detected.' ),
			'severity'    => 'pass',
		);
	}

	/**
	 * Checks if we can access files without providing credentials.
	 *
	 * @since 5.2.0
	 *
	 * @return array The test results.
	 */
	public function test_check_wp_filesystem_method() {
		// Make sure the `request_filesystem_credentials()` function is available during our REST API call.
		if ( ! function_exists( 'request_filesystem_credentials' ) ) {
			require_once ABSPATH . 'wp-admin/includes/file.php';
		}

		$skin    = new Automatic_Upgrader_Skin();
		$success = $skin->request_filesystem_credentials( false, ABSPATH );

		if ( ! $success ) {
			$description  = __( 'Your installation of WordPress prompts for FTP credentials to perform updates.' );
			$description .= ' ' . __( '(Your site is performing updates over FTP due to file ownership. Talk to your hosting company.)' );

			return array(
				'description' => $description,
				'severity'    => 'fail',
			);
		}

		return array(
			'description' => __( 'Your installation of WordPress does not require FTP credentials to perform updates.' ),
			'severity'    => 'pass',
		);
	}

	/**
	 * Checks if core files are writable by the web user/group.
	 *
	 * @since 5.2.0
	 *
	 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
	 *
	 * @return array|false The test results if at least some of WordPress core files are writeable,
	 *                     or if a list of the checksums could not be retrieved from WordPress.org.
	 *                     False if the core files are not writeable.
	 */
	public function test_all_files_writable() {
		global $wp_filesystem;

		require ABSPATH . WPINC . '/version.php'; // $wp_version; // x.y.z

		$skin    = new Automatic_Upgrader_Skin();
		$success = $skin->request_filesystem_credentials( false, ABSPATH );

		if ( ! $success ) {
			return false;
		}

		WP_Filesystem();

		if ( 'direct' !== $wp_filesystem->method ) {
			return false;
		}

		// Make sure the `get_core_checksums()` function is available during our REST API call.
		if ( ! function_exists( 'get_core_checksums' ) ) {
			require_once ABSPATH . 'wp-admin/includes/update.php';
		}

		$checksums = get_core_checksums( $wp_version, 'en_US' );
		$dev       = ( str_contains( $wp_version, '-' ) );
		// Get the last stable version's files and test against that.
		if ( ! $checksums && $dev ) {
			$checksums = get_core_checksums( (float) $wp_version - 0.1, 'en_US' );
		}

		// There aren't always checksums for development releases, so just skip the test if we still can't find any.
		if ( ! $checksums && $dev ) {
			return false;
		}

		if ( ! $checksums ) {
			$description = sprintf(
				/* translators: %s: WordPress version. */
				__( "Couldn't retrieve a list of the checksums for WordPress %s." ),
				$wp_version
			);
			$description .= ' ' . __( 'This could mean that connections are failing to WordPress.org.' );
			return array(
				'description' => $description,
				'severity'    => 'warning',
			);
		}

		$unwritable_files = array();
		foreach ( array_keys( $checksums ) as $file ) {
			if ( str_starts_with( $file, 'wp-content' ) ) {
				continue;
			}
			if ( ! file_exists( ABSPATH . $file ) ) {
				continue;
			}
			if ( ! is_writable( ABSPATH . $file ) ) {
				$unwritable_files[] = $file;
			}
		}

		if ( $unwritable_files ) {
			if ( count( $unwritable_files ) > 20 ) {
				$unwritable_files   = array_slice( $unwritable_files, 0, 20 );
				$unwritable_files[] = '...';
			}
			return array(
				'description' => __( 'Some files are not writable by WordPress:' ) . ' <ul><li>' . implode( '</li><li>', $unwritable_files ) . '</li></ul>',
				'severity'    => 'fail',
			);
		} else {
			return array(
				'description' => __( 'All of your WordPress files are writable.' ),
				'severity'    => 'pass',
			);
		}
	}

	/**
	 * Checks if the install is using a development branch and can use nightly packages.
	 *
	 * @since 5.2.0
	 *
	 * @return array|false|null The test results if development updates are blocked.
	 *                          False if it isn't a development version. Null if the test passed.
	 */
	public function test_accepts_dev_updates() {
		require ABSPATH . WPINC . '/version.php'; // $wp_version; // x.y.z
		// Only for dev versions.
		if ( ! str_contains( $wp_version, '-' ) ) {
			return false;
		}

		if ( defined( 'WP_AUTO_UPDATE_CORE' ) && ( 'minor' === WP_AUTO_UPDATE_CORE || false === WP_AUTO_UPDATE_CORE ) ) {
			return array(
				'description' => sprintf(
					/* translators: %s: Name of the constant used. */
					__( 'WordPress development updates are blocked by the %s constant.' ),
					'<code>WP_AUTO_UPDATE_CORE</code>'
				),
				'severity'    => 'fail',
			);
		}

		/** This filter is documented in wp-admin/includes/class-core-upgrader.php */
		if ( ! apply_filters( 'allow_dev_auto_core_updates', $wp_version ) ) {
			return array(
				'description' => sprintf(
					/* translators: %s: Name of the filter used. */
					__( 'WordPress development updates are blocked by the %s filter.' ),
					'<code>allow_dev_auto_core_updates</code>'
				),
				'severity'    => 'fail',
			);
		}

		return null;
	}

	/**
	 * Checks if the site supports automatic minor updates.
	 *
	 * @since 5.2.0
	 *
	 * @return array|null The test results if minor updates are blocked,
	 *                    or null if the test passed.
	 */
	public function test_accepts_minor_updates() {
		if ( defined( 'WP_AUTO_UPDATE_CORE' ) && false === WP_AUTO_UPDATE_CORE ) {
			return array(
				'description' => sprintf(
					/* translators: %s: Name of the constant used. */
					__( 'WordPress security and maintenance releases are blocked by %s.' ),
					"<code>define( 'WP_AUTO_UPDATE_CORE', false );</code>"
				),
				'severity'    => 'fail',
			);
		}

		/** This filter is documented in wp-admin/includes/class-core-upgrader.php */
		if ( ! apply_filters( 'allow_minor_auto_core_updates', true ) ) {
			return array(
				'description' => sprintf(
					/* translators: %s: Name of the filter used. */
					__( 'WordPress security and maintenance releases are blocked by the %s filter.' ),
					'<code>allow_minor_auto_core_updates</code>'
				),
				'severity'    => 'fail',
			);
		}

		return null;
	}
}
image-edit.php000064400000126175151212616040007274 0ustar00<?php
/**
 * WordPress Image Editor
 *
 * @package WordPress
 * @subpackage Administration
 */

/**
 * Loads the WP image-editing interface.
 *
 * @since 2.9.0
 *
 * @param int          $post_id Attachment post ID.
 * @param false|object $msg     Optional. Message to display for image editor updates or errors.
 *                              Default false.
 */
function wp_image_editor( $post_id, $msg = false ) {
	$nonce     = wp_create_nonce( "image_editor-$post_id" );
	$meta      = wp_get_attachment_metadata( $post_id );
	$thumb     = image_get_intermediate_size( $post_id, 'thumbnail' );
	$sub_sizes = isset( $meta['sizes'] ) && is_array( $meta['sizes'] );
	$note      = '';

	if ( isset( $meta['width'], $meta['height'] ) ) {
		$big = max( $meta['width'], $meta['height'] );
	} else {
		die( __( 'Image data does not exist. Please re-upload the image.' ) );
	}

	$sizer = $big > 600 ? 600 / $big : 1;

	$backup_sizes = get_post_meta( $post_id, '_wp_attachment_backup_sizes', true );
	$can_restore  = false;

	if ( ! empty( $backup_sizes ) && isset( $backup_sizes['full-orig'], $meta['file'] ) ) {
		$can_restore = wp_basename( $meta['file'] ) !== $backup_sizes['full-orig']['file'];
	}

	if ( $msg ) {
		if ( isset( $msg->error ) ) {
			$note = "<div class='notice notice-error' role='alert'><p>$msg->error</p></div>";
		} elseif ( isset( $msg->msg ) ) {
			$note = "<div class='notice notice-success' role='alert'><p>$msg->msg</p></div>";
		}
	}

	/**
	 * Shows the settings in the Image Editor that allow selecting to edit only the thumbnail of an image.
	 *
	 * @since 6.3.0
	 *
	 * @param bool $show Whether to show the settings in the Image Editor. Default false.
	 */
	$edit_thumbnails_separately = (bool) apply_filters( 'image_edit_thumbnails_separately', false );

	?>
	<div class="imgedit-wrap wp-clearfix">
	<div id="imgedit-panel-<?php echo $post_id; ?>">
	<?php echo $note; ?>
	<div class="imgedit-panel-content imgedit-panel-tools wp-clearfix">
		<div class="imgedit-menu wp-clearfix">
			<button type="button" onclick="imageEdit.toggleCropTool( <?php echo "$post_id, '$nonce'"; ?>, this );" aria-expanded="false" aria-controls="imgedit-crop" class="imgedit-crop button disabled" disabled><?php esc_html_e( 'Crop' ); ?></button>
			<button type="button" class="imgedit-scale button" onclick="imageEdit.toggleControls(this);" aria-expanded="false" aria-controls="imgedit-scale"><?php esc_html_e( 'Scale' ); ?></button>
			<div class="imgedit-rotate-menu-container">
				<button type="button" aria-controls="imgedit-rotate-menu" class="imgedit-rotate button" aria-expanded="false" onclick="imageEdit.togglePopup(this)" onblur="imageEdit.monitorPopup()"><?php esc_html_e( 'Image Rotation' ); ?></button>
				<div id="imgedit-rotate-menu" class="imgedit-popup-menu">
			<?php
			// On some setups GD library does not provide imagerotate() - Ticket #11536.
			if ( wp_image_editor_supports(
				array(
					'mime_type' => get_post_mime_type( $post_id ),
					'methods'   => array( 'rotate' ),
				)
			) ) {
				$note_no_rotate = '';
				?>
					<button type="button" class="imgedit-rleft button" onkeydown="imageEdit.browsePopup(event, this)" onclick="imageEdit.rotate( 90, <?php echo "$post_id, '$nonce'"; ?>, this)" onblur="imageEdit.monitorPopup()"><?php esc_html_e( 'Rotate 90&deg; left' ); ?></button>
					<button type="button" class="imgedit-rright button" onkeydown="imageEdit.browsePopup(event, this)" onclick="imageEdit.rotate(-90, <?php echo "$post_id, '$nonce'"; ?>, this)" onblur="imageEdit.monitorPopup()"><?php esc_html_e( 'Rotate 90&deg; right' ); ?></button>
					<button type="button" class="imgedit-rfull button" onkeydown="imageEdit.browsePopup(event, this)" onclick="imageEdit.rotate(180, <?php echo "$post_id, '$nonce'"; ?>, this)" onblur="imageEdit.monitorPopup()"><?php esc_html_e( 'Rotate 180&deg;' ); ?></button>
				<?php
			} else {
				$note_no_rotate = '<p class="note-no-rotate"><em>' . __( 'Image rotation is not supported by your web host.' ) . '</em></p>';
				?>
					<button type="button" class="imgedit-rleft button disabled" disabled></button>
					<button type="button" class="imgedit-rright button disabled" disabled></button>
				<?php
			}
			?>
					<hr />
					<button type="button" onkeydown="imageEdit.browsePopup(event, this)" onclick="imageEdit.flip(1, <?php echo "$post_id, '$nonce'"; ?>, this)" onblur="imageEdit.monitorPopup()" class="imgedit-flipv button"><?php esc_html_e( 'Flip vertical' ); ?></button>
					<button type="button" onkeydown="imageEdit.browsePopup(event, this)" onclick="imageEdit.flip(2, <?php echo "$post_id, '$nonce'"; ?>, this)" onblur="imageEdit.monitorPopup()" class="imgedit-fliph button"><?php esc_html_e( 'Flip horizontal' ); ?></button>
					<?php echo $note_no_rotate; ?>
				</div>
			</div>
		</div>
		<div class="imgedit-submit imgedit-menu">
			<button type="button" id="image-undo-<?php echo $post_id; ?>" onclick="imageEdit.undo(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-undo button disabled" disabled><?php esc_html_e( 'Undo' ); ?></button>
			<button type="button" id="image-redo-<?php echo $post_id; ?>" onclick="imageEdit.redo(<?php echo "$post_id, '$nonce'"; ?>, this)" class="imgedit-redo button disabled" disabled><?php esc_html_e( 'Redo' ); ?></button>
			<button type="button" onclick="imageEdit.close(<?php echo $post_id; ?>, 1)" class="button imgedit-cancel-btn"><?php esc_html_e( 'Cancel Editing' ); ?></button>
			<button type="button" onclick="imageEdit.save(<?php echo "$post_id, '$nonce'"; ?>)" disabled="disabled" class="button button-primary imgedit-submit-btn"><?php esc_html_e( 'Save Edits' ); ?></button>
		</div>
	</div>

	<div class="imgedit-panel-content wp-clearfix">
		<div class="imgedit-tools">
			<input type="hidden" id="imgedit-nonce-<?php echo $post_id; ?>" value="<?php echo $nonce; ?>" />
			<input type="hidden" id="imgedit-sizer-<?php echo $post_id; ?>" value="<?php echo $sizer; ?>" />
			<input type="hidden" id="imgedit-history-<?php echo $post_id; ?>" value="" />
			<input type="hidden" id="imgedit-undone-<?php echo $post_id; ?>" value="0" />
			<input type="hidden" id="imgedit-selection-<?php echo $post_id; ?>" value="" />
			<input type="hidden" id="imgedit-x-<?php echo $post_id; ?>" value="<?php echo isset( $meta['width'] ) ? $meta['width'] : 0; ?>" />
			<input type="hidden" id="imgedit-y-<?php echo $post_id; ?>" value="<?php echo isset( $meta['height'] ) ? $meta['height'] : 0; ?>" />

			<div id="imgedit-crop-<?php echo $post_id; ?>" class="imgedit-crop-wrap">
			<div class="imgedit-crop-grid"></div>
			<img id="image-preview-<?php echo $post_id; ?>" onload="imageEdit.imgLoaded('<?php echo $post_id; ?>')"
				src="<?php echo esc_url( admin_url( 'admin-ajax.php', 'relative' ) ) . '?action=imgedit-preview&amp;_ajax_nonce=' . $nonce . '&amp;postid=' . $post_id . '&amp;rand=' . rand( 1, 99999 ); ?>" alt="" />
			</div>
		</div>
		<div class="imgedit-settings">
			<div class="imgedit-tool-active">
				<div class="imgedit-group">
				<div id="imgedit-scale" tabindex="-1" class="imgedit-group-controls">
					<div class="imgedit-group-top">
						<h2><?php _e( 'Scale Image' ); ?></h2>
						<button type="button" class="dashicons dashicons-editor-help imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);" aria-expanded="false"><span class="screen-reader-text">
						<?php
						/* translators: Hidden accessibility text. */
						esc_html_e( 'Scale Image Help' );
						?>
						</span></button>
						<div class="imgedit-help">
						<p><?php _e( 'You can proportionally scale the original image. For best results, scaling should be done before you crop, flip, or rotate. Images can only be scaled down, not up.' ); ?></p>
						</div>
						<?php if ( isset( $meta['width'], $meta['height'] ) ) : ?>
						<p>
							<?php
							printf(
								/* translators: %s: Image width and height in pixels. */
								__( 'Original dimensions %s' ),
								'<span class="imgedit-original-dimensions">' . $meta['width'] . ' &times; ' . $meta['height'] . '</span>'
							);
							?>
						</p>
						<?php endif; ?>
						<div class="imgedit-submit">
						<fieldset class="imgedit-scale-controls">
							<legend><?php _e( 'New dimensions:' ); ?></legend>
							<div class="nowrap">
							<label for="imgedit-scale-width-<?php echo $post_id; ?>" class="screen-reader-text">
							<?php
							/* translators: Hidden accessibility text. */
							_e( 'scale height' );
							?>
							</label>
							<input type="number" step="1" min="0" max="<?php echo isset( $meta['width'] ) ? $meta['width'] : ''; ?>" aria-describedby="imgedit-scale-warn-<?php echo $post_id; ?>"  id="imgedit-scale-width-<?php echo $post_id; ?>" onkeyup="imageEdit.scaleChanged(<?php echo $post_id; ?>, 1, this)" onblur="imageEdit.scaleChanged(<?php echo $post_id; ?>, 1, this)" value="<?php echo isset( $meta['width'] ) ? $meta['width'] : 0; ?>" />
							<span class="imgedit-separator" aria-hidden="true">&times;</span>
							<label for="imgedit-scale-height-<?php echo $post_id; ?>" class="screen-reader-text"><?php _e( 'scale height' ); ?></label>
							<input type="number" step="1" min="0" max="<?php echo isset( $meta['height'] ) ? $meta['height'] : ''; ?>" aria-describedby="imgedit-scale-warn-<?php echo $post_id; ?>" id="imgedit-scale-height-<?php echo $post_id; ?>" onkeyup="imageEdit.scaleChanged(<?php echo $post_id; ?>, 0, this)" onblur="imageEdit.scaleChanged(<?php echo $post_id; ?>, 0, this)" value="<?php echo isset( $meta['height'] ) ? $meta['height'] : 0; ?>" />
							<button id="imgedit-scale-button" type="button" onclick="imageEdit.action(<?php echo "$post_id, '$nonce'"; ?>, 'scale')" class="button button-primary"><?php esc_html_e( 'Scale' ); ?></button>
							</div>
							<span class="imgedit-scale-warn" id="imgedit-scale-warn-<?php echo $post_id; ?>"><span class="dashicons dashicons-warning" aria-hidden="true"></span><?php esc_html_e( 'Images cannot be scaled to a size larger than the original.' ); ?></span>
						</fieldset>
						</div>
					</div>
				</div>
			</div>

		<?php if ( $can_restore ) { ?>
				<div class="imgedit-group">
				<div class="imgedit-group-top">
					<h2><button type="button" onclick="imageEdit.toggleHelp(this);" class="button-link" aria-expanded="false"><?php _e( 'Restore original image' ); ?> <span class="dashicons dashicons-arrow-down imgedit-help-toggle"></span></button></h2>
					<div class="imgedit-help imgedit-restore">
					<p>
					<?php
					_e( 'Discard any changes and restore the original image.' );
					if ( ! defined( 'IMAGE_EDIT_OVERWRITE' ) || ! IMAGE_EDIT_OVERWRITE ) {
						echo ' ' . __( 'Previously edited copies of the image will not be deleted.' );
					}
					?>
					</p>
					<div class="imgedit-submit">
						<input type="button" onclick="imageEdit.action(<?php echo "$post_id, '$nonce'"; ?>, 'restore')" class="button button-primary" value="<?php esc_attr_e( 'Restore image' ); ?>" <?php echo $can_restore; ?> />
					</div>
				</div>
			</div>
			</div>
		<?php } ?>
			<div class="imgedit-group">
				<div id="imgedit-crop" tabindex="-1" class="imgedit-group-controls">
				<div class="imgedit-group-top">
					<h2><?php _e( 'Crop Image' ); ?></h2>
					<button type="button" class="dashicons dashicons-editor-help imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);" aria-expanded="false"><span class="screen-reader-text">
					<?php
					/* translators: Hidden accessibility text. */
					_e( 'Image Crop Help' );
					?>
					</span></button>
					<div class="imgedit-help">
						<p><?php _e( 'To crop the image, click on it and drag to make your selection.' ); ?></p>
						<p><strong><?php _e( 'Crop Aspect Ratio' ); ?></strong><br />
						<?php _e( 'The aspect ratio is the relationship between the width and height. You can preserve the aspect ratio by holding down the shift key while resizing your selection. Use the input box to specify the aspect ratio, e.g. 1:1 (square), 4:3, 16:9, etc.' ); ?></p>

						<p><strong><?php _e( 'Crop Selection' ); ?></strong><br />
						<?php _e( 'Once you have made your selection, you can adjust it by entering the size in pixels. The minimum selection size is the thumbnail size as set in the Media settings.' ); ?></p>
					</div>
				</div>
				<fieldset class="imgedit-crop-ratio">
					<legend><?php _e( 'Aspect ratio:' ); ?></legend>
					<div class="nowrap">
					<label for="imgedit-crop-width-<?php echo $post_id; ?>" class="screen-reader-text">
					<?php
					/* translators: Hidden accessibility text. */
					_e( 'crop ratio width' );
					?>
					</label>
					<input type="number" step="1" min="1" id="imgedit-crop-width-<?php echo $post_id; ?>" onkeyup="imageEdit.setRatioSelection(<?php echo $post_id; ?>, 0, this)" onblur="imageEdit.setRatioSelection(<?php echo $post_id; ?>, 0, this)" />
					<span class="imgedit-separator" aria-hidden="true">:</span>
					<label for="imgedit-crop-height-<?php echo $post_id; ?>" class="screen-reader-text">
					<?php
					/* translators: Hidden accessibility text. */
					_e( 'crop ratio height' );
					?>
					</label>
					<input  type="number" step="1" min="0" id="imgedit-crop-height-<?php echo $post_id; ?>" onkeyup="imageEdit.setRatioSelection(<?php echo $post_id; ?>, 1, this)" onblur="imageEdit.setRatioSelection(<?php echo $post_id; ?>, 1, this)" />
					</div>
				</fieldset>
				<fieldset id="imgedit-crop-sel-<?php echo $post_id; ?>" class="imgedit-crop-sel">
					<legend><?php _e( 'Selection:' ); ?></legend>
					<div class="nowrap">
					<label for="imgedit-sel-width-<?php echo $post_id; ?>" class="screen-reader-text">
					<?php
					/* translators: Hidden accessibility text. */
					_e( 'selection width' );
					?>
					</label>
					<input  type="number" step="1" min="0" id="imgedit-sel-width-<?php echo $post_id; ?>" onkeyup="imageEdit.setNumSelection(<?php echo $post_id; ?>, this)" onblur="imageEdit.setNumSelection(<?php echo $post_id; ?>, this)" />
					<span class="imgedit-separator" aria-hidden="true">&times;</span>
					<label for="imgedit-sel-height-<?php echo $post_id; ?>" class="screen-reader-text">
					<?php
					/* translators: Hidden accessibility text. */
					_e( 'selection height' );
					?>
					</label>
					<input  type="number" step="1" min="0" id="imgedit-sel-height-<?php echo $post_id; ?>" onkeyup="imageEdit.setNumSelection(<?php echo $post_id; ?>, this)" onblur="imageEdit.setNumSelection(<?php echo $post_id; ?>, this)" />
					</div>
				</fieldset>
				<fieldset id="imgedit-crop-sel-<?php echo $post_id; ?>" class="imgedit-crop-sel">
					<legend><?php _e( 'Starting Coordinates:' ); ?></legend>
					<div class="nowrap">
					<label for="imgedit-start-x-<?php echo $post_id; ?>" class="screen-reader-text">
					<?php
					/* translators: Hidden accessibility text. */
					_e( 'horizontal start position' );
					?>
					</label>
					<input  type="number" step="1" min="0" id="imgedit-start-x-<?php echo $post_id; ?>" onkeyup="imageEdit.setNumSelection(<?php echo $post_id; ?>, this)" onblur="imageEdit.setNumSelection(<?php echo $post_id; ?>, this)" value="0" />
					<span class="imgedit-separator" aria-hidden="true">&times;</span>
					<label for="imgedit-start-y-<?php echo $post_id; ?>" class="screen-reader-text">
					<?php
					/* translators: Hidden accessibility text. */
					_e( 'vertical start position' );
					?>
					</label>
					<input  type="number" step="1" min="0" id="imgedit-start-y-<?php echo $post_id; ?>" onkeyup="imageEdit.setNumSelection(<?php echo $post_id; ?>, this)" onblur="imageEdit.setNumSelection(<?php echo $post_id; ?>, this)" value="0" />
					</div>
				</fieldset>
				<div class="imgedit-crop-apply imgedit-menu container">
					<button class="button button-primary" type="button" onclick="imageEdit.handleCropToolClick( <?php echo "$post_id, '$nonce'"; ?>, this );" class="imgedit-crop-apply button"><?php esc_html_e( 'Apply Crop' ); ?></button> <button type="button" onclick="imageEdit.handleCropToolClick( <?php echo "$post_id, '$nonce'"; ?>, this );" class="imgedit-crop-clear button" disabled="disabled"><?php esc_html_e( 'Clear Crop' ); ?></button>
				</div>
			</div>
		</div>
	</div>

	<?php
	if ( $edit_thumbnails_separately && $thumb && $sub_sizes ) {
		$thumb_img = wp_constrain_dimensions( $thumb['width'], $thumb['height'], 160, 120 );
		?>

	<div class="imgedit-group imgedit-applyto">
		<div class="imgedit-group-top">
			<h2><?php _e( 'Thumbnail Settings' ); ?></h2>
			<button type="button" class="dashicons dashicons-editor-help imgedit-help-toggle" onclick="imageEdit.toggleHelp(this);" aria-expanded="false"><span class="screen-reader-text">
			<?php
			/* translators: Hidden accessibility text. */
			esc_html_e( 'Thumbnail Settings Help' );
			?>
			</span></button>
			<div class="imgedit-help">
			<p><?php _e( 'You can edit the image while preserving the thumbnail. For example, you may wish to have a square thumbnail that displays just a section of the image.' ); ?></p>
			</div>
		</div>
		<div class="imgedit-thumbnail-preview-group">
			<figure class="imgedit-thumbnail-preview">
				<img src="<?php echo esc_url( $thumb['url'] ); ?>" width="<?php echo esc_attr( $thumb_img[0] ); ?>" height="<?php echo esc_attr( $thumb_img[1] ); ?>" class="imgedit-size-preview" alt="" draggable="false" />
				<figcaption class="imgedit-thumbnail-preview-caption"><?php _e( 'Current thumbnail' ); ?></figcaption>
			</figure>
			<div id="imgedit-save-target-<?php echo $post_id; ?>" class="imgedit-save-target">
			<fieldset>
				<legend><?php _e( 'Apply changes to:' ); ?></legend>

				<span class="imgedit-label">
					<input type="radio" id="imgedit-target-all" name="imgedit-target-<?php echo $post_id; ?>" value="all" checked="checked" />
					<label for="imgedit-target-all"><?php _e( 'All image sizes' ); ?></label>
				</span>

				<span class="imgedit-label">
					<input type="radio" id="imgedit-target-thumbnail" name="imgedit-target-<?php echo $post_id; ?>" value="thumbnail" />
					<label for="imgedit-target-thumbnail"><?php _e( 'Thumbnail' ); ?></label>
				</span>

				<span class="imgedit-label">
					<input type="radio" id="imgedit-target-nothumb" name="imgedit-target-<?php echo $post_id; ?>" value="nothumb" />
					<label for="imgedit-target-nothumb"><?php _e( 'All sizes except thumbnail' ); ?></label>
				</span>

				</fieldset>
			</div>
		</div>
	</div>
	<?php } ?>
		</div>
	</div>

	</div>

	<div class="imgedit-wait" id="imgedit-wait-<?php echo $post_id; ?>"></div>
	<div class="hidden" id="imgedit-leaving-<?php echo $post_id; ?>"><?php _e( "There are unsaved changes that will be lost. 'OK' to continue, 'Cancel' to return to the Image Editor." ); ?></div>
	</div>
	<?php
}

/**
 * Streams image in WP_Image_Editor to browser.
 *
 * @since 2.9.0
 *
 * @param WP_Image_Editor $image         The image editor instance.
 * @param string          $mime_type     The mime type of the image.
 * @param int             $attachment_id The image's attachment post ID.
 * @return bool True on success, false on failure.
 */
function wp_stream_image( $image, $mime_type, $attachment_id ) {
	if ( $image instanceof WP_Image_Editor ) {

		/**
		 * Filters the WP_Image_Editor instance for the image to be streamed to the browser.
		 *
		 * @since 3.5.0
		 *
		 * @param WP_Image_Editor $image         The image editor instance.
		 * @param int             $attachment_id The attachment post ID.
		 */
		$image = apply_filters( 'image_editor_save_pre', $image, $attachment_id );

		if ( is_wp_error( $image->stream( $mime_type ) ) ) {
			return false;
		}

		return true;
	} else {
		/* translators: 1: $image, 2: WP_Image_Editor */
		_deprecated_argument( __FUNCTION__, '3.5.0', sprintf( __( '%1$s needs to be a %2$s object.' ), '$image', 'WP_Image_Editor' ) );

		/**
		 * Filters the GD image resource to be streamed to the browser.
		 *
		 * @since 2.9.0
		 * @deprecated 3.5.0 Use {@see 'image_editor_save_pre'} instead.
		 *
		 * @param resource|GdImage $image         Image resource to be streamed.
		 * @param int              $attachment_id The attachment post ID.
		 */
		$image = apply_filters_deprecated( 'image_save_pre', array( $image, $attachment_id ), '3.5.0', 'image_editor_save_pre' );

		switch ( $mime_type ) {
			case 'image/jpeg':
				header( 'Content-Type: image/jpeg' );
				return imagejpeg( $image, null, 90 );
			case 'image/png':
				header( 'Content-Type: image/png' );
				return imagepng( $image );
			case 'image/gif':
				header( 'Content-Type: image/gif' );
				return imagegif( $image );
			case 'image/webp':
				if ( function_exists( 'imagewebp' ) ) {
					header( 'Content-Type: image/webp' );
					return imagewebp( $image, null, 90 );
				}
				return false;
			case 'image/avif':
				if ( function_exists( 'imageavif' ) ) {
					header( 'Content-Type: image/avif' );
					return imageavif( $image, null, 90 );
				}
				return false;
			default:
				return false;
		}
	}
}

/**
 * Saves image to file.
 *
 * @since 2.9.0
 * @since 3.5.0 The `$image` parameter expects a `WP_Image_Editor` instance.
 * @since 6.0.0 The `$filesize` value was added to the returned array.
 *
 * @param string          $filename  Name of the file to be saved.
 * @param WP_Image_Editor $image     The image editor instance.
 * @param string          $mime_type The mime type of the image.
 * @param int             $post_id   Attachment post ID.
 * @return array|WP_Error|bool {
 *     Array on success or WP_Error if the file failed to save.
 *     When called with a deprecated value for the `$image` parameter,
 *     i.e. a non-`WP_Image_Editor` image resource or `GdImage` instance,
 *     the function will return true on success, false on failure.
 *
 *     @type string $path      Path to the image file.
 *     @type string $file      Name of the image file.
 *     @type int    $width     Image width.
 *     @type int    $height    Image height.
 *     @type string $mime-type The mime type of the image.
 *     @type int    $filesize  File size of the image.
 * }
 */
function wp_save_image_file( $filename, $image, $mime_type, $post_id ) {
	if ( $image instanceof WP_Image_Editor ) {

		/** This filter is documented in wp-admin/includes/image-edit.php */
		$image = apply_filters( 'image_editor_save_pre', $image, $post_id );

		/**
		 * Filters whether to skip saving the image file.
		 *
		 * Returning a non-null value will short-circuit the save method,
		 * returning that value instead.
		 *
		 * @since 3.5.0
		 *
		 * @param bool|null       $override  Value to return instead of saving. Default null.
		 * @param string          $filename  Name of the file to be saved.
		 * @param WP_Image_Editor $image     The image editor instance.
		 * @param string          $mime_type The mime type of the image.
		 * @param int             $post_id   Attachment post ID.
		 */
		$saved = apply_filters( 'wp_save_image_editor_file', null, $filename, $image, $mime_type, $post_id );

		if ( null !== $saved ) {
			return $saved;
		}

		return $image->save( $filename, $mime_type );
	} else {
		/* translators: 1: $image, 2: WP_Image_Editor */
		_deprecated_argument( __FUNCTION__, '3.5.0', sprintf( __( '%1$s needs to be a %2$s object.' ), '$image', 'WP_Image_Editor' ) );

		/** This filter is documented in wp-admin/includes/image-edit.php */
		$image = apply_filters_deprecated( 'image_save_pre', array( $image, $post_id ), '3.5.0', 'image_editor_save_pre' );

		/**
		 * Filters whether to skip saving the image file.
		 *
		 * Returning a non-null value will short-circuit the save method,
		 * returning that value instead.
		 *
		 * @since 2.9.0
		 * @deprecated 3.5.0 Use {@see 'wp_save_image_editor_file'} instead.
		 *
		 * @param bool|null        $override  Value to return instead of saving. Default null.
		 * @param string           $filename  Name of the file to be saved.
		 * @param resource|GdImage $image     Image resource or GdImage instance.
		 * @param string           $mime_type The mime type of the image.
		 * @param int              $post_id   Attachment post ID.
		 */
		$saved = apply_filters_deprecated(
			'wp_save_image_file',
			array( null, $filename, $image, $mime_type, $post_id ),
			'3.5.0',
			'wp_save_image_editor_file'
		);

		if ( null !== $saved ) {
			return $saved;
		}

		switch ( $mime_type ) {
			case 'image/jpeg':
				/** This filter is documented in wp-includes/class-wp-image-editor.php */
				return imagejpeg( $image, $filename, apply_filters( 'jpeg_quality', 90, 'edit_image' ) );
			case 'image/png':
				return imagepng( $image, $filename );
			case 'image/gif':
				return imagegif( $image, $filename );
			case 'image/webp':
				if ( function_exists( 'imagewebp' ) ) {
					return imagewebp( $image, $filename );
				}
				return false;
			case 'image/avif':
				if ( function_exists( 'imageavif' ) ) {
					return imageavif( $image, $filename );
				}
				return false;
			default:
				return false;
		}
	}
}

/**
 * Image preview ratio. Internal use only.
 *
 * @since 2.9.0
 *
 * @ignore
 * @param int $w Image width in pixels.
 * @param int $h Image height in pixels.
 * @return float|int Image preview ratio.
 */
function _image_get_preview_ratio( $w, $h ) {
	$max = max( $w, $h );
	return $max > 600 ? ( 600 / $max ) : 1;
}

/**
 * Returns an image resource. Internal use only.
 *
 * @since 2.9.0
 * @deprecated 3.5.0 Use WP_Image_Editor::rotate()
 * @see WP_Image_Editor::rotate()
 *
 * @ignore
 * @param resource|GdImage $img   Image resource.
 * @param float|int        $angle Image rotation angle, in degrees.
 * @return resource|GdImage|false GD image resource or GdImage instance, false otherwise.
 */
function _rotate_image_resource( $img, $angle ) {
	_deprecated_function( __FUNCTION__, '3.5.0', 'WP_Image_Editor::rotate()' );

	if ( function_exists( 'imagerotate' ) ) {
		$rotated = imagerotate( $img, $angle, 0 );

		if ( is_gd_image( $rotated ) ) {
			if ( PHP_VERSION_ID < 80000 ) { // imagedestroy() has no effect as of PHP 8.0.
				imagedestroy( $img );
			}

			$img = $rotated;
		}
	}

	return $img;
}

/**
 * Flips an image resource. Internal use only.
 *
 * @since 2.9.0
 * @deprecated 3.5.0 Use WP_Image_Editor::flip()
 * @see WP_Image_Editor::flip()
 *
 * @ignore
 * @param resource|GdImage $img  Image resource or GdImage instance.
 * @param bool             $horz Whether to flip horizontally.
 * @param bool             $vert Whether to flip vertically.
 * @return resource|GdImage (maybe) flipped image resource or GdImage instance.
 */
function _flip_image_resource( $img, $horz, $vert ) {
	_deprecated_function( __FUNCTION__, '3.5.0', 'WP_Image_Editor::flip()' );

	$w   = imagesx( $img );
	$h   = imagesy( $img );
	$dst = wp_imagecreatetruecolor( $w, $h );

	if ( is_gd_image( $dst ) ) {
		$sx = $vert ? ( $w - 1 ) : 0;
		$sy = $horz ? ( $h - 1 ) : 0;
		$sw = $vert ? -$w : $w;
		$sh = $horz ? -$h : $h;

		if ( imagecopyresampled( $dst, $img, 0, 0, $sx, $sy, $w, $h, $sw, $sh ) ) {
			if ( PHP_VERSION_ID < 80000 ) { // imagedestroy() has no effect as of PHP 8.0.
				imagedestroy( $img );
			}

			$img = $dst;
		}
	}

	return $img;
}

/**
 * Crops an image resource. Internal use only.
 *
 * @since 2.9.0
 *
 * @ignore
 * @param resource|GdImage $img Image resource or GdImage instance.
 * @param float            $x   Source point x-coordinate.
 * @param float            $y   Source point y-coordinate.
 * @param float            $w   Source width.
 * @param float            $h   Source height.
 * @return resource|GdImage (maybe) cropped image resource or GdImage instance.
 */
function _crop_image_resource( $img, $x, $y, $w, $h ) {
	$dst = wp_imagecreatetruecolor( $w, $h );

	if ( is_gd_image( $dst ) ) {
		if ( imagecopy( $dst, $img, 0, 0, $x, $y, $w, $h ) ) {
			if ( PHP_VERSION_ID < 80000 ) { // imagedestroy() has no effect as of PHP 8.0.
				imagedestroy( $img );
			}

			$img = $dst;
		}
	}

	return $img;
}

/**
 * Performs group of changes on Editor specified.
 *
 * @since 2.9.0
 *
 * @param WP_Image_Editor $image   WP_Image_Editor instance.
 * @param array           $changes Array of change operations.
 * @return WP_Image_Editor WP_Image_Editor instance with changes applied.
 */
function image_edit_apply_changes( $image, $changes ) {
	if ( is_gd_image( $image ) ) {
		/* translators: 1: $image, 2: WP_Image_Editor */
		_deprecated_argument( __FUNCTION__, '3.5.0', sprintf( __( '%1$s needs to be a %2$s object.' ), '$image', 'WP_Image_Editor' ) );
	}

	if ( ! is_array( $changes ) ) {
		return $image;
	}

	// Expand change operations.
	foreach ( $changes as $key => $obj ) {
		if ( isset( $obj->r ) ) {
			$obj->type  = 'rotate';
			$obj->angle = $obj->r;
			unset( $obj->r );
		} elseif ( isset( $obj->f ) ) {
			$obj->type = 'flip';
			$obj->axis = $obj->f;
			unset( $obj->f );
		} elseif ( isset( $obj->c ) ) {
			$obj->type = 'crop';
			$obj->sel  = $obj->c;
			unset( $obj->c );
		}

		$changes[ $key ] = $obj;
	}

	// Combine operations.
	if ( count( $changes ) > 1 ) {
		$filtered = array( $changes[0] );

		for ( $i = 0, $j = 1, $c = count( $changes ); $j < $c; $j++ ) {
			$combined = false;

			if ( $filtered[ $i ]->type === $changes[ $j ]->type ) {
				switch ( $filtered[ $i ]->type ) {
					case 'rotate':
						$filtered[ $i ]->angle += $changes[ $j ]->angle;
						$combined               = true;
						break;
					case 'flip':
						$filtered[ $i ]->axis ^= $changes[ $j ]->axis;
						$combined              = true;
						break;
				}
			}

			if ( ! $combined ) {
				$filtered[ ++$i ] = $changes[ $j ];
			}
		}

		$changes = $filtered;
		unset( $filtered );
	}

	// Image resource before applying the changes.
	if ( $image instanceof WP_Image_Editor ) {

		/**
		 * Filters the WP_Image_Editor instance before applying changes to the image.
		 *
		 * @since 3.5.0
		 *
		 * @param WP_Image_Editor $image   WP_Image_Editor instance.
		 * @param array           $changes Array of change operations.
		 */
		$image = apply_filters( 'wp_image_editor_before_change', $image, $changes );
	} elseif ( is_gd_image( $image ) ) {

		/**
		 * Filters the GD image resource before applying changes to the image.
		 *
		 * @since 2.9.0
		 * @deprecated 3.5.0 Use {@see 'wp_image_editor_before_change'} instead.
		 *
		 * @param resource|GdImage $image   GD image resource or GdImage instance.
		 * @param array            $changes Array of change operations.
		 */
		$image = apply_filters_deprecated( 'image_edit_before_change', array( $image, $changes ), '3.5.0', 'wp_image_editor_before_change' );
	}

	foreach ( $changes as $operation ) {
		switch ( $operation->type ) {
			case 'rotate':
				if ( 0 !== $operation->angle ) {
					if ( $image instanceof WP_Image_Editor ) {
						$image->rotate( $operation->angle );
					} else {
						$image = _rotate_image_resource( $image, $operation->angle );
					}
				}
				break;
			case 'flip':
				if ( 0 !== $operation->axis ) {
					if ( $image instanceof WP_Image_Editor ) {
						$image->flip( ( $operation->axis & 1 ) !== 0, ( $operation->axis & 2 ) !== 0 );
					} else {
						$image = _flip_image_resource( $image, ( $operation->axis & 1 ) !== 0, ( $operation->axis & 2 ) !== 0 );
					}
				}
				break;
			case 'crop':
				$sel = $operation->sel;

				if ( $image instanceof WP_Image_Editor ) {
					$size = $image->get_size();
					$w    = $size['width'];
					$h    = $size['height'];

					$scale = isset( $sel->r ) ? $sel->r : 1 / _image_get_preview_ratio( $w, $h ); // Discard preview scaling.
					$image->crop( (int) ( $sel->x * $scale ), (int) ( $sel->y * $scale ), (int) ( $sel->w * $scale ), (int) ( $sel->h * $scale ) );
				} else {
					$scale = isset( $sel->r ) ? $sel->r : 1 / _image_get_preview_ratio( imagesx( $image ), imagesy( $image ) ); // Discard preview scaling.
					$image = _crop_image_resource( $image, $sel->x * $scale, $sel->y * $scale, $sel->w * $scale, $sel->h * $scale );
				}
				break;
		}
	}

	return $image;
}


/**
 * Streams image in post to browser, along with enqueued changes
 * in `$_REQUEST['history']`.
 *
 * @since 2.9.0
 *
 * @param int $post_id Attachment post ID.
 * @return bool True on success, false on failure.
 */
function stream_preview_image( $post_id ) {
	$post = get_post( $post_id );

	wp_raise_memory_limit( 'admin' );

	$img = wp_get_image_editor( _load_image_to_edit_path( $post_id ) );

	if ( is_wp_error( $img ) ) {
		return false;
	}

	$changes = ! empty( $_REQUEST['history'] ) ? json_decode( wp_unslash( $_REQUEST['history'] ) ) : null;
	if ( $changes ) {
		$img = image_edit_apply_changes( $img, $changes );
	}

	// Scale the image.
	$size = $img->get_size();
	$w    = $size['width'];
	$h    = $size['height'];

	$ratio = _image_get_preview_ratio( $w, $h );
	$w2    = max( 1, $w * $ratio );
	$h2    = max( 1, $h * $ratio );

	if ( is_wp_error( $img->resize( $w2, $h2 ) ) ) {
		return false;
	}

	return wp_stream_image( $img, $post->post_mime_type, $post_id );
}

/**
 * Restores the metadata for a given attachment.
 *
 * @since 2.9.0
 *
 * @param int $post_id Attachment post ID.
 * @return stdClass Image restoration message object.
 */
function wp_restore_image( $post_id ) {
	$meta             = wp_get_attachment_metadata( $post_id );
	$file             = get_attached_file( $post_id );
	$backup_sizes     = get_post_meta( $post_id, '_wp_attachment_backup_sizes', true );
	$old_backup_sizes = $backup_sizes;
	$restored         = false;
	$msg              = new stdClass();

	if ( ! is_array( $backup_sizes ) ) {
		$msg->error = __( 'Cannot load image metadata.' );
		return $msg;
	}

	$parts         = pathinfo( $file );
	$suffix        = time() . rand( 100, 999 );
	$default_sizes = get_intermediate_image_sizes();

	if ( isset( $backup_sizes['full-orig'] ) && is_array( $backup_sizes['full-orig'] ) ) {
		$data = $backup_sizes['full-orig'];

		if ( $parts['basename'] !== $data['file'] ) {
			if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE ) {
				// Delete only if it's an edited image.
				if ( preg_match( '/-e[0-9]{13}\./', $parts['basename'] ) ) {
					wp_delete_file( $file );
				}
			} elseif ( isset( $meta['width'], $meta['height'] ) ) {
				$backup_sizes[ "full-$suffix" ] = array(
					'width'    => $meta['width'],
					'height'   => $meta['height'],
					'filesize' => $meta['filesize'],
					'file'     => $parts['basename'],
				);
			}
		}

		$restored_file = path_join( $parts['dirname'], $data['file'] );
		$restored      = update_attached_file( $post_id, $restored_file );

		$meta['file']   = _wp_relative_upload_path( $restored_file );
		$meta['width']  = $data['width'];
		$meta['height'] = $data['height'];
		if ( isset( $data['filesize'] ) ) {
			/*
			 * Restore the original filesize if it was backed up.
			 *
			 * See https://core.trac.wordpress.org/ticket/59684.
			 */
			$meta['filesize'] = $data['filesize'];
		}
	}

	foreach ( $default_sizes as $default_size ) {
		if ( isset( $backup_sizes[ "$default_size-orig" ] ) ) {
			$data = $backup_sizes[ "$default_size-orig" ];

			if ( isset( $meta['sizes'][ $default_size ] ) && $meta['sizes'][ $default_size ]['file'] !== $data['file'] ) {
				if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE ) {
					// Delete only if it's an edited image.
					if ( preg_match( '/-e[0-9]{13}-/', $meta['sizes'][ $default_size ]['file'] ) ) {
						$delete_file = path_join( $parts['dirname'], $meta['sizes'][ $default_size ]['file'] );
						wp_delete_file( $delete_file );
					}
				} else {
					$backup_sizes[ "$default_size-{$suffix}" ] = $meta['sizes'][ $default_size ];
				}
			}

			$meta['sizes'][ $default_size ] = $data;
		} else {
			unset( $meta['sizes'][ $default_size ] );
		}
	}

	if ( ! wp_update_attachment_metadata( $post_id, $meta )
		|| ( $old_backup_sizes !== $backup_sizes && ! update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes ) )
	) {
		$msg->error = __( 'Cannot save image metadata.' );
		return $msg;
	}

	if ( ! $restored ) {
		$msg->error = __( 'Image metadata is inconsistent.' );
	} else {
		$msg->msg = __( 'Image restored successfully.' );

		if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE ) {
			delete_post_meta( $post_id, '_wp_attachment_backup_sizes' );
		}
	}

	return $msg;
}

/**
 * Saves image to post, along with enqueued changes
 * in `$_REQUEST['history']`.
 *
 * @since 2.9.0
 *
 * @param int $post_id Attachment post ID.
 * @return stdClass
 */
function wp_save_image( $post_id ) {
	$_wp_additional_image_sizes = wp_get_additional_image_sizes();

	$return  = new stdClass();
	$success = false;
	$delete  = false;
	$scaled  = false;
	$nocrop  = false;
	$post    = get_post( $post_id );

	$img = wp_get_image_editor( _load_image_to_edit_path( $post_id, 'full' ) );

	if ( is_wp_error( $img ) ) {
		$return->error = esc_js( __( 'Unable to create new image.' ) );
		return $return;
	}

	$full_width  = ! empty( $_REQUEST['fwidth'] ) ? (int) $_REQUEST['fwidth'] : 0;
	$full_height = ! empty( $_REQUEST['fheight'] ) ? (int) $_REQUEST['fheight'] : 0;
	$target      = ! empty( $_REQUEST['target'] ) ? preg_replace( '/[^a-z0-9_-]+/i', '', $_REQUEST['target'] ) : '';
	$scale       = ! empty( $_REQUEST['do'] ) && 'scale' === $_REQUEST['do'];

	/** This filter is documented in wp-admin/includes/image-edit.php */
	$edit_thumbnails_separately = (bool) apply_filters( 'image_edit_thumbnails_separately', false );

	if ( $scale ) {
		$size            = $img->get_size();
		$original_width  = $size['width'];
		$original_height = $size['height'];

		if ( $full_width > $original_width || $full_height > $original_height ) {
			$return->error = esc_js( __( 'Images cannot be scaled to a size larger than the original.' ) );
			return $return;
		}

		if ( $full_width > 0 && $full_height > 0 ) {
			// Check if it has roughly the same w / h ratio.
			$diff = round( $original_width / $original_height, 2 ) - round( $full_width / $full_height, 2 );
			if ( -0.1 < $diff && $diff < 0.1 ) {
				// Scale the full size image.
				if ( $img->resize( $full_width, $full_height ) ) {
					$scaled = true;
				}
			}

			if ( ! $scaled ) {
				$return->error = esc_js( __( 'Error while saving the scaled image. Please reload the page and try again.' ) );
				return $return;
			}
		}
	} elseif ( ! empty( $_REQUEST['history'] ) ) {
		$changes = json_decode( wp_unslash( $_REQUEST['history'] ) );
		if ( $changes ) {
			$img = image_edit_apply_changes( $img, $changes );
		}
	} else {
		$return->error = esc_js( __( 'Nothing to save, the image has not changed.' ) );
		return $return;
	}

	$meta         = wp_get_attachment_metadata( $post_id );
	$backup_sizes = get_post_meta( $post->ID, '_wp_attachment_backup_sizes', true );

	if ( ! is_array( $meta ) ) {
		$return->error = esc_js( __( 'Image data does not exist. Please re-upload the image.' ) );
		return $return;
	}

	if ( ! is_array( $backup_sizes ) ) {
		$backup_sizes = array();
	}

	// Generate new filename.
	$path = get_attached_file( $post_id );

	$basename = pathinfo( $path, PATHINFO_BASENAME );
	$dirname  = pathinfo( $path, PATHINFO_DIRNAME );
	$ext      = pathinfo( $path, PATHINFO_EXTENSION );
	$filename = pathinfo( $path, PATHINFO_FILENAME );
	$suffix   = time() . rand( 100, 999 );

	if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE
		&& isset( $backup_sizes['full-orig'] ) && $backup_sizes['full-orig']['file'] !== $basename
	) {

		if ( $edit_thumbnails_separately && 'thumbnail' === $target ) {
			$new_path = "{$dirname}/{$filename}-temp.{$ext}";
		} else {
			$new_path = $path;
		}
	} else {
		while ( true ) {
			$filename     = preg_replace( '/-e([0-9]+)$/', '', $filename );
			$filename    .= "-e{$suffix}";
			$new_filename = "{$filename}.{$ext}";
			$new_path     = "{$dirname}/$new_filename";

			if ( file_exists( $new_path ) ) {
				++$suffix;
			} else {
				break;
			}
		}
	}

	$saved_image = wp_save_image_file( $new_path, $img, $post->post_mime_type, $post_id );
	// Save the full-size file, also needed to create sub-sizes.
	if ( ! $saved_image ) {
		$return->error = esc_js( __( 'Unable to save the image.' ) );
		return $return;
	}

	if ( 'nothumb' === $target || 'all' === $target || 'full' === $target || $scaled ) {
		$tag = false;

		if ( isset( $backup_sizes['full-orig'] ) ) {
			if ( ( ! defined( 'IMAGE_EDIT_OVERWRITE' ) || ! IMAGE_EDIT_OVERWRITE )
				&& $backup_sizes['full-orig']['file'] !== $basename
			) {
				$tag = "full-$suffix";
			}
		} else {
			$tag = 'full-orig';
		}

		if ( $tag ) {
			$backup_sizes[ $tag ] = array(
				'width'    => $meta['width'],
				'height'   => $meta['height'],
				'filesize' => $meta['filesize'],
				'file'     => $basename,
			);
		}

		$success = ( $path === $new_path ) || update_attached_file( $post_id, $new_path );

		$meta['file'] = _wp_relative_upload_path( $new_path );

		$size             = $img->get_size();
		$meta['width']    = $size['width'];
		$meta['height']   = $size['height'];
		$meta['filesize'] = $saved_image['filesize'];

		if ( $success && ( 'nothumb' === $target || 'all' === $target ) ) {
			$sizes = get_intermediate_image_sizes();

			if ( $edit_thumbnails_separately && 'nothumb' === $target ) {
				$sizes = array_diff( $sizes, array( 'thumbnail' ) );
			}
		}

		$return->fw = $meta['width'];
		$return->fh = $meta['height'];
	} elseif ( $edit_thumbnails_separately && 'thumbnail' === $target ) {
		$sizes   = array( 'thumbnail' );
		$success = true;
		$delete  = true;
		$nocrop  = true;
	}

	/*
	 * We need to remove any existing resized image files because
	 * a new crop or rotate could generate different sizes (and hence, filenames),
	 * keeping the new resized images from overwriting the existing image files.
	 * https://core.trac.wordpress.org/ticket/32171
	 */
	if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE && ! empty( $meta['sizes'] ) ) {
		foreach ( $meta['sizes'] as $size ) {
			if ( ! empty( $size['file'] ) && preg_match( '/-e[0-9]{13}-/', $size['file'] ) ) {
				$delete_file = path_join( $dirname, $size['file'] );
				wp_delete_file( $delete_file );
			}
		}
	}

	if ( isset( $sizes ) ) {
		$_sizes = array();

		foreach ( $sizes as $size ) {
			$tag = false;

			if ( isset( $meta['sizes'][ $size ] ) ) {
				if ( isset( $backup_sizes[ "$size-orig" ] ) ) {
					if ( ( ! defined( 'IMAGE_EDIT_OVERWRITE' ) || ! IMAGE_EDIT_OVERWRITE )
						&& $backup_sizes[ "$size-orig" ]['file'] !== $meta['sizes'][ $size ]['file']
					) {
						$tag = "$size-$suffix";
					}
				} else {
					$tag = "$size-orig";
				}

				if ( $tag ) {
					$backup_sizes[ $tag ] = $meta['sizes'][ $size ];
				}
			}

			if ( isset( $_wp_additional_image_sizes[ $size ] ) ) {
				$width  = (int) $_wp_additional_image_sizes[ $size ]['width'];
				$height = (int) $_wp_additional_image_sizes[ $size ]['height'];
				$crop   = ( $nocrop ) ? false : $_wp_additional_image_sizes[ $size ]['crop'];
			} else {
				$height = get_option( "{$size}_size_h" );
				$width  = get_option( "{$size}_size_w" );
				$crop   = ( $nocrop ) ? false : get_option( "{$size}_crop" );
			}

			$_sizes[ $size ] = array(
				'width'  => $width,
				'height' => $height,
				'crop'   => $crop,
			);
		}

		$meta['sizes'] = array_merge( $meta['sizes'], $img->multi_resize( $_sizes ) );
	}

	unset( $img );

	if ( $success ) {
		wp_update_attachment_metadata( $post_id, $meta );
		update_post_meta( $post_id, '_wp_attachment_backup_sizes', $backup_sizes );

		if ( 'thumbnail' === $target || 'all' === $target || 'full' === $target ) {
			// Check if it's an image edit from attachment edit screen.
			if ( ! empty( $_REQUEST['context'] ) && 'edit-attachment' === $_REQUEST['context'] ) {
				$thumb_url = wp_get_attachment_image_src( $post_id, array( 900, 600 ), true );

				$return->thumbnail = $thumb_url[0];
			} else {
				$file_url = wp_get_attachment_url( $post_id );

				if ( ! empty( $meta['sizes']['thumbnail'] ) ) {
					$thumb             = $meta['sizes']['thumbnail'];
					$return->thumbnail = path_join( dirname( $file_url ), $thumb['file'] );
				} else {
					$return->thumbnail = "$file_url?w=128&h=128";
				}
			}
		}
	} else {
		$delete = true;
	}

	if ( $delete ) {
		wp_delete_file( $new_path );
	}

	$return->msg = esc_js( __( 'Image saved' ) );

	return $return;
}
theme.php000064400000135176151212616040006372 0ustar00<?php
/**
 * WordPress Theme Administration API
 *
 * @package WordPress
 * @subpackage Administration
 */

/**
 * Removes a theme.
 *
 * @since 2.8.0
 *
 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
 *
 * @param string $stylesheet Stylesheet of the theme to delete.
 * @param string $redirect   Redirect to page when complete.
 * @return bool|null|WP_Error True on success, false if `$stylesheet` is empty, WP_Error on failure.
 *                            Null if filesystem credentials are required to proceed.
 */
function delete_theme( $stylesheet, $redirect = '' ) {
	global $wp_filesystem;

	if ( empty( $stylesheet ) ) {
		return false;
	}

	if ( empty( $redirect ) ) {
		$redirect = wp_nonce_url( 'themes.php?action=delete&stylesheet=' . urlencode( $stylesheet ), 'delete-theme_' . $stylesheet );
	}

	ob_start();
	$credentials = request_filesystem_credentials( $redirect );
	$data        = ob_get_clean();

	if ( false === $credentials ) {
		if ( ! empty( $data ) ) {
			require_once ABSPATH . 'wp-admin/admin-header.php';
			echo $data;
			require_once ABSPATH . 'wp-admin/admin-footer.php';
			exit;
		}
		return;
	}

	if ( ! WP_Filesystem( $credentials ) ) {
		ob_start();
		// Failed to connect. Error and request again.
		request_filesystem_credentials( $redirect, '', true );
		$data = ob_get_clean();

		if ( ! empty( $data ) ) {
			require_once ABSPATH . 'wp-admin/admin-header.php';
			echo $data;
			require_once ABSPATH . 'wp-admin/admin-footer.php';
			exit;
		}
		return;
	}

	if ( ! is_object( $wp_filesystem ) ) {
		return new WP_Error( 'fs_unavailable', __( 'Could not access filesystem.' ) );
	}

	if ( is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->has_errors() ) {
		return new WP_Error( 'fs_error', __( 'Filesystem error.' ), $wp_filesystem->errors );
	}

	// Get the base theme folder.
	$themes_dir = $wp_filesystem->wp_themes_dir();
	if ( empty( $themes_dir ) ) {
		return new WP_Error( 'fs_no_themes_dir', __( 'Unable to locate WordPress theme directory.' ) );
	}

	/**
	 * Fires immediately before a theme deletion attempt.
	 *
	 * @since 5.8.0
	 *
	 * @param string $stylesheet Stylesheet of the theme to delete.
	 */
	do_action( 'delete_theme', $stylesheet );

	$theme = wp_get_theme( $stylesheet );

	$themes_dir = trailingslashit( $themes_dir );
	$theme_dir  = trailingslashit( $themes_dir . $stylesheet );
	$deleted    = $wp_filesystem->delete( $theme_dir, true );

	/**
	 * Fires immediately after a theme deletion attempt.
	 *
	 * @since 5.8.0
	 *
	 * @param string $stylesheet Stylesheet of the theme to delete.
	 * @param bool   $deleted    Whether the theme deletion was successful.
	 */
	do_action( 'deleted_theme', $stylesheet, $deleted );

	if ( ! $deleted ) {
		return new WP_Error(
			'could_not_remove_theme',
			/* translators: %s: Theme name. */
			sprintf( __( 'Could not fully remove the theme %s.' ), $stylesheet )
		);
	}

	$theme_translations = wp_get_installed_translations( 'themes' );

	// Remove language files, silently.
	if ( ! empty( $theme_translations[ $stylesheet ] ) ) {
		$translations = $theme_translations[ $stylesheet ];

		foreach ( $translations as $translation => $data ) {
			$wp_filesystem->delete( WP_LANG_DIR . '/themes/' . $stylesheet . '-' . $translation . '.po' );
			$wp_filesystem->delete( WP_LANG_DIR . '/themes/' . $stylesheet . '-' . $translation . '.mo' );
			$wp_filesystem->delete( WP_LANG_DIR . '/themes/' . $stylesheet . '-' . $translation . '.l10n.php' );

			$json_translation_files = glob( WP_LANG_DIR . '/themes/' . $stylesheet . '-' . $translation . '-*.json' );
			if ( $json_translation_files ) {
				array_map( array( $wp_filesystem, 'delete' ), $json_translation_files );
			}
		}
	}

	// Remove the theme from allowed themes on the network.
	if ( is_multisite() ) {
		WP_Theme::network_disable_theme( $stylesheet );
	}

	// Clear theme caches.
	$theme->cache_delete();

	// Force refresh of theme update information.
	delete_site_transient( 'update_themes' );

	return true;
}

/**
 * Gets the page templates available in this theme.
 *
 * @since 1.5.0
 * @since 4.7.0 Added the `$post_type` parameter.
 *
 * @param WP_Post|null $post      Optional. The post being edited, provided for context.
 * @param string       $post_type Optional. Post type to get the templates for. Default 'page'.
 * @return string[] Array of template file names keyed by the template header name.
 */
function get_page_templates( $post = null, $post_type = 'page' ) {
	return array_flip( wp_get_theme()->get_page_templates( $post, $post_type ) );
}

/**
 * Tidies a filename for url display by the theme file editor.
 *
 * @since 2.9.0
 * @access private
 *
 * @param string $fullpath Full path to the theme file
 * @param string $containingfolder Path of the theme parent folder
 * @return string
 */
function _get_template_edit_filename( $fullpath, $containingfolder ) {
	return str_replace( dirname( $containingfolder, 2 ), '', $fullpath );
}

/**
 * Check if there is an update for a theme available.
 *
 * Will display link, if there is an update available.
 *
 * @since 2.7.0
 *
 * @see get_theme_update_available()
 *
 * @param WP_Theme $theme Theme data object.
 */
function theme_update_available( $theme ) {
	echo get_theme_update_available( $theme );
}

/**
 * Retrieves the update link if there is a theme update available.
 *
 * Will return a link if there is an update available.
 *
 * @since 3.8.0
 *
 * @param WP_Theme $theme WP_Theme object.
 * @return string|false HTML for the update link, or false if invalid info was passed.
 */
function get_theme_update_available( $theme ) {
	static $themes_update = null;

	if ( ! current_user_can( 'update_themes' ) ) {
		return false;
	}

	if ( ! isset( $themes_update ) ) {
		$themes_update = get_site_transient( 'update_themes' );
	}

	if ( ! ( $theme instanceof WP_Theme ) ) {
		return false;
	}

	$stylesheet = $theme->get_stylesheet();

	$html = '';

	if ( isset( $themes_update->response[ $stylesheet ] ) ) {
		$update      = $themes_update->response[ $stylesheet ];
		$theme_name  = $theme->display( 'Name' );
		$details_url = add_query_arg(
			array(
				'TB_iframe' => 'true',
				'width'     => 1024,
				'height'    => 800,
			),
			$update['url']
		); // Theme browser inside WP? Replace this. Also, theme preview JS will override this on the available list.
		$update_url  = wp_nonce_url( admin_url( 'update.php?action=upgrade-theme&amp;theme=' . urlencode( $stylesheet ) ), 'upgrade-theme_' . $stylesheet );

		if ( ! is_multisite() ) {
			if ( ! current_user_can( 'update_themes' ) ) {
				$html = sprintf(
					/* translators: 1: Theme name, 2: Theme details URL, 3: Additional link attributes, 4: Version number. */
					'<p><strong>' . __( 'There is a new version of %1$s available. <a href="%2$s" %3$s>View version %4$s details</a>.' ) . '</strong></p>',
					$theme_name,
					esc_url( $details_url ),
					sprintf(
						'class="thickbox open-plugin-details-modal" aria-label="%s"',
						/* translators: 1: Theme name, 2: Version number. */
						esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme_name, $update['new_version'] ) )
					),
					$update['new_version']
				);
			} elseif ( empty( $update['package'] ) ) {
				$html = sprintf(
					/* translators: 1: Theme name, 2: Theme details URL, 3: Additional link attributes, 4: Version number. */
					'<p><strong>' . __( 'There is a new version of %1$s available. <a href="%2$s" %3$s>View version %4$s details</a>. <em>Automatic update is unavailable for this theme.</em>' ) . '</strong></p>',
					$theme_name,
					esc_url( $details_url ),
					sprintf(
						'class="thickbox open-plugin-details-modal" aria-label="%s"',
						/* translators: 1: Theme name, 2: Version number. */
						esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme_name, $update['new_version'] ) )
					),
					$update['new_version']
				);
			} else {
				$html = sprintf(
					/* translators: 1: Theme name, 2: Theme details URL, 3: Additional link attributes, 4: Version number, 5: Update URL, 6: Additional link attributes. */
					'<p><strong>' . __( 'There is a new version of %1$s available. <a href="%2$s" %3$s>View version %4$s details</a> or <a href="%5$s" %6$s>update now</a>.' ) . '</strong></p>',
					$theme_name,
					esc_url( $details_url ),
					sprintf(
						'class="thickbox open-plugin-details-modal" aria-label="%s"',
						/* translators: 1: Theme name, 2: Version number. */
						esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme_name, $update['new_version'] ) )
					),
					$update['new_version'],
					$update_url,
					sprintf(
						'aria-label="%s" id="update-theme" data-slug="%s"',
						/* translators: %s: Theme name. */
						esc_attr( sprintf( _x( 'Update %s now', 'theme' ), $theme_name ) ),
						$stylesheet
					)
				);
			}
		}
	}

	return $html;
}

/**
 * Retrieves list of WordPress theme features (aka theme tags).
 *
 * @since 3.1.0
 * @since 3.2.0 Added 'Gray' color and 'Featured Image Header', 'Featured Images',
 *              'Full Width Template', and 'Post Formats' features.
 * @since 3.5.0 Added 'Flexible Header' feature.
 * @since 3.8.0 Renamed 'Width' filter to 'Layout'.
 * @since 3.8.0 Renamed 'Fixed Width' and 'Flexible Width' options
 *              to 'Fixed Layout' and 'Fluid Layout'.
 * @since 3.8.0 Added 'Accessibility Ready' feature and 'Responsive Layout' option.
 * @since 3.9.0 Combined 'Layout' and 'Columns' filters.
 * @since 4.6.0 Removed 'Colors' filter.
 * @since 4.6.0 Added 'Grid Layout' option.
 *              Removed 'Fixed Layout', 'Fluid Layout', and 'Responsive Layout' options.
 * @since 4.6.0 Added 'Custom Logo' and 'Footer Widgets' features.
 *              Removed 'Blavatar' feature.
 * @since 4.6.0 Added 'Blog', 'E-Commerce', 'Education', 'Entertainment', 'Food & Drink',
 *              'Holiday', 'News', 'Photography', and 'Portfolio' subjects.
 *              Removed 'Photoblogging' and 'Seasonal' subjects.
 * @since 4.9.0 Reordered the filters from 'Layout', 'Features', 'Subject'
 *              to 'Subject', 'Features', 'Layout'.
 * @since 4.9.0 Removed 'BuddyPress', 'Custom Menu', 'Flexible Header',
 *              'Front Page Posting', 'Microformats', 'RTL Language Support',
 *              'Threaded Comments', and 'Translation Ready' features.
 * @since 5.5.0 Added 'Block Editor Patterns', 'Block Editor Styles',
 *              and 'Full Site Editing' features.
 * @since 5.5.0 Added 'Wide Blocks' layout option.
 * @since 5.8.1 Added 'Template Editing' feature.
 * @since 6.1.1 Replaced 'Full Site Editing' feature name with 'Site Editor'.
 * @since 6.2.0 Added 'Style Variations' feature.
 *
 * @param bool $api Optional. Whether try to fetch tags from the WordPress.org API. Defaults to true.
 * @return array Array of features keyed by category with translations keyed by slug.
 */
function get_theme_feature_list( $api = true ) {
	// Hard-coded list is used if API is not accessible.
	$features = array(

		__( 'Subject' )  => array(
			'blog'           => __( 'Blog' ),
			'e-commerce'     => __( 'E-Commerce' ),
			'education'      => __( 'Education' ),
			'entertainment'  => __( 'Entertainment' ),
			'food-and-drink' => __( 'Food & Drink' ),
			'holiday'        => __( 'Holiday' ),
			'news'           => __( 'News' ),
			'photography'    => __( 'Photography' ),
			'portfolio'      => __( 'Portfolio' ),
		),

		__( 'Features' ) => array(
			'accessibility-ready'   => __( 'Accessibility Ready' ),
			'block-patterns'        => __( 'Block Editor Patterns' ),
			'block-styles'          => __( 'Block Editor Styles' ),
			'custom-background'     => __( 'Custom Background' ),
			'custom-colors'         => __( 'Custom Colors' ),
			'custom-header'         => __( 'Custom Header' ),
			'custom-logo'           => __( 'Custom Logo' ),
			'editor-style'          => __( 'Editor Style' ),
			'featured-image-header' => __( 'Featured Image Header' ),
			'featured-images'       => __( 'Featured Images' ),
			'footer-widgets'        => __( 'Footer Widgets' ),
			'full-site-editing'     => __( 'Site Editor' ),
			'full-width-template'   => __( 'Full Width Template' ),
			'post-formats'          => __( 'Post Formats' ),
			'sticky-post'           => __( 'Sticky Post' ),
			'style-variations'      => __( 'Style Variations' ),
			'template-editing'      => __( 'Template Editing' ),
			'theme-options'         => __( 'Theme Options' ),
		),

		__( 'Layout' )   => array(
			'grid-layout'   => __( 'Grid Layout' ),
			'one-column'    => __( 'One Column' ),
			'two-columns'   => __( 'Two Columns' ),
			'three-columns' => __( 'Three Columns' ),
			'four-columns'  => __( 'Four Columns' ),
			'left-sidebar'  => __( 'Left Sidebar' ),
			'right-sidebar' => __( 'Right Sidebar' ),
			'wide-blocks'   => __( 'Wide Blocks' ),
		),

	);

	if ( ! $api || ! current_user_can( 'install_themes' ) ) {
		return $features;
	}

	$feature_list = get_site_transient( 'wporg_theme_feature_list' );
	if ( ! $feature_list ) {
		set_site_transient( 'wporg_theme_feature_list', array(), 3 * HOUR_IN_SECONDS );
	}

	if ( ! $feature_list ) {
		$feature_list = themes_api( 'feature_list', array() );
		if ( is_wp_error( $feature_list ) ) {
			return $features;
		}
	}

	if ( ! $feature_list ) {
		return $features;
	}

	set_site_transient( 'wporg_theme_feature_list', $feature_list, 3 * HOUR_IN_SECONDS );

	$category_translations = array(
		'Layout'   => __( 'Layout' ),
		'Features' => __( 'Features' ),
		'Subject'  => __( 'Subject' ),
	);

	$wporg_features = array();

	// Loop over the wp.org canonical list and apply translations.
	foreach ( (array) $feature_list as $feature_category => $feature_items ) {
		if ( isset( $category_translations[ $feature_category ] ) ) {
			$feature_category = $category_translations[ $feature_category ];
		}

		$wporg_features[ $feature_category ] = array();

		foreach ( $feature_items as $feature ) {
			if ( isset( $features[ $feature_category ][ $feature ] ) ) {
				$wporg_features[ $feature_category ][ $feature ] = $features[ $feature_category ][ $feature ];
			} else {
				$wporg_features[ $feature_category ][ $feature ] = $feature;
			}
		}
	}

	return $wporg_features;
}

/**
 * Retrieves theme installer pages from the WordPress.org Themes API.
 *
 * It is possible for a theme to override the Themes API result with three
 * filters. Assume this is for themes, which can extend on the Theme Info to
 * offer more choices. This is very powerful and must be used with care, when
 * overriding the filters.
 *
 * The first filter, {@see 'themes_api_args'}, is for the args and gives the action
 * as the second parameter. The hook for {@see 'themes_api_args'} must ensure that
 * an object is returned.
 *
 * The second filter, {@see 'themes_api'}, allows a plugin to override the WordPress.org
 * Theme API entirely. If `$action` is 'query_themes', 'theme_information', or 'feature_list',
 * an object MUST be passed. If `$action` is 'hot_tags', an array should be passed.
 *
 * Finally, the third filter, {@see 'themes_api_result'}, makes it possible to filter the
 * response object or array, depending on the `$action` type.
 *
 * Supported arguments per action:
 *
 * | Argument Name      | 'query_themes' | 'theme_information' | 'hot_tags' | 'feature_list'   |
 * | -------------------| :------------: | :-----------------: | :--------: | :--------------: |
 * | `$slug`            | No             |  Yes                | No         | No               |
 * | `$per_page`        | Yes            |  No                 | No         | No               |
 * | `$page`            | Yes            |  No                 | No         | No               |
 * | `$number`          | No             |  No                 | Yes        | No               |
 * | `$search`          | Yes            |  No                 | No         | No               |
 * | `$tag`             | Yes            |  No                 | No         | No               |
 * | `$author`          | Yes            |  No                 | No         | No               |
 * | `$user`            | Yes            |  No                 | No         | No               |
 * | `$browse`          | Yes            |  No                 | No         | No               |
 * | `$locale`          | Yes            |  Yes                | No         | No               |
 * | `$fields`          | Yes            |  Yes                | No         | No               |
 *
 * @since 2.8.0
 *
 * @param string       $action API action to perform: Accepts 'query_themes', 'theme_information',
 *                             'hot_tags' or 'feature_list'.
 * @param array|object $args   {
 *     Optional. Array or object of arguments to serialize for the Themes API. Default empty array.
 *
 *     @type string  $slug     The theme slug. Default empty.
 *     @type int     $per_page Number of themes per page. Default 24.
 *     @type int     $page     Number of current page. Default 1.
 *     @type int     $number   Number of tags to be queried.
 *     @type string  $search   A search term. Default empty.
 *     @type string  $tag      Tag to filter themes. Default empty.
 *     @type string  $author   Username of an author to filter themes. Default empty.
 *     @type string  $user     Username to query for their favorites. Default empty.
 *     @type string  $browse   Browse view: 'featured', 'popular', 'updated', 'favorites'.
 *     @type string  $locale   Locale to provide context-sensitive results. Default is the value of get_locale().
 *     @type array   $fields   {
 *         Array of fields which should or should not be returned.
 *
 *         @type bool $description        Whether to return the theme full description. Default false.
 *         @type bool $sections           Whether to return the theme readme sections: description, installation,
 *                                        FAQ, screenshots, other notes, and changelog. Default false.
 *         @type bool $rating             Whether to return the rating in percent and total number of ratings.
 *                                        Default false.
 *         @type bool $ratings            Whether to return the number of rating for each star (1-5). Default false.
 *         @type bool $downloaded         Whether to return the download count. Default false.
 *         @type bool $downloadlink       Whether to return the download link for the package. Default false.
 *         @type bool $last_updated       Whether to return the date of the last update. Default false.
 *         @type bool $tags               Whether to return the assigned tags. Default false.
 *         @type bool $homepage           Whether to return the theme homepage link. Default false.
 *         @type bool $screenshots        Whether to return the screenshots. Default false.
 *         @type int  $screenshot_count   Number of screenshots to return. Default 1.
 *         @type bool $screenshot_url     Whether to return the URL of the first screenshot. Default false.
 *         @type bool $photon_screenshots Whether to return the screenshots via Photon. Default false.
 *         @type bool $template           Whether to return the slug of the parent theme. Default false.
 *         @type bool $parent             Whether to return the slug, name and homepage of the parent theme. Default false.
 *         @type bool $versions           Whether to return the list of all available versions. Default false.
 *         @type bool $theme_url          Whether to return theme's URL. Default false.
 *         @type bool $extended_author    Whether to return nicename or nicename and display name. Default false.
 *     }
 * }
 * @return object|array|WP_Error Response object or array on success, WP_Error on failure. See the
 *         {@link https://developer.wordpress.org/reference/functions/themes_api/ function reference article}
 *         for more information on the make-up of possible return objects depending on the value of `$action`.
 */
function themes_api( $action, $args = array() ) {
	if ( is_array( $args ) ) {
		$args = (object) $args;
	}

	if ( 'query_themes' === $action ) {
		if ( ! isset( $args->per_page ) ) {
			$args->per_page = 24;
		}
	}

	if ( ! isset( $args->locale ) ) {
		$args->locale = get_user_locale();
	}

	if ( ! isset( $args->wp_version ) ) {
		$args->wp_version = substr( wp_get_wp_version(), 0, 3 ); // x.y
	}

	/**
	 * Filters arguments used to query for installer pages from the WordPress.org Themes API.
	 *
	 * Important: An object MUST be returned to this filter.
	 *
	 * @since 2.8.0
	 *
	 * @param object $args   Arguments used to query for installer pages from the WordPress.org Themes API.
	 * @param string $action Requested action. Likely values are 'theme_information',
	 *                       'feature_list', or 'query_themes'.
	 */
	$args = apply_filters( 'themes_api_args', $args, $action );

	/**
	 * Filters whether to override the WordPress.org Themes API.
	 *
	 * Returning a non-false value will effectively short-circuit the WordPress.org API request.
	 *
	 * If `$action` is 'query_themes', 'theme_information', or 'feature_list', an object MUST
	 * be passed. If `$action` is 'hot_tags', an array should be passed.
	 *
	 * @since 2.8.0
	 *
	 * @param false|object|array $override Whether to override the WordPress.org Themes API. Default false.
	 * @param string             $action   Requested action. Likely values are 'theme_information',
	 *                                    'feature_list', or 'query_themes'.
	 * @param object             $args     Arguments used to query for installer pages from the Themes API.
	 */
	$res = apply_filters( 'themes_api', false, $action, $args );

	if ( ! $res ) {
		$url = 'http://api.wordpress.org/themes/info/1.2/';
		$url = add_query_arg(
			array(
				'action'  => $action,
				'request' => $args,
			),
			$url
		);

		$http_url = $url;
		$ssl      = wp_http_supports( array( 'ssl' ) );
		if ( $ssl ) {
			$url = set_url_scheme( $url, 'https' );
		}

		$http_args = array(
			'timeout'    => 15,
			'user-agent' => 'WordPress/' . wp_get_wp_version() . '; ' . home_url( '/' ),
		);
		$request   = wp_remote_get( $url, $http_args );

		if ( $ssl && is_wp_error( $request ) ) {
			if ( ! wp_doing_ajax() ) {
				wp_trigger_error(
					__FUNCTION__,
					sprintf(
						/* translators: %s: Support forums URL. */
						__( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ),
						__( 'https://wordpress.org/support/forums/' )
					) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ),
					headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE
				);
			}
			$request = wp_remote_get( $http_url, $http_args );
		}

		if ( is_wp_error( $request ) ) {
			$res = new WP_Error(
				'themes_api_failed',
				sprintf(
					/* translators: %s: Support forums URL. */
					__( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ),
					__( 'https://wordpress.org/support/forums/' )
				),
				$request->get_error_message()
			);
		} else {
			$res = json_decode( wp_remote_retrieve_body( $request ), true );
			if ( is_array( $res ) ) {
				// Object casting is required in order to match the info/1.0 format.
				$res = (object) $res;
			} elseif ( null === $res ) {
				$res = new WP_Error(
					'themes_api_failed',
					sprintf(
						/* translators: %s: Support forums URL. */
						__( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ),
						__( 'https://wordpress.org/support/forums/' )
					),
					wp_remote_retrieve_body( $request )
				);
			}

			if ( isset( $res->error ) ) {
				$res = new WP_Error( 'themes_api_failed', $res->error );
			}
		}

		if ( ! is_wp_error( $res ) ) {
			// Back-compat for info/1.2 API, upgrade the theme objects in query_themes to objects.
			if ( 'query_themes' === $action ) {
				foreach ( $res->themes as $i => $theme ) {
					$res->themes[ $i ] = (object) $theme;
				}
			}

			// Back-compat for info/1.2 API, downgrade the feature_list result back to an array.
			if ( 'feature_list' === $action ) {
				$res = (array) $res;
			}
		}
	}

	/**
	 * Filters the returned WordPress.org Themes API response.
	 *
	 * @since 2.8.0
	 *
	 * @param array|stdClass|WP_Error $res    WordPress.org Themes API response.
	 * @param string                  $action Requested action. Likely values are 'theme_information',
	 *                                        'feature_list', or 'query_themes'.
	 * @param stdClass                $args   Arguments used to query for installer pages from the WordPress.org Themes API.
	 */
	return apply_filters( 'themes_api_result', $res, $action, $args );
}

/**
 * Prepares themes for JavaScript.
 *
 * @since 3.8.0
 *
 * @param WP_Theme[] $themes Optional. Array of theme objects to prepare.
 *                           Defaults to all allowed themes.
 *
 * @return array An associative array of theme data, sorted by name.
 */
function wp_prepare_themes_for_js( $themes = null ) {
	$current_theme = get_stylesheet();

	/**
	 * Filters theme data before it is prepared for JavaScript.
	 *
	 * Passing a non-empty array will result in wp_prepare_themes_for_js() returning
	 * early with that value instead.
	 *
	 * @since 4.2.0
	 *
	 * @param array           $prepared_themes An associative array of theme data. Default empty array.
	 * @param WP_Theme[]|null $themes          An array of theme objects to prepare, if any.
	 * @param string          $current_theme   The active theme slug.
	 */
	$prepared_themes = (array) apply_filters( 'pre_prepare_themes_for_js', array(), $themes, $current_theme );

	if ( ! empty( $prepared_themes ) ) {
		return $prepared_themes;
	}

	// Make sure the active theme is listed first.
	$prepared_themes[ $current_theme ] = array();

	if ( null === $themes ) {
		$themes = wp_get_themes( array( 'allowed' => true ) );
		if ( ! isset( $themes[ $current_theme ] ) ) {
			$themes[ $current_theme ] = wp_get_theme();
		}
	}

	$updates    = array();
	$no_updates = array();
	if ( ! is_multisite() && current_user_can( 'update_themes' ) ) {
		$updates_transient = get_site_transient( 'update_themes' );
		if ( isset( $updates_transient->response ) ) {
			$updates = $updates_transient->response;
		}
		if ( isset( $updates_transient->no_update ) ) {
			$no_updates = $updates_transient->no_update;
		}
	}

	WP_Theme::sort_by_name( $themes );

	$parents = array();

	$auto_updates = (array) get_site_option( 'auto_update_themes', array() );

	foreach ( $themes as $theme ) {
		$slug         = $theme->get_stylesheet();
		$encoded_slug = urlencode( $slug );

		$parent = false;
		if ( $theme->parent() ) {
			$parent           = $theme->parent();
			$parents[ $slug ] = $parent->get_stylesheet();
			$parent           = $parent->display( 'Name' );
		}

		$customize_action = null;

		$can_edit_theme_options = current_user_can( 'edit_theme_options' );
		$can_customize          = current_user_can( 'customize' );
		$is_block_theme         = $theme->is_block_theme();

		if ( $is_block_theme && $can_edit_theme_options ) {
			$customize_action = admin_url( 'site-editor.php' );
			if ( $current_theme !== $slug ) {
				$customize_action = add_query_arg( 'wp_theme_preview', $slug, $customize_action );
			}
		} elseif ( ! $is_block_theme && $can_customize && $can_edit_theme_options ) {
			$customize_action = wp_customize_url( $slug );
		}
		if ( null !== $customize_action ) {
			$customize_action = add_query_arg(
				array(
					'return' => urlencode( sanitize_url( remove_query_arg( wp_removable_query_args(), wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) ),
				),
				$customize_action
			);
			$customize_action = esc_url( $customize_action );
		}

		$update_requires_wp  = isset( $updates[ $slug ]['requires'] ) ? $updates[ $slug ]['requires'] : null;
		$update_requires_php = isset( $updates[ $slug ]['requires_php'] ) ? $updates[ $slug ]['requires_php'] : null;

		$auto_update        = in_array( $slug, $auto_updates, true );
		$auto_update_action = $auto_update ? 'disable-auto-update' : 'enable-auto-update';

		if ( isset( $updates[ $slug ] ) ) {
			$auto_update_supported      = true;
			$auto_update_filter_payload = (object) $updates[ $slug ];
		} elseif ( isset( $no_updates[ $slug ] ) ) {
			$auto_update_supported      = true;
			$auto_update_filter_payload = (object) $no_updates[ $slug ];
		} else {
			$auto_update_supported = false;
			/*
			 * Create the expected payload for the auto_update_theme filter, this is the same data
			 * as contained within $updates or $no_updates but used when the Theme is not known.
			 */
			$auto_update_filter_payload = (object) array(
				'theme'        => $slug,
				'new_version'  => $theme->get( 'Version' ),
				'url'          => '',
				'package'      => '',
				'requires'     => $theme->get( 'RequiresWP' ),
				'requires_php' => $theme->get( 'RequiresPHP' ),
			);
		}

		$auto_update_forced = wp_is_auto_update_forced_for_item( 'theme', null, $auto_update_filter_payload );

		$prepared_themes[ $slug ] = array(
			'id'             => $slug,
			'name'           => $theme->display( 'Name' ),
			'screenshot'     => array( $theme->get_screenshot() ), // @todo Multiple screenshots.
			'description'    => $theme->display( 'Description' ),
			'author'         => $theme->display( 'Author', false, true ),
			'authorAndUri'   => $theme->display( 'Author' ),
			'tags'           => $theme->display( 'Tags' ),
			'version'        => $theme->get( 'Version' ),
			'compatibleWP'   => is_wp_version_compatible( $theme->get( 'RequiresWP' ) ),
			'compatiblePHP'  => is_php_version_compatible( $theme->get( 'RequiresPHP' ) ),
			'updateResponse' => array(
				'compatibleWP'  => is_wp_version_compatible( $update_requires_wp ),
				'compatiblePHP' => is_php_version_compatible( $update_requires_php ),
			),
			'parent'         => $parent,
			'active'         => $slug === $current_theme,
			'hasUpdate'      => isset( $updates[ $slug ] ),
			'hasPackage'     => isset( $updates[ $slug ] ) && ! empty( $updates[ $slug ]['package'] ),
			'update'         => get_theme_update_available( $theme ),
			'autoupdate'     => array(
				'enabled'   => $auto_update || $auto_update_forced,
				'supported' => $auto_update_supported,
				'forced'    => $auto_update_forced,
			),
			'actions'        => array(
				'activate'   => current_user_can( 'switch_themes' ) ? wp_nonce_url( admin_url( 'themes.php?action=activate&amp;stylesheet=' . $encoded_slug ), 'switch-theme_' . $slug ) : null,
				'customize'  => $customize_action,
				'delete'     => ( ! is_multisite() && current_user_can( 'delete_themes' ) ) ? wp_nonce_url( admin_url( 'themes.php?action=delete&amp;stylesheet=' . $encoded_slug ), 'delete-theme_' . $slug ) : null,
				'autoupdate' => wp_is_auto_update_enabled_for_type( 'theme' ) && ! is_multisite() && current_user_can( 'update_themes' )
					? wp_nonce_url( admin_url( 'themes.php?action=' . $auto_update_action . '&amp;stylesheet=' . $encoded_slug ), 'updates' )
					: null,
			),
			'blockTheme'     => $theme->is_block_theme(),
		);
	}

	// Remove 'delete' action if theme has an active child.
	if ( ! empty( $parents ) && array_key_exists( $current_theme, $parents ) ) {
		unset( $prepared_themes[ $parents[ $current_theme ] ]['actions']['delete'] );
	}

	/**
	 * Filters the themes prepared for JavaScript, for themes.php.
	 *
	 * Could be useful for changing the order, which is by name by default.
	 *
	 * @since 3.8.0
	 *
	 * @param array $prepared_themes Array of theme data.
	 */
	$prepared_themes = apply_filters( 'wp_prepare_themes_for_js', $prepared_themes );
	$prepared_themes = array_values( $prepared_themes );
	return array_filter( $prepared_themes );
}

/**
 * Prints JS templates for the theme-browsing UI in the Customizer.
 *
 * @since 4.2.0
 */
function customize_themes_print_templates() {
	?>
	<script type="text/html" id="tmpl-customize-themes-details-view">
		<div class="theme-backdrop"></div>
		<div class="theme-wrap wp-clearfix" role="document">
			<div class="theme-header">
				<button type="button" class="left dashicons dashicons-no"><span class="screen-reader-text">
					<?php
					/* translators: Hidden accessibility text. */
					_e( 'Show previous theme' );
					?>
				</span></button>
				<button type="button" class="right dashicons dashicons-no"><span class="screen-reader-text">
					<?php
					/* translators: Hidden accessibility text. */
					_e( 'Show next theme' );
					?>
				</span></button>
				<button type="button" class="close dashicons dashicons-no"><span class="screen-reader-text">
					<?php
					/* translators: Hidden accessibility text. */
					_e( 'Close details dialog' );
					?>
				</span></button>
			</div>
			<div class="theme-about wp-clearfix">
				<div class="theme-screenshots">
				<# if ( data.screenshot && data.screenshot[0] ) { #>
					<div class="screenshot"><img src="{{ data.screenshot[0] }}?ver={{ data.version }}" alt="" /></div>
				<# } else { #>
					<div class="screenshot blank"></div>
				<# } #>
				</div>

				<div class="theme-info">
					<# if ( data.active ) { #>
						<span class="current-label"><?php _e( 'Active Theme' ); ?></span>
					<# } #>
					<h2 class="theme-name">{{{ data.name }}}<span class="theme-version">
						<?php
						/* translators: %s: Theme version. */
						printf( __( 'Version: %s' ), '{{ data.version }}' );
						?>
					</span></h2>
					<h3 class="theme-author">
						<?php
						/* translators: %s: Theme author link. */
						printf( __( 'By %s' ), '{{{ data.authorAndUri }}}' );
						?>
					</h3>

					<# if ( data.stars && 0 != data.num_ratings ) { #>
						<div class="theme-rating">
							{{{ data.stars }}}
							<a class="num-ratings" target="_blank" href="{{ data.reviews_url }}">
								<?php
								printf(
									'%1$s <span class="screen-reader-text">%2$s</span>',
									/* translators: %s: Number of ratings. */
									sprintf( __( '(%s ratings)' ), '{{ data.num_ratings }}' ),
									/* translators: Hidden accessibility text. */
									__( '(opens in a new tab)' )
								);
								?>
							</a>
						</div>
					<# } #>

					<# if ( data.hasUpdate ) { #>
						<# if ( data.updateResponse.compatibleWP && data.updateResponse.compatiblePHP ) { #>
							<div class="notice notice-warning notice-alt notice-large" data-slug="{{ data.id }}">
								<h3 class="notice-title"><?php _e( 'Update Available' ); ?></h3>
								{{{ data.update }}}
							</div>
						<# } else { #>
							<div class="notice notice-error notice-alt notice-large" data-slug="{{ data.id }}">
								<h3 class="notice-title"><?php _e( 'Update Incompatible' ); ?></h3>
								<p>
									<# if ( ! data.updateResponse.compatibleWP && ! data.updateResponse.compatiblePHP ) { #>
										<?php
										printf(
											/* translators: %s: Theme name. */
											__( 'There is a new version of %s available, but it does not work with your versions of WordPress and PHP.' ),
											'{{{ data.name }}}'
										);
										if ( current_user_can( 'update_core' ) && current_user_can( 'update_php' ) ) {
											printf(
												/* translators: 1: URL to WordPress Updates screen, 2: URL to Update PHP page. */
												' ' . __( '<a href="%1$s">Please update WordPress</a>, and then <a href="%2$s">learn more about updating PHP</a>.' ),
												self_admin_url( 'update-core.php' ),
												esc_url( wp_get_update_php_url() )
											);
											wp_update_php_annotation( '</p><p><em>', '</em>' );
										} elseif ( current_user_can( 'update_core' ) ) {
											printf(
												/* translators: %s: URL to WordPress Updates screen. */
												' ' . __( '<a href="%s">Please update WordPress</a>.' ),
												self_admin_url( 'update-core.php' )
											);
										} elseif ( current_user_can( 'update_php' ) ) {
											printf(
												/* translators: %s: URL to Update PHP page. */
												' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
												esc_url( wp_get_update_php_url() )
											);
											wp_update_php_annotation( '</p><p><em>', '</em>' );
										}
										?>
									<# } else if ( ! data.updateResponse.compatibleWP ) { #>
										<?php
										printf(
											/* translators: %s: Theme name. */
											__( 'There is a new version of %s available, but it does not work with your version of WordPress.' ),
											'{{{ data.name }}}'
										);
										if ( current_user_can( 'update_core' ) ) {
											printf(
												/* translators: %s: URL to WordPress Updates screen. */
												' ' . __( '<a href="%s">Please update WordPress</a>.' ),
												self_admin_url( 'update-core.php' )
											);
										}
										?>
									<# } else if ( ! data.updateResponse.compatiblePHP ) { #>
										<?php
										printf(
											/* translators: %s: Theme name. */
											__( 'There is a new version of %s available, but it does not work with your version of PHP.' ),
											'{{{ data.name }}}'
										);
										if ( current_user_can( 'update_php' ) ) {
											printf(
												/* translators: %s: URL to Update PHP page. */
												' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
												esc_url( wp_get_update_php_url() )
											);
											wp_update_php_annotation( '</p><p><em>', '</em>' );
										}
										?>
									<# } #>
								</p>
							</div>
						<# } #>
					<# } #>

					<# if ( data.parent ) { #>
						<p class="parent-theme">
							<?php
							printf(
								/* translators: %s: Theme name. */
								__( 'This is a child theme of %s.' ),
								'<strong>{{{ data.parent }}}</strong>'
							);
							?>
						</p>
					<# } #>

					<# if ( ! data.compatibleWP || ! data.compatiblePHP ) { #>
						<div class="notice notice-error notice-alt notice-large"><p>
							<# if ( ! data.compatibleWP && ! data.compatiblePHP ) { #>
								<?php
								_e( 'This theme does not work with your versions of WordPress and PHP.' );
								if ( current_user_can( 'update_core' ) && current_user_can( 'update_php' ) ) {
									printf(
										/* translators: 1: URL to WordPress Updates screen, 2: URL to Update PHP page. */
										' ' . __( '<a href="%1$s">Please update WordPress</a>, and then <a href="%2$s">learn more about updating PHP</a>.' ),
										self_admin_url( 'update-core.php' ),
										esc_url( wp_get_update_php_url() )
									);
									wp_update_php_annotation( '</p><p><em>', '</em>' );
								} elseif ( current_user_can( 'update_core' ) ) {
									printf(
										/* translators: %s: URL to WordPress Updates screen. */
										' ' . __( '<a href="%s">Please update WordPress</a>.' ),
										self_admin_url( 'update-core.php' )
									);
								} elseif ( current_user_can( 'update_php' ) ) {
									printf(
										/* translators: %s: URL to Update PHP page. */
										' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
										esc_url( wp_get_update_php_url() )
									);
									wp_update_php_annotation( '</p><p><em>', '</em>' );
								}
								?>
							<# } else if ( ! data.compatibleWP ) { #>
								<?php
								_e( 'This theme does not work with your version of WordPress.' );
								if ( current_user_can( 'update_core' ) ) {
									printf(
										/* translators: %s: URL to WordPress Updates screen. */
										' ' . __( '<a href="%s">Please update WordPress</a>.' ),
										self_admin_url( 'update-core.php' )
									);
								}
								?>
							<# } else if ( ! data.compatiblePHP ) { #>
								<?php
								_e( 'This theme does not work with your version of PHP.' );
								if ( current_user_can( 'update_php' ) ) {
									printf(
										/* translators: %s: URL to Update PHP page. */
										' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
										esc_url( wp_get_update_php_url() )
									);
									wp_update_php_annotation( '</p><p><em>', '</em>' );
								}
								?>
							<# } #>
						</p></div>
					<# } else if ( ! data.active && data.blockTheme ) { #>
						<div class="notice notice-error notice-alt notice-large"><p>
						<?php
							_e( 'This theme doesn\'t support Customizer.' );
						?>
						<# if ( data.actions.activate ) { #>
							<?php
							printf(
								/* translators: %s: URL to the themes page (also it activates the theme). */
								' ' . __( 'However, you can still <a href="%s">activate this theme</a>, and use the Site Editor to customize it.' ),
								'{{{ data.actions.activate }}}'
							);
							?>
						<# } #>
						</p></div>
					<# } #>

					<p class="theme-description">{{{ data.description }}}</p>

					<# if ( data.tags ) { #>
						<p class="theme-tags"><span><?php _e( 'Tags:' ); ?></span> {{{ data.tags }}}</p>
					<# } #>
				</div>
			</div>

			<div class="theme-actions">
				<# if ( data.active ) { #>
					<button type="button" class="button button-primary customize-theme"><?php _e( 'Customize' ); ?></button>
				<# } else if ( 'installed' === data.type ) { #>
					<div class="theme-inactive-actions">
					<# if ( data.blockTheme ) { #>
						<?php
							/* translators: %s: Theme name. */
							$aria_label = sprintf( _x( 'Activate %s', 'theme' ), '{{ data.name }}' );
						?>
						<# if ( data.compatibleWP && data.compatiblePHP && data.actions.activate ) { #>
							<a href="{{{ data.actions.activate }}}" class="button button-primary activate" aria-label="<?php echo esc_attr( $aria_label ); ?>"><?php _e( 'Activate' ); ?></a>
						<# } #>
					<# } else { #>
						<# if ( data.compatibleWP && data.compatiblePHP ) { #>
							<button type="button" class="button button-primary preview-theme" data-slug="{{ data.id }}"><?php _e( 'Live Preview' ); ?></button>
						<# } else { #>
							<button class="button button-primary disabled"><?php _e( 'Live Preview' ); ?></button>
						<# } #>
					<# } #>
					</div>
					<?php if ( current_user_can( 'delete_themes' ) ) { ?>
						<# if ( data.actions && data.actions['delete'] ) { #>
							<a href="{{{ data.actions['delete'] }}}" data-slug="{{ data.id }}" class="button button-secondary delete-theme"><?php _e( 'Delete' ); ?></a>
						<# } #>
					<?php } ?>
				<# } else { #>
					<# if ( data.compatibleWP && data.compatiblePHP ) { #>
						<button type="button" class="button theme-install" data-slug="{{ data.id }}"><?php _e( 'Install' ); ?></button>
						<button type="button" class="button button-primary theme-install preview" data-slug="{{ data.id }}"><?php _e( 'Install &amp; Preview' ); ?></button>
					<# } else { #>
						<button type="button" class="button disabled"><?php _ex( 'Cannot Install', 'theme' ); ?></button>
						<button type="button" class="button button-primary disabled"><?php _e( 'Install &amp; Preview' ); ?></button>
					<# } #>
				<# } #>
			</div>
		</div>
	</script>
	<?php
}

/**
 * Determines whether a theme is technically active but was paused while
 * loading.
 *
 * For more information on this and similar theme functions, check out
 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
 * Conditional Tags} article in the Theme Developer Handbook.
 *
 * @since 5.2.0
 *
 * @global WP_Paused_Extensions_Storage $_paused_themes
 *
 * @param string $theme Path to the theme directory relative to the themes directory.
 * @return bool True, if in the list of paused themes. False, not in the list.
 */
function is_theme_paused( $theme ) {
	if ( ! isset( $GLOBALS['_paused_themes'] ) ) {
		return false;
	}

	if ( get_stylesheet() !== $theme && get_template() !== $theme ) {
		return false;
	}

	return array_key_exists( $theme, $GLOBALS['_paused_themes'] );
}

/**
 * Gets the error that was recorded for a paused theme.
 *
 * @since 5.2.0
 *
 * @global WP_Paused_Extensions_Storage $_paused_themes
 *
 * @param string $theme Path to the theme directory relative to the themes
 *                      directory.
 * @return array|false Array of error information as it was returned by
 *                     `error_get_last()`, or false if none was recorded.
 */
function wp_get_theme_error( $theme ) {
	if ( ! isset( $GLOBALS['_paused_themes'] ) ) {
		return false;
	}

	if ( ! array_key_exists( $theme, $GLOBALS['_paused_themes'] ) ) {
		return false;
	}

	return $GLOBALS['_paused_themes'][ $theme ];
}

/**
 * Tries to resume a single theme.
 *
 * If a redirect was provided and a functions.php file was found, we first ensure that
 * functions.php file does not throw fatal errors anymore.
 *
 * The way it works is by setting the redirection to the error before trying to
 * include the file. If the theme fails, then the redirection will not be overwritten
 * with the success message and the theme will not be resumed.
 *
 * @since 5.2.0
 *
 * @global string $wp_stylesheet_path Path to current theme's stylesheet directory.
 * @global string $wp_template_path   Path to current theme's template directory.
 *
 * @param string $theme    Single theme to resume.
 * @param string $redirect Optional. URL to redirect to. Default empty string.
 * @return bool|WP_Error True on success, false if `$theme` was not paused,
 *                       `WP_Error` on failure.
 */
function resume_theme( $theme, $redirect = '' ) {
	global $wp_stylesheet_path, $wp_template_path;

	list( $extension ) = explode( '/', $theme );

	/*
	 * We'll override this later if the theme could be resumed without
	 * creating a fatal error.
	 */
	if ( ! empty( $redirect ) ) {
		$functions_path = '';
		if ( str_contains( $wp_stylesheet_path, $extension ) ) {
			$functions_path = $wp_stylesheet_path . '/functions.php';
		} elseif ( str_contains( $wp_template_path, $extension ) ) {
			$functions_path = $wp_template_path . '/functions.php';
		}

		if ( ! empty( $functions_path ) ) {
			wp_redirect(
				add_query_arg(
					'_error_nonce',
					wp_create_nonce( 'theme-resume-error_' . $theme ),
					$redirect
				)
			);

			// Load the theme's functions.php to test whether it throws a fatal error.
			ob_start();
			if ( ! defined( 'WP_SANDBOX_SCRAPING' ) ) {
				define( 'WP_SANDBOX_SCRAPING', true );
			}
			include $functions_path;
			ob_clean();
		}
	}

	$result = wp_paused_themes()->delete( $extension );

	if ( ! $result ) {
		return new WP_Error(
			'could_not_resume_theme',
			__( 'Could not resume the theme.' )
		);
	}

	return true;
}

/**
 * Renders an admin notice in case some themes have been paused due to errors.
 *
 * @since 5.2.0
 *
 * @global string                       $pagenow        The filename of the current screen.
 * @global WP_Paused_Extensions_Storage $_paused_themes
 */
function paused_themes_notice() {
	if ( 'themes.php' === $GLOBALS['pagenow'] ) {
		return;
	}

	if ( ! current_user_can( 'resume_themes' ) ) {
		return;
	}

	if ( ! isset( $GLOBALS['_paused_themes'] ) || empty( $GLOBALS['_paused_themes'] ) ) {
		return;
	}

	$message = sprintf(
		'<p><strong>%s</strong><br>%s</p><p><a href="%s">%s</a></p>',
		__( 'One or more themes failed to load properly.' ),
		__( 'You can find more details and make changes on the Themes screen.' ),
		esc_url( admin_url( 'themes.php' ) ),
		__( 'Go to the Themes screen' )
	);
	wp_admin_notice(
		$message,
		array(
			'type'           => 'error',
			'paragraph_wrap' => false,
		)
	);
}
network.php000064400000064547151212616040006764 0ustar00<?php
/**
 * WordPress Network Administration API.
 *
 * @package WordPress
 * @subpackage Administration
 * @since 4.4.0
 */

/**
 * Check for an existing network.
 *
 * @since 3.0.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @return string|false Base domain if network exists, otherwise false.
 */
function network_domain_check() {
	global $wpdb;

	if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $wpdb->site ) ) ) ) {
		return $wpdb->get_var( "SELECT domain FROM $wpdb->site ORDER BY id ASC LIMIT 1" );
	}

	return false;
}

/**
 * Allow subdomain installation
 *
 * @since 3.0.0
 * @return bool Whether subdomain installation is allowed
 */
function allow_subdomain_install() {
	$home   = get_option( 'home' );
	$domain = parse_url( $home, PHP_URL_HOST );
	if ( parse_url( $home, PHP_URL_PATH ) || 'localhost' === $domain || preg_match( '|^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$|', $domain ) ) {
		return false;
	}

	return true;
}

/**
 * Allow subdirectory installation.
 *
 * @since 3.0.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @return bool Whether subdirectory installation is allowed
 */
function allow_subdirectory_install() {
	global $wpdb;

	/**
	 * Filters whether to enable the subdirectory installation feature in Multisite.
	 *
	 * @since 3.0.0
	 *
	 * @param bool $allow Whether to enable the subdirectory installation feature in Multisite.
	 *                    Default false.
	 */
	if ( apply_filters( 'allow_subdirectory_install', false ) ) {
		return true;
	}

	if ( defined( 'ALLOW_SUBDIRECTORY_INSTALL' ) && ALLOW_SUBDIRECTORY_INSTALL ) {
		return true;
	}

	$post = $wpdb->get_row( "SELECT ID FROM $wpdb->posts WHERE post_date < DATE_SUB(NOW(), INTERVAL 1 MONTH) AND post_status = 'publish'" );
	if ( empty( $post ) ) {
		return true;
	}

	return false;
}

/**
 * Get base domain of network.
 *
 * @since 3.0.0
 * @return string Base domain.
 */
function get_clean_basedomain() {
	$existing_domain = network_domain_check();
	if ( $existing_domain ) {
		return $existing_domain;
	}
	$domain = preg_replace( '|https?://|', '', get_option( 'siteurl' ) );
	$slash  = strpos( $domain, '/' );
	if ( $slash ) {
		$domain = substr( $domain, 0, $slash );
	}
	return $domain;
}

/**
 * Prints step 1 for Network installation process.
 *
 * @todo Realistically, step 1 should be a welcome screen explaining what a Network is and such.
 *       Navigating to Tools > Network should not be a sudden "Welcome to a new install process!
 *       Fill this out and click here." See also contextual help todo.
 *
 * @since 3.0.0
 *
 * @global bool $is_apache
 *
 * @param false|WP_Error $errors Optional. Error object. Default false.
 */
function network_step1( $errors = false ) {
	global $is_apache;

	if ( defined( 'DO_NOT_UPGRADE_GLOBAL_TABLES' ) ) {
		$cannot_define_constant_message  = '<strong>' . __( 'Error:' ) . '</strong> ';
		$cannot_define_constant_message .= sprintf(
			/* translators: %s: DO_NOT_UPGRADE_GLOBAL_TABLES */
			__( 'The constant %s cannot be defined when creating a network.' ),
			'<code>DO_NOT_UPGRADE_GLOBAL_TABLES</code>'
		);

		wp_admin_notice(
			$cannot_define_constant_message,
			array(
				'additional_classes' => array( 'error' ),
			)
		);

		echo '</div>';
		require_once ABSPATH . 'wp-admin/admin-footer.php';
		die();
	}

	$active_plugins = get_option( 'active_plugins' );
	if ( ! empty( $active_plugins ) ) {
		wp_admin_notice(
			'<strong>' . __( 'Warning:' ) . '</strong> ' . sprintf(
				/* translators: %s: URL to Plugins screen. */
				__( 'Please <a href="%s">deactivate your plugins</a> before enabling the Network feature.' ),
				admin_url( 'plugins.php?plugin_status=active' )
			),
			array( 'type' => 'warning' )
		);
		echo '<p>' . __( 'Once the network is created, you may reactivate your plugins.' ) . '</p>';
		echo '</div>';
		require_once ABSPATH . 'wp-admin/admin-footer.php';
		die();
	}

	// Strip standard port from hostname.
	$hostname = preg_replace( '/(?::80|:443)$/', '', get_clean_basedomain() );

	echo '<form method="post">';

	wp_nonce_field( 'install-network-1' );

	$error_codes = array();
	if ( is_wp_error( $errors ) ) {
		$network_created_error_message = '<p><strong>' . __( 'Error:' ) . '</strong> ' . __( 'The network could not be created.' ) . '</p>';
		foreach ( $errors->get_error_messages() as $error ) {
			$network_created_error_message .= "<p>$error</p>";
		}
		wp_admin_notice(
			$network_created_error_message,
			array(
				'additional_classes' => array( 'error' ),
				'paragraph_wrap'     => false,
			)
		);
		$error_codes = $errors->get_error_codes();
	}

	if ( ! empty( $_POST['sitename'] ) && ! in_array( 'empty_sitename', $error_codes, true ) ) {
		$site_name = $_POST['sitename'];
	} else {
		/* translators: %s: Default network title. */
		$site_name = sprintf( __( '%s Sites' ), get_option( 'blogname' ) );
	}

	if ( ! empty( $_POST['email'] ) && ! in_array( 'invalid_email', $error_codes, true ) ) {
		$admin_email = $_POST['email'];
	} else {
		$admin_email = get_option( 'admin_email' );
	}
	?>
	<p><?php _e( 'Welcome to the Network installation process!' ); ?></p>
	<p><?php _e( 'Fill in the information below and you&#8217;ll be on your way to creating a network of WordPress sites. Configuration files will be created in the next step.' ); ?></p>
	<?php

	if ( isset( $_POST['subdomain_install'] ) ) {
		$subdomain_install = (bool) $_POST['subdomain_install'];
	} elseif ( apache_mod_loaded( 'mod_rewrite' ) ) { // Assume nothing.
		$subdomain_install = true;
	} elseif ( ! allow_subdirectory_install() ) {
		$subdomain_install = true;
	} else {
		$subdomain_install = false;
		$got_mod_rewrite   = got_mod_rewrite();
		if ( $got_mod_rewrite ) { // Dangerous assumptions.
			$message_class = 'updated';
			$message       = '<p><strong>' . __( 'Warning:' ) . '</strong> ';
			$message      .= '<p>' . sprintf(
				/* translators: %s: mod_rewrite */
				__( 'Please make sure the Apache %s module is installed as it will be used at the end of this installation.' ),
				'<code>mod_rewrite</code>'
			) . '</p>';
		} elseif ( $is_apache ) {
			$message_class = 'error';
			$message       = '<p><strong>' . __( 'Warning:' ) . '</strong> ';
			$message      .= sprintf(
				/* translators: %s: mod_rewrite */
				__( 'It looks like the Apache %s module is not installed.' ),
				'<code>mod_rewrite</code>'
			) . '</p>';
		}

		if ( $got_mod_rewrite || $is_apache ) { // Protect against mod_rewrite mimicry (but ! Apache).
			$message .= '<p>' . sprintf(
				/* translators: 1: mod_rewrite, 2: mod_rewrite documentation URL, 3: Google search for mod_rewrite. */
				__( 'If %1$s is disabled, ask your administrator to enable that module, or look at the <a href="%2$s">Apache documentation</a> or <a href="%3$s">elsewhere</a> for help setting it up.' ),
				'<code>mod_rewrite</code>',
				'https://httpd.apache.org/docs/mod/mod_rewrite.html',
				'https://www.google.com/search?q=apache+mod_rewrite'
			) . '</p>';

			wp_admin_notice(
				$message,
				array(
					'additional_classes' => array( $message_class, 'inline' ),
					'paragraph_wrap'     => false,
				)
			);
		}
	}

	if ( allow_subdomain_install() && allow_subdirectory_install() ) :
		?>
		<h3><?php esc_html_e( 'Addresses of Sites in your Network' ); ?></h3>
		<p><?php _e( 'Please choose whether you would like sites in your WordPress network to use sub-domains or sub-directories.' ); ?>
			<strong><?php _e( 'You cannot change this later.' ); ?></strong></p>
		<p><?php _e( 'You will need a wildcard DNS record if you are going to use the virtual host (sub-domain) functionality.' ); ?></p>
		<?php // @todo Link to an MS readme? ?>
		<table class="form-table" role="presentation">
			<tr>
				<th><label><input type="radio" name="subdomain_install" value="1"<?php checked( $subdomain_install ); ?> /> <?php _e( 'Sub-domains' ); ?></label></th>
				<td>
				<?php
				printf(
					/* translators: 1: Host name. */
					_x( 'like <code>site1.%1$s</code> and <code>site2.%1$s</code>', 'subdomain examples' ),
					$hostname
				);
				?>
				</td>
			</tr>
			<tr>
				<th><label><input type="radio" name="subdomain_install" value="0"<?php checked( ! $subdomain_install ); ?> /> <?php _e( 'Sub-directories' ); ?></label></th>
				<td>
				<?php
				printf(
					/* translators: 1: Host name. */
					_x( 'like <code>%1$s/site1</code> and <code>%1$s/site2</code>', 'subdirectory examples' ),
					$hostname
				);
				?>
				</td>
			</tr>
		</table>

		<?php
	endif;

	if ( WP_CONTENT_DIR !== ABSPATH . 'wp-content' && ( allow_subdirectory_install() || ! allow_subdomain_install() ) ) {
		$subdirectory_warning_message  = '<strong>' . __( 'Warning:' ) . '</strong> ';
		$subdirectory_warning_message .= __( 'Subdirectory networks may not be fully compatible with custom wp-content directories.' );
		wp_admin_notice(
			$subdirectory_warning_message,
			array(
				'additional_classes' => array( 'error', 'inline' ),
			)
		);
	}

	$is_www = str_starts_with( $hostname, 'www.' );
	if ( $is_www ) :
		?>
		<h3><?php esc_html_e( 'Server Address' ); ?></h3>
		<p>
		<?php
		printf(
			/* translators: 1: Site URL, 2: Host name, 3: www. */
			__( 'You should consider changing your site domain to %1$s before enabling the network feature. It will still be possible to visit your site using the %3$s prefix with an address like %2$s but any links will not have the %3$s prefix.' ),
			'<code>' . substr( $hostname, 4 ) . '</code>',
			'<code>' . $hostname . '</code>',
			'<code>www</code>'
		);
		?>
		</p>
		<table class="form-table" role="presentation">
			<tr>
			<th scope='row'><?php esc_html_e( 'Server Address' ); ?></th>
			<td>
				<?php
					printf(
						/* translators: %s: Host name. */
						__( 'The internet address of your network will be %s.' ),
						'<code>' . $hostname . '</code>'
					);
				?>
				</td>
			</tr>
		</table>
		<?php endif; ?>

		<h3><?php esc_html_e( 'Network Details' ); ?></h3>
		<table class="form-table" role="presentation">
		<?php if ( 'localhost' === $hostname ) : ?>
			<tr>
				<th scope="row"><?php esc_html_e( 'Sub-directory Installation' ); ?></th>
				<td>
				<?php
					printf(
						/* translators: 1: localhost, 2: localhost.localdomain */
						__( 'Because you are using %1$s, the sites in your WordPress network must use sub-directories. Consider using %2$s if you wish to use sub-domains.' ),
						'<code>localhost</code>',
						'<code>localhost.localdomain</code>'
					);
					// Uh oh:
				if ( ! allow_subdirectory_install() ) {
					echo ' <strong>' . __( 'Warning:' ) . ' ' . __( 'The main site in a sub-directory installation will need to use a modified permalink structure, potentially breaking existing links.' ) . '</strong>';
				}
				?>
				</td>
			</tr>
		<?php elseif ( ! allow_subdomain_install() ) : ?>
			<tr>
				<th scope="row"><?php esc_html_e( 'Sub-directory Installation' ); ?></th>
				<td>
				<?php
					_e( 'Because your installation is in a directory, the sites in your WordPress network must use sub-directories.' );
					// Uh oh:
				if ( ! allow_subdirectory_install() ) {
					echo ' <strong>' . __( 'Warning:' ) . ' ' . __( 'The main site in a sub-directory installation will need to use a modified permalink structure, potentially breaking existing links.' ) . '</strong>';
				}
				?>
				</td>
			</tr>
		<?php elseif ( ! allow_subdirectory_install() ) : ?>
			<tr>
				<th scope="row"><?php esc_html_e( 'Sub-domain Installation' ); ?></th>
				<td>
				<?php
				_e( 'Because your installation is not new, the sites in your WordPress network must use sub-domains.' );
					echo ' <strong>' . __( 'The main site in a sub-directory installation will need to use a modified permalink structure, potentially breaking existing links.' ) . '</strong>';
				?>
				</td>
			</tr>
		<?php endif; ?>
		<?php if ( ! $is_www ) : ?>
			<tr>
				<th scope='row'><?php esc_html_e( 'Server Address' ); ?></th>
				<td>
					<?php
					printf(
						/* translators: %s: Host name. */
						__( 'The internet address of your network will be %s.' ),
						'<code>' . $hostname . '</code>'
					);
					?>
				</td>
			</tr>
		<?php endif; ?>
			<tr>
				<th scope='row'><label for="sitename"><?php esc_html_e( 'Network Title' ); ?></label></th>
				<td>
					<input name='sitename' id='sitename' type='text' size='45' value='<?php echo esc_attr( $site_name ); ?>' />
					<p class="description">
						<?php _e( 'What would you like to call your network?' ); ?>
					</p>
				</td>
			</tr>
			<tr>
				<th scope='row'><label for="email"><?php esc_html_e( 'Network Admin Email' ); ?></label></th>
				<td>
					<input name='email' id='email' type='text' size='45' value='<?php echo esc_attr( $admin_email ); ?>' />
					<p class="description">
						<?php _e( 'Your email address.' ); ?>
					</p>
				</td>
			</tr>
		</table>
		<?php submit_button( __( 'Install' ), 'primary', 'submit' ); ?>
	</form>
	<?php
}

/**
 * Prints step 2 for Network installation process.
 *
 * @since 3.0.0
 *
 * @global wpdb $wpdb     WordPress database abstraction object.
 * @global bool $is_nginx Whether the server software is Nginx or something else.
 *
 * @param false|WP_Error $errors Optional. Error object. Default false.
 */
function network_step2( $errors = false ) {
	global $wpdb, $is_nginx;

	$hostname          = get_clean_basedomain();
	$slashed_home      = trailingslashit( get_option( 'home' ) );
	$base              = parse_url( $slashed_home, PHP_URL_PATH );
	$document_root_fix = str_replace( '\\', '/', realpath( $_SERVER['DOCUMENT_ROOT'] ) );
	$abspath_fix       = str_replace( '\\', '/', ABSPATH );
	$home_path         = str_starts_with( $abspath_fix, $document_root_fix ) ? $document_root_fix . $base : get_home_path();
	$wp_siteurl_subdir = preg_replace( '#^' . preg_quote( $home_path, '#' ) . '#', '', $abspath_fix );
	$rewrite_base      = ! empty( $wp_siteurl_subdir ) ? ltrim( trailingslashit( $wp_siteurl_subdir ), '/' ) : '';

	$location_of_wp_config = $abspath_fix;
	if ( ! file_exists( ABSPATH . 'wp-config.php' ) && file_exists( dirname( ABSPATH ) . '/wp-config.php' ) ) {
		$location_of_wp_config = dirname( $abspath_fix );
	}
	$location_of_wp_config = trailingslashit( $location_of_wp_config );

	// Wildcard DNS message.
	if ( is_wp_error( $errors ) ) {
		wp_admin_notice(
			$errors->get_error_message(),
			array(
				'additional_classes' => array( 'error' ),
			)
		);
	}

	if ( $_POST ) {
		if ( allow_subdomain_install() ) {
			$subdomain_install = allow_subdirectory_install() ? ! empty( $_POST['subdomain_install'] ) : true;
		} else {
			$subdomain_install = false;
		}
	} else {
		if ( is_multisite() ) {
			$subdomain_install = is_subdomain_install();
			?>
	<p><?php _e( 'The original configuration steps are shown here for reference.' ); ?></p>
			<?php
		} else {
			$subdomain_install = (bool) $wpdb->get_var( "SELECT meta_value FROM $wpdb->sitemeta WHERE site_id = 1 AND meta_key = 'subdomain_install'" );

			wp_admin_notice(
				'<strong>' . __( 'Warning:' ) . '</strong> ' . __( 'An existing WordPress network was detected.' ),
				array(
					'additional_classes' => array( 'error' ),
				)
			);
			?>
	<p><?php _e( 'Please complete the configuration steps. To create a new network, you will need to empty or remove the network database tables.' ); ?></p>
			<?php
		}
	}

	$subdir_match          = $subdomain_install ? '' : '([_0-9a-zA-Z-]+/)?';
	$subdir_replacement_01 = $subdomain_install ? '' : '$1';
	$subdir_replacement_12 = $subdomain_install ? '$1' : '$2';

	if ( $_POST || ! is_multisite() ) {
		?>
		<h3><?php esc_html_e( 'Enabling the Network' ); ?></h3>
		<p><?php _e( 'Complete the following steps to enable the features for creating a network of sites.' ); ?></p>
		<?php
		$notice_message = '<strong>' . __( 'Caution:' ) . '</strong> ';
		$notice_args    = array(
			'type'               => 'warning',
			'additional_classes' => array( 'inline' ),
		);

		if ( file_exists( $home_path . '.htaccess' ) ) {
			$notice_message .= sprintf(
				/* translators: 1: wp-config.php, 2: .htaccess */
				__( 'You should back up your existing %1$s and %2$s files.' ),
				'<code>wp-config.php</code>',
				'<code>.htaccess</code>'
			);
		} elseif ( file_exists( $home_path . 'web.config' ) ) {
			$notice_message .= sprintf(
				/* translators: 1: wp-config.php, 2: web.config */
				__( 'You should back up your existing %1$s and %2$s files.' ),
				'<code>wp-config.php</code>',
				'<code>web.config</code>'
			);
		} else {
			$notice_message .= sprintf(
				/* translators: %s: wp-config.php */
				__( 'You should back up your existing %s file.' ),
				'<code>wp-config.php</code>'
			);
		}

		wp_admin_notice( $notice_message, $notice_args );
	}
	?>
	<ol>
		<li><p id="network-wpconfig-rules-description">
		<?php
		printf(
			/* translators: 1: wp-config.php, 2: Location of wp-config file, 3: Translated version of "That's all, stop editing! Happy publishing." */
			__( 'Add the following to your %1$s file in %2$s <strong>above</strong> the line reading %3$s:' ),
			'<code>wp-config.php</code>',
			'<code>' . $location_of_wp_config . '</code>',
			/*
			 * translators: This string should only be translated if wp-config-sample.php is localized.
			 * You can check the localized release package or
			 * https://i18n.svn.wordpress.org/<locale code>/branches/<wp version>/dist/wp-config-sample.php
			 */
			'<code>/* ' . __( 'That&#8217;s all, stop editing! Happy publishing.' ) . ' */</code>'
		);
		?>
		</p>
		<p class="configuration-rules-label"><label for="network-wpconfig-rules">
			<?php
			printf(
				/* translators: %s: File name (wp-config.php, .htaccess or web.config). */
				__( 'Network configuration rules for %s' ),
				'<code>wp-config.php</code>'
			);
			?>
		</label></p>
		<textarea id="network-wpconfig-rules" class="code" readonly="readonly" cols="100" rows="7" aria-describedby="network-wpconfig-rules-description">
define( 'MULTISITE', true );
define( 'SUBDOMAIN_INSTALL', <?php echo $subdomain_install ? 'true' : 'false'; ?> );
define( 'DOMAIN_CURRENT_SITE', '<?php echo $hostname; ?>' );
define( 'PATH_CURRENT_SITE', '<?php echo $base; ?>' );
define( 'SITE_ID_CURRENT_SITE', 1 );
define( 'BLOG_ID_CURRENT_SITE', 1 );
</textarea>
		<?php
		$keys_salts = array(
			'AUTH_KEY'         => '',
			'SECURE_AUTH_KEY'  => '',
			'LOGGED_IN_KEY'    => '',
			'NONCE_KEY'        => '',
			'AUTH_SALT'        => '',
			'SECURE_AUTH_SALT' => '',
			'LOGGED_IN_SALT'   => '',
			'NONCE_SALT'       => '',
		);
		foreach ( $keys_salts as $c => $v ) {
			if ( defined( $c ) ) {
				unset( $keys_salts[ $c ] );
			}
		}

		if ( ! empty( $keys_salts ) ) {
			$keys_salts_str = '';
			$from_api       = wp_remote_get( 'https://api.wordpress.org/secret-key/1.1/salt/' );
			if ( is_wp_error( $from_api ) ) {
				foreach ( $keys_salts as $c => $v ) {
					$keys_salts_str .= "\ndefine( '$c', '" . wp_generate_password( 64, true, true ) . "' );";
				}
			} else {
				$from_api = explode( "\n", wp_remote_retrieve_body( $from_api ) );
				foreach ( $keys_salts as $c => $v ) {
					$keys_salts_str .= "\ndefine( '$c', '" . substr( array_shift( $from_api ), 28, 64 ) . "' );";
				}
			}
			$num_keys_salts = count( $keys_salts );
			?>
		<p id="network-wpconfig-authentication-description">
			<?php
			if ( 1 === $num_keys_salts ) {
				printf(
					/* translators: %s: wp-config.php */
					__( 'This unique authentication key is also missing from your %s file.' ),
					'<code>wp-config.php</code>'
				);
			} else {
				printf(
					/* translators: %s: wp-config.php */
					__( 'These unique authentication keys are also missing from your %s file.' ),
					'<code>wp-config.php</code>'
				);
			}
			?>
			<?php _e( 'To make your installation more secure, you should also add:' ); ?>
		</p>
		<p class="configuration-rules-label"><label for="network-wpconfig-authentication"><?php _e( 'Network configuration authentication keys' ); ?></label></p>
		<textarea id="network-wpconfig-authentication" class="code" readonly="readonly" cols="100" rows="<?php echo $num_keys_salts; ?>" aria-describedby="network-wpconfig-authentication-description"><?php echo esc_textarea( $keys_salts_str ); ?></textarea>
			<?php
		}
		?>
		</li>
	<?php
	if ( iis7_supports_permalinks() ) :
		// IIS doesn't support RewriteBase, all your RewriteBase are belong to us.
		$iis_subdir_match       = ltrim( $base, '/' ) . $subdir_match;
		$iis_rewrite_base       = ltrim( $base, '/' ) . $rewrite_base;
		$iis_subdir_replacement = $subdomain_install ? '' : '{R:1}';

		$web_config_file = '<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name="WordPress Rule 1" stopProcessing="true">
                    <match url="^index\.php$" ignoreCase="false" />
                    <action type="None" />
                </rule>';
		if ( is_multisite() && get_site_option( 'ms_files_rewriting' ) ) {
			$web_config_file .= '
                <rule name="WordPress Rule for Files" stopProcessing="true">
                    <match url="^' . $iis_subdir_match . 'files/(.+)" ignoreCase="false" />
                    <action type="Rewrite" url="' . $iis_rewrite_base . WPINC . '/ms-files.php?file={R:1}" appendQueryString="false" />
                </rule>';
		}
			$web_config_file .= '
                <rule name="WordPress Rule 2" stopProcessing="true">
                    <match url="^' . $iis_subdir_match . 'wp-admin$" ignoreCase="false" />
                    <action type="Redirect" url="' . $iis_subdir_replacement . 'wp-admin/" redirectType="Permanent" />
                </rule>
                <rule name="WordPress Rule 3" stopProcessing="true">
                    <match url="^" ignoreCase="false" />
                    <conditions logicalGrouping="MatchAny">
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" />
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" />
                    </conditions>
                    <action type="None" />
                </rule>
                <rule name="WordPress Rule 4" stopProcessing="true">
                    <match url="^' . $iis_subdir_match . '(wp-(content|admin|includes).*)" ignoreCase="false" />
                    <action type="Rewrite" url="' . $iis_rewrite_base . '{R:1}" />
                </rule>
                <rule name="WordPress Rule 5" stopProcessing="true">
                    <match url="^' . $iis_subdir_match . '([_0-9a-zA-Z-]+/)?(.*\.php)$" ignoreCase="false" />
                    <action type="Rewrite" url="' . $iis_rewrite_base . '{R:2}" />
                </rule>
                <rule name="WordPress Rule 6" stopProcessing="true">
                    <match url="." ignoreCase="false" />
                    <action type="Rewrite" url="index.php" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>
';

			echo '<li><p id="network-webconfig-rules-description">';
			printf(
				/* translators: 1: File name (.htaccess or web.config), 2: File path. */
				__( 'Add the following to your %1$s file in %2$s, <strong>replacing</strong> other WordPress rules:' ),
				'<code>web.config</code>',
				'<code>' . $home_path . '</code>'
			);
		echo '</p>';
		if ( ! $subdomain_install && WP_CONTENT_DIR !== ABSPATH . 'wp-content' ) {
			echo '<p><strong>' . __( 'Warning:' ) . ' ' . __( 'Subdirectory networks may not be fully compatible with custom wp-content directories.' ) . '</strong></p>';
		}
		?>
			<p class="configuration-rules-label"><label for="network-webconfig-rules">
				<?php
				printf(
					/* translators: %s: File name (wp-config.php, .htaccess or web.config). */
					__( 'Network configuration rules for %s' ),
					'<code>web.config</code>'
				);
				?>
			</label></p>
			<textarea id="network-webconfig-rules" class="code" readonly="readonly" cols="100" rows="20" aria-describedby="network-webconfig-rules-description"><?php echo esc_textarea( $web_config_file ); ?></textarea>
		</li>
	</ol>

		<?php
	elseif ( $is_nginx ) : // End iis7_supports_permalinks(). Link to Nginx documentation instead:

		echo '<li><p>';
		printf(
			/* translators: %s: Documentation URL. */
			__( 'It seems your network is running with Nginx web server. <a href="%s">Learn more about further configuration</a>.' ),
			__( 'https://developer.wordpress.org/advanced-administration/server/web-server/nginx/' )
		);
		echo '</p></li>';

	else : // End $is_nginx. Construct an .htaccess file instead:

		$ms_files_rewriting = '';
		if ( is_multisite() && get_site_option( 'ms_files_rewriting' ) ) {
			$ms_files_rewriting  = "\n# uploaded files\nRewriteRule ^";
			$ms_files_rewriting .= $subdir_match . "files/(.+) {$rewrite_base}" . WPINC . "/ms-files.php?file={$subdir_replacement_12} [L]" . "\n";
		}

		$htaccess_file = <<<EOF
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase {$base}
RewriteRule ^index\.php$ - [L]
{$ms_files_rewriting}
# add a trailing slash to /wp-admin
RewriteRule ^{$subdir_match}wp-admin$ {$subdir_replacement_01}wp-admin/ [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^{$subdir_match}(wp-(content|admin|includes).*) {$rewrite_base}{$subdir_replacement_12} [L]
RewriteRule ^{$subdir_match}(.*\.php)$ {$rewrite_base}$subdir_replacement_12 [L]
RewriteRule . index.php [L]

EOF;

		echo '<li><p id="network-htaccess-rules-description">';
		printf(
			/* translators: 1: File name (.htaccess or web.config), 2: File path. */
			__( 'Add the following to your %1$s file in %2$s, <strong>replacing</strong> other WordPress rules:' ),
			'<code>.htaccess</code>',
			'<code>' . $home_path . '</code>'
		);
		echo '</p>';
		if ( ! $subdomain_install && WP_CONTENT_DIR !== ABSPATH . 'wp-content' ) {
			echo '<p><strong>' . __( 'Warning:' ) . ' ' . __( 'Subdirectory networks may not be fully compatible with custom wp-content directories.' ) . '</strong></p>';
		}
		?>
			<p class="configuration-rules-label"><label for="network-htaccess-rules">
				<?php
				printf(
					/* translators: %s: File name (wp-config.php, .htaccess or web.config). */
					__( 'Network configuration rules for %s' ),
					'<code>.htaccess</code>'
				);
				?>
			</label></p>
			<textarea id="network-htaccess-rules" class="code" readonly="readonly" cols="100" rows="<?php echo substr_count( $htaccess_file, "\n" ) + 1; ?>" aria-describedby="network-htaccess-rules-description"><?php echo esc_textarea( $htaccess_file ); ?></textarea>
		</li>
	</ol>

		<?php
	endif; // End IIS/Nginx/Apache code branches.

	if ( ! is_multisite() ) {
		?>
		<p><?php _e( 'Once you complete these steps, your network is enabled and configured. You will have to log in again.' ); ?> <a href="<?php echo esc_url( wp_login_url() ); ?>"><?php _e( 'Log In' ); ?></a></p>
		<?php
	}
}
class-pclzip.php000064400000600127151212616040007665 0ustar00<?php
// --------------------------------------------------------------------------------
// PhpConcept Library - Zip Module 2.8.2
// --------------------------------------------------------------------------------
// License GNU/LGPL - Vincent Blavet - August 2009
// http://www.phpconcept.net
// --------------------------------------------------------------------------------
//
// Presentation :
//   PclZip is a PHP library that manage ZIP archives.
//   So far tests show that archives generated by PclZip are readable by
//   WinZip application and other tools.
//
// Description :
//   See readme.txt and http://www.phpconcept.net
//
// Warning :
//   This library and the associated files are non commercial, non professional
//   work.
//   It should not have unexpected results. However if any damage is caused by
//   this software the author can not be responsible.
//   The use of this software is at the risk of the user.
//
// --------------------------------------------------------------------------------
// $Id: pclzip.lib.php,v 1.60 2009/09/30 21:01:04 vblavet Exp $
// --------------------------------------------------------------------------------

  // ----- Constants
  if (!defined('PCLZIP_READ_BLOCK_SIZE')) {
    define( 'PCLZIP_READ_BLOCK_SIZE', 2048 );
  }

  // ----- File list separator
  // In version 1.x of PclZip, the separator for file list is a space
  // (which is not a very smart choice, specifically for windows paths !).
  // A better separator should be a comma (,). This constant gives you the
  // ability to change that.
  // However notice that changing this value, may have impact on existing
  // scripts, using space separated filenames.
  // Recommended values for compatibility with older versions :
  //define( 'PCLZIP_SEPARATOR', ' ' );
  // Recommended values for smart separation of filenames.
  if (!defined('PCLZIP_SEPARATOR')) {
    define( 'PCLZIP_SEPARATOR', ',' );
  }

  // ----- Error configuration
  // 0 : PclZip Class integrated error handling
  // 1 : PclError external library error handling. By enabling this
  //     you must ensure that you have included PclError library.
  // [2,...] : reserved for future use
  if (!defined('PCLZIP_ERROR_EXTERNAL')) {
    define( 'PCLZIP_ERROR_EXTERNAL', 0 );
  }

  // ----- Optional static temporary directory
  //       By default temporary files are generated in the script current
  //       path.
  //       If defined :
  //       - MUST BE terminated by a '/'.
  //       - MUST be a valid, already created directory
  //       Samples :
  // define( 'PCLZIP_TEMPORARY_DIR', '/temp/' );
  // define( 'PCLZIP_TEMPORARY_DIR', 'C:/Temp/' );
  if (!defined('PCLZIP_TEMPORARY_DIR')) {
    define( 'PCLZIP_TEMPORARY_DIR', '' );
  }

  // ----- Optional threshold ratio for use of temporary files
  //       Pclzip sense the size of the file to add/extract and decide to
  //       use or not temporary file. The algorithm is looking for
  //       memory_limit of PHP and apply a ratio.
  //       threshold = memory_limit * ratio.
  //       Recommended values are under 0.5. Default 0.47.
  //       Samples :
  // define( 'PCLZIP_TEMPORARY_FILE_RATIO', 0.5 );
  if (!defined('PCLZIP_TEMPORARY_FILE_RATIO')) {
    define( 'PCLZIP_TEMPORARY_FILE_RATIO', 0.47 );
  }

// --------------------------------------------------------------------------------
// ***** UNDER THIS LINE NOTHING NEEDS TO BE MODIFIED *****
// --------------------------------------------------------------------------------

  // ----- Global variables
  $g_pclzip_version = "2.8.2";

  // ----- Error codes
  //   -1 : Unable to open file in binary write mode
  //   -2 : Unable to open file in binary read mode
  //   -3 : Invalid parameters
  //   -4 : File does not exist
  //   -5 : Filename is too long (max. 255)
  //   -6 : Not a valid zip file
  //   -7 : Invalid extracted file size
  //   -8 : Unable to create directory
  //   -9 : Invalid archive extension
  //  -10 : Invalid archive format
  //  -11 : Unable to delete file (unlink)
  //  -12 : Unable to rename file (rename)
  //  -13 : Invalid header checksum
  //  -14 : Invalid archive size
  define( 'PCLZIP_ERR_USER_ABORTED', 2 );
  define( 'PCLZIP_ERR_NO_ERROR', 0 );
  define( 'PCLZIP_ERR_WRITE_OPEN_FAIL', -1 );
  define( 'PCLZIP_ERR_READ_OPEN_FAIL', -2 );
  define( 'PCLZIP_ERR_INVALID_PARAMETER', -3 );
  define( 'PCLZIP_ERR_MISSING_FILE', -4 );
  define( 'PCLZIP_ERR_FILENAME_TOO_LONG', -5 );
  define( 'PCLZIP_ERR_INVALID_ZIP', -6 );
  define( 'PCLZIP_ERR_BAD_EXTRACTED_FILE', -7 );
  define( 'PCLZIP_ERR_DIR_CREATE_FAIL', -8 );
  define( 'PCLZIP_ERR_BAD_EXTENSION', -9 );
  define( 'PCLZIP_ERR_BAD_FORMAT', -10 );
  define( 'PCLZIP_ERR_DELETE_FILE_FAIL', -11 );
  define( 'PCLZIP_ERR_RENAME_FILE_FAIL', -12 );
  define( 'PCLZIP_ERR_BAD_CHECKSUM', -13 );
  define( 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP', -14 );
  define( 'PCLZIP_ERR_MISSING_OPTION_VALUE', -15 );
  define( 'PCLZIP_ERR_INVALID_OPTION_VALUE', -16 );
  define( 'PCLZIP_ERR_ALREADY_A_DIRECTORY', -17 );
  define( 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION', -18 );
  define( 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION', -19 );
  define( 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE', -20 );
  define( 'PCLZIP_ERR_DIRECTORY_RESTRICTION', -21 );

  // ----- Options values
  define( 'PCLZIP_OPT_PATH', 77001 );
  define( 'PCLZIP_OPT_ADD_PATH', 77002 );
  define( 'PCLZIP_OPT_REMOVE_PATH', 77003 );
  define( 'PCLZIP_OPT_REMOVE_ALL_PATH', 77004 );
  define( 'PCLZIP_OPT_SET_CHMOD', 77005 );
  define( 'PCLZIP_OPT_EXTRACT_AS_STRING', 77006 );
  define( 'PCLZIP_OPT_NO_COMPRESSION', 77007 );
  define( 'PCLZIP_OPT_BY_NAME', 77008 );
  define( 'PCLZIP_OPT_BY_INDEX', 77009 );
  define( 'PCLZIP_OPT_BY_EREG', 77010 );
  define( 'PCLZIP_OPT_BY_PREG', 77011 );
  define( 'PCLZIP_OPT_COMMENT', 77012 );
  define( 'PCLZIP_OPT_ADD_COMMENT', 77013 );
  define( 'PCLZIP_OPT_PREPEND_COMMENT', 77014 );
  define( 'PCLZIP_OPT_EXTRACT_IN_OUTPUT', 77015 );
  define( 'PCLZIP_OPT_REPLACE_NEWER', 77016 );
  define( 'PCLZIP_OPT_STOP_ON_ERROR', 77017 );
  // Having big trouble with crypt. Need to multiply 2 long int
  // which is not correctly supported by PHP ...
  //define( 'PCLZIP_OPT_CRYPT', 77018 );
  define( 'PCLZIP_OPT_EXTRACT_DIR_RESTRICTION', 77019 );
  define( 'PCLZIP_OPT_TEMP_FILE_THRESHOLD', 77020 );
  define( 'PCLZIP_OPT_ADD_TEMP_FILE_THRESHOLD', 77020 ); // alias
  define( 'PCLZIP_OPT_TEMP_FILE_ON', 77021 );
  define( 'PCLZIP_OPT_ADD_TEMP_FILE_ON', 77021 ); // alias
  define( 'PCLZIP_OPT_TEMP_FILE_OFF', 77022 );
  define( 'PCLZIP_OPT_ADD_TEMP_FILE_OFF', 77022 ); // alias

  // ----- File description attributes
  define( 'PCLZIP_ATT_FILE_NAME', 79001 );
  define( 'PCLZIP_ATT_FILE_NEW_SHORT_NAME', 79002 );
  define( 'PCLZIP_ATT_FILE_NEW_FULL_NAME', 79003 );
  define( 'PCLZIP_ATT_FILE_MTIME', 79004 );
  define( 'PCLZIP_ATT_FILE_CONTENT', 79005 );
  define( 'PCLZIP_ATT_FILE_COMMENT', 79006 );

  // ----- Call backs values
  define( 'PCLZIP_CB_PRE_EXTRACT', 78001 );
  define( 'PCLZIP_CB_POST_EXTRACT', 78002 );
  define( 'PCLZIP_CB_PRE_ADD', 78003 );
  define( 'PCLZIP_CB_POST_ADD', 78004 );
  /* For future use
  define( 'PCLZIP_CB_PRE_LIST', 78005 );
  define( 'PCLZIP_CB_POST_LIST', 78006 );
  define( 'PCLZIP_CB_PRE_DELETE', 78007 );
  define( 'PCLZIP_CB_POST_DELETE', 78008 );
  */

  // --------------------------------------------------------------------------------
  // Class : PclZip
  // Description :
  //   PclZip is the class that represent a Zip archive.
  //   The public methods allow the manipulation of the archive.
  // Attributes :
  //   Attributes must not be accessed directly.
  // Methods :
  //   PclZip() : Object creator
  //   create() : Creates the Zip archive
  //   listContent() : List the content of the Zip archive
  //   extract() : Extract the content of the archive
  //   properties() : List the properties of the archive
  // --------------------------------------------------------------------------------
  class PclZip
  {
    // ----- Filename of the zip file
    var $zipname = '';

    // ----- File descriptor of the zip file
    var $zip_fd = 0;

    // ----- Internal error handling
    var $error_code = 1;
    var $error_string = '';

    // ----- Current status of the magic_quotes_runtime
    // This value store the php configuration for magic_quotes
    // The class can then disable the magic_quotes and reset it after
    var $magic_quotes_status;

  // --------------------------------------------------------------------------------
  // Function : PclZip()
  // Description :
  //   Creates a PclZip object and set the name of the associated Zip archive
  //   filename.
  //   Note that no real action is taken, if the archive does not exist it is not
  //   created. Use create() for that.
  // --------------------------------------------------------------------------------
  function __construct($p_zipname)
  {

    // ----- Tests the zlib
    if (!function_exists('gzopen'))
    {
      die('Abort '.basename(__FILE__).' : Missing zlib extensions');
    }

    // ----- Set the attributes
    $this->zipname = $p_zipname;
    $this->zip_fd = 0;
    $this->magic_quotes_status = -1;

    // ----- Return
    return;
  }

  public function PclZip($p_zipname) {
    self::__construct($p_zipname);
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function :
  //   create($p_filelist, $p_add_dir="", $p_remove_dir="")
  //   create($p_filelist, $p_option, $p_option_value, ...)
  // Description :
  //   This method supports two different synopsis. The first one is historical.
  //   This method creates a Zip Archive. The Zip file is created in the
  //   filesystem. The files and directories indicated in $p_filelist
  //   are added in the archive. See the parameters description for the
  //   supported format of $p_filelist.
  //   When a directory is in the list, the directory and its content is added
  //   in the archive.
  //   In this synopsis, the function takes an optional variable list of
  //   options. See below the supported options.
  // Parameters :
  //   $p_filelist : An array containing file or directory names, or
  //                 a string containing one filename or one directory name, or
  //                 a string containing a list of filenames and/or directory
  //                 names separated by spaces.
  //   $p_add_dir : A path to add before the real path of the archived file,
  //                in order to have it memorized in the archive.
  //   $p_remove_dir : A path to remove from the real path of the file to archive,
  //                   in order to have a shorter path memorized in the archive.
  //                   When $p_add_dir and $p_remove_dir are set, $p_remove_dir
  //                   is removed first, before $p_add_dir is added.
  // Options :
  //   PCLZIP_OPT_ADD_PATH :
  //   PCLZIP_OPT_REMOVE_PATH :
  //   PCLZIP_OPT_REMOVE_ALL_PATH :
  //   PCLZIP_OPT_COMMENT :
  //   PCLZIP_CB_PRE_ADD :
  //   PCLZIP_CB_POST_ADD :
  // Return Values :
  //   0 on failure,
  //   The list of the added files, with a status of the add action.
  //   (see PclZip::listContent() for list entry format)
  // --------------------------------------------------------------------------------
  function create($p_filelist)
  {
    $v_result=1;

    // ----- Reset the error handler
    $this->privErrorReset();

    // ----- Set default values
    $v_options = array();
    $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE;

    // ----- Look for variable options arguments
    $v_size = func_num_args();

    // ----- Look for arguments
    if ($v_size > 1) {
      // ----- Get the arguments
      $v_arg_list = func_get_args();

      // ----- Remove from the options list the first argument
      array_shift($v_arg_list);
      $v_size--;

      // ----- Look for first arg
      if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {

        // ----- Parse the options
        $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
                                            array (PCLZIP_OPT_REMOVE_PATH => 'optional',
                                                   PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
                                                   PCLZIP_OPT_ADD_PATH => 'optional',
                                                   PCLZIP_CB_PRE_ADD => 'optional',
                                                   PCLZIP_CB_POST_ADD => 'optional',
                                                   PCLZIP_OPT_NO_COMPRESSION => 'optional',
                                                   PCLZIP_OPT_COMMENT => 'optional',
                                                   PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
                                                   PCLZIP_OPT_TEMP_FILE_ON => 'optional',
                                                   PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
                                                   //, PCLZIP_OPT_CRYPT => 'optional'
                                             ));
        if ($v_result != 1) {
          return 0;
        }
      }

      // ----- Look for 2 args
      // Here we need to support the first historic synopsis of the
      // method.
      else {

        // ----- Get the first argument
        $v_options[PCLZIP_OPT_ADD_PATH] = $v_arg_list[0];

        // ----- Look for the optional second argument
        if ($v_size == 2) {
          $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
        }
        else if ($v_size > 2) {
          PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
		                       "Invalid number / type of arguments");
          return 0;
        }
      }
    }

    // ----- Look for default option values
    $this->privOptionDefaultThreshold($v_options);

    // ----- Init
    $v_string_list = array();
    $v_att_list = array();
    $v_filedescr_list = array();
    $p_result_list = array();

    // ----- Look if the $p_filelist is really an array
    if (is_array($p_filelist)) {

      // ----- Look if the first element is also an array
      //       This will mean that this is a file description entry
      if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
        $v_att_list = $p_filelist;
      }

      // ----- The list is a list of string names
      else {
        $v_string_list = $p_filelist;
      }
    }

    // ----- Look if the $p_filelist is a string
    else if (is_string($p_filelist)) {
      // ----- Create a list from the string
      $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist);
    }

    // ----- Invalid variable type for $p_filelist
    else {
      PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist");
      return 0;
    }

    // ----- Reformat the string list
    if (sizeof($v_string_list) != 0) {
      foreach ($v_string_list as $v_string) {
        if ($v_string != '') {
          $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
        }
        else {
        }
      }
    }

    // ----- For each file in the list check the attributes
    $v_supported_attributes
    = array ( PCLZIP_ATT_FILE_NAME => 'mandatory'
             ,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional'
             ,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional'
             ,PCLZIP_ATT_FILE_MTIME => 'optional'
             ,PCLZIP_ATT_FILE_CONTENT => 'optional'
             ,PCLZIP_ATT_FILE_COMMENT => 'optional'
						);
    foreach ($v_att_list as $v_entry) {
      $v_result = $this->privFileDescrParseAtt($v_entry,
                                               $v_filedescr_list[],
                                               $v_options,
                                               $v_supported_attributes);
      if ($v_result != 1) {
        return 0;
      }
    }

    // ----- Expand the filelist (expand directories)
    $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
    if ($v_result != 1) {
      return 0;
    }

    // ----- Call the create fct
    $v_result = $this->privCreate($v_filedescr_list, $p_result_list, $v_options);
    if ($v_result != 1) {
      return 0;
    }

    // ----- Return
    return $p_result_list;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function :
  //   add($p_filelist, $p_add_dir="", $p_remove_dir="")
  //   add($p_filelist, $p_option, $p_option_value, ...)
  // Description :
  //   This method supports two synopsis. The first one is historical.
  //   This methods add the list of files in an existing archive.
  //   If a file with the same name already exists, it is added at the end of the
  //   archive, the first one is still present.
  //   If the archive does not exist, it is created.
  // Parameters :
  //   $p_filelist : An array containing file or directory names, or
  //                 a string containing one filename or one directory name, or
  //                 a string containing a list of filenames and/or directory
  //                 names separated by spaces.
  //   $p_add_dir : A path to add before the real path of the archived file,
  //                in order to have it memorized in the archive.
  //   $p_remove_dir : A path to remove from the real path of the file to archive,
  //                   in order to have a shorter path memorized in the archive.
  //                   When $p_add_dir and $p_remove_dir are set, $p_remove_dir
  //                   is removed first, before $p_add_dir is added.
  // Options :
  //   PCLZIP_OPT_ADD_PATH :
  //   PCLZIP_OPT_REMOVE_PATH :
  //   PCLZIP_OPT_REMOVE_ALL_PATH :
  //   PCLZIP_OPT_COMMENT :
  //   PCLZIP_OPT_ADD_COMMENT :
  //   PCLZIP_OPT_PREPEND_COMMENT :
  //   PCLZIP_CB_PRE_ADD :
  //   PCLZIP_CB_POST_ADD :
  // Return Values :
  //   0 on failure,
  //   The list of the added files, with a status of the add action.
  //   (see PclZip::listContent() for list entry format)
  // --------------------------------------------------------------------------------
  function add($p_filelist)
  {
    $v_result=1;

    // ----- Reset the error handler
    $this->privErrorReset();

    // ----- Set default values
    $v_options = array();
    $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE;

    // ----- Look for variable options arguments
    $v_size = func_num_args();

    // ----- Look for arguments
    if ($v_size > 1) {
      // ----- Get the arguments
      $v_arg_list = func_get_args();

      // ----- Remove form the options list the first argument
      array_shift($v_arg_list);
      $v_size--;

      // ----- Look for first arg
      if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {

        // ----- Parse the options
        $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
                                            array (PCLZIP_OPT_REMOVE_PATH => 'optional',
                                                   PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
                                                   PCLZIP_OPT_ADD_PATH => 'optional',
                                                   PCLZIP_CB_PRE_ADD => 'optional',
                                                   PCLZIP_CB_POST_ADD => 'optional',
                                                   PCLZIP_OPT_NO_COMPRESSION => 'optional',
                                                   PCLZIP_OPT_COMMENT => 'optional',
                                                   PCLZIP_OPT_ADD_COMMENT => 'optional',
                                                   PCLZIP_OPT_PREPEND_COMMENT => 'optional',
                                                   PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
                                                   PCLZIP_OPT_TEMP_FILE_ON => 'optional',
                                                   PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
                                                   //, PCLZIP_OPT_CRYPT => 'optional'
												   ));
        if ($v_result != 1) {
          return 0;
        }
      }

      // ----- Look for 2 args
      // Here we need to support the first historic synopsis of the
      // method.
      else {

        // ----- Get the first argument
        $v_options[PCLZIP_OPT_ADD_PATH] = $v_add_path = $v_arg_list[0];

        // ----- Look for the optional second argument
        if ($v_size == 2) {
          $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1];
        }
        else if ($v_size > 2) {
          // ----- Error log
          PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");

          // ----- Return
          return 0;
        }
      }
    }

    // ----- Look for default option values
    $this->privOptionDefaultThreshold($v_options);

    // ----- Init
    $v_string_list = array();
    $v_att_list = array();
    $v_filedescr_list = array();
    $p_result_list = array();

    // ----- Look if the $p_filelist is really an array
    if (is_array($p_filelist)) {

      // ----- Look if the first element is also an array
      //       This will mean that this is a file description entry
      if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
        $v_att_list = $p_filelist;
      }

      // ----- The list is a list of string names
      else {
        $v_string_list = $p_filelist;
      }
    }

    // ----- Look if the $p_filelist is a string
    else if (is_string($p_filelist)) {
      // ----- Create a list from the string
      $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist);
    }

    // ----- Invalid variable type for $p_filelist
    else {
      PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type '".gettype($p_filelist)."' for p_filelist");
      return 0;
    }

    // ----- Reformat the string list
    if (sizeof($v_string_list) != 0) {
      foreach ($v_string_list as $v_string) {
        $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
      }
    }

    // ----- For each file in the list check the attributes
    $v_supported_attributes
    = array ( PCLZIP_ATT_FILE_NAME => 'mandatory'
             ,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional'
             ,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional'
             ,PCLZIP_ATT_FILE_MTIME => 'optional'
             ,PCLZIP_ATT_FILE_CONTENT => 'optional'
             ,PCLZIP_ATT_FILE_COMMENT => 'optional'
						);
    foreach ($v_att_list as $v_entry) {
      $v_result = $this->privFileDescrParseAtt($v_entry,
                                               $v_filedescr_list[],
                                               $v_options,
                                               $v_supported_attributes);
      if ($v_result != 1) {
        return 0;
      }
    }

    // ----- Expand the filelist (expand directories)
    $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
    if ($v_result != 1) {
      return 0;
    }

    // ----- Call the create fct
    $v_result = $this->privAdd($v_filedescr_list, $p_result_list, $v_options);
    if ($v_result != 1) {
      return 0;
    }

    // ----- Return
    return $p_result_list;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : listContent()
  // Description :
  //   This public method, gives the list of the files and directories, with their
  //   properties.
  //   The properties of each entries in the list are (used also in other functions) :
  //     filename : Name of the file. For a create or add action it is the filename
  //                given by the user. For an extract function it is the filename
  //                of the extracted file.
  //     stored_filename : Name of the file / directory stored in the archive.
  //     size : Size of the stored file.
  //     compressed_size : Size of the file's data compressed in the archive
  //                       (without the headers overhead)
  //     mtime : Last known modification date of the file (UNIX timestamp)
  //     comment : Comment associated with the file
  //     folder : true | false
  //     index : index of the file in the archive
  //     status : status of the action (depending of the action) :
  //              Values are :
  //                ok : OK !
  //                filtered : the file / dir is not extracted (filtered by user)
  //                already_a_directory : the file can not be extracted because a
  //                                      directory with the same name already exists
  //                write_protected : the file can not be extracted because a file
  //                                  with the same name already exists and is
  //                                  write protected
  //                newer_exist : the file was not extracted because a newer file exists
  //                path_creation_fail : the file is not extracted because the folder
  //                                     does not exist and can not be created
  //                write_error : the file was not extracted because there was an
  //                              error while writing the file
  //                read_error : the file was not extracted because there was an error
  //                             while reading the file
  //                invalid_header : the file was not extracted because of an archive
  //                                 format error (bad file header)
  //   Note that each time a method can continue operating when there
  //   is an action error on a file, the error is only logged in the file status.
  // Return Values :
  //   0 on an unrecoverable failure,
  //   The list of the files in the archive.
  // --------------------------------------------------------------------------------
  function listContent()
  {
    $v_result=1;

    // ----- Reset the error handler
    $this->privErrorReset();

    // ----- Check archive
    if (!$this->privCheckFormat()) {
      return(0);
    }

    // ----- Call the extracting fct
    $p_list = array();
    if (($v_result = $this->privList($p_list)) != 1)
    {
      unset($p_list);
      return(0);
    }

    // ----- Return
    return $p_list;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function :
  //   extract($p_path="./", $p_remove_path="")
  //   extract([$p_option, $p_option_value, ...])
  // Description :
  //   This method supports two synopsis. The first one is historical.
  //   This method extract all the files / directories from the archive to the
  //   folder indicated in $p_path.
  //   If you want to ignore the 'root' part of path of the memorized files
  //   you can indicate this in the optional $p_remove_path parameter.
  //   By default, if a newer file with the same name already exists, the
  //   file is not extracted.
  //
  //   If both PCLZIP_OPT_PATH and PCLZIP_OPT_ADD_PATH options
  //   are used, the path indicated in PCLZIP_OPT_ADD_PATH is append
  //   at the end of the path value of PCLZIP_OPT_PATH.
  // Parameters :
  //   $p_path : Path where the files and directories are to be extracted
  //   $p_remove_path : First part ('root' part) of the memorized path
  //                    (if any similar) to remove while extracting.
  // Options :
  //   PCLZIP_OPT_PATH :
  //   PCLZIP_OPT_ADD_PATH :
  //   PCLZIP_OPT_REMOVE_PATH :
  //   PCLZIP_OPT_REMOVE_ALL_PATH :
  //   PCLZIP_CB_PRE_EXTRACT :
  //   PCLZIP_CB_POST_EXTRACT :
  // Return Values :
  //   0 or a negative value on failure,
  //   The list of the extracted files, with a status of the action.
  //   (see PclZip::listContent() for list entry format)
  // --------------------------------------------------------------------------------
  function extract()
  {
    $v_result=1;

    // ----- Reset the error handler
    $this->privErrorReset();

    // ----- Check archive
    if (!$this->privCheckFormat()) {
      return(0);
    }

    // ----- Set default values
    $v_options = array();
//    $v_path = "./";
    $v_path = '';
    $v_remove_path = "";
    $v_remove_all_path = false;

    // ----- Look for variable options arguments
    $v_size = func_num_args();

    // ----- Default values for option
    $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;

    // ----- Look for arguments
    if ($v_size > 0) {
      // ----- Get the arguments
      $v_arg_list = func_get_args();

      // ----- Look for first arg
      if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {

        // ----- Parse the options
        $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
                                            array (PCLZIP_OPT_PATH => 'optional',
                                                   PCLZIP_OPT_REMOVE_PATH => 'optional',
                                                   PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
                                                   PCLZIP_OPT_ADD_PATH => 'optional',
                                                   PCLZIP_CB_PRE_EXTRACT => 'optional',
                                                   PCLZIP_CB_POST_EXTRACT => 'optional',
                                                   PCLZIP_OPT_SET_CHMOD => 'optional',
                                                   PCLZIP_OPT_BY_NAME => 'optional',
                                                   PCLZIP_OPT_BY_EREG => 'optional',
                                                   PCLZIP_OPT_BY_PREG => 'optional',
                                                   PCLZIP_OPT_BY_INDEX => 'optional',
                                                   PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
                                                   PCLZIP_OPT_EXTRACT_IN_OUTPUT => 'optional',
                                                   PCLZIP_OPT_REPLACE_NEWER => 'optional'
                                                   ,PCLZIP_OPT_STOP_ON_ERROR => 'optional'
                                                   ,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional',
                                                   PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
                                                   PCLZIP_OPT_TEMP_FILE_ON => 'optional',
                                                   PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
												    ));
        if ($v_result != 1) {
          return 0;
        }

        // ----- Set the arguments
        if (isset($v_options[PCLZIP_OPT_PATH])) {
          $v_path = $v_options[PCLZIP_OPT_PATH];
        }
        if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
          $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
        }
        if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
          $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
        }
        if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
          // ----- Check for '/' in last path char
          if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
            $v_path .= '/';
          }
          $v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
        }
      }

      // ----- Look for 2 args
      // Here we need to support the first historic synopsis of the
      // method.
      else {

        // ----- Get the first argument
        $v_path = $v_arg_list[0];

        // ----- Look for the optional second argument
        if ($v_size == 2) {
          $v_remove_path = $v_arg_list[1];
        }
        else if ($v_size > 2) {
          // ----- Error log
          PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");

          // ----- Return
          return 0;
        }
      }
    }

    // ----- Look for default option values
    $this->privOptionDefaultThreshold($v_options);

    // ----- Trace

    // ----- Call the extracting fct
    $p_list = array();
    $v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path,
	                                     $v_remove_all_path, $v_options);
    if ($v_result < 1) {
      unset($p_list);
      return(0);
    }

    // ----- Return
    return $p_list;
  }
  // --------------------------------------------------------------------------------


  // --------------------------------------------------------------------------------
  // Function :
  //   extractByIndex($p_index, $p_path="./", $p_remove_path="")
  //   extractByIndex($p_index, [$p_option, $p_option_value, ...])
  // Description :
  //   This method supports two synopsis. The first one is historical.
  //   This method is doing a partial extract of the archive.
  //   The extracted files or folders are identified by their index in the
  //   archive (from 0 to n).
  //   Note that if the index identify a folder, only the folder entry is
  //   extracted, not all the files included in the archive.
  // Parameters :
  //   $p_index : A single index (integer) or a string of indexes of files to
  //              extract. The form of the string is "0,4-6,8-12" with only numbers
  //              and '-' for range or ',' to separate ranges. No spaces or ';'
  //              are allowed.
  //   $p_path : Path where the files and directories are to be extracted
  //   $p_remove_path : First part ('root' part) of the memorized path
  //                    (if any similar) to remove while extracting.
  // Options :
  //   PCLZIP_OPT_PATH :
  //   PCLZIP_OPT_ADD_PATH :
  //   PCLZIP_OPT_REMOVE_PATH :
  //   PCLZIP_OPT_REMOVE_ALL_PATH :
  //   PCLZIP_OPT_EXTRACT_AS_STRING : The files are extracted as strings and
  //     not as files.
  //     The resulting content is in a new field 'content' in the file
  //     structure.
  //     This option must be used alone (any other options are ignored).
  //   PCLZIP_CB_PRE_EXTRACT :
  //   PCLZIP_CB_POST_EXTRACT :
  // Return Values :
  //   0 on failure,
  //   The list of the extracted files, with a status of the action.
  //   (see PclZip::listContent() for list entry format)
  // --------------------------------------------------------------------------------
  //function extractByIndex($p_index, options...)
  function extractByIndex($p_index)
  {
    $v_result=1;

    // ----- Reset the error handler
    $this->privErrorReset();

    // ----- Check archive
    if (!$this->privCheckFormat()) {
      return(0);
    }

    // ----- Set default values
    $v_options = array();
//    $v_path = "./";
    $v_path = '';
    $v_remove_path = "";
    $v_remove_all_path = false;

    // ----- Look for variable options arguments
    $v_size = func_num_args();

    // ----- Default values for option
    $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;

    // ----- Look for arguments
    if ($v_size > 1) {
      // ----- Get the arguments
      $v_arg_list = func_get_args();

      // ----- Remove form the options list the first argument
      array_shift($v_arg_list);
      $v_size--;

      // ----- Look for first arg
      if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {

        // ----- Parse the options
        $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
                                            array (PCLZIP_OPT_PATH => 'optional',
                                                   PCLZIP_OPT_REMOVE_PATH => 'optional',
                                                   PCLZIP_OPT_REMOVE_ALL_PATH => 'optional',
                                                   PCLZIP_OPT_EXTRACT_AS_STRING => 'optional',
                                                   PCLZIP_OPT_ADD_PATH => 'optional',
                                                   PCLZIP_CB_PRE_EXTRACT => 'optional',
                                                   PCLZIP_CB_POST_EXTRACT => 'optional',
                                                   PCLZIP_OPT_SET_CHMOD => 'optional',
                                                   PCLZIP_OPT_REPLACE_NEWER => 'optional'
                                                   ,PCLZIP_OPT_STOP_ON_ERROR => 'optional'
                                                   ,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional',
                                                   PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional',
                                                   PCLZIP_OPT_TEMP_FILE_ON => 'optional',
                                                   PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
												   ));
        if ($v_result != 1) {
          return 0;
        }

        // ----- Set the arguments
        if (isset($v_options[PCLZIP_OPT_PATH])) {
          $v_path = $v_options[PCLZIP_OPT_PATH];
        }
        if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) {
          $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH];
        }
        if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
          $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH];
        }
        if (isset($v_options[PCLZIP_OPT_ADD_PATH])) {
          // ----- Check for '/' in last path char
          if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) {
            $v_path .= '/';
          }
          $v_path .= $v_options[PCLZIP_OPT_ADD_PATH];
        }
        if (!isset($v_options[PCLZIP_OPT_EXTRACT_AS_STRING])) {
          $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
        }
        else {
        }
      }

      // ----- Look for 2 args
      // Here we need to support the first historic synopsis of the
      // method.
      else {

        // ----- Get the first argument
        $v_path = $v_arg_list[0];

        // ----- Look for the optional second argument
        if ($v_size == 2) {
          $v_remove_path = $v_arg_list[1];
        }
        else if ($v_size > 2) {
          // ----- Error log
          PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");

          // ----- Return
          return 0;
        }
      }
    }

    // ----- Trace

    // ----- Trick
    // Here I want to reuse extractByRule(), so I need to parse the $p_index
    // with privParseOptions()
    $v_arg_trick = array (PCLZIP_OPT_BY_INDEX, $p_index);
    $v_options_trick = array();
    $v_result = $this->privParseOptions($v_arg_trick, sizeof($v_arg_trick), $v_options_trick,
                                        array (PCLZIP_OPT_BY_INDEX => 'optional' ));
    if ($v_result != 1) {
        return 0;
    }
    $v_options[PCLZIP_OPT_BY_INDEX] = $v_options_trick[PCLZIP_OPT_BY_INDEX];

    // ----- Look for default option values
    $this->privOptionDefaultThreshold($v_options);

    // ----- Call the extracting fct
    if (($v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) < 1) {
        return(0);
    }

    // ----- Return
    return $p_list;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function :
  //   delete([$p_option, $p_option_value, ...])
  // Description :
  //   This method removes files from the archive.
  //   If no parameters are given, then all the archive is emptied.
  // Parameters :
  //   None or optional arguments.
  // Options :
  //   PCLZIP_OPT_BY_INDEX :
  //   PCLZIP_OPT_BY_NAME :
  //   PCLZIP_OPT_BY_EREG :
  //   PCLZIP_OPT_BY_PREG :
  // Return Values :
  //   0 on failure,
  //   The list of the files which are still present in the archive.
  //   (see PclZip::listContent() for list entry format)
  // --------------------------------------------------------------------------------
  function delete()
  {
    $v_result=1;

    // ----- Reset the error handler
    $this->privErrorReset();

    // ----- Check archive
    if (!$this->privCheckFormat()) {
      return(0);
    }

    // ----- Set default values
    $v_options = array();

    // ----- Look for variable options arguments
    $v_size = func_num_args();

    // ----- Look for arguments
    if ($v_size > 0) {
      // ----- Get the arguments
      $v_arg_list = func_get_args();

      // ----- Parse the options
      $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
                                        array (PCLZIP_OPT_BY_NAME => 'optional',
                                               PCLZIP_OPT_BY_EREG => 'optional',
                                               PCLZIP_OPT_BY_PREG => 'optional',
                                               PCLZIP_OPT_BY_INDEX => 'optional' ));
      if ($v_result != 1) {
          return 0;
      }
    }

    // ----- Magic quotes trick
    $this->privDisableMagicQuotes();

    // ----- Call the delete fct
    $v_list = array();
    if (($v_result = $this->privDeleteByRule($v_list, $v_options)) != 1) {
      $this->privSwapBackMagicQuotes();
      unset($v_list);
      return(0);
    }

    // ----- Magic quotes trick
    $this->privSwapBackMagicQuotes();

    // ----- Return
    return $v_list;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : deleteByIndex()
  // Description :
  //   ***** Deprecated *****
  //   delete(PCLZIP_OPT_BY_INDEX, $p_index) should be preferred.
  // --------------------------------------------------------------------------------
  function deleteByIndex($p_index)
  {

    $p_list = $this->delete(PCLZIP_OPT_BY_INDEX, $p_index);

    // ----- Return
    return $p_list;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : properties()
  // Description :
  //   This method gives the properties of the archive.
  //   The properties are :
  //     nb : Number of files in the archive
  //     comment : Comment associated with the archive file
  //     status : not_exist, ok
  // Parameters :
  //   None
  // Return Values :
  //   0 on failure,
  //   An array with the archive properties.
  // --------------------------------------------------------------------------------
  function properties()
  {

    // ----- Reset the error handler
    $this->privErrorReset();

    // ----- Magic quotes trick
    $this->privDisableMagicQuotes();

    // ----- Check archive
    if (!$this->privCheckFormat()) {
      $this->privSwapBackMagicQuotes();
      return(0);
    }

    // ----- Default properties
    $v_prop = array();
    $v_prop['comment'] = '';
    $v_prop['nb'] = 0;
    $v_prop['status'] = 'not_exist';

    // ----- Look if file exists
    if (@is_file($this->zipname))
    {
      // ----- Open the zip file
      if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
      {
        $this->privSwapBackMagicQuotes();

        // ----- Error log
        PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');

        // ----- Return
        return 0;
      }

      // ----- Read the central directory information
      $v_central_dir = array();
      if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
      {
        $this->privSwapBackMagicQuotes();
        return 0;
      }

      // ----- Close the zip file
      $this->privCloseFd();

      // ----- Set the user attributes
      $v_prop['comment'] = $v_central_dir['comment'];
      $v_prop['nb'] = $v_central_dir['entries'];
      $v_prop['status'] = 'ok';
    }

    // ----- Magic quotes trick
    $this->privSwapBackMagicQuotes();

    // ----- Return
    return $v_prop;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : duplicate()
  // Description :
  //   This method creates an archive by copying the content of an other one. If
  //   the archive already exist, it is replaced by the new one without any warning.
  // Parameters :
  //   $p_archive : The filename of a valid archive, or
  //                a valid PclZip object.
  // Return Values :
  //   1 on success.
  //   0 or a negative value on error (error code).
  // --------------------------------------------------------------------------------
  function duplicate($p_archive)
  {
    $v_result = 1;

    // ----- Reset the error handler
    $this->privErrorReset();

    // ----- Look if the $p_archive is an instantiated PclZip object
    if ($p_archive instanceof pclzip)
    {

      // ----- Duplicate the archive
      $v_result = $this->privDuplicate($p_archive->zipname);
    }

    // ----- Look if the $p_archive is a string (so a filename)
    else if (is_string($p_archive))
    {

      // ----- Check that $p_archive is a valid zip file
      // TBC : Should also check the archive format
      if (!is_file($p_archive)) {
        // ----- Error log
        PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "No file with filename '".$p_archive."'");
        $v_result = PCLZIP_ERR_MISSING_FILE;
      }
      else {
        // ----- Duplicate the archive
        $v_result = $this->privDuplicate($p_archive);
      }
    }

    // ----- Invalid variable
    else
    {
      // ----- Error log
      PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
      $v_result = PCLZIP_ERR_INVALID_PARAMETER;
    }

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : merge()
  // Description :
  //   This method merge the $p_archive_to_add archive at the end of the current
  //   one ($this).
  //   If the archive ($this) does not exist, the merge becomes a duplicate.
  //   If the $p_archive_to_add archive does not exist, the merge is a success.
  // Parameters :
  //   $p_archive_to_add : It can be directly the filename of a valid zip archive,
  //                       or a PclZip object archive.
  // Return Values :
  //   1 on success,
  //   0 or negative values on error (see below).
  // --------------------------------------------------------------------------------
  function merge($p_archive_to_add)
  {
    $v_result = 1;

    // ----- Reset the error handler
    $this->privErrorReset();

    // ----- Check archive
    if (!$this->privCheckFormat()) {
      return(0);
    }

    // ----- Look if the $p_archive_to_add is an instantiated PclZip object
    if ($p_archive_to_add instanceof pclzip)
    {

      // ----- Merge the archive
      $v_result = $this->privMerge($p_archive_to_add);
    }

    // ----- Look if the $p_archive_to_add is a string (so a filename)
    else if (is_string($p_archive_to_add))
    {

      // ----- Create a temporary archive
      $v_object_archive = new PclZip($p_archive_to_add);

      // ----- Merge the archive
      $v_result = $this->privMerge($v_object_archive);
    }

    // ----- Invalid variable
    else
    {
      // ----- Error log
      PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add");
      $v_result = PCLZIP_ERR_INVALID_PARAMETER;
    }

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------



  // --------------------------------------------------------------------------------
  // Function : errorCode()
  // Description :
  // Parameters :
  // --------------------------------------------------------------------------------
  function errorCode()
  {
    if (PCLZIP_ERROR_EXTERNAL == 1) {
      return(PclErrorCode());
    }
    else {
      return($this->error_code);
    }
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : errorName()
  // Description :
  // Parameters :
  // --------------------------------------------------------------------------------
  function errorName($p_with_code=false)
  {
    $v_name = array ( PCLZIP_ERR_NO_ERROR => 'PCLZIP_ERR_NO_ERROR',
                      PCLZIP_ERR_WRITE_OPEN_FAIL => 'PCLZIP_ERR_WRITE_OPEN_FAIL',
                      PCLZIP_ERR_READ_OPEN_FAIL => 'PCLZIP_ERR_READ_OPEN_FAIL',
                      PCLZIP_ERR_INVALID_PARAMETER => 'PCLZIP_ERR_INVALID_PARAMETER',
                      PCLZIP_ERR_MISSING_FILE => 'PCLZIP_ERR_MISSING_FILE',
                      PCLZIP_ERR_FILENAME_TOO_LONG => 'PCLZIP_ERR_FILENAME_TOO_LONG',
                      PCLZIP_ERR_INVALID_ZIP => 'PCLZIP_ERR_INVALID_ZIP',
                      PCLZIP_ERR_BAD_EXTRACTED_FILE => 'PCLZIP_ERR_BAD_EXTRACTED_FILE',
                      PCLZIP_ERR_DIR_CREATE_FAIL => 'PCLZIP_ERR_DIR_CREATE_FAIL',
                      PCLZIP_ERR_BAD_EXTENSION => 'PCLZIP_ERR_BAD_EXTENSION',
                      PCLZIP_ERR_BAD_FORMAT => 'PCLZIP_ERR_BAD_FORMAT',
                      PCLZIP_ERR_DELETE_FILE_FAIL => 'PCLZIP_ERR_DELETE_FILE_FAIL',
                      PCLZIP_ERR_RENAME_FILE_FAIL => 'PCLZIP_ERR_RENAME_FILE_FAIL',
                      PCLZIP_ERR_BAD_CHECKSUM => 'PCLZIP_ERR_BAD_CHECKSUM',
                      PCLZIP_ERR_INVALID_ARCHIVE_ZIP => 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP',
                      PCLZIP_ERR_MISSING_OPTION_VALUE => 'PCLZIP_ERR_MISSING_OPTION_VALUE',
                      PCLZIP_ERR_INVALID_OPTION_VALUE => 'PCLZIP_ERR_INVALID_OPTION_VALUE',
                      PCLZIP_ERR_UNSUPPORTED_COMPRESSION => 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION',
                      PCLZIP_ERR_UNSUPPORTED_ENCRYPTION => 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION'
                      ,PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE => 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE'
                      ,PCLZIP_ERR_DIRECTORY_RESTRICTION => 'PCLZIP_ERR_DIRECTORY_RESTRICTION'
                    );

    if (isset($v_name[$this->error_code])) {
      $v_value = $v_name[$this->error_code];
    }
    else {
      $v_value = 'NoName';
    }

    if ($p_with_code) {
      return($v_value.' ('.$this->error_code.')');
    }
    else {
      return($v_value);
    }
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : errorInfo()
  // Description :
  // Parameters :
  // --------------------------------------------------------------------------------
  function errorInfo($p_full=false)
  {
    if (PCLZIP_ERROR_EXTERNAL == 1) {
      return(PclErrorString());
    }
    else {
      if ($p_full) {
        return($this->errorName(true)." : ".$this->error_string);
      }
      else {
        return($this->error_string." [code ".$this->error_code."]");
      }
    }
  }
  // --------------------------------------------------------------------------------


// --------------------------------------------------------------------------------
// ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS *****
// *****                                                        *****
// *****       THESES FUNCTIONS MUST NOT BE USED DIRECTLY       *****
// --------------------------------------------------------------------------------



  // --------------------------------------------------------------------------------
  // Function : privCheckFormat()
  // Description :
  //   This method check that the archive exists and is a valid zip archive.
  //   Several level of check exists. (future)
  // Parameters :
  //   $p_level : Level of check. Default 0.
  //              0 : Check the first bytes (magic codes) (default value))
  //              1 : 0 + Check the central directory (future)
  //              2 : 1 + Check each file header (future)
  // Return Values :
  //   true on success,
  //   false on error, the error code is set.
  // --------------------------------------------------------------------------------
  function privCheckFormat($p_level=0)
  {
    $v_result = true;

	// ----- Reset the file system cache
    clearstatcache();

    // ----- Reset the error handler
    $this->privErrorReset();

    // ----- Look if the file exits
    if (!is_file($this->zipname)) {
      // ----- Error log
      PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "Missing archive file '".$this->zipname."'");
      return(false);
    }

    // ----- Check that the file is readable
    if (!is_readable($this->zipname)) {
      // ----- Error log
      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to read archive '".$this->zipname."'");
      return(false);
    }

    // ----- Check the magic code
    // TBC

    // ----- Check the central header
    // TBC

    // ----- Check each file header
    // TBC

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privParseOptions()
  // Description :
  //   This internal methods reads the variable list of arguments ($p_options_list,
  //   $p_size) and generate an array with the options and values ($v_result_list).
  //   $v_requested_options contains the options that can be present and those that
  //   must be present.
  //   $v_requested_options is an array, with the option value as key, and 'optional',
  //   or 'mandatory' as value.
  // Parameters :
  //   See above.
  // Return Values :
  //   1 on success.
  //   0 on failure.
  // --------------------------------------------------------------------------------
  function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options=false)
  {
    $v_result=1;

    // ----- Read the options
    $i=0;
    while ($i<$p_size) {

      // ----- Check if the option is supported
      if (!isset($v_requested_options[$p_options_list[$i]])) {
        // ----- Error log
        PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid optional parameter '".$p_options_list[$i]."' for this method");

        // ----- Return
        return PclZip::errorCode();
      }

      // ----- Look for next option
      switch ($p_options_list[$i]) {
        // ----- Look for options that request a path value
        case PCLZIP_OPT_PATH :
        case PCLZIP_OPT_REMOVE_PATH :
        case PCLZIP_OPT_ADD_PATH :
          // ----- Check the number of parameters
          if (($i+1) >= $p_size) {
            // ----- Error log
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");

            // ----- Return
            return PclZip::errorCode();
          }

          // ----- Get the value
          $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE);
          $i++;
        break;

        case PCLZIP_OPT_TEMP_FILE_THRESHOLD :
          // ----- Check the number of parameters
          if (($i+1) >= $p_size) {
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
            return PclZip::errorCode();
          }

          // ----- Check for incompatible options
          if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) {
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'");
            return PclZip::errorCode();
          }

          // ----- Check the value
          $v_value = $p_options_list[$i+1];
          if ((!is_integer($v_value)) || ($v_value<0)) {
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Integer expected for option '".PclZipUtilOptionText($p_options_list[$i])."'");
            return PclZip::errorCode();
          }

          // ----- Get the value (and convert it in bytes)
          $v_result_list[$p_options_list[$i]] = $v_value*1048576;
          $i++;
        break;

        case PCLZIP_OPT_TEMP_FILE_ON :
          // ----- Check for incompatible options
          if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) {
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'");
            return PclZip::errorCode();
          }

          $v_result_list[$p_options_list[$i]] = true;
        break;

        case PCLZIP_OPT_TEMP_FILE_OFF :
          // ----- Check for incompatible options
          if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_ON])) {
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_ON'");
            return PclZip::errorCode();
          }
          // ----- Check for incompatible options
          if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) {
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_THRESHOLD'");
            return PclZip::errorCode();
          }

          $v_result_list[$p_options_list[$i]] = true;
        break;

        case PCLZIP_OPT_EXTRACT_DIR_RESTRICTION :
          // ----- Check the number of parameters
          if (($i+1) >= $p_size) {
            // ----- Error log
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");

            // ----- Return
            return PclZip::errorCode();
          }

          // ----- Get the value
          if (   is_string($p_options_list[$i+1])
              && ($p_options_list[$i+1] != '')) {
            $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE);
            $i++;
          }
          else {
          }
        break;

        // ----- Look for options that request an array of string for value
        case PCLZIP_OPT_BY_NAME :
          // ----- Check the number of parameters
          if (($i+1) >= $p_size) {
            // ----- Error log
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");

            // ----- Return
            return PclZip::errorCode();
          }

          // ----- Get the value
          if (is_string($p_options_list[$i+1])) {
              $v_result_list[$p_options_list[$i]][0] = $p_options_list[$i+1];
          }
          else if (is_array($p_options_list[$i+1])) {
              $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
          }
          else {
            // ----- Error log
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");

            // ----- Return
            return PclZip::errorCode();
          }
          $i++;
        break;

        // ----- Look for options that request an EREG or PREG expression
        case PCLZIP_OPT_BY_EREG :
          // ereg() is deprecated starting with PHP 5.3. Move PCLZIP_OPT_BY_EREG
          // to PCLZIP_OPT_BY_PREG
          $p_options_list[$i] = PCLZIP_OPT_BY_PREG;
        case PCLZIP_OPT_BY_PREG :
        //case PCLZIP_OPT_CRYPT :
          // ----- Check the number of parameters
          if (($i+1) >= $p_size) {
            // ----- Error log
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");

            // ----- Return
            return PclZip::errorCode();
          }

          // ----- Get the value
          if (is_string($p_options_list[$i+1])) {
              $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
          }
          else {
            // ----- Error log
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");

            // ----- Return
            return PclZip::errorCode();
          }
          $i++;
        break;

        // ----- Look for options that takes a string
        case PCLZIP_OPT_COMMENT :
        case PCLZIP_OPT_ADD_COMMENT :
        case PCLZIP_OPT_PREPEND_COMMENT :
          // ----- Check the number of parameters
          if (($i+1) >= $p_size) {
            // ----- Error log
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE,
			                     "Missing parameter value for option '"
								 .PclZipUtilOptionText($p_options_list[$i])
								 ."'");

            // ----- Return
            return PclZip::errorCode();
          }

          // ----- Get the value
          if (is_string($p_options_list[$i+1])) {
              $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
          }
          else {
            // ----- Error log
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE,
			                     "Wrong parameter value for option '"
								 .PclZipUtilOptionText($p_options_list[$i])
								 ."'");

            // ----- Return
            return PclZip::errorCode();
          }
          $i++;
        break;

        // ----- Look for options that request an array of index
        case PCLZIP_OPT_BY_INDEX :
          // ----- Check the number of parameters
          if (($i+1) >= $p_size) {
            // ----- Error log
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");

            // ----- Return
            return PclZip::errorCode();
          }

          // ----- Get the value
          $v_work_list = array();
          if (is_string($p_options_list[$i+1])) {

              // ----- Remove spaces
              $p_options_list[$i+1] = strtr($p_options_list[$i+1], ' ', '');

              // ----- Parse items
              $v_work_list = explode(",", $p_options_list[$i+1]);
          }
          else if (is_integer($p_options_list[$i+1])) {
              $v_work_list[0] = $p_options_list[$i+1].'-'.$p_options_list[$i+1];
          }
          else if (is_array($p_options_list[$i+1])) {
              $v_work_list = $p_options_list[$i+1];
          }
          else {
            // ----- Error log
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Value must be integer, string or array for option '".PclZipUtilOptionText($p_options_list[$i])."'");

            // ----- Return
            return PclZip::errorCode();
          }

          // ----- Reduce the index list
          // each index item in the list must be a couple with a start and
          // an end value : [0,3], [5-5], [8-10], ...
          // ----- Check the format of each item
          $v_sort_flag=false;
          $v_sort_value=0;
          for ($j=0; $j<sizeof($v_work_list); $j++) {
              // ----- Explode the item
              $v_item_list = explode("-", $v_work_list[$j]);
              $v_size_item_list = sizeof($v_item_list);

              // ----- TBC : Here we might check that each item is a
              // real integer ...

              // ----- Look for single value
              if ($v_size_item_list == 1) {
                  // ----- Set the option value
                  $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
                  $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[0];
              }
              elseif ($v_size_item_list == 2) {
                  // ----- Set the option value
                  $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0];
                  $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[1];
              }
              else {
                  // ----- Error log
                  PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Too many values in index range for option '".PclZipUtilOptionText($p_options_list[$i])."'");

                  // ----- Return
                  return PclZip::errorCode();
              }


              // ----- Look for list sort
              if ($v_result_list[$p_options_list[$i]][$j]['start'] < $v_sort_value) {
                  $v_sort_flag=true;

                  // ----- TBC : An automatic sort should be written ...
                  // ----- Error log
                  PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Invalid order of index range for option '".PclZipUtilOptionText($p_options_list[$i])."'");

                  // ----- Return
                  return PclZip::errorCode();
              }
              $v_sort_value = $v_result_list[$p_options_list[$i]][$j]['start'];
          }

          // ----- Sort the items
          if ($v_sort_flag) {
              // TBC : To Be Completed
          }

          // ----- Next option
          $i++;
        break;

        // ----- Look for options that request no value
        case PCLZIP_OPT_REMOVE_ALL_PATH :
        case PCLZIP_OPT_EXTRACT_AS_STRING :
        case PCLZIP_OPT_NO_COMPRESSION :
        case PCLZIP_OPT_EXTRACT_IN_OUTPUT :
        case PCLZIP_OPT_REPLACE_NEWER :
        case PCLZIP_OPT_STOP_ON_ERROR :
          $v_result_list[$p_options_list[$i]] = true;
        break;

        // ----- Look for options that request an octal value
        case PCLZIP_OPT_SET_CHMOD :
          // ----- Check the number of parameters
          if (($i+1) >= $p_size) {
            // ----- Error log
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");

            // ----- Return
            return PclZip::errorCode();
          }

          // ----- Get the value
          $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
          $i++;
        break;

        // ----- Look for options that request a call-back
        case PCLZIP_CB_PRE_EXTRACT :
        case PCLZIP_CB_POST_EXTRACT :
        case PCLZIP_CB_PRE_ADD :
        case PCLZIP_CB_POST_ADD :
        /* for future use
        case PCLZIP_CB_PRE_DELETE :
        case PCLZIP_CB_POST_DELETE :
        case PCLZIP_CB_PRE_LIST :
        case PCLZIP_CB_POST_LIST :
        */
          // ----- Check the number of parameters
          if (($i+1) >= $p_size) {
            // ----- Error log
            PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");

            // ----- Return
            return PclZip::errorCode();
          }

          // ----- Get the value
          $v_function_name = $p_options_list[$i+1];

          // ----- Check that the value is a valid existing function
          if (!function_exists($v_function_name)) {
            // ----- Error log
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Function '".$v_function_name."()' is not an existing function for option '".PclZipUtilOptionText($p_options_list[$i])."'");

            // ----- Return
            return PclZip::errorCode();
          }

          // ----- Set the attribute
          $v_result_list[$p_options_list[$i]] = $v_function_name;
          $i++;
        break;

        default :
          // ----- Error log
          PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
		                       "Unknown parameter '"
							   .$p_options_list[$i]."'");

          // ----- Return
          return PclZip::errorCode();
      }

      // ----- Next options
      $i++;
    }

    // ----- Look for mandatory options
    if ($v_requested_options !== false) {
      for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) {
        // ----- Look for mandatory option
        if ($v_requested_options[$key] == 'mandatory') {
          // ----- Look if present
          if (!isset($v_result_list[$key])) {
            // ----- Error log
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")");

            // ----- Return
            return PclZip::errorCode();
          }
        }
      }
    }

    // ----- Look for default values
    if (!isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) {

    }

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privOptionDefaultThreshold()
  // Description :
  // Parameters :
  // Return Values :
  // --------------------------------------------------------------------------------
  function privOptionDefaultThreshold(&$p_options)
  {
    $v_result=1;

    if (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
        || isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) {
      return $v_result;
    }

    // ----- Get 'memory_limit' configuration value
    $v_memory_limit = ini_get('memory_limit');
    $v_memory_limit = trim($v_memory_limit);
    $v_memory_limit_int = (int) $v_memory_limit;
    $last = strtolower(substr($v_memory_limit, -1));

    if($last == 'g')
        //$v_memory_limit_int = $v_memory_limit_int*1024*1024*1024;
        $v_memory_limit_int = $v_memory_limit_int*1073741824;
    if($last == 'm')
        //$v_memory_limit_int = $v_memory_limit_int*1024*1024;
        $v_memory_limit_int = $v_memory_limit_int*1048576;
    if($last == 'k')
        $v_memory_limit_int = $v_memory_limit_int*1024;

    $p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] = floor($v_memory_limit_int*PCLZIP_TEMPORARY_FILE_RATIO);


    // ----- Confidence check : No threshold if value lower than 1M
    if ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] < 1048576) {
      unset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]);
    }

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privFileDescrParseAtt()
  // Description :
  // Parameters :
  // Return Values :
  //   1 on success.
  //   0 on failure.
  // --------------------------------------------------------------------------------
  function privFileDescrParseAtt(&$p_file_list, &$p_filedescr, $v_options, $v_requested_options=false)
  {
    $v_result=1;

    // ----- For each file in the list check the attributes
    foreach ($p_file_list as $v_key => $v_value) {

      // ----- Check if the option is supported
      if (!isset($v_requested_options[$v_key])) {
        // ----- Error log
        PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file attribute '".$v_key."' for this file");

        // ----- Return
        return PclZip::errorCode();
      }

      // ----- Look for attribute
      switch ($v_key) {
        case PCLZIP_ATT_FILE_NAME :
          if (!is_string($v_value)) {
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
            return PclZip::errorCode();
          }

          $p_filedescr['filename'] = PclZipUtilPathReduction($v_value);

          if ($p_filedescr['filename'] == '') {
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty filename for attribute '".PclZipUtilOptionText($v_key)."'");
            return PclZip::errorCode();
          }

        break;

        case PCLZIP_ATT_FILE_NEW_SHORT_NAME :
          if (!is_string($v_value)) {
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
            return PclZip::errorCode();
          }

          $p_filedescr['new_short_name'] = PclZipUtilPathReduction($v_value);

          if ($p_filedescr['new_short_name'] == '') {
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty short filename for attribute '".PclZipUtilOptionText($v_key)."'");
            return PclZip::errorCode();
          }
        break;

        case PCLZIP_ATT_FILE_NEW_FULL_NAME :
          if (!is_string($v_value)) {
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
            return PclZip::errorCode();
          }

          $p_filedescr['new_full_name'] = PclZipUtilPathReduction($v_value);

          if ($p_filedescr['new_full_name'] == '') {
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty full filename for attribute '".PclZipUtilOptionText($v_key)."'");
            return PclZip::errorCode();
          }
        break;

        // ----- Look for options that takes a string
        case PCLZIP_ATT_FILE_COMMENT :
          if (!is_string($v_value)) {
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
            return PclZip::errorCode();
          }

          $p_filedescr['comment'] = $v_value;
        break;

        case PCLZIP_ATT_FILE_MTIME :
          if (!is_integer($v_value)) {
            PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". Integer expected for attribute '".PclZipUtilOptionText($v_key)."'");
            return PclZip::errorCode();
          }

          $p_filedescr['mtime'] = $v_value;
        break;

        case PCLZIP_ATT_FILE_CONTENT :
          $p_filedescr['content'] = $v_value;
        break;

        default :
          // ----- Error log
          PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
		                           "Unknown parameter '".$v_key."'");

          // ----- Return
          return PclZip::errorCode();
      }

      // ----- Look for mandatory options
      if ($v_requested_options !== false) {
        for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) {
          // ----- Look for mandatory option
          if ($v_requested_options[$key] == 'mandatory') {
            // ----- Look if present
            if (!isset($p_file_list[$key])) {
              PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")");
              return PclZip::errorCode();
            }
          }
        }
      }

    // end foreach
    }

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privFileDescrExpand()
  // Description :
  //   This method look for each item of the list to see if its a file, a folder
  //   or a string to be added as file. For any other type of files (link, other)
  //   just ignore the item.
  //   Then prepare the information that will be stored for that file.
  //   When its a folder, expand the folder with all the files that are in that
  //   folder (recursively).
  // Parameters :
  // Return Values :
  //   1 on success.
  //   0 on failure.
  // --------------------------------------------------------------------------------
  function privFileDescrExpand(&$p_filedescr_list, &$p_options)
  {
    $v_result=1;

    // ----- Create a result list
    $v_result_list = array();

    // ----- Look each entry
    for ($i=0; $i<sizeof($p_filedescr_list); $i++) {

      // ----- Get filedescr
      $v_descr = $p_filedescr_list[$i];

      // ----- Reduce the filename
      $v_descr['filename'] = PclZipUtilTranslateWinPath($v_descr['filename'], false);
      $v_descr['filename'] = PclZipUtilPathReduction($v_descr['filename']);

      // ----- Look for real file or folder
      if (file_exists($v_descr['filename'])) {
        if (@is_file($v_descr['filename'])) {
          $v_descr['type'] = 'file';
        }
        else if (@is_dir($v_descr['filename'])) {
          $v_descr['type'] = 'folder';
        }
        else if (@is_link($v_descr['filename'])) {
          // skip
          continue;
        }
        else {
          // skip
          continue;
        }
      }

      // ----- Look for string added as file
      else if (isset($v_descr['content'])) {
        $v_descr['type'] = 'virtual_file';
      }

      // ----- Missing file
      else {
        // ----- Error log
        PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$v_descr['filename']."' does not exist");

        // ----- Return
        return PclZip::errorCode();
      }

      // ----- Calculate the stored filename
      $this->privCalculateStoredFilename($v_descr, $p_options);

      // ----- Add the descriptor in result list
      $v_result_list[sizeof($v_result_list)] = $v_descr;

      // ----- Look for folder
      if ($v_descr['type'] == 'folder') {
        // ----- List of items in folder
        $v_dirlist_descr = array();
        $v_dirlist_nb = 0;
        if ($v_folder_handler = @opendir($v_descr['filename'])) {
          while (($v_item_handler = @readdir($v_folder_handler)) !== false) {

            // ----- Skip '.' and '..'
            if (($v_item_handler == '.') || ($v_item_handler == '..')) {
                continue;
            }

            // ----- Compose the full filename
            $v_dirlist_descr[$v_dirlist_nb]['filename'] = $v_descr['filename'].'/'.$v_item_handler;

            // ----- Look for different stored filename
            // Because the name of the folder was changed, the name of the
            // files/sub-folders also change
            if (($v_descr['stored_filename'] != $v_descr['filename'])
                 && (!isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))) {
              if ($v_descr['stored_filename'] != '') {
                $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_descr['stored_filename'].'/'.$v_item_handler;
              }
              else {
                $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_item_handler;
              }
            }

            $v_dirlist_nb++;
          }

          @closedir($v_folder_handler);
        }
        else {
          // TBC : unable to open folder in read mode
        }

        // ----- Expand each element of the list
        if ($v_dirlist_nb != 0) {
          // ----- Expand
          if (($v_result = $this->privFileDescrExpand($v_dirlist_descr, $p_options)) != 1) {
            return $v_result;
          }

          // ----- Concat the resulting list
          $v_result_list = array_merge($v_result_list, $v_dirlist_descr);
        }
        else {
        }

        // ----- Free local array
        unset($v_dirlist_descr);
      }
    }

    // ----- Get the result list
    $p_filedescr_list = $v_result_list;

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privCreate()
  // Description :
  // Parameters :
  // Return Values :
  // --------------------------------------------------------------------------------
  function privCreate($p_filedescr_list, &$p_result_list, &$p_options)
  {
    $v_result=1;
    $v_list_detail = array();

    // ----- Magic quotes trick
    $this->privDisableMagicQuotes();

    // ----- Open the file in write mode
    if (($v_result = $this->privOpenFd('wb')) != 1)
    {
      // ----- Return
      return $v_result;
    }

    // ----- Add the list of files
    $v_result = $this->privAddList($p_filedescr_list, $p_result_list, $p_options);

    // ----- Close
    $this->privCloseFd();

    // ----- Magic quotes trick
    $this->privSwapBackMagicQuotes();

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privAdd()
  // Description :
  // Parameters :
  // Return Values :
  // --------------------------------------------------------------------------------
  function privAdd($p_filedescr_list, &$p_result_list, &$p_options)
  {
    $v_result=1;
    $v_list_detail = array();

    // ----- Look if the archive exists or is empty
    if ((!is_file($this->zipname)) || (filesize($this->zipname) == 0))
    {

      // ----- Do a create
      $v_result = $this->privCreate($p_filedescr_list, $p_result_list, $p_options);

      // ----- Return
      return $v_result;
    }
    // ----- Magic quotes trick
    $this->privDisableMagicQuotes();

    // ----- Open the zip file
    if (($v_result=$this->privOpenFd('rb')) != 1)
    {
      // ----- Magic quotes trick
      $this->privSwapBackMagicQuotes();

      // ----- Return
      return $v_result;
    }

    // ----- Read the central directory information
    $v_central_dir = array();
    if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
    {
      $this->privCloseFd();
      $this->privSwapBackMagicQuotes();
      return $v_result;
    }

    // ----- Go to beginning of File
    @rewind($this->zip_fd);

    // ----- Creates a temporary file
    $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';

    // ----- Open the temporary file in write mode
    if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
    {
      $this->privCloseFd();
      $this->privSwapBackMagicQuotes();

      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');

      // ----- Return
      return PclZip::errorCode();
    }

    // ----- Copy the files from the archive to the temporary file
    // TBC : Here I should better append the file and go back to erase the central dir
    $v_size = $v_central_dir['offset'];
    while ($v_size != 0)
    {
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
      $v_buffer = fread($this->zip_fd, $v_read_size);
      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
      $v_size -= $v_read_size;
    }

    // ----- Swap the file descriptor
    // Here is a trick : I swap the temporary fd with the zip fd, in order to use
    // the following methods on the temporary fil and not the real archive
    $v_swap = $this->zip_fd;
    $this->zip_fd = $v_zip_temp_fd;
    $v_zip_temp_fd = $v_swap;

    // ----- Add the files
    $v_header_list = array();
    if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1)
    {
      fclose($v_zip_temp_fd);
      $this->privCloseFd();
      @unlink($v_zip_temp_name);
      $this->privSwapBackMagicQuotes();

      // ----- Return
      return $v_result;
    }

    // ----- Store the offset of the central dir
    $v_offset = @ftell($this->zip_fd);

    // ----- Copy the block of file headers from the old archive
    $v_size = $v_central_dir['size'];
    while ($v_size != 0)
    {
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
      $v_buffer = @fread($v_zip_temp_fd, $v_read_size);
      @fwrite($this->zip_fd, $v_buffer, $v_read_size);
      $v_size -= $v_read_size;
    }

    // ----- Create the Central Dir files header
    for ($i=0, $v_count=0; $i<sizeof($v_header_list); $i++)
    {
      // ----- Create the file header
      if ($v_header_list[$i]['status'] == 'ok') {
        if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
          fclose($v_zip_temp_fd);
          $this->privCloseFd();
          @unlink($v_zip_temp_name);
          $this->privSwapBackMagicQuotes();

          // ----- Return
          return $v_result;
        }
        $v_count++;
      }

      // ----- Transform the header to a 'usable' info
      $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
    }

    // ----- Zip file comment
    $v_comment = $v_central_dir['comment'];
    if (isset($p_options[PCLZIP_OPT_COMMENT])) {
      $v_comment = $p_options[PCLZIP_OPT_COMMENT];
    }
    if (isset($p_options[PCLZIP_OPT_ADD_COMMENT])) {
      $v_comment = $v_comment.$p_options[PCLZIP_OPT_ADD_COMMENT];
    }
    if (isset($p_options[PCLZIP_OPT_PREPEND_COMMENT])) {
      $v_comment = $p_options[PCLZIP_OPT_PREPEND_COMMENT].$v_comment;
    }

    // ----- Calculate the size of the central header
    $v_size = @ftell($this->zip_fd)-$v_offset;

    // ----- Create the central dir footer
    if (($v_result = $this->privWriteCentralHeader($v_count+$v_central_dir['entries'], $v_size, $v_offset, $v_comment)) != 1)
    {
      // ----- Reset the file list
      unset($v_header_list);
      $this->privSwapBackMagicQuotes();

      // ----- Return
      return $v_result;
    }

    // ----- Swap back the file descriptor
    $v_swap = $this->zip_fd;
    $this->zip_fd = $v_zip_temp_fd;
    $v_zip_temp_fd = $v_swap;

    // ----- Close
    $this->privCloseFd();

    // ----- Close the temporary file
    @fclose($v_zip_temp_fd);

    // ----- Magic quotes trick
    $this->privSwapBackMagicQuotes();

    // ----- Delete the zip file
    // TBC : I should test the result ...
    @unlink($this->zipname);

    // ----- Rename the temporary file
    // TBC : I should test the result ...
    //@rename($v_zip_temp_name, $this->zipname);
    PclZipUtilRename($v_zip_temp_name, $this->zipname);

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privOpenFd()
  // Description :
  // Parameters :
  // --------------------------------------------------------------------------------
  function privOpenFd($p_mode)
  {
    $v_result=1;

    // ----- Look if already open
    if ($this->zip_fd != 0)
    {
      // ----- Error log
      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Zip file \''.$this->zipname.'\' already open');

      // ----- Return
      return PclZip::errorCode();
    }

    // ----- Open the zip file
    if (($this->zip_fd = @fopen($this->zipname, $p_mode)) == 0)
    {
      // ----- Error log
      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in '.$p_mode.' mode');

      // ----- Return
      return PclZip::errorCode();
    }

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privCloseFd()
  // Description :
  // Parameters :
  // --------------------------------------------------------------------------------
  function privCloseFd()
  {
    $v_result=1;

    if ($this->zip_fd != 0)
      @fclose($this->zip_fd);
    $this->zip_fd = 0;

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privAddList()
  // Description :
  //   $p_add_dir and $p_remove_dir will give the ability to memorize a path which is
  //   different from the real path of the file. This is useful if you want to have PclTar
  //   running in any directory, and memorize relative path from an other directory.
  // Parameters :
  //   $p_list : An array containing the file or directory names to add in the tar
  //   $p_result_list : list of added files with their properties (specially the status field)
  //   $p_add_dir : Path to add in the filename path archived
  //   $p_remove_dir : Path to remove in the filename path archived
  // Return Values :
  // --------------------------------------------------------------------------------
//  function privAddList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
  function privAddList($p_filedescr_list, &$p_result_list, &$p_options)
  {
    $v_result=1;

    // ----- Add the files
    $v_header_list = array();
    if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1)
    {
      // ----- Return
      return $v_result;
    }

    // ----- Store the offset of the central dir
    $v_offset = @ftell($this->zip_fd);

    // ----- Create the Central Dir files header
    for ($i=0,$v_count=0; $i<sizeof($v_header_list); $i++)
    {
      // ----- Create the file header
      if ($v_header_list[$i]['status'] == 'ok') {
        if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
          // ----- Return
          return $v_result;
        }
        $v_count++;
      }

      // ----- Transform the header to a 'usable' info
      $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
    }

    // ----- Zip file comment
    $v_comment = '';
    if (isset($p_options[PCLZIP_OPT_COMMENT])) {
      $v_comment = $p_options[PCLZIP_OPT_COMMENT];
    }

    // ----- Calculate the size of the central header
    $v_size = @ftell($this->zip_fd)-$v_offset;

    // ----- Create the central dir footer
    if (($v_result = $this->privWriteCentralHeader($v_count, $v_size, $v_offset, $v_comment)) != 1)
    {
      // ----- Reset the file list
      unset($v_header_list);

      // ----- Return
      return $v_result;
    }

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privAddFileList()
  // Description :
  // Parameters :
  //   $p_filedescr_list : An array containing the file description
  //                      or directory names to add in the zip
  //   $p_result_list : list of added files with their properties (specially the status field)
  // Return Values :
  // --------------------------------------------------------------------------------
  function privAddFileList($p_filedescr_list, &$p_result_list, &$p_options)
  {
    $v_result=1;
    $v_header = array();

    // ----- Recuperate the current number of elt in list
    $v_nb = sizeof($p_result_list);

    // ----- Loop on the files
    for ($j=0; ($j<sizeof($p_filedescr_list)) && ($v_result==1); $j++) {
      // ----- Format the filename
      $p_filedescr_list[$j]['filename']
      = PclZipUtilTranslateWinPath($p_filedescr_list[$j]['filename'], false);


      // ----- Skip empty file names
      // TBC : Can this be possible ? not checked in DescrParseAtt ?
      if ($p_filedescr_list[$j]['filename'] == "") {
        continue;
      }

      // ----- Check the filename
      if (   ($p_filedescr_list[$j]['type'] != 'virtual_file')
          && (!file_exists($p_filedescr_list[$j]['filename']))) {
        PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$p_filedescr_list[$j]['filename']."' does not exist");
        return PclZip::errorCode();
      }

      // ----- Look if it is a file or a dir with no all path remove option
      // or a dir with all its path removed
//      if (   (is_file($p_filedescr_list[$j]['filename']))
//          || (   is_dir($p_filedescr_list[$j]['filename'])
      if (   ($p_filedescr_list[$j]['type'] == 'file')
          || ($p_filedescr_list[$j]['type'] == 'virtual_file')
          || (   ($p_filedescr_list[$j]['type'] == 'folder')
              && (   !isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])
                  || !$p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))
          ) {

        // ----- Add the file
        $v_result = $this->privAddFile($p_filedescr_list[$j], $v_header,
                                       $p_options);
        if ($v_result != 1) {
          return $v_result;
        }

        // ----- Store the file infos
        $p_result_list[$v_nb++] = $v_header;
      }
    }

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privAddFile()
  // Description :
  // Parameters :
  // Return Values :
  // --------------------------------------------------------------------------------
  function privAddFile($p_filedescr, &$p_header, &$p_options)
  {
    $v_result=1;

    // ----- Working variable
    $p_filename = $p_filedescr['filename'];

    // TBC : Already done in the fileAtt check ... ?
    if ($p_filename == "") {
      // ----- Error log
      PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)");

      // ----- Return
      return PclZip::errorCode();
    }

    // ----- Look for a stored different filename
    /* TBC : Removed
    if (isset($p_filedescr['stored_filename'])) {
      $v_stored_filename = $p_filedescr['stored_filename'];
    }
    else {
      $v_stored_filename = $p_filedescr['stored_filename'];
    }
    */

    // ----- Set the file properties
    clearstatcache();
    $p_header['version'] = 20;
    $p_header['version_extracted'] = 10;
    $p_header['flag'] = 0;
    $p_header['compression'] = 0;
    $p_header['crc'] = 0;
    $p_header['compressed_size'] = 0;
    $p_header['filename_len'] = strlen($p_filename);
    $p_header['extra_len'] = 0;
    $p_header['disk'] = 0;
    $p_header['internal'] = 0;
    $p_header['offset'] = 0;
    $p_header['filename'] = $p_filename;
// TBC : Removed    $p_header['stored_filename'] = $v_stored_filename;
    $p_header['stored_filename'] = $p_filedescr['stored_filename'];
    $p_header['extra'] = '';
    $p_header['status'] = 'ok';
    $p_header['index'] = -1;

    // ----- Look for regular file
    if ($p_filedescr['type']=='file') {
      $p_header['external'] = 0x00000000;
      $p_header['size'] = filesize($p_filename);
    }

    // ----- Look for regular folder
    else if ($p_filedescr['type']=='folder') {
      $p_header['external'] = 0x00000010;
      $p_header['mtime'] = filemtime($p_filename);
      $p_header['size'] = filesize($p_filename);
    }

    // ----- Look for virtual file
    else if ($p_filedescr['type'] == 'virtual_file') {
      $p_header['external'] = 0x00000000;
      $p_header['size'] = strlen($p_filedescr['content']);
    }


    // ----- Look for filetime
    if (isset($p_filedescr['mtime'])) {
      $p_header['mtime'] = $p_filedescr['mtime'];
    }
    else if ($p_filedescr['type'] == 'virtual_file') {
      $p_header['mtime'] = time();
    }
    else {
      $p_header['mtime'] = filemtime($p_filename);
    }

    // ------ Look for file comment
    if (isset($p_filedescr['comment'])) {
      $p_header['comment_len'] = strlen($p_filedescr['comment']);
      $p_header['comment'] = $p_filedescr['comment'];
    }
    else {
      $p_header['comment_len'] = 0;
      $p_header['comment'] = '';
    }

    // ----- Look for pre-add callback
    if (isset($p_options[PCLZIP_CB_PRE_ADD])) {

      // ----- Generate a local information
      $v_local_header = array();
      $this->privConvertHeader2FileInfo($p_header, $v_local_header);

      // ----- Call the callback
      // Here I do not use call_user_func() because I need to send a reference to the
      // header.
      $v_result = $p_options[PCLZIP_CB_PRE_ADD](PCLZIP_CB_PRE_ADD, $v_local_header);
      if ($v_result == 0) {
        // ----- Change the file status
        $p_header['status'] = "skipped";
        $v_result = 1;
      }

      // ----- Update the information
      // Only some fields can be modified
      if ($p_header['stored_filename'] != $v_local_header['stored_filename']) {
        $p_header['stored_filename'] = PclZipUtilPathReduction($v_local_header['stored_filename']);
      }
    }

    // ----- Look for empty stored filename
    if ($p_header['stored_filename'] == "") {
      $p_header['status'] = "filtered";
    }

    // ----- Check the path length
    if (strlen($p_header['stored_filename']) > 0xFF) {
      $p_header['status'] = 'filename_too_long';
    }

    // ----- Look if no error, or file not skipped
    if ($p_header['status'] == 'ok') {

      // ----- Look for a file
      if ($p_filedescr['type'] == 'file') {
        // ----- Look for using temporary file to zip
        if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF]))
            && (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON])
                || (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
                    && ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_header['size'])) ) ) {
          $v_result = $this->privAddFileUsingTempFile($p_filedescr, $p_header, $p_options);
          if ($v_result < PCLZIP_ERR_NO_ERROR) {
            return $v_result;
          }
        }

        // ----- Use "in memory" zip algo
        else {

        // ----- Open the source file
        if (($v_file = @fopen($p_filename, "rb")) == 0) {
          PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
          return PclZip::errorCode();
        }

        // ----- Read the file content
        if ($p_header['size'] > 0) {
          $v_content = @fread($v_file, $p_header['size']);
        }
        else {
          $v_content = '';
        }

        // ----- Close the file
        @fclose($v_file);

        // ----- Calculate the CRC
        $p_header['crc'] = @crc32($v_content);

        // ----- Look for no compression
        if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
          // ----- Set header parameters
          $p_header['compressed_size'] = $p_header['size'];
          $p_header['compression'] = 0;
        }

        // ----- Look for normal compression
        else {
          // ----- Compress the content
          $v_content = @gzdeflate($v_content);

          // ----- Set header parameters
          $p_header['compressed_size'] = strlen($v_content);
          $p_header['compression'] = 8;
        }

        // ----- Call the header generation
        if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
          @fclose($v_file);
          return $v_result;
        }

        // ----- Write the compressed (or not) content
        @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']);

        }

      }

      // ----- Look for a virtual file (a file from string)
      else if ($p_filedescr['type'] == 'virtual_file') {

        $v_content = $p_filedescr['content'];

        // ----- Calculate the CRC
        $p_header['crc'] = @crc32($v_content);

        // ----- Look for no compression
        if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
          // ----- Set header parameters
          $p_header['compressed_size'] = $p_header['size'];
          $p_header['compression'] = 0;
        }

        // ----- Look for normal compression
        else {
          // ----- Compress the content
          $v_content = @gzdeflate($v_content);

          // ----- Set header parameters
          $p_header['compressed_size'] = strlen($v_content);
          $p_header['compression'] = 8;
        }

        // ----- Call the header generation
        if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
          @fclose($v_file);
          return $v_result;
        }

        // ----- Write the compressed (or not) content
        @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']);
      }

      // ----- Look for a directory
      else if ($p_filedescr['type'] == 'folder') {
        // ----- Look for directory last '/'
        if (@substr($p_header['stored_filename'], -1) != '/') {
          $p_header['stored_filename'] .= '/';
        }

        // ----- Set the file properties
        $p_header['size'] = 0;
        //$p_header['external'] = 0x41FF0010;   // Value for a folder : to be checked
        $p_header['external'] = 0x00000010;   // Value for a folder : to be checked

        // ----- Call the header generation
        if (($v_result = $this->privWriteFileHeader($p_header)) != 1)
        {
          return $v_result;
        }
      }
    }

    // ----- Look for post-add callback
    if (isset($p_options[PCLZIP_CB_POST_ADD])) {

      // ----- Generate a local information
      $v_local_header = array();
      $this->privConvertHeader2FileInfo($p_header, $v_local_header);

      // ----- Call the callback
      // Here I do not use call_user_func() because I need to send a reference to the
      // header.
      $v_result = $p_options[PCLZIP_CB_POST_ADD](PCLZIP_CB_POST_ADD, $v_local_header);
      if ($v_result == 0) {
        // ----- Ignored
        $v_result = 1;
      }

      // ----- Update the information
      // Nothing can be modified
    }

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privAddFileUsingTempFile()
  // Description :
  // Parameters :
  // Return Values :
  // --------------------------------------------------------------------------------
  function privAddFileUsingTempFile($p_filedescr, &$p_header, &$p_options)
  {
    $v_result=PCLZIP_ERR_NO_ERROR;

    // ----- Working variable
    $p_filename = $p_filedescr['filename'];


    // ----- Open the source file
    if (($v_file = @fopen($p_filename, "rb")) == 0) {
      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
      return PclZip::errorCode();
    }

    // ----- Creates a compressed temporary file
    $v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz';
    if (($v_file_compressed = @gzopen($v_gzip_temp_name, "wb")) == 0) {
      fclose($v_file);
      PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode');
      return PclZip::errorCode();
    }

    // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
    $v_size = filesize($p_filename);
    while ($v_size != 0) {
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
      $v_buffer = @fread($v_file, $v_read_size);
      //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
      @gzputs($v_file_compressed, $v_buffer, $v_read_size);
      $v_size -= $v_read_size;
    }

    // ----- Close the file
    @fclose($v_file);
    @gzclose($v_file_compressed);

    // ----- Check the minimum file size
    if (filesize($v_gzip_temp_name) < 18) {
      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'gzip temporary file \''.$v_gzip_temp_name.'\' has invalid filesize - should be minimum 18 bytes');
      return PclZip::errorCode();
    }

    // ----- Extract the compressed attributes
    if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0) {
      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
      return PclZip::errorCode();
    }

    // ----- Read the gzip file header
    $v_binary_data = @fread($v_file_compressed, 10);
    $v_data_header = unpack('a1id1/a1id2/a1cm/a1flag/Vmtime/a1xfl/a1os', $v_binary_data);

    // ----- Check some parameters
    $v_data_header['os'] = bin2hex($v_data_header['os']);

    // ----- Read the gzip file footer
    @fseek($v_file_compressed, filesize($v_gzip_temp_name)-8);
    $v_binary_data = @fread($v_file_compressed, 8);
    $v_data_footer = unpack('Vcrc/Vcompressed_size', $v_binary_data);

    // ----- Set the attributes
    $p_header['compression'] = ord($v_data_header['cm']);
    //$p_header['mtime'] = $v_data_header['mtime'];
    $p_header['crc'] = $v_data_footer['crc'];
    $p_header['compressed_size'] = filesize($v_gzip_temp_name)-18;

    // ----- Close the file
    @fclose($v_file_compressed);

    // ----- Call the header generation
    if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
      return $v_result;
    }

    // ----- Add the compressed data
    if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0)
    {
      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
      return PclZip::errorCode();
    }

    // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
    fseek($v_file_compressed, 10);
    $v_size = $p_header['compressed_size'];
    while ($v_size != 0)
    {
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
      $v_buffer = @fread($v_file_compressed, $v_read_size);
      //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
      @fwrite($this->zip_fd, $v_buffer, $v_read_size);
      $v_size -= $v_read_size;
    }

    // ----- Close the file
    @fclose($v_file_compressed);

    // ----- Unlink the temporary file
    @unlink($v_gzip_temp_name);

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privCalculateStoredFilename()
  // Description :
  //   Based on file descriptor properties and global options, this method
  //   calculate the filename that will be stored in the archive.
  // Parameters :
  // Return Values :
  // --------------------------------------------------------------------------------
  function privCalculateStoredFilename(&$p_filedescr, &$p_options)
  {
    $v_result=1;

    // ----- Working variables
    $p_filename = $p_filedescr['filename'];
    if (isset($p_options[PCLZIP_OPT_ADD_PATH])) {
      $p_add_dir = $p_options[PCLZIP_OPT_ADD_PATH];
    }
    else {
      $p_add_dir = '';
    }
    if (isset($p_options[PCLZIP_OPT_REMOVE_PATH])) {
      $p_remove_dir = $p_options[PCLZIP_OPT_REMOVE_PATH];
    }
    else {
      $p_remove_dir = '';
    }
    if (isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
      $p_remove_all_dir = $p_options[PCLZIP_OPT_REMOVE_ALL_PATH];
    }
    else {
      $p_remove_all_dir = 0;
    }


    // ----- Look for full name change
    if (isset($p_filedescr['new_full_name'])) {
      // ----- Remove drive letter if any
      $v_stored_filename = PclZipUtilTranslateWinPath($p_filedescr['new_full_name']);
    }

    // ----- Look for path and/or short name change
    else {

      // ----- Look for short name change
      // Its when we change just the filename but not the path
      if (isset($p_filedescr['new_short_name'])) {
        $v_path_info = pathinfo($p_filename);
        $v_dir = '';
        if ($v_path_info['dirname'] != '') {
          $v_dir = $v_path_info['dirname'].'/';
        }
        $v_stored_filename = $v_dir.$p_filedescr['new_short_name'];
      }
      else {
        // ----- Calculate the stored filename
        $v_stored_filename = $p_filename;
      }

      // ----- Look for all path to remove
      if ($p_remove_all_dir) {
        $v_stored_filename = basename($p_filename);
      }
      // ----- Look for partial path remove
      else if ($p_remove_dir != "") {
        if (substr($p_remove_dir, -1) != '/')
          $p_remove_dir .= "/";

        if (   (substr($p_filename, 0, 2) == "./")
            || (substr($p_remove_dir, 0, 2) == "./")) {

          if (   (substr($p_filename, 0, 2) == "./")
              && (substr($p_remove_dir, 0, 2) != "./")) {
            $p_remove_dir = "./".$p_remove_dir;
          }
          if (   (substr($p_filename, 0, 2) != "./")
              && (substr($p_remove_dir, 0, 2) == "./")) {
            $p_remove_dir = substr($p_remove_dir, 2);
          }
        }

        $v_compare = PclZipUtilPathInclusion($p_remove_dir,
                                             $v_stored_filename);
        if ($v_compare > 0) {
          if ($v_compare == 2) {
            $v_stored_filename = "";
          }
          else {
            $v_stored_filename = substr($v_stored_filename,
                                        strlen($p_remove_dir));
          }
        }
      }

      // ----- Remove drive letter if any
      $v_stored_filename = PclZipUtilTranslateWinPath($v_stored_filename);

      // ----- Look for path to add
      if ($p_add_dir != "") {
        if (substr($p_add_dir, -1) == "/")
          $v_stored_filename = $p_add_dir.$v_stored_filename;
        else
          $v_stored_filename = $p_add_dir."/".$v_stored_filename;
      }
    }

    // ----- Filename (reduce the path of stored name)
    $v_stored_filename = PclZipUtilPathReduction($v_stored_filename);
    $p_filedescr['stored_filename'] = $v_stored_filename;

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privWriteFileHeader()
  // Description :
  // Parameters :
  // Return Values :
  // --------------------------------------------------------------------------------
  function privWriteFileHeader(&$p_header)
  {
    $v_result=1;

    // ----- Store the offset position of the file
    $p_header['offset'] = ftell($this->zip_fd);

    // ----- Transform UNIX mtime to DOS format mdate/mtime
    $v_date = getdate($p_header['mtime']);
    $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
    $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];

    // ----- Packed data
    $v_binary_data = pack("VvvvvvVVVvv", 0x04034b50,
	                      $p_header['version_extracted'], $p_header['flag'],
                          $p_header['compression'], $v_mtime, $v_mdate,
                          $p_header['crc'], $p_header['compressed_size'],
						  $p_header['size'],
                          strlen($p_header['stored_filename']),
						  $p_header['extra_len']);

    // ----- Write the first 148 bytes of the header in the archive
    fputs($this->zip_fd, $v_binary_data, 30);

    // ----- Write the variable fields
    if (strlen($p_header['stored_filename']) != 0)
    {
      fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
    }
    if ($p_header['extra_len'] != 0)
    {
      fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
    }

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privWriteCentralFileHeader()
  // Description :
  // Parameters :
  // Return Values :
  // --------------------------------------------------------------------------------
  function privWriteCentralFileHeader(&$p_header)
  {
    $v_result=1;

    // TBC
    //for(reset($p_header); $key = key($p_header); next($p_header)) {
    //}

    // ----- Transform UNIX mtime to DOS format mdate/mtime
    $v_date = getdate($p_header['mtime']);
    $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
    $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];


    // ----- Packed data
    $v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50,
	                      $p_header['version'], $p_header['version_extracted'],
                          $p_header['flag'], $p_header['compression'],
						  $v_mtime, $v_mdate, $p_header['crc'],
                          $p_header['compressed_size'], $p_header['size'],
                          strlen($p_header['stored_filename']),
						  $p_header['extra_len'], $p_header['comment_len'],
                          $p_header['disk'], $p_header['internal'],
						  $p_header['external'], $p_header['offset']);

    // ----- Write the 42 bytes of the header in the zip file
    fputs($this->zip_fd, $v_binary_data, 46);

    // ----- Write the variable fields
    if (strlen($p_header['stored_filename']) != 0)
    {
      fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename']));
    }
    if ($p_header['extra_len'] != 0)
    {
      fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']);
    }
    if ($p_header['comment_len'] != 0)
    {
      fputs($this->zip_fd, $p_header['comment'], $p_header['comment_len']);
    }

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privWriteCentralHeader()
  // Description :
  // Parameters :
  // Return Values :
  // --------------------------------------------------------------------------------
  function privWriteCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment)
  {
    $v_result=1;

    // ----- Packed data
    $v_binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries,
	                      $p_nb_entries, $p_size,
						  $p_offset, strlen($p_comment));

    // ----- Write the 22 bytes of the header in the zip file
    fputs($this->zip_fd, $v_binary_data, 22);

    // ----- Write the variable fields
    if (strlen($p_comment) != 0)
    {
      fputs($this->zip_fd, $p_comment, strlen($p_comment));
    }

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privList()
  // Description :
  // Parameters :
  // Return Values :
  // --------------------------------------------------------------------------------
  function privList(&$p_list)
  {
    $v_result=1;

    // ----- Magic quotes trick
    $this->privDisableMagicQuotes();

    // ----- Open the zip file
    if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
    {
      // ----- Magic quotes trick
      $this->privSwapBackMagicQuotes();

      // ----- Error log
      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');

      // ----- Return
      return PclZip::errorCode();
    }

    // ----- Read the central directory information
    $v_central_dir = array();
    if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
    {
      $this->privSwapBackMagicQuotes();
      return $v_result;
    }

    // ----- Go to beginning of Central Dir
    @rewind($this->zip_fd);
    if (@fseek($this->zip_fd, $v_central_dir['offset']))
    {
      $this->privSwapBackMagicQuotes();

      // ----- Error log
      PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');

      // ----- Return
      return PclZip::errorCode();
    }

    // ----- Read each entry
    for ($i=0; $i<$v_central_dir['entries']; $i++)
    {
      // ----- Read the file header
      if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
      {
        $this->privSwapBackMagicQuotes();
        return $v_result;
      }
      $v_header['index'] = $i;

      // ----- Get the only interesting attributes
      $this->privConvertHeader2FileInfo($v_header, $p_list[$i]);
      unset($v_header);
    }

    // ----- Close the zip file
    $this->privCloseFd();

    // ----- Magic quotes trick
    $this->privSwapBackMagicQuotes();

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privConvertHeader2FileInfo()
  // Description :
  //   This function takes the file information from the central directory
  //   entries and extract the interesting parameters that will be given back.
  //   The resulting file infos are set in the array $p_info
  //     $p_info['filename'] : Filename with full path. Given by user (add),
  //                           extracted in the filesystem (extract).
  //     $p_info['stored_filename'] : Stored filename in the archive.
  //     $p_info['size'] = Size of the file.
  //     $p_info['compressed_size'] = Compressed size of the file.
  //     $p_info['mtime'] = Last modification date of the file.
  //     $p_info['comment'] = Comment associated with the file.
  //     $p_info['folder'] = true/false : indicates if the entry is a folder or not.
  //     $p_info['status'] = status of the action on the file.
  //     $p_info['crc'] = CRC of the file content.
  // Parameters :
  // Return Values :
  // --------------------------------------------------------------------------------
  function privConvertHeader2FileInfo($p_header, &$p_info)
  {
    $v_result=1;

    // ----- Get the interesting attributes
    $v_temp_path = PclZipUtilPathReduction($p_header['filename']);
    $p_info['filename'] = $v_temp_path;
    $v_temp_path = PclZipUtilPathReduction($p_header['stored_filename']);
    $p_info['stored_filename'] = $v_temp_path;
    $p_info['size'] = $p_header['size'];
    $p_info['compressed_size'] = $p_header['compressed_size'];
    $p_info['mtime'] = $p_header['mtime'];
    $p_info['comment'] = $p_header['comment'];
    $p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010);
    $p_info['index'] = $p_header['index'];
    $p_info['status'] = $p_header['status'];
    $p_info['crc'] = $p_header['crc'];

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privExtractByRule()
  // Description :
  //   Extract a file or directory depending of rules (by index, by name, ...)
  // Parameters :
  //   $p_file_list : An array where will be placed the properties of each
  //                  extracted file
  //   $p_path : Path to add while writing the extracted files
  //   $p_remove_path : Path to remove (from the file memorized path) while writing the
  //                    extracted files. If the path does not match the file path,
  //                    the file is extracted with its memorized path.
  //                    $p_remove_path does not apply to 'list' mode.
  //                    $p_path and $p_remove_path are commulative.
  // Return Values :
  //   1 on success,0 or less on error (see error code list)
  // --------------------------------------------------------------------------------
  function privExtractByRule(&$p_file_list, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
  {
    $v_result=1;

    // ----- Magic quotes trick
    $this->privDisableMagicQuotes();

    // ----- Check the path
    if (   ($p_path == "")
	    || (   (substr($p_path, 0, 1) != "/")
		    && (substr($p_path, 0, 3) != "../")
			&& (substr($p_path,1,2)!=":/")))
      $p_path = "./".$p_path;

    // ----- Reduce the path last (and duplicated) '/'
    if (($p_path != "./") && ($p_path != "/"))
    {
      // ----- Look for the path end '/'
      while (substr($p_path, -1) == "/")
      {
        $p_path = substr($p_path, 0, strlen($p_path)-1);
      }
    }

    // ----- Look for path to remove format (should end by /)
    if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/'))
    {
      $p_remove_path .= '/';
    }
    $p_remove_path_size = strlen($p_remove_path);

    // ----- Open the zip file
    if (($v_result = $this->privOpenFd('rb')) != 1)
    {
      $this->privSwapBackMagicQuotes();
      return $v_result;
    }

    // ----- Read the central directory information
    $v_central_dir = array();
    if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
    {
      // ----- Close the zip file
      $this->privCloseFd();
      $this->privSwapBackMagicQuotes();

      return $v_result;
    }

    // ----- Start at beginning of Central Dir
    $v_pos_entry = $v_central_dir['offset'];

    // ----- Read each entry
    $j_start = 0;
    for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
    {

      // ----- Read next Central dir entry
      @rewind($this->zip_fd);
      if (@fseek($this->zip_fd, $v_pos_entry))
      {
        // ----- Close the zip file
        $this->privCloseFd();
        $this->privSwapBackMagicQuotes();

        // ----- Error log
        PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');

        // ----- Return
        return PclZip::errorCode();
      }

      // ----- Read the file header
      $v_header = array();
      if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
      {
        // ----- Close the zip file
        $this->privCloseFd();
        $this->privSwapBackMagicQuotes();

        return $v_result;
      }

      // ----- Store the index
      $v_header['index'] = $i;

      // ----- Store the file position
      $v_pos_entry = ftell($this->zip_fd);

      // ----- Look for the specific extract rules
      $v_extract = false;

      // ----- Look for extract by name rule
      if (   (isset($p_options[PCLZIP_OPT_BY_NAME]))
          && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) {

          // ----- Look if the filename is in the list
          for ($j=0; ($j<sizeof($p_options[PCLZIP_OPT_BY_NAME])) && (!$v_extract); $j++) {

              // ----- Look for a directory
              if (substr($p_options[PCLZIP_OPT_BY_NAME][$j], -1) == "/") {

                  // ----- Look if the directory is in the filename path
                  if (   (strlen($v_header['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j]))
                      && (substr($v_header['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
                      $v_extract = true;
                  }
              }
              // ----- Look for a filename
              elseif ($v_header['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) {
                  $v_extract = true;
              }
          }
      }

      // ----- Look for extract by ereg rule
      // ereg() is deprecated with PHP 5.3
      /*
      else if (   (isset($p_options[PCLZIP_OPT_BY_EREG]))
               && ($p_options[PCLZIP_OPT_BY_EREG] != "")) {

          if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header['stored_filename'])) {
              $v_extract = true;
          }
      }
      */

      // ----- Look for extract by preg rule
      else if (   (isset($p_options[PCLZIP_OPT_BY_PREG]))
               && ($p_options[PCLZIP_OPT_BY_PREG] != "")) {

          if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header['stored_filename'])) {
              $v_extract = true;
          }
      }

      // ----- Look for extract by index rule
      else if (   (isset($p_options[PCLZIP_OPT_BY_INDEX]))
               && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) {

          // ----- Look if the index is in the list
          for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_extract); $j++) {

              if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) {
                  $v_extract = true;
              }
              if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) {
                  $j_start = $j+1;
              }

              if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
                  break;
              }
          }
      }

      // ----- Look for no rule, which means extract all the archive
      else {
          $v_extract = true;
      }

	  // ----- Check compression method
	  if (   ($v_extract)
	      && (   ($v_header['compression'] != 8)
		      && ($v_header['compression'] != 0))) {
          $v_header['status'] = 'unsupported_compression';

          // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
          if (   (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
		      && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {

              $this->privSwapBackMagicQuotes();

              PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_COMPRESSION,
			                       "Filename '".$v_header['stored_filename']."' is "
				  	    	  	   ."compressed by an unsupported compression "
				  	    	  	   ."method (".$v_header['compression'].") ");

              return PclZip::errorCode();
		  }
	  }

	  // ----- Check encrypted files
	  if (($v_extract) && (($v_header['flag'] & 1) == 1)) {
          $v_header['status'] = 'unsupported_encryption';

          // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
          if (   (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
		      && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {

              $this->privSwapBackMagicQuotes();

              PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION,
			                       "Unsupported encryption for "
				  	    	  	   ." filename '".$v_header['stored_filename']
								   ."'");

              return PclZip::errorCode();
		  }
    }

      // ----- Look for real extraction
      if (($v_extract) && ($v_header['status'] != 'ok')) {
          $v_result = $this->privConvertHeader2FileInfo($v_header,
		                                        $p_file_list[$v_nb_extracted++]);
          if ($v_result != 1) {
              $this->privCloseFd();
              $this->privSwapBackMagicQuotes();
              return $v_result;
          }

          $v_extract = false;
      }

      // ----- Look for real extraction
      if ($v_extract)
      {

        // ----- Go to the file position
        @rewind($this->zip_fd);
        if (@fseek($this->zip_fd, $v_header['offset']))
        {
          // ----- Close the zip file
          $this->privCloseFd();

          $this->privSwapBackMagicQuotes();

          // ----- Error log
          PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');

          // ----- Return
          return PclZip::errorCode();
        }

        // ----- Look for extraction as string
        if ($p_options[PCLZIP_OPT_EXTRACT_AS_STRING]) {

          $v_string = '';

          // ----- Extracting the file
          $v_result1 = $this->privExtractFileAsString($v_header, $v_string, $p_options);
          if ($v_result1 < 1) {
            $this->privCloseFd();
            $this->privSwapBackMagicQuotes();
            return $v_result1;
          }

          // ----- Get the only interesting attributes
          if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted])) != 1)
          {
            // ----- Close the zip file
            $this->privCloseFd();
            $this->privSwapBackMagicQuotes();

            return $v_result;
          }

          // ----- Set the file content
          $p_file_list[$v_nb_extracted]['content'] = $v_string;

          // ----- Next extracted file
          $v_nb_extracted++;

          // ----- Look for user callback abort
          if ($v_result1 == 2) {
          	break;
          }
        }
        // ----- Look for extraction in standard output
        elseif (   (isset($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT]))
		        && ($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT])) {
          // ----- Extracting the file in standard output
          $v_result1 = $this->privExtractFileInOutput($v_header, $p_options);
          if ($v_result1 < 1) {
            $this->privCloseFd();
            $this->privSwapBackMagicQuotes();
            return $v_result1;
          }

          // ----- Get the only interesting attributes
          if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) {
            $this->privCloseFd();
            $this->privSwapBackMagicQuotes();
            return $v_result;
          }

          // ----- Look for user callback abort
          if ($v_result1 == 2) {
          	break;
          }
        }
        // ----- Look for normal extraction
        else {
          // ----- Extracting the file
          $v_result1 = $this->privExtractFile($v_header,
		                                      $p_path, $p_remove_path,
											  $p_remove_all_path,
											  $p_options);
          if ($v_result1 < 1) {
            $this->privCloseFd();
            $this->privSwapBackMagicQuotes();
            return $v_result1;
          }

          // ----- Get the only interesting attributes
          if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1)
          {
            // ----- Close the zip file
            $this->privCloseFd();
            $this->privSwapBackMagicQuotes();

            return $v_result;
          }

          // ----- Look for user callback abort
          if ($v_result1 == 2) {
          	break;
          }
        }
      }
    }

    // ----- Close the zip file
    $this->privCloseFd();
    $this->privSwapBackMagicQuotes();

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privExtractFile()
  // Description :
  // Parameters :
  // Return Values :
  //
  // 1 : ... ?
  // PCLZIP_ERR_USER_ABORTED(2) : User ask for extraction stop in callback
  // --------------------------------------------------------------------------------
  function privExtractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
  {
    $v_result=1;

    // ----- Read the file header
    if (($v_result = $this->privReadFileHeader($v_header)) != 1)
    {
      // ----- Return
      return $v_result;
    }


    // ----- Check that the file header is coherent with $p_entry info
    if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
        // TBC
    }

    // ----- Look for all path to remove
    if ($p_remove_all_path == true) {
        // ----- Look for folder entry that not need to be extracted
        if (($p_entry['external']&0x00000010)==0x00000010) {

            $p_entry['status'] = "filtered";

            return $v_result;
        }

        // ----- Get the basename of the path
        $p_entry['filename'] = basename($p_entry['filename']);
    }

    // ----- Look for path to remove
    else if ($p_remove_path != "")
    {
      if (PclZipUtilPathInclusion($p_remove_path, $p_entry['filename']) == 2)
      {

        // ----- Change the file status
        $p_entry['status'] = "filtered";

        // ----- Return
        return $v_result;
      }

      $p_remove_path_size = strlen($p_remove_path);
      if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path)
      {

        // ----- Remove the path
        $p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size);

      }
    }

    // ----- Add the path
    if ($p_path != '') {
      $p_entry['filename'] = $p_path."/".$p_entry['filename'];
    }

    // ----- Check a base_dir_restriction
    if (isset($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION])) {
      $v_inclusion
      = PclZipUtilPathInclusion($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION],
                                $p_entry['filename']);
      if ($v_inclusion == 0) {

        PclZip::privErrorLog(PCLZIP_ERR_DIRECTORY_RESTRICTION,
			                     "Filename '".$p_entry['filename']."' is "
								 ."outside PCLZIP_OPT_EXTRACT_DIR_RESTRICTION");

        return PclZip::errorCode();
      }
    }

    // ----- Look for pre-extract callback
    if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {

      // ----- Generate a local information
      $v_local_header = array();
      $this->privConvertHeader2FileInfo($p_entry, $v_local_header);

      // ----- Call the callback
      // Here I do not use call_user_func() because I need to send a reference to the
      // header.
      $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header);
      if ($v_result == 0) {
        // ----- Change the file status
        $p_entry['status'] = "skipped";
        $v_result = 1;
      }

      // ----- Look for abort result
      if ($v_result == 2) {
        // ----- This status is internal and will be changed in 'skipped'
        $p_entry['status'] = "aborted";
      	$v_result = PCLZIP_ERR_USER_ABORTED;
      }

      // ----- Update the information
      // Only some fields can be modified
      $p_entry['filename'] = $v_local_header['filename'];
    }


    // ----- Look if extraction should be done
    if ($p_entry['status'] == 'ok') {

    // ----- Look for specific actions while the file exist
    if (file_exists($p_entry['filename']))
    {

      // ----- Look if file is a directory
      if (is_dir($p_entry['filename']))
      {

        // ----- Change the file status
        $p_entry['status'] = "already_a_directory";

        // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
        // For historical reason first PclZip implementation does not stop
        // when this kind of error occurs.
        if (   (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
		    && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {

            PclZip::privErrorLog(PCLZIP_ERR_ALREADY_A_DIRECTORY,
			                     "Filename '".$p_entry['filename']."' is "
								 ."already used by an existing directory");

            return PclZip::errorCode();
		    }
      }
      // ----- Look if file is write protected
      else if (!is_writeable($p_entry['filename']))
      {

        // ----- Change the file status
        $p_entry['status'] = "write_protected";

        // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
        // For historical reason first PclZip implementation does not stop
        // when this kind of error occurs.
        if (   (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
		    && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {

            PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL,
			                     "Filename '".$p_entry['filename']."' exists "
								 ."and is write protected");

            return PclZip::errorCode();
		    }
      }

      // ----- Look if the extracted file is older
      else if (filemtime($p_entry['filename']) > $p_entry['mtime'])
      {
        // ----- Change the file status
        if (   (isset($p_options[PCLZIP_OPT_REPLACE_NEWER]))
		    && ($p_options[PCLZIP_OPT_REPLACE_NEWER]===true)) {
	  	  }
		    else {
            $p_entry['status'] = "newer_exist";

            // ----- Look for PCLZIP_OPT_STOP_ON_ERROR
            // For historical reason first PclZip implementation does not stop
            // when this kind of error occurs.
            if (   (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
		        && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {

                PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL,
			             "Newer version of '".$p_entry['filename']."' exists "
					    ."and option PCLZIP_OPT_REPLACE_NEWER is not selected");

                return PclZip::errorCode();
		      }
		    }
      }
      else {
      }
    }

    // ----- Check the directory availability and create it if necessary
    else {
      if ((($p_entry['external']&0x00000010)==0x00000010) || (substr($p_entry['filename'], -1) == '/'))
        $v_dir_to_check = $p_entry['filename'];
      else if (!strstr($p_entry['filename'], "/"))
        $v_dir_to_check = "";
      else
        $v_dir_to_check = dirname($p_entry['filename']);

        if (($v_result = $this->privDirCheck($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) {

          // ----- Change the file status
          $p_entry['status'] = "path_creation_fail";

          // ----- Return
          //return $v_result;
          $v_result = 1;
        }
      }
    }

    // ----- Look if extraction should be done
    if ($p_entry['status'] == 'ok') {

      // ----- Do the extraction (if not a folder)
      if (!(($p_entry['external']&0x00000010)==0x00000010))
      {
        // ----- Look for not compressed file
        if ($p_entry['compression'] == 0) {

    		  // ----- Opening destination file
          if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0)
          {

            // ----- Change the file status
            $p_entry['status'] = "write_error";

            // ----- Return
            return $v_result;
          }


          // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
          $v_size = $p_entry['compressed_size'];
          while ($v_size != 0)
          {
            $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
            $v_buffer = @fread($this->zip_fd, $v_read_size);
            /* Try to speed up the code
            $v_binary_data = pack('a'.$v_read_size, $v_buffer);
            @fwrite($v_dest_file, $v_binary_data, $v_read_size);
            */
            @fwrite($v_dest_file, $v_buffer, $v_read_size);
            $v_size -= $v_read_size;
          }

          // ----- Closing the destination file
          fclose($v_dest_file);

          // ----- Change the file mtime
          touch($p_entry['filename'], $p_entry['mtime']);


        }
        else {
          // ----- TBC
          // Need to be finished
          if (($p_entry['flag'] & 1) == 1) {
            PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION, 'File \''.$p_entry['filename'].'\' is encrypted. Encrypted files are not supported.');
            return PclZip::errorCode();
          }


          // ----- Look for using temporary file to unzip
          if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF]))
              && (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON])
                  || (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
                      && ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_entry['size'])) ) ) {
            $v_result = $this->privExtractFileUsingTempFile($p_entry, $p_options);
            if ($v_result < PCLZIP_ERR_NO_ERROR) {
              return $v_result;
            }
          }

          // ----- Look for extract in memory
          else {


            // ----- Read the compressed file in a buffer (one shot)
            if ($p_entry['compressed_size'] > 0) {
              $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
            }
            else {
              $v_buffer = '';
            }

            // ----- Decompress the file
            $v_file_content = @gzinflate($v_buffer);
            unset($v_buffer);
            if ($v_file_content === FALSE) {

              // ----- Change the file status
              // TBC
              $p_entry['status'] = "error";

              return $v_result;
            }

            // ----- Opening destination file
            if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {

              // ----- Change the file status
              $p_entry['status'] = "write_error";

              return $v_result;
            }

            // ----- Write the uncompressed data
            @fwrite($v_dest_file, $v_file_content, $p_entry['size']);
            unset($v_file_content);

            // ----- Closing the destination file
            @fclose($v_dest_file);

          }

          // ----- Change the file mtime
          @touch($p_entry['filename'], $p_entry['mtime']);
        }

        // ----- Look for chmod option
        if (isset($p_options[PCLZIP_OPT_SET_CHMOD])) {

          // ----- Change the mode of the file
          @chmod($p_entry['filename'], $p_options[PCLZIP_OPT_SET_CHMOD]);
        }

      }
    }

  	// ----- Change abort status
  	if ($p_entry['status'] == "aborted") {
        $p_entry['status'] = "skipped";
  	}

    // ----- Look for post-extract callback
    elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {

      // ----- Generate a local information
      $v_local_header = array();
      $this->privConvertHeader2FileInfo($p_entry, $v_local_header);

      // ----- Call the callback
      // Here I do not use call_user_func() because I need to send a reference to the
      // header.
      $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header);

      // ----- Look for abort result
      if ($v_result == 2) {
      	$v_result = PCLZIP_ERR_USER_ABORTED;
      }
    }

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privExtractFileUsingTempFile()
  // Description :
  // Parameters :
  // Return Values :
  // --------------------------------------------------------------------------------
  function privExtractFileUsingTempFile(&$p_entry, &$p_options)
  {
    $v_result=1;

    // ----- Creates a temporary file
    $v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz';
    if (($v_dest_file = @fopen($v_gzip_temp_name, "wb")) == 0) {
      fclose($v_file);
      PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode');
      return PclZip::errorCode();
    }


    // ----- Write gz file format header
    $v_binary_data = pack('va1a1Va1a1', 0x8b1f, Chr($p_entry['compression']), Chr(0x00), time(), Chr(0x00), Chr(3));
    @fwrite($v_dest_file, $v_binary_data, 10);

    // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
    $v_size = $p_entry['compressed_size'];
    while ($v_size != 0)
    {
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
      $v_buffer = @fread($this->zip_fd, $v_read_size);
      //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
      @fwrite($v_dest_file, $v_buffer, $v_read_size);
      $v_size -= $v_read_size;
    }

    // ----- Write gz file format footer
    $v_binary_data = pack('VV', $p_entry['crc'], $p_entry['size']);
    @fwrite($v_dest_file, $v_binary_data, 8);

    // ----- Close the temporary file
    @fclose($v_dest_file);

    // ----- Opening destination file
    if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
      $p_entry['status'] = "write_error";
      return $v_result;
    }

    // ----- Open the temporary gz file
    if (($v_src_file = @gzopen($v_gzip_temp_name, 'rb')) == 0) {
      @fclose($v_dest_file);
      $p_entry['status'] = "read_error";
      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
      return PclZip::errorCode();
    }


    // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
    $v_size = $p_entry['size'];
    while ($v_size != 0) {
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
      $v_buffer = @gzread($v_src_file, $v_read_size);
      //$v_binary_data = pack('a'.$v_read_size, $v_buffer);
      @fwrite($v_dest_file, $v_buffer, $v_read_size);
      $v_size -= $v_read_size;
    }
    @fclose($v_dest_file);
    @gzclose($v_src_file);

    // ----- Delete the temporary file
    @unlink($v_gzip_temp_name);

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privExtractFileInOutput()
  // Description :
  // Parameters :
  // Return Values :
  // --------------------------------------------------------------------------------
  function privExtractFileInOutput(&$p_entry, &$p_options)
  {
    $v_result=1;

    // ----- Read the file header
    if (($v_result = $this->privReadFileHeader($v_header)) != 1) {
      return $v_result;
    }


    // ----- Check that the file header is coherent with $p_entry info
    if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
        // TBC
    }

    // ----- Look for pre-extract callback
    if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {

      // ----- Generate a local information
      $v_local_header = array();
      $this->privConvertHeader2FileInfo($p_entry, $v_local_header);

      // ----- Call the callback
      // Here I do not use call_user_func() because I need to send a reference to the
      // header.
//      eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
      $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header);
      if ($v_result == 0) {
        // ----- Change the file status
        $p_entry['status'] = "skipped";
        $v_result = 1;
      }

      // ----- Look for abort result
      if ($v_result == 2) {
        // ----- This status is internal and will be changed in 'skipped'
        $p_entry['status'] = "aborted";
      	$v_result = PCLZIP_ERR_USER_ABORTED;
      }

      // ----- Update the information
      // Only some fields can be modified
      $p_entry['filename'] = $v_local_header['filename'];
    }

    // ----- Trace

    // ----- Look if extraction should be done
    if ($p_entry['status'] == 'ok') {

      // ----- Do the extraction (if not a folder)
      if (!(($p_entry['external']&0x00000010)==0x00000010)) {
        // ----- Look for not compressed file
        if ($p_entry['compressed_size'] == $p_entry['size']) {

          // ----- Read the file in a buffer (one shot)
          if ($p_entry['compressed_size'] > 0) {
            $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
          }
          else {
            $v_buffer = '';
          }

          // ----- Send the file to the output
          echo $v_buffer;
          unset($v_buffer);
        }
        else {

          // ----- Read the compressed file in a buffer (one shot)
          if ($p_entry['compressed_size'] > 0) {
            $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
          }
          else {
            $v_buffer = '';
          }

          // ----- Decompress the file
          $v_file_content = gzinflate($v_buffer);
          unset($v_buffer);

          // ----- Send the file to the output
          echo $v_file_content;
          unset($v_file_content);
        }
      }
    }

	// ----- Change abort status
	if ($p_entry['status'] == "aborted") {
      $p_entry['status'] = "skipped";
	}

    // ----- Look for post-extract callback
    elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {

      // ----- Generate a local information
      $v_local_header = array();
      $this->privConvertHeader2FileInfo($p_entry, $v_local_header);

      // ----- Call the callback
      // Here I do not use call_user_func() because I need to send a reference to the
      // header.
      $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header);

      // ----- Look for abort result
      if ($v_result == 2) {
      	$v_result = PCLZIP_ERR_USER_ABORTED;
      }
    }

    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privExtractFileAsString()
  // Description :
  // Parameters :
  // Return Values :
  // --------------------------------------------------------------------------------
  function privExtractFileAsString(&$p_entry, &$p_string, &$p_options)
  {
    $v_result=1;

    // ----- Read the file header
    $v_header = array();
    if (($v_result = $this->privReadFileHeader($v_header)) != 1)
    {
      // ----- Return
      return $v_result;
    }


    // ----- Check that the file header is coherent with $p_entry info
    if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
        // TBC
    }

    // ----- Look for pre-extract callback
    if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {

      // ----- Generate a local information
      $v_local_header = array();
      $this->privConvertHeader2FileInfo($p_entry, $v_local_header);

      // ----- Call the callback
      // Here I do not use call_user_func() because I need to send a reference to the
      // header.
      $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header);
      if ($v_result == 0) {
        // ----- Change the file status
        $p_entry['status'] = "skipped";
        $v_result = 1;
      }

      // ----- Look for abort result
      if ($v_result == 2) {
        // ----- This status is internal and will be changed in 'skipped'
        $p_entry['status'] = "aborted";
      	$v_result = PCLZIP_ERR_USER_ABORTED;
      }

      // ----- Update the information
      // Only some fields can be modified
      $p_entry['filename'] = $v_local_header['filename'];
    }


    // ----- Look if extraction should be done
    if ($p_entry['status'] == 'ok') {

      // ----- Do the extraction (if not a folder)
      if (!(($p_entry['external']&0x00000010)==0x00000010)) {
        // ----- Look for not compressed file
  //      if ($p_entry['compressed_size'] == $p_entry['size'])
        if ($p_entry['compression'] == 0) {

          // ----- Reading the file
          if ($p_entry['compressed_size'] > 0) {
            $p_string = @fread($this->zip_fd, $p_entry['compressed_size']);
          }
          else {
            $p_string = '';
          }
        }
        else {

          // ----- Reading the file
          if ($p_entry['compressed_size'] > 0) {
            $v_data = @fread($this->zip_fd, $p_entry['compressed_size']);
          }
          else {
            $v_data = '';
          }

          // ----- Decompress the file
          if (($p_string = @gzinflate($v_data)) === FALSE) {
              // TBC
          }
        }

        // ----- Trace
      }
      else {
          // TBC : error : can not extract a folder in a string
      }

    }

  	// ----- Change abort status
  	if ($p_entry['status'] == "aborted") {
        $p_entry['status'] = "skipped";
  	}

    // ----- Look for post-extract callback
    elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {

      // ----- Generate a local information
      $v_local_header = array();
      $this->privConvertHeader2FileInfo($p_entry, $v_local_header);

      // ----- Swap the content to header
      $v_local_header['content'] = $p_string;
      $p_string = '';

      // ----- Call the callback
      // Here I do not use call_user_func() because I need to send a reference to the
      // header.
      $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header);

      // ----- Swap back the content to header
      $p_string = $v_local_header['content'];
      unset($v_local_header['content']);

      // ----- Look for abort result
      if ($v_result == 2) {
      	$v_result = PCLZIP_ERR_USER_ABORTED;
      }
    }

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privReadFileHeader()
  // Description :
  // Parameters :
  // Return Values :
  // --------------------------------------------------------------------------------
  function privReadFileHeader(&$p_header)
  {
    $v_result=1;

    // ----- Read the 4 bytes signature
    $v_binary_data = @fread($this->zip_fd, 4);
    $v_data = unpack('Vid', $v_binary_data);

    // ----- Check signature
    if ($v_data['id'] != 0x04034b50)
    {

      // ----- Error log
      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');

      // ----- Return
      return PclZip::errorCode();
    }

    // ----- Read the first 42 bytes of the header
    $v_binary_data = fread($this->zip_fd, 26);

    // ----- Look for invalid block size
    if (strlen($v_binary_data) != 26)
    {
      $p_header['filename'] = "";
      $p_header['status'] = "invalid_header";

      // ----- Error log
      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));

      // ----- Return
      return PclZip::errorCode();
    }

    // ----- Extract the values
    $v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data);

    // ----- Get filename
    $p_header['filename'] = fread($this->zip_fd, $v_data['filename_len']);

    // ----- Get extra_fields
    if ($v_data['extra_len'] != 0) {
      $p_header['extra'] = fread($this->zip_fd, $v_data['extra_len']);
    }
    else {
      $p_header['extra'] = '';
    }

    // ----- Extract properties
    $p_header['version_extracted'] = $v_data['version'];
    $p_header['compression'] = $v_data['compression'];
    $p_header['size'] = $v_data['size'];
    $p_header['compressed_size'] = $v_data['compressed_size'];
    $p_header['crc'] = $v_data['crc'];
    $p_header['flag'] = $v_data['flag'];
    $p_header['filename_len'] = $v_data['filename_len'];

    // ----- Recuperate date in UNIX format
    $p_header['mdate'] = $v_data['mdate'];
    $p_header['mtime'] = $v_data['mtime'];
    if ($p_header['mdate'] && $p_header['mtime'])
    {
      // ----- Extract time
      $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
      $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
      $v_seconde = ($p_header['mtime'] & 0x001F)*2;

      // ----- Extract date
      $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
      $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
      $v_day = $p_header['mdate'] & 0x001F;

      // ----- Get UNIX date format
      $p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);

    }
    else
    {
      $p_header['mtime'] = time();
    }

    // TBC
    //for(reset($v_data); $key = key($v_data); next($v_data)) {
    //}

    // ----- Set the stored filename
    $p_header['stored_filename'] = $p_header['filename'];

    // ----- Set the status field
    $p_header['status'] = "ok";

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privReadCentralFileHeader()
  // Description :
  // Parameters :
  // Return Values :
  // --------------------------------------------------------------------------------
  function privReadCentralFileHeader(&$p_header)
  {
    $v_result=1;

    // ----- Read the 4 bytes signature
    $v_binary_data = @fread($this->zip_fd, 4);
    $v_data = unpack('Vid', $v_binary_data);

    // ----- Check signature
    if ($v_data['id'] != 0x02014b50)
    {

      // ----- Error log
      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');

      // ----- Return
      return PclZip::errorCode();
    }

    // ----- Read the first 42 bytes of the header
    $v_binary_data = fread($this->zip_fd, 42);

    // ----- Look for invalid block size
    if (strlen($v_binary_data) != 42)
    {
      $p_header['filename'] = "";
      $p_header['status'] = "invalid_header";

      // ----- Error log
      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));

      // ----- Return
      return PclZip::errorCode();
    }

    // ----- Extract the values
    $p_header = unpack('vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $v_binary_data);

    // ----- Get filename
    if ($p_header['filename_len'] != 0)
      $p_header['filename'] = fread($this->zip_fd, $p_header['filename_len']);
    else
      $p_header['filename'] = '';

    // ----- Get extra
    if ($p_header['extra_len'] != 0)
      $p_header['extra'] = fread($this->zip_fd, $p_header['extra_len']);
    else
      $p_header['extra'] = '';

    // ----- Get comment
    if ($p_header['comment_len'] != 0)
      $p_header['comment'] = fread($this->zip_fd, $p_header['comment_len']);
    else
      $p_header['comment'] = '';

    // ----- Extract properties

    // ----- Recuperate date in UNIX format
    //if ($p_header['mdate'] && $p_header['mtime'])
    // TBC : bug : this was ignoring time with 0/0/0
    if (1)
    {
      // ----- Extract time
      $v_hour = ($p_header['mtime'] & 0xF800) >> 11;
      $v_minute = ($p_header['mtime'] & 0x07E0) >> 5;
      $v_seconde = ($p_header['mtime'] & 0x001F)*2;

      // ----- Extract date
      $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980;
      $v_month = ($p_header['mdate'] & 0x01E0) >> 5;
      $v_day = $p_header['mdate'] & 0x001F;

      // ----- Get UNIX date format
      $p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);

    }
    else
    {
      $p_header['mtime'] = time();
    }

    // ----- Set the stored filename
    $p_header['stored_filename'] = $p_header['filename'];

    // ----- Set default status to ok
    $p_header['status'] = 'ok';

    // ----- Look if it is a directory
    if (substr($p_header['filename'], -1) == '/') {
      //$p_header['external'] = 0x41FF0010;
      $p_header['external'] = 0x00000010;
    }


    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privCheckFileHeaders()
  // Description :
  // Parameters :
  // Return Values :
  //   1 on success,
  //   0 on error;
  // --------------------------------------------------------------------------------
  function privCheckFileHeaders(&$p_local_header, &$p_central_header)
  {
    $v_result=1;

  	// ----- Check the static values
  	// TBC
  	if ($p_local_header['filename'] != $p_central_header['filename']) {
  	}
  	if ($p_local_header['version_extracted'] != $p_central_header['version_extracted']) {
  	}
  	if ($p_local_header['flag'] != $p_central_header['flag']) {
  	}
  	if ($p_local_header['compression'] != $p_central_header['compression']) {
  	}
  	if ($p_local_header['mtime'] != $p_central_header['mtime']) {
  	}
  	if ($p_local_header['filename_len'] != $p_central_header['filename_len']) {
  	}

  	// ----- Look for flag bit 3
  	if (($p_local_header['flag'] & 8) == 8) {
          $p_local_header['size'] = $p_central_header['size'];
          $p_local_header['compressed_size'] = $p_central_header['compressed_size'];
          $p_local_header['crc'] = $p_central_header['crc'];
  	}

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privReadEndCentralDir()
  // Description :
  // Parameters :
  // Return Values :
  // --------------------------------------------------------------------------------
  function privReadEndCentralDir(&$p_central_dir)
  {
    $v_result=1;

    // ----- Go to the end of the zip file
    $v_size = filesize($this->zipname);
    @fseek($this->zip_fd, $v_size);
    if (@ftell($this->zip_fd) != $v_size)
    {
      // ----- Error log
      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to go to the end of the archive \''.$this->zipname.'\'');

      // ----- Return
      return PclZip::errorCode();
    }

    // ----- First try : look if this is an archive with no commentaries (most of the time)
    // in this case the end of central dir is at 22 bytes of the file end
    $v_found = 0;
    if ($v_size > 26) {
      @fseek($this->zip_fd, $v_size-22);
      if (($v_pos = @ftell($this->zip_fd)) != ($v_size-22))
      {
        // ----- Error log
        PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');

        // ----- Return
        return PclZip::errorCode();
      }

      // ----- Read for bytes
      $v_binary_data = @fread($this->zip_fd, 4);
      $v_data = @unpack('Vid', $v_binary_data);

      // ----- Check signature
      if ($v_data['id'] == 0x06054b50) {
        $v_found = 1;
      }

      $v_pos = ftell($this->zip_fd);
    }

    // ----- Go back to the maximum possible size of the Central Dir End Record
    if (!$v_found) {
      $v_maximum_size = 65557; // 0xFFFF + 22;
      if ($v_maximum_size > $v_size)
        $v_maximum_size = $v_size;
      @fseek($this->zip_fd, $v_size-$v_maximum_size);
      if (@ftell($this->zip_fd) != ($v_size-$v_maximum_size))
      {
        // ----- Error log
        PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');

        // ----- Return
        return PclZip::errorCode();
      }

      // ----- Read byte per byte in order to find the signature
      $v_pos = ftell($this->zip_fd);
      $v_bytes = 0x00000000;
      while ($v_pos < $v_size)
      {
        // ----- Read a byte
        $v_byte = @fread($this->zip_fd, 1);

        // -----  Add the byte
        //$v_bytes = ($v_bytes << 8) | Ord($v_byte);
        // Note we mask the old value down such that once shifted we can never end up with more than a 32bit number
        // Otherwise on systems where we have 64bit integers the check below for the magic number will fail.
        $v_bytes = ( ($v_bytes & 0xFFFFFF) << 8) | Ord($v_byte);

        // ----- Compare the bytes
        if ($v_bytes == 0x504b0506)
        {
          $v_pos++;
          break;
        }

        $v_pos++;
      }

      // ----- Look if not found end of central dir
      if ($v_pos == $v_size)
      {

        // ----- Error log
        PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Unable to find End of Central Dir Record signature");

        // ----- Return
        return PclZip::errorCode();
      }
    }

    // ----- Read the first 18 bytes of the header
    $v_binary_data = fread($this->zip_fd, 18);

    // ----- Look for invalid block size
    if (strlen($v_binary_data) != 18)
    {

      // ----- Error log
      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid End of Central Dir Record size : ".strlen($v_binary_data));

      // ----- Return
      return PclZip::errorCode();
    }

    // ----- Extract the values
    $v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data);

    // ----- Check the global size
    if (($v_pos + $v_data['comment_size'] + 18) != $v_size) {

	  // ----- Removed in release 2.2 see readme file
	  // The check of the file size is a little too strict.
	  // Some bugs where found when a zip is encrypted/decrypted with 'crypt'.
	  // While decrypted, zip has training 0 bytes
	  if (0) {
      // ----- Error log
      PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT,
	                       'The central dir is not at the end of the archive.'
						   .' Some trailing bytes exists after the archive.');

      // ----- Return
      return PclZip::errorCode();
	  }
    }

    // ----- Get comment
    if ($v_data['comment_size'] != 0) {
      $p_central_dir['comment'] = fread($this->zip_fd, $v_data['comment_size']);
    }
    else
      $p_central_dir['comment'] = '';

    $p_central_dir['entries'] = $v_data['entries'];
    $p_central_dir['disk_entries'] = $v_data['disk_entries'];
    $p_central_dir['offset'] = $v_data['offset'];
    $p_central_dir['size'] = $v_data['size'];
    $p_central_dir['disk'] = $v_data['disk'];
    $p_central_dir['disk_start'] = $v_data['disk_start'];

    // TBC
    //for(reset($p_central_dir); $key = key($p_central_dir); next($p_central_dir)) {
    //}

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privDeleteByRule()
  // Description :
  // Parameters :
  // Return Values :
  // --------------------------------------------------------------------------------
  function privDeleteByRule(&$p_result_list, &$p_options)
  {
    $v_result=1;
    $v_list_detail = array();

    // ----- Open the zip file
    if (($v_result=$this->privOpenFd('rb')) != 1)
    {
      // ----- Return
      return $v_result;
    }

    // ----- Read the central directory information
    $v_central_dir = array();
    if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
    {
      $this->privCloseFd();
      return $v_result;
    }

    // ----- Go to beginning of File
    @rewind($this->zip_fd);

    // ----- Scan all the files
    // ----- Start at beginning of Central Dir
    $v_pos_entry = $v_central_dir['offset'];
    @rewind($this->zip_fd);
    if (@fseek($this->zip_fd, $v_pos_entry))
    {
      // ----- Close the zip file
      $this->privCloseFd();

      // ----- Error log
      PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');

      // ----- Return
      return PclZip::errorCode();
    }

    // ----- Read each entry
    $v_header_list = array();
    $j_start = 0;
    for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
    {

      // ----- Read the file header
      $v_header_list[$v_nb_extracted] = array();
      if (($v_result = $this->privReadCentralFileHeader($v_header_list[$v_nb_extracted])) != 1)
      {
        // ----- Close the zip file
        $this->privCloseFd();

        return $v_result;
      }


      // ----- Store the index
      $v_header_list[$v_nb_extracted]['index'] = $i;

      // ----- Look for the specific extract rules
      $v_found = false;

      // ----- Look for extract by name rule
      if (   (isset($p_options[PCLZIP_OPT_BY_NAME]))
          && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) {

          // ----- Look if the filename is in the list
          for ($j=0; ($j<sizeof($p_options[PCLZIP_OPT_BY_NAME])) && (!$v_found); $j++) {

              // ----- Look for a directory
              if (substr($p_options[PCLZIP_OPT_BY_NAME][$j], -1) == "/") {

                  // ----- Look if the directory is in the filename path
                  if (   (strlen($v_header_list[$v_nb_extracted]['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j]))
                      && (substr($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
                      $v_found = true;
                  }
                  elseif (   (($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */
                          && ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
                      $v_found = true;
                  }
              }
              // ----- Look for a filename
              elseif ($v_header_list[$v_nb_extracted]['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) {
                  $v_found = true;
              }
          }
      }

      // ----- Look for extract by ereg rule
      // ereg() is deprecated with PHP 5.3
      /*
      else if (   (isset($p_options[PCLZIP_OPT_BY_EREG]))
               && ($p_options[PCLZIP_OPT_BY_EREG] != "")) {

          if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
              $v_found = true;
          }
      }
      */

      // ----- Look for extract by preg rule
      else if (   (isset($p_options[PCLZIP_OPT_BY_PREG]))
               && ($p_options[PCLZIP_OPT_BY_PREG] != "")) {

          if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
              $v_found = true;
          }
      }

      // ----- Look for extract by index rule
      else if (   (isset($p_options[PCLZIP_OPT_BY_INDEX]))
               && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) {

          // ----- Look if the index is in the list
          for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_found); $j++) {

              if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) {
                  $v_found = true;
              }
              if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) {
                  $j_start = $j+1;
              }

              if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
                  break;
              }
          }
      }
      else {
      	$v_found = true;
      }

      // ----- Look for deletion
      if ($v_found)
      {
        unset($v_header_list[$v_nb_extracted]);
      }
      else
      {
        $v_nb_extracted++;
      }
    }

    // ----- Look if something need to be deleted
    if ($v_nb_extracted > 0) {

        // ----- Creates a temporary file
        $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';

        // ----- Creates a temporary zip archive
        $v_temp_zip = new PclZip($v_zip_temp_name);

        // ----- Open the temporary zip file in write mode
        if (($v_result = $v_temp_zip->privOpenFd('wb')) != 1) {
            $this->privCloseFd();

            // ----- Return
            return $v_result;
        }

        // ----- Look which file need to be kept
        for ($i=0; $i<sizeof($v_header_list); $i++) {

            // ----- Calculate the position of the header
            @rewind($this->zip_fd);
            if (@fseek($this->zip_fd,  $v_header_list[$i]['offset'])) {
                // ----- Close the zip file
                $this->privCloseFd();
                $v_temp_zip->privCloseFd();
                @unlink($v_zip_temp_name);

                // ----- Error log
                PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');

                // ----- Return
                return PclZip::errorCode();
            }

            // ----- Read the file header
            $v_local_header = array();
            if (($v_result = $this->privReadFileHeader($v_local_header)) != 1) {
                // ----- Close the zip file
                $this->privCloseFd();
                $v_temp_zip->privCloseFd();
                @unlink($v_zip_temp_name);

                // ----- Return
                return $v_result;
            }

            // ----- Check that local file header is same as central file header
            if ($this->privCheckFileHeaders($v_local_header,
			                                $v_header_list[$i]) != 1) {
                // TBC
            }
            unset($v_local_header);

            // ----- Write the file header
            if (($v_result = $v_temp_zip->privWriteFileHeader($v_header_list[$i])) != 1) {
                // ----- Close the zip file
                $this->privCloseFd();
                $v_temp_zip->privCloseFd();
                @unlink($v_zip_temp_name);

                // ----- Return
                return $v_result;
            }

            // ----- Read/write the data block
            if (($v_result = PclZipUtilCopyBlock($this->zip_fd, $v_temp_zip->zip_fd, $v_header_list[$i]['compressed_size'])) != 1) {
                // ----- Close the zip file
                $this->privCloseFd();
                $v_temp_zip->privCloseFd();
                @unlink($v_zip_temp_name);

                // ----- Return
                return $v_result;
            }
        }

        // ----- Store the offset of the central dir
        $v_offset = @ftell($v_temp_zip->zip_fd);

        // ----- Re-Create the Central Dir files header
        for ($i=0; $i<sizeof($v_header_list); $i++) {
            // ----- Create the file header
            if (($v_result = $v_temp_zip->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
                $v_temp_zip->privCloseFd();
                $this->privCloseFd();
                @unlink($v_zip_temp_name);

                // ----- Return
                return $v_result;
            }

            // ----- Transform the header to a 'usable' info
            $v_temp_zip->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
        }


        // ----- Zip file comment
        $v_comment = '';
        if (isset($p_options[PCLZIP_OPT_COMMENT])) {
          $v_comment = $p_options[PCLZIP_OPT_COMMENT];
        }

        // ----- Calculate the size of the central header
        $v_size = @ftell($v_temp_zip->zip_fd)-$v_offset;

        // ----- Create the central dir footer
        if (($v_result = $v_temp_zip->privWriteCentralHeader(sizeof($v_header_list), $v_size, $v_offset, $v_comment)) != 1) {
            // ----- Reset the file list
            unset($v_header_list);
            $v_temp_zip->privCloseFd();
            $this->privCloseFd();
            @unlink($v_zip_temp_name);

            // ----- Return
            return $v_result;
        }

        // ----- Close
        $v_temp_zip->privCloseFd();
        $this->privCloseFd();

        // ----- Delete the zip file
        // TBC : I should test the result ...
        @unlink($this->zipname);

        // ----- Rename the temporary file
        // TBC : I should test the result ...
        //@rename($v_zip_temp_name, $this->zipname);
        PclZipUtilRename($v_zip_temp_name, $this->zipname);

        // ----- Destroy the temporary archive
        unset($v_temp_zip);
    }

    // ----- Remove every files : reset the file
    else if ($v_central_dir['entries'] != 0) {
        $this->privCloseFd();

        if (($v_result = $this->privOpenFd('wb')) != 1) {
          return $v_result;
        }

        if (($v_result = $this->privWriteCentralHeader(0, 0, 0, '')) != 1) {
          return $v_result;
        }

        $this->privCloseFd();
    }

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privDirCheck()
  // Description :
  //   Check if a directory exists, if not it creates it and all the parents directory
  //   which may be useful.
  // Parameters :
  //   $p_dir : Directory path to check.
  // Return Values :
  //    1 : OK
  //   -1 : Unable to create directory
  // --------------------------------------------------------------------------------
  function privDirCheck($p_dir, $p_is_dir=false)
  {
    $v_result = 1;


    // ----- Remove the final '/'
    if (($p_is_dir) && (substr($p_dir, -1)=='/'))
    {
      $p_dir = substr($p_dir, 0, strlen($p_dir)-1);
    }

    // ----- Check the directory availability
    if ((is_dir($p_dir)) || ($p_dir == ""))
    {
      return 1;
    }

    // ----- Extract parent directory
    $p_parent_dir = dirname($p_dir);

    // ----- Just a check
    if ($p_parent_dir != $p_dir)
    {
      // ----- Look for parent directory
      if ($p_parent_dir != "")
      {
        if (($v_result = $this->privDirCheck($p_parent_dir)) != 1)
        {
          return $v_result;
        }
      }
    }

    // ----- Create the directory
    if (!@mkdir($p_dir, 0777))
    {
      // ----- Error log
      PclZip::privErrorLog(PCLZIP_ERR_DIR_CREATE_FAIL, "Unable to create directory '$p_dir'");

      // ----- Return
      return PclZip::errorCode();
    }

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privMerge()
  // Description :
  //   If $p_archive_to_add does not exist, the function exit with a success result.
  // Parameters :
  // Return Values :
  // --------------------------------------------------------------------------------
  function privMerge(&$p_archive_to_add)
  {
    $v_result=1;

    // ----- Look if the archive_to_add exists
    if (!is_file($p_archive_to_add->zipname))
    {

      // ----- Nothing to merge, so merge is a success
      $v_result = 1;

      // ----- Return
      return $v_result;
    }

    // ----- Look if the archive exists
    if (!is_file($this->zipname))
    {

      // ----- Do a duplicate
      $v_result = $this->privDuplicate($p_archive_to_add->zipname);

      // ----- Return
      return $v_result;
    }

    // ----- Open the zip file
    if (($v_result=$this->privOpenFd('rb')) != 1)
    {
      // ----- Return
      return $v_result;
    }

    // ----- Read the central directory information
    $v_central_dir = array();
    if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
    {
      $this->privCloseFd();
      return $v_result;
    }

    // ----- Go to beginning of File
    @rewind($this->zip_fd);

    // ----- Open the archive_to_add file
    if (($v_result=$p_archive_to_add->privOpenFd('rb')) != 1)
    {
      $this->privCloseFd();

      // ----- Return
      return $v_result;
    }

    // ----- Read the central directory information
    $v_central_dir_to_add = array();
    if (($v_result = $p_archive_to_add->privReadEndCentralDir($v_central_dir_to_add)) != 1)
    {
      $this->privCloseFd();
      $p_archive_to_add->privCloseFd();

      return $v_result;
    }

    // ----- Go to beginning of File
    @rewind($p_archive_to_add->zip_fd);

    // ----- Creates a temporary file
    $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';

    // ----- Open the temporary file in write mode
    if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
    {
      $this->privCloseFd();
      $p_archive_to_add->privCloseFd();

      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');

      // ----- Return
      return PclZip::errorCode();
    }

    // ----- Copy the files from the archive to the temporary file
    // TBC : Here I should better append the file and go back to erase the central dir
    $v_size = $v_central_dir['offset'];
    while ($v_size != 0)
    {
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
      $v_buffer = fread($this->zip_fd, $v_read_size);
      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
      $v_size -= $v_read_size;
    }

    // ----- Copy the files from the archive_to_add into the temporary file
    $v_size = $v_central_dir_to_add['offset'];
    while ($v_size != 0)
    {
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
      $v_buffer = fread($p_archive_to_add->zip_fd, $v_read_size);
      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
      $v_size -= $v_read_size;
    }

    // ----- Store the offset of the central dir
    $v_offset = @ftell($v_zip_temp_fd);

    // ----- Copy the block of file headers from the old archive
    $v_size = $v_central_dir['size'];
    while ($v_size != 0)
    {
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
      $v_buffer = @fread($this->zip_fd, $v_read_size);
      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
      $v_size -= $v_read_size;
    }

    // ----- Copy the block of file headers from the archive_to_add
    $v_size = $v_central_dir_to_add['size'];
    while ($v_size != 0)
    {
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
      $v_buffer = @fread($p_archive_to_add->zip_fd, $v_read_size);
      @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
      $v_size -= $v_read_size;
    }

    // ----- Merge the file comments
    $v_comment = $v_central_dir['comment'].' '.$v_central_dir_to_add['comment'];

    // ----- Calculate the size of the (new) central header
    $v_size = @ftell($v_zip_temp_fd)-$v_offset;

    // ----- Swap the file descriptor
    // Here is a trick : I swap the temporary fd with the zip fd, in order to use
    // the following methods on the temporary fil and not the real archive fd
    $v_swap = $this->zip_fd;
    $this->zip_fd = $v_zip_temp_fd;
    $v_zip_temp_fd = $v_swap;

    // ----- Create the central dir footer
    if (($v_result = $this->privWriteCentralHeader($v_central_dir['entries']+$v_central_dir_to_add['entries'], $v_size, $v_offset, $v_comment)) != 1)
    {
      $this->privCloseFd();
      $p_archive_to_add->privCloseFd();
      @fclose($v_zip_temp_fd);
      $this->zip_fd = null;

      // ----- Reset the file list
      unset($v_header_list);

      // ----- Return
      return $v_result;
    }

    // ----- Swap back the file descriptor
    $v_swap = $this->zip_fd;
    $this->zip_fd = $v_zip_temp_fd;
    $v_zip_temp_fd = $v_swap;

    // ----- Close
    $this->privCloseFd();
    $p_archive_to_add->privCloseFd();

    // ----- Close the temporary file
    @fclose($v_zip_temp_fd);

    // ----- Delete the zip file
    // TBC : I should test the result ...
    @unlink($this->zipname);

    // ----- Rename the temporary file
    // TBC : I should test the result ...
    //@rename($v_zip_temp_name, $this->zipname);
    PclZipUtilRename($v_zip_temp_name, $this->zipname);

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privDuplicate()
  // Description :
  // Parameters :
  // Return Values :
  // --------------------------------------------------------------------------------
  function privDuplicate($p_archive_filename)
  {
    $v_result=1;

    // ----- Look if the $p_archive_filename exists
    if (!is_file($p_archive_filename))
    {

      // ----- Nothing to duplicate, so duplicate is a success.
      $v_result = 1;

      // ----- Return
      return $v_result;
    }

    // ----- Open the zip file
    if (($v_result=$this->privOpenFd('wb')) != 1)
    {
      // ----- Return
      return $v_result;
    }

    // ----- Open the temporary file in write mode
    if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0)
    {
      $this->privCloseFd();

      PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive file \''.$p_archive_filename.'\' in binary write mode');

      // ----- Return
      return PclZip::errorCode();
    }

    // ----- Copy the files from the archive to the temporary file
    // TBC : Here I should better append the file and go back to erase the central dir
    $v_size = filesize($p_archive_filename);
    while ($v_size != 0)
    {
      $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
      $v_buffer = fread($v_zip_temp_fd, $v_read_size);
      @fwrite($this->zip_fd, $v_buffer, $v_read_size);
      $v_size -= $v_read_size;
    }

    // ----- Close
    $this->privCloseFd();

    // ----- Close the temporary file
    @fclose($v_zip_temp_fd);

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privErrorLog()
  // Description :
  // Parameters :
  // --------------------------------------------------------------------------------
  function privErrorLog($p_error_code=0, $p_error_string='')
  {
    if (PCLZIP_ERROR_EXTERNAL == 1) {
      PclError($p_error_code, $p_error_string);
    }
    else {
      $this->error_code = $p_error_code;
      $this->error_string = $p_error_string;
    }
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privErrorReset()
  // Description :
  // Parameters :
  // --------------------------------------------------------------------------------
  function privErrorReset()
  {
    if (PCLZIP_ERROR_EXTERNAL == 1) {
      PclErrorReset();
    }
    else {
      $this->error_code = 0;
      $this->error_string = '';
    }
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privDisableMagicQuotes()
  // Description :
  // Parameters :
  // Return Values :
  // --------------------------------------------------------------------------------
  function privDisableMagicQuotes()
  {
    $v_result=1;

	// EDIT for WordPress 5.3.0
	// magic_quote functions are deprecated in PHP 7.4, now assuming it's always off.
	/*

    // ----- Look if function exists
    if (   (!function_exists("get_magic_quotes_runtime"))
	    || (!function_exists("set_magic_quotes_runtime"))) {
      return $v_result;
	}

    // ----- Look if already done
    if ($this->magic_quotes_status != -1) {
      return $v_result;
	}

	// ----- Get and memorize the magic_quote value
	$this->magic_quotes_status = @get_magic_quotes_runtime();

	// ----- Disable magic_quotes
	if ($this->magic_quotes_status == 1) {
	  @set_magic_quotes_runtime(0);
	}
	*/

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : privSwapBackMagicQuotes()
  // Description :
  // Parameters :
  // Return Values :
  // --------------------------------------------------------------------------------
  function privSwapBackMagicQuotes()
  {
    $v_result=1;

	// EDIT for WordPress 5.3.0
	// magic_quote functions are deprecated in PHP 7.4, now assuming it's always off.
	/*

    // ----- Look if function exists
    if (   (!function_exists("get_magic_quotes_runtime"))
	    || (!function_exists("set_magic_quotes_runtime"))) {
      return $v_result;
	}

    // ----- Look if something to do
    if ($this->magic_quotes_status != -1) {
      return $v_result;
	}

	// ----- Swap back magic_quotes
	if ($this->magic_quotes_status == 1) {
  	  @set_magic_quotes_runtime($this->magic_quotes_status);
	}

	*/
    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  }
  // End of class
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : PclZipUtilPathReduction()
  // Description :
  // Parameters :
  // Return Values :
  // --------------------------------------------------------------------------------
  function PclZipUtilPathReduction($p_dir)
  {
    $v_result = "";

    // ----- Look for not empty path
    if ($p_dir != "") {
      // ----- Explode path by directory names
      $v_list = explode("/", $p_dir);

      // ----- Study directories from last to first
      $v_skip = 0;
      for ($i=sizeof($v_list)-1; $i>=0; $i--) {
        // ----- Look for current path
        if ($v_list[$i] == ".") {
          // ----- Ignore this directory
          // Should be the first $i=0, but no check is done
        }
        else if ($v_list[$i] == "..") {
		  $v_skip++;
        }
        else if ($v_list[$i] == "") {
		  // ----- First '/' i.e. root slash
		  if ($i == 0) {
            $v_result = "/".$v_result;
		    if ($v_skip > 0) {
		        // ----- It is an invalid path, so the path is not modified
		        // TBC
		        $v_result = $p_dir;
                $v_skip = 0;
		    }
		  }
		  // ----- Last '/' i.e. indicates a directory
		  else if ($i == (sizeof($v_list)-1)) {
            $v_result = $v_list[$i];
		  }
		  // ----- Double '/' inside the path
		  else {
            // ----- Ignore only the double '//' in path,
            // but not the first and last '/'
		  }
        }
        else {
		  // ----- Look for item to skip
		  if ($v_skip > 0) {
		    $v_skip--;
		  }
		  else {
            $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?"/".$v_result:"");
		  }
        }
      }

      // ----- Look for skip
      if ($v_skip > 0) {
        while ($v_skip > 0) {
            $v_result = '../'.$v_result;
            $v_skip--;
        }
      }
    }

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : PclZipUtilPathInclusion()
  // Description :
  //   This function indicates if the path $p_path is under the $p_dir tree. Or,
  //   said in an other way, if the file or sub-dir $p_path is inside the dir
  //   $p_dir.
  //   The function indicates also if the path is exactly the same as the dir.
  //   This function supports path with duplicated '/' like '//', but does not
  //   support '.' or '..' statements.
  // Parameters :
  // Return Values :
  //   0 if $p_path is not inside directory $p_dir
  //   1 if $p_path is inside directory $p_dir
  //   2 if $p_path is exactly the same as $p_dir
  // --------------------------------------------------------------------------------
  function PclZipUtilPathInclusion($p_dir, $p_path)
  {
    $v_result = 1;

    // ----- Look for path beginning by ./
    if (   ($p_dir == '.')
        || ((strlen($p_dir) >=2) && (substr($p_dir, 0, 2) == './'))) {
      $p_dir = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_dir, 1);
    }
    if (   ($p_path == '.')
        || ((strlen($p_path) >=2) && (substr($p_path, 0, 2) == './'))) {
      $p_path = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_path, 1);
    }

    // ----- Explode dir and path by directory separator
    $v_list_dir = explode("/", $p_dir);
    $v_list_dir_size = sizeof($v_list_dir);
    $v_list_path = explode("/", $p_path);
    $v_list_path_size = sizeof($v_list_path);

    // ----- Study directories paths
    $i = 0;
    $j = 0;
    while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) {

      // ----- Look for empty dir (path reduction)
      if ($v_list_dir[$i] == '') {
        $i++;
        continue;
      }
      if ($v_list_path[$j] == '') {
        $j++;
        continue;
      }

      // ----- Compare the items
      if (($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ( $v_list_path[$j] != ''))  {
        $v_result = 0;
      }

      // ----- Next items
      $i++;
      $j++;
    }

    // ----- Look if everything seems to be the same
    if ($v_result) {
      // ----- Skip all the empty items
      while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) $j++;
      while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) $i++;

      if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) {
        // ----- There are exactly the same
        $v_result = 2;
      }
      else if ($i < $v_list_dir_size) {
        // ----- The path is shorter than the dir
        $v_result = 0;
      }
    }

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : PclZipUtilCopyBlock()
  // Description :
  // Parameters :
  //   $p_mode : read/write compression mode
  //             0 : src & dest normal
  //             1 : src gzip, dest normal
  //             2 : src normal, dest gzip
  //             3 : src & dest gzip
  // Return Values :
  // --------------------------------------------------------------------------------
  function PclZipUtilCopyBlock($p_src, $p_dest, $p_size, $p_mode=0)
  {
    $v_result = 1;

    if ($p_mode==0)
    {
      while ($p_size != 0)
      {
        $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
        $v_buffer = @fread($p_src, $v_read_size);
        @fwrite($p_dest, $v_buffer, $v_read_size);
        $p_size -= $v_read_size;
      }
    }
    else if ($p_mode==1)
    {
      while ($p_size != 0)
      {
        $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
        $v_buffer = @gzread($p_src, $v_read_size);
        @fwrite($p_dest, $v_buffer, $v_read_size);
        $p_size -= $v_read_size;
      }
    }
    else if ($p_mode==2)
    {
      while ($p_size != 0)
      {
        $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
        $v_buffer = @fread($p_src, $v_read_size);
        @gzwrite($p_dest, $v_buffer, $v_read_size);
        $p_size -= $v_read_size;
      }
    }
    else if ($p_mode==3)
    {
      while ($p_size != 0)
      {
        $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
        $v_buffer = @gzread($p_src, $v_read_size);
        @gzwrite($p_dest, $v_buffer, $v_read_size);
        $p_size -= $v_read_size;
      }
    }

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : PclZipUtilRename()
  // Description :
  //   This function tries to do a simple rename() function. If it fails, it
  //   tries to copy the $p_src file in a new $p_dest file and then unlink the
  //   first one.
  // Parameters :
  //   $p_src : Old filename
  //   $p_dest : New filename
  // Return Values :
  //   1 on success, 0 on failure.
  // --------------------------------------------------------------------------------
  function PclZipUtilRename($p_src, $p_dest)
  {
    $v_result = 1;

    // ----- Try to rename the files
    if (!@rename($p_src, $p_dest)) {

      // ----- Try to copy & unlink the src
      if (!@copy($p_src, $p_dest)) {
        $v_result = 0;
      }
      else if (!@unlink($p_src)) {
        $v_result = 0;
      }
    }

    // ----- Return
    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : PclZipUtilOptionText()
  // Description :
  //   Translate option value in text. Mainly for debug purpose.
  // Parameters :
  //   $p_option : the option value.
  // Return Values :
  //   The option text value.
  // --------------------------------------------------------------------------------
  function PclZipUtilOptionText($p_option)
  {

    $v_list = get_defined_constants();
    for (reset($v_list); $v_key = key($v_list); next($v_list)) {
	    $v_prefix = substr($v_key, 0, 10);
	    if ((   ($v_prefix == 'PCLZIP_OPT')
           || ($v_prefix == 'PCLZIP_CB_')
           || ($v_prefix == 'PCLZIP_ATT'))
	        && ($v_list[$v_key] == $p_option)) {
        return $v_key;
	    }
    }

    $v_result = 'Unknown';

    return $v_result;
  }
  // --------------------------------------------------------------------------------

  // --------------------------------------------------------------------------------
  // Function : PclZipUtilTranslateWinPath()
  // Description :
  //   Translate windows path by replacing '\' by '/' and optionally removing
  //   drive letter.
  // Parameters :
  //   $p_path : path to translate.
  //   $p_remove_disk_letter : true | false
  // Return Values :
  //   The path translated.
  // --------------------------------------------------------------------------------
  function PclZipUtilTranslateWinPath($p_path, $p_remove_disk_letter=true)
  {
    if (PHP_OS_FAMILY == 'Windows') {
      // ----- Look for potential disk letter
      if (($p_remove_disk_letter) && (($v_position = strpos($p_path, ':')) != false)) {
          $p_path = substr($p_path, $v_position+1);
      }
      // ----- Change potential windows directory separator
      if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) {
          $p_path = strtr($p_path, '\\', '/');
      }
    }
    return $p_path;
  }
  // --------------------------------------------------------------------------------


?>
class-wp-users-list-table.php000064400000045162151212616040012211 0ustar00<?php
/**
 * List Table API: WP_Users_List_Table class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 3.1.0
 */

/**
 * Core class used to implement displaying users in a list table.
 *
 * @since 3.1.0
 *
 * @see WP_List_Table
 */
class WP_Users_List_Table extends WP_List_Table {

	/**
	 * Site ID to generate the Users list table for.
	 *
	 * @since 3.1.0
	 * @var int
	 */
	public $site_id;

	/**
	 * Whether or not the current Users list table is for Multisite.
	 *
	 * @since 3.1.0
	 * @var bool
	 */
	public $is_site_users;

	/**
	 * Constructor.
	 *
	 * @since 3.1.0
	 *
	 * @see WP_List_Table::__construct() for more information on default arguments.
	 *
	 * @param array $args An associative array of arguments.
	 */
	public function __construct( $args = array() ) {
		parent::__construct(
			array(
				'singular' => 'user',
				'plural'   => 'users',
				'screen'   => isset( $args['screen'] ) ? $args['screen'] : null,
			)
		);

		$this->is_site_users = 'site-users-network' === $this->screen->id;

		if ( $this->is_site_users ) {
			$this->site_id = isset( $_REQUEST['id'] ) ? (int) $_REQUEST['id'] : 0;
		}
	}

	/**
	 * Checks the current user's permissions.
	 *
	 * @since 3.1.0
	 *
	 * @return bool
	 */
	public function ajax_user_can() {
		if ( $this->is_site_users ) {
			return current_user_can( 'manage_sites' );
		} else {
			return current_user_can( 'list_users' );
		}
	}

	/**
	 * Prepares the users list for display.
	 *
	 * @since 3.1.0
	 *
	 * @global string $role
	 * @global string $usersearch
	 */
	public function prepare_items() {
		global $role, $usersearch;

		$usersearch = isset( $_REQUEST['s'] ) ? wp_unslash( trim( $_REQUEST['s'] ) ) : '';

		$role = isset( $_REQUEST['role'] ) ? $_REQUEST['role'] : '';

		$per_page       = ( $this->is_site_users ) ? 'site_users_network_per_page' : 'users_per_page';
		$users_per_page = $this->get_items_per_page( $per_page );

		$paged = $this->get_pagenum();

		if ( 'none' === $role ) {
			$args = array(
				'number'  => $users_per_page,
				'offset'  => ( $paged - 1 ) * $users_per_page,
				'include' => wp_get_users_with_no_role( $this->site_id ),
				'search'  => $usersearch,
				'fields'  => 'all_with_meta',
			);
		} else {
			$args = array(
				'number' => $users_per_page,
				'offset' => ( $paged - 1 ) * $users_per_page,
				'role'   => $role,
				'search' => $usersearch,
				'fields' => 'all_with_meta',
			);
		}

		if ( '' !== $args['search'] ) {
			$args['search'] = '*' . $args['search'] . '*';
		}

		if ( $this->is_site_users ) {
			$args['blog_id'] = $this->site_id;
		}

		if ( isset( $_REQUEST['orderby'] ) ) {
			$args['orderby'] = $_REQUEST['orderby'];
		}

		if ( isset( $_REQUEST['order'] ) ) {
			$args['order'] = $_REQUEST['order'];
		}

		/**
		 * Filters the query arguments used to retrieve users for the current users list table.
		 *
		 * @since 4.4.0
		 *
		 * @param array $args Arguments passed to WP_User_Query to retrieve items for the current
		 *                    users list table.
		 */
		$args = apply_filters( 'users_list_table_query_args', $args );

		// Query the user IDs for this page.
		$wp_user_search = new WP_User_Query( $args );

		$this->items = $wp_user_search->get_results();

		$this->set_pagination_args(
			array(
				'total_items' => $wp_user_search->get_total(),
				'per_page'    => $users_per_page,
			)
		);
	}

	/**
	 * Outputs 'no users' message.
	 *
	 * @since 3.1.0
	 */
	public function no_items() {
		_e( 'No users found.' );
	}

	/**
	 * Returns an associative array listing all the views that can be used
	 * with this table.
	 *
	 * Provides a list of roles and user count for that role for easy
	 * filtering of the user table.
	 *
	 * @since 3.1.0
	 *
	 * @global string $role
	 *
	 * @return string[] An array of HTML links keyed by their view.
	 */
	protected function get_views() {
		global $role;

		$wp_roles = wp_roles();

		$count_users = ! wp_is_large_user_count();

		if ( $this->is_site_users ) {
			$url = 'site-users.php?id=' . $this->site_id;
		} else {
			$url = 'users.php';
		}

		$role_links  = array();
		$avail_roles = array();
		$all_text    = __( 'All' );

		if ( $count_users ) {
			if ( $this->is_site_users ) {
				switch_to_blog( $this->site_id );
				$users_of_blog = count_users( 'time', $this->site_id );
				restore_current_blog();
			} else {
				$users_of_blog = count_users();
			}

			$total_users = $users_of_blog['total_users'];
			$avail_roles =& $users_of_blog['avail_roles'];
			unset( $users_of_blog );

			$all_text = sprintf(
				/* translators: %s: Number of users. */
				_nx(
					'All <span class="count">(%s)</span>',
					'All <span class="count">(%s)</span>',
					$total_users,
					'users'
				),
				number_format_i18n( $total_users )
			);
		}

		$role_links['all'] = array(
			'url'     => $url,
			'label'   => $all_text,
			'current' => empty( $role ),
		);

		foreach ( $wp_roles->get_names() as $this_role => $name ) {
			if ( $count_users && ! isset( $avail_roles[ $this_role ] ) ) {
				continue;
			}

			$name = translate_user_role( $name );
			if ( $count_users ) {
				$name = sprintf(
					/* translators: 1: User role name, 2: Number of users. */
					__( '%1$s <span class="count">(%2$s)</span>' ),
					$name,
					number_format_i18n( $avail_roles[ $this_role ] )
				);
			}

			$role_links[ $this_role ] = array(
				'url'     => esc_url( add_query_arg( 'role', $this_role, $url ) ),
				'label'   => $name,
				'current' => $this_role === $role,
			);
		}

		if ( ! empty( $avail_roles['none'] ) ) {

			$name = __( 'No role' );
			$name = sprintf(
				/* translators: 1: User role name, 2: Number of users. */
				__( '%1$s <span class="count">(%2$s)</span>' ),
				$name,
				number_format_i18n( $avail_roles['none'] )
			);

			$role_links['none'] = array(
				'url'     => esc_url( add_query_arg( 'role', 'none', $url ) ),
				'label'   => $name,
				'current' => 'none' === $role,
			);
		}

		return $this->get_views_links( $role_links );
	}

	/**
	 * Retrieves an associative array of bulk actions available on this table.
	 *
	 * @since 3.1.0
	 *
	 * @return array Array of bulk action labels keyed by their action.
	 */
	protected function get_bulk_actions() {
		$actions = array();

		if ( is_multisite() ) {
			if ( current_user_can( 'remove_users' ) ) {
				$actions['remove'] = __( 'Remove' );
			}
		} else {
			if ( current_user_can( 'delete_users' ) ) {
				$actions['delete'] = __( 'Delete' );
			}
		}

		// Add a password reset link to the bulk actions dropdown.
		if ( current_user_can( 'edit_users' ) ) {
			$actions['resetpassword'] = __( 'Send password reset' );
		}

		return $actions;
	}

	/**
	 * Outputs the controls to allow user roles to be changed in bulk.
	 *
	 * @since 3.1.0
	 *
	 * @param string $which Whether this is being invoked above ("top")
	 *                      or below the table ("bottom").
	 */
	protected function extra_tablenav( $which ) {
		$id        = 'bottom' === $which ? 'new_role2' : 'new_role';
		$button_id = 'bottom' === $which ? 'changeit2' : 'changeit';
		?>
	<div class="alignleft actions">
		<?php if ( current_user_can( 'promote_users' ) && $this->has_items() ) : ?>
		<label class="screen-reader-text" for="<?php echo $id; ?>">
			<?php
			/* translators: Hidden accessibility text. */
			_e( 'Change role to&hellip;' );
			?>
		</label>
		<select name="<?php echo $id; ?>" id="<?php echo $id; ?>">
			<option value=""><?php _e( 'Change role to&hellip;' ); ?></option>
			<?php wp_dropdown_roles(); ?>
			<option value="none"><?php _e( '&mdash; No role for this site &mdash;' ); ?></option>
		</select>
			<?php
			submit_button( __( 'Change' ), '', $button_id, false );
		endif;

		/**
		 * Fires just before the closing div containing the bulk role-change controls
		 * in the Users list table.
		 *
		 * @since 3.5.0
		 * @since 4.6.0 The `$which` parameter was added.
		 *
		 * @param string $which The location of the extra table nav markup: 'top' or 'bottom'.
		 */
		do_action( 'restrict_manage_users', $which );
		?>
		</div>
		<?php
		/**
		 * Fires immediately following the closing "actions" div in the tablenav for the users
		 * list table.
		 *
		 * @since 4.9.0
		 *
		 * @param string $which The location of the extra table nav markup: 'top' or 'bottom'.
		 */
		do_action( 'manage_users_extra_tablenav', $which );
	}

	/**
	 * Captures the bulk action required, and return it.
	 *
	 * Overridden from the base class implementation to capture
	 * the role change drop-down.
	 *
	 * @since 3.1.0
	 *
	 * @return string The bulk action required.
	 */
	public function current_action() {
		if ( isset( $_REQUEST['changeit'] ) ) {
			return 'promote';
		}

		return parent::current_action();
	}

	/**
	 * Gets a list of columns for the list table.
	 *
	 * @since 3.1.0
	 *
	 * @return string[] Array of column titles keyed by their column name.
	 */
	public function get_columns() {
		$columns = array(
			'cb'       => '<input type="checkbox" />',
			'username' => __( 'Username' ),
			'name'     => __( 'Name' ),
			'email'    => __( 'Email' ),
			'role'     => __( 'Role' ),
			'posts'    => _x( 'Posts', 'post type general name' ),
		);

		if ( $this->is_site_users ) {
			unset( $columns['posts'] );
		}

		return $columns;
	}

	/**
	 * Gets a list of sortable columns for the list table.
	 *
	 * @since 3.1.0
	 *
	 * @return array Array of sortable columns.
	 */
	protected function get_sortable_columns() {
		$columns = array(
			'username' => array( 'login', false, __( 'Username' ), __( 'Table ordered by Username.' ), 'asc' ),
			'email'    => array( 'email', false, __( 'E-mail' ), __( 'Table ordered by E-mail.' ) ),
		);

		return $columns;
	}

	/**
	 * Generates the list table rows.
	 *
	 * @since 3.1.0
	 */
	public function display_rows() {
		// Query the post counts for this page.
		if ( ! $this->is_site_users ) {
			$post_counts = count_many_users_posts( array_keys( $this->items ) );
		}

		foreach ( $this->items as $userid => $user_object ) {
			echo "\n\t" . $this->single_row( $user_object, '', '', isset( $post_counts ) ? $post_counts[ $userid ] : 0 );
		}
	}

	/**
	 * Generates HTML for a single row on the users.php admin panel.
	 *
	 * @since 3.1.0
	 * @since 4.2.0 The `$style` parameter was deprecated.
	 * @since 4.4.0 The `$role` parameter was deprecated.
	 *
	 * @param WP_User $user_object The current user object.
	 * @param string  $style       Deprecated. Not used.
	 * @param string  $role        Deprecated. Not used.
	 * @param int     $numposts    Optional. Post count to display for this user. Defaults
	 *                             to zero, as in, a new user has made zero posts.
	 * @return string Output for a single row.
	 */
	public function single_row( $user_object, $style = '', $role = '', $numposts = 0 ) {
		if ( ! ( $user_object instanceof WP_User ) ) {
			$user_object = get_userdata( (int) $user_object );
		}
		$user_object->filter = 'display';
		$email               = $user_object->user_email;

		if ( $this->is_site_users ) {
			$url = "site-users.php?id={$this->site_id}&amp;";
		} else {
			$url = 'users.php?';
		}

		$user_roles = $this->get_role_list( $user_object );

		// Set up the hover actions for this user.
		$actions     = array();
		$checkbox    = '';
		$super_admin = '';

		if ( is_multisite() && current_user_can( 'manage_network_users' ) ) {
			if ( in_array( $user_object->user_login, get_super_admins(), true ) ) {
				$super_admin = ' &mdash; ' . __( 'Super Admin' );
			}
		}

		// Check if the user for this row is editable.
		if ( current_user_can( 'list_users' ) ) {
			// Set up the user editing link.
			$edit_link = esc_url(
				add_query_arg(
					'wp_http_referer',
					urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ),
					get_edit_user_link( $user_object->ID )
				)
			);

			if ( current_user_can( 'edit_user', $user_object->ID ) ) {
				$edit            = "<strong><a href=\"{$edit_link}\">{$user_object->user_login}</a>{$super_admin}</strong><br />";
				$actions['edit'] = '<a href="' . $edit_link . '">' . __( 'Edit' ) . '</a>';
			} else {
				$edit = "<strong>{$user_object->user_login}{$super_admin}</strong><br />";
			}

			if ( ! is_multisite()
				&& get_current_user_id() !== $user_object->ID
				&& current_user_can( 'delete_user', $user_object->ID )
			) {
				$actions['delete'] = "<a class='submitdelete' href='" . wp_nonce_url( "users.php?action=delete&amp;user=$user_object->ID", 'bulk-users' ) . "'>" . __( 'Delete' ) . '</a>';
			}

			if ( is_multisite()
				&& current_user_can( 'remove_user', $user_object->ID )
			) {
				$actions['remove'] = "<a class='submitdelete' href='" . wp_nonce_url( $url . "action=remove&amp;user=$user_object->ID", 'bulk-users' ) . "'>" . __( 'Remove' ) . '</a>';
			}

			// Add a link to the user's author archive, if not empty.
			$author_posts_url = get_author_posts_url( $user_object->ID );
			if ( $author_posts_url ) {
				$actions['view'] = sprintf(
					'<a href="%s" aria-label="%s">%s</a>',
					esc_url( $author_posts_url ),
					/* translators: %s: Author's display name. */
					esc_attr( sprintf( __( 'View posts by %s' ), $user_object->display_name ) ),
					__( 'View' )
				);
			}

			// Add a link to send the user a reset password link by email.
			if ( get_current_user_id() !== $user_object->ID
				&& current_user_can( 'edit_user', $user_object->ID )
				&& true === wp_is_password_reset_allowed_for_user( $user_object )
			) {
				$actions['resetpassword'] = "<a class='resetpassword' href='" . wp_nonce_url( "users.php?action=resetpassword&amp;users=$user_object->ID", 'bulk-users' ) . "'>" . __( 'Send password reset' ) . '</a>';
			}

			/**
			 * Filters the action links displayed under each user in the Users list table.
			 *
			 * @since 2.8.0
			 *
			 * @param string[] $actions     An array of action links to be displayed.
			 *                              Default 'Edit', 'Delete' for single site, and
			 *                              'Edit', 'Remove' for Multisite.
			 * @param WP_User  $user_object WP_User object for the currently listed user.
			 */
			$actions = apply_filters( 'user_row_actions', $actions, $user_object );

			// Role classes.
			$role_classes = esc_attr( implode( ' ', array_keys( $user_roles ) ) );

			// Set up the checkbox (because the user is editable, otherwise it's empty).
			$checkbox = sprintf(
				'<input type="checkbox" name="users[]" id="user_%1$s" class="%2$s" value="%1$s" />' .
				'<label for="user_%1$s"><span class="screen-reader-text">%3$s</span></label>',
				$user_object->ID,
				$role_classes,
				/* translators: Hidden accessibility text. %s: User login. */
				sprintf( __( 'Select %s' ), $user_object->user_login )
			);

		} else {
			$edit = "<strong>{$user_object->user_login}{$super_admin}</strong>";
		}

		$avatar = get_avatar( $user_object->ID, 32 );

		// Comma-separated list of user roles.
		$roles_list = implode( ', ', $user_roles );

		$row = "<tr id='user-$user_object->ID'>";

		list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();

		foreach ( $columns as $column_name => $column_display_name ) {
			$classes = "$column_name column-$column_name";
			if ( $primary === $column_name ) {
				$classes .= ' has-row-actions column-primary';
			}
			if ( 'posts' === $column_name ) {
				$classes .= ' num'; // Special case for that column.
			}

			if ( in_array( $column_name, $hidden, true ) ) {
				$classes .= ' hidden';
			}

			$data = 'data-colname="' . esc_attr( wp_strip_all_tags( $column_display_name ) ) . '"';

			$attributes = "class='$classes' $data";

			if ( 'cb' === $column_name ) {
				$row .= "<th scope='row' class='check-column'>$checkbox</th>";
			} else {
				$row .= "<td $attributes>";
				switch ( $column_name ) {
					case 'username':
						$row .= "$avatar $edit";
						break;
					case 'name':
						if ( $user_object->first_name && $user_object->last_name ) {
							$row .= sprintf(
								/* translators: 1: User's first name, 2: Last name. */
								_x( '%1$s %2$s', 'Display name based on first name and last name' ),
								$user_object->first_name,
								$user_object->last_name
							);
						} elseif ( $user_object->first_name ) {
							$row .= $user_object->first_name;
						} elseif ( $user_object->last_name ) {
							$row .= $user_object->last_name;
						} else {
							$row .= sprintf(
								'<span aria-hidden="true">&#8212;</span><span class="screen-reader-text">%s</span>',
								/* translators: Hidden accessibility text. */
								_x( 'Unknown', 'name' )
							);
						}
						break;
					case 'email':
						$row .= "<a href='" . esc_url( "mailto:$email" ) . "'>$email</a>";
						break;
					case 'role':
						$row .= esc_html( $roles_list );
						break;
					case 'posts':
						if ( $numposts > 0 ) {
							$row .= sprintf(
								'<a href="%s" class="edit"><span aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></a>',
								"edit.php?author={$user_object->ID}",
								$numposts,
								sprintf(
									/* translators: Hidden accessibility text. %s: Number of posts. */
									_n( '%s post by this author', '%s posts by this author', $numposts ),
									number_format_i18n( $numposts )
								)
							);
						} else {
							$row .= 0;
						}
						break;
					default:
						/**
						 * Filters the display output of custom columns in the Users list table.
						 *
						 * @since 2.8.0
						 *
						 * @param string $output      Custom column output. Default empty.
						 * @param string $column_name Column name.
						 * @param int    $user_id     ID of the currently-listed user.
						 */
						$row .= apply_filters( 'manage_users_custom_column', '', $column_name, $user_object->ID );
				}

				if ( $primary === $column_name ) {
					$row .= $this->row_actions( $actions );
				}
				$row .= '</td>';
			}
		}
		$row .= '</tr>';

		return $row;
	}

	/**
	 * Gets the name of the default primary column.
	 *
	 * @since 4.3.0
	 *
	 * @return string Name of the default primary column, in this case, 'username'.
	 */
	protected function get_default_primary_column_name() {
		return 'username';
	}

	/**
	 * Returns an array of translated user role names for a given user object.
	 *
	 * @since 4.4.0
	 *
	 * @param WP_User $user_object The WP_User object.
	 * @return string[] An array of user role names keyed by role.
	 */
	protected function get_role_list( $user_object ) {
		$wp_roles = wp_roles();

		$role_list = array();

		foreach ( $user_object->roles as $role ) {
			if ( isset( $wp_roles->role_names[ $role ] ) ) {
				$role_list[ $role ] = translate_user_role( $wp_roles->role_names[ $role ] );
			}
		}

		if ( empty( $role_list ) ) {
			$role_list['none'] = _x( 'None', 'no user roles' );
		}

		/**
		 * Filters the returned array of translated role names for a user.
		 *
		 * @since 4.4.0
		 *
		 * @param string[] $role_list   An array of translated user role names keyed by role.
		 * @param WP_User  $user_object A WP_User object.
		 */
		return apply_filters( 'get_role_list', $role_list, $user_object );
	}
}
class-wp-site-health.php000064400000363614151212616040011226 0ustar00<?php
/**
 * Class for looking up a site's health based on a user's WordPress environment.
 *
 * @package WordPress
 * @subpackage Site_Health
 * @since 5.2.0
 */

#[AllowDynamicProperties]
class WP_Site_Health {
	private static $instance = null;

	private $is_acceptable_mysql_version;
	private $is_recommended_mysql_version;

	public $is_mariadb                   = false;
	private $mysql_server_version        = '';
	private $mysql_required_version      = '5.5';
	private $mysql_recommended_version   = '8.0';
	private $mariadb_recommended_version = '10.6';

	public $php_memory_limit;

	public $schedules;
	public $crons;
	public $last_missed_cron     = null;
	public $last_late_cron       = null;
	private $timeout_missed_cron = null;
	private $timeout_late_cron   = null;

	/**
	 * WP_Site_Health constructor.
	 *
	 * @since 5.2.0
	 */
	public function __construct() {
		$this->maybe_create_scheduled_event();

		// Save memory limit before it's affected by wp_raise_memory_limit( 'admin' ).
		$this->php_memory_limit = ini_get( 'memory_limit' );

		$this->timeout_late_cron   = 0;
		$this->timeout_missed_cron = - 5 * MINUTE_IN_SECONDS;

		if ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ) {
			$this->timeout_late_cron   = - 15 * MINUTE_IN_SECONDS;
			$this->timeout_missed_cron = - 1 * HOUR_IN_SECONDS;
		}

		add_filter( 'admin_body_class', array( $this, 'admin_body_class' ) );

		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
		add_action( 'wp_site_health_scheduled_check', array( $this, 'wp_cron_scheduled_check' ) );

		add_action( 'site_health_tab_content', array( $this, 'show_site_health_tab' ) );
	}

	/**
	 * Outputs the content of a tab in the Site Health screen.
	 *
	 * @since 5.8.0
	 *
	 * @param string $tab Slug of the current tab being displayed.
	 */
	public function show_site_health_tab( $tab ) {
		if ( 'debug' === $tab ) {
			require_once ABSPATH . 'wp-admin/site-health-info.php';
		}
	}

	/**
	 * Returns an instance of the WP_Site_Health class, or create one if none exist yet.
	 *
	 * @since 5.4.0
	 *
	 * @return WP_Site_Health|null
	 */
	public static function get_instance() {
		if ( null === self::$instance ) {
			self::$instance = new WP_Site_Health();
		}

		return self::$instance;
	}

	/**
	 * Enqueues the site health scripts.
	 *
	 * @since 5.2.0
	 */
	public function enqueue_scripts() {
		$screen = get_current_screen();
		if ( 'site-health' !== $screen->id && 'dashboard' !== $screen->id ) {
			return;
		}

		$health_check_js_variables = array(
			'screen'      => $screen->id,
			'nonce'       => array(
				'site_status'        => wp_create_nonce( 'health-check-site-status' ),
				'site_status_result' => wp_create_nonce( 'health-check-site-status-result' ),
			),
			'site_status' => array(
				'direct' => array(),
				'async'  => array(),
				'issues' => array(
					'good'        => 0,
					'recommended' => 0,
					'critical'    => 0,
				),
			),
		);

		$issue_counts = get_transient( 'health-check-site-status-result' );

		if ( false !== $issue_counts ) {
			$issue_counts = json_decode( $issue_counts );

			$health_check_js_variables['site_status']['issues'] = $issue_counts;
		}

		if ( 'site-health' === $screen->id && ( ! isset( $_GET['tab'] ) || empty( $_GET['tab'] ) ) ) {
			$tests = WP_Site_Health::get_tests();

			// Don't run https test on development environments.
			if ( $this->is_development_environment() ) {
				unset( $tests['async']['https_status'] );
			}

			foreach ( $tests['direct'] as $test ) {
				if ( is_string( $test['test'] ) ) {
					$test_function = sprintf(
						'get_test_%s',
						$test['test']
					);

					if ( method_exists( $this, $test_function ) && is_callable( array( $this, $test_function ) ) ) {
						$health_check_js_variables['site_status']['direct'][] = $this->perform_test( array( $this, $test_function ) );
						continue;
					}
				}

				if ( is_callable( $test['test'] ) ) {
					$health_check_js_variables['site_status']['direct'][] = $this->perform_test( $test['test'] );
				}
			}

			foreach ( $tests['async'] as $test ) {
				if ( is_string( $test['test'] ) ) {
					$health_check_js_variables['site_status']['async'][] = array(
						'test'      => $test['test'],
						'has_rest'  => ( isset( $test['has_rest'] ) ? $test['has_rest'] : false ),
						'completed' => false,
						'headers'   => isset( $test['headers'] ) ? $test['headers'] : array(),
					);
				}
			}
		}

		wp_localize_script( 'site-health', 'SiteHealth', $health_check_js_variables );
	}

	/**
	 * Runs a Site Health test directly.
	 *
	 * @since 5.4.0
	 *
	 * @param callable $callback
	 * @return mixed|void
	 */
	private function perform_test( $callback ) {
		/**
		 * Filters the output of a finished Site Health test.
		 *
		 * @since 5.3.0
		 *
		 * @param array $test_result {
		 *     An associative array of test result data.
		 *
		 *     @type string $label       A label describing the test, and is used as a header in the output.
		 *     @type string $status      The status of the test, which can be a value of `good`, `recommended` or `critical`.
		 *     @type array  $badge {
		 *         Tests are put into categories which have an associated badge shown, these can be modified and assigned here.
		 *
		 *         @type string $label The test label, for example `Performance`.
		 *         @type string $color Default `blue`. A string representing a color to use for the label.
		 *     }
		 *     @type string $description A more descriptive explanation of what the test looks for, and why it is important for the end user.
		 *     @type string $actions     An action to direct the user to where they can resolve the issue, if one exists.
		 *     @type string $test        The name of the test being ran, used as a reference point.
		 * }
		 */
		return apply_filters( 'site_status_test_result', call_user_func( $callback ) );
	}

	/**
	 * Runs the SQL version checks.
	 *
	 * These values are used in later tests, but the part of preparing them is more easily managed
	 * early in the class for ease of access and discovery.
	 *
	 * @since 5.2.0
	 *
	 * @global wpdb $wpdb WordPress database abstraction object.
	 */
	private function prepare_sql_data() {
		global $wpdb;

		$mysql_server_type = $wpdb->db_server_info();

		$this->mysql_server_version = $wpdb->get_var( 'SELECT VERSION()' );

		if ( stristr( $mysql_server_type, 'mariadb' ) ) {
			$this->is_mariadb                = true;
			$this->mysql_recommended_version = $this->mariadb_recommended_version;
		}

		$this->is_acceptable_mysql_version  = version_compare( $this->mysql_required_version, $this->mysql_server_version, '<=' );
		$this->is_recommended_mysql_version = version_compare( $this->mysql_recommended_version, $this->mysql_server_version, '<=' );
	}

	/**
	 * Tests whether `wp_version_check` is blocked.
	 *
	 * It's possible to block updates with the `wp_version_check` filter, but this can't be checked
	 * during an Ajax call, as the filter is never introduced then.
	 *
	 * This filter overrides a standard page request if it's made by an admin through the Ajax call
	 * with the right query argument to check for this.
	 *
	 * @since 5.2.0
	 */
	public function check_wp_version_check_exists() {
		if ( ! is_admin() || ! is_user_logged_in() || ! current_user_can( 'update_core' ) || ! isset( $_GET['health-check-test-wp_version_check'] ) ) {
			return;
		}

		echo ( has_filter( 'wp_version_check', 'wp_version_check' ) ? 'yes' : 'no' );

		die();
	}

	/**
	 * Tests for WordPress version and outputs it.
	 *
	 * Gives various results depending on what kind of updates are available, if any, to encourage
	 * the user to install security updates as a priority.
	 *
	 * @since 5.2.0
	 *
	 * @return array The test result.
	 */
	public function get_test_wordpress_version() {
		$result = array(
			'label'       => '',
			'status'      => '',
			'badge'       => array(
				'label' => __( 'Performance' ),
				'color' => 'blue',
			),
			'description' => '',
			'actions'     => '',
			'test'        => 'wordpress_version',
		);

		$core_current_version = wp_get_wp_version();
		$core_updates         = get_core_updates();

		if ( ! is_array( $core_updates ) ) {
			$result['status'] = 'recommended';

			$result['label'] = sprintf(
				/* translators: %s: Your current version of WordPress. */
				__( 'WordPress version %s' ),
				$core_current_version
			);

			$result['description'] = sprintf(
				'<p>%s</p>',
				__( 'Unable to check if any new versions of WordPress are available.' )
			);

			$result['actions'] = sprintf(
				'<a href="%s">%s</a>',
				esc_url( admin_url( 'update-core.php?force-check=1' ) ),
				__( 'Check for updates manually' )
			);
		} else {
			foreach ( $core_updates as $core => $update ) {
				if ( 'upgrade' === $update->response ) {
					$current_version = explode( '.', $core_current_version );
					$new_version     = explode( '.', $update->version );

					$current_major = $current_version[0] . '.' . $current_version[1];
					$new_major     = $new_version[0] . '.' . $new_version[1];

					$result['label'] = sprintf(
						/* translators: %s: The latest version of WordPress available. */
						__( 'WordPress update available (%s)' ),
						$update->version
					);

					$result['actions'] = sprintf(
						'<a href="%s">%s</a>',
						esc_url( admin_url( 'update-core.php' ) ),
						__( 'Install the latest version of WordPress' )
					);

					if ( $current_major !== $new_major ) {
						// This is a major version mismatch.
						$result['status']      = 'recommended';
						$result['description'] = sprintf(
							'<p>%s</p>',
							__( 'A new version of WordPress is available.' )
						);
					} else {
						// This is a minor version, sometimes considered more critical.
						$result['status']         = 'critical';
						$result['badge']['label'] = __( 'Security' );
						$result['description']    = sprintf(
							'<p>%s</p>',
							__( 'A new minor update is available for your site. Because minor updates often address security, it&#8217;s important to install them.' )
						);
					}
				} else {
					$result['status'] = 'good';
					$result['label']  = sprintf(
						/* translators: %s: The current version of WordPress installed on this site. */
						__( 'Your version of WordPress (%s) is up to date' ),
						$core_current_version
					);

					$result['description'] = sprintf(
						'<p>%s</p>',
						__( 'You are currently running the latest version of WordPress available, keep it up!' )
					);
				}
			}
		}

		return $result;
	}

	/**
	 * Tests if plugins are outdated, or unnecessary.
	 *
	 * The test checks if your plugins are up to date, and encourages you to remove any
	 * that are not in use.
	 *
	 * @since 5.2.0
	 *
	 * @return array The test result.
	 */
	public function get_test_plugin_version() {
		$result = array(
			'label'       => __( 'Your plugins are all up to date' ),
			'status'      => 'good',
			'badge'       => array(
				'label' => __( 'Security' ),
				'color' => 'blue',
			),
			'description' => sprintf(
				'<p>%s</p>',
				__( 'Plugins extend your site&#8217;s functionality with things like contact forms, ecommerce and much more. That means they have deep access to your site, so it&#8217;s vital to keep them up to date.' )
			),
			'actions'     => sprintf(
				'<p><a href="%s">%s</a></p>',
				esc_url( admin_url( 'plugins.php' ) ),
				__( 'Manage your plugins' )
			),
			'test'        => 'plugin_version',
		);

		$plugins        = get_plugins();
		$plugin_updates = get_plugin_updates();

		$plugins_active      = 0;
		$plugins_total       = 0;
		$plugins_need_update = 0;

		// Loop over the available plugins and check their versions and active state.
		foreach ( $plugins as $plugin_path => $plugin ) {
			++$plugins_total;

			if ( is_plugin_active( $plugin_path ) ) {
				++$plugins_active;
			}

			if ( array_key_exists( $plugin_path, $plugin_updates ) ) {
				++$plugins_need_update;
			}
		}

		// Add a notice if there are outdated plugins.
		if ( $plugins_need_update > 0 ) {
			$result['status'] = 'critical';

			$result['label'] = __( 'You have plugins waiting to be updated' );

			$result['description'] .= sprintf(
				'<p>%s</p>',
				sprintf(
					/* translators: %d: The number of outdated plugins. */
					_n(
						'Your site has %d plugin waiting to be updated.',
						'Your site has %d plugins waiting to be updated.',
						$plugins_need_update
					),
					$plugins_need_update
				)
			);

			$result['actions'] .= sprintf(
				'<p><a href="%s">%s</a></p>',
				esc_url( network_admin_url( 'plugins.php?plugin_status=upgrade' ) ),
				__( 'Update your plugins' )
			);
		} else {
			if ( 1 === $plugins_active ) {
				$result['description'] .= sprintf(
					'<p>%s</p>',
					__( 'Your site has 1 active plugin, and it is up to date.' )
				);
			} elseif ( $plugins_active > 0 ) {
				$result['description'] .= sprintf(
					'<p>%s</p>',
					sprintf(
						/* translators: %d: The number of active plugins. */
						_n(
							'Your site has %d active plugin, and it is up to date.',
							'Your site has %d active plugins, and they are all up to date.',
							$plugins_active
						),
						$plugins_active
					)
				);
			} else {
				$result['description'] .= sprintf(
					'<p>%s</p>',
					__( 'Your site does not have any active plugins.' )
				);
			}
		}

		// Check if there are inactive plugins.
		if ( $plugins_total > $plugins_active && ! is_multisite() ) {
			$unused_plugins = $plugins_total - $plugins_active;

			$result['status'] = 'recommended';

			$result['label'] = __( 'You should remove inactive plugins' );

			$result['description'] .= sprintf(
				'<p>%s %s</p>',
				sprintf(
					/* translators: %d: The number of inactive plugins. */
					_n(
						'Your site has %d inactive plugin.',
						'Your site has %d inactive plugins.',
						$unused_plugins
					),
					$unused_plugins
				),
				__( 'Inactive plugins are tempting targets for attackers. If you are not going to use a plugin, you should consider removing it.' )
			);

			$result['actions'] .= sprintf(
				'<p><a href="%s">%s</a></p>',
				esc_url( admin_url( 'plugins.php?plugin_status=inactive' ) ),
				__( 'Manage inactive plugins' )
			);
		}

		return $result;
	}

	/**
	 * Tests if themes are outdated, or unnecessary.
	 *
	 * Checks if your site has a default theme (to fall back on if there is a need),
	 * if your themes are up to date and, finally, encourages you to remove any themes
	 * that are not needed.
	 *
	 * @since 5.2.0
	 *
	 * @return array The test results.
	 */
	public function get_test_theme_version() {
		$result = array(
			'label'       => __( 'Your themes are all up to date' ),
			'status'      => 'good',
			'badge'       => array(
				'label' => __( 'Security' ),
				'color' => 'blue',
			),
			'description' => sprintf(
				'<p>%s</p>',
				__( 'Themes add your site&#8217;s look and feel. It&#8217;s important to keep them up to date, to stay consistent with your brand and keep your site secure.' )
			),
			'actions'     => sprintf(
				'<p><a href="%s">%s</a></p>',
				esc_url( admin_url( 'themes.php' ) ),
				__( 'Manage your themes' )
			),
			'test'        => 'theme_version',
		);

		$theme_updates = get_theme_updates();

		$themes_total        = 0;
		$themes_need_updates = 0;
		$themes_inactive     = 0;

		// This value is changed during processing to determine how many themes are considered a reasonable amount.
		$allowed_theme_count = 1;

		$has_default_theme   = false;
		$has_unused_themes   = false;
		$show_unused_themes  = true;
		$using_default_theme = false;

		// Populate a list of all themes available in the install.
		$all_themes   = wp_get_themes();
		$active_theme = wp_get_theme();

		// If WP_DEFAULT_THEME doesn't exist, fall back to the latest core default theme.
		$default_theme = wp_get_theme( WP_DEFAULT_THEME );
		if ( ! $default_theme->exists() ) {
			$default_theme = WP_Theme::get_core_default_theme();
		}

		if ( $default_theme ) {
			$has_default_theme = true;

			if (
				$active_theme->get_stylesheet() === $default_theme->get_stylesheet()
			||
				is_child_theme() && $active_theme->get_template() === $default_theme->get_template()
			) {
				$using_default_theme = true;
			}
		}

		foreach ( $all_themes as $theme_slug => $theme ) {
			++$themes_total;

			if ( array_key_exists( $theme_slug, $theme_updates ) ) {
				++$themes_need_updates;
			}
		}

		// If this is a child theme, increase the allowed theme count by one, to account for the parent.
		if ( is_child_theme() ) {
			++$allowed_theme_count;
		}

		// If there's a default theme installed and not in use, we count that as allowed as well.
		if ( $has_default_theme && ! $using_default_theme ) {
			++$allowed_theme_count;
		}

		if ( $themes_total > $allowed_theme_count ) {
			$has_unused_themes = true;
			$themes_inactive   = ( $themes_total - $allowed_theme_count );
		}

		// Check if any themes need to be updated.
		if ( $themes_need_updates > 0 ) {
			$result['status'] = 'critical';

			$result['label'] = __( 'You have themes waiting to be updated' );

			$result['description'] .= sprintf(
				'<p>%s</p>',
				sprintf(
					/* translators: %d: The number of outdated themes. */
					_n(
						'Your site has %d theme waiting to be updated.',
						'Your site has %d themes waiting to be updated.',
						$themes_need_updates
					),
					$themes_need_updates
				)
			);
		} else {
			// Give positive feedback about the site being good about keeping things up to date.
			if ( 1 === $themes_total ) {
				$result['description'] .= sprintf(
					'<p>%s</p>',
					__( 'Your site has 1 installed theme, and it is up to date.' )
				);
			} elseif ( $themes_total > 0 ) {
				$result['description'] .= sprintf(
					'<p>%s</p>',
					sprintf(
						/* translators: %d: The number of themes. */
						_n(
							'Your site has %d installed theme, and it is up to date.',
							'Your site has %d installed themes, and they are all up to date.',
							$themes_total
						),
						$themes_total
					)
				);
			} else {
				$result['description'] .= sprintf(
					'<p>%s</p>',
					__( 'Your site does not have any installed themes.' )
				);
			}
		}

		if ( $has_unused_themes && $show_unused_themes && ! is_multisite() ) {

			// This is a child theme, so we want to be a bit more explicit in our messages.
			if ( $active_theme->parent() ) {
				// Recommend removing inactive themes, except a default theme, your current one, and the parent theme.
				$result['status'] = 'recommended';

				$result['label'] = __( 'You should remove inactive themes' );

				if ( $using_default_theme ) {
					$result['description'] .= sprintf(
						'<p>%s %s</p>',
						sprintf(
							/* translators: %d: The number of inactive themes. */
							_n(
								'Your site has %d inactive theme.',
								'Your site has %d inactive themes.',
								$themes_inactive
							),
							$themes_inactive
						),
						sprintf(
							/* translators: 1: The currently active theme. 2: The active theme's parent theme. */
							__( 'To enhance your site&#8217;s security, you should consider removing any themes you are not using. You should keep your active theme, %1$s, and %2$s, its parent theme.' ),
							$active_theme->name,
							$active_theme->parent()->name
						)
					);
				} else {
					$result['description'] .= sprintf(
						'<p>%s %s</p>',
						sprintf(
							/* translators: %d: The number of inactive themes. */
							_n(
								'Your site has %d inactive theme.',
								'Your site has %d inactive themes.',
								$themes_inactive
							),
							$themes_inactive
						),
						sprintf(
							/* translators: 1: The default theme for WordPress. 2: The currently active theme. 3: The active theme's parent theme. */
							__( 'To enhance your site&#8217;s security, you should consider removing any themes you are not using. You should keep %1$s, the default WordPress theme, %2$s, your active theme, and %3$s, its parent theme.' ),
							$default_theme ? $default_theme->name : WP_DEFAULT_THEME,
							$active_theme->name,
							$active_theme->parent()->name
						)
					);
				}
			} else {
				// Recommend removing all inactive themes.
				$result['status'] = 'recommended';

				$result['label'] = __( 'You should remove inactive themes' );

				if ( $using_default_theme ) {
					$result['description'] .= sprintf(
						'<p>%s %s</p>',
						sprintf(
							/* translators: 1: The amount of inactive themes. 2: The currently active theme. */
							_n(
								'Your site has %1$d inactive theme, other than %2$s, your active theme.',
								'Your site has %1$d inactive themes, other than %2$s, your active theme.',
								$themes_inactive
							),
							$themes_inactive,
							$active_theme->name
						),
						__( 'You should consider removing any unused themes to enhance your site&#8217;s security.' )
					);
				} else {
					$result['description'] .= sprintf(
						'<p>%s %s</p>',
						sprintf(
							/* translators: 1: The amount of inactive themes. 2: The default theme for WordPress. 3: The currently active theme. */
							_n(
								'Your site has %1$d inactive theme, other than %2$s, the default WordPress theme, and %3$s, your active theme.',
								'Your site has %1$d inactive themes, other than %2$s, the default WordPress theme, and %3$s, your active theme.',
								$themes_inactive
							),
							$themes_inactive,
							$default_theme ? $default_theme->name : WP_DEFAULT_THEME,
							$active_theme->name
						),
						__( 'You should consider removing any unused themes to enhance your site&#8217;s security.' )
					);
				}
			}
		}

		// If no default Twenty* theme exists.
		if ( ! $has_default_theme ) {
			$result['status'] = 'recommended';

			$result['label'] = __( 'Have a default theme available' );

			$result['description'] .= sprintf(
				'<p>%s</p>',
				__( 'Your site does not have any default theme. Default themes are used by WordPress automatically if anything is wrong with your chosen theme.' )
			);
		}

		return $result;
	}

	/**
	 * Tests if the supplied PHP version is supported.
	 *
	 * @since 5.2.0
	 *
	 * @return array The test results.
	 */
	public function get_test_php_version() {
		$response = wp_check_php_version();

		$result = array(
			'label'       => sprintf(
				/* translators: %s: The server PHP version. */
				__( 'Your site is running PHP %s' ),
				PHP_VERSION
			),
			'status'      => 'good',
			'badge'       => array(
				'label' => __( 'Performance' ),
				'color' => 'blue',
			),
			'description' => sprintf(
				'<p>%s</p>',
				__( 'PHP is one of the programming languages used to build WordPress. Newer versions of PHP receive regular security updates and may increase your site&#8217;s performance.' )
			),
			'actions'     => sprintf(
				'<p><a href="%s" target="_blank">%s<span class="screen-reader-text"> %s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
				esc_url( wp_get_update_php_url() ),
				__( 'Learn more about updating PHP' ),
				/* translators: Hidden accessibility text. */
				__( '(opens in a new tab)' )
			),
			'test'        => 'php_version',
		);

		if ( ! $response ) {
			$result['label'] = sprintf(
				/* translators: %s: The server PHP version. */
				__( 'Unable to determine the status of the current PHP version (%s)' ),
				PHP_VERSION
			);
			$result['status']      = 'recommended';
			$result['description'] = '<p><em>' . sprintf(
				/* translators: %s is the URL to the Serve Happy docs page. */
				__( 'Unable to access the WordPress.org API for <a href="%s">Serve Happy</a>.' ),
				'https://codex.wordpress.org/WordPress.org_API#Serve_Happy'
			) . '</em></p>' . $result['description'];
			return $result;
		}

		$result['description'] .= '<p>' . sprintf(
			/* translators: %s: The minimum recommended PHP version. */
			__( 'The minimum recommended version of PHP is %s.' ),
			$response['recommended_version']
		) . '</p>';

		// PHP is up to date.
		if ( version_compare( PHP_VERSION, $response['recommended_version'], '>=' ) ) {
			$result['label'] = sprintf(
				/* translators: %s: The server PHP version. */
				__( 'Your site is running a recommended version of PHP (%s)' ),
				PHP_VERSION
			);
			$result['status'] = 'good';

			return $result;
		}

		// The PHP version is older than the recommended version, but still receiving active support.
		if ( $response['is_supported'] ) {
			$result['label'] = sprintf(
				/* translators: %s: The server PHP version. */
				__( 'Your site is running on an older version of PHP (%s)' ),
				PHP_VERSION
			);
			$result['status'] = 'recommended';

			return $result;
		}

		/*
		 * The PHP version is still receiving security fixes, but is lower than
		 * the expected minimum version that will be required by WordPress in the near future.
		 */
		if ( $response['is_secure'] && $response['is_lower_than_future_minimum'] ) {
			// The `is_secure` array key name doesn't actually imply this is a secure version of PHP. It only means it receives security updates.

			$result['label'] = sprintf(
				/* translators: %s: The server PHP version. */
				__( 'Your site is running on an outdated version of PHP (%s), which soon will not be supported by WordPress.' ),
				PHP_VERSION
			);

			$result['status']         = 'critical';
			$result['badge']['label'] = __( 'Requirements' );

			return $result;
		}

		// The PHP version is only receiving security fixes.
		if ( $response['is_secure'] ) {
			$result['label'] = sprintf(
				/* translators: %s: The server PHP version. */
				__( 'Your site is running on an older version of PHP (%s), which should be updated' ),
				PHP_VERSION
			);
			$result['status'] = 'recommended';

			return $result;
		}

		// No more security updates for the PHP version, and lower than the expected minimum version required by WordPress.
		if ( $response['is_lower_than_future_minimum'] ) {
			$message = sprintf(
				/* translators: %s: The server PHP version. */
				__( 'Your site is running on an outdated version of PHP (%s), which does not receive security updates and soon will not be supported by WordPress.' ),
				PHP_VERSION
			);
		} else {
			// No more security updates for the PHP version, must be updated.
			$message = sprintf(
				/* translators: %s: The server PHP version. */
				__( 'Your site is running on an outdated version of PHP (%s), which does not receive security updates. It should be updated.' ),
				PHP_VERSION
			);
		}

		$result['label']  = $message;
		$result['status'] = 'critical';

		$result['badge']['label'] = __( 'Security' );

		return $result;
	}

	/**
	 * Checks if the passed extension or function are available.
	 *
	 * Make the check for available PHP modules into a simple boolean operator for a cleaner test runner.
	 *
	 * @since 5.2.0
	 * @since 5.3.0 The `$constant_name` and `$class_name` parameters were added.
	 *
	 * @param string $extension_name Optional. The extension name to test. Default null.
	 * @param string $function_name  Optional. The function name to test. Default null.
	 * @param string $constant_name  Optional. The constant name to test for. Default null.
	 * @param string $class_name     Optional. The class name to test for. Default null.
	 * @return bool Whether or not the extension and function are available.
	 */
	private function test_php_extension_availability( $extension_name = null, $function_name = null, $constant_name = null, $class_name = null ) {
		// If no extension or function is passed, claim to fail testing, as we have nothing to test against.
		if ( ! $extension_name && ! $function_name && ! $constant_name && ! $class_name ) {
			return false;
		}

		if ( $extension_name && ! extension_loaded( $extension_name ) ) {
			return false;
		}

		if ( $function_name && ! function_exists( $function_name ) ) {
			return false;
		}

		if ( $constant_name && ! defined( $constant_name ) ) {
			return false;
		}

		if ( $class_name && ! class_exists( $class_name ) ) {
			return false;
		}

		return true;
	}

	/**
	 * Tests if required PHP modules are installed on the host.
	 *
	 * This test builds on the recommendations made by the WordPress Hosting Team
	 * as seen at https://make.wordpress.org/hosting/handbook/handbook/server-environment/#php-extensions
	 *
	 * @since 5.2.0
	 *
	 * @return array
	 */
	public function get_test_php_extensions() {
		$result = array(
			'label'       => __( 'Required and recommended modules are installed' ),
			'status'      => 'good',
			'badge'       => array(
				'label' => __( 'Performance' ),
				'color' => 'blue',
			),
			'description' => sprintf(
				'<p>%s</p><p>%s</p>',
				__( 'PHP modules perform most of the tasks on the server that make your site run. Any changes to these must be made by your server administrator.' ),
				sprintf(
					/* translators: 1: Link to the hosting group page about recommended PHP modules. 2: Additional link attributes. 3: Accessibility text. */
					__( 'The WordPress Hosting Team maintains a list of those modules, both recommended and required, in <a href="%1$s" %2$s>the team handbook%3$s</a>.' ),
					/* translators: Localized team handbook, if one exists. */
					esc_url( __( 'https://make.wordpress.org/hosting/handbook/handbook/server-environment/#php-extensions' ) ),
					'target="_blank"',
					sprintf(
						'<span class="screen-reader-text"> %s</span><span aria-hidden="true" class="dashicons dashicons-external"></span>',
						/* translators: Hidden accessibility text. */
						__( '(opens in a new tab)' )
					)
				)
			),
			'actions'     => '',
			'test'        => 'php_extensions',
		);

		$modules = array(
			'curl'      => array(
				'function' => 'curl_version',
				'required' => false,
			),
			'dom'       => array(
				'class'    => 'DOMNode',
				'required' => false,
			),
			'exif'      => array(
				'function' => 'exif_read_data',
				'required' => false,
			),
			'fileinfo'  => array(
				'function' => 'finfo_file',
				'required' => false,
			),
			'hash'      => array(
				'function' => 'hash',
				'required' => true,
			),
			'imagick'   => array(
				'extension' => 'imagick',
				'required'  => false,
			),
			'json'      => array(
				'function' => 'json_last_error',
				'required' => true,
			),
			'mbstring'  => array(
				'function' => 'mb_check_encoding',
				'required' => false,
			),
			'mysqli'    => array(
				'function' => 'mysqli_connect',
				'required' => false,
			),
			'libsodium' => array(
				'constant'            => 'SODIUM_LIBRARY_VERSION',
				'required'            => false,
				'php_bundled_version' => '7.2.0',
			),
			'openssl'   => array(
				'function' => 'openssl_encrypt',
				'required' => false,
			),
			'pcre'      => array(
				'function' => 'preg_match',
				'required' => false,
			),
			'mod_xml'   => array(
				'extension' => 'libxml',
				'required'  => false,
			),
			'zip'       => array(
				'class'    => 'ZipArchive',
				'required' => false,
			),
			'filter'    => array(
				'function' => 'filter_list',
				'required' => false,
			),
			'gd'        => array(
				'extension'    => 'gd',
				'required'     => false,
				'fallback_for' => 'imagick',
			),
			'iconv'     => array(
				'function' => 'iconv',
				'required' => false,
			),
			'intl'      => array(
				'extension' => 'intl',
				'required'  => false,
			),
			'mcrypt'    => array(
				'extension'    => 'mcrypt',
				'required'     => false,
				'fallback_for' => 'libsodium',
			),
			'simplexml' => array(
				'extension'    => 'simplexml',
				'required'     => false,
				'fallback_for' => 'mod_xml',
			),
			'xmlreader' => array(
				'extension'    => 'xmlreader',
				'required'     => false,
				'fallback_for' => 'mod_xml',
			),
			'zlib'      => array(
				'extension'    => 'zlib',
				'required'     => false,
				'fallback_for' => 'zip',
			),
		);

		/**
		 * Filters the array representing all the modules we wish to test for.
		 *
		 * @since 5.2.0
		 * @since 5.3.0 The `$constant` and `$class` parameters were added.
		 *
		 * @param array $modules {
		 *     An associative array of modules to test for.
		 *
		 *     @type array ...$0 {
		 *         An associative array of module properties used during testing.
		 *         One of either `$function` or `$extension` must be provided, or they will fail by default.
		 *
		 *         @type string $function     Optional. A function name to test for the existence of.
		 *         @type string $extension    Optional. An extension to check if is loaded in PHP.
		 *         @type string $constant     Optional. A constant name to check for to verify an extension exists.
		 *         @type string $class        Optional. A class name to check for to verify an extension exists.
		 *         @type bool   $required     Is this a required feature or not.
		 *         @type string $fallback_for Optional. The module this module replaces as a fallback.
		 *     }
		 * }
		 */
		$modules = apply_filters( 'site_status_test_php_modules', $modules );

		$failures = array();

		foreach ( $modules as $library => $module ) {
			$extension_name = ( isset( $module['extension'] ) ? $module['extension'] : null );
			$function_name  = ( isset( $module['function'] ) ? $module['function'] : null );
			$constant_name  = ( isset( $module['constant'] ) ? $module['constant'] : null );
			$class_name     = ( isset( $module['class'] ) ? $module['class'] : null );

			// If this module is a fallback for another function, check if that other function passed.
			if ( isset( $module['fallback_for'] ) ) {
				/*
				 * If that other function has a failure, mark this module as required for usual operations.
				 * If that other function hasn't failed, skip this test as it's only a fallback.
				 */
				if ( isset( $failures[ $module['fallback_for'] ] ) ) {
					$module['required'] = true;
				} else {
					continue;
				}
			}

			if ( ! $this->test_php_extension_availability( $extension_name, $function_name, $constant_name, $class_name )
				&& ( ! isset( $module['php_bundled_version'] )
					|| version_compare( PHP_VERSION, $module['php_bundled_version'], '<' ) )
			) {
				if ( $module['required'] ) {
					$result['status'] = 'critical';

					$class = 'error';
					/* translators: Hidden accessibility text. */
					$screen_reader = __( 'Error' );
					$message       = sprintf(
						/* translators: %s: The module name. */
						__( 'The required module, %s, is not installed, or has been disabled.' ),
						$library
					);
				} else {
					$class = 'warning';
					/* translators: Hidden accessibility text. */
					$screen_reader = __( 'Warning' );
					$message       = sprintf(
						/* translators: %s: The module name. */
						__( 'The optional module, %s, is not installed, or has been disabled.' ),
						$library
					);
				}

				if ( ! $module['required'] && 'good' === $result['status'] ) {
					$result['status'] = 'recommended';
				}

				$failures[ $library ] = "<span class='dashicons $class' aria-hidden='true'></span><span class='screen-reader-text'>$screen_reader</span> $message";
			}
		}

		if ( ! empty( $failures ) ) {
			$output = '<ul>';

			foreach ( $failures as $failure ) {
				$output .= sprintf(
					'<li>%s</li>',
					$failure
				);
			}

			$output .= '</ul>';
		}

		if ( 'good' !== $result['status'] ) {
			if ( 'recommended' === $result['status'] ) {
				$result['label'] = __( 'One or more recommended modules are missing' );
			}
			if ( 'critical' === $result['status'] ) {
				$result['label'] = __( 'One or more required modules are missing' );
			}

			$result['description'] .= $output;
		}

		return $result;
	}

	/**
	 * Tests if the PHP default timezone is set to UTC.
	 *
	 * @since 5.3.1
	 *
	 * @return array The test results.
	 */
	public function get_test_php_default_timezone() {
		$result = array(
			'label'       => __( 'PHP default timezone is valid' ),
			'status'      => 'good',
			'badge'       => array(
				'label' => __( 'Performance' ),
				'color' => 'blue',
			),
			'description' => sprintf(
				'<p>%s</p>',
				__( 'PHP default timezone was configured by WordPress on loading. This is necessary for correct calculations of dates and times.' )
			),
			'actions'     => '',
			'test'        => 'php_default_timezone',
		);

		if ( 'UTC' !== date_default_timezone_get() ) {
			$result['status'] = 'critical';

			$result['label'] = __( 'PHP default timezone is invalid' );

			$result['description'] = sprintf(
				'<p>%s</p>',
				sprintf(
					/* translators: %s: date_default_timezone_set() */
					__( 'PHP default timezone was changed after WordPress loading by a %s function call. This interferes with correct calculations of dates and times.' ),
					'<code>date_default_timezone_set()</code>'
				)
			);
		}

		return $result;
	}

	/**
	 * Tests if there's an active PHP session that can affect loopback requests.
	 *
	 * @since 5.5.0
	 *
	 * @return array The test results.
	 */
	public function get_test_php_sessions() {
		$result = array(
			'label'       => __( 'No PHP sessions detected' ),
			'status'      => 'good',
			'badge'       => array(
				'label' => __( 'Performance' ),
				'color' => 'blue',
			),
			'description' => sprintf(
				'<p>%s</p>',
				sprintf(
					/* translators: 1: session_start(), 2: session_write_close() */
					__( 'PHP sessions created by a %1$s function call may interfere with REST API and loopback requests. An active session should be closed by %2$s before making any HTTP requests.' ),
					'<code>session_start()</code>',
					'<code>session_write_close()</code>'
				)
			),
			'test'        => 'php_sessions',
		);

		if ( function_exists( 'session_status' ) && PHP_SESSION_ACTIVE === session_status() ) {
			$result['status'] = 'critical';

			$result['label'] = __( 'An active PHP session was detected' );

			$result['description'] = sprintf(
				'<p>%s</p>',
				sprintf(
					/* translators: 1: session_start(), 2: session_write_close() */
					__( 'A PHP session was created by a %1$s function call. This interferes with REST API and loopback requests. The session should be closed by %2$s before making any HTTP requests.' ),
					'<code>session_start()</code>',
					'<code>session_write_close()</code>'
				)
			);
		}

		return $result;
	}

	/**
	 * Tests if the SQL server is up to date.
	 *
	 * @since 5.2.0
	 *
	 * @return array The test results.
	 */
	public function get_test_sql_server() {
		if ( ! $this->mysql_server_version ) {
			$this->prepare_sql_data();
		}

		$result = array(
			'label'       => __( 'SQL server is up to date' ),
			'status'      => 'good',
			'badge'       => array(
				'label' => __( 'Performance' ),
				'color' => 'blue',
			),
			'description' => sprintf(
				'<p>%s</p>',
				__( 'The SQL server is a required piece of software for the database WordPress uses to store all your site&#8217;s content and settings.' )
			),
			'actions'     => sprintf(
				'<p><a href="%s" target="_blank">%s<span class="screen-reader-text"> %s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
				/* translators: Localized version of WordPress requirements if one exists. */
				esc_url( __( 'https://wordpress.org/about/requirements/' ) ),
				__( 'Learn more about what WordPress requires to run.' ),
				/* translators: Hidden accessibility text. */
				__( '(opens in a new tab)' )
			),
			'test'        => 'sql_server',
		);

		$db_dropin = file_exists( WP_CONTENT_DIR . '/db.php' );

		if ( ! $this->is_recommended_mysql_version ) {
			$result['status'] = 'recommended';

			$result['label'] = __( 'Outdated SQL server' );

			$result['description'] .= sprintf(
				'<p>%s</p>',
				sprintf(
					/* translators: 1: The database engine in use (MySQL or MariaDB). 2: Database server recommended version number. */
					__( 'For optimal performance and security reasons, you should consider running %1$s version %2$s or higher. Contact your web hosting company to correct this.' ),
					( $this->is_mariadb ? 'MariaDB' : 'MySQL' ),
					$this->mysql_recommended_version
				)
			);
		}

		if ( ! $this->is_acceptable_mysql_version ) {
			$result['status'] = 'critical';

			$result['label']          = __( 'Severely outdated SQL server' );
			$result['badge']['label'] = __( 'Security' );

			$result['description'] .= sprintf(
				'<p>%s</p>',
				sprintf(
					/* translators: 1: The database engine in use (MySQL or MariaDB). 2: Database server minimum version number. */
					__( 'WordPress requires %1$s version %2$s or higher. Contact your web hosting company to correct this.' ),
					( $this->is_mariadb ? 'MariaDB' : 'MySQL' ),
					$this->mysql_required_version
				)
			);
		}

		if ( $db_dropin ) {
			$result['description'] .= sprintf(
				'<p>%s</p>',
				wp_kses(
					sprintf(
						/* translators: 1: The name of the drop-in. 2: The name of the database engine. */
						__( 'You are using a %1$s drop-in which might mean that a %2$s database is not being used.' ),
						'<code>wp-content/db.php</code>',
						( $this->is_mariadb ? 'MariaDB' : 'MySQL' )
					),
					array(
						'code' => true,
					)
				)
			);
		}

		return $result;
	}

	/**
	 * Tests if the site can communicate with WordPress.org.
	 *
	 * @since 5.2.0
	 *
	 * @return array The test results.
	 */
	public function get_test_dotorg_communication() {
		$result = array(
			'label'       => __( 'Can communicate with WordPress.org' ),
			'status'      => '',
			'badge'       => array(
				'label' => __( 'Security' ),
				'color' => 'blue',
			),
			'description' => sprintf(
				'<p>%s</p>',
				__( 'Communicating with the WordPress servers is used to check for new versions, and to both install and update WordPress core, themes or plugins.' )
			),
			'actions'     => '',
			'test'        => 'dotorg_communication',
		);

		$wp_dotorg = wp_remote_get(
			'https://api.wordpress.org',
			array(
				'timeout' => 10,
			)
		);
		if ( ! is_wp_error( $wp_dotorg ) ) {
			$result['status'] = 'good';
		} else {
			$result['status'] = 'critical';

			$result['label'] = __( 'Could not reach WordPress.org' );

			$result['description'] .= sprintf(
				'<p>%s</p>',
				sprintf(
					'<span class="error"><span class="screen-reader-text">%s</span></span> %s',
					/* translators: Hidden accessibility text. */
					__( 'Error' ),
					sprintf(
						/* translators: 1: The IP address WordPress.org resolves to. 2: The error returned by the lookup. */
						__( 'Your site is unable to reach WordPress.org at %1$s, and returned the error: %2$s' ),
						gethostbyname( 'api.wordpress.org' ),
						$wp_dotorg->get_error_message()
					)
				)
			);

			$result['actions'] = sprintf(
				'<p><a href="%s" target="_blank">%s<span class="screen-reader-text"> %s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
				/* translators: Localized Support reference. */
				esc_url( __( 'https://wordpress.org/support/forums/' ) ),
				__( 'Get help resolving this issue.' ),
				/* translators: Hidden accessibility text. */
				__( '(opens in a new tab)' )
			);
		}

		return $result;
	}

	/**
	 * Tests if debug information is enabled.
	 *
	 * When WP_DEBUG is enabled, errors and information may be disclosed to site visitors,
	 * or logged to a publicly accessible file.
	 *
	 * Debugging is also frequently left enabled after looking for errors on a site,
	 * as site owners do not understand the implications of this.
	 *
	 * @since 5.2.0
	 *
	 * @return array The test results.
	 */
	public function get_test_is_in_debug_mode() {
		$result = array(
			'label'       => __( 'Your site is not set to output debug information' ),
			'status'      => 'good',
			'badge'       => array(
				'label' => __( 'Security' ),
				'color' => 'blue',
			),
			'description' => sprintf(
				'<p>%s</p>',
				__( 'Debug mode is often enabled to gather more details about an error or site failure, but may contain sensitive information which should not be available on a publicly available website.' )
			),
			'actions'     => sprintf(
				'<p><a href="%s" target="_blank">%s<span class="screen-reader-text"> %s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
				/* translators: Documentation explaining debugging in WordPress. */
				esc_url( __( 'https://developer.wordpress.org/advanced-administration/debug/debug-wordpress/' ) ),
				__( 'Learn more about debugging in WordPress.' ),
				/* translators: Hidden accessibility text. */
				__( '(opens in a new tab)' )
			),
			'test'        => 'is_in_debug_mode',
		);

		if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
			if ( defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ) {
				$result['label'] = __( 'Your site is set to log errors to a potentially public file' );

				$result['status'] = str_starts_with( ini_get( 'error_log' ), ABSPATH ) ? 'critical' : 'recommended';

				$result['description'] .= sprintf(
					'<p>%s</p>',
					sprintf(
						/* translators: %s: WP_DEBUG_LOG */
						__( 'The value, %s, has been added to this website&#8217;s configuration file. This means any errors on the site will be written to a file which is potentially available to all users.' ),
						'<code>WP_DEBUG_LOG</code>'
					)
				);
			}

			if ( defined( 'WP_DEBUG_DISPLAY' ) && WP_DEBUG_DISPLAY ) {
				$result['label'] = __( 'Your site is set to display errors to site visitors' );

				$result['status'] = 'critical';

				// On development environments, set the status to recommended.
				if ( $this->is_development_environment() ) {
					$result['status'] = 'recommended';
				}

				$result['description'] .= sprintf(
					'<p>%s</p>',
					sprintf(
						/* translators: 1: WP_DEBUG_DISPLAY, 2: WP_DEBUG */
						__( 'The value, %1$s, has either been enabled by %2$s or added to your configuration file. This will make errors display on the front end of your site.' ),
						'<code>WP_DEBUG_DISPLAY</code>',
						'<code>WP_DEBUG</code>'
					)
				);
			}
		}

		return $result;
	}

	/**
	 * Tests if the site is serving content over HTTPS.
	 *
	 * Many sites have varying degrees of HTTPS support, the most common of which is sites that have it
	 * enabled, but only if you visit the right site address.
	 *
	 * @since 5.2.0
	 * @since 5.7.0 Updated to rely on {@see wp_is_using_https()} and {@see wp_is_https_supported()}.
	 *
	 * @return array The test results.
	 */
	public function get_test_https_status() {
		/*
		 * Check HTTPS detection results.
		 */
		$errors = wp_get_https_detection_errors();

		$default_update_url = wp_get_default_update_https_url();

		$result = array(
			'label'       => __( 'Your website is using an active HTTPS connection' ),
			'status'      => 'good',
			'badge'       => array(
				'label' => __( 'Security' ),
				'color' => 'blue',
			),
			'description' => sprintf(
				'<p>%s</p>',
				__( 'An HTTPS connection is a more secure way of browsing the web. Many services now have HTTPS as a requirement. HTTPS allows you to take advantage of new features that can increase site speed, improve search rankings, and gain the trust of your visitors by helping to protect their online privacy.' )
			),
			'actions'     => sprintf(
				'<p><a href="%s" target="_blank">%s<span class="screen-reader-text"> %s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
				esc_url( $default_update_url ),
				__( 'Learn more about why you should use HTTPS' ),
				/* translators: Hidden accessibility text. */
				__( '(opens in a new tab)' )
			),
			'test'        => 'https_status',
		);

		if ( ! wp_is_using_https() ) {
			/*
			 * If the website is not using HTTPS, provide more information
			 * about whether it is supported and how it can be enabled.
			 */
			$result['status'] = 'recommended';
			$result['label']  = __( 'Your website does not use HTTPS' );

			if ( wp_is_site_url_using_https() ) {
				if ( is_ssl() ) {
					$result['description'] = sprintf(
						'<p>%s</p>',
						sprintf(
							/* translators: %s: URL to Settings > General > Site Address. */
							__( 'You are accessing this website using HTTPS, but your <a href="%s">Site Address</a> is not set up to use HTTPS by default.' ),
							esc_url( admin_url( 'options-general.php' ) . '#home' )
						)
					);
				} else {
					$result['description'] = sprintf(
						'<p>%s</p>',
						sprintf(
							/* translators: %s: URL to Settings > General > Site Address. */
							__( 'Your <a href="%s">Site Address</a> is not set up to use HTTPS.' ),
							esc_url( admin_url( 'options-general.php' ) . '#home' )
						)
					);
				}
			} else {
				if ( is_ssl() ) {
					$result['description'] = sprintf(
						'<p>%s</p>',
						sprintf(
							/* translators: 1: URL to Settings > General > WordPress Address, 2: URL to Settings > General > Site Address. */
							__( 'You are accessing this website using HTTPS, but your <a href="%1$s">WordPress Address</a> and <a href="%2$s">Site Address</a> are not set up to use HTTPS by default.' ),
							esc_url( admin_url( 'options-general.php' ) . '#siteurl' ),
							esc_url( admin_url( 'options-general.php' ) . '#home' )
						)
					);
				} else {
					$result['description'] = sprintf(
						'<p>%s</p>',
						sprintf(
							/* translators: 1: URL to Settings > General > WordPress Address, 2: URL to Settings > General > Site Address. */
							__( 'Your <a href="%1$s">WordPress Address</a> and <a href="%2$s">Site Address</a> are not set up to use HTTPS.' ),
							esc_url( admin_url( 'options-general.php' ) . '#siteurl' ),
							esc_url( admin_url( 'options-general.php' ) . '#home' )
						)
					);
				}
			}

			if ( wp_is_https_supported() ) {
				$result['description'] .= sprintf(
					'<p>%s</p>',
					__( 'HTTPS is already supported for your website.' )
				);

				if ( defined( 'WP_HOME' ) || defined( 'WP_SITEURL' ) ) {
					$result['description'] .= sprintf(
						'<p>%s</p>',
						sprintf(
							/* translators: 1: wp-config.php, 2: WP_HOME, 3: WP_SITEURL */
							__( 'However, your WordPress Address is currently controlled by a PHP constant and therefore cannot be updated. You need to edit your %1$s and remove or update the definitions of %2$s and %3$s.' ),
							'<code>wp-config.php</code>',
							'<code>WP_HOME</code>',
							'<code>WP_SITEURL</code>'
						)
					);
				} elseif ( current_user_can( 'update_https' ) ) {
					$default_direct_update_url = add_query_arg( 'action', 'update_https', wp_nonce_url( admin_url( 'site-health.php' ), 'wp_update_https' ) );
					$direct_update_url         = wp_get_direct_update_https_url();

					if ( ! empty( $direct_update_url ) ) {
						$result['actions'] = sprintf(
							'<p class="button-container"><a class="button button-primary" href="%1$s" target="_blank">%2$s<span class="screen-reader-text"> %3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
							esc_url( $direct_update_url ),
							__( 'Update your site to use HTTPS' ),
							/* translators: Hidden accessibility text. */
							__( '(opens in a new tab)' )
						);
					} else {
						$result['actions'] = sprintf(
							'<p class="button-container"><a class="button button-primary" href="%1$s">%2$s</a></p>',
							esc_url( $default_direct_update_url ),
							__( 'Update your site to use HTTPS' )
						);
					}
				}
			} else {
				// If host-specific "Update HTTPS" URL is provided, include a link.
				$update_url = wp_get_update_https_url();
				if ( $update_url !== $default_update_url ) {
					$result['description'] .= sprintf(
						'<p><a href="%s" target="_blank">%s<span class="screen-reader-text"> %s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
						esc_url( $update_url ),
						__( 'Talk to your web host about supporting HTTPS for your website.' ),
						/* translators: Hidden accessibility text. */
						__( '(opens in a new tab)' )
					);
				} else {
					$result['description'] .= sprintf(
						'<p>%s</p>',
						__( 'Talk to your web host about supporting HTTPS for your website.' )
					);
				}
			}
		}

		return $result;
	}

	/**
	 * Checks if the HTTP API can handle SSL/TLS requests.
	 *
	 * @since 5.2.0
	 *
	 * @return array The test result.
	 */
	public function get_test_ssl_support() {
		$result = array(
			'label'       => '',
			'status'      => '',
			'badge'       => array(
				'label' => __( 'Security' ),
				'color' => 'blue',
			),
			'description' => sprintf(
				'<p>%s</p>',
				__( 'Securely communicating between servers are needed for transactions such as fetching files, conducting sales on store sites, and much more.' )
			),
			'actions'     => '',
			'test'        => 'ssl_support',
		);

		$supports_https = wp_http_supports( array( 'ssl' ) );

		if ( $supports_https ) {
			$result['status'] = 'good';

			$result['label'] = __( 'Your site can communicate securely with other services' );
		} else {
			$result['status'] = 'critical';

			$result['label'] = __( 'Your site is unable to communicate securely with other services' );

			$result['description'] .= sprintf(
				'<p>%s</p>',
				__( 'Talk to your web host about OpenSSL support for PHP.' )
			);
		}

		return $result;
	}

	/**
	 * Tests if scheduled events run as intended.
	 *
	 * If scheduled events are not running, this may indicate something with WP_Cron is not working
	 * as intended, or that there are orphaned events hanging around from older code.
	 *
	 * @since 5.2.0
	 *
	 * @return array The test results.
	 */
	public function get_test_scheduled_events() {
		$result = array(
			'label'       => __( 'Scheduled events are running' ),
			'status'      => 'good',
			'badge'       => array(
				'label' => __( 'Performance' ),
				'color' => 'blue',
			),
			'description' => sprintf(
				'<p>%s</p>',
				__( 'Scheduled events are what periodically looks for updates to plugins, themes and WordPress itself. It is also what makes sure scheduled posts are published on time. It may also be used by various plugins to make sure that planned actions are executed.' )
			),
			'actions'     => '',
			'test'        => 'scheduled_events',
		);

		$this->wp_schedule_test_init();

		if ( is_wp_error( $this->has_missed_cron() ) ) {
			$result['status'] = 'critical';

			$result['label'] = __( 'It was not possible to check your scheduled events' );

			$result['description'] = sprintf(
				'<p>%s</p>',
				sprintf(
					/* translators: %s: The error message returned while from the cron scheduler. */
					__( 'While trying to test your site&#8217;s scheduled events, the following error was returned: %s' ),
					$this->has_missed_cron()->get_error_message()
				)
			);
		} elseif ( $this->has_missed_cron() ) {
			$result['status'] = 'recommended';

			$result['label'] = __( 'A scheduled event has failed' );

			$result['description'] = sprintf(
				'<p>%s</p>',
				sprintf(
					/* translators: %s: The name of the failed cron event. */
					__( 'The scheduled event, %s, failed to run. Your site still works, but this may indicate that scheduling posts or automated updates may not work as intended.' ),
					$this->last_missed_cron
				)
			);
		} elseif ( $this->has_late_cron() ) {
			$result['status'] = 'recommended';

			$result['label'] = __( 'A scheduled event is late' );

			$result['description'] = sprintf(
				'<p>%s</p>',
				sprintf(
					/* translators: %s: The name of the late cron event. */
					__( 'The scheduled event, %s, is late to run. Your site still works, but this may indicate that scheduling posts or automated updates may not work as intended.' ),
					$this->last_late_cron
				)
			);
		}

		return $result;
	}

	/**
	 * Tests if WordPress can run automated background updates.
	 *
	 * Background updates in WordPress are primarily used for minor releases and security updates.
	 * It's important to either have these working, or be aware that they are intentionally disabled
	 * for whatever reason.
	 *
	 * @since 5.2.0
	 *
	 * @return array The test results.
	 */
	public function get_test_background_updates() {
		$result = array(
			'label'       => __( 'Background updates are working' ),
			'status'      => 'good',
			'badge'       => array(
				'label' => __( 'Security' ),
				'color' => 'blue',
			),
			'description' => sprintf(
				'<p>%s</p>',
				__( 'Background updates ensure that WordPress can auto-update if a security update is released for the version you are currently using.' )
			),
			'actions'     => '',
			'test'        => 'background_updates',
		);

		if ( ! class_exists( 'WP_Site_Health_Auto_Updates' ) ) {
			require_once ABSPATH . 'wp-admin/includes/class-wp-site-health-auto-updates.php';
		}

		/*
		 * Run the auto-update tests in a separate class,
		 * as there are many considerations to be made.
		 */
		$automatic_updates = new WP_Site_Health_Auto_Updates();
		$tests             = $automatic_updates->run_tests();

		$output = '<ul>';

		foreach ( $tests as $test ) {
			/* translators: Hidden accessibility text. */
			$severity_string = __( 'Passed' );

			if ( 'fail' === $test->severity ) {
				$result['label'] = __( 'Background updates are not working as expected' );

				$result['status'] = 'critical';

				/* translators: Hidden accessibility text. */
				$severity_string = __( 'Error' );
			}

			if ( 'warning' === $test->severity && 'good' === $result['status'] ) {
				$result['label'] = __( 'Background updates may not be working properly' );

				$result['status'] = 'recommended';

				/* translators: Hidden accessibility text. */
				$severity_string = __( 'Warning' );
			}

			$output .= sprintf(
				'<li><span class="dashicons %s"><span class="screen-reader-text">%s</span></span> %s</li>',
				esc_attr( $test->severity ),
				$severity_string,
				$test->description
			);
		}

		$output .= '</ul>';

		if ( 'good' !== $result['status'] ) {
			$result['description'] .= $output;
		}

		return $result;
	}

	/**
	 * Tests if plugin and theme auto-updates appear to be configured correctly.
	 *
	 * @since 5.5.0
	 *
	 * @return array The test results.
	 */
	public function get_test_plugin_theme_auto_updates() {
		$result = array(
			'label'       => __( 'Plugin and theme auto-updates appear to be configured correctly' ),
			'status'      => 'good',
			'badge'       => array(
				'label' => __( 'Security' ),
				'color' => 'blue',
			),
			'description' => sprintf(
				'<p>%s</p>',
				__( 'Plugin and theme auto-updates ensure that the latest versions are always installed.' )
			),
			'actions'     => '',
			'test'        => 'plugin_theme_auto_updates',
		);

		$check_plugin_theme_updates = $this->detect_plugin_theme_auto_update_issues();

		$result['status'] = $check_plugin_theme_updates->status;

		if ( 'good' !== $result['status'] ) {
			$result['label'] = __( 'Your site may have problems auto-updating plugins and themes' );

			$result['description'] .= sprintf(
				'<p>%s</p>',
				$check_plugin_theme_updates->message
			);
		}

		return $result;
	}

	/**
	 * Tests available disk space for updates.
	 *
	 * @since 6.3.0
	 *
	 * @return array The test results.
	 */
	public function get_test_available_updates_disk_space() {
		$available_space = function_exists( 'disk_free_space' ) ? @disk_free_space( WP_CONTENT_DIR ) : false;

		$result = array(
			'label'       => __( 'Disk space available to safely perform updates' ),
			'status'      => 'good',
			'badge'       => array(
				'label' => __( 'Security' ),
				'color' => 'blue',
			),
			'description' => sprintf(
				/* translators: %s: Available disk space in MB or GB. */
				'<p>' . __( '%s available disk space was detected, update routines can be performed safely.' ) . '</p>',
				size_format( $available_space )
			),
			'actions'     => '',
			'test'        => 'available_updates_disk_space',
		);

		if ( false === $available_space ) {
			$result['description'] = __( 'Could not determine available disk space for updates.' );
			$result['status']      = 'recommended';
		} elseif ( $available_space < 20 * MB_IN_BYTES ) {
			$result['description'] = sprintf(
				/* translators: %s: Available disk space in MB or GB. */
				__( 'Available disk space is critically low, less than %s available. Proceed with caution, updates may fail.' ),
				size_format( 20 * MB_IN_BYTES )
			);
			$result['status'] = 'critical';
		} elseif ( $available_space < 100 * MB_IN_BYTES ) {
			$result['description'] = sprintf(
				/* translators: %s: Available disk space in MB or GB. */
				__( 'Available disk space is low, less than %s available.' ),
				size_format( 100 * MB_IN_BYTES )
			);
			$result['status'] = 'recommended';
		}

		return $result;
	}

	/**
	 * Tests if plugin and theme temporary backup directories are writable or can be created.
	 *
	 * @since 6.3.0
	 *
	 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
	 *
	 * @return array The test results.
	 */
	public function get_test_update_temp_backup_writable() {
		global $wp_filesystem;

		$result = array(
			'label'       => __( 'Plugin and theme temporary backup directory is writable' ),
			'status'      => 'good',
			'badge'       => array(
				'label' => __( 'Security' ),
				'color' => 'blue',
			),
			'description' => sprintf(
				/* translators: %s: wp-content/upgrade-temp-backup */
				'<p>' . __( 'The %s directory used to improve the stability of plugin and theme updates is writable.' ) . '</p>',
				'<code>wp-content/upgrade-temp-backup</code>'
			),
			'actions'     => '',
			'test'        => 'update_temp_backup_writable',
		);

		if ( ! function_exists( 'WP_Filesystem' ) ) {
			require_once ABSPATH . 'wp-admin/includes/file.php';
		}

		ob_start();
		$credentials = request_filesystem_credentials( '' );
		ob_end_clean();

		if ( false === $credentials || ! WP_Filesystem( $credentials ) ) {
			$result['status']      = 'recommended';
			$result['label']       = __( 'Could not access filesystem' );
			$result['description'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );
			return $result;
		}

		$wp_content = $wp_filesystem->wp_content_dir();

		if ( ! $wp_content ) {
			$result['status']      = 'critical';
			$result['label']       = __( 'Unable to locate WordPress content directory' );
			$result['description'] = sprintf(
				/* translators: %s: wp-content */
				'<p>' . __( 'The %s directory cannot be located.' ) . '</p>',
				'<code>wp-content</code>'
			);
			return $result;
		}

		$upgrade_dir_exists      = $wp_filesystem->is_dir( "$wp_content/upgrade" );
		$upgrade_dir_is_writable = $wp_filesystem->is_writable( "$wp_content/upgrade" );
		$backup_dir_exists       = $wp_filesystem->is_dir( "$wp_content/upgrade-temp-backup" );
		$backup_dir_is_writable  = $wp_filesystem->is_writable( "$wp_content/upgrade-temp-backup" );

		$plugins_dir_exists      = $wp_filesystem->is_dir( "$wp_content/upgrade-temp-backup/plugins" );
		$plugins_dir_is_writable = $wp_filesystem->is_writable( "$wp_content/upgrade-temp-backup/plugins" );
		$themes_dir_exists       = $wp_filesystem->is_dir( "$wp_content/upgrade-temp-backup/themes" );
		$themes_dir_is_writable  = $wp_filesystem->is_writable( "$wp_content/upgrade-temp-backup/themes" );

		if ( $plugins_dir_exists && ! $plugins_dir_is_writable && $themes_dir_exists && ! $themes_dir_is_writable ) {
			$result['status']      = 'critical';
			$result['label']       = __( 'Plugin and theme temporary backup directories exist but are not writable' );
			$result['description'] = sprintf(
				/* translators: 1: wp-content/upgrade-temp-backup/plugins, 2: wp-content/upgrade-temp-backup/themes. */
				'<p>' . __( 'The %1$s and %2$s directories exist but are not writable. These directories are used to improve the stability of plugin updates. Please make sure the server has write permissions to these directories.' ) . '</p>',
				'<code>wp-content/upgrade-temp-backup/plugins</code>',
				'<code>wp-content/upgrade-temp-backup/themes</code>'
			);
			return $result;
		}

		if ( $plugins_dir_exists && ! $plugins_dir_is_writable ) {
			$result['status']      = 'critical';
			$result['label']       = __( 'Plugin temporary backup directory exists but is not writable' );
			$result['description'] = sprintf(
				/* translators: %s: wp-content/upgrade-temp-backup/plugins */
				'<p>' . __( 'The %s directory exists but is not writable. This directory is used to improve the stability of plugin updates. Please make sure the server has write permissions to this directory.' ) . '</p>',
				'<code>wp-content/upgrade-temp-backup/plugins</code>'
			);
			return $result;
		}

		if ( $themes_dir_exists && ! $themes_dir_is_writable ) {
			$result['status']      = 'critical';
			$result['label']       = __( 'Theme temporary backup directory exists but is not writable' );
			$result['description'] = sprintf(
				/* translators: %s: wp-content/upgrade-temp-backup/themes */
				'<p>' . __( 'The %s directory exists but is not writable. This directory is used to improve the stability of theme updates. Please make sure the server has write permissions to this directory.' ) . '</p>',
				'<code>wp-content/upgrade-temp-backup/themes</code>'
			);
			return $result;
		}

		if ( ( ! $plugins_dir_exists || ! $themes_dir_exists ) && $backup_dir_exists && ! $backup_dir_is_writable ) {
			$result['status']      = 'critical';
			$result['label']       = __( 'The temporary backup directory exists but is not writable' );
			$result['description'] = sprintf(
				/* translators: %s: wp-content/upgrade-temp-backup */
				'<p>' . __( 'The %s directory exists but is not writable. This directory is used to improve the stability of plugin and theme updates. Please make sure the server has write permissions to this directory.' ) . '</p>',
				'<code>wp-content/upgrade-temp-backup</code>'
			);
			return $result;
		}

		if ( ! $backup_dir_exists && $upgrade_dir_exists && ! $upgrade_dir_is_writable ) {
			$result['status']      = 'critical';
			$result['label']       = __( 'The upgrade directory exists but is not writable' );
			$result['description'] = sprintf(
				/* translators: %s: wp-content/upgrade */
				'<p>' . __( 'The %s directory exists but is not writable. This directory is used for plugin and theme updates. Please make sure the server has write permissions to this directory.' ) . '</p>',
				'<code>wp-content/upgrade</code>'
			);
			return $result;
		}

		if ( ! $upgrade_dir_exists && ! $wp_filesystem->is_writable( $wp_content ) ) {
			$result['status']      = 'critical';
			$result['label']       = __( 'The upgrade directory cannot be created' );
			$result['description'] = sprintf(
				/* translators: 1: wp-content/upgrade, 2: wp-content. */
				'<p>' . __( 'The %1$s directory does not exist, and the server does not have write permissions in %2$s to create it. This directory is used for plugin and theme updates. Please make sure the server has write permissions in %2$s.' ) . '</p>',
				'<code>wp-content/upgrade</code>',
				'<code>wp-content</code>'
			);
			return $result;
		}

		return $result;
	}

	/**
	 * Tests if loopbacks work as expected.
	 *
	 * A loopback is when WordPress queries itself, for example to start a new WP_Cron instance,
	 * or when editing a plugin or theme. This has shown itself to be a recurring issue,
	 * as code can very easily break this interaction.
	 *
	 * @since 5.2.0
	 *
	 * @return array The test results.
	 */
	public function get_test_loopback_requests() {
		$result = array(
			'label'       => __( 'Your site can perform loopback requests' ),
			'status'      => 'good',
			'badge'       => array(
				'label' => __( 'Performance' ),
				'color' => 'blue',
			),
			'description' => sprintf(
				'<p>%s</p>',
				__( 'Loopback requests are used to run scheduled events, and are also used by the built-in editors for themes and plugins to verify code stability.' )
			),
			'actions'     => '',
			'test'        => 'loopback_requests',
		);

		$check_loopback = $this->can_perform_loopback();

		$result['status'] = $check_loopback->status;

		if ( 'good' !== $result['status'] ) {
			$result['label'] = __( 'Your site could not complete a loopback request' );

			$result['description'] .= sprintf(
				'<p>%s</p>',
				$check_loopback->message
			);
		}

		return $result;
	}

	/**
	 * Tests if HTTP requests are blocked.
	 *
	 * It's possible to block all outgoing communication (with the possibility of allowing certain
	 * hosts) via the HTTP API. This may create problems for users as many features are running as
	 * services these days.
	 *
	 * @since 5.2.0
	 *
	 * @return array The test results.
	 */
	public function get_test_http_requests() {
		$result = array(
			'label'       => __( 'HTTP requests seem to be working as expected' ),
			'status'      => 'good',
			'badge'       => array(
				'label' => __( 'Performance' ),
				'color' => 'blue',
			),
			'description' => sprintf(
				'<p>%s</p>',
				__( 'It is possible for site maintainers to block all, or some, communication to other sites and services. If set up incorrectly, this may prevent plugins and themes from working as intended.' )
			),
			'actions'     => '',
			'test'        => 'http_requests',
		);

		$blocked = false;
		$hosts   = array();

		if ( defined( 'WP_HTTP_BLOCK_EXTERNAL' ) && WP_HTTP_BLOCK_EXTERNAL ) {
			$blocked = true;
		}

		if ( defined( 'WP_ACCESSIBLE_HOSTS' ) ) {
			$hosts = explode( ',', WP_ACCESSIBLE_HOSTS );
		}

		if ( $blocked && 0 === count( $hosts ) ) {
			$result['status'] = 'critical';

			$result['label'] = __( 'HTTP requests are blocked' );

			$result['description'] .= sprintf(
				'<p>%s</p>',
				sprintf(
					/* translators: %s: Name of the constant used. */
					__( 'HTTP requests have been blocked by the %s constant, with no allowed hosts.' ),
					'<code>WP_HTTP_BLOCK_EXTERNAL</code>'
				)
			);
		}

		if ( $blocked && 0 < count( $hosts ) ) {
			$result['status'] = 'recommended';

			$result['label'] = __( 'HTTP requests are partially blocked' );

			$result['description'] .= sprintf(
				'<p>%s</p>',
				sprintf(
					/* translators: 1: Name of the constant used. 2: List of allowed hostnames. */
					__( 'HTTP requests have been blocked by the %1$s constant, with some allowed hosts: %2$s.' ),
					'<code>WP_HTTP_BLOCK_EXTERNAL</code>',
					implode( ',', $hosts )
				)
			);
		}

		return $result;
	}

	/**
	 * Tests if the REST API is accessible.
	 *
	 * Various security measures may block the REST API from working, or it may have been disabled in general.
	 * This is required for the new block editor to work, so we explicitly test for this.
	 *
	 * @since 5.2.0
	 *
	 * @return array The test results.
	 */
	public function get_test_rest_availability() {
		$result = array(
			'label'       => __( 'The REST API is available' ),
			'status'      => 'good',
			'badge'       => array(
				'label' => __( 'Performance' ),
				'color' => 'blue',
			),
			'description' => sprintf(
				'<p>%s</p>',
				__( 'The REST API is one way that WordPress and other applications communicate with the server. For example, the block editor screen relies on the REST API to display and save your posts and pages.' )
			),
			'actions'     => '',
			'test'        => 'rest_availability',
		);

		$cookies = wp_unslash( $_COOKIE );
		$timeout = 10; // 10 seconds.
		$headers = array(
			'Cache-Control' => 'no-cache',
			'X-WP-Nonce'    => wp_create_nonce( 'wp_rest' ),
		);
		/** This filter is documented in wp-includes/class-wp-http-streams.php */
		$sslverify = apply_filters( 'https_local_ssl_verify', false );

		// Include Basic auth in loopback requests.
		if ( isset( $_SERVER['PHP_AUTH_USER'] ) && isset( $_SERVER['PHP_AUTH_PW'] ) ) {
			$headers['Authorization'] = 'Basic ' . base64_encode( wp_unslash( $_SERVER['PHP_AUTH_USER'] ) . ':' . wp_unslash( $_SERVER['PHP_AUTH_PW'] ) );
		}

		$url = rest_url( 'wp/v2/types/post' );

		// The context for this is editing with the new block editor.
		$url = add_query_arg(
			array(
				'context' => 'edit',
			),
			$url
		);

		$r = wp_remote_get( $url, compact( 'cookies', 'headers', 'timeout', 'sslverify' ) );

		if ( is_wp_error( $r ) ) {
			$result['status'] = 'critical';

			$result['label'] = __( 'The REST API encountered an error' );

			$result['description'] .= sprintf(
				'<p>%s</p><p>%s<br>%s</p>',
				__( 'When testing the REST API, an error was encountered:' ),
				sprintf(
					// translators: %s: The REST API URL.
					__( 'REST API Endpoint: %s' ),
					$url
				),
				sprintf(
					// translators: 1: The WordPress error code. 2: The WordPress error message.
					__( 'REST API Response: (%1$s) %2$s' ),
					$r->get_error_code(),
					$r->get_error_message()
				)
			);
		} elseif ( 200 !== wp_remote_retrieve_response_code( $r ) ) {
			$result['status'] = 'recommended';

			$result['label'] = __( 'The REST API encountered an unexpected result' );

			$result['description'] .= sprintf(
				'<p>%s</p><p>%s<br>%s</p>',
				__( 'When testing the REST API, an unexpected result was returned:' ),
				sprintf(
					// translators: %s: The REST API URL.
					__( 'REST API Endpoint: %s' ),
					$url
				),
				sprintf(
					// translators: 1: The WordPress error code. 2: The HTTP status code error message.
					__( 'REST API Response: (%1$s) %2$s' ),
					wp_remote_retrieve_response_code( $r ),
					wp_remote_retrieve_response_message( $r )
				)
			);
		} else {
			$json = json_decode( wp_remote_retrieve_body( $r ), true );

			if ( false !== $json && ! isset( $json['capabilities'] ) ) {
				$result['status'] = 'recommended';

				$result['label'] = __( 'The REST API did not behave correctly' );

				$result['description'] .= sprintf(
					'<p>%s</p>',
					sprintf(
						/* translators: %s: The name of the query parameter being tested. */
						__( 'The REST API did not process the %s query parameter correctly.' ),
						'<code>context</code>'
					)
				);
			}
		}

		return $result;
	}

	/**
	 * Tests if 'file_uploads' directive in PHP.ini is turned off.
	 *
	 * @since 5.5.0
	 *
	 * @return array The test results.
	 */
	public function get_test_file_uploads() {
		$result = array(
			'label'       => __( 'Files can be uploaded' ),
			'status'      => 'good',
			'badge'       => array(
				'label' => __( 'Performance' ),
				'color' => 'blue',
			),
			'description' => sprintf(
				'<p>%s</p>',
				sprintf(
					/* translators: 1: file_uploads, 2: php.ini */
					__( 'The %1$s directive in %2$s determines if uploading files is allowed on your site.' ),
					'<code>file_uploads</code>',
					'<code>php.ini</code>'
				)
			),
			'actions'     => '',
			'test'        => 'file_uploads',
		);

		if ( ! function_exists( 'ini_get' ) ) {
			$result['status']       = 'critical';
			$result['description'] .= sprintf(
				/* translators: %s: ini_get() */
				__( 'The %s function has been disabled, some media settings are unavailable because of this.' ),
				'<code>ini_get()</code>'
			);
			return $result;
		}

		if ( empty( ini_get( 'file_uploads' ) ) ) {
			$result['status']       = 'critical';
			$result['description'] .= sprintf(
				'<p>%s</p>',
				sprintf(
					/* translators: 1: file_uploads, 2: 0 */
					__( '%1$s is set to %2$s. You won\'t be able to upload files on your site.' ),
					'<code>file_uploads</code>',
					'<code>0</code>'
				)
			);
			return $result;
		}

		$post_max_size       = ini_get( 'post_max_size' );
		$upload_max_filesize = ini_get( 'upload_max_filesize' );

		if ( wp_convert_hr_to_bytes( $post_max_size ) < wp_convert_hr_to_bytes( $upload_max_filesize ) ) {
			$result['label'] = sprintf(
				/* translators: 1: post_max_size, 2: upload_max_filesize */
				__( 'The "%1$s" value is smaller than "%2$s"' ),
				'post_max_size',
				'upload_max_filesize'
			);
			$result['status'] = 'recommended';

			if ( 0 === wp_convert_hr_to_bytes( $post_max_size ) ) {
				$result['description'] = sprintf(
					'<p>%s</p>',
					sprintf(
						/* translators: 1: post_max_size, 2: upload_max_filesize */
						__( 'The setting for %1$s is currently configured as 0, this could cause some problems when trying to upload files through plugin or theme features that rely on various upload methods. It is recommended to configure this setting to a fixed value, ideally matching the value of %2$s, as some upload methods read the value 0 as either unlimited, or disabled.' ),
						'<code>post_max_size</code>',
						'<code>upload_max_filesize</code>'
					)
				);
			} else {
				$result['description'] = sprintf(
					'<p>%s</p>',
					sprintf(
						/* translators: 1: post_max_size, 2: upload_max_filesize */
						__( 'The setting for %1$s is smaller than %2$s, this could cause some problems when trying to upload files.' ),
						'<code>post_max_size</code>',
						'<code>upload_max_filesize</code>'
					)
				);
			}

			return $result;
		}

		return $result;
	}

	/**
	 * Tests if the Authorization header has the expected values.
	 *
	 * @since 5.6.0
	 *
	 * @return array
	 */
	public function get_test_authorization_header() {
		$result = array(
			'label'       => __( 'The Authorization header is working as expected' ),
			'status'      => 'good',
			'badge'       => array(
				'label' => __( 'Security' ),
				'color' => 'blue',
			),
			'description' => sprintf(
				'<p>%s</p>',
				__( 'The Authorization header is used by third-party applications you have approved for this site. Without this header, those apps cannot connect to your site.' )
			),
			'actions'     => '',
			'test'        => 'authorization_header',
		);

		if ( ! isset( $_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'] ) ) {
			$result['label'] = __( 'The authorization header is missing' );
		} elseif ( 'user' !== $_SERVER['PHP_AUTH_USER'] || 'pwd' !== $_SERVER['PHP_AUTH_PW'] ) {
			$result['label'] = __( 'The authorization header is invalid' );
		} else {
			return $result;
		}

		$result['status']       = 'recommended';
		$result['description'] .= sprintf(
			'<p>%s</p>',
			__( 'If you are still seeing this warning after having tried the actions below, you may need to contact your hosting provider for further assistance.' )
		);

		if ( ! function_exists( 'got_mod_rewrite' ) ) {
			require_once ABSPATH . 'wp-admin/includes/misc.php';
		}

		if ( got_mod_rewrite() ) {
			$result['actions'] .= sprintf(
				'<p><a href="%s">%s</a></p>',
				esc_url( admin_url( 'options-permalink.php' ) ),
				__( 'Flush permalinks' )
			);
		} else {
			$result['actions'] .= sprintf(
				'<p><a href="%s" target="_blank">%s<span class="screen-reader-text"> %s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
				__( 'https://developer.wordpress.org/rest-api/frequently-asked-questions/#why-is-authentication-not-working' ),
				__( 'Learn how to configure the Authorization header.' ),
				/* translators: Hidden accessibility text. */
				__( '(opens in a new tab)' )
			);
		}

		return $result;
	}

	/**
	 * Tests if a full page cache is available.
	 *
	 * @since 6.1.0
	 *
	 * @return array The test result.
	 */
	public function get_test_page_cache() {
		$description  = '<p>' . __( 'Page cache enhances the speed and performance of your site by saving and serving static pages instead of calling for a page every time a user visits.' ) . '</p>';
		$description .= '<p>' . __( 'Page cache is detected by looking for an active page cache plugin as well as making three requests to the homepage and looking for one or more of the following HTTP client caching response headers:' ) . '</p>';
		$description .= '<code>' . implode( '</code>, <code>', array_keys( $this->get_page_cache_headers() ) ) . '.</code>';

		$result = array(
			'badge'       => array(
				'label' => __( 'Performance' ),
				'color' => 'blue',
			),
			'description' => wp_kses_post( $description ),
			'test'        => 'page_cache',
			'status'      => 'good',
			'label'       => '',
			'actions'     => sprintf(
				'<p><a href="%1$s" target="_blank" rel="noreferrer">%2$s<span class="screen-reader-text"> %3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
				__( 'https://developer.wordpress.org/advanced-administration/performance/optimization/#caching' ),
				__( 'Learn more about page cache' ),
				/* translators: Hidden accessibility text. */
				__( '(opens in a new tab)' )
			),
		);

		$page_cache_detail = $this->get_page_cache_detail();

		if ( is_wp_error( $page_cache_detail ) ) {
			$result['label']  = __( 'Unable to detect the presence of page cache' );
			$result['status'] = 'recommended';
			$error_info       = sprintf(
			/* translators: 1: Error message, 2: Error code. */
				__( 'Unable to detect page cache due to possible loopback request problem. Please verify that the loopback request test is passing. Error: %1$s (Code: %2$s)' ),
				$page_cache_detail->get_error_message(),
				$page_cache_detail->get_error_code()
			);
			$result['description'] = wp_kses_post( "<p>$error_info</p>" ) . $result['description'];
			return $result;
		}

		$result['status'] = $page_cache_detail['status'];

		switch ( $page_cache_detail['status'] ) {
			case 'recommended':
				$result['label'] = __( 'Page cache is not detected but the server response time is OK' );
				break;
			case 'good':
				$result['label'] = __( 'Page cache is detected and the server response time is good' );
				break;
			default:
				if ( empty( $page_cache_detail['headers'] ) && ! $page_cache_detail['advanced_cache_present'] ) {
					$result['label'] = __( 'Page cache is not detected and the server response time is slow' );
				} else {
					$result['label'] = __( 'Page cache is detected but the server response time is still slow' );
				}
		}

		$page_cache_test_summary = array();

		if ( empty( $page_cache_detail['response_time'] ) ) {
			$page_cache_test_summary[] = '<span class="dashicons dashicons-dismiss" aria-hidden="true"></span> ' . __( 'Server response time could not be determined. Verify that loopback requests are working.' );
		} else {

			$threshold = $this->get_good_response_time_threshold();
			if ( $page_cache_detail['response_time'] < $threshold ) {
				$page_cache_test_summary[] = '<span class="dashicons dashicons-yes-alt" aria-hidden="true"></span> ' . sprintf(
					/* translators: 1: The response time in milliseconds, 2: The recommended threshold in milliseconds. */
					__( 'Median server response time was %1$s milliseconds. This is less than the recommended %2$s milliseconds threshold.' ),
					number_format_i18n( $page_cache_detail['response_time'] ),
					number_format_i18n( $threshold )
				);
			} else {
				$page_cache_test_summary[] = '<span class="dashicons dashicons-warning" aria-hidden="true"></span> ' . sprintf(
					/* translators: 1: The response time in milliseconds, 2: The recommended threshold in milliseconds. */
					__( 'Median server response time was %1$s milliseconds. It should be less than the recommended %2$s milliseconds threshold.' ),
					number_format_i18n( $page_cache_detail['response_time'] ),
					number_format_i18n( $threshold )
				);
			}

			if ( empty( $page_cache_detail['headers'] ) ) {
				$page_cache_test_summary[] = '<span class="dashicons dashicons-warning" aria-hidden="true"></span> ' . __( 'No client caching response headers were detected.' );
			} else {
				$headers_summary  = '<span class="dashicons dashicons-yes-alt" aria-hidden="true"></span>';
				$headers_summary .= ' ' . sprintf(
					/* translators: %d: Number of caching headers. */
					_n(
						'There was %d client caching response header detected:',
						'There were %d client caching response headers detected:',
						count( $page_cache_detail['headers'] )
					),
					count( $page_cache_detail['headers'] )
				);
				$headers_summary          .= ' <code>' . implode( '</code>, <code>', $page_cache_detail['headers'] ) . '</code>.';
				$page_cache_test_summary[] = $headers_summary;
			}
		}

		if ( $page_cache_detail['advanced_cache_present'] ) {
			$page_cache_test_summary[] = '<span class="dashicons dashicons-yes-alt" aria-hidden="true"></span> ' . __( 'A page cache plugin was detected.' );
		} elseif ( ! ( is_array( $page_cache_detail ) && ! empty( $page_cache_detail['headers'] ) ) ) {
			// Note: This message is not shown if client caching response headers were present since an external caching layer may be employed.
			$page_cache_test_summary[] = '<span class="dashicons dashicons-warning" aria-hidden="true"></span> ' . __( 'A page cache plugin was not detected.' );
		}

		$result['description'] .= '<ul><li>' . implode( '</li><li>', $page_cache_test_summary ) . '</li></ul>';
		return $result;
	}

	/**
	 * Tests if the site uses persistent object cache and recommends to use it if not.
	 *
	 * @since 6.1.0
	 *
	 * @return array The test result.
	 */
	public function get_test_persistent_object_cache() {
		/**
		 * Filters the action URL for the persistent object cache health check.
		 *
		 * @since 6.1.0
		 *
		 * @param string $action_url Learn more link for persistent object cache health check.
		 */
		$action_url = apply_filters(
			'site_status_persistent_object_cache_url',
			/* translators: Localized Support reference. */
			__( 'https://developer.wordpress.org/advanced-administration/performance/optimization/#persistent-object-cache' )
		);

		$result = array(
			'test'        => 'persistent_object_cache',
			'status'      => 'good',
			'badge'       => array(
				'label' => __( 'Performance' ),
				'color' => 'blue',
			),
			'label'       => __( 'A persistent object cache is being used' ),
			'description' => sprintf(
				'<p>%s</p>',
				__( 'A persistent object cache makes your site&#8217;s database more efficient, resulting in faster load times because WordPress can retrieve your site&#8217;s content and settings much more quickly.' )
			),
			'actions'     => sprintf(
				'<p><a href="%s" target="_blank">%s<span class="screen-reader-text"> %s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a></p>',
				esc_url( $action_url ),
				__( 'Learn more about persistent object caching.' ),
				/* translators: Hidden accessibility text. */
				__( '(opens in a new tab)' )
			),
		);

		if ( wp_using_ext_object_cache() ) {
			return $result;
		}

		if ( ! $this->should_suggest_persistent_object_cache() ) {
			$result['label'] = __( 'A persistent object cache is not required' );

			return $result;
		}

		$available_services = $this->available_object_cache_services();

		$notes = __( 'Your hosting provider can tell you if a persistent object cache can be enabled on your site.' );

		if ( ! empty( $available_services ) ) {
			$notes .= ' ' . sprintf(
				/* translators: Available object caching services. */
				__( 'Your host appears to support the following object caching services: %s.' ),
				implode( ', ', $available_services )
			);
		}

		/**
		 * Filters the second paragraph of the health check's description
		 * when suggesting the use of a persistent object cache.
		 *
		 * Hosts may want to replace the notes to recommend their preferred object caching solution.
		 *
		 * Plugin authors may want to append notes (not replace) on why object caching is recommended for their plugin.
		 *
		 * @since 6.1.0
		 *
		 * @param string   $notes              The notes appended to the health check description.
		 * @param string[] $available_services The list of available persistent object cache services.
		 */
		$notes = apply_filters( 'site_status_persistent_object_cache_notes', $notes, $available_services );

		$result['status']       = 'recommended';
		$result['label']        = __( 'You should use a persistent object cache' );
		$result['description'] .= sprintf(
			'<p>%s</p>',
			wp_kses(
				$notes,
				array(
					'a'      => array( 'href' => true ),
					'code'   => true,
					'em'     => true,
					'strong' => true,
				)
			)
		);

		return $result;
	}

	/**
	 * Calculates total amount of autoloaded data.
	 *
	 * @since 6.6.0
	 *
	 * @return int Autoloaded data in bytes.
	 */
	public function get_autoloaded_options_size() {
		$alloptions = wp_load_alloptions();

		$total_length = 0;

		foreach ( $alloptions as $option_value ) {
			if ( is_array( $option_value ) || is_object( $option_value ) ) {
				$option_value = maybe_serialize( $option_value );
			}
			$total_length += strlen( (string) $option_value );
		}

		return $total_length;
	}

	/**
	 * Tests the number of autoloaded options.
	 *
	 * @since 6.6.0
	 *
	 * @return array The test results.
	 */
	public function get_test_autoloaded_options() {
		$autoloaded_options_size  = $this->get_autoloaded_options_size();
		$autoloaded_options_count = count( wp_load_alloptions() );

		$base_description = __( 'Autoloaded options are configuration settings for plugins and themes that are automatically loaded with every page load in WordPress. Having too many autoloaded options can slow down your site.' );

		$result = array(
			'label'       => __( 'Autoloaded options are acceptable' ),
			'status'      => 'good',
			'badge'       => array(
				'label' => __( 'Performance' ),
				'color' => 'blue',
			),
			'description' => sprintf(
				/* translators: 1: Number of autoloaded options, 2: Autoloaded options size. */
				'<p>' . esc_html( $base_description ) . ' ' . __( 'Your site has %1$s autoloaded options (size: %2$s) in the options table, which is acceptable.' ) . '</p>',
				$autoloaded_options_count,
				size_format( $autoloaded_options_size )
			),
			'actions'     => '',
			'test'        => 'autoloaded_options',
		);

		/**
		 * Filters max bytes threshold to trigger warning in Site Health.
		 *
		 * @since 6.6.0
		 *
		 * @param int $limit Autoloaded options threshold size. Default 800000.
		 */
		$limit = apply_filters( 'site_status_autoloaded_options_size_limit', 800000 );

		if ( $autoloaded_options_size < $limit ) {
			return $result;
		}

		$result['status']      = 'critical';
		$result['label']       = __( 'Autoloaded options could affect performance' );
		$result['description'] = sprintf(
			/* translators: 1: Number of autoloaded options, 2: Autoloaded options size. */
			'<p>' . esc_html( $base_description ) . ' ' . __( 'Your site has %1$s autoloaded options (size: %2$s) in the options table, which could cause your site to be slow. You can review the options being autoloaded in your database and remove any options that are no longer needed by your site.' ) . '</p>',
			$autoloaded_options_count,
			size_format( $autoloaded_options_size )
		);

		/**
		 * Filters description to be shown on Site Health warning when threshold is met.
		 *
		 * @since 6.6.0
		 *
		 * @param string $description Description message when autoloaded options bigger than threshold.
		 */
		$result['description'] = apply_filters( 'site_status_autoloaded_options_limit_description', $result['description'] );

		$result['actions'] = sprintf(
			/* translators: 1: HelpHub URL, 2: Link description. */
			'<p><a target="_blank" href="%1$s">%2$s</a></p>',
			esc_url( __( 'https://developer.wordpress.org/advanced-administration/performance/optimization/#autoloaded-options' ) ),
			__( 'More info about optimizing autoloaded options' )
		);

		/**
		 * Filters actionable information to tackle the problem. It can be a link to an external guide.
		 *
		 * @since 6.6.0
		 *
		 * @param string $actions Call to Action to be used to point to the right direction to solve the issue.
		 */
		$result['actions'] = apply_filters( 'site_status_autoloaded_options_action_to_perform', $result['actions'] );
		return $result;
	}

	/**
	 * Tests whether search engine indexing is enabled.
	 *
	 * Surfaces as “good” if `blog_public === 1`, or “recommended” if `blog_public === 0`.
	 *
	 * @since 6.9.0
	 *
	 * @return array The test results.
	 */
	public function get_test_search_engine_visibility() {
		$result = array(
			'label'       => __( 'Search engine indexing is enabled.', 'default' ),
			'status'      => 'good',
			'badge'       => array(
				'label' => __( 'Privacy', 'default' ),
				'color' => 'blue',
			),
			'description' => sprintf(
				'<p>%s</p>',
				__( 'Search engines can crawl and index your site. No action needed.', 'default' )
			),
			'actions'     => sprintf(
				'<p><a href="%1$s">%2$s</a></p>',
				esc_url( admin_url( 'options-reading.php#blog_public' ) ),
				__( 'Review your visibility settings', 'default' )
			),
			'test'        => 'search_engine_visibility',
		);

		// If indexing is discouraged, flip to “recommended”:
		if ( ! get_option( 'blog_public' ) ) {
			$result['status']         = 'recommended';
			$result['label']          = __( 'Search engines are discouraged from indexing this site.', 'default' );
			$result['badge']['color'] = 'blue';
			$result['description']    = sprintf(
				'<p>%s</p>',
				__( 'Your site is hidden from search engines. Consider enabling indexing if this is a public site.', 'default' )
			);
		}

		return $result;
	}

	/**
	 * Returns a set of tests that belong to the site status page.
	 *
	 * Each site status test is defined here, they may be `direct` tests, that run on page load, or `async` tests
	 * which will run later down the line via JavaScript calls to improve page performance and hopefully also user
	 * experiences.
	 *
	 * @since 5.2.0
	 * @since 5.6.0 Added support for `has_rest` and `permissions`.
	 *
	 * @return array The list of tests to run.
	 */
	public static function get_tests() {
		$tests = array(
			'direct' => array(
				'wordpress_version'            => array(
					'label' => __( 'WordPress Version' ),
					'test'  => 'wordpress_version',
				),
				'plugin_version'               => array(
					'label' => __( 'Plugin Versions' ),
					'test'  => 'plugin_version',
				),
				'theme_version'                => array(
					'label' => __( 'Theme Versions' ),
					'test'  => 'theme_version',
				),
				'php_version'                  => array(
					'label' => __( 'PHP Version' ),
					'test'  => 'php_version',
				),
				'php_extensions'               => array(
					'label' => __( 'PHP Extensions' ),
					'test'  => 'php_extensions',
				),
				'php_default_timezone'         => array(
					'label' => __( 'PHP Default Timezone' ),
					'test'  => 'php_default_timezone',
				),
				'php_sessions'                 => array(
					'label' => __( 'PHP Sessions' ),
					'test'  => 'php_sessions',
				),
				'sql_server'                   => array(
					'label' => __( 'Database Server version' ),
					'test'  => 'sql_server',
				),
				'ssl_support'                  => array(
					'label' => __( 'Secure communication' ),
					'test'  => 'ssl_support',
				),
				'scheduled_events'             => array(
					'label' => __( 'Scheduled events' ),
					'test'  => 'scheduled_events',
				),
				'http_requests'                => array(
					'label' => __( 'HTTP Requests' ),
					'test'  => 'http_requests',
				),
				'rest_availability'            => array(
					'label'     => __( 'REST API availability' ),
					'test'      => 'rest_availability',
					'skip_cron' => true,
				),
				'debug_enabled'                => array(
					'label' => __( 'Debugging enabled' ),
					'test'  => 'is_in_debug_mode',
				),
				'file_uploads'                 => array(
					'label' => __( 'File uploads' ),
					'test'  => 'file_uploads',
				),
				'plugin_theme_auto_updates'    => array(
					'label' => __( 'Plugin and theme auto-updates' ),
					'test'  => 'plugin_theme_auto_updates',
				),
				'update_temp_backup_writable'  => array(
					'label' => __( 'Plugin and theme temporary backup directory access' ),
					'test'  => 'update_temp_backup_writable',
				),
				'available_updates_disk_space' => array(
					'label' => __( 'Available disk space' ),
					'test'  => 'available_updates_disk_space',
				),
				'autoloaded_options'           => array(
					'label' => __( 'Autoloaded options' ),
					'test'  => 'autoloaded_options',
				),
				'search_engine_visibility'     => array(
					'label' => __( 'Search Engine Visibility' ),
					'test'  => 'search_engine_visibility',
				),
			),
			'async'  => array(
				'dotorg_communication' => array(
					'label'             => __( 'Communication with WordPress.org' ),
					'test'              => rest_url( 'wp-site-health/v1/tests/dotorg-communication' ),
					'has_rest'          => true,
					'async_direct_test' => array( WP_Site_Health::get_instance(), 'get_test_dotorg_communication' ),
				),
				'background_updates'   => array(
					'label'             => __( 'Background updates' ),
					'test'              => rest_url( 'wp-site-health/v1/tests/background-updates' ),
					'has_rest'          => true,
					'async_direct_test' => array( WP_Site_Health::get_instance(), 'get_test_background_updates' ),
				),
				'loopback_requests'    => array(
					'label'             => __( 'Loopback request' ),
					'test'              => rest_url( 'wp-site-health/v1/tests/loopback-requests' ),
					'has_rest'          => true,
					'async_direct_test' => array( WP_Site_Health::get_instance(), 'get_test_loopback_requests' ),
				),
				'https_status'         => array(
					'label'             => __( 'HTTPS status' ),
					'test'              => rest_url( 'wp-site-health/v1/tests/https-status' ),
					'has_rest'          => true,
					'async_direct_test' => array( WP_Site_Health::get_instance(), 'get_test_https_status' ),
				),
			),
		);

		// Conditionally include Authorization header test if the site isn't protected by Basic Auth.
		if ( ! wp_is_site_protected_by_basic_auth() ) {
			$tests['async']['authorization_header'] = array(
				'label'     => __( 'Authorization header' ),
				'test'      => rest_url( 'wp-site-health/v1/tests/authorization-header' ),
				'has_rest'  => true,
				'headers'   => array( 'Authorization' => 'Basic ' . base64_encode( 'user:pwd' ) ),
				'skip_cron' => true,
			);
		}

		// Only check for caches in production environments.
		if ( 'production' === wp_get_environment_type() ) {
			$tests['async']['page_cache'] = array(
				'label'             => __( 'Page cache' ),
				'test'              => rest_url( 'wp-site-health/v1/tests/page-cache' ),
				'has_rest'          => true,
				'async_direct_test' => array( WP_Site_Health::get_instance(), 'get_test_page_cache' ),
			);

			$tests['direct']['persistent_object_cache'] = array(
				'label' => __( 'Persistent object cache' ),
				'test'  => 'persistent_object_cache',
			);
		}

		/**
		 * Filters which site status tests are run on a site.
		 *
		 * The site health is determined by a set of tests based on best practices from
		 * both the WordPress Hosting Team and web standards in general.
		 *
		 * Some sites may not have the same requirements, for example the automatic update
		 * checks may be handled by a host, and are therefore disabled in core.
		 * Or maybe you want to introduce a new test, is caching enabled/disabled/stale for example.
		 *
		 * Tests may be added either as direct, or asynchronous ones. Any test that may require some time
		 * to complete should run asynchronously, to avoid extended loading periods within wp-admin.
		 *
		 * @since 5.2.0
		 * @since 5.6.0 Added the `async_direct_test` array key for asynchronous tests.
		 *              Added the `skip_cron` array key for all tests.
		 *
		 * @param array[] $tests {
		 *     An associative array of direct and asynchronous tests.
		 *
		 *     @type array[] $direct {
		 *         An array of direct tests.
		 *
		 *         @type array ...$identifier {
		 *             `$identifier` should be a unique identifier for the test. Plugins and themes are encouraged to
		 *             prefix test identifiers with their slug to avoid collisions between tests.
		 *
		 *             @type string   $label     The friendly label to identify the test.
		 *             @type callable $test      The callback function that runs the test and returns its result.
		 *             @type bool     $skip_cron Whether to skip this test when running as cron.
		 *         }
		 *     }
		 *     @type array[] $async {
		 *         An array of asynchronous tests.
		 *
		 *         @type array ...$identifier {
		 *             `$identifier` should be a unique identifier for the test. Plugins and themes are encouraged to
		 *             prefix test identifiers with their slug to avoid collisions between tests.
		 *
		 *             @type string   $label             The friendly label to identify the test.
		 *             @type string   $test              An admin-ajax.php action to be called to perform the test, or
		 *                                               if `$has_rest` is true, a URL to a REST API endpoint to perform
		 *                                               the test.
		 *             @type bool     $has_rest          Whether the `$test` property points to a REST API endpoint.
		 *             @type bool     $skip_cron         Whether to skip this test when running as cron.
		 *             @type callable $async_direct_test A manner of directly calling the test marked as asynchronous,
		 *                                               as the scheduled event can not authenticate, and endpoints
		 *                                               may require authentication.
		 *         }
		 *     }
		 * }
		 */
		$tests = apply_filters( 'site_status_tests', $tests );

		// Ensure that the filtered tests contain the required array keys.
		$tests = array_merge(
			array(
				'direct' => array(),
				'async'  => array(),
			),
			$tests
		);

		return $tests;
	}

	/**
	 * Adds a class to the body HTML tag.
	 *
	 * Filters the body class string for admin pages and adds our own class for easier styling.
	 *
	 * @since 5.2.0
	 *
	 * @param string $body_class The body class string.
	 * @return string The modified body class string.
	 */
	public function admin_body_class( $body_class ) {
		$screen = get_current_screen();
		if ( 'site-health' !== $screen->id ) {
			return $body_class;
		}

		$body_class .= ' site-health';

		return $body_class;
	}

	/**
	 * Initiates the WP_Cron schedule test cases.
	 *
	 * @since 5.2.0
	 */
	private function wp_schedule_test_init() {
		$this->schedules = wp_get_schedules();
		$this->get_cron_tasks();
	}

	/**
	 * Populates the list of cron events and store them to a class-wide variable.
	 *
	 * @since 5.2.0
	 */
	private function get_cron_tasks() {
		$cron_tasks = _get_cron_array();

		if ( empty( $cron_tasks ) ) {
			$this->crons = new WP_Error( 'no_tasks', __( 'No scheduled events exist on this site.' ) );
			return;
		}

		$this->crons = array();

		foreach ( $cron_tasks as $time => $cron ) {
			foreach ( $cron as $hook => $dings ) {
				foreach ( $dings as $sig => $data ) {

					$this->crons[ "$hook-$sig-$time" ] = (object) array(
						'hook'     => $hook,
						'time'     => $time,
						'sig'      => $sig,
						'args'     => $data['args'],
						'schedule' => $data['schedule'],
						'interval' => isset( $data['interval'] ) ? $data['interval'] : null,
					);

				}
			}
		}
	}

	/**
	 * Checks if any scheduled tasks have been missed.
	 *
	 * Returns a boolean value of `true` if a scheduled task has been missed and ends processing.
	 *
	 * If the list of crons is an instance of WP_Error, returns the instance instead of a boolean value.
	 *
	 * @since 5.2.0
	 *
	 * @return bool|WP_Error True if a cron was missed, false if not. WP_Error if the cron is set to that.
	 */
	public function has_missed_cron() {
		if ( is_wp_error( $this->crons ) ) {
			return $this->crons;
		}

		foreach ( $this->crons as $id => $cron ) {
			if ( ( $cron->time - time() ) < $this->timeout_missed_cron ) {
				$this->last_missed_cron = $cron->hook;
				return true;
			}
		}

		return false;
	}

	/**
	 * Checks if any scheduled tasks are late.
	 *
	 * Returns a boolean value of `true` if a scheduled task is late and ends processing.
	 *
	 * If the list of crons is an instance of WP_Error, returns the instance instead of a boolean value.
	 *
	 * @since 5.3.0
	 *
	 * @return bool|WP_Error True if a cron is late, false if not. WP_Error if the cron is set to that.
	 */
	public function has_late_cron() {
		if ( is_wp_error( $this->crons ) ) {
			return $this->crons;
		}

		foreach ( $this->crons as $id => $cron ) {
			$cron_offset = $cron->time - time();
			if (
				$cron_offset >= $this->timeout_missed_cron &&
				$cron_offset < $this->timeout_late_cron
			) {
				$this->last_late_cron = $cron->hook;
				return true;
			}
		}

		return false;
	}

	/**
	 * Checks for potential issues with plugin and theme auto-updates.
	 *
	 * Though there is no way to 100% determine if plugin and theme auto-updates are configured
	 * correctly, a few educated guesses could be made to flag any conditions that would
	 * potentially cause unexpected behaviors.
	 *
	 * @since 5.5.0
	 *
	 * @return object The test results.
	 */
	public function detect_plugin_theme_auto_update_issues() {
		$mock_plugin = (object) array(
			'id'            => 'w.org/plugins/a-fake-plugin',
			'slug'          => 'a-fake-plugin',
			'plugin'        => 'a-fake-plugin/a-fake-plugin.php',
			'new_version'   => '9.9',
			'url'           => 'https://wordpress.org/plugins/a-fake-plugin/',
			'package'       => 'https://downloads.wordpress.org/plugin/a-fake-plugin.9.9.zip',
			'icons'         => array(
				'2x' => 'https://ps.w.org/a-fake-plugin/assets/icon-256x256.png',
				'1x' => 'https://ps.w.org/a-fake-plugin/assets/icon-128x128.png',
			),
			'banners'       => array(
				'2x' => 'https://ps.w.org/a-fake-plugin/assets/banner-1544x500.png',
				'1x' => 'https://ps.w.org/a-fake-plugin/assets/banner-772x250.png',
			),
			'banners_rtl'   => array(),
			'tested'        => '5.5.0',
			'requires_php'  => '5.6.20',
			'compatibility' => new stdClass(),
		);

		$mock_theme = (object) array(
			'theme'        => 'a-fake-theme',
			'new_version'  => '9.9',
			'url'          => 'https://wordpress.org/themes/a-fake-theme/',
			'package'      => 'https://downloads.wordpress.org/theme/a-fake-theme.9.9.zip',
			'requires'     => '5.0.0',
			'requires_php' => '5.6.20',
		);

		$test_plugins_enabled = wp_is_auto_update_forced_for_item( 'plugin', true, $mock_plugin );
		$test_themes_enabled  = wp_is_auto_update_forced_for_item( 'theme', true, $mock_theme );

		$ui_enabled_for_plugins = wp_is_auto_update_enabled_for_type( 'plugin' );
		$ui_enabled_for_themes  = wp_is_auto_update_enabled_for_type( 'theme' );
		$plugin_filter_present  = has_filter( 'auto_update_plugin' );
		$theme_filter_present   = has_filter( 'auto_update_theme' );

		if ( ( ! $test_plugins_enabled && $ui_enabled_for_plugins )
			|| ( ! $test_themes_enabled && $ui_enabled_for_themes )
		) {
			return (object) array(
				'status'  => 'critical',
				'message' => __( 'Auto-updates for plugins and/or themes appear to be disabled, but settings are still set to be displayed. This could cause auto-updates to not work as expected.' ),
			);
		}

		if ( ( ! $test_plugins_enabled && $plugin_filter_present )
			&& ( ! $test_themes_enabled && $theme_filter_present )
		) {
			return (object) array(
				'status'  => 'recommended',
				'message' => __( 'Auto-updates for plugins and themes appear to be disabled. This will prevent your site from receiving new versions automatically when available.' ),
			);
		} elseif ( ! $test_plugins_enabled && $plugin_filter_present ) {
			return (object) array(
				'status'  => 'recommended',
				'message' => __( 'Auto-updates for plugins appear to be disabled. This will prevent your site from receiving new versions automatically when available.' ),
			);
		} elseif ( ! $test_themes_enabled && $theme_filter_present ) {
			return (object) array(
				'status'  => 'recommended',
				'message' => __( 'Auto-updates for themes appear to be disabled. This will prevent your site from receiving new versions automatically when available.' ),
			);
		}

		return (object) array(
			'status'  => 'good',
			'message' => __( 'There appear to be no issues with plugin and theme auto-updates.' ),
		);
	}

	/**
	 * Runs a loopback test on the site.
	 *
	 * Loopbacks are what WordPress uses to communicate with itself to start up WP_Cron, scheduled posts,
	 * make sure plugin or theme edits don't cause site failures and similar.
	 *
	 * @since 5.2.0
	 *
	 * @return object The test results.
	 */
	public function can_perform_loopback() {
		$body    = array( 'site-health' => 'loopback-test' );
		$cookies = wp_unslash( $_COOKIE );
		$timeout = 10; // 10 seconds.
		$headers = array(
			'Cache-Control' => 'no-cache',
		);
		/** This filter is documented in wp-includes/class-wp-http-streams.php */
		$sslverify = apply_filters( 'https_local_ssl_verify', false );

		// Include Basic auth in loopback requests.
		if ( isset( $_SERVER['PHP_AUTH_USER'] ) && isset( $_SERVER['PHP_AUTH_PW'] ) ) {
			$headers['Authorization'] = 'Basic ' . base64_encode( wp_unslash( $_SERVER['PHP_AUTH_USER'] ) . ':' . wp_unslash( $_SERVER['PHP_AUTH_PW'] ) );
		}

		$url = site_url( 'wp-cron.php' );

		/*
		 * A post request is used for the wp-cron.php loopback test to cause the file
		 * to finish early without triggering cron jobs. This has two benefits:
		 * - cron jobs are not triggered a second time on the site health page,
		 * - the loopback request finishes sooner providing a quicker result.
		 *
		 * Using a POST request causes the loopback to differ slightly to the standard
		 * GET request WordPress uses for wp-cron.php loopback requests but is close
		 * enough. See https://core.trac.wordpress.org/ticket/52547
		 */
		$r = wp_remote_post( $url, compact( 'body', 'cookies', 'headers', 'timeout', 'sslverify' ) );

		if ( is_wp_error( $r ) ) {
			return (object) array(
				'status'  => 'critical',
				'message' => sprintf(
					'%s<br>%s',
					__( 'The loopback request to your site failed, this means features relying on them are not currently working as expected.' ),
					sprintf(
						/* translators: 1: The WordPress error message. 2: The WordPress error code. */
						__( 'Error: %1$s (%2$s)' ),
						$r->get_error_message(),
						$r->get_error_code()
					)
				),
			);
		}

		if ( 200 !== wp_remote_retrieve_response_code( $r ) ) {
			return (object) array(
				'status'  => 'recommended',
				'message' => sprintf(
					/* translators: %d: The HTTP response code returned. */
					__( 'The loopback request returned an unexpected http status code, %d, it was not possible to determine if this will prevent features from working as expected.' ),
					wp_remote_retrieve_response_code( $r )
				),
			);
		}

		return (object) array(
			'status'  => 'good',
			'message' => __( 'The loopback request to your site completed successfully.' ),
		);
	}

	/**
	 * Creates a weekly cron event, if one does not already exist.
	 *
	 * @since 5.4.0
	 */
	public function maybe_create_scheduled_event() {
		if ( ! wp_next_scheduled( 'wp_site_health_scheduled_check' ) && ! wp_installing() ) {
			wp_schedule_event( time() + DAY_IN_SECONDS, 'weekly', 'wp_site_health_scheduled_check' );
		}
	}

	/**
	 * Runs the scheduled event to check and update the latest site health status for the website.
	 *
	 * @since 5.4.0
	 */
	public function wp_cron_scheduled_check() {
		// Bootstrap wp-admin, as WP_Cron doesn't do this for us.
		require_once trailingslashit( ABSPATH ) . 'wp-admin/includes/admin.php';

		$tests = WP_Site_Health::get_tests();

		$results = array();

		$site_status = array(
			'good'        => 0,
			'recommended' => 0,
			'critical'    => 0,
		);

		// Don't run https test on development environments.
		if ( $this->is_development_environment() ) {
			unset( $tests['async']['https_status'] );
		}

		foreach ( $tests['direct'] as $test ) {
			if ( ! empty( $test['skip_cron'] ) ) {
				continue;
			}

			if ( is_string( $test['test'] ) ) {
				$test_function = sprintf(
					'get_test_%s',
					$test['test']
				);

				if ( method_exists( $this, $test_function ) && is_callable( array( $this, $test_function ) ) ) {
					$results[] = $this->perform_test( array( $this, $test_function ) );
					continue;
				}
			}

			if ( is_callable( $test['test'] ) ) {
				$results[] = $this->perform_test( $test['test'] );
			}
		}

		foreach ( $tests['async'] as $test ) {
			if ( ! empty( $test['skip_cron'] ) ) {
				continue;
			}

			// Local endpoints may require authentication, so asynchronous tests can pass a direct test runner as well.
			if ( ! empty( $test['async_direct_test'] ) && is_callable( $test['async_direct_test'] ) ) {
				// This test is callable, do so and continue to the next asynchronous check.
				$results[] = $this->perform_test( $test['async_direct_test'] );
				continue;
			}

			if ( is_string( $test['test'] ) ) {
				// Check if this test has a REST API endpoint.
				if ( isset( $test['has_rest'] ) && $test['has_rest'] ) {
					$result_fetch = wp_remote_get(
						$test['test'],
						array(
							'body' => array(
								'_wpnonce' => wp_create_nonce( 'wp_rest' ),
							),
						)
					);
				} else {
					$result_fetch = wp_remote_post(
						admin_url( 'admin-ajax.php' ),
						array(
							'body' => array(
								'action'   => $test['test'],
								'_wpnonce' => wp_create_nonce( 'health-check-site-status' ),
							),
						)
					);
				}

				if ( ! is_wp_error( $result_fetch ) && 200 === wp_remote_retrieve_response_code( $result_fetch ) ) {
					$result = json_decode( wp_remote_retrieve_body( $result_fetch ), true );
				} else {
					$result = false;
				}

				if ( is_array( $result ) ) {
					$results[] = $result;
				} else {
					$results[] = array(
						'status' => 'recommended',
						'label'  => __( 'A test is unavailable' ),
					);
				}
			}
		}

		foreach ( $results as $result ) {
			if ( 'critical' === $result['status'] ) {
				++$site_status['critical'];
			} elseif ( 'recommended' === $result['status'] ) {
				++$site_status['recommended'];
			} else {
				++$site_status['good'];
			}
		}

		set_transient( 'health-check-site-status-result', wp_json_encode( $site_status ) );
	}

	/**
	 * Checks if the current environment type is set to 'development' or 'local'.
	 *
	 * @since 5.6.0
	 *
	 * @return bool True if it is a development environment, false if not.
	 */
	public function is_development_environment() {
		return in_array( wp_get_environment_type(), array( 'development', 'local' ), true );
	}

	/**
	 * Returns a list of headers and its verification callback to verify if page cache is enabled or not.
	 *
	 * Note: key is header name and value could be callable function to verify header value.
	 * Empty value mean existence of header detect page cache is enabled.
	 *
	 * @since 6.1.0
	 *
	 * @return array List of client caching headers and their (optional) verification callbacks.
	 */
	public function get_page_cache_headers() {

		$cache_hit_callback = static function ( $header_value ) {
			return str_contains( strtolower( $header_value ), 'hit' );
		};

		$cache_headers = array(
			'cache-control'          => static function ( $header_value ) {
				return (bool) preg_match( '/max-age=[1-9]/', $header_value );
			},
			'expires'                => static function ( $header_value ) {
				return strtotime( $header_value ) > time();
			},
			'age'                    => static function ( $header_value ) {
				return is_numeric( $header_value ) && $header_value > 0;
			},
			'last-modified'          => '',
			'etag'                   => '',
			'x-cache-enabled'        => static function ( $header_value ) {
				return 'true' === strtolower( $header_value );
			},
			'x-cache-disabled'       => static function ( $header_value ) {
				return ( 'on' !== strtolower( $header_value ) );
			},
			'x-srcache-store-status' => $cache_hit_callback,
			'x-srcache-fetch-status' => $cache_hit_callback,
		);

		/**
		 * Filters the list of cache headers supported by core.
		 *
		 * @since 6.1.0
		 *
		 * @param array $cache_headers Array of supported cache headers.
		 */
		return apply_filters( 'site_status_page_cache_supported_cache_headers', $cache_headers );
	}

	/**
	 * Checks if site has page cache enabled or not.
	 *
	 * @since 6.1.0
	 *
	 * @return WP_Error|array {
	 *     Page cache detection details or else error information.
	 *
	 *     @type bool    $advanced_cache_present        Whether a page cache plugin is present.
	 *     @type array[] $page_caching_response_headers Sets of client caching headers for the responses.
	 *     @type float[] $response_timing               Response timings.
	 * }
	 */
	private function check_for_page_caching() {

		/** This filter is documented in wp-includes/class-wp-http-streams.php */
		$sslverify = apply_filters( 'https_local_ssl_verify', false );

		$headers = array();

		/*
		 * Include basic auth in loopback requests. Note that this will only pass along basic auth when user is
		 * initiating the test. If a site requires basic auth, the test will fail when it runs in WP Cron as part of
		 * wp_site_health_scheduled_check. This logic is copied from WP_Site_Health::can_perform_loopback().
		 */
		if ( isset( $_SERVER['PHP_AUTH_USER'] ) && isset( $_SERVER['PHP_AUTH_PW'] ) ) {
			$headers['Authorization'] = 'Basic ' . base64_encode( wp_unslash( $_SERVER['PHP_AUTH_USER'] ) . ':' . wp_unslash( $_SERVER['PHP_AUTH_PW'] ) );
		}

		$caching_headers               = $this->get_page_cache_headers();
		$page_caching_response_headers = array();
		$response_timing               = array();

		for ( $i = 1; $i <= 3; $i++ ) {
			$start_time    = microtime( true );
			$http_response = wp_remote_get( home_url( '/' ), compact( 'sslverify', 'headers' ) );
			$end_time      = microtime( true );

			if ( is_wp_error( $http_response ) ) {
				return $http_response;
			}
			if ( wp_remote_retrieve_response_code( $http_response ) !== 200 ) {
				return new WP_Error(
					'http_' . wp_remote_retrieve_response_code( $http_response ),
					wp_remote_retrieve_response_message( $http_response )
				);
			}

			$response_headers = array();

			foreach ( $caching_headers as $header => $callback ) {
				$header_values = wp_remote_retrieve_header( $http_response, $header );
				if ( empty( $header_values ) ) {
					continue;
				}
				$header_values = (array) $header_values;
				if ( empty( $callback ) || ( is_callable( $callback ) && count( array_filter( $header_values, $callback ) ) > 0 ) ) {
					$response_headers[ $header ] = $header_values;
				}
			}

			$page_caching_response_headers[] = $response_headers;
			$response_timing[]               = ( $end_time - $start_time ) * 1000;
		}

		return array(
			'advanced_cache_present'        => (
				file_exists( WP_CONTENT_DIR . '/advanced-cache.php' )
				&&
				( defined( 'WP_CACHE' ) && WP_CACHE )
				&&
				/** This filter is documented in wp-settings.php */
				apply_filters( 'enable_loading_advanced_cache_dropin', true )
			),
			'page_caching_response_headers' => $page_caching_response_headers,
			'response_timing'               => $response_timing,
		);
	}

	/**
	 * Gets page cache details.
	 *
	 * @since 6.1.0
	 *
	 * @return WP_Error|array {
	 *     Page cache detail or else a WP_Error if unable to determine.
	 *
	 *     @type string   $status                 Page cache status. Good, Recommended or Critical.
	 *     @type bool     $advanced_cache_present Whether page cache plugin is available or not.
	 *     @type string[] $headers                Client caching response headers detected.
	 *     @type float    $response_time          Response time of site.
	 * }
	 */
	private function get_page_cache_detail() {
		$page_cache_detail = $this->check_for_page_caching();
		if ( is_wp_error( $page_cache_detail ) ) {
			return $page_cache_detail;
		}

		// Use the median server response time.
		$response_timings = $page_cache_detail['response_timing'];
		rsort( $response_timings );
		$page_speed = $response_timings[ floor( count( $response_timings ) / 2 ) ];

		// Obtain unique set of all client caching response headers.
		$headers = array();
		foreach ( $page_cache_detail['page_caching_response_headers'] as $page_caching_response_headers ) {
			$headers = array_merge( $headers, array_keys( $page_caching_response_headers ) );
		}
		$headers = array_unique( $headers );

		// Page cache is detected if there are response headers or a page cache plugin is present.
		$has_page_caching = ( count( $headers ) > 0 || $page_cache_detail['advanced_cache_present'] );

		if ( $page_speed && $page_speed < $this->get_good_response_time_threshold() ) {
			$result = $has_page_caching ? 'good' : 'recommended';
		} else {
			$result = 'critical';
		}

		return array(
			'status'                 => $result,
			'advanced_cache_present' => $page_cache_detail['advanced_cache_present'],
			'headers'                => $headers,
			'response_time'          => $page_speed,
		);
	}

	/**
	 * Gets the threshold below which a response time is considered good.
	 *
	 * @since 6.1.0
	 *
	 * @return int Threshold in milliseconds.
	 */
	private function get_good_response_time_threshold() {
		/**
		 * Filters the threshold below which a response time is considered good.
		 *
		 * The default is based on https://web.dev/time-to-first-byte/.
		 *
		 * @since 6.1.0
		 *
		 * @param int $threshold Threshold in milliseconds. Default 600.
		 */
		return (int) apply_filters( 'site_status_good_response_time_threshold', 600 );
	}

	/**
	 * Determines whether to suggest using a persistent object cache.
	 *
	 * @since 6.1.0
	 *
	 * @global wpdb $wpdb WordPress database abstraction object.
	 *
	 * @return bool Whether to suggest using a persistent object cache.
	 */
	public function should_suggest_persistent_object_cache() {
		global $wpdb;

		/**
		 * Filters whether to suggest use of a persistent object cache and bypass default threshold checks.
		 *
		 * Using this filter allows to override the default logic, effectively short-circuiting the method.
		 *
		 * @since 6.1.0
		 *
		 * @param bool|null $suggest Boolean to short-circuit, for whether to suggest using a persistent object cache.
		 *                           Default null.
		 */
		$short_circuit = apply_filters( 'site_status_should_suggest_persistent_object_cache', null );
		if ( is_bool( $short_circuit ) ) {
			return $short_circuit;
		}

		if ( is_multisite() ) {
			return true;
		}

		/**
		 * Filters the thresholds used to determine whether to suggest the use of a persistent object cache.
		 *
		 * @since 6.1.0
		 *
		 * @param int[] $thresholds The list of threshold numbers keyed by threshold name.
		 */
		$thresholds = apply_filters(
			'site_status_persistent_object_cache_thresholds',
			array(
				'alloptions_count' => 500,
				'alloptions_bytes' => 100000,
				'comments_count'   => 1000,
				'options_count'    => 1000,
				'posts_count'      => 1000,
				'terms_count'      => 1000,
				'users_count'      => 1000,
			)
		);

		$alloptions = wp_load_alloptions();

		if ( $thresholds['alloptions_count'] < count( $alloptions ) ) {
			return true;
		}

		if ( $thresholds['alloptions_bytes'] < strlen( serialize( $alloptions ) ) ) {
			return true;
		}

		$table_names = implode( "','", array( $wpdb->comments, $wpdb->options, $wpdb->posts, $wpdb->terms, $wpdb->users ) );

		// With InnoDB the `TABLE_ROWS` are estimates, which are accurate enough and faster to retrieve than individual `COUNT()` queries.
		$results = $wpdb->get_results(
			$wpdb->prepare(
				// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- This query cannot use interpolation.
				"SELECT TABLE_NAME AS 'table', TABLE_ROWS AS 'rows', SUM(data_length + index_length) as 'bytes' FROM information_schema.TABLES WHERE TABLE_SCHEMA = %s AND TABLE_NAME IN ('$table_names') GROUP BY TABLE_NAME;",
				DB_NAME
			),
			OBJECT_K
		);

		$threshold_map = array(
			'comments_count' => $wpdb->comments,
			'options_count'  => $wpdb->options,
			'posts_count'    => $wpdb->posts,
			'terms_count'    => $wpdb->terms,
			'users_count'    => $wpdb->users,
		);

		foreach ( $threshold_map as $threshold => $table ) {
			if ( $thresholds[ $threshold ] <= $results[ $table ]->rows ) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Returns a list of available persistent object cache services.
	 *
	 * @since 6.1.0
	 *
	 * @return string[] The list of available persistent object cache services.
	 */
	private function available_object_cache_services() {
		$extensions = array_map(
			'extension_loaded',
			array(
				'APCu'      => 'apcu',
				'Redis'     => 'redis',
				'Relay'     => 'relay',
				'Memcache'  => 'memcache',
				'Memcached' => 'memcached',
			)
		);

		$services = array_keys( array_filter( $extensions ) );

		/**
		 * Filters the persistent object cache services available to the user.
		 *
		 * This can be useful to hide or add services not included in the defaults.
		 *
		 * @since 6.1.0
		 *
		 * @param string[] $services The list of available persistent object cache services.
		 */
		return apply_filters( 'site_status_available_object_cache_services', $services );
	}
}
class-theme-upgrader.php000064400000064430151212616040011276 0ustar00<?php
/**
 * Upgrade API: Theme_Upgrader class
 *
 * @package WordPress
 * @subpackage Upgrader
 * @since 4.6.0
 */

/**
 * Core class used for upgrading/installing themes.
 *
 * It is designed to upgrade/install themes from a local zip, remote zip URL,
 * or uploaded zip file.
 *
 * @since 2.8.0
 * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader.php.
 *
 * @see WP_Upgrader
 */
class Theme_Upgrader extends WP_Upgrader {

	/**
	 * Result of the theme upgrade offer.
	 *
	 * @since 2.8.0
	 * @var array|WP_Error $result
	 * @see WP_Upgrader::$result
	 */
	public $result;

	/**
	 * Whether multiple themes are being upgraded/installed in bulk.
	 *
	 * @since 2.9.0
	 * @var bool $bulk
	 */
	public $bulk = false;

	/**
	 * New theme info.
	 *
	 * @since 5.5.0
	 * @var array $new_theme_data
	 *
	 * @see check_package()
	 */
	public $new_theme_data = array();

	/**
	 * Initializes the upgrade strings.
	 *
	 * @since 2.8.0
	 */
	public function upgrade_strings() {
		$this->strings['up_to_date'] = __( 'The theme is at the latest version.' );
		$this->strings['no_package'] = __( 'Update package not available.' );
		/* translators: %s: Package URL. */
		$this->strings['downloading_package'] = sprintf( __( 'Downloading update from %s&#8230;' ), '<span class="code pre">%s</span>' );
		$this->strings['unpack_package']      = __( 'Unpacking the update&#8230;' );
		$this->strings['remove_old']          = __( 'Removing the old version of the theme&#8230;' );
		$this->strings['remove_old_failed']   = __( 'Could not remove the old theme.' );
		$this->strings['process_failed']      = __( 'Theme update failed.' );
		$this->strings['process_success']     = __( 'Theme updated successfully.' );
	}

	/**
	 * Initializes the installation strings.
	 *
	 * @since 2.8.0
	 */
	public function install_strings() {
		$this->strings['no_package'] = __( 'Installation package not available.' );
		/* translators: %s: Package URL. */
		$this->strings['downloading_package'] = sprintf( __( 'Downloading installation package from %s&#8230;' ), '<span class="code pre">%s</span>' );
		$this->strings['unpack_package']      = __( 'Unpacking the package&#8230;' );
		$this->strings['installing_package']  = __( 'Installing the theme&#8230;' );
		$this->strings['remove_old']          = __( 'Removing the old version of the theme&#8230;' );
		$this->strings['remove_old_failed']   = __( 'Could not remove the old theme.' );
		$this->strings['no_files']            = __( 'The theme contains no files.' );
		$this->strings['process_failed']      = __( 'Theme installation failed.' );
		$this->strings['process_success']     = __( 'Theme installed successfully.' );
		/* translators: 1: Theme name, 2: Theme version. */
		$this->strings['process_success_specific'] = __( 'Successfully installed the theme <strong>%1$s %2$s</strong>.' );
		$this->strings['parent_theme_search']      = __( 'This theme requires a parent theme. Checking if it is installed&#8230;' );
		/* translators: 1: Theme name, 2: Theme version. */
		$this->strings['parent_theme_prepare_install'] = __( 'Preparing to install <strong>%1$s %2$s</strong>&#8230;' );
		/* translators: 1: Theme name, 2: Theme version. */
		$this->strings['parent_theme_currently_installed'] = __( 'The parent theme, <strong>%1$s %2$s</strong>, is currently installed.' );
		/* translators: 1: Theme name, 2: Theme version. */
		$this->strings['parent_theme_install_success'] = __( 'Successfully installed the parent theme, <strong>%1$s %2$s</strong>.' );
		/* translators: %s: Theme name. */
		$this->strings['parent_theme_not_found'] = sprintf( __( '<strong>The parent theme could not be found.</strong> You will need to install the parent theme, %s, before you can use this child theme.' ), '<strong>%s</strong>' );
		/* translators: %s: Theme error. */
		$this->strings['current_theme_has_errors'] = __( 'The active theme has the following error: "%s".' );

		if ( ! empty( $this->skin->overwrite ) ) {
			if ( 'update-theme' === $this->skin->overwrite ) {
				$this->strings['installing_package'] = __( 'Updating the theme&#8230;' );
				$this->strings['process_failed']     = __( 'Theme update failed.' );
				$this->strings['process_success']    = __( 'Theme updated successfully.' );
			}

			if ( 'downgrade-theme' === $this->skin->overwrite ) {
				$this->strings['installing_package'] = __( 'Downgrading the theme&#8230;' );
				$this->strings['process_failed']     = __( 'Theme downgrade failed.' );
				$this->strings['process_success']    = __( 'Theme downgraded successfully.' );
			}
		}
	}

	/**
	 * Checks if a child theme is being installed and its parent also needs to be installed.
	 *
	 * Hooked to the {@see 'upgrader_post_install'} filter by Theme_Upgrader::install().
	 *
	 * @since 3.4.0
	 *
	 * @param bool  $install_result
	 * @param array $hook_extra
	 * @param array $child_result
	 * @return bool
	 */
	public function check_parent_theme_filter( $install_result, $hook_extra, $child_result ) {
		// Check to see if we need to install a parent theme.
		$theme_info = $this->theme_info();

		if ( ! $theme_info->parent() ) {
			return $install_result;
		}

		$this->skin->feedback( 'parent_theme_search' );

		if ( ! $theme_info->parent()->errors() ) {
			$this->skin->feedback( 'parent_theme_currently_installed', $theme_info->parent()->display( 'Name' ), $theme_info->parent()->display( 'Version' ) );
			// We already have the theme, fall through.
			return $install_result;
		}

		// We don't have the parent theme, let's install it.
		$api = themes_api(
			'theme_information',
			array(
				'slug'   => $theme_info->get( 'Template' ),
				'fields' => array(
					'sections' => false,
					'tags'     => false,
				),
			)
		); // Save on a bit of bandwidth.

		if ( ! $api || is_wp_error( $api ) ) {
			$this->skin->feedback( 'parent_theme_not_found', $theme_info->get( 'Template' ) );
			// Don't show activate or preview actions after installation.
			add_filter( 'install_theme_complete_actions', array( $this, 'hide_activate_preview_actions' ) );
			return $install_result;
		}

		// Backup required data we're going to override:
		$child_api             = $this->skin->api;
		$child_success_message = $this->strings['process_success'];

		// Override them.
		$this->skin->api = $api;

		$this->strings['process_success_specific'] = $this->strings['parent_theme_install_success'];

		$this->skin->feedback( 'parent_theme_prepare_install', $api->name, $api->version );

		add_filter( 'install_theme_complete_actions', '__return_false', 999 ); // Don't show any actions after installing the theme.

		// Install the parent theme.
		$parent_result = $this->run(
			array(
				'package'           => $api->download_link,
				'destination'       => get_theme_root(),
				'clear_destination' => false, // Do not overwrite files.
				'clear_working'     => true,
			)
		);

		if ( is_wp_error( $parent_result ) ) {
			add_filter( 'install_theme_complete_actions', array( $this, 'hide_activate_preview_actions' ) );
		}

		// Start cleaning up after the parent's installation.
		remove_filter( 'install_theme_complete_actions', '__return_false', 999 );

		// Reset child's result and data.
		$this->result                     = $child_result;
		$this->skin->api                  = $child_api;
		$this->strings['process_success'] = $child_success_message;

		return $install_result;
	}

	/**
	 * Don't display the activate and preview actions to the user.
	 *
	 * Hooked to the {@see 'install_theme_complete_actions'} filter by
	 * Theme_Upgrader::check_parent_theme_filter() when installing
	 * a child theme and installing the parent theme fails.
	 *
	 * @since 3.4.0
	 *
	 * @param array $actions Preview actions.
	 * @return array
	 */
	public function hide_activate_preview_actions( $actions ) {
		unset( $actions['activate'], $actions['preview'] );
		return $actions;
	}

	/**
	 * Install a theme package.
	 *
	 * @since 2.8.0
	 * @since 3.7.0 The `$args` parameter was added, making clearing the update cache optional.
	 *
	 * @param string $package The full local path or URI of the package.
	 * @param array  $args {
	 *     Optional. Other arguments for installing a theme package. Default empty array.
	 *
	 *     @type bool $clear_update_cache Whether to clear the updates cache if successful.
	 *                                    Default true.
	 * }
	 *
	 * @return bool|WP_Error True if the installation was successful, false or a WP_Error object otherwise.
	 */
	public function install( $package, $args = array() ) {
		$defaults    = array(
			'clear_update_cache' => true,
			'overwrite_package'  => false, // Do not overwrite files.
		);
		$parsed_args = wp_parse_args( $args, $defaults );

		$this->init();
		$this->install_strings();

		add_filter( 'upgrader_source_selection', array( $this, 'check_package' ) );
		add_filter( 'upgrader_post_install', array( $this, 'check_parent_theme_filter' ), 10, 3 );

		if ( $parsed_args['clear_update_cache'] ) {
			// Clear cache so wp_update_themes() knows about the new theme.
			add_action( 'upgrader_process_complete', 'wp_clean_themes_cache', 9, 0 );
		}

		$this->run(
			array(
				'package'           => $package,
				'destination'       => get_theme_root(),
				'clear_destination' => $parsed_args['overwrite_package'],
				'clear_working'     => true,
				'hook_extra'        => array(
					'type'   => 'theme',
					'action' => 'install',
				),
			)
		);

		remove_action( 'upgrader_process_complete', 'wp_clean_themes_cache', 9 );
		remove_filter( 'upgrader_source_selection', array( $this, 'check_package' ) );
		remove_filter( 'upgrader_post_install', array( $this, 'check_parent_theme_filter' ) );

		if ( ! $this->result || is_wp_error( $this->result ) ) {
			return $this->result;
		}

		// Refresh the Theme Update information.
		wp_clean_themes_cache( $parsed_args['clear_update_cache'] );

		if ( $parsed_args['overwrite_package'] ) {
			/** This action is documented in wp-admin/includes/class-plugin-upgrader.php */
			do_action( 'upgrader_overwrote_package', $package, $this->new_theme_data, 'theme' );
		}

		return true;
	}

	/**
	 * Upgrades a theme.
	 *
	 * @since 2.8.0
	 * @since 3.7.0 The `$args` parameter was added, making clearing the update cache optional.
	 *
	 * @param string $theme The theme slug.
	 * @param array  $args {
	 *     Optional. Other arguments for upgrading a theme. Default empty array.
	 *
	 *     @type bool $clear_update_cache Whether to clear the update cache if successful.
	 *                                    Default true.
	 * }
	 * @return bool|WP_Error True if the upgrade was successful, false or a WP_Error object otherwise.
	 */
	public function upgrade( $theme, $args = array() ) {
		$defaults    = array(
			'clear_update_cache' => true,
		);
		$parsed_args = wp_parse_args( $args, $defaults );

		$this->init();
		$this->upgrade_strings();

		// Is an update available?
		$current = get_site_transient( 'update_themes' );
		if ( ! isset( $current->response[ $theme ] ) ) {
			$this->skin->before();
			$this->skin->set_result( false );
			$this->skin->error( 'up_to_date' );
			$this->skin->after();
			return false;
		}

		$upgrade_data = $current->response[ $theme ];

		add_filter( 'upgrader_pre_install', array( $this, 'current_before' ), 10, 2 );
		add_filter( 'upgrader_post_install', array( $this, 'current_after' ), 10, 2 );
		add_filter( 'upgrader_clear_destination', array( $this, 'delete_old_theme' ), 10, 4 );
		if ( $parsed_args['clear_update_cache'] ) {
			// Clear cache so wp_update_themes() knows about the new theme.
			add_action( 'upgrader_process_complete', 'wp_clean_themes_cache', 9, 0 );
		}

		$this->run(
			array(
				'package'           => $upgrade_data['package'],
				'destination'       => get_theme_root( $theme ),
				'clear_destination' => true,
				'clear_working'     => true,
				'hook_extra'        => array(
					'theme'       => $theme,
					'type'        => 'theme',
					'action'      => 'update',
					'temp_backup' => array(
						'slug' => $theme,
						'src'  => get_theme_root( $theme ),
						'dir'  => 'themes',
					),
				),
			)
		);

		remove_action( 'upgrader_process_complete', 'wp_clean_themes_cache', 9 );
		remove_filter( 'upgrader_pre_install', array( $this, 'current_before' ) );
		remove_filter( 'upgrader_post_install', array( $this, 'current_after' ) );
		remove_filter( 'upgrader_clear_destination', array( $this, 'delete_old_theme' ) );

		if ( ! $this->result || is_wp_error( $this->result ) ) {
			return $this->result;
		}

		wp_clean_themes_cache( $parsed_args['clear_update_cache'] );

		/*
		 * Ensure any future auto-update failures trigger a failure email by removing
		 * the last failure notification from the list when themes update successfully.
		 */
		$past_failure_emails = get_option( 'auto_plugin_theme_update_emails', array() );

		if ( isset( $past_failure_emails[ $theme ] ) ) {
			unset( $past_failure_emails[ $theme ] );
			update_option( 'auto_plugin_theme_update_emails', $past_failure_emails );
		}

		return true;
	}

	/**
	 * Upgrades several themes at once.
	 *
	 * @since 3.0.0
	 * @since 3.7.0 The `$args` parameter was added, making clearing the update cache optional.
	 *
	 * @param string[] $themes Array of the theme slugs.
	 * @param array    $args {
	 *     Optional. Other arguments for upgrading several themes at once. Default empty array.
	 *
	 *     @type bool $clear_update_cache Whether to clear the update cache if successful.
	 *                                    Default true.
	 * }
	 * @return array[]|false An array of results, or false if unable to connect to the filesystem.
	 */
	public function bulk_upgrade( $themes, $args = array() ) {
		$wp_version  = wp_get_wp_version();
		$defaults    = array(
			'clear_update_cache' => true,
		);
		$parsed_args = wp_parse_args( $args, $defaults );

		$this->init();
		$this->bulk = true;
		$this->upgrade_strings();

		$current = get_site_transient( 'update_themes' );

		add_filter( 'upgrader_pre_install', array( $this, 'current_before' ), 10, 2 );
		add_filter( 'upgrader_post_install', array( $this, 'current_after' ), 10, 2 );
		add_filter( 'upgrader_clear_destination', array( $this, 'delete_old_theme' ), 10, 4 );

		$this->skin->header();

		// Connect to the filesystem first.
		$connected = $this->fs_connect( array( WP_CONTENT_DIR ) );
		if ( ! $connected ) {
			$this->skin->footer();
			return false;
		}

		$this->skin->bulk_header();

		/*
		 * Only start maintenance mode if:
		 * - running Multisite and there are one or more themes specified, OR
		 * - a theme with an update available is currently in use.
		 * @todo For multisite, maintenance mode should only kick in for individual sites if at all possible.
		 */
		$maintenance = ( is_multisite() && ! empty( $themes ) );
		foreach ( $themes as $theme ) {
			$maintenance = $maintenance || get_stylesheet() === $theme || get_template() === $theme;
		}
		if ( $maintenance ) {
			$this->maintenance_mode( true );
		}

		$results = array();

		$this->update_count   = count( $themes );
		$this->update_current = 0;
		foreach ( $themes as $theme ) {
			++$this->update_current;

			$this->skin->theme_info = $this->theme_info( $theme );

			if ( ! isset( $current->response[ $theme ] ) ) {
				$this->skin->set_result( true );
				$this->skin->before();
				$this->skin->feedback( 'up_to_date' );
				$this->skin->after();
				$results[ $theme ] = true;
				continue;
			}

			// Get the URL to the zip file.
			$upgrade_data = $current->response[ $theme ];

			if ( isset( $upgrade_data['requires'] ) && ! is_wp_version_compatible( $upgrade_data['requires'] ) ) {
				$result = new WP_Error(
					'incompatible_wp_required_version',
					sprintf(
						/* translators: 1: Current WordPress version, 2: WordPress version required by the new theme version. */
						__( 'Your WordPress version is %1$s, however the new theme version requires %2$s.' ),
						$wp_version,
						$upgrade_data['requires']
					)
				);

				$this->skin->before( $result );
				$this->skin->error( $result );
				$this->skin->after();
			} elseif ( isset( $upgrade_data['requires_php'] ) && ! is_php_version_compatible( $upgrade_data['requires_php'] ) ) {
				$result = new WP_Error(
					'incompatible_php_required_version',
					sprintf(
						/* translators: 1: Current PHP version, 2: PHP version required by the new theme version. */
						__( 'The PHP version on your server is %1$s, however the new theme version requires %2$s.' ),
						PHP_VERSION,
						$upgrade_data['requires_php']
					)
				);

				$this->skin->before( $result );
				$this->skin->error( $result );
				$this->skin->after();
			} else {
				add_filter( 'upgrader_source_selection', array( $this, 'check_package' ) );
				$result = $this->run(
					array(
						'package'           => $upgrade_data['package'],
						'destination'       => get_theme_root( $theme ),
						'clear_destination' => true,
						'clear_working'     => true,
						'is_multi'          => true,
						'hook_extra'        => array(
							'theme'       => $theme,
							'temp_backup' => array(
								'slug' => $theme,
								'src'  => get_theme_root( $theme ),
								'dir'  => 'themes',
							),
						),
					)
				);
				remove_filter( 'upgrader_source_selection', array( $this, 'check_package' ) );
			}

			$results[ $theme ] = $result;

			// Prevent credentials auth screen from displaying multiple times.
			if ( false === $result ) {
				break;
			}
		} // End foreach $themes.

		$this->maintenance_mode( false );

		// Refresh the Theme Update information.
		wp_clean_themes_cache( $parsed_args['clear_update_cache'] );

		/** This action is documented in wp-admin/includes/class-wp-upgrader.php */
		do_action(
			'upgrader_process_complete',
			$this,
			array(
				'action' => 'update',
				'type'   => 'theme',
				'bulk'   => true,
				'themes' => $themes,
			)
		);

		$this->skin->bulk_footer();

		$this->skin->footer();

		// Cleanup our hooks, in case something else does an upgrade on this connection.
		remove_filter( 'upgrader_pre_install', array( $this, 'current_before' ) );
		remove_filter( 'upgrader_post_install', array( $this, 'current_after' ) );
		remove_filter( 'upgrader_clear_destination', array( $this, 'delete_old_theme' ) );

		/*
		 * Ensure any future auto-update failures trigger a failure email by removing
		 * the last failure notification from the list when themes update successfully.
		 */
		$past_failure_emails = get_option( 'auto_plugin_theme_update_emails', array() );

		foreach ( $results as $theme => $result ) {
			// Maintain last failure notification when themes failed to update manually.
			if ( ! $result || is_wp_error( $result ) || ! isset( $past_failure_emails[ $theme ] ) ) {
				continue;
			}

			unset( $past_failure_emails[ $theme ] );
		}

		update_option( 'auto_plugin_theme_update_emails', $past_failure_emails );

		return $results;
	}

	/**
	 * Checks that the package source contains a valid theme.
	 *
	 * Hooked to the {@see 'upgrader_source_selection'} filter by Theme_Upgrader::install().
	 *
	 * @since 3.3.0
	 *
	 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
	 *
	 * @param string $source The path to the downloaded package source.
	 * @return string|WP_Error The source as passed, or a WP_Error object on failure.
	 */
	public function check_package( $source ) {
		global $wp_filesystem;

		$wp_version           = wp_get_wp_version();
		$this->new_theme_data = array();

		if ( is_wp_error( $source ) ) {
			return $source;
		}

		// Check that the folder contains a valid theme.
		$working_directory = str_replace( $wp_filesystem->wp_content_dir(), trailingslashit( WP_CONTENT_DIR ), $source );
		if ( ! is_dir( $working_directory ) ) { // Confidence check, if the above fails, let's not prevent installation.
			return $source;
		}

		// A proper archive should have a style.css file in the single subdirectory.
		if ( ! file_exists( $working_directory . 'style.css' ) ) {
			return new WP_Error(
				'incompatible_archive_theme_no_style',
				$this->strings['incompatible_archive'],
				sprintf(
					/* translators: %s: style.css */
					__( 'The theme is missing the %s stylesheet.' ),
					'<code>style.css</code>'
				)
			);
		}

		// All these headers are needed on Theme_Installer_Skin::do_overwrite().
		$new_theme_data = get_file_data(
			$working_directory . 'style.css',
			array(
				'Name'        => 'Theme Name',
				'Version'     => 'Version',
				'Author'      => 'Author',
				'Template'    => 'Template',
				'RequiresWP'  => 'Requires at least',
				'RequiresPHP' => 'Requires PHP',
			)
		);

		if ( empty( $new_theme_data['Name'] ) ) {
			return new WP_Error(
				'incompatible_archive_theme_no_name',
				$this->strings['incompatible_archive'],
				sprintf(
					/* translators: %s: style.css */
					__( 'The %s stylesheet does not contain a valid theme header.' ),
					'<code>style.css</code>'
				)
			);
		}

		/*
		 * Parent themes must contain an index file:
		 * - classic themes require /index.php
		 * - block themes require /templates/index.html or block-templates/index.html (deprecated 5.9.0).
		 */
		if (
			empty( $new_theme_data['Template'] ) &&
			! file_exists( $working_directory . 'index.php' ) &&
			! file_exists( $working_directory . 'templates/index.html' ) &&
			! file_exists( $working_directory . 'block-templates/index.html' )
		) {
			return new WP_Error(
				'incompatible_archive_theme_no_index',
				$this->strings['incompatible_archive'],
				sprintf(
					/* translators: 1: templates/index.html, 2: index.php, 3: Documentation URL, 4: Template, 5: style.css */
					__( 'Template is missing. Standalone themes need to have a %1$s or %2$s template file. <a href="%3$s">Child themes</a> need to have a %4$s header in the %5$s stylesheet.' ),
					'<code>templates/index.html</code>',
					'<code>index.php</code>',
					__( 'https://developer.wordpress.org/themes/advanced-topics/child-themes/' ),
					'<code>Template</code>',
					'<code>style.css</code>'
				)
			);
		}

		$requires_php = isset( $new_theme_data['RequiresPHP'] ) ? $new_theme_data['RequiresPHP'] : null;
		$requires_wp  = isset( $new_theme_data['RequiresWP'] ) ? $new_theme_data['RequiresWP'] : null;

		if ( ! is_php_version_compatible( $requires_php ) ) {
			$error = sprintf(
				/* translators: 1: Current PHP version, 2: Version required by the uploaded theme. */
				__( 'The PHP version on your server is %1$s, however the uploaded theme requires %2$s.' ),
				PHP_VERSION,
				$requires_php
			);

			return new WP_Error( 'incompatible_php_required_version', $this->strings['incompatible_archive'], $error );
		}
		if ( ! is_wp_version_compatible( $requires_wp ) ) {
			$error = sprintf(
				/* translators: 1: Current WordPress version, 2: Version required by the uploaded theme. */
				__( 'Your WordPress version is %1$s, however the uploaded theme requires %2$s.' ),
				$wp_version,
				$requires_wp
			);

			return new WP_Error( 'incompatible_wp_required_version', $this->strings['incompatible_archive'], $error );
		}

		$this->new_theme_data = $new_theme_data;

		return $source;
	}

	/**
	 * Turns on maintenance mode before attempting to upgrade the active theme.
	 *
	 * Hooked to the {@see 'upgrader_pre_install'} filter by Theme_Upgrader::upgrade() and
	 * Theme_Upgrader::bulk_upgrade().
	 *
	 * @since 2.8.0
	 *
	 * @param bool|WP_Error $response The installation response before the installation has started.
	 * @param array         $theme    Theme arguments.
	 * @return bool|WP_Error The original `$response` parameter or WP_Error.
	 */
	public function current_before( $response, $theme ) {
		if ( is_wp_error( $response ) ) {
			return $response;
		}

		$theme = isset( $theme['theme'] ) ? $theme['theme'] : '';

		// Only run if active theme.
		if ( get_stylesheet() !== $theme ) {
			return $response;
		}

		// Change to maintenance mode. Bulk edit handles this separately.
		if ( ! $this->bulk ) {
			$this->maintenance_mode( true );
		}

		return $response;
	}

	/**
	 * Turns off maintenance mode after upgrading the active theme.
	 *
	 * Hooked to the {@see 'upgrader_post_install'} filter by Theme_Upgrader::upgrade()
	 * and Theme_Upgrader::bulk_upgrade().
	 *
	 * @since 2.8.0
	 *
	 * @param bool|WP_Error $response The installation response after the installation has finished.
	 * @param array         $theme    Theme arguments.
	 * @return bool|WP_Error The original `$response` parameter or WP_Error.
	 */
	public function current_after( $response, $theme ) {
		if ( is_wp_error( $response ) ) {
			return $response;
		}

		$theme = isset( $theme['theme'] ) ? $theme['theme'] : '';

		// Only run if active theme.
		if ( get_stylesheet() !== $theme ) {
			return $response;
		}

		// Ensure stylesheet name hasn't changed after the upgrade:
		if ( get_stylesheet() === $theme && $theme !== $this->result['destination_name'] ) {
			wp_clean_themes_cache();
			$stylesheet = $this->result['destination_name'];
			switch_theme( $stylesheet );
		}

		// Time to remove maintenance mode. Bulk edit handles this separately.
		if ( ! $this->bulk ) {
			$this->maintenance_mode( false );
		}
		return $response;
	}

	/**
	 * Deletes the old theme during an upgrade.
	 *
	 * Hooked to the {@see 'upgrader_clear_destination'} filter by Theme_Upgrader::upgrade()
	 * and Theme_Upgrader::bulk_upgrade().
	 *
	 * @since 2.8.0
	 *
	 * @global WP_Filesystem_Base $wp_filesystem Subclass
	 *
	 * @param bool   $removed
	 * @param string $local_destination
	 * @param string $remote_destination
	 * @param array  $theme
	 * @return bool
	 */
	public function delete_old_theme( $removed, $local_destination, $remote_destination, $theme ) {
		global $wp_filesystem;

		if ( is_wp_error( $removed ) ) {
			return $removed; // Pass errors through.
		}

		if ( ! isset( $theme['theme'] ) ) {
			return $removed;
		}

		$theme      = $theme['theme'];
		$themes_dir = trailingslashit( $wp_filesystem->wp_themes_dir( $theme ) );
		if ( $wp_filesystem->exists( $themes_dir . $theme ) ) {
			if ( ! $wp_filesystem->delete( $themes_dir . $theme, true ) ) {
				return false;
			}
		}

		return true;
	}

	/**
	 * Gets the WP_Theme object for a theme.
	 *
	 * @since 2.8.0
	 * @since 3.0.0 The `$theme` argument was added.
	 *
	 * @param string $theme The directory name of the theme. This is optional, and if not supplied,
	 *                      the directory name from the last result will be used.
	 * @return WP_Theme|false The theme's info object, or false `$theme` is not supplied
	 *                        and the last result isn't set.
	 */
	public function theme_info( $theme = null ) {
		if ( empty( $theme ) ) {
			if ( ! empty( $this->result['destination_name'] ) ) {
				$theme = $this->result['destination_name'];
			} else {
				return false;
			}
		}

		$theme = wp_get_theme( $theme );
		$theme->cache_delete();

		return $theme;
	}
}
post.php000064400000240624151212616040006250 0ustar00<?php
/**
 * WordPress Post Administration API.
 *
 * @package WordPress
 * @subpackage Administration
 */

/**
 * Renames `$_POST` data from form names to DB post columns.
 *
 * Manipulates `$_POST` directly.
 *
 * @since 2.6.0
 *
 * @param bool       $update    Whether the post already exists.
 * @param array|null $post_data Optional. The array of post data to process.
 *                              Defaults to the `$_POST` superglobal.
 * @return array|WP_Error Array of post data on success, WP_Error on failure.
 */
function _wp_translate_postdata( $update = false, $post_data = null ) {

	if ( empty( $post_data ) ) {
		$post_data = &$_POST;
	}

	if ( $update ) {
		$post_data['ID'] = (int) $post_data['post_ID'];
	}

	$ptype = get_post_type_object( $post_data['post_type'] );

	if ( $update && ! current_user_can( 'edit_post', $post_data['ID'] ) ) {
		if ( 'page' === $post_data['post_type'] ) {
			return new WP_Error( 'edit_others_pages', __( 'Sorry, you are not allowed to edit pages as this user.' ) );
		} else {
			return new WP_Error( 'edit_others_posts', __( 'Sorry, you are not allowed to edit posts as this user.' ) );
		}
	} elseif ( ! $update && ! current_user_can( $ptype->cap->create_posts ) ) {
		if ( 'page' === $post_data['post_type'] ) {
			return new WP_Error( 'edit_others_pages', __( 'Sorry, you are not allowed to create pages as this user.' ) );
		} else {
			return new WP_Error( 'edit_others_posts', __( 'Sorry, you are not allowed to create posts as this user.' ) );
		}
	}

	if ( isset( $post_data['content'] ) ) {
		$post_data['post_content'] = $post_data['content'];
	}

	if ( isset( $post_data['excerpt'] ) ) {
		$post_data['post_excerpt'] = $post_data['excerpt'];
	}

	if ( isset( $post_data['parent_id'] ) ) {
		$post_data['post_parent'] = (int) $post_data['parent_id'];
	}

	if ( isset( $post_data['trackback_url'] ) ) {
		$post_data['to_ping'] = $post_data['trackback_url'];
	}

	$post_data['user_ID'] = get_current_user_id();

	if ( ! empty( $post_data['post_author_override'] ) ) {
		$post_data['post_author'] = (int) $post_data['post_author_override'];
	} else {
		if ( ! empty( $post_data['post_author'] ) ) {
			$post_data['post_author'] = (int) $post_data['post_author'];
		} else {
			$post_data['post_author'] = (int) $post_data['user_ID'];
		}
	}

	if ( isset( $post_data['user_ID'] ) && ( $post_data['post_author'] !== $post_data['user_ID'] )
		&& ! current_user_can( $ptype->cap->edit_others_posts ) ) {

		if ( $update ) {
			if ( 'page' === $post_data['post_type'] ) {
				return new WP_Error( 'edit_others_pages', __( 'Sorry, you are not allowed to edit pages as this user.' ) );
			} else {
				return new WP_Error( 'edit_others_posts', __( 'Sorry, you are not allowed to edit posts as this user.' ) );
			}
		} else {
			if ( 'page' === $post_data['post_type'] ) {
				return new WP_Error( 'edit_others_pages', __( 'Sorry, you are not allowed to create pages as this user.' ) );
			} else {
				return new WP_Error( 'edit_others_posts', __( 'Sorry, you are not allowed to create posts as this user.' ) );
			}
		}
	}

	if ( ! empty( $post_data['post_status'] ) ) {
		$post_data['post_status'] = sanitize_key( $post_data['post_status'] );

		// No longer an auto-draft.
		if ( 'auto-draft' === $post_data['post_status'] ) {
			$post_data['post_status'] = 'draft';
		}

		if ( ! get_post_status_object( $post_data['post_status'] ) ) {
			unset( $post_data['post_status'] );
		}
	}

	// What to do based on which button they pressed.
	if ( isset( $post_data['saveasdraft'] ) && '' !== $post_data['saveasdraft'] ) {
		$post_data['post_status'] = 'draft';
	}
	if ( isset( $post_data['saveasprivate'] ) && '' !== $post_data['saveasprivate'] ) {
		$post_data['post_status'] = 'private';
	}
	if ( isset( $post_data['publish'] ) && ( '' !== $post_data['publish'] )
		&& ( ! isset( $post_data['post_status'] ) || 'private' !== $post_data['post_status'] )
	) {
		$post_data['post_status'] = 'publish';
	}
	if ( isset( $post_data['advanced'] ) && '' !== $post_data['advanced'] ) {
		$post_data['post_status'] = 'draft';
	}
	if ( isset( $post_data['pending'] ) && '' !== $post_data['pending'] ) {
		$post_data['post_status'] = 'pending';
	}

	if ( isset( $post_data['ID'] ) ) {
		$post_id = $post_data['ID'];
	} else {
		$post_id = false;
	}
	$previous_status = $post_id ? get_post_field( 'post_status', $post_id ) : false;

	if ( isset( $post_data['post_status'] ) && 'private' === $post_data['post_status'] && ! current_user_can( $ptype->cap->publish_posts ) ) {
		$post_data['post_status'] = $previous_status ? $previous_status : 'pending';
	}

	$published_statuses = array( 'publish', 'future' );

	/*
	 * Posts 'submitted for approval' are submitted to $_POST the same as if they were being published.
	 * Change status from 'publish' to 'pending' if user lacks permissions to publish or to resave published posts.
	 */
	if ( isset( $post_data['post_status'] )
		&& ( in_array( $post_data['post_status'], $published_statuses, true )
		&& ! current_user_can( $ptype->cap->publish_posts ) )
	) {
		if ( ! in_array( $previous_status, $published_statuses, true ) || ! current_user_can( 'edit_post', $post_id ) ) {
			$post_data['post_status'] = 'pending';
		}
	}

	if ( ! isset( $post_data['post_status'] ) ) {
		$post_data['post_status'] = 'auto-draft' === $previous_status ? 'draft' : $previous_status;
	}

	if ( isset( $post_data['post_password'] ) && ! current_user_can( $ptype->cap->publish_posts ) ) {
		unset( $post_data['post_password'] );
	}

	if ( ! isset( $post_data['comment_status'] ) ) {
		$post_data['comment_status'] = 'closed';
	}

	if ( ! isset( $post_data['ping_status'] ) ) {
		$post_data['ping_status'] = 'closed';
	}

	foreach ( array( 'aa', 'mm', 'jj', 'hh', 'mn' ) as $timeunit ) {
		if ( ! empty( $post_data[ 'hidden_' . $timeunit ] ) && $post_data[ 'hidden_' . $timeunit ] !== $post_data[ $timeunit ] ) {
			$post_data['edit_date'] = '1';
			break;
		}
	}

	if ( ! empty( $post_data['edit_date'] ) ) {
		$aa = $post_data['aa'];
		$mm = $post_data['mm'];
		$jj = $post_data['jj'];
		$hh = $post_data['hh'];
		$mn = $post_data['mn'];
		$ss = $post_data['ss'];
		$aa = ( $aa <= 0 ) ? gmdate( 'Y' ) : $aa;
		$mm = ( $mm <= 0 ) ? gmdate( 'n' ) : $mm;
		$jj = ( $jj > 31 ) ? 31 : $jj;
		$jj = ( $jj <= 0 ) ? gmdate( 'j' ) : $jj;
		$hh = ( $hh > 23 ) ? $hh - 24 : $hh;
		$mn = ( $mn > 59 ) ? $mn - 60 : $mn;
		$ss = ( $ss > 59 ) ? $ss - 60 : $ss;

		$post_data['post_date'] = sprintf( '%04d-%02d-%02d %02d:%02d:%02d', $aa, $mm, $jj, $hh, $mn, $ss );

		$valid_date = wp_checkdate( $mm, $jj, $aa, $post_data['post_date'] );
		if ( ! $valid_date ) {
			return new WP_Error( 'invalid_date', __( 'Invalid date.' ) );
		}

		/*
		 * Only assign a post date if the user has explicitly set a new value.
		 * See #59125 and #19907.
		 */
		$previous_date = $post_id ? get_post_field( 'post_date', $post_id ) : false;
		if ( $previous_date && $previous_date !== $post_data['post_date'] ) {
			$post_data['edit_date']     = true;
			$post_data['post_date_gmt'] = get_gmt_from_date( $post_data['post_date'] );
		} else {
			$post_data['edit_date'] = false;
			unset( $post_data['post_date'] );
			unset( $post_data['post_date_gmt'] );
		}
	}

	if ( isset( $post_data['post_category'] ) ) {
		$category_object = get_taxonomy( 'category' );
		if ( ! current_user_can( $category_object->cap->assign_terms ) ) {
			unset( $post_data['post_category'] );
		}
	}

	return $post_data;
}

/**
 * Returns only allowed post data fields.
 *
 * @since 5.0.1
 *
 * @param array|WP_Error|null $post_data The array of post data to process, or an error object.
 *                                       Defaults to the `$_POST` superglobal.
 * @return array|WP_Error Array of post data on success, WP_Error on failure.
 */
function _wp_get_allowed_postdata( $post_data = null ) {
	if ( empty( $post_data ) ) {
		$post_data = $_POST;
	}

	// Pass through errors.
	if ( is_wp_error( $post_data ) ) {
		return $post_data;
	}

	return array_diff_key( $post_data, array_flip( array( 'meta_input', 'file', 'guid' ) ) );
}

/**
 * Updates an existing post with values provided in `$_POST`.
 *
 * If post data is passed as an argument, it is treated as an array of data
 * keyed appropriately for turning into a post object.
 *
 * If post data is not passed, the `$_POST` global variable is used instead.
 *
 * @since 1.5.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param array|null $post_data Optional. The array of post data to process.
 *                              Defaults to the `$_POST` superglobal.
 * @return int Post ID.
 */
function edit_post( $post_data = null ) {
	global $wpdb;

	if ( empty( $post_data ) ) {
		$post_data = &$_POST;
	}

	// Clear out any data in internal vars.
	unset( $post_data['filter'] );

	$post_id = (int) $post_data['post_ID'];
	$post    = get_post( $post_id );

	$post_data['post_type']      = $post->post_type;
	$post_data['post_mime_type'] = $post->post_mime_type;

	if ( ! empty( $post_data['post_status'] ) ) {
		$post_data['post_status'] = sanitize_key( $post_data['post_status'] );

		if ( 'inherit' === $post_data['post_status'] ) {
			unset( $post_data['post_status'] );
		}
	}

	$ptype = get_post_type_object( $post_data['post_type'] );
	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		if ( 'page' === $post_data['post_type'] ) {
			wp_die( __( 'Sorry, you are not allowed to edit this page.' ) );
		} else {
			wp_die( __( 'Sorry, you are not allowed to edit this post.' ) );
		}
	}

	if ( post_type_supports( $ptype->name, 'revisions' ) ) {
		$revisions = wp_get_post_revisions(
			$post_id,
			array(
				'order'          => 'ASC',
				'posts_per_page' => 1,
			)
		);
		$revision  = current( $revisions );

		// Check if the revisions have been upgraded.
		if ( $revisions && _wp_get_post_revision_version( $revision ) < 1 ) {
			_wp_upgrade_revisions_of_post( $post, wp_get_post_revisions( $post_id ) );
		}
	}

	if ( isset( $post_data['visibility'] ) ) {
		switch ( $post_data['visibility'] ) {
			case 'public':
				$post_data['post_password'] = '';
				break;
			case 'password':
				unset( $post_data['sticky'] );
				break;
			case 'private':
				$post_data['post_status']   = 'private';
				$post_data['post_password'] = '';
				unset( $post_data['sticky'] );
				break;
		}
	}

	$post_data = _wp_translate_postdata( true, $post_data );
	if ( is_wp_error( $post_data ) ) {
		wp_die( $post_data->get_error_message() );
	}
	$translated = _wp_get_allowed_postdata( $post_data );

	// Post formats.
	if ( isset( $post_data['post_format'] ) ) {
		set_post_format( $post_id, $post_data['post_format'] );
	}

	$format_meta_urls = array( 'url', 'link_url', 'quote_source_url' );
	foreach ( $format_meta_urls as $format_meta_url ) {
		$keyed = '_format_' . $format_meta_url;
		if ( isset( $post_data[ $keyed ] ) ) {
			update_post_meta( $post_id, $keyed, wp_slash( sanitize_url( wp_unslash( $post_data[ $keyed ] ) ) ) );
		}
	}

	$format_keys = array( 'quote', 'quote_source_name', 'image', 'gallery', 'audio_embed', 'video_embed' );

	foreach ( $format_keys as $key ) {
		$keyed = '_format_' . $key;
		if ( isset( $post_data[ $keyed ] ) ) {
			if ( current_user_can( 'unfiltered_html' ) ) {
				update_post_meta( $post_id, $keyed, $post_data[ $keyed ] );
			} else {
				update_post_meta( $post_id, $keyed, wp_filter_post_kses( $post_data[ $keyed ] ) );
			}
		}
	}

	if ( 'attachment' === $post_data['post_type'] && preg_match( '#^(audio|video)/#', $post_data['post_mime_type'] ) ) {
		$id3data = wp_get_attachment_metadata( $post_id );
		if ( ! is_array( $id3data ) ) {
			$id3data = array();
		}

		foreach ( wp_get_attachment_id3_keys( $post, 'edit' ) as $key => $label ) {
			if ( isset( $post_data[ 'id3_' . $key ] ) ) {
				$id3data[ $key ] = sanitize_text_field( wp_unslash( $post_data[ 'id3_' . $key ] ) );
			}
		}
		wp_update_attachment_metadata( $post_id, $id3data );
	}

	// Meta stuff.
	if ( isset( $post_data['meta'] ) && $post_data['meta'] ) {
		foreach ( $post_data['meta'] as $key => $value ) {
			$meta = get_post_meta_by_id( $key );
			if ( ! $meta ) {
				continue;
			}

			if ( (int) $meta->post_id !== $post_id ) {
				continue;
			}

			if ( is_protected_meta( $meta->meta_key, 'post' )
				|| ! current_user_can( 'edit_post_meta', $post_id, $meta->meta_key )
			) {
				continue;
			}

			if ( is_protected_meta( $value['key'], 'post' )
				|| ! current_user_can( 'edit_post_meta', $post_id, $value['key'] )
			) {
				continue;
			}

			update_meta( $key, $value['key'], $value['value'] );
		}
	}

	if ( isset( $post_data['deletemeta'] ) && $post_data['deletemeta'] ) {
		foreach ( $post_data['deletemeta'] as $key => $value ) {
			$meta = get_post_meta_by_id( $key );
			if ( ! $meta ) {
				continue;
			}

			if ( (int) $meta->post_id !== $post_id ) {
				continue;
			}

			if ( is_protected_meta( $meta->meta_key, 'post' )
				|| ! current_user_can( 'delete_post_meta', $post_id, $meta->meta_key )
			) {
				continue;
			}

			delete_meta( $key );
		}
	}

	// Attachment stuff.
	if ( 'attachment' === $post_data['post_type'] ) {
		if ( isset( $post_data['_wp_attachment_image_alt'] ) ) {
			$image_alt = wp_unslash( $post_data['_wp_attachment_image_alt'] );

			if ( get_post_meta( $post_id, '_wp_attachment_image_alt', true ) !== $image_alt ) {
				$image_alt = wp_strip_all_tags( $image_alt, true );

				// update_post_meta() expects slashed.
				update_post_meta( $post_id, '_wp_attachment_image_alt', wp_slash( $image_alt ) );
			}
		}

		$attachment_data = isset( $post_data['attachments'][ $post_id ] ) ? $post_data['attachments'][ $post_id ] : array();

		/** This filter is documented in wp-admin/includes/media.php */
		$translated = apply_filters( 'attachment_fields_to_save', $translated, $attachment_data );
	}

	// Convert taxonomy input to term IDs, to avoid ambiguity.
	if ( isset( $post_data['tax_input'] ) ) {
		foreach ( (array) $post_data['tax_input'] as $taxonomy => $terms ) {
			$tax_object = get_taxonomy( $taxonomy );

			if ( $tax_object && isset( $tax_object->meta_box_sanitize_cb ) ) {
				$translated['tax_input'][ $taxonomy ] = call_user_func_array( $tax_object->meta_box_sanitize_cb, array( $taxonomy, $terms ) );
			}
		}
	}

	add_meta( $post_id );

	update_post_meta( $post_id, '_edit_last', get_current_user_id() );

	$success = wp_update_post( $translated );

	// If the save failed, see if we can confidence check the main fields and try again.
	if ( ! $success && is_callable( array( $wpdb, 'strip_invalid_text_for_column' ) ) ) {
		$fields = array( 'post_title', 'post_content', 'post_excerpt' );

		foreach ( $fields as $field ) {
			if ( isset( $translated[ $field ] ) ) {
				$translated[ $field ] = $wpdb->strip_invalid_text_for_column( $wpdb->posts, $field, $translated[ $field ] );
			}
		}

		wp_update_post( $translated );
	}

	// Now that we have an ID we can fix any attachment anchor hrefs.
	_fix_attachment_links( $post_id );

	wp_set_post_lock( $post_id );

	if ( current_user_can( $ptype->cap->edit_others_posts ) && current_user_can( $ptype->cap->publish_posts ) ) {
		if ( ! empty( $post_data['sticky'] ) ) {
			stick_post( $post_id );
		} else {
			unstick_post( $post_id );
		}
	}

	return $post_id;
}

/**
 * Processes the post data for the bulk editing of posts.
 *
 * Updates all bulk edited posts/pages, adding (but not removing) tags and
 * categories. Skips pages when they would be their own parent or child.
 *
 * @since 2.7.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param array|null $post_data Optional. The array of post data to process.
 *                              Defaults to the `$_POST` superglobal.
 * @return array {
 *     An array of updated, skipped, and locked post IDs.
 *
 *     @type int[] $updated An array of updated post IDs.
 *     @type int[] $skipped An array of skipped post IDs.
 *     @type int[] $locked  An array of locked post IDs.
 * }
 */
function bulk_edit_posts( $post_data = null ) {
	global $wpdb;

	if ( empty( $post_data ) ) {
		$post_data = &$_POST;
	}

	if ( isset( $post_data['post_type'] ) ) {
		$ptype = get_post_type_object( $post_data['post_type'] );
	} else {
		$ptype = get_post_type_object( 'post' );
	}

	if ( ! current_user_can( $ptype->cap->edit_posts ) ) {
		if ( 'page' === $ptype->name ) {
			wp_die( __( 'Sorry, you are not allowed to edit pages.' ) );
		} else {
			wp_die( __( 'Sorry, you are not allowed to edit posts.' ) );
		}
	}

	if ( '-1' === $post_data['_status'] ) {
		$post_data['post_status'] = null;
		unset( $post_data['post_status'] );
	} else {
		$post_data['post_status'] = $post_data['_status'];
	}
	unset( $post_data['_status'] );

	if ( ! empty( $post_data['post_status'] ) ) {
		$post_data['post_status'] = sanitize_key( $post_data['post_status'] );

		if ( 'inherit' === $post_data['post_status'] ) {
			unset( $post_data['post_status'] );
		}
	}

	$post_ids = array_map( 'intval', (array) $post_data['post'] );

	$reset = array(
		'post_author',
		'post_status',
		'post_password',
		'post_parent',
		'page_template',
		'comment_status',
		'ping_status',
		'keep_private',
		'tax_input',
		'post_category',
		'sticky',
		'post_format',
	);

	foreach ( $reset as $field ) {
		if ( isset( $post_data[ $field ] ) && ( '' === $post_data[ $field ] || '-1' === $post_data[ $field ] ) ) {
			unset( $post_data[ $field ] );
		}
	}

	if ( isset( $post_data['post_category'] ) ) {
		if ( is_array( $post_data['post_category'] ) && ! empty( $post_data['post_category'] ) ) {
			$new_cats = array_map( 'absint', $post_data['post_category'] );
		} else {
			unset( $post_data['post_category'] );
		}
	}

	$tax_input = array();
	if ( isset( $post_data['tax_input'] ) ) {
		foreach ( $post_data['tax_input'] as $tax_name => $terms ) {
			if ( empty( $terms ) ) {
				continue;
			}

			if ( is_taxonomy_hierarchical( $tax_name ) ) {
				$tax_input[ $tax_name ] = array_map( 'absint', $terms );
			} else {
				$comma = _x( ',', 'tag delimiter' );
				if ( ',' !== $comma ) {
					$terms = str_replace( $comma, ',', $terms );
				}
				$tax_input[ $tax_name ] = explode( ',', trim( $terms, " \n\t\r\0\x0B," ) );
			}
		}
	}

	if ( isset( $post_data['post_parent'] ) && (int) $post_data['post_parent'] ) {
		$parent   = (int) $post_data['post_parent'];
		$pages    = $wpdb->get_results( "SELECT ID, post_parent FROM $wpdb->posts WHERE post_type = 'page'" );
		$children = array();

		for ( $i = 0; $i < 50 && $parent > 0; $i++ ) {
			$children[] = $parent;

			foreach ( $pages as $page ) {
				if ( (int) $page->ID === $parent ) {
					$parent = (int) $page->post_parent;
					break;
				}
			}
		}
	}

	$updated          = array();
	$skipped          = array();
	$locked           = array();
	$shared_post_data = $post_data;

	foreach ( $post_ids as $post_id ) {
		// Start with fresh post data with each iteration.
		$post_data = $shared_post_data;

		$post_type_object = get_post_type_object( get_post_type( $post_id ) );

		if ( ! isset( $post_type_object )
			|| ( isset( $children ) && in_array( $post_id, $children, true ) )
			|| ! current_user_can( 'edit_post', $post_id )
		) {
			$skipped[] = $post_id;
			continue;
		}

		if ( wp_check_post_lock( $post_id ) ) {
			$locked[] = $post_id;
			continue;
		}

		$post      = get_post( $post_id );
		$tax_names = get_object_taxonomies( $post );

		foreach ( $tax_names as $tax_name ) {
			$taxonomy_obj = get_taxonomy( $tax_name );

			if ( ! $taxonomy_obj->show_in_quick_edit ) {
				continue;
			}

			if ( isset( $tax_input[ $tax_name ] ) && current_user_can( $taxonomy_obj->cap->assign_terms ) ) {
				$new_terms = $tax_input[ $tax_name ];
			} else {
				$new_terms = array();
			}

			if ( $taxonomy_obj->hierarchical ) {
				$current_terms = (array) wp_get_object_terms( $post_id, $tax_name, array( 'fields' => 'ids' ) );
			} else {
				$current_terms = (array) wp_get_object_terms( $post_id, $tax_name, array( 'fields' => 'names' ) );
			}

			$post_data['tax_input'][ $tax_name ] = array_merge( $current_terms, $new_terms );
		}

		if ( isset( $new_cats ) && in_array( 'category', $tax_names, true ) ) {
			$cats = (array) wp_get_post_categories( $post_id );

			if (
				isset( $post_data['indeterminate_post_category'] )
				&& is_array( $post_data['indeterminate_post_category'] )
			) {
				$indeterminate_post_category = $post_data['indeterminate_post_category'];
			} else {
				$indeterminate_post_category = array();
			}

			$indeterminate_cats         = array_intersect( $cats, $indeterminate_post_category );
			$determinate_cats           = array_diff( $new_cats, $indeterminate_post_category );
			$post_data['post_category'] = array_unique( array_merge( $indeterminate_cats, $determinate_cats ) );

			unset( $post_data['tax_input']['category'] );
		}

		$post_data['post_ID']        = $post_id;
		$post_data['post_type']      = $post->post_type;
		$post_data['post_mime_type'] = $post->post_mime_type;

		foreach ( array( 'comment_status', 'ping_status', 'post_author' ) as $field ) {
			if ( ! isset( $post_data[ $field ] ) ) {
				$post_data[ $field ] = $post->$field;
			}
		}

		$post_data = _wp_translate_postdata( true, $post_data );
		if ( is_wp_error( $post_data ) ) {
			$skipped[] = $post_id;
			continue;
		}
		$post_data = _wp_get_allowed_postdata( $post_data );

		if ( isset( $shared_post_data['post_format'] ) ) {
			set_post_format( $post_id, $shared_post_data['post_format'] );
		}

		// Prevent wp_insert_post() from overwriting post format with the old data.
		unset( $post_data['tax_input']['post_format'] );

		// Reset post date of scheduled post to be published.
		if (
			in_array( $post->post_status, array( 'future', 'draft' ), true ) &&
			'publish' === $post_data['post_status']
		) {
			$post_data['post_date']     = current_time( 'mysql' );
			$post_data['post_date_gmt'] = '';
		}

		$post_id = wp_update_post( $post_data );
		update_post_meta( $post_id, '_edit_last', get_current_user_id() );
		$updated[] = $post_id;

		if ( isset( $post_data['sticky'] ) && current_user_can( $ptype->cap->edit_others_posts ) ) {
			if ( 'sticky' === $post_data['sticky'] ) {
				stick_post( $post_id );
			} else {
				unstick_post( $post_id );
			}
		}
	}

	/**
	 * Fires after processing the post data for bulk edit.
	 *
	 * @since 6.3.0
	 *
	 * @param int[] $updated          An array of updated post IDs.
	 * @param array $shared_post_data Associative array containing the post data.
	 */
	do_action( 'bulk_edit_posts', $updated, $shared_post_data );

	return array(
		'updated' => $updated,
		'skipped' => $skipped,
		'locked'  => $locked,
	);
}

/**
 * Returns default post information to use when populating the "Write Post" form.
 *
 * @since 2.0.0
 *
 * @param string $post_type    Optional. A post type string. Default 'post'.
 * @param bool   $create_in_db Optional. Whether to insert the post into database. Default false.
 * @return WP_Post Post object containing all the default post data as attributes
 */
function get_default_post_to_edit( $post_type = 'post', $create_in_db = false ) {
	$post_title = '';
	if ( ! empty( $_REQUEST['post_title'] ) ) {
		$post_title = esc_html( wp_unslash( $_REQUEST['post_title'] ) );
	}

	$post_content = '';
	if ( ! empty( $_REQUEST['content'] ) ) {
		$post_content = esc_html( wp_unslash( $_REQUEST['content'] ) );
	}

	$post_excerpt = '';
	if ( ! empty( $_REQUEST['excerpt'] ) ) {
		$post_excerpt = esc_html( wp_unslash( $_REQUEST['excerpt'] ) );
	}

	if ( $create_in_db ) {
		$post_id = wp_insert_post(
			array(
				'post_title'  => __( 'Auto Draft' ),
				'post_type'   => $post_type,
				'post_status' => 'auto-draft',
			),
			true,
			false
		);

		if ( is_wp_error( $post_id ) ) {
			wp_die( $post_id->get_error_message() );
		}

		$post = get_post( $post_id );

		if ( current_theme_supports( 'post-formats' ) && post_type_supports( $post->post_type, 'post-formats' ) && get_option( 'default_post_format' ) ) {
			set_post_format( $post, get_option( 'default_post_format' ) );
		}

		wp_after_insert_post( $post, false, null );

		// Schedule auto-draft cleanup.
		if ( ! wp_next_scheduled( 'wp_scheduled_auto_draft_delete' ) ) {
			wp_schedule_event( time(), 'daily', 'wp_scheduled_auto_draft_delete' );
		}
	} else {
		$post                 = new stdClass();
		$post->ID             = 0;
		$post->post_author    = '';
		$post->post_date      = '';
		$post->post_date_gmt  = '';
		$post->post_password  = '';
		$post->post_name      = '';
		$post->post_type      = $post_type;
		$post->post_status    = 'draft';
		$post->to_ping        = '';
		$post->pinged         = '';
		$post->comment_status = get_default_comment_status( $post_type );
		$post->ping_status    = get_default_comment_status( $post_type, 'pingback' );
		$post->post_pingback  = get_option( 'default_pingback_flag' );
		$post->post_category  = get_option( 'default_category' );
		$post->page_template  = 'default';
		$post->post_parent    = 0;
		$post->menu_order     = 0;
		$post                 = new WP_Post( $post );
	}

	/**
	 * Filters the default post content initially used in the "Write Post" form.
	 *
	 * @since 1.5.0
	 *
	 * @param string  $post_content Default post content.
	 * @param WP_Post $post         Post object.
	 */
	$post->post_content = (string) apply_filters( 'default_content', $post_content, $post );

	/**
	 * Filters the default post title initially used in the "Write Post" form.
	 *
	 * @since 1.5.0
	 *
	 * @param string  $post_title Default post title.
	 * @param WP_Post $post       Post object.
	 */
	$post->post_title = (string) apply_filters( 'default_title', $post_title, $post );

	/**
	 * Filters the default post excerpt initially used in the "Write Post" form.
	 *
	 * @since 1.5.0
	 *
	 * @param string  $post_excerpt Default post excerpt.
	 * @param WP_Post $post         Post object.
	 */
	$post->post_excerpt = (string) apply_filters( 'default_excerpt', $post_excerpt, $post );

	return $post;
}

/**
 * Determines if a post exists based on title, content, date and type.
 *
 * @since 2.0.0
 * @since 5.2.0 Added the `$type` parameter.
 * @since 5.8.0 Added the `$status` parameter.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param string $title   Post title.
 * @param string $content Optional. Post content.
 * @param string $date    Optional. Post date.
 * @param string $type    Optional. Post type.
 * @param string $status  Optional. Post status.
 * @return int Post ID if post exists, 0 otherwise.
 */
function post_exists( $title, $content = '', $date = '', $type = '', $status = '' ) {
	global $wpdb;

	$post_title   = wp_unslash( sanitize_post_field( 'post_title', $title, 0, 'db' ) );
	$post_content = wp_unslash( sanitize_post_field( 'post_content', $content, 0, 'db' ) );
	$post_date    = wp_unslash( sanitize_post_field( 'post_date', $date, 0, 'db' ) );
	$post_type    = wp_unslash( sanitize_post_field( 'post_type', $type, 0, 'db' ) );
	$post_status  = wp_unslash( sanitize_post_field( 'post_status', $status, 0, 'db' ) );

	$query = "SELECT ID FROM $wpdb->posts WHERE 1=1";
	$args  = array();

	if ( ! empty( $date ) ) {
		$query .= ' AND post_date = %s';
		$args[] = $post_date;
	}

	if ( ! empty( $title ) ) {
		$query .= ' AND post_title = %s';
		$args[] = $post_title;
	}

	if ( ! empty( $content ) ) {
		$query .= ' AND post_content = %s';
		$args[] = $post_content;
	}

	if ( ! empty( $type ) ) {
		$query .= ' AND post_type = %s';
		$args[] = $post_type;
	}

	if ( ! empty( $status ) ) {
		$query .= ' AND post_status = %s';
		$args[] = $post_status;
	}

	if ( ! empty( $args ) ) {
		return (int) $wpdb->get_var( $wpdb->prepare( $query, $args ) );
	}

	return 0;
}

/**
 * Creates a new post from the "Write Post" form using `$_POST` information.
 *
 * @since 2.1.0
 *
 * @global WP_User $current_user
 *
 * @return int|WP_Error Post ID on success, WP_Error on failure.
 */
function wp_write_post() {
	if ( isset( $_POST['post_type'] ) ) {
		$ptype = get_post_type_object( $_POST['post_type'] );
	} else {
		$ptype = get_post_type_object( 'post' );
	}

	if ( ! current_user_can( $ptype->cap->edit_posts ) ) {
		if ( 'page' === $ptype->name ) {
			return new WP_Error( 'edit_pages', __( 'Sorry, you are not allowed to create pages on this site.' ) );
		} else {
			return new WP_Error( 'edit_posts', __( 'Sorry, you are not allowed to create posts or drafts on this site.' ) );
		}
	}

	$_POST['post_mime_type'] = '';

	// Clear out any data in internal vars.
	unset( $_POST['filter'] );

	// Edit, don't write, if we have a post ID.
	if ( isset( $_POST['post_ID'] ) ) {
		return edit_post();
	}

	if ( isset( $_POST['visibility'] ) ) {
		switch ( $_POST['visibility'] ) {
			case 'public':
				$_POST['post_password'] = '';
				break;
			case 'password':
				unset( $_POST['sticky'] );
				break;
			case 'private':
				$_POST['post_status']   = 'private';
				$_POST['post_password'] = '';
				unset( $_POST['sticky'] );
				break;
		}
	}

	$translated = _wp_translate_postdata( false );
	if ( is_wp_error( $translated ) ) {
		return $translated;
	}
	$translated = _wp_get_allowed_postdata( $translated );

	// Create the post.
	$post_id = wp_insert_post( $translated );
	if ( is_wp_error( $post_id ) ) {
		return $post_id;
	}

	if ( empty( $post_id ) ) {
		return 0;
	}

	add_meta( $post_id );

	add_post_meta( $post_id, '_edit_last', $GLOBALS['current_user']->ID );

	// Now that we have an ID we can fix any attachment anchor hrefs.
	_fix_attachment_links( $post_id );

	wp_set_post_lock( $post_id );

	return $post_id;
}

/**
 * Calls wp_write_post() and handles the errors.
 *
 * @since 2.0.0
 *
 * @return int|void Post ID on success, void on failure.
 */
function write_post() {
	$result = wp_write_post();
	if ( is_wp_error( $result ) ) {
		wp_die( $result->get_error_message() );
	} else {
		return $result;
	}
}

//
// Post Meta.
//

/**
 * Adds post meta data defined in the `$_POST` superglobal for a post with given ID.
 *
 * @since 1.2.0
 *
 * @param int $post_id
 * @return int|bool
 */
function add_meta( $post_id ) {
	$post_id = (int) $post_id;

	$metakeyselect = isset( $_POST['metakeyselect'] ) ? wp_unslash( trim( $_POST['metakeyselect'] ) ) : '';
	$metakeyinput  = isset( $_POST['metakeyinput'] ) ? wp_unslash( trim( $_POST['metakeyinput'] ) ) : '';
	$metavalue     = isset( $_POST['metavalue'] ) ? $_POST['metavalue'] : '';
	if ( is_string( $metavalue ) ) {
		$metavalue = trim( $metavalue );
	}

	if ( ( ( '#NONE#' !== $metakeyselect ) && ! empty( $metakeyselect ) ) || ! empty( $metakeyinput ) ) {
		/*
		 * We have a key/value pair. If both the select and the input
		 * for the key have data, the input takes precedence.
		 */
		if ( '#NONE#' !== $metakeyselect ) {
			$metakey = $metakeyselect;
		}

		if ( $metakeyinput ) {
			$metakey = $metakeyinput; // Default.
		}

		if ( is_protected_meta( $metakey, 'post' ) || ! current_user_can( 'add_post_meta', $post_id, $metakey ) ) {
			return false;
		}

		$metakey = wp_slash( $metakey );

		return add_post_meta( $post_id, $metakey, $metavalue );
	}

	return false;
}

/**
 * Deletes post meta data by meta ID.
 *
 * @since 1.2.0
 *
 * @param int $mid
 * @return bool
 */
function delete_meta( $mid ) {
	return delete_metadata_by_mid( 'post', $mid );
}

/**
 * Returns a list of previously defined keys.
 *
 * @since 1.2.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @return string[] Array of meta key names.
 */
function get_meta_keys() {
	global $wpdb;

	$keys = $wpdb->get_col(
		"SELECT meta_key
		FROM $wpdb->postmeta
		GROUP BY meta_key
		ORDER BY meta_key"
	);

	return $keys;
}

/**
 * Returns post meta data by meta ID.
 *
 * @since 2.1.0
 *
 * @param int $mid
 * @return object|bool
 */
function get_post_meta_by_id( $mid ) {
	return get_metadata_by_mid( 'post', $mid );
}

/**
 * Returns meta data for the given post ID.
 *
 * @since 1.2.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int $post_id A post ID.
 * @return array[] {
 *     Array of meta data arrays for the given post ID.
 *
 *     @type array ...$0 {
 *         Associative array of meta data.
 *
 *         @type string $meta_key   Meta key.
 *         @type mixed  $meta_value Meta value.
 *         @type string $meta_id    Meta ID as a numeric string.
 *         @type string $post_id    Post ID as a numeric string.
 *     }
 * }
 */
function has_meta( $post_id ) {
	global $wpdb;

	return $wpdb->get_results(
		$wpdb->prepare(
			"SELECT meta_key, meta_value, meta_id, post_id
			FROM $wpdb->postmeta WHERE post_id = %d
			ORDER BY meta_key,meta_id",
			$post_id
		),
		ARRAY_A
	);
}

/**
 * Updates post meta data by meta ID.
 *
 * @since 1.2.0
 *
 * @param int    $meta_id    Meta ID.
 * @param string $meta_key   Meta key. Expect slashed.
 * @param string $meta_value Meta value. Expect slashed.
 * @return bool
 */
function update_meta( $meta_id, $meta_key, $meta_value ) {
	$meta_key   = wp_unslash( $meta_key );
	$meta_value = wp_unslash( $meta_value );

	return update_metadata_by_mid( 'post', $meta_id, $meta_value, $meta_key );
}

//
// Private.
//

/**
 * Replaces hrefs of attachment anchors with up-to-date permalinks.
 *
 * @since 2.3.0
 * @access private
 *
 * @param int|WP_Post $post Post ID or post object.
 * @return void|int|WP_Error Void if nothing fixed. 0 or WP_Error on update failure. The post ID on update success.
 */
function _fix_attachment_links( $post ) {
	$post    = get_post( $post, ARRAY_A );
	$content = $post['post_content'];

	// Don't run if no pretty permalinks or post is not published, scheduled, or privately published.
	if ( ! get_option( 'permalink_structure' ) || ! in_array( $post['post_status'], array( 'publish', 'future', 'private' ), true ) ) {
		return;
	}

	// Short if there aren't any links or no '?attachment_id=' strings (strpos cannot be zero).
	if ( ! strpos( $content, '?attachment_id=' ) || ! preg_match_all( '/<a ([^>]+)>[\s\S]+?<\/a>/', $content, $link_matches ) ) {
		return;
	}

	$site_url = get_bloginfo( 'url' );
	$site_url = substr( $site_url, (int) strpos( $site_url, '://' ) ); // Remove the http(s).
	$replace  = '';

	foreach ( $link_matches[1] as $key => $value ) {
		if ( ! strpos( $value, '?attachment_id=' ) || ! strpos( $value, 'wp-att-' )
			|| ! preg_match( '/href=(["\'])[^"\']*\?attachment_id=(\d+)[^"\']*\\1/', $value, $url_match )
			|| ! preg_match( '/rel=["\'][^"\']*wp-att-(\d+)/', $value, $rel_match ) ) {
				continue;
		}

		$quote  = $url_match[1]; // The quote (single or double).
		$url_id = (int) $url_match[2];
		$rel_id = (int) $rel_match[1];

		if ( ! $url_id || ! $rel_id || $url_id !== $rel_id || ! str_contains( $url_match[0], $site_url ) ) {
			continue;
		}

		$link    = $link_matches[0][ $key ];
		$replace = str_replace( $url_match[0], 'href=' . $quote . get_attachment_link( $url_id ) . $quote, $link );

		$content = str_replace( $link, $replace, $content );
	}

	if ( $replace ) {
		$post['post_content'] = $content;
		// Escape data pulled from DB.
		$post = add_magic_quotes( $post );

		return wp_update_post( $post );
	}
}

/**
 * Returns all the possible statuses for a post type.
 *
 * @since 2.5.0
 *
 * @param string $type The post_type you want the statuses for. Default 'post'.
 * @return string[] An array of all the statuses for the supplied post type.
 */
function get_available_post_statuses( $type = 'post' ) {
	$statuses = wp_count_posts( $type );

	return array_keys( get_object_vars( $statuses ) );
}

/**
 * Runs the query to fetch the posts for listing on the edit posts page.
 *
 * @since 2.5.0
 *
 * @param array|false $q Optional. Array of query variables to use to build the query.
 *                       Defaults to the `$_GET` superglobal.
 * @return string[] An array of all the statuses for the queried post type.
 */
function wp_edit_posts_query( $q = false ) {
	if ( false === $q ) {
		$q = $_GET;
	}

	$q['m']   = isset( $q['m'] ) ? (int) $q['m'] : 0;
	$q['cat'] = isset( $q['cat'] ) ? (int) $q['cat'] : 0;

	$post_statuses = get_post_stati();

	if ( isset( $q['post_type'] ) && in_array( $q['post_type'], get_post_types(), true ) ) {
		$post_type = $q['post_type'];
	} else {
		$post_type = 'post';
	}

	$avail_post_stati = get_available_post_statuses( $post_type );
	$post_status      = '';
	$perm             = '';

	if ( isset( $q['post_status'] ) && in_array( $q['post_status'], $post_statuses, true ) ) {
		$post_status = $q['post_status'];
		$perm        = 'readable';
	}

	$orderby = '';

	if ( isset( $q['orderby'] ) ) {
		$orderby = $q['orderby'];
	} elseif ( isset( $q['post_status'] ) && in_array( $q['post_status'], array( 'pending', 'draft' ), true ) ) {
		$orderby = 'modified';
	}

	$order = '';

	if ( isset( $q['order'] ) ) {
		$order = $q['order'];
	} elseif ( isset( $q['post_status'] ) && 'pending' === $q['post_status'] ) {
		$order = 'ASC';
	}

	$per_page       = "edit_{$post_type}_per_page";
	$posts_per_page = (int) get_user_option( $per_page );
	if ( empty( $posts_per_page ) || $posts_per_page < 1 ) {
		$posts_per_page = 20;
	}

	/**
	 * Filters the number of items per page to show for a specific 'per_page' type.
	 *
	 * The dynamic portion of the hook name, `$post_type`, refers to the post type.
	 *
	 * Possible hook names include:
	 *
	 *  - `edit_post_per_page`
	 *  - `edit_page_per_page`
	 *  - `edit_attachment_per_page`
	 *
	 * @since 3.0.0
	 *
	 * @param int $posts_per_page Number of posts to display per page for the given post
	 *                            type. Default 20.
	 */
	$posts_per_page = apply_filters( "edit_{$post_type}_per_page", $posts_per_page );

	/**
	 * Filters the number of posts displayed per page when specifically listing "posts".
	 *
	 * @since 2.8.0
	 *
	 * @param int    $posts_per_page Number of posts to be displayed. Default 20.
	 * @param string $post_type      The post type.
	 */
	$posts_per_page = apply_filters( 'edit_posts_per_page', $posts_per_page, $post_type );

	$query = compact( 'post_type', 'post_status', 'perm', 'order', 'orderby', 'posts_per_page' );

	// Hierarchical types require special args.
	if ( is_post_type_hierarchical( $post_type ) && empty( $orderby ) ) {
		$query['orderby']                = 'menu_order title';
		$query['order']                  = 'asc';
		$query['posts_per_page']         = -1;
		$query['posts_per_archive_page'] = -1;
		$query['fields']                 = 'id=>parent';
	}

	if ( ! empty( $q['show_sticky'] ) ) {
		$query['post__in'] = (array) get_option( 'sticky_posts' );
	}

	wp( $query );

	return $avail_post_stati;
}

/**
 * Returns the query variables for the current attachments request.
 *
 * @since 4.2.0
 *
 * @param array|false $q Optional. Array of query variables to use to build the query.
 *                       Defaults to the `$_GET` superglobal.
 * @return array The parsed query vars.
 */
function wp_edit_attachments_query_vars( $q = false ) {
	if ( false === $q ) {
		$q = $_GET;
	}
	$q['m']         = isset( $q['m'] ) ? (int) $q['m'] : 0;
	$q['cat']       = isset( $q['cat'] ) ? (int) $q['cat'] : 0;
	$q['post_type'] = 'attachment';
	$post_type      = get_post_type_object( 'attachment' );
	$states         = 'inherit';
	if ( current_user_can( $post_type->cap->read_private_posts ) ) {
		$states .= ',private';
	}

	$q['post_status'] = isset( $q['status'] ) && 'trash' === $q['status'] ? 'trash' : $states;
	$q['post_status'] = isset( $q['attachment-filter'] ) && 'trash' === $q['attachment-filter'] ? 'trash' : $states;

	$media_per_page = (int) get_user_option( 'upload_per_page' );
	if ( empty( $media_per_page ) || $media_per_page < 1 ) {
		$media_per_page = 20;
	}

	/**
	 * Filters the number of items to list per page when listing media items.
	 *
	 * @since 2.9.0
	 *
	 * @param int $media_per_page Number of media to list. Default 20.
	 */
	$q['posts_per_page'] = apply_filters( 'upload_per_page', $media_per_page );

	$post_mime_types = get_post_mime_types();
	if ( isset( $q['post_mime_type'] ) && ! array_intersect( (array) $q['post_mime_type'], array_keys( $post_mime_types ) ) ) {
		unset( $q['post_mime_type'] );
	}

	foreach ( array_keys( $post_mime_types ) as $type ) {
		if ( isset( $q['attachment-filter'] ) && "post_mime_type:$type" === $q['attachment-filter'] ) {
			$q['post_mime_type'] = $type;
			break;
		}
	}

	if ( isset( $q['detached'] ) || ( isset( $q['attachment-filter'] ) && 'detached' === $q['attachment-filter'] ) ) {
		$q['post_parent'] = 0;
	}

	if ( isset( $q['mine'] ) || ( isset( $q['attachment-filter'] ) && 'mine' === $q['attachment-filter'] ) ) {
		$q['author'] = get_current_user_id();
	}

	// Filter query clauses to include filenames.
	if ( isset( $q['s'] ) ) {
		add_filter( 'wp_allow_query_attachment_by_filename', '__return_true' );
	}

	return $q;
}

/**
 * Executes a query for attachments. An array of WP_Query arguments
 * can be passed in, which will override the arguments set by this function.
 *
 * @since 2.5.0
 *
 * @param array|false $q Optional. Array of query variables to use to build the query.
 *                       Defaults to the `$_GET` superglobal.
 * @return array {
 *     Array containing the post mime types and available post mime types.
 *
 *     @type array[]  $post_mime_types       Post mime types.
 *     @type string[] $avail_post_mime_types Available post mime types.
 * }
 */
function wp_edit_attachments_query( $q = false ) {
	wp( wp_edit_attachments_query_vars( $q ) );

	$post_mime_types       = get_post_mime_types();
	$avail_post_mime_types = get_available_post_mime_types( 'attachment' );

	return array( $post_mime_types, $avail_post_mime_types );
}

/**
 * Returns the list of classes to be used by a meta box.
 *
 * @since 2.5.0
 *
 * @param string $box_id    Meta box ID (used in the 'id' attribute for the meta box).
 * @param string $screen_id The screen on which the meta box is shown.
 * @return string Space-separated string of class names.
 */
function postbox_classes( $box_id, $screen_id ) {
	if ( isset( $_GET['edit'] ) && $_GET['edit'] === $box_id ) {
		$classes = array( '' );
	} elseif ( get_user_option( 'closedpostboxes_' . $screen_id ) ) {
		$closed = get_user_option( 'closedpostboxes_' . $screen_id );
		if ( ! is_array( $closed ) ) {
			$classes = array( '' );
		} else {
			$classes = in_array( $box_id, $closed, true ) ? array( 'closed' ) : array( '' );
		}
	} else {
		$classes = array( '' );
	}

	/**
	 * Filters the postbox classes for a specific screen and box ID combo.
	 *
	 * The dynamic portions of the hook name, `$screen_id` and `$box_id`, refer to
	 * the screen ID and meta box ID, respectively.
	 *
	 * @since 3.2.0
	 *
	 * @param string[] $classes An array of postbox classes.
	 */
	$classes = apply_filters( "postbox_classes_{$screen_id}_{$box_id}", $classes );

	return implode( ' ', $classes );
}

/**
 * Returns a sample permalink based on the post name.
 *
 * @since 2.5.0
 *
 * @param int|WP_Post $post  Post ID or post object.
 * @param string|null $title Optional. Title to override the post's current title
 *                           when generating the post name. Default null.
 * @param string|null $name  Optional. Name to override the post name. Default null.
 * @return array {
 *     Array containing the sample permalink with placeholder for the post name, and the post name.
 *
 *     @type string $0 The permalink with placeholder for the post name.
 *     @type string $1 The post name.
 * }
 */
function get_sample_permalink( $post, $title = null, $name = null ) {
	$post = get_post( $post );

	if ( ! $post ) {
		return array( '', '' );
	}

	$ptype = get_post_type_object( $post->post_type );

	$original_status = $post->post_status;
	$original_date   = $post->post_date;
	$original_name   = $post->post_name;
	$original_filter = $post->filter;

	// Hack: get_permalink() would return plain permalink for drafts, so we will fake that our post is published.
	if ( in_array( $post->post_status, array( 'auto-draft', 'draft', 'pending', 'future' ), true ) ) {
		$post->post_status = 'publish';
		$post->post_name   = sanitize_title( $post->post_name ? $post->post_name : $post->post_title, $post->ID );
	}

	/*
	 * If the user wants to set a new name -- override the current one.
	 * Note: if empty name is supplied -- use the title instead, see #6072.
	 */
	if ( ! is_null( $name ) ) {
		$post->post_name = sanitize_title( $name ? $name : $title, $post->ID );
	}

	$post->post_name = wp_unique_post_slug( $post->post_name, $post->ID, $post->post_status, $post->post_type, $post->post_parent );

	$post->filter = 'sample';

	$permalink = get_permalink( $post, true );

	// Replace custom post_type token with generic pagename token for ease of use.
	$permalink = str_replace( "%$post->post_type%", '%pagename%', $permalink );

	// Handle page hierarchy.
	if ( $ptype->hierarchical ) {
		$uri = get_page_uri( $post );
		if ( $uri ) {
			$uri = untrailingslashit( $uri );
			$uri = strrev( stristr( strrev( $uri ), '/' ) );
			$uri = untrailingslashit( $uri );
		}

		/** This filter is documented in wp-admin/edit-tag-form.php */
		$uri = apply_filters( 'editable_slug', $uri, $post );
		if ( ! empty( $uri ) ) {
			$uri .= '/';
		}
		$permalink = str_replace( '%pagename%', "{$uri}%pagename%", $permalink );
	}

	/** This filter is documented in wp-admin/edit-tag-form.php */
	$permalink         = array( $permalink, apply_filters( 'editable_slug', $post->post_name, $post ) );
	$post->post_status = $original_status;
	$post->post_date   = $original_date;
	$post->post_name   = $original_name;
	$post->filter      = $original_filter;

	/**
	 * Filters the sample permalink.
	 *
	 * @since 4.4.0
	 *
	 * @param array   $permalink {
	 *     Array containing the sample permalink with placeholder for the post name, and the post name.
	 *
	 *     @type string $0 The permalink with placeholder for the post name.
	 *     @type string $1 The post name.
	 * }
	 * @param int     $post_id Post ID.
	 * @param string  $title   Post title.
	 * @param string  $name    Post name (slug).
	 * @param WP_Post $post    Post object.
	 */
	return apply_filters( 'get_sample_permalink', $permalink, $post->ID, $title, $name, $post );
}

/**
 * Returns the HTML of the sample permalink slug editor.
 *
 * @since 2.5.0
 *
 * @param int|WP_Post $post      Post ID or post object.
 * @param string|null $new_title Optional. New title. Default null.
 * @param string|null $new_slug  Optional. New slug. Default null.
 * @return string The HTML of the sample permalink slug editor.
 */
function get_sample_permalink_html( $post, $new_title = null, $new_slug = null ) {
	$post = get_post( $post );

	if ( ! $post ) {
		return '';
	}

	list($permalink, $post_name) = get_sample_permalink( $post->ID, $new_title, $new_slug );

	$view_link      = false;
	$preview_target = '';

	if ( current_user_can( 'read_post', $post->ID ) ) {
		if ( 'draft' === $post->post_status || empty( $post->post_name ) ) {
			$view_link      = get_preview_post_link( $post );
			$preview_target = " target='wp-preview-{$post->ID}'";
		} else {
			if ( 'publish' === $post->post_status || 'attachment' === $post->post_type ) {
				$view_link = get_permalink( $post );
			} else {
				// Allow non-published (private, future) to be viewed at a pretty permalink, in case $post->post_name is set.
				$view_link = str_replace( array( '%pagename%', '%postname%' ), $post->post_name, $permalink );
			}
		}
	}

	// Permalinks without a post/page name placeholder don't have anything to edit.
	if ( ! str_contains( $permalink, '%postname%' ) && ! str_contains( $permalink, '%pagename%' ) ) {
		$return = '<strong>' . __( 'Permalink:' ) . "</strong>\n";

		if ( false !== $view_link ) {
			$display_link = urldecode( $view_link );
			$return      .= '<a id="sample-permalink" href="' . esc_url( $view_link ) . '"' . $preview_target . '>' . esc_html( $display_link ) . "</a>\n";
		} else {
			$return .= '<span id="sample-permalink">' . $permalink . "</span>\n";
		}

		// Encourage a pretty permalink setting.
		if ( ! get_option( 'permalink_structure' ) && current_user_can( 'manage_options' )
			&& ! ( 'page' === get_option( 'show_on_front' ) && (int) get_option( 'page_on_front' ) === $post->ID )
		) {
			$return .= '<span id="change-permalinks"><a href="options-permalink.php" class="button button-small">' . __( 'Change Permalink Structure' ) . "</a></span>\n";
		}
	} else {
		if ( mb_strlen( $post_name ) > 34 ) {
			$post_name_abridged = mb_substr( $post_name, 0, 16 ) . '&hellip;' . mb_substr( $post_name, -16 );
		} else {
			$post_name_abridged = $post_name;
		}

		$post_name_html = '<span id="editable-post-name">' . esc_html( $post_name_abridged ) . '</span>';
		$display_link   = str_replace( array( '%pagename%', '%postname%' ), $post_name_html, esc_html( urldecode( $permalink ) ) );

		$return  = '<strong>' . __( 'Permalink:' ) . "</strong>\n";
		$return .= '<span id="sample-permalink"><a href="' . esc_url( $view_link ) . '"' . $preview_target . '>' . $display_link . "</a></span>\n";
		$return .= '&lrm;'; // Fix bi-directional text display defect in RTL languages.
		$return .= '<span id="edit-slug-buttons"><button type="button" class="edit-slug button button-small hide-if-no-js" aria-label="' . __( 'Edit permalink' ) . '">' . __( 'Edit' ) . "</button></span>\n";
		$return .= '<span id="editable-post-name-full">' . esc_html( $post_name ) . "</span>\n";
	}

	/**
	 * Filters the sample permalink HTML markup.
	 *
	 * @since 2.9.0
	 * @since 4.4.0 Added `$post` parameter.
	 *
	 * @param string      $return    Sample permalink HTML markup.
	 * @param int         $post_id   Post ID.
	 * @param string|null $new_title New sample permalink title.
	 * @param string|null $new_slug  New sample permalink slug.
	 * @param WP_Post     $post      Post object.
	 */
	$return = apply_filters( 'get_sample_permalink_html', $return, $post->ID, $new_title, $new_slug, $post );

	return $return;
}

/**
 * Returns HTML for the post thumbnail meta box.
 *
 * @since 2.9.0
 *
 * @param int|null         $thumbnail_id Optional. Thumbnail attachment ID. Default null.
 * @param int|WP_Post|null $post         Optional. The post ID or object associated
 *                                       with the thumbnail. Defaults to global $post.
 * @return string The post thumbnail HTML.
 */
function _wp_post_thumbnail_html( $thumbnail_id = null, $post = null ) {
	$_wp_additional_image_sizes = wp_get_additional_image_sizes();

	$post               = get_post( $post );
	$post_type_object   = get_post_type_object( $post->post_type );
	$set_thumbnail_link = '<p class="hide-if-no-js"><a href="%s" id="set-post-thumbnail"%s class="thickbox">%s</a></p>';
	$upload_iframe_src  = get_upload_iframe_src( 'image', $post->ID );

	$content = sprintf(
		$set_thumbnail_link,
		esc_url( $upload_iframe_src ),
		'', // Empty when there's no featured image set, `aria-describedby` attribute otherwise.
		esc_html( $post_type_object->labels->set_featured_image )
	);

	if ( $thumbnail_id && get_post( $thumbnail_id ) ) {
		$size = isset( $_wp_additional_image_sizes['post-thumbnail'] ) ? 'post-thumbnail' : array( 266, 266 );

		/**
		 * Filters the size used to display the post thumbnail image in the 'Featured image' meta box.
		 *
		 * Note: When a theme adds 'post-thumbnail' support, a special 'post-thumbnail'
		 * image size is registered, which differs from the 'thumbnail' image size
		 * managed via the Settings > Media screen.
		 *
		 * @since 4.4.0
		 *
		 * @param string|int[] $size         Requested image size. Can be any registered image size name, or
		 *                                   an array of width and height values in pixels (in that order).
		 * @param int          $thumbnail_id Post thumbnail attachment ID.
		 * @param WP_Post      $post         The post object associated with the thumbnail.
		 */
		$size = apply_filters( 'admin_post_thumbnail_size', $size, $thumbnail_id, $post );

		$thumbnail_html = wp_get_attachment_image( $thumbnail_id, $size );

		if ( ! empty( $thumbnail_html ) ) {
			$content  = sprintf(
				$set_thumbnail_link,
				esc_url( $upload_iframe_src ),
				' aria-describedby="set-post-thumbnail-desc"',
				$thumbnail_html
			);
			$content .= '<p class="hide-if-no-js howto" id="set-post-thumbnail-desc">' . __( 'Click the image to edit or update' ) . '</p>';
			$content .= '<p class="hide-if-no-js"><a href="#" id="remove-post-thumbnail">' . esc_html( $post_type_object->labels->remove_featured_image ) . '</a></p>';
		}
	}

	$content .= '<input type="hidden" id="_thumbnail_id" name="_thumbnail_id" value="' . esc_attr( $thumbnail_id ? $thumbnail_id : '-1' ) . '" />';

	/**
	 * Filters the admin post thumbnail HTML markup to return.
	 *
	 * @since 2.9.0
	 * @since 3.5.0 Added the `$post_id` parameter.
	 * @since 4.6.0 Added the `$thumbnail_id` parameter.
	 *
	 * @param string   $content      Admin post thumbnail HTML markup.
	 * @param int      $post_id      Post ID.
	 * @param int|null $thumbnail_id Thumbnail attachment ID, or null if there isn't one.
	 */
	return apply_filters( 'admin_post_thumbnail_html', $content, $post->ID, $thumbnail_id );
}

/**
 * Determines whether the post is currently being edited by another user.
 *
 * @since 2.5.0
 *
 * @param int|WP_Post $post ID or object of the post to check for editing.
 * @return int|false ID of the user with lock. False if the post does not exist, post is not locked,
 *                   the user with lock does not exist, or the post is locked by current user.
 */
function wp_check_post_lock( $post ) {
	$post = get_post( $post );

	if ( ! $post ) {
		return false;
	}

	$lock = get_post_meta( $post->ID, '_edit_lock', true );

	if ( ! $lock ) {
		return false;
	}

	$lock = explode( ':', $lock );
	$time = $lock[0];
	$user = isset( $lock[1] ) ? (int) $lock[1] : (int) get_post_meta( $post->ID, '_edit_last', true );

	if ( ! get_userdata( $user ) ) {
		return false;
	}

	/** This filter is documented in wp-admin/includes/ajax-actions.php */
	$time_window = apply_filters( 'wp_check_post_lock_window', 150 );

	if ( $time && $time > time() - $time_window && get_current_user_id() !== $user ) {
		return $user;
	}

	return false;
}

/**
 * Marks the post as currently being edited by the current user.
 *
 * @since 2.5.0
 *
 * @param int|WP_Post $post ID or object of the post being edited.
 * @return array|false {
 *     Array of the lock time and user ID. False if the post does not exist, or there
 *     is no current user.
 *
 *     @type int $0 The current time as a Unix timestamp.
 *     @type int $1 The ID of the current user.
 * }
 */
function wp_set_post_lock( $post ) {
	$post = get_post( $post );

	if ( ! $post ) {
		return false;
	}

	$user_id = get_current_user_id();

	if ( 0 === $user_id ) {
		return false;
	}

	$now  = time();
	$lock = "$now:$user_id";

	update_post_meta( $post->ID, '_edit_lock', $lock );

	return array( $now, $user_id );
}

/**
 * Outputs the HTML for the notice to say that someone else is editing or has taken over editing of this post.
 *
 * @since 2.8.5
 */
function _admin_notice_post_locked() {
	$post = get_post();

	if ( ! $post ) {
		return;
	}

	$user    = null;
	$user_id = wp_check_post_lock( $post->ID );

	if ( $user_id ) {
		$user = get_userdata( $user_id );
	}

	if ( $user ) {
		/**
		 * Filters whether to show the post locked dialog.
		 *
		 * Returning false from the filter will prevent the dialog from being displayed.
		 *
		 * @since 3.6.0
		 *
		 * @param bool    $display Whether to display the dialog. Default true.
		 * @param WP_Post $post    Post object.
		 * @param WP_User $user    The user with the lock for the post.
		 */
		if ( ! apply_filters( 'show_post_locked_dialog', true, $post, $user ) ) {
			return;
		}

		$locked = true;
	} else {
		$locked = false;
	}

	$sendback      = wp_get_referer();
	$sendback_text = __( 'Go back' );

	if ( ! $locked || ! $sendback || str_contains( $sendback, 'post.php' ) || str_contains( $sendback, 'post-new.php' ) ) {
		$sendback = admin_url( 'edit.php' );

		if ( 'post' !== $post->post_type ) {
			$sendback = add_query_arg( 'post_type', $post->post_type, $sendback );
		}

		$post_type_object = get_post_type_object( $post->post_type );

		if ( $post_type_object ) {
			$sendback_text = $post_type_object->labels->all_items;
		}
	}

	$hidden = $locked ? '' : ' hidden';

	?>
	<div id="post-lock-dialog" class="notification-dialog-wrap<?php echo $hidden; ?>">
	<div class="notification-dialog-background"></div>
	<div class="notification-dialog">
	<?php

	if ( $locked ) {
		$query_args = array();
		if ( get_post_type_object( $post->post_type )->public ) {
			if ( 'publish' === $post->post_status || $user->ID !== (int) $post->post_author ) {
				// Latest content is in autosave.
				$nonce                       = wp_create_nonce( 'post_preview_' . $post->ID );
				$query_args['preview_id']    = $post->ID;
				$query_args['preview_nonce'] = $nonce;
			}
		}

		$preview_link = get_preview_post_link( $post->ID, $query_args );

		/**
		 * Filters whether to allow the post lock to be overridden.
		 *
		 * Returning false from the filter will disable the ability
		 * to override the post lock.
		 *
		 * @since 3.6.0
		 *
		 * @param bool    $override Whether to allow the post lock to be overridden. Default true.
		 * @param WP_Post $post     Post object.
		 * @param WP_User $user     The user with the lock for the post.
		 */
		$override = apply_filters( 'override_post_lock', true, $post, $user );
		$tab_last = $override ? '' : ' wp-tab-last';

		?>
		<div class="post-locked-message">
		<div class="post-locked-avatar"><?php echo get_avatar( $user->ID, 64 ); ?></div>
		<p class="currently-editing wp-tab-first" tabindex="0">
		<?php
		if ( $override ) {
			/* translators: %s: User's display name. */
			printf( __( '%s is currently editing this post. Do you want to take over?' ), esc_html( $user->display_name ) );
		} else {
			/* translators: %s: User's display name. */
			printf( __( '%s is currently editing this post.' ), esc_html( $user->display_name ) );
		}
		?>
		</p>
		<?php
		/**
		 * Fires inside the post locked dialog before the buttons are displayed.
		 *
		 * @since 3.6.0
		 * @since 5.4.0 The $user parameter was added.
		 *
		 * @param WP_Post $post Post object.
		 * @param WP_User $user The user with the lock for the post.
		 */
		do_action( 'post_locked_dialog', $post, $user );
		?>
		<p>
		<a class="button" href="<?php echo esc_url( $sendback ); ?>"><?php echo $sendback_text; ?></a>
		<?php if ( $preview_link ) { ?>
		<a class="button<?php echo $tab_last; ?>" href="<?php echo esc_url( $preview_link ); ?>"><?php _e( 'Preview' ); ?></a>
			<?php
		}

		// Allow plugins to prevent some users overriding the post lock.
		if ( $override ) {
			?>
	<a class="button button-primary wp-tab-last" href="<?php echo esc_url( add_query_arg( 'get-post-lock', '1', wp_nonce_url( get_edit_post_link( $post->ID, 'url' ), 'lock-post_' . $post->ID ) ) ); ?>"><?php _e( 'Take over' ); ?></a>
			<?php
		}

		?>
		</p>
		</div>
		<?php
	} else {
		?>
		<div class="post-taken-over">
			<div class="post-locked-avatar"></div>
			<p class="wp-tab-first" tabindex="0">
			<span class="currently-editing"></span><br />
			<span class="locked-saving hidden"><img src="<?php echo esc_url( admin_url( 'images/spinner-2x.gif' ) ); ?>" width="16" height="16" alt="" /> <?php _e( 'Saving revision&hellip;' ); ?></span>
			<span class="locked-saved hidden"><?php _e( 'Your latest changes were saved as a revision.' ); ?></span>
			</p>
			<?php
			/**
			 * Fires inside the dialog displayed when a user has lost the post lock.
			 *
			 * @since 3.6.0
			 *
			 * @param WP_Post $post Post object.
			 */
			do_action( 'post_lock_lost_dialog', $post );
			?>
			<p><a class="button button-primary wp-tab-last" href="<?php echo esc_url( $sendback ); ?>"><?php echo $sendback_text; ?></a></p>
		</div>
		<?php
	}

	?>
	</div>
	</div>
	<?php
}

/**
 * Creates autosave data for the specified post from `$_POST` data.
 *
 * @since 2.6.0
 *
 * @param array|int $post_data Associative array containing the post data, or integer post ID.
 *                             If a numeric post ID is provided, will use the `$_POST` superglobal.
 * @return int|WP_Error The autosave revision ID. WP_Error or 0 on error.
 */
function wp_create_post_autosave( $post_data ) {
	if ( is_numeric( $post_data ) ) {
		$post_id   = $post_data;
		$post_data = $_POST;
	} else {
		$post_id = (int) $post_data['post_ID'];
	}

	$post_data = _wp_translate_postdata( true, $post_data );
	if ( is_wp_error( $post_data ) ) {
		return $post_data;
	}
	$post_data = _wp_get_allowed_postdata( $post_data );

	$post_author = get_current_user_id();

	// Store one autosave per author. If there is already an autosave, overwrite it.
	$old_autosave = wp_get_post_autosave( $post_id, $post_author );
	if ( $old_autosave ) {
		$new_autosave                = _wp_post_revision_data( $post_data, true );
		$new_autosave['ID']          = $old_autosave->ID;
		$new_autosave['post_author'] = $post_author;

		$post = get_post( $post_id );

		// If the new autosave has the same content as the post, delete the autosave.
		$autosave_is_different = false;
		foreach ( array_intersect( array_keys( $new_autosave ), array_keys( _wp_post_revision_fields( $post ) ) ) as $field ) {
			if ( normalize_whitespace( $new_autosave[ $field ] ) !== normalize_whitespace( $post->$field ) ) {
				$autosave_is_different = true;
				break;
			}
		}

		if ( ! $autosave_is_different ) {
			wp_delete_post_revision( $old_autosave->ID );
			return 0;
		}

		/**
		 * Fires before an autosave is stored.
		 *
		 * @since 4.1.0
		 * @since 6.4.0 The `$is_update` parameter was added to indicate if the autosave is being updated or was newly created.
		 *
		 * @param array $new_autosave Post array - the autosave that is about to be saved.
		 * @param bool  $is_update    Whether this is an existing autosave.
		 */
		do_action( 'wp_creating_autosave', $new_autosave, true );
		return wp_update_post( $new_autosave );
	}

	// _wp_put_post_revision() expects unescaped.
	$post_data = wp_unslash( $post_data );

	// Otherwise create the new autosave as a special post revision.
	$revision = _wp_put_post_revision( $post_data, true );

	if ( ! is_wp_error( $revision ) && 0 !== $revision ) {

		/** This action is documented in wp-admin/includes/post.php */
		do_action( 'wp_creating_autosave', get_post( $revision, ARRAY_A ), false );
	}

	return $revision;
}

/**
 * Autosaves the revisioned meta fields.
 *
 * Iterates through the revisioned meta fields and checks each to see if they are set,
 * and have a changed value. If so, the meta value is saved and attached to the autosave.
 *
 * @since 6.4.0
 *
 * @param array $new_autosave The new post data being autosaved.
 */
function wp_autosave_post_revisioned_meta_fields( $new_autosave ) {
	/*
	 * The post data arrives as either $_POST['data']['wp_autosave'] or the $_POST
	 * itself. This sets $posted_data to the correct variable.
	 *
	 * Ignoring sanitization to avoid altering meta. Ignoring the nonce check because
	 * this is hooked on inner core hooks where a valid nonce was already checked.
	 */
	$posted_data = isset( $_POST['data']['wp_autosave'] ) ? $_POST['data']['wp_autosave'] : $_POST;

	$post_type = get_post_type( $new_autosave['post_parent'] );

	/*
	 * Go through the revisioned meta keys and save them as part of the autosave,
	 * if the meta key is part of the posted data, the meta value is not blank,
	 * and the meta value has changes from the last autosaved value.
	 */
	foreach ( wp_post_revision_meta_keys( $post_type ) as $meta_key ) {

		if ( isset( $posted_data[ $meta_key ] )
			&& get_post_meta( $new_autosave['ID'], $meta_key, true ) !== wp_unslash( $posted_data[ $meta_key ] )
		) {
			/*
			 * Use the underlying delete_metadata() and add_metadata() functions
			 * vs delete_post_meta() and add_post_meta() to make sure we're working
			 * with the actual revision meta.
			 */
			delete_metadata( 'post', $new_autosave['ID'], $meta_key );

			// One last check to ensure meta value is not empty.
			if ( ! empty( $posted_data[ $meta_key ] ) ) {
				// Add the revisions meta data to the autosave.
				add_metadata( 'post', $new_autosave['ID'], $meta_key, $posted_data[ $meta_key ] );
			}
		}
	}
}

/**
 * Saves a draft or manually autosaves for the purpose of showing a post preview.
 *
 * @since 2.7.0
 *
 * @return string URL to redirect to show the preview.
 */
function post_preview() {

	$post_id     = (int) $_POST['post_ID'];
	$_POST['ID'] = $post_id;

	$post = get_post( $post_id );

	if ( ! $post ) {
		wp_die( __( 'Sorry, you are not allowed to edit this post.' ) );
	}

	if ( ! current_user_can( 'edit_post', $post->ID ) ) {
		wp_die( __( 'Sorry, you are not allowed to edit this post.' ) );
	}

	$is_autosave = false;

	if ( ! wp_check_post_lock( $post->ID ) && get_current_user_id() === (int) $post->post_author
		&& ( 'draft' === $post->post_status || 'auto-draft' === $post->post_status )
	) {
		$saved_post_id = edit_post();
	} else {
		$is_autosave = true;

		if ( isset( $_POST['post_status'] ) && 'auto-draft' === $_POST['post_status'] ) {
			$_POST['post_status'] = 'draft';
		}

		$saved_post_id = wp_create_post_autosave( $post->ID );
	}

	if ( is_wp_error( $saved_post_id ) ) {
		wp_die( $saved_post_id->get_error_message() );
	}

	$query_args = array();

	if ( $is_autosave && $saved_post_id ) {
		$query_args['preview_id']    = $post->ID;
		$query_args['preview_nonce'] = wp_create_nonce( 'post_preview_' . $post->ID );

		if ( isset( $_POST['post_format'] ) ) {
			$query_args['post_format'] = empty( $_POST['post_format'] ) ? 'standard' : sanitize_key( $_POST['post_format'] );
		}

		if ( isset( $_POST['_thumbnail_id'] ) ) {
			$query_args['_thumbnail_id'] = ( (int) $_POST['_thumbnail_id'] <= 0 ) ? '-1' : (int) $_POST['_thumbnail_id'];
		}
	}

	return get_preview_post_link( $post, $query_args );
}

/**
 * Saves a post submitted with XHR.
 *
 * Intended for use with heartbeat and autosave.js
 *
 * @since 3.9.0
 *
 * @param array $post_data Associative array of the submitted post data.
 * @return mixed The value 0 or WP_Error on failure. The saved post ID on success.
 *               The ID can be the draft post_id or the autosave revision post_id.
 */
function wp_autosave( $post_data ) {
	// Back-compat.
	if ( ! defined( 'DOING_AUTOSAVE' ) ) {
		define( 'DOING_AUTOSAVE', true );
	}

	$post_id              = (int) $post_data['post_id'];
	$post_data['ID']      = $post_id;
	$post_data['post_ID'] = $post_id;

	if ( false === wp_verify_nonce( $post_data['_wpnonce'], 'update-post_' . $post_id ) ) {
		return new WP_Error( 'invalid_nonce', __( 'Error while saving.' ) );
	}

	$post = get_post( $post_id );

	if ( ! current_user_can( 'edit_post', $post->ID ) ) {
		return new WP_Error( 'edit_posts', __( 'Sorry, you are not allowed to edit this item.' ) );
	}

	if ( 'auto-draft' === $post->post_status ) {
		$post_data['post_status'] = 'draft';
	}

	if ( 'page' !== $post_data['post_type'] && ! empty( $post_data['catslist'] ) ) {
		$post_data['post_category'] = explode( ',', $post_data['catslist'] );
	}

	if ( ! wp_check_post_lock( $post->ID ) && get_current_user_id() === (int) $post->post_author
		&& ( 'auto-draft' === $post->post_status || 'draft' === $post->post_status )
	) {
		// Drafts and auto-drafts are just overwritten by autosave for the same user if the post is not locked.
		return edit_post( wp_slash( $post_data ) );
	} else {
		/*
		 * Non-drafts or other users' drafts are not overwritten.
		 * The autosave is stored in a special post revision for each user.
		 */
		return wp_create_post_autosave( wp_slash( $post_data ) );
	}
}

/**
 * Redirects to previous page.
 *
 * @since 2.7.0
 *
 * @param int $post_id Optional. Post ID.
 */
function redirect_post( $post_id = 0 ) {
	if ( isset( $_POST['save'] ) || isset( $_POST['publish'] ) ) {
		$status = get_post_status( $post_id );

		switch ( $status ) {
			case 'pending':
				$message = 8;
				break;
			case 'future':
				$message = 9;
				break;
			case 'draft':
				$message = 10;
				break;
			default:
				$message = isset( $_POST['publish'] ) ? 6 : 1;
				break;
		}

		$location = add_query_arg( 'message', $message, get_edit_post_link( $post_id, 'url' ) );
	} elseif ( isset( $_POST['addmeta'] ) && $_POST['addmeta'] ) {
		$location = add_query_arg( 'message', 2, wp_get_referer() );
		$location = explode( '#', $location );
		$location = $location[0] . '#postcustom';
	} elseif ( isset( $_POST['deletemeta'] ) && $_POST['deletemeta'] ) {
		$location = add_query_arg( 'message', 3, wp_get_referer() );
		$location = explode( '#', $location );
		$location = $location[0] . '#postcustom';
	} else {
		$location = add_query_arg( 'message', 4, get_edit_post_link( $post_id, 'url' ) );
	}

	/**
	 * Filters the post redirect destination URL.
	 *
	 * @since 2.9.0
	 *
	 * @param string $location The destination URL.
	 * @param int    $post_id  The post ID.
	 */
	wp_redirect( apply_filters( 'redirect_post_location', $location, $post_id ) );
	exit;
}

/**
 * Sanitizes POST values from a checkbox taxonomy metabox.
 *
 * @since 5.1.0
 *
 * @param string $taxonomy The taxonomy name.
 * @param array  $terms    Raw term data from the 'tax_input' field.
 * @return int[] Array of sanitized term IDs.
 */
function taxonomy_meta_box_sanitize_cb_checkboxes( $taxonomy, $terms ) {
	return array_map( 'intval', $terms );
}

/**
 * Sanitizes POST values from an input taxonomy metabox.
 *
 * @since 5.1.0
 *
 * @param string       $taxonomy The taxonomy name.
 * @param array|string $terms    Raw term data from the 'tax_input' field.
 * @return array
 */
function taxonomy_meta_box_sanitize_cb_input( $taxonomy, $terms ) {
	/*
	 * Assume that a 'tax_input' string is a comma-separated list of term names.
	 * Some languages may use a character other than a comma as a delimiter, so we standardize on
	 * commas before parsing the list.
	 */
	if ( ! is_array( $terms ) ) {
		$comma = _x( ',', 'tag delimiter' );
		if ( ',' !== $comma ) {
			$terms = str_replace( $comma, ',', $terms );
		}
		$terms = explode( ',', trim( $terms, " \n\t\r\0\x0B," ) );
	}

	$clean_terms = array();
	foreach ( $terms as $term ) {
		// Empty terms are invalid input.
		if ( empty( $term ) ) {
			continue;
		}

		$_term = get_terms(
			array(
				'taxonomy'   => $taxonomy,
				'name'       => $term,
				'fields'     => 'ids',
				'hide_empty' => false,
			)
		);

		if ( ! empty( $_term ) ) {
			$clean_terms[] = (int) $_term[0];
		} else {
			// No existing term was found, so pass the string. A new term will be created.
			$clean_terms[] = $term;
		}
	}

	return $clean_terms;
}

/**
 * Prepares server-registered blocks for the block editor.
 *
 * Returns an associative array of registered block data keyed by block name. Data includes properties
 * of a block relevant for client registration.
 *
 * @since 5.0.0
 * @since 6.3.0 Added `selectors` field.
 * @since 6.4.0 Added `block_hooks` field.
 *
 * @return array An associative array of registered block data.
 */
function get_block_editor_server_block_settings() {
	$block_registry = WP_Block_Type_Registry::get_instance();
	$blocks         = array();
	$fields_to_pick = array(
		'api_version'      => 'apiVersion',
		'title'            => 'title',
		'description'      => 'description',
		'icon'             => 'icon',
		'attributes'       => 'attributes',
		'provides_context' => 'providesContext',
		'uses_context'     => 'usesContext',
		'block_hooks'      => 'blockHooks',
		'selectors'        => 'selectors',
		'supports'         => 'supports',
		'category'         => 'category',
		'styles'           => 'styles',
		'textdomain'       => 'textdomain',
		'parent'           => 'parent',
		'ancestor'         => 'ancestor',
		'keywords'         => 'keywords',
		'example'          => 'example',
		'variations'       => 'variations',
		'allowed_blocks'   => 'allowedBlocks',
	);

	foreach ( $block_registry->get_all_registered() as $block_name => $block_type ) {
		foreach ( $fields_to_pick as $field => $key ) {
			if ( ! isset( $block_type->{ $field } ) ) {
				continue;
			}

			if ( ! isset( $blocks[ $block_name ] ) ) {
				$blocks[ $block_name ] = array();
			}

			$blocks[ $block_name ][ $key ] = $block_type->{ $field };
		}
	}

	return $blocks;
}

/**
 * Renders the meta boxes forms.
 *
 * @since 5.0.0
 *
 * @global WP_Post   $post           Global post object.
 * @global WP_Screen $current_screen WordPress current screen object.
 * @global array     $wp_meta_boxes  Global meta box state.
 */
function the_block_editor_meta_boxes() {
	global $post, $current_screen, $wp_meta_boxes;

	// Handle meta box state.
	$_original_meta_boxes = $wp_meta_boxes;

	/**
	 * Fires right before the meta boxes are rendered.
	 *
	 * This allows for the filtering of meta box data, that should already be
	 * present by this point. Do not use as a means of adding meta box data.
	 *
	 * @since 5.0.0
	 *
	 * @param array $wp_meta_boxes Global meta box state.
	 */
	$wp_meta_boxes = apply_filters( 'filter_block_editor_meta_boxes', $wp_meta_boxes );
	$locations     = array( 'side', 'normal', 'advanced' );
	$priorities    = array( 'high', 'sorted', 'core', 'default', 'low' );

	// Render meta boxes.
	?>
	<form class="metabox-base-form">
	<?php the_block_editor_meta_box_post_form_hidden_fields( $post ); ?>
	</form>
	<form id="toggle-custom-fields-form" method="post" action="<?php echo esc_url( admin_url( 'post.php' ) ); ?>">
		<?php wp_nonce_field( 'toggle-custom-fields', 'toggle-custom-fields-nonce' ); ?>
		<input type="hidden" name="action" value="toggle-custom-fields" />
	</form>
	<?php foreach ( $locations as $location ) : ?>
		<form class="metabox-location-<?php echo esc_attr( $location ); ?>" onsubmit="return false;">
			<div id="poststuff" class="sidebar-open">
				<div id="postbox-container-2" class="postbox-container">
					<?php
					do_meta_boxes(
						$current_screen,
						$location,
						$post
					);
					?>
				</div>
			</div>
		</form>
	<?php endforeach; ?>
	<?php

	$meta_boxes_per_location = array();
	foreach ( $locations as $location ) {
		$meta_boxes_per_location[ $location ] = array();

		if ( ! isset( $wp_meta_boxes[ $current_screen->id ][ $location ] ) ) {
			continue;
		}

		foreach ( $priorities as $priority ) {
			if ( ! isset( $wp_meta_boxes[ $current_screen->id ][ $location ][ $priority ] ) ) {
				continue;
			}

			$meta_boxes = (array) $wp_meta_boxes[ $current_screen->id ][ $location ][ $priority ];
			foreach ( $meta_boxes as $meta_box ) {
				if ( false === $meta_box || ! $meta_box['title'] ) {
					continue;
				}

				// If a meta box is just here for back compat, don't show it in the block editor.
				if ( isset( $meta_box['args']['__back_compat_meta_box'] ) && $meta_box['args']['__back_compat_meta_box'] ) {
					continue;
				}

				$meta_boxes_per_location[ $location ][] = array(
					'id'    => $meta_box['id'],
					'title' => $meta_box['title'],
				);
			}
		}
	}

	/*
	 * Sadly we probably cannot add this data directly into editor settings.
	 *
	 * Some meta boxes need `admin_head` to fire for meta box registry.
	 * `admin_head` fires after `admin_enqueue_scripts`, which is where we create
	 * our editor instance.
	 */
	$script = 'window._wpLoadBlockEditor.then( function() {
		wp.data.dispatch( \'core/edit-post\' ).setAvailableMetaBoxesPerLocation( ' . wp_json_encode( $meta_boxes_per_location, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) . ' );
	} );';

	wp_add_inline_script( 'wp-edit-post', $script );

	/*
	 * When `wp-edit-post` is output in the `<head>`, the inline script needs to be manually printed.
	 * Otherwise, meta boxes will not display because inline scripts for `wp-edit-post`
	 * will not be printed again after this point.
	 */
	if ( wp_script_is( 'wp-edit-post', 'done' ) ) {
		printf( "<script type='text/javascript'>\n%s\n</script>\n", trim( $script ) );
	}

	/*
	 * If the 'postcustom' meta box is enabled, then we need to perform
	 * some extra initialization on it.
	 */
	$enable_custom_fields = (bool) get_user_meta( get_current_user_id(), 'enable_custom_fields', true );

	if ( $enable_custom_fields ) {
		$script = "( function( $ ) {
			if ( $('#postcustom').length ) {
				$( '#the-list' ).wpList( {
					addBefore: function( s ) {
						s.data += '&post_id=$post->ID';
						return s;
					},
					addAfter: function() {
						$('table#list-table').show();
					}
				});
			}
		} )( jQuery );";
		wp_enqueue_script( 'wp-lists' );
		wp_add_inline_script( 'wp-lists', $script );
	}

	/*
	 * Refresh nonces used by the meta box loader.
	 *
	 * The logic is very similar to that provided by post.js for the classic editor.
	 */
	$script = "( function( $ ) {
		var check, timeout;

		function schedule() {
			check = false;
			window.clearTimeout( timeout );
			timeout = window.setTimeout( function() { check = true; }, 300000 );
		}

		$( document ).on( 'heartbeat-send.wp-refresh-nonces', function( e, data ) {
			var post_id, \$authCheck = $( '#wp-auth-check-wrap' );

			if ( check || ( \$authCheck.length && ! \$authCheck.hasClass( 'hidden' ) ) ) {
				if ( ( post_id = $( '#post_ID' ).val() ) && $( '#_wpnonce' ).val() ) {
					data['wp-refresh-metabox-loader-nonces'] = {
						post_id: post_id
					};
				}
			}
		}).on( 'heartbeat-tick.wp-refresh-nonces', function( e, data ) {
			var nonces = data['wp-refresh-metabox-loader-nonces'];

			if ( nonces ) {
				if ( nonces.replace ) {
					if ( nonces.replace.metabox_loader_nonce && window._wpMetaBoxUrl && wp.url ) {
						window._wpMetaBoxUrl= wp.url.addQueryArgs( window._wpMetaBoxUrl, { 'meta-box-loader-nonce': nonces.replace.metabox_loader_nonce } );
					}

					if ( nonces.replace._wpnonce ) {
						$( '#_wpnonce' ).val( nonces.replace._wpnonce );
					}
				}
			}
		}).ready( function() {
			schedule();
		});
	} )( jQuery );";
	wp_add_inline_script( 'heartbeat', $script );

	// Reset meta box data.
	$wp_meta_boxes = $_original_meta_boxes;
}

/**
 * Renders the hidden form required for the meta boxes form.
 *
 * @since 5.0.0
 *
 * @param WP_Post $post Current post object.
 */
function the_block_editor_meta_box_post_form_hidden_fields( $post ) {
	$form_extra = '';
	if ( 'auto-draft' === $post->post_status ) {
		$form_extra .= "<input type='hidden' id='auto_draft' name='auto_draft' value='1' />";
	}
	$form_action  = 'editpost';
	$nonce_action = 'update-post_' . $post->ID;
	$form_extra  .= "<input type='hidden' id='post_ID' name='post_ID' value='" . esc_attr( $post->ID ) . "' />";
	$referer      = wp_get_referer();
	$current_user = wp_get_current_user();
	$user_id      = $current_user->ID;
	wp_nonce_field( $nonce_action );

	/*
	 * Some meta boxes hook into these actions to add hidden input fields in the classic post form.
	 * For backward compatibility, we can capture the output from these actions,
	 * and extract the hidden input fields.
	 */
	ob_start();
	/** This filter is documented in wp-admin/edit-form-advanced.php */
	do_action( 'edit_form_after_title', $post );
	/** This filter is documented in wp-admin/edit-form-advanced.php */
	do_action( 'edit_form_advanced', $post );
	$classic_output = ob_get_clean();

	$classic_elements = wp_html_split( $classic_output );
	$hidden_inputs    = '';
	foreach ( $classic_elements as $element ) {
		if ( ! str_starts_with( $element, '<input ' ) ) {
			continue;
		}

		if ( preg_match( '/\stype=[\'"]hidden[\'"]\s/', $element ) ) {
			echo $element;
		}
	}
	?>
	<input type="hidden" id="user-id" name="user_ID" value="<?php echo (int) $user_id; ?>" />
	<input type="hidden" id="hiddenaction" name="action" value="<?php echo esc_attr( $form_action ); ?>" />
	<input type="hidden" id="originalaction" name="originalaction" value="<?php echo esc_attr( $form_action ); ?>" />
	<input type="hidden" id="post_type" name="post_type" value="<?php echo esc_attr( $post->post_type ); ?>" />
	<input type="hidden" id="original_post_status" name="original_post_status" value="<?php echo esc_attr( $post->post_status ); ?>" />
	<input type="hidden" id="referredby" name="referredby" value="<?php echo $referer ? esc_url( $referer ) : ''; ?>" />

	<?php
	if ( 'draft' !== get_post_status( $post ) ) {
		wp_original_referer_field( true, 'previous' );
	}
	echo $form_extra;
	wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false );
	wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
	// Permalink title nonce.
	wp_nonce_field( 'samplepermalink', 'samplepermalinknonce', false );

	/**
	 * Adds hidden input fields to the meta box save form.
	 *
	 * Hook into this action to print `<input type="hidden" ... />` fields, which will be POSTed back to
	 * the server when meta boxes are saved.
	 *
	 * @since 5.0.0
	 *
	 * @param WP_Post $post The post that is being edited.
	 */
	do_action( 'block_editor_meta_box_hidden_fields', $post );
}

/**
 * Disables block editor for wp_navigation type posts so they can be managed via the UI.
 *
 * @since 5.9.0
 * @access private
 *
 * @param bool   $value Whether the CPT supports block editor or not.
 * @param string $post_type Post type.
 * @return bool Whether the block editor should be disabled or not.
 */
function _disable_block_editor_for_navigation_post_type( $value, $post_type ) {
	if ( 'wp_navigation' === $post_type ) {
		return false;
	}

	return $value;
}

/**
 * This callback disables the content editor for wp_navigation type posts.
 * Content editor cannot handle wp_navigation type posts correctly.
 * We cannot disable the "editor" feature in the wp_navigation's CPT definition
 * because it disables the ability to save navigation blocks via REST API.
 *
 * @since 5.9.0
 * @access private
 *
 * @param WP_Post $post An instance of WP_Post class.
 */
function _disable_content_editor_for_navigation_post_type( $post ) {
	$post_type = get_post_type( $post );
	if ( 'wp_navigation' !== $post_type ) {
		return;
	}

	remove_post_type_support( $post_type, 'editor' );
}

/**
 * This callback enables content editor for wp_navigation type posts.
 * We need to enable it back because we disable it to hide
 * the content editor for wp_navigation type posts.
 *
 * @since 5.9.0
 * @access private
 *
 * @see _disable_content_editor_for_navigation_post_type
 *
 * @param WP_Post $post An instance of WP_Post class.
 */
function _enable_content_editor_for_navigation_post_type( $post ) {
	$post_type = get_post_type( $post );
	if ( 'wp_navigation' !== $post_type ) {
		return;
	}

	add_post_type_support( $post_type, 'editor' );
}
class-plugin-upgrader.php000064400000055624151212616040011477 0ustar00<?php
/**
 * Upgrade API: Plugin_Upgrader class
 *
 * @package WordPress
 * @subpackage Upgrader
 * @since 4.6.0
 */

/**
 * Core class used for upgrading/installing plugins.
 *
 * It is designed to upgrade/install plugins from a local zip, remote zip URL,
 * or uploaded zip file.
 *
 * @since 2.8.0
 * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader.php.
 *
 * @see WP_Upgrader
 */
class Plugin_Upgrader extends WP_Upgrader {

	/**
	 * Plugin upgrade result.
	 *
	 * @since 2.8.0
	 * @var array|WP_Error $result
	 *
	 * @see WP_Upgrader::$result
	 */
	public $result;

	/**
	 * Whether a bulk upgrade/installation is being performed.
	 *
	 * @since 2.9.0
	 * @var bool $bulk
	 */
	public $bulk = false;

	/**
	 * New plugin info.
	 *
	 * @since 5.5.0
	 * @var array $new_plugin_data
	 *
	 * @see check_package()
	 */
	public $new_plugin_data = array();

	/**
	 * Initializes the upgrade strings.
	 *
	 * @since 2.8.0
	 */
	public function upgrade_strings() {
		$this->strings['up_to_date'] = __( 'The plugin is at the latest version.' );
		$this->strings['no_package'] = __( 'Update package not available.' );
		/* translators: %s: Package URL. */
		$this->strings['downloading_package']  = sprintf( __( 'Downloading update from %s&#8230;' ), '<span class="code pre">%s</span>' );
		$this->strings['unpack_package']       = __( 'Unpacking the update&#8230;' );
		$this->strings['remove_old']           = __( 'Removing the old version of the plugin&#8230;' );
		$this->strings['remove_old_failed']    = __( 'Could not remove the old plugin.' );
		$this->strings['process_failed']       = __( 'Plugin update failed.' );
		$this->strings['process_success']      = __( 'Plugin updated successfully.' );
		$this->strings['process_bulk_success'] = __( 'Plugins updated successfully.' );
	}

	/**
	 * Initializes the installation strings.
	 *
	 * @since 2.8.0
	 */
	public function install_strings() {
		$this->strings['no_package'] = __( 'Installation package not available.' );
		/* translators: %s: Package URL. */
		$this->strings['downloading_package'] = sprintf( __( 'Downloading installation package from %s&#8230;' ), '<span class="code pre">%s</span>' );
		$this->strings['unpack_package']      = __( 'Unpacking the package&#8230;' );
		$this->strings['installing_package']  = __( 'Installing the plugin&#8230;' );
		$this->strings['remove_old']          = __( 'Removing the current plugin&#8230;' );
		$this->strings['remove_old_failed']   = __( 'Could not remove the current plugin.' );
		$this->strings['no_files']            = __( 'The plugin contains no files.' );
		$this->strings['process_failed']      = __( 'Plugin installation failed.' );
		$this->strings['process_success']     = __( 'Plugin installed successfully.' );
		/* translators: 1: Plugin name, 2: Plugin version. */
		$this->strings['process_success_specific'] = __( 'Successfully installed the plugin <strong>%1$s %2$s</strong>.' );

		if ( ! empty( $this->skin->overwrite ) ) {
			if ( 'update-plugin' === $this->skin->overwrite ) {
				$this->strings['installing_package'] = __( 'Updating the plugin&#8230;' );
				$this->strings['process_failed']     = __( 'Plugin update failed.' );
				$this->strings['process_success']    = __( 'Plugin updated successfully.' );
			}

			if ( 'downgrade-plugin' === $this->skin->overwrite ) {
				$this->strings['installing_package'] = __( 'Downgrading the plugin&#8230;' );
				$this->strings['process_failed']     = __( 'Plugin downgrade failed.' );
				$this->strings['process_success']    = __( 'Plugin downgraded successfully.' );
			}
		}
	}

	/**
	 * Install a plugin package.
	 *
	 * @since 2.8.0
	 * @since 3.7.0 The `$args` parameter was added, making clearing the plugin update cache optional.
	 *
	 * @param string $package The full local path or URI of the package.
	 * @param array  $args {
	 *     Optional. Other arguments for installing a plugin package. Default empty array.
	 *
	 *     @type bool $clear_update_cache Whether to clear the plugin updates cache if successful.
	 *                                    Default true.
	 * }
	 * @return bool|WP_Error True if the installation was successful, false or a WP_Error otherwise.
	 */
	public function install( $package, $args = array() ) {
		$defaults    = array(
			'clear_update_cache' => true,
			'overwrite_package'  => false, // Do not overwrite files.
		);
		$parsed_args = wp_parse_args( $args, $defaults );

		$this->init();
		$this->install_strings();

		add_filter( 'upgrader_source_selection', array( $this, 'check_package' ) );

		if ( $parsed_args['clear_update_cache'] ) {
			// Clear cache so wp_update_plugins() knows about the new plugin.
			add_action( 'upgrader_process_complete', 'wp_clean_plugins_cache', 9, 0 );
		}

		$this->run(
			array(
				'package'           => $package,
				'destination'       => WP_PLUGIN_DIR,
				'clear_destination' => $parsed_args['overwrite_package'],
				'clear_working'     => true,
				'hook_extra'        => array(
					'type'   => 'plugin',
					'action' => 'install',
				),
			)
		);

		remove_action( 'upgrader_process_complete', 'wp_clean_plugins_cache', 9 );
		remove_filter( 'upgrader_source_selection', array( $this, 'check_package' ) );

		if ( ! $this->result || is_wp_error( $this->result ) ) {
			return $this->result;
		}

		// Force refresh of plugin update information.
		wp_clean_plugins_cache( $parsed_args['clear_update_cache'] );

		if ( $parsed_args['overwrite_package'] ) {
			/**
			 * Fires when the upgrader has successfully overwritten a currently installed
			 * plugin or theme with an uploaded zip package.
			 *
			 * @since 5.5.0
			 *
			 * @param string  $package      The package file.
			 * @param array   $data         The new plugin or theme data.
			 * @param string  $package_type The package type ('plugin' or 'theme').
			 */
			do_action( 'upgrader_overwrote_package', $package, $this->new_plugin_data, 'plugin' );
		}

		return true;
	}

	/**
	 * Upgrades a plugin.
	 *
	 * @since 2.8.0
	 * @since 3.7.0 The `$args` parameter was added, making clearing the plugin update cache optional.
	 *
	 * @param string $plugin Path to the plugin file relative to the plugins directory.
	 * @param array  $args {
	 *     Optional. Other arguments for upgrading a plugin package. Default empty array.
	 *
	 *     @type bool $clear_update_cache Whether to clear the plugin updates cache if successful.
	 *                                    Default true.
	 * }
	 * @return bool|WP_Error True if the upgrade was successful, false or a WP_Error object otherwise.
	 */
	public function upgrade( $plugin, $args = array() ) {
		$defaults    = array(
			'clear_update_cache' => true,
		);
		$parsed_args = wp_parse_args( $args, $defaults );

		$this->init();
		$this->upgrade_strings();

		$current = get_site_transient( 'update_plugins' );
		if ( ! isset( $current->response[ $plugin ] ) ) {
			$this->skin->before();
			$this->skin->set_result( false );
			$this->skin->error( 'up_to_date' );
			$this->skin->after();
			return false;
		}

		// Get the URL to the zip file.
		$upgrade_data = $current->response[ $plugin ];

		add_filter( 'upgrader_pre_install', array( $this, 'deactivate_plugin_before_upgrade' ), 10, 2 );
		add_filter( 'upgrader_pre_install', array( $this, 'active_before' ), 10, 2 );
		add_filter( 'upgrader_clear_destination', array( $this, 'delete_old_plugin' ), 10, 4 );
		add_filter( 'upgrader_post_install', array( $this, 'active_after' ), 10, 2 );
		/*
		 * There's a Trac ticket to move up the directory for zips which are made a bit differently, useful for non-.org plugins.
		 * 'source_selection' => array( $this, 'source_selection' ),
		 */
		if ( $parsed_args['clear_update_cache'] ) {
			// Clear cache so wp_update_plugins() knows about the new plugin.
			add_action( 'upgrader_process_complete', 'wp_clean_plugins_cache', 9, 0 );
		}

		$this->run(
			array(
				'package'           => $upgrade_data->package,
				'destination'       => WP_PLUGIN_DIR,
				'clear_destination' => true,
				'clear_working'     => true,
				'hook_extra'        => array(
					'plugin'      => $plugin,
					'type'        => 'plugin',
					'action'      => 'update',
					'temp_backup' => array(
						'slug' => dirname( $plugin ),
						'src'  => WP_PLUGIN_DIR,
						'dir'  => 'plugins',
					),
				),
			)
		);

		// Cleanup our hooks, in case something else does an upgrade on this connection.
		remove_action( 'upgrader_process_complete', 'wp_clean_plugins_cache', 9 );
		remove_filter( 'upgrader_pre_install', array( $this, 'deactivate_plugin_before_upgrade' ) );
		remove_filter( 'upgrader_pre_install', array( $this, 'active_before' ) );
		remove_filter( 'upgrader_clear_destination', array( $this, 'delete_old_plugin' ) );
		remove_filter( 'upgrader_post_install', array( $this, 'active_after' ) );

		if ( ! $this->result || is_wp_error( $this->result ) ) {
			return $this->result;
		}

		// Force refresh of plugin update information.
		wp_clean_plugins_cache( $parsed_args['clear_update_cache'] );

		/*
		 * Ensure any future auto-update failures trigger a failure email by removing
		 * the last failure notification from the list when plugins update successfully.
		 */
		$past_failure_emails = get_option( 'auto_plugin_theme_update_emails', array() );

		if ( isset( $past_failure_emails[ $plugin ] ) ) {
			unset( $past_failure_emails[ $plugin ] );
			update_option( 'auto_plugin_theme_update_emails', $past_failure_emails );
		}

		return true;
	}

	/**
	 * Upgrades several plugins at once.
	 *
	 * @since 2.8.0
	 * @since 3.7.0 The `$args` parameter was added, making clearing the plugin update cache optional.
	 *
	 * @param string[] $plugins Array of paths to plugin files relative to the plugins directory.
	 * @param array    $args {
	 *     Optional. Other arguments for upgrading several plugins at once.
	 *
	 *     @type bool $clear_update_cache Whether to clear the plugin updates cache if successful. Default true.
	 * }
	 * @return array|false An array of results indexed by plugin file, or false if unable to connect to the filesystem.
	 */
	public function bulk_upgrade( $plugins, $args = array() ) {
		$wp_version = wp_get_wp_version();

		$defaults    = array(
			'clear_update_cache' => true,
		);
		$parsed_args = wp_parse_args( $args, $defaults );

		$this->init();
		$this->bulk = true;
		$this->upgrade_strings();

		$current = get_site_transient( 'update_plugins' );

		add_filter( 'upgrader_clear_destination', array( $this, 'delete_old_plugin' ), 10, 4 );

		$this->skin->header();

		// Connect to the filesystem first.
		$connected = $this->fs_connect( array( WP_CONTENT_DIR, WP_PLUGIN_DIR ) );
		if ( ! $connected ) {
			$this->skin->footer();
			return false;
		}

		$this->skin->bulk_header();

		/*
		 * Only start maintenance mode if:
		 * - running Multisite and there are one or more plugins specified, OR
		 * - a plugin with an update available is currently active.
		 * @todo For multisite, maintenance mode should only kick in for individual sites if at all possible.
		 */
		$maintenance = ( is_multisite() && ! empty( $plugins ) );
		foreach ( $plugins as $plugin ) {
			$maintenance = $maintenance || ( is_plugin_active( $plugin ) && isset( $current->response[ $plugin ] ) );
		}
		if ( $maintenance ) {
			$this->maintenance_mode( true );
		}

		$results = array();

		$this->update_count   = count( $plugins );
		$this->update_current = 0;
		foreach ( $plugins as $plugin ) {
			++$this->update_current;
			$this->skin->plugin_info = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin, false, true );

			if ( ! isset( $current->response[ $plugin ] ) ) {
				$this->skin->set_result( 'up_to_date' );
				$this->skin->before();
				$this->skin->feedback( 'up_to_date' );
				$this->skin->after();
				$results[ $plugin ] = true;
				continue;
			}

			// Get the URL to the zip file.
			$upgrade_data = $current->response[ $plugin ];

			$this->skin->plugin_active = is_plugin_active( $plugin );

			if ( isset( $upgrade_data->requires ) && ! is_wp_version_compatible( $upgrade_data->requires ) ) {
				$result = new WP_Error(
					'incompatible_wp_required_version',
					sprintf(
						/* translators: 1: Current WordPress version, 2: WordPress version required by the new plugin version. */
						__( 'Your WordPress version is %1$s, however the new plugin version requires %2$s.' ),
						$wp_version,
						$upgrade_data->requires
					)
				);

				$this->skin->before( $result );
				$this->skin->error( $result );
				$this->skin->after();
			} elseif ( isset( $upgrade_data->requires_php ) && ! is_php_version_compatible( $upgrade_data->requires_php ) ) {
				$result = new WP_Error(
					'incompatible_php_required_version',
					sprintf(
						/* translators: 1: Current PHP version, 2: PHP version required by the new plugin version. */
						__( 'The PHP version on your server is %1$s, however the new plugin version requires %2$s.' ),
						PHP_VERSION,
						$upgrade_data->requires_php
					)
				);

				$this->skin->before( $result );
				$this->skin->error( $result );
				$this->skin->after();
			} else {
				add_filter( 'upgrader_source_selection', array( $this, 'check_package' ) );
				$result = $this->run(
					array(
						'package'           => $upgrade_data->package,
						'destination'       => WP_PLUGIN_DIR,
						'clear_destination' => true,
						'clear_working'     => true,
						'is_multi'          => true,
						'hook_extra'        => array(
							'plugin'      => $plugin,
							'temp_backup' => array(
								'slug' => dirname( $plugin ),
								'src'  => WP_PLUGIN_DIR,
								'dir'  => 'plugins',
							),
						),
					)
				);
				remove_filter( 'upgrader_source_selection', array( $this, 'check_package' ) );
			}

			$results[ $plugin ] = $result;

			// Prevent credentials auth screen from displaying multiple times.
			if ( false === $result ) {
				break;
			}
		} // End foreach $plugins.

		$this->maintenance_mode( false );

		// Force refresh of plugin update information.
		wp_clean_plugins_cache( $parsed_args['clear_update_cache'] );

		/** This action is documented in wp-admin/includes/class-wp-upgrader.php */
		do_action(
			'upgrader_process_complete',
			$this,
			array(
				'action'  => 'update',
				'type'    => 'plugin',
				'bulk'    => true,
				'plugins' => $plugins,
			)
		);

		$this->skin->bulk_footer();

		$this->skin->footer();

		// Cleanup our hooks, in case something else does an upgrade on this connection.
		remove_filter( 'upgrader_clear_destination', array( $this, 'delete_old_plugin' ) );

		/*
		 * Ensure any future auto-update failures trigger a failure email by removing
		 * the last failure notification from the list when plugins update successfully.
		 */
		$past_failure_emails = get_option( 'auto_plugin_theme_update_emails', array() );

		foreach ( $results as $plugin => $result ) {
			// Maintain last failure notification when plugins failed to update manually.
			if ( ! $result || is_wp_error( $result ) || ! isset( $past_failure_emails[ $plugin ] ) ) {
				continue;
			}

			unset( $past_failure_emails[ $plugin ] );
		}

		update_option( 'auto_plugin_theme_update_emails', $past_failure_emails );

		return $results;
	}

	/**
	 * Checks that the source package contains a valid plugin.
	 *
	 * Hooked to the {@see 'upgrader_source_selection'} filter by Plugin_Upgrader::install().
	 *
	 * @since 3.3.0
	 *
	 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
	 *
	 * @param string $source The path to the downloaded package source.
	 * @return string|WP_Error The source as passed, or a WP_Error object on failure.
	 */
	public function check_package( $source ) {
		global $wp_filesystem;

		$wp_version            = wp_get_wp_version();
		$this->new_plugin_data = array();

		if ( is_wp_error( $source ) ) {
			return $source;
		}

		$working_directory = str_replace( $wp_filesystem->wp_content_dir(), trailingslashit( WP_CONTENT_DIR ), $source );
		if ( ! is_dir( $working_directory ) ) { // Confidence check, if the above fails, let's not prevent installation.
			return $source;
		}

		// Check that the folder contains at least 1 valid plugin.
		$files = glob( $working_directory . '*.php' );
		if ( $files ) {
			foreach ( $files as $file ) {
				$new_plugin_data = get_plugin_data( $file, false, false );
				if ( ! empty( $new_plugin_data['Name'] ) ) {
					$this->new_plugin_data = $new_plugin_data;
					break;
				}
			}
		}

		if ( empty( $this->new_plugin_data ) ) {
			return new WP_Error( 'incompatible_archive_no_plugins', $this->strings['incompatible_archive'], __( 'No valid plugins were found.' ) );
		}

		$requires_php = isset( $new_plugin_data['RequiresPHP'] ) ? $new_plugin_data['RequiresPHP'] : null;
		$requires_wp  = isset( $new_plugin_data['RequiresWP'] ) ? $new_plugin_data['RequiresWP'] : null;

		if ( ! is_php_version_compatible( $requires_php ) ) {
			$error = sprintf(
				/* translators: 1: Current PHP version, 2: Version required by the uploaded plugin. */
				__( 'The PHP version on your server is %1$s, however the uploaded plugin requires %2$s.' ),
				PHP_VERSION,
				$requires_php
			);

			return new WP_Error( 'incompatible_php_required_version', $this->strings['incompatible_archive'], $error );
		}

		if ( ! is_wp_version_compatible( $requires_wp ) ) {
			$error = sprintf(
				/* translators: 1: Current WordPress version, 2: Version required by the uploaded plugin. */
				__( 'Your WordPress version is %1$s, however the uploaded plugin requires %2$s.' ),
				$wp_version,
				$requires_wp
			);

			return new WP_Error( 'incompatible_wp_required_version', $this->strings['incompatible_archive'], $error );
		}

		return $source;
	}

	/**
	 * Retrieves the path to the file that contains the plugin info.
	 *
	 * This isn't used internally in the class, but is called by the skins.
	 *
	 * @since 2.8.0
	 *
	 * @return string|false The full path to the main plugin file, or false.
	 */
	public function plugin_info() {
		if ( ! is_array( $this->result ) ) {
			return false;
		}
		if ( empty( $this->result['destination_name'] ) ) {
			return false;
		}

		// Ensure to pass with leading slash.
		$plugin = get_plugins( '/' . $this->result['destination_name'] );
		if ( empty( $plugin ) ) {
			return false;
		}

		// Assume the requested plugin is the first in the list.
		$plugin_files = array_keys( $plugin );

		return $this->result['destination_name'] . '/' . $plugin_files[0];
	}

	/**
	 * Deactivates a plugin before it is upgraded.
	 *
	 * Hooked to the {@see 'upgrader_pre_install'} filter by Plugin_Upgrader::upgrade().
	 *
	 * @since 2.8.0
	 * @since 4.1.0 Added a return value.
	 *
	 * @param bool|WP_Error $response The installation response before the installation has started.
	 * @param array         $plugin   Plugin package arguments.
	 * @return bool|WP_Error The original `$response` parameter or WP_Error.
	 */
	public function deactivate_plugin_before_upgrade( $response, $plugin ) {

		if ( is_wp_error( $response ) ) { // Bypass.
			return $response;
		}

		// When in cron (background updates) don't deactivate the plugin, as we require a browser to reactivate it.
		if ( wp_doing_cron() ) {
			return $response;
		}

		$plugin = isset( $plugin['plugin'] ) ? $plugin['plugin'] : '';
		if ( empty( $plugin ) ) {
			return new WP_Error( 'bad_request', $this->strings['bad_request'] );
		}

		if ( is_plugin_active( $plugin ) ) {
			// Deactivate the plugin silently, Prevent deactivation hooks from running.
			deactivate_plugins( $plugin, true );
		}

		return $response;
	}

	/**
	 * Turns on maintenance mode before attempting to background update an active plugin.
	 *
	 * Hooked to the {@see 'upgrader_pre_install'} filter by Plugin_Upgrader::upgrade().
	 *
	 * @since 5.4.0
	 *
	 * @param bool|WP_Error $response The installation response before the installation has started.
	 * @param array         $plugin   Plugin package arguments.
	 * @return bool|WP_Error The original `$response` parameter or WP_Error.
	 */
	public function active_before( $response, $plugin ) {
		if ( is_wp_error( $response ) ) {
			return $response;
		}

		// Only enable maintenance mode when in cron (background update).
		if ( ! wp_doing_cron() ) {
			return $response;
		}

		$plugin = isset( $plugin['plugin'] ) ? $plugin['plugin'] : '';

		// Only run if plugin is active.
		if ( ! is_plugin_active( $plugin ) ) {
			return $response;
		}

		// Change to maintenance mode. Bulk edit handles this separately.
		if ( ! $this->bulk ) {
			$this->maintenance_mode( true );
		}

		return $response;
	}

	/**
	 * Turns off maintenance mode after upgrading an active plugin.
	 *
	 * Hooked to the {@see 'upgrader_post_install'} filter by Plugin_Upgrader::upgrade().
	 *
	 * @since 5.4.0
	 *
	 * @param bool|WP_Error $response The installation response after the installation has finished.
	 * @param array         $plugin   Plugin package arguments.
	 * @return bool|WP_Error The original `$response` parameter or WP_Error.
	 */
	public function active_after( $response, $plugin ) {
		if ( is_wp_error( $response ) ) {
			return $response;
		}

		// Only disable maintenance mode when in cron (background update).
		if ( ! wp_doing_cron() ) {
			return $response;
		}

		$plugin = isset( $plugin['plugin'] ) ? $plugin['plugin'] : '';

		// Only run if plugin is active.
		if ( ! is_plugin_active( $plugin ) ) {
			return $response;
		}

		// Time to remove maintenance mode. Bulk edit handles this separately.
		if ( ! $this->bulk ) {
			$this->maintenance_mode( false );
		}

		return $response;
	}

	/**
	 * Deletes the old plugin during an upgrade.
	 *
	 * Hooked to the {@see 'upgrader_clear_destination'} filter by
	 * Plugin_Upgrader::upgrade() and Plugin_Upgrader::bulk_upgrade().
	 *
	 * @since 2.8.0
	 *
	 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
	 *
	 * @param bool|WP_Error $removed            Whether the destination was cleared.
	 *                                          True on success, WP_Error on failure.
	 * @param string        $local_destination  The local package destination.
	 * @param string        $remote_destination The remote package destination.
	 * @param array         $plugin             Extra arguments passed to hooked filters.
	 * @return bool|WP_Error
	 */
	public function delete_old_plugin( $removed, $local_destination, $remote_destination, $plugin ) {
		global $wp_filesystem;

		if ( is_wp_error( $removed ) ) {
			return $removed; // Pass errors through.
		}

		$plugin = isset( $plugin['plugin'] ) ? $plugin['plugin'] : '';
		if ( empty( $plugin ) ) {
			return new WP_Error( 'bad_request', $this->strings['bad_request'] );
		}

		$plugins_dir     = $wp_filesystem->wp_plugins_dir();
		$this_plugin_dir = trailingslashit( dirname( $plugins_dir . $plugin ) );

		if ( ! $wp_filesystem->exists( $this_plugin_dir ) ) { // If it's already vanished.
			return $removed;
		}

		/*
		 * If plugin is in its own directory, recursively delete the directory.
		 * Base check on if plugin includes directory separator AND that it's not the root plugin folder.
		 */
		if ( strpos( $plugin, '/' ) && $this_plugin_dir !== $plugins_dir ) {
			$deleted = $wp_filesystem->delete( $this_plugin_dir, true );
		} else {
			$deleted = $wp_filesystem->delete( $plugins_dir . $plugin );
		}

		if ( ! $deleted ) {
			return new WP_Error( 'remove_old_failed', $this->strings['remove_old_failed'] );
		}

		return true;
	}
}
list-table.php000064400000007332151212616040007320 0ustar00<?php
/**
 * Helper functions for displaying a list of items in an ajaxified HTML table.
 *
 * @package WordPress
 * @subpackage List_Table
 * @since 3.1.0
 */

/**
 * Fetches an instance of a WP_List_Table class.
 *
 * @since 3.1.0
 *
 * @global string $hook_suffix
 *
 * @param string $class_name The type of the list table, which is the class name.
 * @param array  $args       Optional. Arguments to pass to the class. Accepts 'screen'.
 * @return WP_List_Table|false List table object on success, false if the class does not exist.
 */
function _get_list_table( $class_name, $args = array() ) {
	$core_classes = array(
		// Site Admin.
		'WP_Posts_List_Table'                         => 'posts',
		'WP_Media_List_Table'                         => 'media',
		'WP_Terms_List_Table'                         => 'terms',
		'WP_Users_List_Table'                         => 'users',
		'WP_Comments_List_Table'                      => 'comments',
		'WP_Post_Comments_List_Table'                 => array( 'comments', 'post-comments' ),
		'WP_Links_List_Table'                         => 'links',
		'WP_Plugin_Install_List_Table'                => 'plugin-install',
		'WP_Themes_List_Table'                        => 'themes',
		'WP_Theme_Install_List_Table'                 => array( 'themes', 'theme-install' ),
		'WP_Plugins_List_Table'                       => 'plugins',
		'WP_Application_Passwords_List_Table'         => 'application-passwords',

		// Network Admin.
		'WP_MS_Sites_List_Table'                      => 'ms-sites',
		'WP_MS_Users_List_Table'                      => 'ms-users',
		'WP_MS_Themes_List_Table'                     => 'ms-themes',

		// Privacy requests tables.
		'WP_Privacy_Data_Export_Requests_List_Table'  => 'privacy-data-export-requests',
		'WP_Privacy_Data_Removal_Requests_List_Table' => 'privacy-data-removal-requests',
	);

	if ( isset( $core_classes[ $class_name ] ) ) {
		foreach ( (array) $core_classes[ $class_name ] as $required ) {
			require_once ABSPATH . 'wp-admin/includes/class-wp-' . $required . '-list-table.php';
		}

		if ( isset( $args['screen'] ) ) {
			$args['screen'] = convert_to_screen( $args['screen'] );
		} elseif ( isset( $GLOBALS['hook_suffix'] ) ) {
			$args['screen'] = get_current_screen();
		} else {
			$args['screen'] = null;
		}

		/**
		 * Filters the list table class to instantiate.
		 *
		 * @since 6.1.0
		 *
		 * @param string $class_name The list table class to use.
		 * @param array  $args       An array containing _get_list_table() arguments.
		 */
		$custom_class_name = apply_filters( 'wp_list_table_class_name', $class_name, $args );

		if ( is_string( $custom_class_name ) && class_exists( $custom_class_name ) ) {
			$class_name = $custom_class_name;
		}

		return new $class_name( $args );
	}

	return false;
}

/**
 * Register column headers for a particular screen.
 *
 * @see get_column_headers(), print_column_headers(), get_hidden_columns()
 *
 * @since 2.7.0
 *
 * @param string    $screen The handle for the screen to register column headers for. This is
 *                          usually the hook name returned by the `add_*_page()` functions.
 * @param string[] $columns An array of columns with column IDs as the keys and translated
 *                          column names as the values.
 */
function register_column_headers( $screen, $columns ) {
	new _WP_List_Table_Compat( $screen, $columns );
}

/**
 * Prints column headers for a particular screen.
 *
 * @since 2.7.0
 *
 * @param string|WP_Screen $screen  The screen hook name or screen object.
 * @param bool             $with_id Whether to set the ID attribute or not.
 */
function print_column_headers( $screen, $with_id = true ) {
	$wp_list_table = new _WP_List_Table_Compat( $screen );

	$wp_list_table->print_column_headers( $with_id );
}
class-custom-background.php000064400000052265151212616040012017 0ustar00<?php
/**
 * The custom background script.
 *
 * @package WordPress
 * @subpackage Administration
 */

/**
 * The custom background class.
 *
 * @since 3.0.0
 */
#[AllowDynamicProperties]
class Custom_Background {

	/**
	 * Callback for administration header.
	 *
	 * @since 3.0.0
	 * @var callable
	 */
	public $admin_header_callback;

	/**
	 * Callback for header div.
	 *
	 * @since 3.0.0
	 * @var callable
	 */
	public $admin_image_div_callback;

	/**
	 * Used to trigger a success message when settings updated and set to true.
	 *
	 * @since 3.0.0
	 * @var bool
	 */
	private $updated;

	/**
	 * Constructor - Registers administration header callback.
	 *
	 * @since 3.0.0
	 *
	 * @param callable $admin_header_callback    Optional. Administration header callback.
	 *                                           Default empty string.
	 * @param callable $admin_image_div_callback Optional. Custom image div output callback.
	 *                                           Default empty string.
	 */
	public function __construct( $admin_header_callback = '', $admin_image_div_callback = '' ) {
		$this->admin_header_callback    = $admin_header_callback;
		$this->admin_image_div_callback = $admin_image_div_callback;

		add_action( 'admin_menu', array( $this, 'init' ) );

		add_action( 'wp_ajax_custom-background-add', array( $this, 'ajax_background_add' ) );

		// Unused since 3.5.0.
		add_action( 'wp_ajax_set-background-image', array( $this, 'wp_set_background_image' ) );
	}

	/**
	 * Sets up the hooks for the Custom Background admin page.
	 *
	 * @since 3.0.0
	 */
	public function init() {
		$page = add_theme_page(
			_x( 'Background', 'custom background' ),
			_x( 'Background', 'custom background' ),
			'edit_theme_options',
			'custom-background',
			array( $this, 'admin_page' )
		);

		if ( ! $page ) {
			return;
		}

		add_action( "load-{$page}", array( $this, 'admin_load' ) );
		add_action( "load-{$page}", array( $this, 'take_action' ), 49 );
		add_action( "load-{$page}", array( $this, 'handle_upload' ), 49 );

		if ( $this->admin_header_callback ) {
			add_action( "admin_head-{$page}", $this->admin_header_callback, 51 );
		}
	}

	/**
	 * Sets up the enqueue for the CSS & JavaScript files.
	 *
	 * @since 3.0.0
	 */
	public function admin_load() {
		get_current_screen()->add_help_tab(
			array(
				'id'      => 'overview',
				'title'   => __( 'Overview' ),
				'content' =>
					'<p>' . __( 'You can customize the look of your site without touching any of your theme&#8217;s code by using a custom background. Your background can be an image or a color.' ) . '</p>' .
					'<p>' . __( 'To use a background image, simply upload it or choose an image that has already been uploaded to your Media Library by clicking the &#8220;Choose Image&#8221; button. You can display a single instance of your image, or tile it to fill the screen. You can have your background fixed in place, so your site content moves on top of it, or you can have it scroll with your site.' ) . '</p>' .
					'<p>' . __( 'You can also choose a background color by clicking the Select Color button and either typing in a legitimate HTML hex value, e.g. &#8220;#ff0000&#8221; for red, or by choosing a color using the color picker.' ) . '</p>' .
					'<p>' . __( 'Do not forget to click on the Save Changes button when you are finished.' ) . '</p>',
			)
		);

		get_current_screen()->set_help_sidebar(
			'<p><strong>' . __( 'For more information:' ) . '</strong></p>' .
			'<p>' . __( '<a href="https://codex.wordpress.org/Appearance_Background_Screen">Documentation on Custom Background</a>' ) . '</p>' .
			'<p>' . __( '<a href="https://wordpress.org/support/forums/">Support forums</a>' ) . '</p>'
		);

		wp_enqueue_media();
		wp_enqueue_script( 'custom-background' );
		wp_enqueue_style( 'wp-color-picker' );
	}

	/**
	 * Executes custom background modification.
	 *
	 * @since 3.0.0
	 */
	public function take_action() {
		if ( empty( $_POST ) ) {
			return;
		}

		if ( isset( $_POST['reset-background'] ) ) {
			check_admin_referer( 'custom-background-reset', '_wpnonce-custom-background-reset' );

			remove_theme_mod( 'background_image' );
			remove_theme_mod( 'background_image_thumb' );

			$this->updated = true;
			return;
		}

		if ( isset( $_POST['remove-background'] ) ) {
			// @todo Uploaded files are not removed here.
			check_admin_referer( 'custom-background-remove', '_wpnonce-custom-background-remove' );

			set_theme_mod( 'background_image', '' );
			set_theme_mod( 'background_image_thumb', '' );

			$this->updated = true;
			wp_safe_redirect( $_POST['_wp_http_referer'] );
			return;
		}

		if ( isset( $_POST['background-preset'] ) ) {
			check_admin_referer( 'custom-background' );

			if ( in_array( $_POST['background-preset'], array( 'default', 'fill', 'fit', 'repeat', 'custom' ), true ) ) {
				$preset = $_POST['background-preset'];
			} else {
				$preset = 'default';
			}

			set_theme_mod( 'background_preset', $preset );
		}

		if ( isset( $_POST['background-position'] ) ) {
			check_admin_referer( 'custom-background' );

			$position = explode( ' ', $_POST['background-position'] );

			if ( in_array( $position[0], array( 'left', 'center', 'right' ), true ) ) {
				$position_x = $position[0];
			} else {
				$position_x = 'left';
			}

			if ( in_array( $position[1], array( 'top', 'center', 'bottom' ), true ) ) {
				$position_y = $position[1];
			} else {
				$position_y = 'top';
			}

			set_theme_mod( 'background_position_x', $position_x );
			set_theme_mod( 'background_position_y', $position_y );
		}

		if ( isset( $_POST['background-size'] ) ) {
			check_admin_referer( 'custom-background' );

			if ( in_array( $_POST['background-size'], array( 'auto', 'contain', 'cover' ), true ) ) {
				$size = $_POST['background-size'];
			} else {
				$size = 'auto';
			}

			set_theme_mod( 'background_size', $size );
		}

		if ( isset( $_POST['background-repeat'] ) ) {
			check_admin_referer( 'custom-background' );

			$repeat = $_POST['background-repeat'];

			if ( 'no-repeat' !== $repeat ) {
				$repeat = 'repeat';
			}

			set_theme_mod( 'background_repeat', $repeat );
		}

		if ( isset( $_POST['background-attachment'] ) ) {
			check_admin_referer( 'custom-background' );

			$attachment = $_POST['background-attachment'];

			if ( 'fixed' !== $attachment ) {
				$attachment = 'scroll';
			}

			set_theme_mod( 'background_attachment', $attachment );
		}

		if ( isset( $_POST['background-color'] ) ) {
			check_admin_referer( 'custom-background' );

			$color = preg_replace( '/[^0-9a-fA-F]/', '', $_POST['background-color'] );

			if ( strlen( $color ) === 6 || strlen( $color ) === 3 ) {
				set_theme_mod( 'background_color', $color );
			} else {
				set_theme_mod( 'background_color', '' );
			}
		}

		$this->updated = true;
	}

	/**
	 * Displays the custom background page.
	 *
	 * @since 3.0.0
	 */
	public function admin_page() {
		?>
<div class="wrap" id="custom-background">
<h1><?php _e( 'Custom Background' ); ?></h1>

		<?php
		if ( current_user_can( 'customize' ) ) {
			$message = sprintf(
				/* translators: %s: URL to background image configuration in Customizer. */
				__( 'You can now manage and live-preview Custom Backgrounds in the <a href="%s">Customizer</a>.' ),
				admin_url( 'customize.php?autofocus[control]=background_image' )
			);
			wp_admin_notice(
				$message,
				array(
					'type'               => 'info',
					'additional_classes' => array( 'hide-if-no-customize' ),
				)
			);
		}

		if ( ! empty( $this->updated ) ) {
			$updated_message = sprintf(
				/* translators: %s: Home URL. */
				__( 'Background updated. <a href="%s">Visit your site</a> to see how it looks.' ),
				esc_url( home_url( '/' ) )
			);
			wp_admin_notice(
				$updated_message,
				array(
					'id'                 => 'message',
					'additional_classes' => array( 'updated' ),
				)
			);
		}
		?>

<h2><?php _e( 'Background Image' ); ?></h2>

<table class="form-table" role="presentation">
<tbody>
<tr>
<th scope="row"><?php _e( 'Preview' ); ?></th>
<td>
		<?php
		if ( $this->admin_image_div_callback ) {
			call_user_func( $this->admin_image_div_callback );
		} else {
			$background_styles = '';
			$bgcolor           = get_background_color();
			if ( $bgcolor ) {
				$background_styles .= 'background-color: ' . maybe_hash_hex_color( $bgcolor ) . ';';
			}

			$background_image_thumb = get_background_image();
			if ( $background_image_thumb ) {
				$background_image_thumb = esc_url( set_url_scheme( get_theme_mod( 'background_image_thumb', str_replace( '%', '%%', $background_image_thumb ) ) ) );
				$background_position_x  = get_theme_mod( 'background_position_x', get_theme_support( 'custom-background', 'default-position-x' ) );
				$background_position_y  = get_theme_mod( 'background_position_y', get_theme_support( 'custom-background', 'default-position-y' ) );
				$background_size        = get_theme_mod( 'background_size', get_theme_support( 'custom-background', 'default-size' ) );
				$background_repeat      = get_theme_mod( 'background_repeat', get_theme_support( 'custom-background', 'default-repeat' ) );
				$background_attachment  = get_theme_mod( 'background_attachment', get_theme_support( 'custom-background', 'default-attachment' ) );

				// Background-image URL must be single quote, see below.
				$background_styles .= " background-image: url('$background_image_thumb');"
				. " background-size: $background_size;"
				. " background-position: $background_position_x $background_position_y;"
				. " background-repeat: $background_repeat;"
				. " background-attachment: $background_attachment;";
			}
			?>
	<div id="custom-background-image" style="<?php echo $background_styles; ?>"><?php // Must be double quote, see above. ?>
			<?php if ( $background_image_thumb ) { ?>
		<img class="custom-background-image" src="<?php echo $background_image_thumb; ?>" style="visibility:hidden;" alt="" /><br />
		<img class="custom-background-image" src="<?php echo $background_image_thumb; ?>" style="visibility:hidden;" alt="" />
		<?php } ?>
	</div>
	<?php } ?>
</td>
</tr>

		<?php if ( get_background_image() ) : ?>
<tr>
<th scope="row"><?php _e( 'Remove Image' ); ?></th>
<td>
<form method="post">
			<?php wp_nonce_field( 'custom-background-remove', '_wpnonce-custom-background-remove' ); ?>
			<?php submit_button( __( 'Remove Background Image' ), '', 'remove-background', false ); ?><br />
			<?php _e( 'This will remove the background image. You will not be able to restore any customizations.' ); ?>
</form>
</td>
</tr>
		<?php endif; ?>

		<?php $default_image = get_theme_support( 'custom-background', 'default-image' ); ?>
		<?php if ( $default_image && get_background_image() !== $default_image ) : ?>
<tr>
<th scope="row"><?php _e( 'Restore Original Image' ); ?></th>
<td>
<form method="post">
			<?php wp_nonce_field( 'custom-background-reset', '_wpnonce-custom-background-reset' ); ?>
			<?php submit_button( __( 'Restore Original Image' ), '', 'reset-background', false ); ?><br />
			<?php _e( 'This will restore the original background image. You will not be able to restore any customizations.' ); ?>
</form>
</td>
</tr>
		<?php endif; ?>

		<?php if ( current_user_can( 'upload_files' ) ) : ?>
<tr>
<th scope="row"><?php _e( 'Select Image' ); ?></th>
<td><form enctype="multipart/form-data" id="upload-form" class="wp-upload-form" method="post">
	<p>
		<label for="upload"><?php _e( 'Choose an image from your computer:' ); ?></label><br />
		<input type="file" id="upload" name="import" />
		<input type="hidden" name="action" value="save" />
			<?php wp_nonce_field( 'custom-background-upload', '_wpnonce-custom-background-upload' ); ?>
			<?php submit_button( _x( 'Upload', 'verb' ), '', 'submit', false ); ?>
	</p>
	<p>
		<label for="choose-from-library-link"><?php _e( 'Or choose an image from your media library:' ); ?></label><br />
		<button id="choose-from-library-link" class="button"
			data-choose="<?php esc_attr_e( 'Choose a Background Image' ); ?>"
			data-update="<?php esc_attr_e( 'Set as background' ); ?>"><?php _e( 'Choose Image' ); ?></button>
	</p>
	</form>
</td>
</tr>
		<?php endif; ?>
</tbody>
</table>

<h2><?php _e( 'Display Options' ); ?></h2>
<form method="post">
<table class="form-table" role="presentation">
<tbody>
		<?php if ( get_background_image() ) : ?>
<input name="background-preset" type="hidden" value="custom">

			<?php
			$background_position_title = __( 'Image Position' );

			$background_position = sprintf(
				'%s %s',
				get_theme_mod( 'background_position_x', get_theme_support( 'custom-background', 'default-position-x' ) ),
				get_theme_mod( 'background_position_y', get_theme_support( 'custom-background', 'default-position-y' ) )
			);

			$background_position_options = array(
				array(
					'left top'   => array(
						'label' => __( 'Top Left' ),
						'icon'  => 'dashicons dashicons-arrow-left-alt',
					),
					'center top' => array(
						'label' => __( 'Top' ),
						'icon'  => 'dashicons dashicons-arrow-up-alt',
					),
					'right top'  => array(
						'label' => __( 'Top Right' ),
						'icon'  => 'dashicons dashicons-arrow-right-alt',
					),
				),
				array(
					'left center'   => array(
						'label' => __( 'Left' ),
						'icon'  => 'dashicons dashicons-arrow-left-alt',
					),
					'center center' => array(
						'label' => __( 'Center' ),
						'icon'  => 'background-position-center-icon',
					),
					'right center'  => array(
						'label' => __( 'Right' ),
						'icon'  => 'dashicons dashicons-arrow-right-alt',
					),
				),
				array(
					'left bottom'   => array(
						'label' => __( 'Bottom Left' ),
						'icon'  => 'dashicons dashicons-arrow-left-alt',
					),
					'center bottom' => array(
						'label' => __( 'Bottom' ),
						'icon'  => 'dashicons dashicons-arrow-down-alt',
					),
					'right bottom'  => array(
						'label' => __( 'Bottom Right' ),
						'icon'  => 'dashicons dashicons-arrow-right-alt',
					),
				),
			);
			?>
<tr>
<th scope="row"><?php echo $background_position_title; ?></th>
<td><fieldset><legend class="screen-reader-text"><span><?php echo $background_position_title; ?></span></legend>
<div class="background-position-control">
			<?php foreach ( $background_position_options as $group ) : ?>
	<div class="button-group">
				<?php foreach ( $group as $value => $input ) : ?>
		<label>
			<input class="ui-helper-hidden-accessible" name="background-position" type="radio" value="<?php echo esc_attr( $value ); ?>"<?php checked( $value, $background_position ); ?>>
			<span class="button display-options position"><span class="<?php echo esc_attr( $input['icon'] ); ?>" aria-hidden="true"></span></span>
			<span class="screen-reader-text"><?php echo $input['label']; ?></span>
		</label>
	<?php endforeach; ?>
	</div>
<?php endforeach; ?>
</div>
</fieldset></td>
</tr>

			<?php $image_size_title = __( 'Image Size' ); ?>
<tr>
<th scope="row"><label for="background-size"><?php echo $image_size_title; ?></label></th>
<td><fieldset><legend class="screen-reader-text"><span><?php echo $image_size_title; ?></span></legend>
<select id="background-size" name="background-size">
<option value="auto"<?php selected( 'auto', get_theme_mod( 'background_size', get_theme_support( 'custom-background', 'default-size' ) ) ); ?>><?php _ex( 'Original', 'Original Size' ); ?></option>
<option value="contain"<?php selected( 'contain', get_theme_mod( 'background_size', get_theme_support( 'custom-background', 'default-size' ) ) ); ?>><?php _e( 'Fit to Screen' ); ?></option>
<option value="cover"<?php selected( 'cover', get_theme_mod( 'background_size', get_theme_support( 'custom-background', 'default-size' ) ) ); ?>><?php _e( 'Fill Screen' ); ?></option>
</select>
</fieldset></td>
</tr>

			<?php $background_repeat_title = _x( 'Repeat', 'Background Repeat' ); ?>
<tr>
<th scope="row"><?php echo $background_repeat_title; ?></th>
<td><fieldset><legend class="screen-reader-text"><span><?php echo $background_repeat_title; ?></span></legend>
<input name="background-repeat" type="hidden" value="no-repeat">
<label><input type="checkbox" name="background-repeat" value="repeat"<?php checked( 'repeat', get_theme_mod( 'background_repeat', get_theme_support( 'custom-background', 'default-repeat' ) ) ); ?>> <?php _e( 'Repeat Background Image' ); ?></label>
</fieldset></td>
</tr>

			<?php $background_scroll_title = _x( 'Scroll', 'Background Scroll' ); ?>
<tr>
<th scope="row"><?php echo $background_scroll_title; ?></th>
<td><fieldset><legend class="screen-reader-text"><span><?php echo $background_scroll_title; ?></span></legend>
<input name="background-attachment" type="hidden" value="fixed">
<label><input name="background-attachment" type="checkbox" value="scroll" <?php checked( 'scroll', get_theme_mod( 'background_attachment', get_theme_support( 'custom-background', 'default-attachment' ) ) ); ?>> <?php _e( 'Scroll with Page' ); ?></label>
</fieldset></td>
</tr>
<?php endif; // get_background_image() ?>

		<?php $background_color_title = __( 'Background Color' ); ?>
<tr>
<th scope="row"><?php echo $background_color_title; ?></th>
<td><fieldset><legend class="screen-reader-text"><span><?php echo $background_color_title; ?></span></legend>
		<?php
		$default_color = '';
		if ( current_theme_supports( 'custom-background', 'default-color' ) ) {
			$default_color = ' data-default-color="#' . esc_attr( get_theme_support( 'custom-background', 'default-color' ) ) . '"';
		}
		?>
<input type="text" name="background-color" id="background-color" value="#<?php echo esc_attr( get_background_color() ); ?>"<?php echo $default_color; ?>>
</fieldset></td>
</tr>
</tbody>
</table>

		<?php wp_nonce_field( 'custom-background' ); ?>
		<?php submit_button( null, 'primary', 'save-background-options' ); ?>
</form>

</div>
		<?php
	}

	/**
	 * Handles an Image upload for the background image.
	 *
	 * @since 3.0.0
	 */
	public function handle_upload() {
		if ( empty( $_FILES ) ) {
			return;
		}

		check_admin_referer( 'custom-background-upload', '_wpnonce-custom-background-upload' );

		$overrides = array( 'test_form' => false );

		$uploaded_file = $_FILES['import'];
		$wp_filetype   = wp_check_filetype_and_ext( $uploaded_file['tmp_name'], $uploaded_file['name'] );
		if ( ! wp_match_mime_types( 'image', $wp_filetype['type'] ) ) {
			wp_die( __( 'The uploaded file is not a valid image. Please try again.' ) );
		}

		$file = wp_handle_upload( $uploaded_file, $overrides );

		if ( isset( $file['error'] ) ) {
			wp_die( $file['error'] );
		}

		$url      = $file['url'];
		$type     = $file['type'];
		$file     = $file['file'];
		$filename = wp_basename( $file );

		// Construct the attachment array.
		$attachment = array(
			'post_title'     => $filename,
			'post_content'   => $url,
			'post_mime_type' => $type,
			'guid'           => $url,
			'context'        => 'custom-background',
		);

		// Save the data.
		$id = wp_insert_attachment( $attachment, $file );

		// Add the metadata.
		wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $file ) );
		update_post_meta( $id, '_wp_attachment_is_custom_background', get_option( 'stylesheet' ) );

		set_theme_mod( 'background_image', sanitize_url( $url ) );

		$thumbnail = wp_get_attachment_image_src( $id, 'thumbnail' );
		set_theme_mod( 'background_image_thumb', sanitize_url( $thumbnail[0] ) );

		/** This filter is documented in wp-admin/includes/class-custom-image-header.php */
		$file = apply_filters( 'wp_create_file_in_uploads', $file, $id ); // For replication.

		$this->updated = true;
	}

	/**
	 * Handles Ajax request for adding custom background context to an attachment.
	 *
	 * Triggers when the user adds a new background image from the
	 * Media Manager.
	 *
	 * @since 4.1.0
	 */
	public function ajax_background_add() {
		check_ajax_referer( 'background-add', 'nonce' );

		if ( ! current_user_can( 'edit_theme_options' ) ) {
			wp_send_json_error();
		}

		$attachment_id = absint( $_POST['attachment_id'] );
		if ( $attachment_id < 1 ) {
			wp_send_json_error();
		}

		update_post_meta( $attachment_id, '_wp_attachment_is_custom_background', get_stylesheet() );

		wp_send_json_success();
	}

	/**
	 * @since 3.4.0
	 * @deprecated 3.5.0
	 *
	 * @param array $form_fields
	 * @return array $form_fields
	 */
	public function attachment_fields_to_edit( $form_fields ) {
		return $form_fields;
	}

	/**
	 * @since 3.4.0
	 * @deprecated 3.5.0
	 *
	 * @param array $tabs
	 * @return array $tabs
	 */
	public function filter_upload_tabs( $tabs ) {
		return $tabs;
	}

	/**
	 * @since 3.4.0
	 * @deprecated 3.5.0
	 */
	public function wp_set_background_image() {
		check_ajax_referer( 'custom-background' );

		if ( ! current_user_can( 'edit_theme_options' ) || ! isset( $_POST['attachment_id'] ) ) {
			exit;
		}

		$attachment_id = absint( $_POST['attachment_id'] );

		$sizes = array_keys(
			/** This filter is documented in wp-admin/includes/media.php */
			apply_filters(
				'image_size_names_choose',
				array(
					'thumbnail' => __( 'Thumbnail' ),
					'medium'    => __( 'Medium' ),
					'large'     => __( 'Large' ),
					'full'      => __( 'Full Size' ),
				)
			)
		);

		$size = 'thumbnail';
		if ( in_array( $_POST['size'], $sizes, true ) ) {
			$size = esc_attr( $_POST['size'] );
		}

		update_post_meta( $attachment_id, '_wp_attachment_is_custom_background', get_option( 'stylesheet' ) );

		$url       = wp_get_attachment_image_src( $attachment_id, $size );
		$thumbnail = wp_get_attachment_image_src( $attachment_id, 'thumbnail' );
		set_theme_mod( 'background_image', sanitize_url( $url[0] ) );
		set_theme_mod( 'background_image_thumb', sanitize_url( $thumbnail[0] ) );
		exit;
	}
}
translation-install.php000064400000025503151212616040011262 0ustar00<?php
/**
 * WordPress Translation Installation Administration API
 *
 * @package WordPress
 * @subpackage Administration
 */


/**
 * Retrieve translations from WordPress Translation API.
 *
 * @since 4.0.0
 *
 * @param string       $type Type of translations. Accepts 'plugins', 'themes', 'core'.
 * @param array|object $args Translation API arguments. Optional.
 * @return array|WP_Error {
 *     On success an associative array of translations, WP_Error on failure.
 *
 *     @type array $translations {
 *         List of translations, each an array of data.
 *
 *         @type array ...$0 {
 *             @type string   $language     Language code.
 *             @type string   $version      WordPress version.
 *             @type string   $updated      Date the translation was last updated, in MySQL datetime format.
 *             @type string   $english_name English name of the language.
 *             @type string   $native_name  Native name of the language.
 *             @type string   $package      URL to download the translation package.
 *             @type string[] $iso          Array of ISO language codes.
 *             @type array    $strings      Array of translated strings used in the installation process.
 *         }
 *     }
 * }
 */
function translations_api( $type, $args = null ) {
	if ( ! in_array( $type, array( 'plugins', 'themes', 'core' ), true ) ) {
		return new WP_Error( 'invalid_type', __( 'Invalid translation type.' ) );
	}

	/**
	 * Allows a plugin to override the WordPress.org Translation Installation API entirely.
	 *
	 * @since 4.0.0
	 *
	 * @param false|array $result The result array. Default false.
	 * @param string      $type   The type of translations being requested.
	 * @param object      $args   Translation API arguments.
	 */
	$res = apply_filters( 'translations_api', false, $type, $args );

	if ( false === $res ) {
		$url      = 'http://api.wordpress.org/translations/' . $type . '/1.0/';
		$http_url = $url;
		$ssl      = wp_http_supports( array( 'ssl' ) );
		if ( $ssl ) {
			$url = set_url_scheme( $url, 'https' );
		}

		$options = array(
			'timeout' => 3,
			'body'    => array(
				'wp_version' => wp_get_wp_version(),
				'locale'     => get_locale(),
				'version'    => $args['version'], // Version of plugin, theme or core.
			),
		);

		if ( 'core' !== $type ) {
			$options['body']['slug'] = $args['slug']; // Plugin or theme slug.
		}

		$request = wp_remote_post( $url, $options );

		if ( $ssl && is_wp_error( $request ) ) {
			wp_trigger_error(
				__FUNCTION__,
				sprintf(
					/* translators: %s: Support forums URL. */
					__( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ),
					__( 'https://wordpress.org/support/forums/' )
				) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ),
				headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE
			);

			$request = wp_remote_post( $http_url, $options );
		}

		if ( is_wp_error( $request ) ) {
			$res = new WP_Error(
				'translations_api_failed',
				sprintf(
					/* translators: %s: Support forums URL. */
					__( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ),
					__( 'https://wordpress.org/support/forums/' )
				),
				$request->get_error_message()
			);
		} else {
			$res = json_decode( wp_remote_retrieve_body( $request ), true );
			if ( ! is_object( $res ) && ! is_array( $res ) ) {
				$res = new WP_Error(
					'translations_api_failed',
					sprintf(
						/* translators: %s: Support forums URL. */
						__( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ),
						__( 'https://wordpress.org/support/forums/' )
					),
					wp_remote_retrieve_body( $request )
				);
			}
		}
	}

	/**
	 * Filters the Translation Installation API response results.
	 *
	 * @since 4.0.0
	 *
	 * @param array|WP_Error $res  {
	 *     On success an associative array of translations, WP_Error on failure.
	 *
	 *     @type array $translations {
	 *         List of translations, each an array of data.
	 *
	 *         @type array ...$0 {
	 *             @type string   $language     Language code.
	 *             @type string   $version      WordPress version.
	 *             @type string   $updated      Date the translation was last updated, in MySQL datetime format.
	 *             @type string   $english_name English name of the language.
	 *             @type string   $native_name  Native name of the language.
	 *             @type string   $package      URL to download the translation package.
	 *             @type string[] $iso          Array of ISO language codes.
	 *             @type array    $strings      Array of translated strings used in the installation process.
	 *         }
	 *     }
	 * }
	 * @param string         $type The type of translations being requested.
	 * @param object         $args Translation API arguments.
	 */
	return apply_filters( 'translations_api_result', $res, $type, $args );
}

/**
 * Get available translations from the WordPress.org API.
 *
 * @since 4.0.0
 *
 * @see translations_api()
 *
 * @return array {
 *     Array of translations keyed by the language code, each an associative array of data.
 *     If the API response results in an error, an empty array will be returned.
 *
 *     @type array ...$0 {
 *         @type string   $language     Language code.
 *         @type string   $version      WordPress version.
 *         @type string   $updated      Date the translation was last updated, in MySQL datetime format.
 *         @type string   $english_name English name of the language.
 *         @type string   $native_name  Native name of the language.
 *         @type string   $package      URL to download the translation package.
 *         @type string[] $iso          Array of ISO language codes.
 *         @type array    $strings      Array of translated strings used in the installation process.
 *     }
 * }
 */
function wp_get_available_translations() {
	if ( ! wp_installing() ) {
		$translations = get_site_transient( 'available_translations' );
		if ( false !== $translations ) {
			return $translations;
		}
	}

	$api = translations_api( 'core', array( 'version' => wp_get_wp_version() ) );

	if ( is_wp_error( $api ) || empty( $api['translations'] ) ) {
		return array();
	}

	$translations = array();
	// Key the array with the language code.
	foreach ( $api['translations'] as $translation ) {
		$translations[ $translation['language'] ] = $translation;
	}

	if ( ! defined( 'WP_INSTALLING' ) ) {
		set_site_transient( 'available_translations', $translations, 3 * HOUR_IN_SECONDS );
	}

	return $translations;
}

/**
 * Output the select form for the language selection on the installation screen.
 *
 * @since 4.0.0
 *
 * @global string $wp_local_package Locale code of the package.
 *
 * @param array[] $languages Array of available languages (populated via the Translation API).
 */
function wp_install_language_form( $languages ) {
	global $wp_local_package;

	$installed_languages = get_available_languages();

	echo "<label class='screen-reader-text' for='language'>Select a default language</label>\n";
	echo "<select size='14' name='language' id='language'>\n";
	echo '<option value="" lang="en" selected="selected" data-continue="Continue" data-installed="1">English (United States)</option>';
	echo "\n";

	if ( ! empty( $wp_local_package ) && isset( $languages[ $wp_local_package ] ) ) {
		if ( isset( $languages[ $wp_local_package ] ) ) {
			$language = $languages[ $wp_local_package ];
			printf(
				'<option value="%s" lang="%s" data-continue="%s"%s>%s</option>' . "\n",
				esc_attr( $language['language'] ),
				esc_attr( current( $language['iso'] ) ),
				esc_attr( $language['strings']['continue'] ? $language['strings']['continue'] : 'Continue' ),
				in_array( $language['language'], $installed_languages, true ) ? ' data-installed="1"' : '',
				esc_html( $language['native_name'] )
			);

			unset( $languages[ $wp_local_package ] );
		}
	}

	foreach ( $languages as $language ) {
		printf(
			'<option value="%s" lang="%s" data-continue="%s"%s>%s</option>' . "\n",
			esc_attr( $language['language'] ),
			esc_attr( current( $language['iso'] ) ),
			esc_attr( $language['strings']['continue'] ? $language['strings']['continue'] : 'Continue' ),
			in_array( $language['language'], $installed_languages, true ) ? ' data-installed="1"' : '',
			esc_html( $language['native_name'] )
		);
	}
	echo "</select>\n";
	echo '<p class="step"><span class="spinner"></span><input id="language-continue" type="submit" class="button button-primary button-large" value="Continue" /></p>';
}

/**
 * Download a language pack.
 *
 * @since 4.0.0
 *
 * @see wp_get_available_translations()
 *
 * @param string $download Language code to download.
 * @return string|false Returns the language code if successfully downloaded
 *                      (or already installed), or false on failure.
 */
function wp_download_language_pack( $download ) {
	// Check if the translation is already installed.
	if ( in_array( $download, get_available_languages(), true ) ) {
		return $download;
	}

	if ( ! wp_is_file_mod_allowed( 'download_language_pack' ) ) {
		return false;
	}

	// Confirm the translation is one we can download.
	$translations = wp_get_available_translations();
	if ( ! $translations ) {
		return false;
	}
	foreach ( $translations as $translation ) {
		if ( $translation['language'] === $download ) {
			$translation_to_load = true;
			break;
		}
	}

	if ( empty( $translation_to_load ) ) {
		return false;
	}
	$translation = (object) $translation;

	require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
	$skin              = new Automatic_Upgrader_Skin();
	$upgrader          = new Language_Pack_Upgrader( $skin );
	$translation->type = 'core';
	$result            = $upgrader->upgrade( $translation, array( 'clear_update_cache' => false ) );

	if ( ! $result || is_wp_error( $result ) ) {
		return false;
	}

	return $translation->language;
}

/**
 * Check if WordPress has access to the filesystem without asking for
 * credentials.
 *
 * @since 4.0.0
 *
 * @return bool Returns true on success, false on failure.
 */
function wp_can_install_language_pack() {
	if ( ! wp_is_file_mod_allowed( 'can_install_language_pack' ) ) {
		return false;
	}

	require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
	$skin     = new Automatic_Upgrader_Skin();
	$upgrader = new Language_Pack_Upgrader( $skin );
	$upgrader->init();

	$check = $upgrader->fs_connect( array( WP_CONTENT_DIR, WP_LANG_DIR ) );

	if ( ! $check || is_wp_error( $check ) ) {
		return false;
	}

	return true;
}
ms-admin-filters.php000064400000002420151212616040010424 0ustar00<?php
/**
 * Multisite Administration hooks
 *
 * @package WordPress
 * @subpackage Administration
 * @since 4.3.0
 */

// Media hooks.
add_filter( 'wp_handle_upload_prefilter', 'check_upload_size' );

// User hooks.
add_action( 'user_admin_notices', 'new_user_email_admin_notice' );
add_action( 'network_admin_notices', 'new_user_email_admin_notice' );

add_action( 'admin_page_access_denied', '_access_denied_splash', 99 );

// Site hooks.
add_action( 'wpmueditblogaction', 'upload_space_setting' );

// Network hooks.
add_action( 'update_site_option_admin_email', 'wp_network_admin_email_change_notification', 10, 4 );

// Post hooks.
add_filter( 'wp_insert_post_data', 'avoid_blog_page_permalink_collision', 10, 2 );

// Tools hooks.
add_filter( 'import_allow_create_users', 'check_import_new_users' );

// Notices hooks.
add_action( 'admin_notices', 'site_admin_notice' );
add_action( 'network_admin_notices', 'site_admin_notice' );

// Update hooks.
add_action( 'network_admin_notices', 'update_nag', 3 );
add_action( 'network_admin_notices', 'maintenance_nag', 10 );

// Network Admin hooks.
add_action( 'add_site_option_new_admin_email', 'update_network_option_new_admin_email', 10, 2 );
add_action( 'update_site_option_new_admin_email', 'update_network_option_new_admin_email', 10, 2 );
class-wp-posts-list-table.php000064400000177246151212616040012231 0ustar00<?php
/**
 * List Table API: WP_Posts_List_Table class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 3.1.0
 */

/**
 * Core class used to implement displaying posts in a list table.
 *
 * @since 3.1.0
 *
 * @see WP_List_Table
 */
class WP_Posts_List_Table extends WP_List_Table {

	/**
	 * Whether the items should be displayed hierarchically or linearly.
	 *
	 * @since 3.1.0
	 * @var bool
	 */
	protected $hierarchical_display;

	/**
	 * Holds the number of pending comments for each post.
	 *
	 * @since 3.1.0
	 * @var array
	 */
	protected $comment_pending_count;

	/**
	 * Holds the number of posts for this user.
	 *
	 * @since 3.1.0
	 * @var int
	 */
	private $user_posts_count;

	/**
	 * Holds the number of posts which are sticky.
	 *
	 * @since 3.1.0
	 * @var int
	 */
	private $sticky_posts_count = 0;

	private $is_trash;

	/**
	 * Current level for output.
	 *
	 * @since 4.3.0
	 * @var int
	 */
	protected $current_level = 0;

	/**
	 * Constructor.
	 *
	 * @since 3.1.0
	 *
	 * @see WP_List_Table::__construct() for more information on default arguments.
	 *
	 * @global WP_Post_Type $post_type_object Global post type object.
	 * @global wpdb         $wpdb             WordPress database abstraction object.
	 *
	 * @param array $args An associative array of arguments.
	 */
	public function __construct( $args = array() ) {
		global $post_type_object, $wpdb;

		parent::__construct(
			array(
				'plural' => 'posts',
				'screen' => isset( $args['screen'] ) ? $args['screen'] : null,
			)
		);

		$post_type        = $this->screen->post_type;
		$post_type_object = get_post_type_object( $post_type );

		$exclude_states = get_post_stati(
			array(
				'show_in_admin_all_list' => false,
			)
		);

		$this->user_posts_count = (int) $wpdb->get_var(
			$wpdb->prepare(
				"SELECT COUNT( 1 )
				FROM $wpdb->posts
				WHERE post_type = %s
				AND post_status NOT IN ( '" . implode( "','", $exclude_states ) . "' )
				AND post_author = %d",
				$post_type,
				get_current_user_id()
			)
		);

		if ( $this->user_posts_count
			&& ! current_user_can( $post_type_object->cap->edit_others_posts )
			&& empty( $_REQUEST['post_status'] ) && empty( $_REQUEST['all_posts'] )
			&& empty( $_REQUEST['author'] ) && empty( $_REQUEST['show_sticky'] )
		) {
			$_GET['author'] = get_current_user_id();
		}

		$sticky_posts = get_option( 'sticky_posts' );

		if ( 'post' === $post_type && $sticky_posts ) {
			$sticky_posts = implode( ', ', array_map( 'absint', (array) $sticky_posts ) );

			$this->sticky_posts_count = (int) $wpdb->get_var(
				$wpdb->prepare(
					"SELECT COUNT( 1 )
					FROM $wpdb->posts
					WHERE post_type = %s
					AND post_status NOT IN ('trash', 'auto-draft')
					AND ID IN ($sticky_posts)",
					$post_type
				)
			);
		}
	}

	/**
	 * Sets whether the table layout should be hierarchical or not.
	 *
	 * @since 4.2.0
	 *
	 * @param bool $display Whether the table layout should be hierarchical.
	 */
	public function set_hierarchical_display( $display ) {
		$this->hierarchical_display = $display;
	}

	/**
	 * @return bool
	 */
	public function ajax_user_can() {
		return current_user_can( get_post_type_object( $this->screen->post_type )->cap->edit_posts );
	}

	/**
	 * @global string   $mode             List table view mode.
	 * @global array    $avail_post_stati
	 * @global WP_Query $wp_query         WordPress Query object.
	 * @global int      $per_page
	 */
	public function prepare_items() {
		global $mode, $avail_post_stati, $wp_query, $per_page;

		if ( ! empty( $_REQUEST['mode'] ) ) {
			$mode = 'excerpt' === $_REQUEST['mode'] ? 'excerpt' : 'list';
			set_user_setting( 'posts_list_mode', $mode );
		} else {
			$mode = get_user_setting( 'posts_list_mode', 'list' );
		}

		// Is going to call wp().
		$avail_post_stati = wp_edit_posts_query();

		$this->set_hierarchical_display(
			is_post_type_hierarchical( $this->screen->post_type )
			&& 'menu_order title' === $wp_query->query['orderby']
		);

		$post_type = $this->screen->post_type;
		$per_page  = $this->get_items_per_page( 'edit_' . $post_type . '_per_page' );

		/** This filter is documented in wp-admin/includes/post.php */
		$per_page = apply_filters( 'edit_posts_per_page', $per_page, $post_type );

		if ( $this->hierarchical_display ) {
			$total_items = $wp_query->post_count;
		} elseif ( $wp_query->found_posts || $this->get_pagenum() === 1 ) {
			$total_items = $wp_query->found_posts;
		} else {
			$post_counts = (array) wp_count_posts( $post_type, 'readable' );

			if ( isset( $_REQUEST['post_status'] ) && in_array( $_REQUEST['post_status'], $avail_post_stati, true ) ) {
				$total_items = $post_counts[ $_REQUEST['post_status'] ];
			} elseif ( isset( $_REQUEST['show_sticky'] ) && $_REQUEST['show_sticky'] ) {
				$total_items = $this->sticky_posts_count;
			} elseif ( isset( $_GET['author'] ) && get_current_user_id() === (int) $_GET['author'] ) {
				$total_items = $this->user_posts_count;
			} else {
				$total_items = array_sum( $post_counts );

				// Subtract post types that are not included in the admin all list.
				foreach ( get_post_stati( array( 'show_in_admin_all_list' => false ) ) as $state ) {
					$total_items -= $post_counts[ $state ];
				}
			}
		}

		$this->is_trash = isset( $_REQUEST['post_status'] ) && 'trash' === $_REQUEST['post_status'];

		$this->set_pagination_args(
			array(
				'total_items' => $total_items,
				'per_page'    => $per_page,
			)
		);
	}

	/**
	 * @return bool
	 */
	public function has_items() {
		return have_posts();
	}

	/**
	 */
	public function no_items() {
		if ( isset( $_REQUEST['post_status'] ) && 'trash' === $_REQUEST['post_status'] ) {
			echo get_post_type_object( $this->screen->post_type )->labels->not_found_in_trash;
		} else {
			echo get_post_type_object( $this->screen->post_type )->labels->not_found;
		}
	}

	/**
	 * Determines if the current view is the "All" view.
	 *
	 * @since 4.2.0
	 *
	 * @return bool Whether the current view is the "All" view.
	 */
	protected function is_base_request() {
		$vars = $_GET;
		unset( $vars['paged'] );

		if ( empty( $vars ) ) {
			return true;
		} elseif ( 1 === count( $vars ) && ! empty( $vars['post_type'] ) ) {
			return $this->screen->post_type === $vars['post_type'];
		}

		return 1 === count( $vars ) && ! empty( $vars['mode'] );
	}

	/**
	 * Creates a link to edit.php with params.
	 *
	 * @since 4.4.0
	 *
	 * @param string[] $args      Associative array of URL parameters for the link.
	 * @param string   $link_text Link text.
	 * @param string   $css_class Optional. Class attribute. Default empty string.
	 * @return string The formatted link string.
	 */
	protected function get_edit_link( $args, $link_text, $css_class = '' ) {
		$url = add_query_arg( $args, 'edit.php' );

		$class_html   = '';
		$aria_current = '';

		if ( ! empty( $css_class ) ) {
			$class_html = sprintf(
				' class="%s"',
				esc_attr( $css_class )
			);

			if ( 'current' === $css_class ) {
				$aria_current = ' aria-current="page"';
			}
		}

		return sprintf(
			'<a href="%s"%s%s>%s</a>',
			esc_url( $url ),
			$class_html,
			$aria_current,
			$link_text
		);
	}

	/**
	 * @global array $locked_post_status This seems to be deprecated.
	 * @global array $avail_post_stati
	 * @return array
	 */
	protected function get_views() {
		global $locked_post_status, $avail_post_stati;

		$post_type = $this->screen->post_type;

		if ( ! empty( $locked_post_status ) ) {
			return array();
		}

		$status_links = array();
		$num_posts    = wp_count_posts( $post_type, 'readable' );
		$total_posts  = array_sum( (array) $num_posts );
		$class        = '';

		$current_user_id = get_current_user_id();
		$all_args        = array( 'post_type' => $post_type );
		$mine            = '';

		// Subtract post types that are not included in the admin all list.
		foreach ( get_post_stati( array( 'show_in_admin_all_list' => false ) ) as $state ) {
			$total_posts -= $num_posts->$state;
		}

		if ( $this->user_posts_count && $this->user_posts_count !== $total_posts ) {
			if ( isset( $_GET['author'] ) && ( $current_user_id === (int) $_GET['author'] ) ) {
				$class = 'current';
			}

			$mine_args = array(
				'post_type' => $post_type,
				'author'    => $current_user_id,
			);

			$mine_inner_html = sprintf(
				/* translators: %s: Number of posts. */
				_nx(
					'Mine <span class="count">(%s)</span>',
					'Mine <span class="count">(%s)</span>',
					$this->user_posts_count,
					'posts'
				),
				number_format_i18n( $this->user_posts_count )
			);

			$mine = array(
				'url'     => esc_url( add_query_arg( $mine_args, 'edit.php' ) ),
				'label'   => $mine_inner_html,
				'current' => isset( $_GET['author'] ) && ( $current_user_id === (int) $_GET['author'] ),
			);

			$all_args['all_posts'] = 1;
			$class                 = '';
		}

		$all_inner_html = sprintf(
			/* translators: %s: Number of posts. */
			_nx(
				'All <span class="count">(%s)</span>',
				'All <span class="count">(%s)</span>',
				$total_posts,
				'posts'
			),
			number_format_i18n( $total_posts )
		);

		$status_links['all'] = array(
			'url'     => esc_url( add_query_arg( $all_args, 'edit.php' ) ),
			'label'   => $all_inner_html,
			'current' => empty( $class ) && ( $this->is_base_request() || isset( $_REQUEST['all_posts'] ) ),
		);

		if ( $mine ) {
			$status_links['mine'] = $mine;
		}

		foreach ( get_post_stati( array( 'show_in_admin_status_list' => true ), 'objects' ) as $status ) {
			$class = '';

			$status_name = $status->name;

			if ( ! in_array( $status_name, $avail_post_stati, true ) || empty( $num_posts->$status_name ) ) {
				continue;
			}

			if ( isset( $_REQUEST['post_status'] ) && $status_name === $_REQUEST['post_status'] ) {
				$class = 'current';
			}

			$status_args = array(
				'post_status' => $status_name,
				'post_type'   => $post_type,
			);

			$status_label = sprintf(
				translate_nooped_plural( $status->label_count, $num_posts->$status_name ),
				number_format_i18n( $num_posts->$status_name )
			);

			$status_links[ $status_name ] = array(
				'url'     => esc_url( add_query_arg( $status_args, 'edit.php' ) ),
				'label'   => $status_label,
				'current' => isset( $_REQUEST['post_status'] ) && $status_name === $_REQUEST['post_status'],
			);
		}

		if ( ! empty( $this->sticky_posts_count ) ) {
			$class = ! empty( $_REQUEST['show_sticky'] ) ? 'current' : '';

			$sticky_args = array(
				'post_type'   => $post_type,
				'show_sticky' => 1,
			);

			$sticky_inner_html = sprintf(
				/* translators: %s: Number of posts. */
				_nx(
					'Sticky <span class="count">(%s)</span>',
					'Sticky <span class="count">(%s)</span>',
					$this->sticky_posts_count,
					'posts'
				),
				number_format_i18n( $this->sticky_posts_count )
			);

			$sticky_link = array(
				'sticky' => array(
					'url'     => esc_url( add_query_arg( $sticky_args, 'edit.php' ) ),
					'label'   => $sticky_inner_html,
					'current' => ! empty( $_REQUEST['show_sticky'] ),
				),
			);

			// Sticky comes after Publish, or if not listed, after All.
			$split        = 1 + array_search( ( isset( $status_links['publish'] ) ? 'publish' : 'all' ), array_keys( $status_links ), true );
			$status_links = array_merge( array_slice( $status_links, 0, $split ), $sticky_link, array_slice( $status_links, $split ) );
		}

		return $this->get_views_links( $status_links );
	}

	/**
	 * @return array
	 */
	protected function get_bulk_actions() {
		$actions       = array();
		$post_type_obj = get_post_type_object( $this->screen->post_type );

		if ( current_user_can( $post_type_obj->cap->edit_posts ) ) {
			if ( $this->is_trash ) {
				$actions['untrash'] = __( 'Restore' );
			} else {
				$actions['edit'] = __( 'Edit' );
			}
		}

		if ( current_user_can( $post_type_obj->cap->delete_posts ) ) {
			if ( $this->is_trash || ! EMPTY_TRASH_DAYS ) {
				$actions['delete'] = __( 'Delete permanently' );
			} else {
				$actions['trash'] = __( 'Move to Trash' );
			}
		}

		return $actions;
	}

	/**
	 * Displays a categories drop-down for filtering on the Posts list table.
	 *
	 * @since 4.6.0
	 *
	 * @global int $cat Currently selected category.
	 *
	 * @param string $post_type Post type slug.
	 */
	protected function categories_dropdown( $post_type ) {
		global $cat;

		/**
		 * Filters whether to remove the 'Categories' drop-down from the post list table.
		 *
		 * @since 4.6.0
		 *
		 * @param bool   $disable   Whether to disable the categories drop-down. Default false.
		 * @param string $post_type Post type slug.
		 */
		if ( false !== apply_filters( 'disable_categories_dropdown', false, $post_type ) ) {
			return;
		}

		if ( is_object_in_taxonomy( $post_type, 'category' ) ) {
			$dropdown_options = array(
				'show_option_all' => get_taxonomy( 'category' )->labels->all_items,
				'hide_empty'      => 0,
				'hierarchical'    => 1,
				'show_count'      => 0,
				'orderby'         => 'name',
				'selected'        => $cat,
			);

			echo '<label class="screen-reader-text" for="cat">' . get_taxonomy( 'category' )->labels->filter_by_item . '</label>';

			wp_dropdown_categories( $dropdown_options );
		}
	}

	/**
	 * Displays a formats drop-down for filtering items.
	 *
	 * @since 5.2.0
	 *
	 * @param string $post_type Post type slug.
	 */
	protected function formats_dropdown( $post_type ) {
		/**
		 * Filters whether to remove the 'Formats' drop-down from the post list table.
		 *
		 * @since 5.2.0
		 * @since 5.5.0 The `$post_type` parameter was added.
		 *
		 * @param bool   $disable   Whether to disable the drop-down. Default false.
		 * @param string $post_type Post type slug.
		 */
		if ( apply_filters( 'disable_formats_dropdown', false, $post_type ) ) {
			return;
		}

		// Return if the post type doesn't have post formats or if we're in the Trash.
		if ( ! is_object_in_taxonomy( $post_type, 'post_format' ) || $this->is_trash ) {
			return;
		}

		// Make sure the dropdown shows only formats with a post count greater than 0.
		$used_post_formats = get_terms(
			array(
				'taxonomy'   => 'post_format',
				'hide_empty' => true,
			)
		);

		// Return if there are no posts using formats.
		if ( ! $used_post_formats ) {
			return;
		}

		$displayed_post_format = isset( $_GET['post_format'] ) ? $_GET['post_format'] : '';
		?>
		<label for="filter-by-format" class="screen-reader-text">
			<?php
			/* translators: Hidden accessibility text. */
			_e( 'Filter by post format' );
			?>
		</label>
		<select name="post_format" id="filter-by-format">
			<option<?php selected( $displayed_post_format, '' ); ?> value=""><?php _e( 'All formats' ); ?></option>
			<?php
			foreach ( $used_post_formats as $used_post_format ) {
				// Post format slug.
				$slug = str_replace( 'post-format-', '', $used_post_format->slug );
				// Pretty, translated version of the post format slug.
				$pretty_name = get_post_format_string( $slug );

				// Skip the standard post format.
				if ( 'standard' === $slug ) {
					continue;
				}
				?>
				<option<?php selected( $displayed_post_format, $slug ); ?> value="<?php echo esc_attr( $slug ); ?>"><?php echo esc_html( $pretty_name ); ?></option>
				<?php
			}
			?>
		</select>
		<?php
	}

	/**
	 * @param string $which
	 */
	protected function extra_tablenav( $which ) {
		?>
		<div class="alignleft actions">
		<?php
		if ( 'top' === $which ) {
			ob_start();

			$this->months_dropdown( $this->screen->post_type );
			$this->categories_dropdown( $this->screen->post_type );
			$this->formats_dropdown( $this->screen->post_type );

			/**
			 * Fires before the Filter button on the Posts and Pages list tables.
			 *
			 * The Filter button allows sorting by date and/or category on the
			 * Posts list table, and sorting by date on the Pages list table.
			 *
			 * @since 2.1.0
			 * @since 4.4.0 The `$post_type` parameter was added.
			 * @since 4.6.0 The `$which` parameter was added.
			 *
			 * @param string $post_type The post type slug.
			 * @param string $which     The location of the extra table nav markup:
			 *                          'top' or 'bottom' for WP_Posts_List_Table,
			 *                          'bar' for WP_Media_List_Table.
			 */
			do_action( 'restrict_manage_posts', $this->screen->post_type, $which );

			$output = ob_get_clean();

			if ( ! empty( $output ) ) {
				echo $output;
				submit_button( __( 'Filter' ), '', 'filter_action', false, array( 'id' => 'post-query-submit' ) );
			}
		}

		if ( $this->is_trash && $this->has_items()
			&& current_user_can( get_post_type_object( $this->screen->post_type )->cap->edit_others_posts )
		) {
			submit_button( __( 'Empty Trash' ), 'apply', 'delete_all', false );
		}
		?>
		</div>
		<?php
		/**
		 * Fires immediately following the closing "actions" div in the tablenav for the posts
		 * list table.
		 *
		 * @since 4.4.0
		 *
		 * @param string $which The location of the extra table nav markup: 'top' or 'bottom'.
		 */
		do_action( 'manage_posts_extra_tablenav', $which );
	}

	/**
	 * @return string
	 */
	public function current_action() {
		if ( isset( $_REQUEST['delete_all'] ) || isset( $_REQUEST['delete_all2'] ) ) {
			return 'delete_all';
		}

		return parent::current_action();
	}

	/**
	 * @global string $mode List table view mode.
	 *
	 * @return array
	 */
	protected function get_table_classes() {
		global $mode;

		$mode_class = esc_attr( 'table-view-' . $mode );

		return array(
			'widefat',
			'fixed',
			'striped',
			$mode_class,
			is_post_type_hierarchical( $this->screen->post_type ) ? 'pages' : 'posts',
		);
	}

	/**
	 * @return string[] Array of column titles keyed by their column name.
	 */
	public function get_columns() {
		$post_type = $this->screen->post_type;

		$posts_columns = array();

		$posts_columns['cb'] = '<input type="checkbox" />';

		/* translators: Posts screen column name. */
		$posts_columns['title'] = _x( 'Title', 'column name' );

		if ( post_type_supports( $post_type, 'author' ) ) {
			$posts_columns['author'] = __( 'Author' );
		}

		$taxonomies = get_object_taxonomies( $post_type, 'objects' );
		$taxonomies = wp_filter_object_list( $taxonomies, array( 'show_admin_column' => true ), 'and', 'name' );

		/**
		 * Filters the taxonomy columns in the Posts list table.
		 *
		 * The dynamic portion of the hook name, `$post_type`, refers to the post
		 * type slug.
		 *
		 * Possible hook names include:
		 *
		 *  - `manage_taxonomies_for_post_columns`
		 *  - `manage_taxonomies_for_page_columns`
		 *
		 * @since 3.5.0
		 *
		 * @param string[] $taxonomies Array of taxonomy names to show columns for.
		 * @param string   $post_type  The post type.
		 */
		$taxonomies = apply_filters( "manage_taxonomies_for_{$post_type}_columns", $taxonomies, $post_type );
		$taxonomies = array_filter( $taxonomies, 'taxonomy_exists' );

		foreach ( $taxonomies as $taxonomy ) {
			if ( 'category' === $taxonomy ) {
				$column_key = 'categories';
			} elseif ( 'post_tag' === $taxonomy ) {
				$column_key = 'tags';
			} else {
				$column_key = 'taxonomy-' . $taxonomy;
			}

			$posts_columns[ $column_key ] = get_taxonomy( $taxonomy )->labels->name;
		}

		$post_status = ! empty( $_REQUEST['post_status'] ) ? $_REQUEST['post_status'] : 'all';

		if ( post_type_supports( $post_type, 'comments' )
			&& ! in_array( $post_status, array( 'pending', 'draft', 'future' ), true )
		) {
			$posts_columns['comments'] = sprintf(
				'<span class="vers comment-grey-bubble" title="%1$s" aria-hidden="true"></span><span class="screen-reader-text">%2$s</span>',
				esc_attr__( 'Comments' ),
				/* translators: Hidden accessibility text. */
				__( 'Comments' )
			);
		}

		$posts_columns['date'] = __( 'Date' );

		if ( 'page' === $post_type ) {

			/**
			 * Filters the columns displayed in the Pages list table.
			 *
			 * @since 2.5.0
			 *
			 * @param string[] $posts_columns An associative array of column headings.
			 */
			$posts_columns = apply_filters( 'manage_pages_columns', $posts_columns );
		} else {

			/**
			 * Filters the columns displayed in the Posts list table.
			 *
			 * @since 1.5.0
			 *
			 * @param string[] $posts_columns An associative array of column headings.
			 * @param string   $post_type     The post type slug.
			 */
			$posts_columns = apply_filters( 'manage_posts_columns', $posts_columns, $post_type );
		}

		/**
		 * Filters the columns displayed in the Posts list table for a specific post type.
		 *
		 * The dynamic portion of the hook name, `$post_type`, refers to the post type slug.
		 *
		 * Possible hook names include:
		 *
		 *  - `manage_post_posts_columns`
		 *  - `manage_page_posts_columns`
		 *
		 * @since 3.0.0
		 *
		 * @param string[] $posts_columns An associative array of column headings.
		 */
		return apply_filters( "manage_{$post_type}_posts_columns", $posts_columns );
	}

	/**
	 * @return array
	 */
	protected function get_sortable_columns() {

		$post_type = $this->screen->post_type;

		if ( 'page' === $post_type ) {
			if ( isset( $_GET['orderby'] ) ) {
				$title_orderby_text = __( 'Table ordered by Title.' );
			} else {
				$title_orderby_text = __( 'Table ordered by Hierarchical Menu Order and Title.' );
			}

			$sortables = array(
				'title'    => array( 'title', false, __( 'Title' ), $title_orderby_text, 'asc' ),
				'parent'   => array( 'parent', false ),
				'comments' => array( 'comment_count', false, __( 'Comments' ), __( 'Table ordered by Comments.' ) ),
				'date'     => array( 'date', true, __( 'Date' ), __( 'Table ordered by Date.' ) ),
			);
		} else {
			$sortables = array(
				'title'    => array( 'title', false, __( 'Title' ), __( 'Table ordered by Title.' ) ),
				'parent'   => array( 'parent', false ),
				'comments' => array( 'comment_count', false, __( 'Comments' ), __( 'Table ordered by Comments.' ) ),
				'date'     => array( 'date', true, __( 'Date' ), __( 'Table ordered by Date.' ), 'desc' ),
			);
		}
		// Custom Post Types: there's a filter for that, see get_column_info().

		return $sortables;
	}

	/**
	 * Generates the list table rows.
	 *
	 * @since 3.1.0
	 *
	 * @global WP_Query $wp_query WordPress Query object.
	 * @global int      $per_page
	 *
	 * @param array $posts
	 * @param int   $level
	 */
	public function display_rows( $posts = array(), $level = 0 ) {
		global $wp_query, $per_page;

		if ( empty( $posts ) ) {
			$posts = $wp_query->posts;
		}

		add_filter( 'the_title', 'esc_html' );

		if ( $this->hierarchical_display ) {
			$this->_display_rows_hierarchical( $posts, $this->get_pagenum(), $per_page );
		} else {
			$this->_display_rows( $posts, $level );
		}
	}

	/**
	 * @param array $posts
	 * @param int   $level
	 */
	private function _display_rows( $posts, $level = 0 ) {
		$post_type = $this->screen->post_type;

		// Create array of post IDs.
		$post_ids = array();

		foreach ( $posts as $a_post ) {
			$post_ids[] = $a_post->ID;
		}

		if ( post_type_supports( $post_type, 'comments' ) ) {
			$this->comment_pending_count = get_pending_comments_num( $post_ids );
		}
		update_post_author_caches( $posts );

		foreach ( $posts as $post ) {
			$this->single_row( $post, $level );
		}
	}

	/**
	 * @global wpdb    $wpdb WordPress database abstraction object.
	 * @global WP_Post $post Global post object.
	 * @param array $pages
	 * @param int   $pagenum
	 * @param int   $per_page
	 */
	private function _display_rows_hierarchical( $pages, $pagenum = 1, $per_page = 20 ) {
		global $wpdb;

		$level = 0;

		if ( ! $pages ) {
			$pages = get_pages( array( 'sort_column' => 'menu_order' ) );

			if ( ! $pages ) {
				return;
			}
		}

		/*
		 * Arrange pages into two parts: top level pages and children_pages.
		 * children_pages is two dimensional array. Example:
		 * children_pages[10][] contains all sub-pages whose parent is 10.
		 * It only takes O( N ) to arrange this and it takes O( 1 ) for subsequent lookup operations
		 * If searching, ignore hierarchy and treat everything as top level
		 */
		if ( empty( $_REQUEST['s'] ) ) {
			$top_level_pages = array();
			$children_pages  = array();

			foreach ( $pages as $page ) {
				// Catch and repair bad pages.
				if ( $page->post_parent === $page->ID ) {
					$page->post_parent = 0;
					$wpdb->update( $wpdb->posts, array( 'post_parent' => 0 ), array( 'ID' => $page->ID ) );
					clean_post_cache( $page );
				}

				if ( $page->post_parent > 0 ) {
					$children_pages[ $page->post_parent ][] = $page;
				} else {
					$top_level_pages[] = $page;
				}
			}

			$pages = &$top_level_pages;
		}

		$count      = 0;
		$start      = ( $pagenum - 1 ) * $per_page;
		$end        = $start + $per_page;
		$to_display = array();

		foreach ( $pages as $page ) {
			if ( $count >= $end ) {
				break;
			}

			if ( $count >= $start ) {
				$to_display[ $page->ID ] = $level;
			}

			++$count;

			if ( isset( $children_pages ) ) {
				$this->_page_rows( $children_pages, $count, $page->ID, $level + 1, $pagenum, $per_page, $to_display );
			}
		}

		// If it is the last pagenum and there are orphaned pages, display them with paging as well.
		if ( isset( $children_pages ) && $count < $end ) {
			foreach ( $children_pages as $orphans ) {
				foreach ( $orphans as $op ) {
					if ( $count >= $end ) {
						break;
					}

					if ( $count >= $start ) {
						$to_display[ $op->ID ] = 0;
					}

					++$count;
				}
			}
		}

		$ids = array_keys( $to_display );
		_prime_post_caches( $ids );
		$_posts = array_map( 'get_post', $ids );
		update_post_author_caches( $_posts );

		if ( ! isset( $GLOBALS['post'] ) ) {
			$GLOBALS['post'] = reset( $ids );
		}

		foreach ( $to_display as $page_id => $level ) {
			echo "\t";
			$this->single_row( $page_id, $level );
		}
	}

	/**
	 * Displays the nested hierarchy of sub-pages together with paging
	 * support, based on a top level page ID.
	 *
	 * @since 3.1.0 (Standalone function exists since 2.6.0)
	 * @since 4.2.0 Added the `$to_display` parameter.
	 *
	 * @param array $children_pages
	 * @param int   $count
	 * @param int   $parent_page
	 * @param int   $level
	 * @param int   $pagenum
	 * @param int   $per_page
	 * @param array $to_display List of pages to be displayed. Passed by reference.
	 */
	private function _page_rows( &$children_pages, &$count, $parent_page, $level, $pagenum, $per_page, &$to_display ) {
		if ( ! isset( $children_pages[ $parent_page ] ) ) {
			return;
		}

		$start = ( $pagenum - 1 ) * $per_page;
		$end   = $start + $per_page;

		foreach ( $children_pages[ $parent_page ] as $page ) {
			if ( $count >= $end ) {
				break;
			}

			// If the page starts in a subtree, print the parents.
			if ( $count === $start && $page->post_parent > 0 ) {
				$my_parents = array();
				$my_parent  = $page->post_parent;

				while ( $my_parent ) {
					// Get the ID from the list or the attribute if my_parent is an object.
					$parent_id = $my_parent;

					if ( is_object( $my_parent ) ) {
						$parent_id = $my_parent->ID;
					}

					$my_parent    = get_post( $parent_id );
					$my_parents[] = $my_parent;

					if ( ! $my_parent->post_parent ) {
						break;
					}

					$my_parent = $my_parent->post_parent;
				}

				$num_parents = count( $my_parents );

				while ( $my_parent = array_pop( $my_parents ) ) {
					$to_display[ $my_parent->ID ] = $level - $num_parents;
					--$num_parents;
				}
			}

			if ( $count >= $start ) {
				$to_display[ $page->ID ] = $level;
			}

			++$count;

			$this->_page_rows( $children_pages, $count, $page->ID, $level + 1, $pagenum, $per_page, $to_display );
		}

		unset( $children_pages[ $parent_page ] ); // Required in order to keep track of orphans.
	}

	/**
	 * Handles the checkbox column output.
	 *
	 * @since 4.3.0
	 * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support.
	 *
	 * @param WP_Post $item The current WP_Post object.
	 */
	public function column_cb( $item ) {
		// Restores the more descriptive, specific name for use within this method.
		$post = $item;

		$show = current_user_can( 'edit_post', $post->ID );

		/**
		 * Filters whether to show the bulk edit checkbox for a post in its list table.
		 *
		 * By default the checkbox is only shown if the current user can edit the post.
		 *
		 * @since 5.7.0
		 *
		 * @param bool    $show Whether to show the checkbox.
		 * @param WP_Post $post The current WP_Post object.
		 */
		if ( apply_filters( 'wp_list_table_show_post_checkbox', $show, $post ) ) :
			?>
			<input id="cb-select-<?php the_ID(); ?>" type="checkbox" name="post[]" value="<?php the_ID(); ?>" />
			<label for="cb-select-<?php the_ID(); ?>">
				<span class="screen-reader-text">
				<?php
					/* translators: %s: Post title. */
					printf( __( 'Select %s' ), _draft_or_post_title() );
				?>
				</span>
			</label>
			<div class="locked-indicator">
				<span class="locked-indicator-icon" aria-hidden="true"></span>
				<span class="screen-reader-text">
				<?php
				printf(
					/* translators: Hidden accessibility text. %s: Post title. */
					__( '&#8220;%s&#8221; is locked' ),
					_draft_or_post_title()
				);
				?>
				</span>
			</div>
			<?php
		endif;
	}

	/**
	 * @since 4.3.0
	 *
	 * @param WP_Post $post
	 * @param string  $classes
	 * @param string  $data
	 * @param string  $primary
	 */
	protected function _column_title( $post, $classes, $data, $primary ) {
		echo '<td class="' . $classes . ' page-title" ', $data, '>';
		echo $this->column_title( $post );
		echo $this->handle_row_actions( $post, 'title', $primary );
		echo '</td>';
	}

	/**
	 * Handles the title column output.
	 *
	 * @since 4.3.0
	 *
	 * @global string $mode List table view mode.
	 *
	 * @param WP_Post $post The current WP_Post object.
	 */
	public function column_title( $post ) {
		global $mode;

		if ( $this->hierarchical_display ) {
			if ( 0 === $this->current_level && (int) $post->post_parent > 0 ) {
				// Sent level 0 by accident, by default, or because we don't know the actual level.
				$find_main_page = (int) $post->post_parent;

				while ( $find_main_page > 0 ) {
					$parent = get_post( $find_main_page );

					if ( is_null( $parent ) ) {
						break;
					}

					++$this->current_level;
					$find_main_page = (int) $parent->post_parent;

					if ( ! isset( $parent_name ) ) {
						/** This filter is documented in wp-includes/post-template.php */
						$parent_name = apply_filters( 'the_title', $parent->post_title, $parent->ID );
					}
				}
			}
		}

		$can_edit_post = current_user_can( 'edit_post', $post->ID );

		if ( $can_edit_post && 'trash' !== $post->post_status ) {
			$lock_holder = wp_check_post_lock( $post->ID );

			if ( $lock_holder ) {
				$lock_holder   = get_userdata( $lock_holder );
				$locked_avatar = get_avatar( $lock_holder->ID, 18 );
				/* translators: %s: User's display name. */
				$locked_text = esc_html( sprintf( __( '%s is currently editing' ), $lock_holder->display_name ) );
			} else {
				$locked_avatar = '';
				$locked_text   = '';
			}

			echo '<div class="locked-info"><span class="locked-avatar">' . $locked_avatar . '</span> <span class="locked-text">' . $locked_text . "</span></div>\n";
		}

		$pad = str_repeat( '&#8212; ', $this->current_level );
		echo '<strong>';

		$title = _draft_or_post_title();

		if ( $can_edit_post && 'trash' !== $post->post_status ) {
			printf(
				'<a class="row-title" href="%s" aria-label="%s">%s%s</a>',
				get_edit_post_link( $post->ID ),
				/* translators: %s: Post title. */
				esc_attr( sprintf( __( '&#8220;%s&#8221; (Edit)' ), $title ) ),
				$pad,
				$title
			);
		} else {
			printf(
				'<span>%s%s</span>',
				$pad,
				$title
			);
		}
		_post_states( $post );

		if ( isset( $parent_name ) ) {
			$post_type_object = get_post_type_object( $post->post_type );
			echo ' | ' . $post_type_object->labels->parent_item_colon . ' ' . esc_html( $parent_name );
		}

		echo "</strong>\n";

		if ( 'excerpt' === $mode
			&& ! is_post_type_hierarchical( $this->screen->post_type )
			&& current_user_can( 'read_post', $post->ID )
		) {
			if ( post_password_required( $post ) ) {
				echo '<span class="protected-post-excerpt">' . esc_html( get_the_excerpt() ) . '</span>';
			} else {
				echo esc_html( get_the_excerpt() );
			}
		}

		/** This filter is documented in wp-admin/includes/class-wp-posts-list-table.php */
		$quick_edit_enabled = apply_filters( 'quick_edit_enabled_for_post_type', true, $post->post_type );

		if ( $quick_edit_enabled ) {
			get_inline_data( $post );
		}
	}

	/**
	 * Handles the post date column output.
	 *
	 * @since 4.3.0
	 *
	 * @global string $mode List table view mode.
	 *
	 * @param WP_Post $post The current WP_Post object.
	 */
	public function column_date( $post ) {
		global $mode;

		if ( '0000-00-00 00:00:00' === $post->post_date ) {
			$t_time    = __( 'Unpublished' );
			$time_diff = 0;
		} else {
			$t_time = sprintf(
				/* translators: 1: Post date, 2: Post time. */
				__( '%1$s at %2$s' ),
				/* translators: Post date format. See https://www.php.net/manual/datetime.format.php */
				get_the_time( __( 'Y/m/d' ), $post ),
				/* translators: Post time format. See https://www.php.net/manual/datetime.format.php */
				get_the_time( __( 'g:i a' ), $post )
			);

			$time      = get_post_timestamp( $post );
			$time_diff = time() - $time;
		}

		if ( 'publish' === $post->post_status ) {
			$status = __( 'Published' );
		} elseif ( 'future' === $post->post_status ) {
			if ( $time_diff > 0 ) {
				$status = '<strong class="error-message">' . __( 'Missed schedule' ) . '</strong>';
			} else {
				$status = __( 'Scheduled' );
			}
		} else {
			$status = __( 'Last Modified' );
		}

		/**
		 * Filters the status text of the post.
		 *
		 * @since 4.8.0
		 *
		 * @param string  $status      The status text.
		 * @param WP_Post $post        Post object.
		 * @param string  $column_name The column name.
		 * @param string  $mode        The list display mode ('excerpt' or 'list').
		 */
		$status = apply_filters( 'post_date_column_status', $status, $post, 'date', $mode );

		if ( $status ) {
			echo $status . '<br />';
		}

		/**
		 * Filters the published, scheduled, or unpublished time of the post.
		 *
		 * @since 2.5.1
		 * @since 5.5.0 Removed the difference between 'excerpt' and 'list' modes.
		 *              The published time and date are both displayed now,
		 *              which is equivalent to the previous 'excerpt' mode.
		 *
		 * @param string  $t_time      The published time.
		 * @param WP_Post $post        Post object.
		 * @param string  $column_name The column name.
		 * @param string  $mode        The list display mode ('excerpt' or 'list').
		 */
		echo apply_filters( 'post_date_column_time', $t_time, $post, 'date', $mode );
	}

	/**
	 * Handles the comments column output.
	 *
	 * @since 4.3.0
	 *
	 * @param WP_Post $post The current WP_Post object.
	 */
	public function column_comments( $post ) {
		?>
		<div class="post-com-count-wrapper">
		<?php
			$pending_comments = isset( $this->comment_pending_count[ $post->ID ] ) ? $this->comment_pending_count[ $post->ID ] : 0;

			$this->comments_bubble( $post->ID, $pending_comments );
		?>
		</div>
		<?php
	}

	/**
	 * Handles the post author column output.
	 *
	 * @since 4.3.0
	 * @since 6.8.0 Added fallback text when author's name is unknown.
	 *
	 * @param WP_Post $post The current WP_Post object.
	 */
	public function column_author( $post ) {
		$author = get_the_author();

		if ( ! empty( $author ) ) {
			$args = array(
				'post_type' => $post->post_type,
				'author'    => get_the_author_meta( 'ID' ),
			);
			echo $this->get_edit_link( $args, esc_html( $author ) );
		} else {
			echo '<span aria-hidden="true">&#8212;</span><span class="screen-reader-text">' . __( '(no author)' ) . '</span>';
		}
	}

	/**
	 * Handles the default column output.
	 *
	 * @since 4.3.0
	 * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support.
	 *
	 * @param WP_Post $item        The current WP_Post object.
	 * @param string  $column_name The current column name.
	 */
	public function column_default( $item, $column_name ) {
		// Restores the more descriptive, specific name for use within this method.
		$post = $item;

		if ( 'categories' === $column_name ) {
			$taxonomy = 'category';
		} elseif ( 'tags' === $column_name ) {
			$taxonomy = 'post_tag';
		} elseif ( str_starts_with( $column_name, 'taxonomy-' ) ) {
			$taxonomy = substr( $column_name, 9 );
		} else {
			$taxonomy = false;
		}

		if ( $taxonomy ) {
			$taxonomy_object = get_taxonomy( $taxonomy );
			$terms           = get_the_terms( $post->ID, $taxonomy );

			if ( is_array( $terms ) ) {
				$term_links = array();

				foreach ( $terms as $t ) {
					$posts_in_term_qv = array();

					if ( 'post' !== $post->post_type ) {
						$posts_in_term_qv['post_type'] = $post->post_type;
					}

					if ( $taxonomy_object->query_var ) {
						$posts_in_term_qv[ $taxonomy_object->query_var ] = $t->slug;
					} else {
						$posts_in_term_qv['taxonomy'] = $taxonomy;
						$posts_in_term_qv['term']     = $t->slug;
					}

					$label = esc_html( sanitize_term_field( 'name', $t->name, $t->term_id, $taxonomy, 'display' ) );

					$term_links[] = $this->get_edit_link( $posts_in_term_qv, $label );
				}

				/**
				 * Filters the links in `$taxonomy` column of edit.php.
				 *
				 * @since 5.2.0
				 *
				 * @param string[]  $term_links Array of term editing links.
				 * @param string    $taxonomy   Taxonomy name.
				 * @param WP_Term[] $terms      Array of term objects appearing in the post row.
				 */
				$term_links = apply_filters( 'post_column_taxonomy_links', $term_links, $taxonomy, $terms );

				echo implode( wp_get_list_item_separator(), $term_links );
			} else {
				echo '<span aria-hidden="true">&#8212;</span><span class="screen-reader-text">' . $taxonomy_object->labels->no_terms . '</span>';
			}
			return;
		}

		if ( is_post_type_hierarchical( $post->post_type ) ) {

			/**
			 * Fires in each custom column on the Posts list table.
			 *
			 * This hook only fires if the current post type is hierarchical,
			 * such as pages.
			 *
			 * @since 2.5.0
			 *
			 * @param string $column_name The name of the column to display.
			 * @param int    $post_id     The current post ID.
			 */
			do_action( 'manage_pages_custom_column', $column_name, $post->ID );
		} else {

			/**
			 * Fires in each custom column in the Posts list table.
			 *
			 * This hook only fires if the current post type is non-hierarchical,
			 * such as posts.
			 *
			 * @since 1.5.0
			 *
			 * @param string $column_name The name of the column to display.
			 * @param int    $post_id     The current post ID.
			 */
			do_action( 'manage_posts_custom_column', $column_name, $post->ID );
		}

		/**
		 * Fires for each custom column of a specific post type in the Posts list table.
		 *
		 * The dynamic portion of the hook name, `$post->post_type`, refers to the post type.
		 *
		 * Possible hook names include:
		 *
		 *  - `manage_post_posts_custom_column`
		 *  - `manage_page_posts_custom_column`
		 *
		 * @since 3.1.0
		 *
		 * @param string $column_name The name of the column to display.
		 * @param int    $post_id     The current post ID.
		 */
		do_action( "manage_{$post->post_type}_posts_custom_column", $column_name, $post->ID );
	}

	/**
	 * @global WP_Post $post Global post object.
	 *
	 * @param int|WP_Post $post
	 * @param int         $level
	 */
	public function single_row( $post, $level = 0 ) {
		$global_post = get_post();

		$post                = get_post( $post );
		$this->current_level = $level;

		$GLOBALS['post'] = $post;
		setup_postdata( $post );

		$classes = 'iedit author-' . ( get_current_user_id() === (int) $post->post_author ? 'self' : 'other' );

		$lock_holder = wp_check_post_lock( $post->ID );

		if ( $lock_holder ) {
			$classes .= ' wp-locked';
		}

		if ( $post->post_parent ) {
			$count    = count( get_post_ancestors( $post->ID ) );
			$classes .= ' level-' . $count;
		} else {
			$classes .= ' level-0';
		}
		?>
		<tr id="post-<?php echo $post->ID; ?>" class="<?php echo implode( ' ', get_post_class( $classes, $post->ID ) ); ?>">
			<?php $this->single_row_columns( $post ); ?>
		</tr>
		<?php
		$GLOBALS['post'] = $global_post;
	}

	/**
	 * Gets the name of the default primary column.
	 *
	 * @since 4.3.0
	 *
	 * @return string Name of the default primary column, in this case, 'title'.
	 */
	protected function get_default_primary_column_name() {
		return 'title';
	}

	/**
	 * Generates and displays row action links.
	 *
	 * @since 4.3.0
	 * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support.
	 *
	 * @param WP_Post $item        Post being acted upon.
	 * @param string  $column_name Current column name.
	 * @param string  $primary     Primary column name.
	 * @return string Row actions output for posts, or an empty string
	 *                if the current column is not the primary column.
	 */
	protected function handle_row_actions( $item, $column_name, $primary ) {
		if ( $primary !== $column_name ) {
			return '';
		}

		// Restores the more descriptive, specific name for use within this method.
		$post = $item;

		$post_type_object = get_post_type_object( $post->post_type );
		$can_edit_post    = current_user_can( 'edit_post', $post->ID );
		$actions          = array();
		$title            = _draft_or_post_title();

		if ( $can_edit_post && 'trash' !== $post->post_status ) {
			$actions['edit'] = sprintf(
				'<a href="%s" aria-label="%s">%s</a>',
				get_edit_post_link( $post->ID ),
				/* translators: %s: Post title. */
				esc_attr( sprintf( __( 'Edit &#8220;%s&#8221;' ), $title ) ),
				__( 'Edit' )
			);

			/**
			 * Filters whether Quick Edit should be enabled for the given post type.
			 *
			 * @since 6.4.0
			 *
			 * @param bool   $enable    Whether to enable the Quick Edit functionality. Default true.
			 * @param string $post_type Post type name.
			 */
			$quick_edit_enabled = apply_filters( 'quick_edit_enabled_for_post_type', true, $post->post_type );

			if ( $quick_edit_enabled && 'wp_block' !== $post->post_type ) {
				$actions['inline hide-if-no-js'] = sprintf(
					'<button type="button" class="button-link editinline" aria-label="%s" aria-expanded="false">%s</button>',
					/* translators: %s: Post title. */
					esc_attr( sprintf( __( 'Quick edit &#8220;%s&#8221; inline' ), $title ) ),
					__( 'Quick&nbsp;Edit' )
				);
			}
		}

		if ( current_user_can( 'delete_post', $post->ID ) ) {
			if ( 'trash' === $post->post_status ) {
				$actions['untrash'] = sprintf(
					'<a href="%s" aria-label="%s">%s</a>',
					wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&amp;action=untrash', $post->ID ) ), 'untrash-post_' . $post->ID ),
					/* translators: %s: Post title. */
					esc_attr( sprintf( __( 'Restore &#8220;%s&#8221; from the Trash' ), $title ) ),
					__( 'Restore' )
				);
			} elseif ( EMPTY_TRASH_DAYS ) {
				$actions['trash'] = sprintf(
					'<a href="%s" class="submitdelete" aria-label="%s">%s</a>',
					get_delete_post_link( $post->ID ),
					/* translators: %s: Post title. */
					esc_attr( sprintf( __( 'Move &#8220;%s&#8221; to the Trash' ), $title ) ),
					_x( 'Trash', 'verb' )
				);
			}

			if ( 'trash' === $post->post_status || ! EMPTY_TRASH_DAYS ) {
				$actions['delete'] = sprintf(
					'<a href="%s" class="submitdelete" aria-label="%s">%s</a>',
					get_delete_post_link( $post->ID, '', true ),
					/* translators: %s: Post title. */
					esc_attr( sprintf( __( 'Delete &#8220;%s&#8221; permanently' ), $title ) ),
					__( 'Delete Permanently' )
				);
			}
		}

		if ( is_post_type_viewable( $post_type_object ) ) {
			if ( in_array( $post->post_status, array( 'pending', 'draft', 'future' ), true ) ) {
				if ( $can_edit_post ) {
					$preview_link    = get_preview_post_link( $post );
					$actions['view'] = sprintf(
						'<a href="%s" rel="bookmark" aria-label="%s">%s</a>',
						esc_url( $preview_link ),
						/* translators: %s: Post title. */
						esc_attr( sprintf( __( 'Preview &#8220;%s&#8221;' ), $title ) ),
						__( 'Preview' )
					);
				}
			} elseif ( 'trash' !== $post->post_status ) {
				$actions['view'] = sprintf(
					'<a href="%s" rel="bookmark" aria-label="%s">%s</a>',
					get_permalink( $post->ID ),
					/* translators: %s: Post title. */
					esc_attr( sprintf( __( 'View &#8220;%s&#8221;' ), $title ) ),
					__( 'View' )
				);
			}
		}

		if ( 'wp_block' === $post->post_type ) {
			$actions['export'] = sprintf(
				'<button type="button" class="wp-list-reusable-blocks__export button-link" data-id="%s" aria-label="%s">%s</button>',
				$post->ID,
				/* translators: %s: Post title. */
				esc_attr( sprintf( __( 'Export &#8220;%s&#8221; as JSON' ), $title ) ),
				__( 'Export as JSON' )
			);
		}

		if ( is_post_type_hierarchical( $post->post_type ) ) {

			/**
			 * Filters the array of row action links on the Pages list table.
			 *
			 * The filter is evaluated only for hierarchical post types.
			 *
			 * @since 2.8.0
			 *
			 * @param string[] $actions An array of row action links. Defaults are
			 *                          'Edit', 'Quick Edit', 'Restore', 'Trash',
			 *                          'Delete Permanently', 'Preview', and 'View'.
			 * @param WP_Post  $post    The post object.
			 */
			$actions = apply_filters( 'page_row_actions', $actions, $post );
		} else {

			/**
			 * Filters the array of row action links on the Posts list table.
			 *
			 * The filter is evaluated only for non-hierarchical post types.
			 *
			 * @since 2.8.0
			 *
			 * @param string[] $actions An array of row action links. Defaults are
			 *                          'Edit', 'Quick Edit', 'Restore', 'Trash',
			 *                          'Delete Permanently', 'Preview', and 'View'.
			 * @param WP_Post  $post    The post object.
			 */
			$actions = apply_filters( 'post_row_actions', $actions, $post );
		}

		return $this->row_actions( $actions );
	}

	/**
	 * Outputs the hidden row displayed when inline editing
	 *
	 * @since 3.1.0
	 *
	 * @global string $mode List table view mode.
	 */
	public function inline_edit() {
		global $mode;

		$screen = $this->screen;

		$post             = get_default_post_to_edit( $screen->post_type );
		$post_type_object = get_post_type_object( $screen->post_type );

		$taxonomy_names          = get_object_taxonomies( $screen->post_type );
		$hierarchical_taxonomies = array();
		$flat_taxonomies         = array();

		foreach ( $taxonomy_names as $taxonomy_name ) {
			$taxonomy = get_taxonomy( $taxonomy_name );

			$show_in_quick_edit = $taxonomy->show_in_quick_edit;

			/**
			 * Filters whether the current taxonomy should be shown in the Quick Edit panel.
			 *
			 * @since 4.2.0
			 *
			 * @param bool   $show_in_quick_edit Whether to show the current taxonomy in Quick Edit.
			 * @param string $taxonomy_name      Taxonomy name.
			 * @param string $post_type          Post type of current Quick Edit post.
			 */
			if ( ! apply_filters( 'quick_edit_show_taxonomy', $show_in_quick_edit, $taxonomy_name, $screen->post_type ) ) {
				continue;
			}

			if ( $taxonomy->hierarchical ) {
				$hierarchical_taxonomies[] = $taxonomy;
			} else {
				$flat_taxonomies[] = $taxonomy;
			}
		}

		$m            = ( isset( $mode ) && 'excerpt' === $mode ) ? 'excerpt' : 'list';
		$can_publish  = current_user_can( $post_type_object->cap->publish_posts );
		$core_columns = array(
			'cb'         => true,
			'date'       => true,
			'title'      => true,
			'categories' => true,
			'tags'       => true,
			'comments'   => true,
			'author'     => true,
		);
		?>

		<form method="get">
		<table style="display: none"><tbody id="inlineedit">
		<?php
		$hclass              = count( $hierarchical_taxonomies ) ? 'post' : 'page';
		$inline_edit_classes = "inline-edit-row inline-edit-row-$hclass";
		$bulk_edit_classes   = "bulk-edit-row bulk-edit-row-$hclass bulk-edit-{$screen->post_type}";
		$quick_edit_classes  = "quick-edit-row quick-edit-row-$hclass inline-edit-{$screen->post_type}";

		$bulk = 0;

		while ( $bulk < 2 ) :
			$classes  = $inline_edit_classes . ' ';
			$classes .= $bulk ? $bulk_edit_classes : $quick_edit_classes;
			?>
			<tr id="<?php echo $bulk ? 'bulk-edit' : 'inline-edit'; ?>" class="<?php echo $classes; ?>" style="display: none">
			<td colspan="<?php echo $this->get_column_count(); ?>" class="colspanchange">
			<div class="inline-edit-wrapper" role="region" aria-labelledby="<?php echo $bulk ? 'bulk' : 'quick'; ?>-edit-legend">
			<fieldset class="inline-edit-col-left">
				<legend class="inline-edit-legend" id="<?php echo $bulk ? 'bulk' : 'quick'; ?>-edit-legend"><?php echo $bulk ? __( 'Bulk Edit' ) : __( 'Quick Edit' ); ?></legend>
				<div class="inline-edit-col">

				<?php if ( post_type_supports( $screen->post_type, 'title' ) ) : ?>

					<?php if ( $bulk ) : ?>

						<div id="bulk-title-div">
							<div id="bulk-titles"></div>
						</div>

					<?php else : // $bulk ?>

						<label>
							<span class="title"><?php _e( 'Title' ); ?></span>
							<span class="input-text-wrap"><input type="text" name="post_title" class="ptitle" value="" /></span>
						</label>

						<?php if ( is_post_type_viewable( $screen->post_type ) ) : ?>

							<label>
								<span class="title"><?php _e( 'Slug' ); ?></span>
								<span class="input-text-wrap"><input type="text" name="post_name" value="" autocomplete="off" spellcheck="false" /></span>
							</label>

						<?php endif; // is_post_type_viewable() ?>

					<?php endif; // $bulk ?>

				<?php endif; // post_type_supports( ... 'title' ) ?>

				<?php if ( ! $bulk ) : ?>
					<fieldset class="inline-edit-date">
						<legend><span class="title"><?php _e( 'Date' ); ?></span></legend>
						<?php touch_time( 1, 1, 0, 1 ); ?>
					</fieldset>
					<br class="clear" />
				<?php endif; // $bulk ?>

				<?php
				if ( post_type_supports( $screen->post_type, 'author' ) ) {
					$authors_dropdown = '';

					if ( current_user_can( $post_type_object->cap->edit_others_posts ) ) {
						$dropdown_name  = 'post_author';
						$dropdown_class = 'authors';
						if ( wp_is_large_user_count() ) {
							$authors_dropdown = sprintf( '<select name="%s" class="%s hidden"></select>', esc_attr( $dropdown_name ), esc_attr( $dropdown_class ) );
						} else {
							$users_opt = array(
								'hide_if_only_one_author' => false,
								'capability'              => array( $post_type_object->cap->edit_posts ),
								'name'                    => $dropdown_name,
								'class'                   => $dropdown_class,
								'multi'                   => 1,
								'echo'                    => 0,
								'show'                    => 'display_name_with_login',
							);

							if ( $bulk ) {
								$users_opt['show_option_none'] = __( '&mdash; No Change &mdash;' );
							}

							/**
							 * Filters the arguments used to generate the Quick Edit authors drop-down.
							 *
							 * @since 5.6.0
							 *
							 * @see wp_dropdown_users()
							 *
							 * @param array $users_opt An array of arguments passed to wp_dropdown_users().
							 * @param bool $bulk A flag to denote if it's a bulk action.
							 */
							$users_opt = apply_filters( 'quick_edit_dropdown_authors_args', $users_opt, $bulk );

							$authors = wp_dropdown_users( $users_opt );

							if ( $authors ) {
								$authors_dropdown  = '<label class="inline-edit-author">';
								$authors_dropdown .= '<span class="title">' . __( 'Author' ) . '</span>';
								$authors_dropdown .= $authors;
								$authors_dropdown .= '</label>';
							}
						}
					} // current_user_can( 'edit_others_posts' )

					if ( ! $bulk ) {
						echo $authors_dropdown;
					}
				} // post_type_supports( ... 'author' )
				?>

				<?php if ( ! $bulk && $can_publish ) : ?>

					<div class="inline-edit-group wp-clearfix">
						<label class="alignleft">
							<span class="title"><?php _e( 'Password' ); ?></span>
							<span class="input-text-wrap"><input type="text" name="post_password" class="inline-edit-password-input" value="" /></span>
						</label>

						<span class="alignleft inline-edit-or">
							<?php
							/* translators: Between password field and private checkbox on post quick edit interface. */
							_e( '&ndash;OR&ndash;' );
							?>
						</span>
						<label class="alignleft inline-edit-private">
							<input type="checkbox" name="keep_private" value="private" />
							<span class="checkbox-title"><?php _e( 'Private' ); ?></span>
						</label>
					</div>

				<?php endif; ?>

				</div>
			</fieldset>

			<?php if ( count( $hierarchical_taxonomies ) && ! $bulk ) : ?>

				<fieldset class="inline-edit-col-center inline-edit-categories">
					<div class="inline-edit-col">

					<?php foreach ( $hierarchical_taxonomies as $taxonomy ) : ?>

						<span class="title inline-edit-categories-label"><?php echo esc_html( $taxonomy->labels->name ); ?></span>
						<input type="hidden" name="<?php echo ( 'category' === $taxonomy->name ) ? 'post_category[]' : 'tax_input[' . esc_attr( $taxonomy->name ) . '][]'; ?>" value="0" />
						<ul class="cat-checklist <?php echo esc_attr( $taxonomy->name ); ?>-checklist">
							<?php wp_terms_checklist( 0, array( 'taxonomy' => $taxonomy->name ) ); ?>
						</ul>

					<?php endforeach; // $hierarchical_taxonomies as $taxonomy ?>

					</div>
				</fieldset>

			<?php endif; // count( $hierarchical_taxonomies ) && ! $bulk ?>

			<fieldset class="inline-edit-col-right">
				<div class="inline-edit-col">

				<?php
				if ( post_type_supports( $screen->post_type, 'author' ) && $bulk ) {
					echo $authors_dropdown;
				}
				?>

				<?php if ( post_type_supports( $screen->post_type, 'page-attributes' ) ) : ?>

					<?php if ( $post_type_object->hierarchical ) : ?>

						<label>
							<span class="title"><?php _e( 'Parent' ); ?></span>
							<?php
							$dropdown_args = array(
								'post_type'         => $post_type_object->name,
								'selected'          => $post->post_parent,
								'name'              => 'post_parent',
								'show_option_none'  => __( 'Main Page (no parent)' ),
								'option_none_value' => 0,
								'sort_column'       => 'menu_order, post_title',
							);

							if ( $bulk ) {
								$dropdown_args['show_option_no_change'] = __( '&mdash; No Change &mdash;' );
								$dropdown_args['id']                    = 'bulk_edit_post_parent';
							}

							/**
							 * Filters the arguments used to generate the Quick Edit page-parent drop-down.
							 *
							 * @since 2.7.0
							 * @since 5.6.0 The `$bulk` parameter was added.
							 *
							 * @see wp_dropdown_pages()
							 *
							 * @param array $dropdown_args An array of arguments passed to wp_dropdown_pages().
							 * @param bool  $bulk          A flag to denote if it's a bulk action.
							 */
							$dropdown_args = apply_filters( 'quick_edit_dropdown_pages_args', $dropdown_args, $bulk );

							wp_dropdown_pages( $dropdown_args );
							?>
						</label>

					<?php endif; // hierarchical ?>

					<?php if ( ! $bulk ) : ?>

						<label>
							<span class="title"><?php _e( 'Order' ); ?></span>
							<span class="input-text-wrap"><input type="text" name="menu_order" class="inline-edit-menu-order-input" value="<?php echo $post->menu_order; ?>" /></span>
						</label>

					<?php endif; // ! $bulk ?>

				<?php endif; // post_type_supports( ... 'page-attributes' ) ?>

				<?php if ( 0 < count( get_page_templates( null, $screen->post_type ) ) ) : ?>

					<label>
						<span class="title"><?php _e( 'Template' ); ?></span>
						<select name="page_template">
							<?php if ( $bulk ) : ?>
							<option value="-1"><?php _e( '&mdash; No Change &mdash;' ); ?></option>
							<?php endif; // $bulk ?>
							<?php
							/** This filter is documented in wp-admin/includes/meta-boxes.php */
							$default_title = apply_filters( 'default_page_template_title', __( 'Default template' ), 'quick-edit' );
							?>
							<option value="default"><?php echo esc_html( $default_title ); ?></option>
							<?php page_template_dropdown( '', $screen->post_type ); ?>
						</select>
					</label>

				<?php endif; ?>

				<?php if ( count( $flat_taxonomies ) && ! $bulk ) : ?>

					<?php foreach ( $flat_taxonomies as $taxonomy ) : ?>

						<?php if ( current_user_can( $taxonomy->cap->assign_terms ) ) : ?>
							<?php $taxonomy_name = esc_attr( $taxonomy->name ); ?>
							<div class="inline-edit-tags-wrap">
							<label class="inline-edit-tags">
								<span class="title"><?php echo esc_html( $taxonomy->labels->name ); ?></span>
								<textarea data-wp-taxonomy="<?php echo $taxonomy_name; ?>" cols="22" rows="1" name="tax_input[<?php echo esc_attr( $taxonomy->name ); ?>]" class="tax_input_<?php echo esc_attr( $taxonomy->name ); ?>" aria-describedby="inline-edit-<?php echo esc_attr( $taxonomy->name ); ?>-desc"></textarea>
							</label>
							<p class="howto" id="inline-edit-<?php echo esc_attr( $taxonomy->name ); ?>-desc"><?php echo esc_html( $taxonomy->labels->separate_items_with_commas ); ?></p>
							</div>
						<?php endif; // current_user_can( 'assign_terms' ) ?>

					<?php endforeach; // $flat_taxonomies as $taxonomy ?>

				<?php endif; // count( $flat_taxonomies ) && ! $bulk ?>

				<?php if ( post_type_supports( $screen->post_type, 'comments' ) || post_type_supports( $screen->post_type, 'trackbacks' ) ) : ?>

					<?php if ( $bulk ) : ?>

						<div class="inline-edit-group wp-clearfix">

						<?php if ( post_type_supports( $screen->post_type, 'comments' ) ) : ?>

							<label class="alignleft">
								<span class="title"><?php _e( 'Comments' ); ?></span>
								<select name="comment_status">
									<option value=""><?php _e( '&mdash; No Change &mdash;' ); ?></option>
									<option value="open"><?php _e( 'Allow' ); ?></option>
									<option value="closed"><?php _e( 'Do not allow' ); ?></option>
								</select>
							</label>

						<?php endif; ?>

						<?php if ( post_type_supports( $screen->post_type, 'trackbacks' ) ) : ?>

							<label class="alignright">
								<span class="title"><?php _e( 'Pings' ); ?></span>
								<select name="ping_status">
									<option value=""><?php _e( '&mdash; No Change &mdash;' ); ?></option>
									<option value="open"><?php _e( 'Allow' ); ?></option>
									<option value="closed"><?php _e( 'Do not allow' ); ?></option>
								</select>
							</label>

						<?php endif; ?>

						</div>

					<?php else : // $bulk ?>

						<div class="inline-edit-group wp-clearfix">

						<?php if ( post_type_supports( $screen->post_type, 'comments' ) ) : ?>

							<label class="alignleft">
								<input type="checkbox" name="comment_status" value="open" />
								<span class="checkbox-title"><?php _e( 'Allow Comments' ); ?></span>
							</label>

						<?php endif; ?>

						<?php if ( post_type_supports( $screen->post_type, 'trackbacks' ) ) : ?>

							<label class="alignleft">
								<input type="checkbox" name="ping_status" value="open" />
								<span class="checkbox-title"><?php _e( 'Allow Pings' ); ?></span>
							</label>

						<?php endif; ?>

						</div>

					<?php endif; // $bulk ?>

				<?php endif; // post_type_supports( ... comments or pings ) ?>

					<div class="inline-edit-group wp-clearfix">

						<label class="inline-edit-status alignleft">
							<span class="title"><?php _e( 'Status' ); ?></span>
							<select name="_status">
								<?php
								$inline_edit_statuses = array();
								if ( $bulk ) {
									$inline_edit_statuses['-1'] = __( '&mdash; No Change &mdash;' );
								}
								// Contributors only get "Unpublished" and "Pending Review".
								if ( $can_publish ) {
									$inline_edit_statuses['publish'] = __( 'Published' );
									$inline_edit_statuses['future']  = __( 'Scheduled' );
									// There is already a checkbox for Private in Single Post Quick Edit. See #63612.
									if ( $bulk ) {
										$inline_edit_statuses['private'] = __( 'Private' );
									}
								}

								$inline_edit_statuses['pending'] = __( 'Pending Review' );
								$inline_edit_statuses['draft']   = __( 'Draft' );

								/**
								 * Filters the statuses available in the Quick Edit and Bulk Edit UI.
								 *
								 * @since 6.9.0
								 *
								 * @param array<string,string> $inline_edit_statuses An array of statuses available in the Quick Edit UI.
								 * @param string               $post_type            The post type slug.
								 * @param bool                 $bulk                 A flag to denote if it's a bulk action.
								 * @param bool                 $can_publish          A flag to denote if the user can publish posts.
								 */
								$inline_edit_statuses = apply_filters( 'quick_edit_statuses', $inline_edit_statuses, $screen->post_type, $bulk, $can_publish );

								foreach ( $inline_edit_statuses as $inline_status_value => $inline_status_text ) :
									?>
									<option value="<?php echo esc_attr( $inline_status_value ); ?>"><?php echo esc_attr( $inline_status_text ); ?></option>
									<?php
								endforeach;
								?>
							</select>
						</label>

						<?php if ( 'post' === $screen->post_type && $can_publish && current_user_can( $post_type_object->cap->edit_others_posts ) ) : ?>

							<?php if ( $bulk ) : ?>

								<label class="alignright">
									<span class="title"><?php _e( 'Sticky' ); ?></span>
									<select name="sticky">
										<option value="-1"><?php _e( '&mdash; No Change &mdash;' ); ?></option>
										<option value="sticky"><?php _e( 'Sticky' ); ?></option>
										<option value="unsticky"><?php _e( 'Not Sticky' ); ?></option>
									</select>
								</label>

							<?php else : // $bulk ?>

								<label class="alignleft">
									<input type="checkbox" name="sticky" value="sticky" />
									<span class="checkbox-title"><?php _e( 'Make this post sticky' ); ?></span>
								</label>

							<?php endif; // $bulk ?>

						<?php endif; // 'post' && $can_publish && current_user_can( 'edit_others_posts' ) ?>

					</div>

				<?php if ( $bulk && current_theme_supports( 'post-formats' ) && post_type_supports( $screen->post_type, 'post-formats' ) ) : ?>
					<?php $post_formats = get_theme_support( 'post-formats' ); ?>

					<label class="alignleft">
						<span class="title"><?php _ex( 'Format', 'post format' ); ?></span>
						<select name="post_format">
							<option value="-1"><?php _e( '&mdash; No Change &mdash;' ); ?></option>
							<option value="0"><?php echo get_post_format_string( 'standard' ); ?></option>
							<?php if ( is_array( $post_formats[0] ) ) : ?>
								<?php foreach ( $post_formats[0] as $format ) : ?>
									<option value="<?php echo esc_attr( $format ); ?>"><?php echo esc_html( get_post_format_string( $format ) ); ?></option>
								<?php endforeach; ?>
							<?php endif; ?>
						</select>
					</label>

				<?php endif; ?>

				</div>
			</fieldset>

			<?php
			list( $columns ) = $this->get_column_info();

			foreach ( $columns as $column_name => $column_display_name ) {
				if ( isset( $core_columns[ $column_name ] ) ) {
					continue;
				}

				if ( $bulk ) {

					/**
					 * Fires once for each column in Bulk Edit mode.
					 *
					 * @since 2.7.0
					 *
					 * @param string $column_name Name of the column to edit.
					 * @param string $post_type   The post type slug.
					 */
					do_action( 'bulk_edit_custom_box', $column_name, $screen->post_type );
				} else {

					/**
					 * Fires once for each column in Quick Edit mode.
					 *
					 * @since 2.7.0
					 *
					 * @param string $column_name Name of the column to edit.
					 * @param string $post_type   The post type slug, or current screen name if this is a taxonomy list table.
					 * @param string $taxonomy    The taxonomy name, if any.
					 */
					do_action( 'quick_edit_custom_box', $column_name, $screen->post_type, '' );
				}
			}
			?>

			<div class="submit inline-edit-save">
				<?php if ( ! $bulk ) : ?>
					<?php wp_nonce_field( 'inlineeditnonce', '_inline_edit', false ); ?>
					<button type="button" class="button button-primary save"><?php _e( 'Update' ); ?></button>
				<?php else : ?>
					<?php submit_button( __( 'Update' ), 'primary', 'bulk_edit', false ); ?>
				<?php endif; ?>

				<button type="button" class="button cancel"><?php _e( 'Cancel' ); ?></button>

				<?php if ( ! $bulk ) : ?>
					<span class="spinner"></span>
				<?php endif; ?>

				<input type="hidden" name="post_view" value="<?php echo esc_attr( $m ); ?>" />
				<input type="hidden" name="screen" value="<?php echo esc_attr( $screen->id ); ?>" />
				<?php if ( ! $bulk && ! post_type_supports( $screen->post_type, 'author' ) ) : ?>
					<input type="hidden" name="post_author" value="<?php echo esc_attr( $post->post_author ); ?>" />
				<?php endif; ?>

				<?php
				wp_admin_notice(
					'<p class="error"></p>',
					array(
						'type'               => 'error',
						'additional_classes' => array( 'notice-alt', 'inline', 'hidden' ),
						'paragraph_wrap'     => false,
					)
				);
				?>
			</div>
		</div> <!-- end of .inline-edit-wrapper -->

			</td></tr>

			<?php
			++$bulk;
		endwhile;
		?>
		</tbody></table>
		</form>
		<?php
	}
}
meta-boxes.php000064400000200536151212616040007325 0ustar00<?php
/**
 * WordPress Administration Meta Boxes API.
 *
 * @package WordPress
 * @subpackage Administration
 */

//
// Post-related Meta Boxes.
//

/**
 * Displays post submit form fields.
 *
 * @since 2.7.0
 *
 * @global string $action
 *
 * @param WP_Post $post Current post object.
 * @param array   $args {
 *     Array of arguments for building the post submit meta box.
 *
 *     @type string   $id       Meta box 'id' attribute.
 *     @type string   $title    Meta box title.
 *     @type callable $callback Meta box display callback.
 *     @type array    $args     Extra meta box arguments.
 * }
 */
function post_submit_meta_box( $post, $args = array() ) {
	global $action;

	$post_id          = (int) $post->ID;
	$post_type        = $post->post_type;
	$post_type_object = get_post_type_object( $post_type );
	$can_publish      = current_user_can( $post_type_object->cap->publish_posts );
	?>
<div class="submitbox" id="submitpost">

<div id="minor-publishing">

	<?php // Hidden submit button early on so that the browser chooses the right button when form is submitted with Return key. ?>
	<div style="display:none;">
		<?php submit_button( __( 'Save' ), '', 'save' ); ?>
	</div>

	<div id="minor-publishing-actions">
		<div id="save-action">
			<?php
			if ( ! in_array( $post->post_status, array( 'publish', 'future', 'pending' ), true ) ) {
				$private_style = '';
				if ( 'private' === $post->post_status ) {
					$private_style = 'style="display:none"';
				}
				?>
				<input <?php echo $private_style; ?> type="submit" name="save" id="save-post" value="<?php esc_attr_e( 'Save Draft' ); ?>" class="button" />
				<span class="spinner"></span>
			<?php } elseif ( 'pending' === $post->post_status && $can_publish ) { ?>
				<input type="submit" name="save" id="save-post" value="<?php esc_attr_e( 'Save as Pending' ); ?>" class="button" />
				<span class="spinner"></span>
			<?php } ?>
		</div>

		<?php
		if ( is_post_type_viewable( $post_type_object ) ) :
			?>
			<div id="preview-action">
				<?php
				$preview_link = esc_url( get_preview_post_link( $post ) );
				if ( 'publish' === $post->post_status ) {
					$preview_button_text = __( 'Preview Changes' );
				} else {
					$preview_button_text = __( 'Preview' );
				}

				$preview_button = sprintf(
					'%1$s<span class="screen-reader-text"> %2$s</span>',
					$preview_button_text,
					/* translators: Hidden accessibility text. */
					__( '(opens in a new tab)' )
				);
				?>
				<a class="preview button" href="<?php echo $preview_link; ?>" target="wp-preview-<?php echo $post_id; ?>" id="post-preview"><?php echo $preview_button; ?></a>
				<input type="hidden" name="wp-preview" id="wp-preview" value="" />
			</div>
			<?php
		endif;

		/**
		 * Fires after the Save Draft (or Save as Pending) and Preview (or Preview Changes) buttons
		 * in the Publish meta box.
		 *
		 * @since 4.4.0
		 *
		 * @param WP_Post $post WP_Post object for the current post.
		 */
		do_action( 'post_submitbox_minor_actions', $post );
		?>
		<div class="clear"></div>
	</div>

	<div id="misc-publishing-actions">
		<div class="misc-pub-section misc-pub-post-status">
			<?php _e( 'Status:' ); ?>
			<span id="post-status-display">
				<?php
				switch ( $post->post_status ) {
					case 'private':
						_e( 'Privately Published' );
						break;
					case 'publish':
						_e( 'Published' );
						break;
					case 'future':
						_e( 'Scheduled' );
						break;
					case 'pending':
						_e( 'Pending Review' );
						break;
					case 'draft':
					case 'auto-draft':
						_e( 'Draft' );
						break;
				}
				?>
			</span>

			<?php
			if ( 'publish' === $post->post_status || 'private' === $post->post_status || $can_publish ) {
				$private_style = '';
				if ( 'private' === $post->post_status ) {
					$private_style = 'style="display:none"';
				}
				?>
				<a href="#post_status" <?php echo $private_style; ?> class="edit-post-status hide-if-no-js" role="button"><span aria-hidden="true"><?php _e( 'Edit' ); ?></span> <span class="screen-reader-text">
					<?php
					/* translators: Hidden accessibility text. */
					_e( 'Edit status' );
					?>
				</span></a>

				<div id="post-status-select" class="hide-if-js">
					<input type="hidden" name="hidden_post_status" id="hidden_post_status" value="<?php echo esc_attr( ( 'auto-draft' === $post->post_status ) ? 'draft' : $post->post_status ); ?>" />
					<label for="post_status" class="screen-reader-text">
						<?php
						/* translators: Hidden accessibility text. */
						_e( 'Set status' );
						?>
					</label>
					<select name="post_status" id="post_status">
						<?php if ( 'publish' === $post->post_status ) : ?>
							<option<?php selected( $post->post_status, 'publish' ); ?> value='publish'><?php _e( 'Published' ); ?></option>
						<?php elseif ( 'private' === $post->post_status ) : ?>
							<option<?php selected( $post->post_status, 'private' ); ?> value='publish'><?php _e( 'Privately Published' ); ?></option>
						<?php elseif ( 'future' === $post->post_status ) : ?>
							<option<?php selected( $post->post_status, 'future' ); ?> value='future'><?php _e( 'Scheduled' ); ?></option>
						<?php endif; ?>
							<option<?php selected( $post->post_status, 'pending' ); ?> value='pending'><?php _e( 'Pending Review' ); ?></option>
						<?php if ( 'auto-draft' === $post->post_status ) : ?>
							<option<?php selected( $post->post_status, 'auto-draft' ); ?> value='draft'><?php _e( 'Draft' ); ?></option>
						<?php else : ?>
							<option<?php selected( $post->post_status, 'draft' ); ?> value='draft'><?php _e( 'Draft' ); ?></option>
						<?php endif; ?>
					</select>
					<a href="#post_status" class="save-post-status hide-if-no-js button"><?php _e( 'OK' ); ?></a>
					<a href="#post_status" class="cancel-post-status hide-if-no-js button-cancel"><?php _e( 'Cancel' ); ?></a>
				</div>
				<?php
			}
			?>
		</div>

		<div class="misc-pub-section misc-pub-visibility" id="visibility">
			<?php _e( 'Visibility:' ); ?>
			<span id="post-visibility-display">
				<?php
				if ( 'private' === $post->post_status ) {
					$post->post_password = '';
					$visibility          = 'private';
					$visibility_trans    = __( 'Private' );
				} elseif ( ! empty( $post->post_password ) ) {
					$visibility       = 'password';
					$visibility_trans = __( 'Password protected' );
				} elseif ( 'post' === $post_type && is_sticky( $post_id ) ) {
					$visibility       = 'public';
					$visibility_trans = __( 'Public, Sticky' );
				} else {
					$visibility       = 'public';
					$visibility_trans = __( 'Public' );
				}

				echo esc_html( $visibility_trans );
				?>
			</span>

			<?php if ( $can_publish ) { ?>
				<a href="#visibility" class="edit-visibility hide-if-no-js" role="button"><span aria-hidden="true"><?php _e( 'Edit' ); ?></span> <span class="screen-reader-text">
					<?php
					/* translators: Hidden accessibility text. */
					_e( 'Edit visibility' );
					?>
				</span></a>

				<div id="post-visibility-select" class="hide-if-js">
					<input type="hidden" name="hidden_post_password" id="hidden-post-password" value="<?php echo esc_attr( $post->post_password ); ?>" />
					<?php if ( 'post' === $post_type ) : ?>
						<input type="checkbox" style="display:none" name="hidden_post_sticky" id="hidden-post-sticky" value="sticky" <?php checked( is_sticky( $post_id ) ); ?> />
					<?php endif; ?>

					<input type="hidden" name="hidden_post_visibility" id="hidden-post-visibility" value="<?php echo esc_attr( $visibility ); ?>" />
					<input type="radio" name="visibility" id="visibility-radio-public" value="public" <?php checked( $visibility, 'public' ); ?> /> <label for="visibility-radio-public" class="selectit"><?php _e( 'Public' ); ?></label><br />

					<?php if ( 'post' === $post_type && current_user_can( 'edit_others_posts' ) ) : ?>
						<span id="sticky-span"><input id="sticky" name="sticky" type="checkbox" value="sticky" <?php checked( is_sticky( $post_id ) ); ?> /> <label for="sticky" class="selectit"><?php _e( 'Stick this post to the front page' ); ?></label><br /></span>
					<?php endif; ?>

					<input type="radio" name="visibility" id="visibility-radio-password" value="password" <?php checked( $visibility, 'password' ); ?> /> <label for="visibility-radio-password" class="selectit"><?php _e( 'Password protected' ); ?></label><br />
					<span id="password-span"><label for="post_password"><?php _e( 'Password:' ); ?></label> <input type="text" name="post_password" id="post_password" value="<?php echo esc_attr( $post->post_password ); ?>"  maxlength="255" /><br /></span>

					<input type="radio" name="visibility" id="visibility-radio-private" value="private" <?php checked( $visibility, 'private' ); ?> /> <label for="visibility-radio-private" class="selectit"><?php _e( 'Private' ); ?></label><br />

					<p>
						<a href="#visibility" class="save-post-visibility hide-if-no-js button"><?php _e( 'OK' ); ?></a>
						<a href="#visibility" class="cancel-post-visibility hide-if-no-js button-cancel"><?php _e( 'Cancel' ); ?></a>
					</p>
				</div>
			<?php } ?>
		</div>

		<?php
		/* translators: Publish box date string. 1: Date, 2: Time. See https://www.php.net/manual/datetime.format.php */
		$date_string = __( '%1$s at %2$s' );
		/* translators: Publish box date format, see https://www.php.net/manual/datetime.format.php */
		$date_format = _x( 'M j, Y', 'publish box date format' );
		/* translators: Publish box time format, see https://www.php.net/manual/datetime.format.php */
		$time_format = _x( 'H:i', 'publish box time format' );

		if ( 0 !== $post_id ) {
			if ( 'future' === $post->post_status ) { // Scheduled for publishing at a future date.
				/* translators: Post date information. %s: Date on which the post is currently scheduled to be published. */
				$stamp = __( 'Scheduled for: %s' );
			} elseif ( 'publish' === $post->post_status || 'private' === $post->post_status ) { // Already published.
				/* translators: Post date information. %s: Date on which the post was published. */
				$stamp = __( 'Published on: %s' );
			} elseif ( '0000-00-00 00:00:00' === $post->post_date_gmt ) { // Draft, 1 or more saves, no date specified.
				$stamp = __( 'Publish <b>immediately</b>' );
			} elseif ( time() < strtotime( $post->post_date_gmt . ' +0000' ) ) { // Draft, 1 or more saves, future date specified.
				/* translators: Post date information. %s: Date on which the post is to be published. */
				$stamp = __( 'Schedule for: %s' );
			} else { // Draft, 1 or more saves, date specified.
				/* translators: Post date information. %s: Date on which the post is to be published. */
				$stamp = __( 'Publish on: %s' );
			}
			$date = sprintf(
				$date_string,
				date_i18n( $date_format, strtotime( $post->post_date ) ),
				date_i18n( $time_format, strtotime( $post->post_date ) )
			);
		} else { // Draft (no saves, and thus no date specified).
			$stamp = __( 'Publish <b>immediately</b>' );
			$date  = sprintf(
				$date_string,
				date_i18n( $date_format, strtotime( current_time( 'mysql' ) ) ),
				date_i18n( $time_format, strtotime( current_time( 'mysql' ) ) )
			);
		}

		if ( ! empty( $args['args']['revisions_count'] ) ) :
			?>
			<div class="misc-pub-section misc-pub-revisions">
				<?php
				/* translators: Post revisions heading. %s: The number of available revisions. */
				printf( __( 'Revisions: %s' ), '<b>' . number_format_i18n( $args['args']['revisions_count'] ) . '</b>' );
				?>
				<a class="hide-if-no-js" href="<?php echo esc_url( get_edit_post_link( $args['args']['revision_id'] ) ); ?>"><span aria-hidden="true"><?php _ex( 'Browse', 'revisions' ); ?></span> <span class="screen-reader-text">
					<?php
					/* translators: Hidden accessibility text. */
					_e( 'Browse revisions' );
					?>
				</span></a>
			</div>
			<?php
		endif;

		if ( $can_publish ) : // Contributors don't get to choose the date of publish.
			?>
			<div class="misc-pub-section curtime misc-pub-curtime">
				<span id="timestamp">
					<?php printf( $stamp, '<b>' . $date . '</b>' ); ?>
				</span>
				<a href="#edit_timestamp" class="edit-timestamp hide-if-no-js" role="button">
					<span aria-hidden="true"><?php _e( 'Edit' ); ?></span>
					<span class="screen-reader-text">
						<?php
						/* translators: Hidden accessibility text. */
						_e( 'Edit date and time' );
						?>
					</span>
				</a>
				<fieldset id="timestampdiv" class="hide-if-js">
					<legend class="screen-reader-text">
						<?php
						/* translators: Hidden accessibility text. */
						_e( 'Date and time' );
						?>
					</legend>
					<?php touch_time( ( 'edit' === $action ), 1 ); ?>
				</fieldset>
			</div>
			<?php
		endif;

		if ( 'draft' === $post->post_status && get_post_meta( $post_id, '_customize_changeset_uuid', true ) ) :
			$message = sprintf(
				/* translators: %s: URL to the Customizer. */
				__( 'This draft comes from your <a href="%s">unpublished customization changes</a>. You can edit, but there is no need to publish now. It will be published automatically with those changes.' ),
				esc_url(
					add_query_arg(
						'changeset_uuid',
						rawurlencode( get_post_meta( $post_id, '_customize_changeset_uuid', true ) ),
						admin_url( 'customize.php' )
					)
				)
			);
			wp_admin_notice(
				$message,
				array(
					'type'               => 'info',
					'additional_classes' => array( 'notice-alt', 'inline' ),
				)
			);
		endif;

		/**
		 * Fires after the post time/date setting in the Publish meta box.
		 *
		 * @since 2.9.0
		 * @since 4.4.0 Added the `$post` parameter.
		 *
		 * @param WP_Post $post WP_Post object for the current post.
		 */
		do_action( 'post_submitbox_misc_actions', $post );
		?>
	</div>
	<div class="clear"></div>
</div>

<div id="major-publishing-actions">
	<?php
	/**
	 * Fires at the beginning of the publishing actions section of the Publish meta box.
	 *
	 * @since 2.7.0
	 * @since 4.9.0 Added the `$post` parameter.
	 *
	 * @param WP_Post|null $post WP_Post object for the current post on Edit Post screen,
	 *                           null on Edit Link screen.
	 */
	do_action( 'post_submitbox_start', $post );
	?>
	<div id="delete-action">
		<?php
		if ( current_user_can( 'delete_post', $post_id ) ) {
			if ( ! EMPTY_TRASH_DAYS ) {
				$delete_text = __( 'Delete permanently' );
			} else {
				$delete_text = __( 'Move to Trash' );
			}
			?>
			<a class="submitdelete deletion" href="<?php echo get_delete_post_link( $post_id ); ?>"><?php echo $delete_text; ?></a>
			<?php
		}
		?>
	</div>

	<div id="publishing-action">
		<span class="spinner"></span>
		<?php
		if ( ! in_array( $post->post_status, array( 'publish', 'future', 'private' ), true ) || 0 === $post_id ) {
			if ( $can_publish ) :
				if ( ! empty( $post->post_date_gmt ) && time() < strtotime( $post->post_date_gmt . ' +0000' ) ) :
					?>
					<input name="original_publish" type="hidden" id="original_publish" value="<?php echo esc_attr_x( 'Schedule', 'post action/button label' ); ?>" />
					<?php submit_button( _x( 'Schedule', 'post action/button label' ), 'primary large', 'publish', false ); ?>
					<?php
				else :
					?>
					<input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e( 'Publish' ); ?>" />
					<?php submit_button( __( 'Publish' ), 'primary large', 'publish', false ); ?>
					<?php
				endif;
			else :
				?>
				<input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e( 'Submit for Review' ); ?>" />
				<?php submit_button( __( 'Submit for Review' ), 'primary large', 'publish', false ); ?>
				<?php
			endif;
		} else {
			?>
			<input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e( 'Update' ); ?>" />
			<?php submit_button( __( 'Update' ), 'primary large', 'save', false, array( 'id' => 'publish' ) ); ?>
			<?php
		}
		?>
	</div>
	<div class="clear"></div>
</div>

</div>
	<?php
}

/**
 * Displays attachment submit form fields.
 *
 * @since 3.5.0
 *
 * @param WP_Post $post Current post object.
 */
function attachment_submit_meta_box( $post ) {
	?>
<div class="submitbox" id="submitpost">

<div id="minor-publishing">

	<?php // Hidden submit button early on so that the browser chooses the right button when form is submitted with Return key. ?>
<div style="display:none;">
	<?php submit_button( __( 'Save' ), '', 'save' ); ?>
</div>


<div id="misc-publishing-actions">
	<div class="misc-pub-section curtime misc-pub-curtime">
		<span id="timestamp">
			<?php
			$uploaded_on = sprintf(
				/* translators: Publish box date string. 1: Date, 2: Time. */
				__( '%1$s at %2$s' ),
				/* translators: Publish box date format, see https://www.php.net/manual/datetime.format.php */
				date_i18n( _x( 'M j, Y', 'publish box date format' ), strtotime( $post->post_date ) ),
				/* translators: Publish box time format, see https://www.php.net/manual/datetime.format.php */
				date_i18n( _x( 'H:i', 'publish box time format' ), strtotime( $post->post_date ) )
			);
			/* translators: Attachment information. %s: Date the attachment was uploaded. */
			printf( __( 'Uploaded on: %s' ), '<b>' . $uploaded_on . '</b>' );
			?>
		</span>
	</div><!-- .misc-pub-section -->

	<?php
	/**
	 * Fires after the 'Uploaded on' section of the Save meta box
	 * in the attachment editing screen.
	 *
	 * @since 3.5.0
	 * @since 4.9.0 Added the `$post` parameter.
	 *
	 * @param WP_Post $post WP_Post object for the current attachment.
	 */
	do_action( 'attachment_submitbox_misc_actions', $post );
	?>
</div><!-- #misc-publishing-actions -->
<div class="clear"></div>
</div><!-- #minor-publishing -->

<div id="major-publishing-actions">
	<div id="delete-action">
	<?php
	if ( current_user_can( 'delete_post', $post->ID ) ) {
		if ( EMPTY_TRASH_DAYS && MEDIA_TRASH ) {
			printf(
				'<a class="submitdelete deletion" href="%1$s">%2$s</a>',
				get_delete_post_link( $post->ID ),
				__( 'Move to Trash' )
			);
		} else {
			$show_confirmation = ! MEDIA_TRASH ? " onclick='return showNotice.warn();'" : '';

			printf(
				'<a class="submitdelete deletion"%1$s href="%2$s">%3$s</a>',
				$show_confirmation,
				get_delete_post_link( $post->ID, '', true ),
				__( 'Delete permanently' )
			);
		}
	}
	?>
	</div>

	<div id="publishing-action">
		<span class="spinner"></span>
		<input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e( 'Update' ); ?>" />
		<input name="save" type="submit" class="button button-primary button-large" id="publish" value="<?php esc_attr_e( 'Update' ); ?>" />
	</div>
	<div class="clear"></div>
</div><!-- #major-publishing-actions -->

</div>

	<?php
}

/**
 * Displays post format form elements.
 *
 * @since 3.1.0
 *
 * @param WP_Post $post Current post object.
 * @param array   $box {
 *     Post formats meta box arguments.
 *
 *     @type string   $id       Meta box 'id' attribute.
 *     @type string   $title    Meta box title.
 *     @type callable $callback Meta box display callback.
 *     @type array    $args     Extra meta box arguments.
 * }
 */
function post_format_meta_box( $post, $box ) {
	if ( current_theme_supports( 'post-formats' ) && post_type_supports( $post->post_type, 'post-formats' ) ) :
		$post_formats = get_theme_support( 'post-formats' );

		if ( is_array( $post_formats[0] ) ) :
			$post_format = get_post_format( $post->ID );
			if ( ! $post_format ) {
				$post_format = '0';
			}
			// Add in the current one if it isn't there yet, in case the active theme doesn't support it.
			if ( $post_format && ! in_array( $post_format, $post_formats[0], true ) ) {
				$post_formats[0][] = $post_format;
			}
			?>
		<div id="post-formats-select">
		<fieldset>
			<legend class="screen-reader-text">
				<?php
				/* translators: Hidden accessibility text. */
				_e( 'Post Formats' );
				?>
			</legend>
			<input type="radio" name="post_format" class="post-format" id="post-format-0" value="0" <?php checked( $post_format, '0' ); ?> /> <label for="post-format-0" class="post-format-icon post-format-standard"><?php echo get_post_format_string( 'standard' ); ?></label>
			<?php foreach ( $post_formats[0] as $format ) : ?>
			<br /><input type="radio" name="post_format" class="post-format" id="post-format-<?php echo esc_attr( $format ); ?>" value="<?php echo esc_attr( $format ); ?>" <?php checked( $post_format, $format ); ?> /> <label for="post-format-<?php echo esc_attr( $format ); ?>" class="post-format-icon post-format-<?php echo esc_attr( $format ); ?>"><?php echo esc_html( get_post_format_string( $format ) ); ?></label>
			<?php endforeach; ?>
		</fieldset>
	</div>
			<?php
	endif;
endif;
}

/**
 * Displays post tags form fields.
 *
 * @since 2.6.0
 *
 * @todo Create taxonomy-agnostic wrapper for this.
 *
 * @param WP_Post $post Current post object.
 * @param array   $box {
 *     Tags meta box arguments.
 *
 *     @type string   $id       Meta box 'id' attribute.
 *     @type string   $title    Meta box title.
 *     @type callable $callback Meta box display callback.
 *     @type array    $args {
 *         Extra meta box arguments.
 *
 *         @type string $taxonomy Taxonomy. Default 'post_tag'.
 *     }
 * }
 */
function post_tags_meta_box( $post, $box ) {
	$defaults = array( 'taxonomy' => 'post_tag' );
	if ( ! isset( $box['args'] ) || ! is_array( $box['args'] ) ) {
		$args = array();
	} else {
		$args = $box['args'];
	}
	$parsed_args           = wp_parse_args( $args, $defaults );
	$tax_name              = esc_attr( $parsed_args['taxonomy'] );
	$taxonomy              = get_taxonomy( $parsed_args['taxonomy'] );
	$user_can_assign_terms = current_user_can( $taxonomy->cap->assign_terms );
	$comma                 = _x( ',', 'tag delimiter' );
	$terms_to_edit         = get_terms_to_edit( $post->ID, $tax_name );
	if ( ! is_string( $terms_to_edit ) ) {
		$terms_to_edit = '';
	}
	?>
<div class="tagsdiv" id="<?php echo $tax_name; ?>">
	<div class="jaxtag">
	<div class="nojs-tags hide-if-js">
		<label for="tax-input-<?php echo $tax_name; ?>"><?php echo $taxonomy->labels->add_or_remove_items; ?></label>
		<p><textarea name="<?php echo "tax_input[$tax_name]"; ?>" rows="3" cols="20" class="the-tags" id="tax-input-<?php echo $tax_name; ?>" <?php disabled( ! $user_can_assign_terms ); ?> aria-describedby="new-tag-<?php echo $tax_name; ?>-desc"><?php echo str_replace( ',', $comma . ' ', $terms_to_edit ); // textarea_escaped by esc_attr() ?></textarea></p>
	</div>
	<?php if ( $user_can_assign_terms ) : ?>
	<div class="ajaxtag hide-if-no-js">
		<label class="screen-reader-text" for="new-tag-<?php echo $tax_name; ?>"><?php echo $taxonomy->labels->add_new_item; ?></label>
		<input data-wp-taxonomy="<?php echo $tax_name; ?>" type="text" id="new-tag-<?php echo $tax_name; ?>" name="newtag[<?php echo $tax_name; ?>]" class="newtag form-input-tip" size="16" autocomplete="off" aria-describedby="new-tag-<?php echo $tax_name; ?>-desc" value="" />
		<input type="button" class="button tagadd" value="<?php esc_attr_e( 'Add' ); ?>" />
	</div>
	<p class="howto" id="new-tag-<?php echo $tax_name; ?>-desc"><?php echo $taxonomy->labels->separate_items_with_commas; ?></p>
	<?php elseif ( empty( $terms_to_edit ) ) : ?>
		<p><?php echo $taxonomy->labels->no_terms; ?></p>
	<?php endif; ?>
	</div>
	<ul class="tagchecklist" role="list"></ul>
</div>
	<?php if ( $user_can_assign_terms ) : ?>
<p class="hide-if-no-js"><button type="button" class="button-link tagcloud-link" id="link-<?php echo $tax_name; ?>" aria-expanded="false"><?php echo $taxonomy->labels->choose_from_most_used; ?></button></p>
<?php endif; ?>
	<?php
}

/**
 * Displays post categories form fields.
 *
 * @since 2.6.0
 *
 * @todo Create taxonomy-agnostic wrapper for this.
 *
 * @param WP_Post $post Current post object.
 * @param array   $box {
 *     Categories meta box arguments.
 *
 *     @type string   $id       Meta box 'id' attribute.
 *     @type string   $title    Meta box title.
 *     @type callable $callback Meta box display callback.
 *     @type array    $args {
 *         Extra meta box arguments.
 *
 *         @type string $taxonomy Taxonomy. Default 'category'.
 *     }
 * }
 */
function post_categories_meta_box( $post, $box ) {
	$defaults = array( 'taxonomy' => 'category' );
	if ( ! isset( $box['args'] ) || ! is_array( $box['args'] ) ) {
		$args = array();
	} else {
		$args = $box['args'];
	}
	$parsed_args = wp_parse_args( $args, $defaults );
	$tax_name    = esc_attr( $parsed_args['taxonomy'] );
	$taxonomy    = get_taxonomy( $parsed_args['taxonomy'] );
	?>
	<div id="taxonomy-<?php echo $tax_name; ?>" class="categorydiv">
		<ul id="<?php echo $tax_name; ?>-tabs" class="category-tabs">
			<li class="tabs"><a href="#<?php echo $tax_name; ?>-all"><?php echo $taxonomy->labels->all_items; ?></a></li>
			<li class="hide-if-no-js"><a href="#<?php echo $tax_name; ?>-pop"><?php echo esc_html( $taxonomy->labels->most_used ); ?></a></li>
		</ul>

		<div id="<?php echo $tax_name; ?>-pop" class="tabs-panel" style="display: none;">
			<ul id="<?php echo $tax_name; ?>checklist-pop" class="categorychecklist form-no-clear" >
				<?php $popular_ids = wp_popular_terms_checklist( $tax_name ); ?>
			</ul>
		</div>

		<div id="<?php echo $tax_name; ?>-all" class="tabs-panel">
			<?php
			$name = ( 'category' === $tax_name ) ? 'post_category' : 'tax_input[' . $tax_name . ']';
			// Allows for an empty term set to be sent. 0 is an invalid term ID and will be ignored by empty() checks.
			echo "<input type='hidden' name='{$name}[]' value='0' />";
			?>
			<ul id="<?php echo $tax_name; ?>checklist" data-wp-lists="list:<?php echo $tax_name; ?>" class="categorychecklist form-no-clear">
				<?php
				wp_terms_checklist(
					$post->ID,
					array(
						'taxonomy'     => $tax_name,
						'popular_cats' => $popular_ids,
					)
				);
				?>
			</ul>
		</div>
	<?php if ( current_user_can( $taxonomy->cap->edit_terms ) ) : ?>
			<div id="<?php echo $tax_name; ?>-adder" class="wp-hidden-children">
				<a id="<?php echo $tax_name; ?>-add-toggle" href="#<?php echo $tax_name; ?>-add" class="hide-if-no-js taxonomy-add-new">
					<?php
						/* translators: %s: Add New taxonomy label. */
						printf( __( '+ %s' ), $taxonomy->labels->add_new_item );
					?>
				</a>
				<p id="<?php echo $tax_name; ?>-add" class="category-add wp-hidden-child">
					<label class="screen-reader-text" for="new<?php echo $tax_name; ?>"><?php echo $taxonomy->labels->add_new_item; ?></label>
					<input type="text" name="new<?php echo $tax_name; ?>" id="new<?php echo $tax_name; ?>" class="form-required form-input-tip" value="<?php echo esc_attr( $taxonomy->labels->new_item_name ); ?>" aria-required="true" />
					<label class="screen-reader-text" for="new<?php echo $tax_name; ?>_parent">
						<?php echo $taxonomy->labels->parent_item_colon; ?>
					</label>
					<?php
					$parent_dropdown_args = array(
						'taxonomy'         => $tax_name,
						'hide_empty'       => 0,
						'name'             => 'new' . $tax_name . '_parent',
						'orderby'          => 'name',
						'hierarchical'     => 1,
						'show_option_none' => '&mdash; ' . $taxonomy->labels->parent_item . ' &mdash;',
					);

					/**
					 * Filters the arguments for the taxonomy parent dropdown on the Post Edit page.
					 *
					 * @since 4.4.0
					 *
					 * @param array $parent_dropdown_args {
					 *     Optional. Array of arguments to generate parent dropdown.
					 *
					 *     @type string   $taxonomy         Name of the taxonomy to retrieve.
					 *     @type bool     $hide_if_empty    True to skip generating markup if no
					 *                                      categories are found. Default 0.
					 *     @type string   $name             Value for the 'name' attribute
					 *                                      of the select element.
					 *                                      Default "new{$tax_name}_parent".
					 *     @type string   $orderby          Which column to use for ordering
					 *                                      terms. Default 'name'.
					 *     @type bool|int $hierarchical     Whether to traverse the taxonomy
					 *                                      hierarchy. Default 1.
					 *     @type string   $show_option_none Text to display for the "none" option.
					 *                                      Default "&mdash; {$parent} &mdash;",
					 *                                      where `$parent` is 'parent_item'
					 *                                      taxonomy label.
					 * }
					 */
					$parent_dropdown_args = apply_filters( 'post_edit_category_parent_dropdown_args', $parent_dropdown_args );

					wp_dropdown_categories( $parent_dropdown_args );
					?>
					<input type="button" id="<?php echo $tax_name; ?>-add-submit" data-wp-lists="add:<?php echo $tax_name; ?>checklist:<?php echo $tax_name; ?>-add" class="button category-add-submit" value="<?php echo esc_attr( $taxonomy->labels->add_new_item ); ?>" />
					<?php wp_nonce_field( 'add-' . $tax_name, '_ajax_nonce-add-' . $tax_name, false ); ?>
					<span id="<?php echo $tax_name; ?>-ajax-response"></span>
				</p>
			</div>
		<?php endif; ?>
	</div>
	<?php
}

/**
 * Displays post excerpt form fields.
 *
 * @since 2.6.0
 *
 * @param WP_Post $post Current post object.
 */
function post_excerpt_meta_box( $post ) {
	?>
<label class="screen-reader-text" for="excerpt">
	<?php
	/* translators: Hidden accessibility text. */
	_e( 'Excerpt' );
	?>
</label><textarea rows="1" cols="40" name="excerpt" id="excerpt"><?php echo $post->post_excerpt; // textarea_escaped ?></textarea>
<p>
	<?php
	printf(
		/* translators: %s: Documentation URL. */
		__( 'Excerpts are optional hand-crafted summaries of your content that can be used in your theme. <a href="%s">Learn more about manual excerpts</a>.' ),
		__( 'https://wordpress.org/documentation/article/what-is-an-excerpt-classic-editor/' )
	);
	?>
</p>
	<?php
}

/**
 * Displays trackback links form fields.
 *
 * @since 2.6.0
 *
 * @param WP_Post $post Current post object.
 */
function post_trackback_meta_box( $post ) {
	$form_trackback = '<input type="text" name="trackback_url" id="trackback_url" class="code" value="' .
		esc_attr( str_replace( "\n", ' ', $post->to_ping ) ) . '" aria-describedby="trackback-url-desc" />';

	if ( '' !== $post->pinged ) {
		$pings          = '<p>' . __( 'Already pinged:' ) . '</p><ul>';
		$already_pinged = explode( "\n", trim( $post->pinged ) );
		foreach ( $already_pinged as $pinged_url ) {
			$pings .= "\n\t<li>" . esc_html( $pinged_url ) . '</li>';
		}
		$pings .= '</ul>';
	}

	?>
<p>
	<label for="trackback_url"><?php _e( 'Send trackbacks to:' ); ?></label>
	<?php echo $form_trackback; ?>
</p>
<p id="trackback-url-desc" class="howto"><?php _e( 'Separate multiple URLs with spaces' ); ?></p>
<p>
	<?php
	printf(
		/* translators: %s: Documentation URL. */
		__( 'Trackbacks are a way to notify legacy blog systems that you&#8217;ve linked to them. If you link other WordPress sites, they&#8217;ll be notified automatically using <a href="%s">pingbacks</a>, no other action necessary.' ),
		__( 'https://wordpress.org/documentation/article/introduction-to-blogging/#comments' )
	);
	?>
</p>
	<?php
	if ( ! empty( $pings ) ) {
		echo $pings;
	}
}

/**
 * Displays custom fields form fields.
 *
 * @since 2.6.0
 *
 * @param WP_Post $post Current post object.
 */
function post_custom_meta_box( $post ) {
	?>
<div id="postcustomstuff">
<div id="ajax-response"></div>
	<?php
	$metadata = has_meta( $post->ID );
	foreach ( $metadata as $key => $value ) {
		if ( is_protected_meta( $metadata[ $key ]['meta_key'], 'post' ) || ! current_user_can( 'edit_post_meta', $post->ID, $metadata[ $key ]['meta_key'] ) ) {
			unset( $metadata[ $key ] );
		}
	}
	list_meta( $metadata );
	meta_form( $post );
	?>
</div>
<p>
	<?php
	printf(
		/* translators: %s: Documentation URL. */
		__( 'Custom fields can be used to add extra metadata to a post that you can <a href="%s">use in your theme</a>.' ),
		__( 'https://wordpress.org/documentation/article/assign-custom-fields/' )
	);
	?>
</p>
	<?php
}

/**
 * Displays comments status form fields.
 *
 * @since 2.6.0
 *
 * @param WP_Post $post Current post object.
 */
function post_comment_status_meta_box( $post ) {
	?>
<input name="advanced_view" type="hidden" value="1" />
<p class="meta-options">
	<label for="comment_status" class="selectit"><input name="comment_status" type="checkbox" id="comment_status" value="open" <?php checked( $post->comment_status, 'open' ); ?> /> <?php _e( 'Allow comments' ); ?></label><br />
	<label for="ping_status" class="selectit"><input name="ping_status" type="checkbox" id="ping_status" value="open" <?php checked( $post->ping_status, 'open' ); ?> />
		<?php
		printf(
			/* translators: %s: Documentation URL. */
			__( 'Allow <a href="%s">trackbacks and pingbacks</a>' ),
			__( 'https://wordpress.org/documentation/article/introduction-to-blogging/#managing-comments' )
		);
		?>
	</label>
	<?php
	/**
	 * Fires at the end of the Discussion meta box on the post editing screen.
	 *
	 * @since 3.1.0
	 *
	 * @param WP_Post $post WP_Post object for the current post.
	 */
	do_action( 'post_comment_status_meta_box-options', $post ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
	?>
</p>
	<?php
}

/**
 * Displays comments for post table header
 *
 * @since 3.0.0
 *
 * @param array $result Table header rows.
 * @return array
 */
function post_comment_meta_box_thead( $result ) {
	unset( $result['cb'], $result['response'] );
	return $result;
}

/**
 * Displays comments for post.
 *
 * @since 2.8.0
 *
 * @param WP_Post $post Current post object.
 */
function post_comment_meta_box( $post ) {
	wp_nonce_field( 'get-comments', 'add_comment_nonce', false );
	?>
	<p class="hide-if-no-js" id="add-new-comment"><button type="button" class="button" onclick="window.commentReply && commentReply.addcomment(<?php echo $post->ID; ?>);"><?php _e( 'Add Comment' ); ?></button></p>
	<?php

	$total         = get_comments(
		array(
			'post_id' => $post->ID,
			'count'   => true,
			'orderby' => 'none',
		)
	);
	$wp_list_table = _get_list_table( 'WP_Post_Comments_List_Table' );
	$wp_list_table->display( true );

	if ( 1 > $total ) {
		echo '<p id="no-comments">' . __( 'No comments yet.' ) . '</p>';
	} else {
		$hidden = get_hidden_meta_boxes( get_current_screen() );
		if ( ! in_array( 'commentsdiv', $hidden, true ) ) {
			?>
			<script type="text/javascript">jQuery(function(){commentsBox.get(<?php echo $total; ?>, 10);});</script>
			<?php
		}

		?>
		<p class="hide-if-no-js" id="show-comments"><a href="#commentstatusdiv" onclick="commentsBox.load(<?php echo $total; ?>);return false;"><?php _e( 'Show comments' ); ?></a> <span class="spinner"></span></p>
		<?php
	}

	wp_comment_trashnotice();
}

/**
 * Displays slug form fields.
 *
 * @since 2.6.0
 *
 * @param WP_Post $post Current post object.
 */
function post_slug_meta_box( $post ) {
	/** This filter is documented in wp-admin/edit-tag-form.php */
	$editable_slug = apply_filters( 'editable_slug', $post->post_name, $post );
	?>
<label class="screen-reader-text" for="post_name">
	<?php
	/* translators: Hidden accessibility text. */
	_e( 'Slug' );
	?>
</label><input name="post_name" type="text" class="large-text" id="post_name" value="<?php echo esc_attr( $editable_slug ); ?>" />
	<?php
}

/**
 * Displays form field with list of authors.
 *
 * @since 2.6.0
 *
 * @global int $user_ID
 *
 * @param WP_Post $post Current post object.
 */
function post_author_meta_box( $post ) {
	global $user_ID;

	$post_type_object = get_post_type_object( $post->post_type );
	?>
<label class="screen-reader-text" for="post_author_override">
	<?php
	/* translators: Hidden accessibility text. */
	_e( 'Author' );
	?>
</label>
	<?php
	wp_dropdown_users(
		array(
			'capability'       => array( $post_type_object->cap->edit_posts ),
			'name'             => 'post_author_override',
			'selected'         => empty( $post->ID ) ? $user_ID : $post->post_author,
			'include_selected' => true,
			'show'             => 'display_name_with_login',
		)
	);
}

/**
 * Displays list of revisions.
 *
 * @since 2.6.0
 *
 * @param WP_Post $post Current post object.
 */
function post_revisions_meta_box( $post ) {
	wp_list_post_revisions( $post );
}

//
// Page-related Meta Boxes.
//

/**
 * Displays page attributes form fields.
 *
 * @since 2.7.0
 *
 * @param WP_Post $post Current post object.
 */
function page_attributes_meta_box( $post ) {
	if ( is_post_type_hierarchical( $post->post_type ) ) :
		$dropdown_args = array(
			'post_type'        => $post->post_type,
			'exclude_tree'     => $post->ID,
			'selected'         => $post->post_parent,
			'name'             => 'parent_id',
			'show_option_none' => __( '(no parent)' ),
			'sort_column'      => 'menu_order, post_title',
			'echo'             => 0,
		);

		/**
		 * Filters the arguments used to generate a Pages drop-down element.
		 *
		 * @since 3.3.0
		 *
		 * @see wp_dropdown_pages()
		 *
		 * @param array   $dropdown_args Array of arguments used to generate the pages drop-down.
		 * @param WP_Post $post          The current post.
		 */
		$dropdown_args = apply_filters( 'page_attributes_dropdown_pages_args', $dropdown_args, $post );
		$pages         = wp_dropdown_pages( $dropdown_args );
		if ( ! empty( $pages ) ) :
			?>
<p class="post-attributes-label-wrapper parent-id-label-wrapper"><label class="post-attributes-label" for="parent_id"><?php _e( 'Parent' ); ?></label></p>
			<?php echo $pages; ?>
			<?php
		endif; // End empty pages check.
	endif;  // End hierarchical check.

	if ( count( get_page_templates( $post ) ) > 0 && (int) get_option( 'page_for_posts' ) !== $post->ID ) :
		$template = ! empty( $post->page_template ) ? $post->page_template : false;
		?>
<p class="post-attributes-label-wrapper page-template-label-wrapper"><label class="post-attributes-label" for="page_template"><?php _e( 'Template' ); ?></label>
		<?php
		/**
		 * Fires immediately after the label inside the 'Template' section
		 * of the 'Page Attributes' meta box.
		 *
		 * @since 4.4.0
		 *
		 * @param string|false $template The template used for the current post.
		 * @param WP_Post      $post     The current post.
		 */
		do_action( 'page_attributes_meta_box_template', $template, $post );
		?>
</p>
<select name="page_template" id="page_template">
		<?php
		/**
		 * Filters the title of the default page template displayed in the drop-down.
		 *
		 * @since 4.1.0
		 *
		 * @param string $label   The display value for the default page template title.
		 * @param string $context Where the option label is displayed. Possible values
		 *                        include 'meta-box' or 'quick-edit'.
		 */
		$default_title = apply_filters( 'default_page_template_title', __( 'Default template' ), 'meta-box' );
		?>
<option value="default"><?php echo esc_html( $default_title ); ?></option>
		<?php page_template_dropdown( $template, $post->post_type ); ?>
</select>
<?php endif; ?>
	<?php if ( post_type_supports( $post->post_type, 'page-attributes' ) ) : ?>
<p class="post-attributes-label-wrapper menu-order-label-wrapper"><label class="post-attributes-label" for="menu_order"><?php _e( 'Order' ); ?></label></p>
<input name="menu_order" type="text" size="4" id="menu_order" value="<?php echo esc_attr( $post->menu_order ); ?>" />
		<?php
		/**
		 * Fires before the help hint text in the 'Page Attributes' meta box.
		 *
		 * @since 4.9.0
		 *
		 * @param WP_Post $post The current post.
		 */
		do_action( 'page_attributes_misc_attributes', $post );
		?>
		<?php if ( 'page' === $post->post_type && get_current_screen()->get_help_tabs() ) : ?>
<p class="post-attributes-help-text"><?php _e( 'Need help? Use the Help tab above the screen title.' ); ?></p>
			<?php
	endif;
	endif;
}

//
// Link-related Meta Boxes.
//

/**
 * Displays link create form fields.
 *
 * @since 2.7.0
 *
 * @param object $link Current link object.
 */
function link_submit_meta_box( $link ) {
	?>
<div class="submitbox" id="submitlink">

<div id="minor-publishing">

	<?php // Hidden submit button early on so that the browser chooses the right button when form is submitted with Return key. ?>
<div style="display:none;">
	<?php submit_button( __( 'Save' ), '', 'save', false ); ?>
</div>

<div id="minor-publishing-actions">
<div id="preview-action">
	<?php if ( ! empty( $link->link_id ) ) { ?>
	<a class="preview button" href="<?php echo $link->link_url; ?>" target="_blank"><?php _e( 'Visit Link' ); ?></a>
<?php } ?>
</div>
<div class="clear"></div>
</div>

<div id="misc-publishing-actions">
<div class="misc-pub-section misc-pub-private">
	<label for="link_private" class="selectit"><input id="link_private" name="link_visible" type="checkbox" value="N" <?php checked( $link->link_visible, 'N' ); ?> /> <?php _e( 'Keep this link private' ); ?></label>
</div>
</div>

</div>

<div id="major-publishing-actions">
	<?php
	/** This action is documented in wp-admin/includes/meta-boxes.php */
	do_action( 'post_submitbox_start', null );
	?>
<div id="delete-action">
	<?php
	if ( ! empty( $_GET['action'] ) && 'edit' === $_GET['action'] && current_user_can( 'manage_links' ) ) {
		printf(
			'<a class="submitdelete deletion" href="%s" onclick="return confirm( \'%s\' );">%s</a>',
			wp_nonce_url( "link.php?action=delete&amp;link_id=$link->link_id", 'delete-bookmark_' . $link->link_id ),
			/* translators: %s: Link name. */
			esc_js( sprintf( __( "You are about to delete this link '%s'\n  'Cancel' to stop, 'OK' to delete." ), $link->link_name ) ),
			__( 'Delete' )
		);
	}
	?>
</div>

<div id="publishing-action">
	<?php if ( ! empty( $link->link_id ) ) { ?>
	<input name="save" type="submit" class="button button-primary button-large" id="publish" value="<?php esc_attr_e( 'Update Link' ); ?>" />
<?php } else { ?>
	<input name="save" type="submit" class="button button-primary button-large" id="publish" value="<?php esc_attr_e( 'Add Link' ); ?>" />
<?php } ?>
</div>
<div class="clear"></div>
</div>
	<?php
	/**
	 * Fires at the end of the Publish box in the Link editing screen.
	 *
	 * @since 2.5.0
	 */
	do_action( 'submitlink_box' );
	?>
<div class="clear"></div>
</div>
	<?php
}

/**
 * Displays link categories form fields.
 *
 * @since 2.6.0
 *
 * @param object $link Current link object.
 */
function link_categories_meta_box( $link ) {
	?>
<div id="taxonomy-linkcategory" class="categorydiv">
	<ul id="category-tabs" class="category-tabs">
		<li class="tabs"><a href="#categories-all"><?php _e( 'All categories' ); ?></a></li>
		<li class="hide-if-no-js"><a href="#categories-pop"><?php _ex( 'Most Used', 'categories' ); ?></a></li>
	</ul>

	<div id="categories-all" class="tabs-panel">
		<ul id="categorychecklist" data-wp-lists="list:category" class="categorychecklist form-no-clear">
			<?php
			if ( isset( $link->link_id ) ) {
				wp_link_category_checklist( $link->link_id );
			} else {
				wp_link_category_checklist();
			}
			?>
		</ul>
	</div>

	<div id="categories-pop" class="tabs-panel" style="display: none;">
		<ul id="categorychecklist-pop" class="categorychecklist form-no-clear">
			<?php wp_popular_terms_checklist( 'link_category' ); ?>
		</ul>
	</div>

	<div id="category-adder" class="wp-hidden-children">
		<a id="category-add-toggle" href="#category-add" class="taxonomy-add-new"><?php _e( '+ Add Category' ); ?></a>
		<p id="link-category-add" class="wp-hidden-child">
			<label class="screen-reader-text" for="newcat">
				<?php
				/* translators: Hidden accessibility text. */
				_e( '+ Add Category' );
				?>
			</label>
			<input type="text" name="newcat" id="newcat" class="form-required form-input-tip" value="<?php esc_attr_e( 'New category name' ); ?>" aria-required="true" />
			<input type="button" id="link-category-add-submit" data-wp-lists="add:categorychecklist:link-category-add" class="button" value="<?php esc_attr_e( 'Add' ); ?>" />
			<?php wp_nonce_field( 'add-link-category', '_ajax_nonce', false ); ?>
			<span id="category-ajax-response"></span>
		</p>
	</div>
</div>
	<?php
}

/**
 * Displays form fields for changing link target.
 *
 * @since 2.6.0
 *
 * @param object $link Current link object.
 */
function link_target_meta_box( $link ) {

	?>
<fieldset><legend class="screen-reader-text"><span><?php _e( 'Target' ); ?></span></legend>
<p><label for="link_target_blank" class="selectit">
<input id="link_target_blank" type="radio" name="link_target" value="_blank" <?php echo ( isset( $link->link_target ) && ( '_blank' === $link->link_target ) ? 'checked="checked"' : '' ); ?> />
	<?php _e( '<code>_blank</code> &mdash; new window or tab.' ); ?></label></p>
<p><label for="link_target_top" class="selectit">
<input id="link_target_top" type="radio" name="link_target" value="_top" <?php echo ( isset( $link->link_target ) && ( '_top' === $link->link_target ) ? 'checked="checked"' : '' ); ?> />
	<?php _e( '<code>_top</code> &mdash; current window or tab, with no frames.' ); ?></label></p>
<p><label for="link_target_none" class="selectit">
<input id="link_target_none" type="radio" name="link_target" value="" <?php echo ( isset( $link->link_target ) && ( '' === $link->link_target ) ? 'checked="checked"' : '' ); ?> />
	<?php _e( '<code>_none</code> &mdash; same window or tab.' ); ?></label></p>
</fieldset>
<p><?php _e( 'Choose the target frame for your link.' ); ?></p>
	<?php
}

/**
 * Displays 'checked' checkboxes attribute for XFN microformat options.
 *
 * @since 1.0.1
 *
 * @global object $link Current link object.
 *
 * @param string $xfn_relationship XFN relationship category. Possible values are:
 *                                 'friendship', 'physical', 'professional',
 *                                 'geographical', 'family', 'romantic', 'identity'.
 * @param string $xfn_value        Optional. The XFN value to mark as checked
 *                                 if it matches the current link's relationship.
 *                                 Default empty string.
 * @param mixed  $deprecated       Deprecated. Not used.
 */
function xfn_check( $xfn_relationship, $xfn_value = '', $deprecated = '' ) {
	global $link;

	if ( ! empty( $deprecated ) ) {
		_deprecated_argument( __FUNCTION__, '2.5.0' ); // Never implemented.
	}

	$link_rel  = isset( $link->link_rel ) ? $link->link_rel : '';
	$link_rels = preg_split( '/\s+/', $link_rel );

	// Mark the specified value as checked if it matches the current link's relationship.
	if ( '' !== $xfn_value && in_array( $xfn_value, $link_rels, true ) ) {
		echo ' checked="checked"';
	}

	if ( '' === $xfn_value ) {
		// Mark the 'none' value as checked if the current link does not match the specified relationship.
		if ( 'family' === $xfn_relationship
			&& ! array_intersect( $link_rels, array( 'child', 'parent', 'sibling', 'spouse', 'kin' ) )
		) {
			echo ' checked="checked"';
		}

		if ( 'friendship' === $xfn_relationship
			&& ! array_intersect( $link_rels, array( 'friend', 'acquaintance', 'contact' ) )
		) {
			echo ' checked="checked"';
		}

		if ( 'geographical' === $xfn_relationship
			&& ! array_intersect( $link_rels, array( 'co-resident', 'neighbor' ) )
		) {
			echo ' checked="checked"';
		}

		// Mark the 'me' value as checked if it matches the current link's relationship.
		if ( 'identity' === $xfn_relationship
			&& in_array( 'me', $link_rels, true )
		) {
			echo ' checked="checked"';
		}
	}
}

/**
 * Displays XFN form fields.
 *
 * @since 2.6.0
 *
 * @param object $link Current link object.
 */
function link_xfn_meta_box( $link ) {
	?>
<table class="links-table">
	<tr>
		<th scope="row"><label for="link_rel"><?php /* translators: xfn: https://gmpg.org/xfn/ */ _e( 'rel:' ); ?></label></th>
		<td><input type="text" name="link_rel" id="link_rel" value="<?php echo ( isset( $link->link_rel ) ? esc_attr( $link->link_rel ) : '' ); ?>" /></td>
	</tr>
	<?php $identity_group_title = /* translators: xfn: https://gmpg.org/xfn/ */ __( 'identity' ); ?>
	<tr>
		<th scope="row"><?php echo $identity_group_title; ?></th>
		<td><fieldset>
			<legend class="screen-reader-text"><span><?php echo $identity_group_title; ?></span></legend>
			<label for="me">
			<input type="checkbox" name="identity" value="me" id="me" <?php xfn_check( 'identity', 'me' ); ?> />
			<?php _e( 'another web address of mine' ); ?></label>
		</fieldset></td>
	</tr>
	<?php $friendship_group_title = /* translators: xfn: https://gmpg.org/xfn/ */ __( 'friendship' ); ?>
	<tr>
		<th scope="row"><?php echo $friendship_group_title; ?></th>
		<td><fieldset>
			<legend class="screen-reader-text"><span><?php echo $friendship_group_title; ?></span></legend>
			<label for="contact">
			<input class="valinp" type="radio" name="friendship" value="contact" id="contact" <?php xfn_check( 'friendship', 'contact' ); ?> />&nbsp;<?php /* translators: xfn: https://gmpg.org/xfn/ */ _e( 'contact' ); ?>
			</label>
			<label for="acquaintance">
			<input class="valinp" type="radio" name="friendship" value="acquaintance" id="acquaintance" <?php xfn_check( 'friendship', 'acquaintance' ); ?> />&nbsp;<?php /* translators: xfn: https://gmpg.org/xfn/ */ _e( 'acquaintance' ); ?>
			</label>
			<label for="friend">
			<input class="valinp" type="radio" name="friendship" value="friend" id="friend" <?php xfn_check( 'friendship', 'friend' ); ?> />&nbsp;<?php /* translators: xfn: https://gmpg.org/xfn/ */ _e( 'friend' ); ?>
			</label>
			<label for="friendship">
			<input name="friendship" type="radio" class="valinp" value="" id="friendship" <?php xfn_check( 'friendship' ); ?> />&nbsp;<?php /* translators: xfn (friendship relation): http://gmpg.org/xfn/ */ _ex( 'none', 'Type of relation' ); ?>
			</label>
		</fieldset></td>
	</tr>
	<?php $physical_group_title = /* translators: xfn: https://gmpg.org/xfn/ */ __( 'physical' ); ?>
	<tr>
		<th scope="row"> <?php echo $physical_group_title; ?> </th>
		<td><fieldset>
			<legend class="screen-reader-text"><span><?php echo $physical_group_title; ?></span></legend>
			<label for="met">
			<input class="valinp" type="checkbox" name="physical" value="met" id="met" <?php xfn_check( 'physical', 'met' ); ?> />&nbsp;<?php /* translators: xfn: https://gmpg.org/xfn/ */ _e( 'met' ); ?>
			</label>
		</fieldset></td>
	</tr>
	<?php $professional_group_title = /* translators: xfn: https://gmpg.org/xfn/ */ __( 'professional' ); ?>
	<tr>
		<th scope="row"> <?php echo $professional_group_title; ?> </th>
		<td><fieldset>
			<legend class="screen-reader-text"><span><?php echo $professional_group_title; ?></span></legend>
			<label for="co-worker">
			<input class="valinp" type="checkbox" name="professional" value="co-worker" id="co-worker" <?php xfn_check( 'professional', 'co-worker' ); ?> />&nbsp;<?php /* translators: xfn: https://gmpg.org/xfn/ */ _e( 'co-worker' ); ?>
			</label>
			<label for="colleague">
			<input class="valinp" type="checkbox" name="professional" value="colleague" id="colleague" <?php xfn_check( 'professional', 'colleague' ); ?> />&nbsp;<?php /* translators: xfn: https://gmpg.org/xfn/ */ _e( 'colleague' ); ?>
			</label>
		</fieldset></td>
	</tr>
	<?php $geographical_group_title = /* translators: xfn: https://gmpg.org/xfn/ */ __( 'geographical' ); ?>
	<tr>
		<th scope="row"><?php echo $geographical_group_title; ?></th>
		<td><fieldset>
			<legend class="screen-reader-text"><span><?php echo $geographical_group_title; ?></span></legend>
			<label for="co-resident">
			<input class="valinp" type="radio" name="geographical" value="co-resident" id="co-resident" <?php xfn_check( 'geographical', 'co-resident' ); ?> />&nbsp;<?php /* translators: xfn: https://gmpg.org/xfn/ */ _e( 'co-resident' ); ?>
			</label>
			<label for="neighbor">
			<input class="valinp" type="radio" name="geographical" value="neighbor" id="neighbor" <?php xfn_check( 'geographical', 'neighbor' ); ?> />&nbsp;<?php /* translators: xfn: https://gmpg.org/xfn/ */ _e( 'neighbor' ); ?>
			</label>
			<label for="geographical">
			<input class="valinp" type="radio" name="geographical" value="" id="geographical" <?php xfn_check( 'geographical' ); ?> />&nbsp;<?php /* translators: xfn (geographical relation): http://gmpg.org/xfn/ */ _ex( 'none', 'Type of relation' ); ?>
			</label>
		</fieldset></td>
	</tr>
	<?php $family_group_title = /* translators: xfn: https://gmpg.org/xfn/ */ __( 'family' ); ?>
	<tr>
		<th scope="row"><?php echo $family_group_title; ?></th>
		<td><fieldset>
			<legend class="screen-reader-text"><span><?php echo $family_group_title; ?></span></legend>
			<label for="child">
			<input class="valinp" type="radio" name="family" value="child" id="child" <?php xfn_check( 'family', 'child' ); ?> />&nbsp;<?php /* translators: xfn: https://gmpg.org/xfn/ */ _e( 'child' ); ?>
			</label>
			<label for="kin">
			<input class="valinp" type="radio" name="family" value="kin" id="kin" <?php xfn_check( 'family', 'kin' ); ?> />&nbsp;<?php /* translators: xfn: https://gmpg.org/xfn/ */ _e( 'kin' ); ?>
			</label>
			<label for="parent">
			<input class="valinp" type="radio" name="family" value="parent" id="parent" <?php xfn_check( 'family', 'parent' ); ?> />&nbsp;<?php /* translators: xfn: https://gmpg.org/xfn/ */ _e( 'parent' ); ?>
			</label>
			<label for="sibling">
			<input class="valinp" type="radio" name="family" value="sibling" id="sibling" <?php xfn_check( 'family', 'sibling' ); ?> />&nbsp;<?php /* translators: xfn: https://gmpg.org/xfn/ */ _e( 'sibling' ); ?>
			</label>
			<label for="spouse">
			<input class="valinp" type="radio" name="family" value="spouse" id="spouse" <?php xfn_check( 'family', 'spouse' ); ?> />&nbsp;<?php /* translators: xfn: https://gmpg.org/xfn/ */ _e( 'spouse' ); ?>
			</label>
			<label for="family">
			<input class="valinp" type="radio" name="family" value="" id="family" <?php xfn_check( 'family' ); ?> />&nbsp;<?php /* translators: xfn (family relation): http://gmpg.org/xfn/ */ _ex( 'none', 'Type of relation' ); ?>
			</label>
		</fieldset></td>
	</tr>
	<?php $romantic_group_title = /* translators: xfn: https://gmpg.org/xfn/ */ __( 'romantic' ); ?>
	<tr>
		<th scope="row"><?php echo $romantic_group_title; ?></th>
		<td><fieldset>
			<legend class="screen-reader-text"><span><?php echo $romantic_group_title; ?></span></legend>
			<label for="muse">
			<input class="valinp" type="checkbox" name="romantic" value="muse" id="muse" <?php xfn_check( 'romantic', 'muse' ); ?> />&nbsp;<?php /* translators: xfn: https://gmpg.org/xfn/ */ _e( 'muse' ); ?>
			</label>
			<label for="crush">
			<input class="valinp" type="checkbox" name="romantic" value="crush" id="crush" <?php xfn_check( 'romantic', 'crush' ); ?> />&nbsp;<?php /* translators: xfn: https://gmpg.org/xfn/ */ _e( 'crush' ); ?>
			</label>
			<label for="date">
			<input class="valinp" type="checkbox" name="romantic" value="date" id="date" <?php xfn_check( 'romantic', 'date' ); ?> />&nbsp;<?php /* translators: xfn: https://gmpg.org/xfn/ */ _e( 'date' ); ?>
			</label>
			<label for="romantic">
			<input class="valinp" type="checkbox" name="romantic" value="sweetheart" id="romantic" <?php xfn_check( 'romantic', 'sweetheart' ); ?> />&nbsp;<?php /* translators: xfn: https://gmpg.org/xfn/ */ _e( 'sweetheart' ); ?>
			</label>
		</fieldset></td>
	</tr>

</table>
<p><?php _e( 'If the link is to a person, you can specify your relationship with them using the above form. If you would like to learn more about the idea check out <a href="https://gmpg.org/xfn/">XFN</a>.' ); ?></p>
	<?php
}

/**
 * Displays advanced link options form fields.
 *
 * @since 2.6.0
 *
 * @param object $link Current link object.
 */
function link_advanced_meta_box( $link ) {
	?>
<table class="links-table" cellpadding="0">
	<tr>
		<th scope="row"><label for="link_image"><?php _e( 'Image Address' ); ?></label></th>
		<td><input type="text" name="link_image" class="code" id="link_image" maxlength="255" value="<?php echo ( isset( $link->link_image ) ? esc_attr( $link->link_image ) : '' ); ?>" /></td>
	</tr>
	<tr>
		<th scope="row"><label for="rss_uri"><?php _e( 'RSS Address' ); ?></label></th>
		<td><input name="link_rss" class="code" type="text" id="rss_uri" maxlength="255" value="<?php echo ( isset( $link->link_rss ) ? esc_attr( $link->link_rss ) : '' ); ?>" /></td>
	</tr>
	<tr>
		<th scope="row"><label for="link_notes"><?php _e( 'Notes' ); ?></label></th>
		<td><textarea name="link_notes" id="link_notes" rows="10"><?php echo ( isset( $link->link_notes ) ? $link->link_notes : '' ); // textarea_escaped ?></textarea></td>
	</tr>
	<tr>
		<th scope="row"><label for="link_rating"><?php _e( 'Rating' ); ?></label></th>
		<td><select name="link_rating" id="link_rating" size="1">
		<?php
		for ( $rating = 0; $rating <= 10; $rating++ ) {
			echo '<option value="' . $rating . '"';
			if ( isset( $link->link_rating ) && $link->link_rating === $rating ) {
				echo ' selected="selected"';
			}
			echo '>' . $rating . '</option>';
		}
		?>
		</select>&nbsp;<?php _e( '(Leave at 0 for no rating.)' ); ?>
		</td>
	</tr>
</table>
	<?php
}

/**
 * Displays post thumbnail meta box.
 *
 * @since 2.9.0
 *
 * @param WP_Post $post Current post object.
 */
function post_thumbnail_meta_box( $post ) {
	$thumbnail_id = get_post_meta( $post->ID, '_thumbnail_id', true );
	echo _wp_post_thumbnail_html( $thumbnail_id, $post->ID );
}

/**
 * Displays fields for ID3 data.
 *
 * @since 3.9.0
 *
 * @param WP_Post $post Current post object.
 */
function attachment_id3_data_meta_box( $post ) {
	$meta = array();
	if ( ! empty( $post->ID ) ) {
		$meta = wp_get_attachment_metadata( $post->ID );
	}

	foreach ( wp_get_attachment_id3_keys( $post, 'edit' ) as $key => $label ) :
		$value = '';
		if ( ! empty( $meta[ $key ] ) ) {
			$value = $meta[ $key ];
		}
		?>
	<p>
		<label for="title"><?php echo $label; ?></label><br />
		<input type="text" name="id3_<?php echo esc_attr( $key ); ?>" id="id3_<?php echo esc_attr( $key ); ?>" class="large-text" value="<?php echo esc_attr( $value ); ?>" />
	</p>
		<?php
	endforeach;
}

/**
 * Registers the default post meta boxes, and runs the `do_meta_boxes` actions.
 *
 * @since 5.0.0
 *
 * @param WP_Post $post The post object that these meta boxes are being generated for.
 */
function register_and_do_post_meta_boxes( $post ) {
	$post_type        = $post->post_type;
	$post_type_object = get_post_type_object( $post_type );

	$thumbnail_support = current_theme_supports( 'post-thumbnails', $post_type ) && post_type_supports( $post_type, 'thumbnail' );
	if ( ! $thumbnail_support && 'attachment' === $post_type && $post->post_mime_type ) {
		if ( wp_attachment_is( 'audio', $post ) ) {
			$thumbnail_support = post_type_supports( 'attachment:audio', 'thumbnail' ) || current_theme_supports( 'post-thumbnails', 'attachment:audio' );
		} elseif ( wp_attachment_is( 'video', $post ) ) {
			$thumbnail_support = post_type_supports( 'attachment:video', 'thumbnail' ) || current_theme_supports( 'post-thumbnails', 'attachment:video' );
		}
	}

	$publish_callback_args = array( '__back_compat_meta_box' => true );

	if ( post_type_supports( $post_type, 'revisions' ) && 'auto-draft' !== $post->post_status ) {
		$revisions = wp_get_latest_revision_id_and_total_count( $post->ID );

		// We should aim to show the revisions meta box only when there are revisions.
		if ( ! is_wp_error( $revisions ) && $revisions['count'] > 1 ) {
			$publish_callback_args = array(
				'revisions_count'        => $revisions['count'],
				'revision_id'            => $revisions['latest_id'],
				'__back_compat_meta_box' => true,
			);

			add_meta_box( 'revisionsdiv', __( 'Revisions' ), 'post_revisions_meta_box', null, 'normal', 'core', array( '__back_compat_meta_box' => true ) );
		}
	}

	if ( 'attachment' === $post_type ) {
		wp_enqueue_script( 'image-edit' );
		wp_enqueue_style( 'imgareaselect' );
		add_meta_box( 'submitdiv', __( 'Save' ), 'attachment_submit_meta_box', null, 'side', 'core', array( '__back_compat_meta_box' => true ) );
		add_action( 'edit_form_after_title', 'edit_form_image_editor' );

		if ( wp_attachment_is( 'audio', $post ) ) {
			add_meta_box( 'attachment-id3', __( 'Metadata' ), 'attachment_id3_data_meta_box', null, 'normal', 'core', array( '__back_compat_meta_box' => true ) );
		}
	} else {
		add_meta_box( 'submitdiv', __( 'Publish' ), 'post_submit_meta_box', null, 'side', 'core', $publish_callback_args );
	}

	if ( current_theme_supports( 'post-formats' ) && post_type_supports( $post_type, 'post-formats' ) ) {
		add_meta_box( 'formatdiv', _x( 'Format', 'post format' ), 'post_format_meta_box', null, 'side', 'core', array( '__back_compat_meta_box' => true ) );
	}

	// All taxonomies.
	foreach ( get_object_taxonomies( $post ) as $tax_name ) {
		$taxonomy = get_taxonomy( $tax_name );
		if ( ! $taxonomy->show_ui || false === $taxonomy->meta_box_cb ) {
			continue;
		}

		$label = $taxonomy->labels->name;

		if ( ! is_taxonomy_hierarchical( $tax_name ) ) {
			$tax_meta_box_id = 'tagsdiv-' . $tax_name;
		} else {
			$tax_meta_box_id = $tax_name . 'div';
		}

		add_meta_box(
			$tax_meta_box_id,
			$label,
			$taxonomy->meta_box_cb,
			null,
			'side',
			'core',
			array(
				'taxonomy'               => $tax_name,
				'__back_compat_meta_box' => true,
			)
		);
	}

	if ( post_type_supports( $post_type, 'page-attributes' ) || count( get_page_templates( $post ) ) > 0 ) {
		add_meta_box( 'pageparentdiv', $post_type_object->labels->attributes, 'page_attributes_meta_box', null, 'side', 'core', array( '__back_compat_meta_box' => true ) );
	}

	if ( $thumbnail_support && current_user_can( 'upload_files' ) ) {
		add_meta_box( 'postimagediv', esc_html( $post_type_object->labels->featured_image ), 'post_thumbnail_meta_box', null, 'side', 'low', array( '__back_compat_meta_box' => true ) );
	}

	if ( post_type_supports( $post_type, 'excerpt' ) ) {
		add_meta_box( 'postexcerpt', __( 'Excerpt' ), 'post_excerpt_meta_box', null, 'normal', 'core', array( '__back_compat_meta_box' => true ) );
	}

	if ( post_type_supports( $post_type, 'trackbacks' ) ) {
		add_meta_box( 'trackbacksdiv', __( 'Send Trackbacks' ), 'post_trackback_meta_box', null, 'normal', 'core', array( '__back_compat_meta_box' => true ) );
	}

	if ( post_type_supports( $post_type, 'custom-fields' ) ) {
		add_meta_box(
			'postcustom',
			__( 'Custom Fields' ),
			'post_custom_meta_box',
			null,
			'normal',
			'core',
			array(
				'__back_compat_meta_box'             => ! (bool) get_user_meta( get_current_user_id(), 'enable_custom_fields', true ),
				'__block_editor_compatible_meta_box' => true,
			)
		);
	}

	/**
	 * Fires in the middle of built-in meta box registration.
	 *
	 * @since 2.1.0
	 * @deprecated 3.7.0 Use {@see 'add_meta_boxes'} instead.
	 *
	 * @param WP_Post $post Post object.
	 */
	do_action_deprecated( 'dbx_post_advanced', array( $post ), '3.7.0', 'add_meta_boxes' );

	/*
	 * Allow the Discussion meta box to show up if the post type supports comments,
	 * or if comments or pings are open.
	 */
	if ( comments_open( $post ) || pings_open( $post ) || post_type_supports( $post_type, 'comments' ) ) {
		add_meta_box( 'commentstatusdiv', __( 'Discussion' ), 'post_comment_status_meta_box', null, 'normal', 'core', array( '__back_compat_meta_box' => true ) );
	}

	$statuses = get_post_stati( array( 'public' => true ) );

	if ( empty( $statuses ) ) {
		$statuses = array( 'publish' );
	}

	$statuses[] = 'private';

	if ( in_array( get_post_status( $post ), $statuses, true ) ) {
		/*
		 * If the post type support comments, or the post has comments,
		 * allow the Comments meta box.
		 */
		if ( comments_open( $post ) || pings_open( $post ) || $post->comment_count > 0 || post_type_supports( $post_type, 'comments' ) ) {
			add_meta_box( 'commentsdiv', __( 'Comments' ), 'post_comment_meta_box', null, 'normal', 'core', array( '__back_compat_meta_box' => true ) );
		}
	}

	if ( ! ( 'pending' === get_post_status( $post ) && ! current_user_can( $post_type_object->cap->publish_posts ) ) ) {
		add_meta_box( 'slugdiv', __( 'Slug' ), 'post_slug_meta_box', null, 'normal', 'core', array( '__back_compat_meta_box' => true ) );
	}

	if ( post_type_supports( $post_type, 'author' ) && current_user_can( $post_type_object->cap->edit_others_posts ) ) {
		add_meta_box( 'authordiv', __( 'Author' ), 'post_author_meta_box', null, 'normal', 'core', array( '__back_compat_meta_box' => true ) );
	}

	/**
	 * Fires after all built-in meta boxes have been added.
	 *
	 * @since 3.0.0
	 *
	 * @param string  $post_type Post type.
	 * @param WP_Post $post      Post object.
	 */
	do_action( 'add_meta_boxes', $post_type, $post );

	/**
	 * Fires after all built-in meta boxes have been added, contextually for the given post type.
	 *
	 * The dynamic portion of the hook name, `$post_type`, refers to the post type of the post.
	 *
	 * Possible hook names include:
	 *
	 *  - `add_meta_boxes_post`
	 *  - `add_meta_boxes_page`
	 *  - `add_meta_boxes_attachment`
	 *
	 * @since 3.0.0
	 *
	 * @param WP_Post $post Post object.
	 */
	do_action( "add_meta_boxes_{$post_type}", $post );

	/**
	 * Fires after meta boxes have been added.
	 *
	 * Fires once for each of the default meta box contexts: normal, advanced, and side.
	 *
	 * @since 3.0.0
	 *
	 * @param string                $post_type Post type of the post on Edit Post screen, 'link' on Edit Link screen,
	 *                                         'dashboard' on Dashboard screen.
	 * @param string                $context   Meta box context. Possible values include 'normal', 'advanced', 'side'.
	 * @param WP_Post|object|string $post      Post object on Edit Post screen, link object on Edit Link screen,
	 *                                         an empty string on Dashboard screen.
	 */
	do_action( 'do_meta_boxes', $post_type, 'normal', $post );
	/** This action is documented in wp-admin/includes/meta-boxes.php */
	do_action( 'do_meta_boxes', $post_type, 'advanced', $post );
	/** This action is documented in wp-admin/includes/meta-boxes.php */
	do_action( 'do_meta_boxes', $post_type, 'side', $post );
}
class-theme-upgrader-skin.php000064400000010120151212616040012223 0ustar00<?php
/**
 * Upgrader API: Theme_Upgrader_Skin class
 *
 * @package WordPress
 * @subpackage Upgrader
 * @since 4.6.0
 */

/**
 * Theme Upgrader Skin for WordPress Theme Upgrades.
 *
 * @since 2.8.0
 * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader-skins.php.
 *
 * @see WP_Upgrader_Skin
 */
class Theme_Upgrader_Skin extends WP_Upgrader_Skin {

	/**
	 * Holds the theme slug in the Theme Directory.
	 *
	 * @since 2.8.0
	 *
	 * @var string
	 */
	public $theme = '';

	/**
	 * Constructor.
	 *
	 * Sets up the theme upgrader skin.
	 *
	 * @since 2.8.0
	 *
	 * @param array $args Optional. The theme upgrader skin arguments to
	 *                    override default options. Default empty array.
	 */
	public function __construct( $args = array() ) {
		$defaults = array(
			'url'   => '',
			'theme' => '',
			'nonce' => '',
			'title' => __( 'Update Theme' ),
		);
		$args     = wp_parse_args( $args, $defaults );

		$this->theme = $args['theme'];

		parent::__construct( $args );
	}

	/**
	 * Performs an action following a single theme update.
	 *
	 * @since 2.8.0
	 */
	public function after() {
		$this->decrement_update_count( 'theme' );

		$update_actions = array();
		$theme_info     = $this->upgrader->theme_info();
		if ( $theme_info ) {
			$name       = $theme_info->display( 'Name' );
			$stylesheet = $this->upgrader->result['destination_name'];
			$template   = $theme_info->get_template();

			$activate_link = add_query_arg(
				array(
					'action'     => 'activate',
					'template'   => urlencode( $template ),
					'stylesheet' => urlencode( $stylesheet ),
				),
				admin_url( 'themes.php' )
			);
			$activate_link = wp_nonce_url( $activate_link, 'switch-theme_' . $stylesheet );

			$customize_url = add_query_arg(
				array(
					'theme'  => urlencode( $stylesheet ),
					'return' => urlencode( admin_url( 'themes.php' ) ),
				),
				admin_url( 'customize.php' )
			);

			if ( get_stylesheet() === $stylesheet ) {
				if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) {
					$update_actions['preview'] = sprintf(
						'<a href="%s" class="hide-if-no-customize load-customize">' .
						'<span aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></a>',
						esc_url( $customize_url ),
						__( 'Customize' ),
						/* translators: Hidden accessibility text. %s: Theme name. */
						sprintf( __( 'Customize &#8220;%s&#8221;' ), $name )
					);
				}
			} elseif ( current_user_can( 'switch_themes' ) ) {
				if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) {
					$update_actions['preview'] = sprintf(
						'<a href="%s" class="hide-if-no-customize load-customize">' .
						'<span aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></a>',
						esc_url( $customize_url ),
						__( 'Live Preview' ),
						/* translators: Hidden accessibility text. %s: Theme name. */
						sprintf( __( 'Live Preview &#8220;%s&#8221;' ), $name )
					);
				}

				$update_actions['activate'] = sprintf(
					'<a href="%s" class="activatelink">' .
					'<span aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></a>',
					esc_url( $activate_link ),
					_x( 'Activate', 'theme' ),
					/* translators: Hidden accessibility text. %s: Theme name. */
					sprintf( _x( 'Activate &#8220;%s&#8221;', 'theme' ), $name )
				);
			}

			if ( ! $this->result || is_wp_error( $this->result ) || is_network_admin() ) {
				unset( $update_actions['preview'], $update_actions['activate'] );
			}
		}

		$update_actions['themes_page'] = sprintf(
			'<a href="%s" target="_parent">%s</a>',
			self_admin_url( 'themes.php' ),
			__( 'Go to Themes page' )
		);

		/**
		 * Filters the list of action links available following a single theme update.
		 *
		 * @since 2.8.0
		 *
		 * @param string[] $update_actions Array of theme action links.
		 * @param string   $theme          Theme directory name.
		 */
		$update_actions = apply_filters( 'update_theme_complete_actions', $update_actions, $this->theme );

		if ( ! empty( $update_actions ) ) {
			$this->feedback( implode( ' | ', (array) $update_actions ) );
		}
	}
}
ms.php000064400000103041151212616040005671 0ustar00<?php
/**
 * Multisite administration functions.
 *
 * @package WordPress
 * @subpackage Multisite
 * @since 3.0.0
 */

/**
 * Determines whether uploaded file exceeds space quota.
 *
 * @since 3.0.0
 *
 * @param array $file An element from the `$_FILES` array for a given file.
 * @return array The `$_FILES` array element with 'error' key set if file exceeds quota. 'error' is empty otherwise.
 */
function check_upload_size( $file ) {
	if ( get_site_option( 'upload_space_check_disabled' ) ) {
		return $file;
	}

	if ( $file['error'] > 0 ) { // There's already an error.
		return $file;
	}

	if ( defined( 'WP_IMPORTING' ) ) {
		return $file;
	}

	$space_left = get_upload_space_available();

	$file_size = filesize( $file['tmp_name'] );
	if ( $space_left < $file_size ) {
		/* translators: %s: Required disk space in kilobytes. */
		$file['error'] = sprintf( __( 'Not enough space to upload. %s KB needed.' ), number_format( ( $file_size - $space_left ) / KB_IN_BYTES ) );
	}

	if ( $file_size > ( KB_IN_BYTES * get_site_option( 'fileupload_maxk', 1500 ) ) ) {
		/* translators: %s: Maximum allowed file size in kilobytes. */
		$file['error'] = sprintf( __( 'This file is too big. Files must be less than %s KB in size.' ), get_site_option( 'fileupload_maxk', 1500 ) );
	}

	if ( upload_is_user_over_quota( false ) ) {
		$file['error'] = __( 'You have used your space quota. Please delete files before uploading.' );
	}

	if ( $file['error'] > 0 && ! isset( $_POST['html-upload'] ) && ! wp_doing_ajax() ) {
		wp_die( $file['error'] . ' <a href="javascript:history.go(-1)">' . __( 'Back' ) . '</a>' );
	}

	return $file;
}

/**
 * Deletes a site.
 *
 * @since 3.0.0
 * @since 5.1.0 Use wp_delete_site() internally to delete the site row from the database.
 *
 * @param int  $blog_id Site ID.
 * @param bool $drop    True if site's database tables should be dropped. Default false.
 */
function wpmu_delete_blog( $blog_id, $drop = false ) {
	$blog_id = (int) $blog_id;

	$switch = false;
	if ( get_current_blog_id() !== $blog_id ) {
		$switch = true;
		switch_to_blog( $blog_id );
	}

	$blog = get_site( $blog_id );

	$current_network = get_network();

	// If a full blog object is not available, do not destroy anything.
	if ( $drop && ! $blog ) {
		$drop = false;
	}

	// Don't destroy the initial, main, or root blog.
	if ( $drop
		&& ( 1 === $blog_id || is_main_site( $blog_id )
			|| ( $blog->path === $current_network->path && $blog->domain === $current_network->domain ) )
	) {
		$drop = false;
	}

	$upload_path = trim( get_option( 'upload_path' ) );

	// If ms_files_rewriting is enabled and upload_path is empty, wp_upload_dir is not reliable.
	if ( $drop && get_site_option( 'ms_files_rewriting' ) && empty( $upload_path ) ) {
		$drop = false;
	}

	if ( $drop ) {
		wp_delete_site( $blog_id );
	} else {
		/** This action is documented in wp-includes/ms-blogs.php */
		do_action_deprecated( 'delete_blog', array( $blog_id, false ), '5.1.0' );

		$users = get_users(
			array(
				'blog_id' => $blog_id,
				'fields'  => 'ids',
			)
		);

		// Remove users from this blog.
		if ( ! empty( $users ) ) {
			foreach ( $users as $user_id ) {
				remove_user_from_blog( $user_id, $blog_id );
			}
		}

		update_blog_status( $blog_id, 'deleted', 1 );

		/** This action is documented in wp-includes/ms-blogs.php */
		do_action_deprecated( 'deleted_blog', array( $blog_id, false ), '5.1.0' );
	}

	if ( $switch ) {
		restore_current_blog();
	}
}

/**
 * Deletes a user and all of their posts from the network.
 *
 * This function:
 *
 * - Deletes all posts (of all post types) authored by the user on all sites on the network
 * - Deletes all links owned by the user on all sites on the network
 * - Removes the user from all sites on the network
 * - Deletes the user from the database
 *
 * @since 3.0.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int $id The user ID.
 * @return bool True if the user was deleted, false otherwise.
 */
function wpmu_delete_user( $id ) {
	global $wpdb;

	if ( ! is_numeric( $id ) ) {
		return false;
	}

	$id   = (int) $id;
	$user = new WP_User( $id );

	if ( ! $user->exists() ) {
		return false;
	}

	// Global super-administrators are protected, and cannot be deleted.
	$_super_admins = get_super_admins();
	if ( in_array( $user->user_login, $_super_admins, true ) ) {
		return false;
	}

	/**
	 * Fires before a user is deleted from the network.
	 *
	 * @since MU (3.0.0)
	 * @since 5.5.0 Added the `$user` parameter.
	 *
	 * @param int     $id   ID of the user about to be deleted from the network.
	 * @param WP_User $user WP_User object of the user about to be deleted from the network.
	 */
	do_action( 'wpmu_delete_user', $id, $user );

	$blogs = get_blogs_of_user( $id );

	if ( ! empty( $blogs ) ) {
		foreach ( $blogs as $blog ) {
			switch_to_blog( $blog->userblog_id );
			remove_user_from_blog( $id, $blog->userblog_id );

			$post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_author = %d", $id ) );
			foreach ( (array) $post_ids as $post_id ) {
				wp_delete_post( $post_id );
			}

			// Clean links.
			$link_ids = $wpdb->get_col( $wpdb->prepare( "SELECT link_id FROM $wpdb->links WHERE link_owner = %d", $id ) );

			if ( $link_ids ) {
				foreach ( $link_ids as $link_id ) {
					wp_delete_link( $link_id );
				}
			}

			restore_current_blog();
		}
	}

	$meta = $wpdb->get_col( $wpdb->prepare( "SELECT umeta_id FROM $wpdb->usermeta WHERE user_id = %d", $id ) );
	foreach ( $meta as $mid ) {
		delete_metadata_by_mid( 'user', $mid );
	}

	$wpdb->delete( $wpdb->users, array( 'ID' => $id ) );

	clean_user_cache( $user );

	/** This action is documented in wp-admin/includes/user.php */
	do_action( 'deleted_user', $id, null, $user );

	return true;
}

/**
 * Checks whether a site has used its allotted upload space.
 *
 * @since MU (3.0.0)
 *
 * @param bool $display_message Optional. If set to true and the quota is exceeded,
 *                              a warning message is displayed. Default true.
 * @return bool True if user is over upload space quota, otherwise false.
 */
function upload_is_user_over_quota( $display_message = true ) {
	if ( get_site_option( 'upload_space_check_disabled' ) ) {
		return false;
	}

	$space_allowed = get_space_allowed();
	if ( ! is_numeric( $space_allowed ) ) {
		$space_allowed = 10; // Default space allowed is 10 MB.
	}
	$space_used = get_space_used();

	if ( ( $space_allowed - $space_used ) < 0 ) {
		if ( $display_message ) {
			printf(
				/* translators: %s: Allowed space allocation. */
				__( 'Sorry, you have used your space allocation of %s. Please delete some files to upload more files.' ),
				size_format( $space_allowed * MB_IN_BYTES )
			);
		}
		return true;
	} else {
		return false;
	}
}

/**
 * Displays the amount of disk space used by the current site. Not used in core.
 *
 * @since MU (3.0.0)
 */
function display_space_usage() {
	$space_allowed = get_space_allowed();
	$space_used    = get_space_used();

	$percent_used = ( $space_used / $space_allowed ) * 100;

	$space = size_format( $space_allowed * MB_IN_BYTES );
	?>
	<strong>
	<?php
		/* translators: Storage space that's been used. 1: Percentage of used space, 2: Total space allowed in megabytes or gigabytes. */
		printf( __( 'Used: %1$s%% of %2$s' ), number_format( $percent_used ), $space );
	?>
	</strong>
	<?php
}

/**
 * Gets the remaining upload space for this site.
 *
 * @since MU (3.0.0)
 *
 * @param int $size Current max size in bytes.
 * @return int Max size in bytes.
 */
function fix_import_form_size( $size ) {
	if ( upload_is_user_over_quota( false ) ) {
		return 0;
	}
	$available = get_upload_space_available();
	return min( $size, $available );
}

/**
 * Displays the site upload space quota setting form on the Edit Site Settings screen.
 *
 * @since 3.0.0
 *
 * @param int $id The ID of the site to display the setting for.
 */
function upload_space_setting( $id ) {
	switch_to_blog( $id );
	$quota = get_option( 'blog_upload_space' );
	restore_current_blog();

	if ( ! $quota ) {
		$quota = '';
	}

	?>
	<tr>
		<th><label for="blog-upload-space-number"><?php _e( 'Site Upload Space Quota' ); ?></label></th>
		<td>
			<input type="number" step="1" min="0" style="width: 100px"
				name="option[blog_upload_space]" id="blog-upload-space-number"
				aria-describedby="blog-upload-space-desc" value="<?php echo esc_attr( $quota ); ?>" />
			<span id="blog-upload-space-desc"><span class="screen-reader-text">
				<?php
				/* translators: Hidden accessibility text. */
				_e( 'Size in megabytes' );
				?>
			</span> <?php _e( 'MB (Leave blank for network default)' ); ?></span>
		</td>
	</tr>
	<?php
}

/**
 * Cleans the user cache for a specific user.
 *
 * @since 3.0.0
 *
 * @param int $id The user ID.
 * @return int|false The ID of the refreshed user or false if the user does not exist.
 */
function refresh_user_details( $id ) {
	$id = (int) $id;

	$user = get_userdata( $id );
	if ( ! $user ) {
		return false;
	}

	clean_user_cache( $user );

	return $id;
}

/**
 * Returns the language for a language code.
 *
 * @since 3.0.0
 *
 * @param string $code Optional. The two-letter language code. Default empty.
 * @return string The language corresponding to $code if it exists. If it does not exist,
 *                then the first two letters of $code is returned.
 */
function format_code_lang( $code = '' ) {
	$code       = strtolower( substr( $code, 0, 2 ) );
	$lang_codes = array(
		'aa' => 'Afar',
		'ab' => 'Abkhazian',
		'af' => 'Afrikaans',
		'ak' => 'Akan',
		'sq' => 'Albanian',
		'am' => 'Amharic',
		'ar' => 'Arabic',
		'an' => 'Aragonese',
		'hy' => 'Armenian',
		'as' => 'Assamese',
		'av' => 'Avaric',
		'ae' => 'Avestan',
		'ay' => 'Aymara',
		'az' => 'Azerbaijani',
		'ba' => 'Bashkir',
		'bm' => 'Bambara',
		'eu' => 'Basque',
		'be' => 'Belarusian',
		'bn' => 'Bengali',
		'bh' => 'Bihari',
		'bi' => 'Bislama',
		'bs' => 'Bosnian',
		'br' => 'Breton',
		'bg' => 'Bulgarian',
		'my' => 'Burmese',
		'ca' => 'Catalan; Valencian',
		'ch' => 'Chamorro',
		'ce' => 'Chechen',
		'zh' => 'Chinese',
		'cu' => 'Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic',
		'cv' => 'Chuvash',
		'kw' => 'Cornish',
		'co' => 'Corsican',
		'cr' => 'Cree',
		'cs' => 'Czech',
		'da' => 'Danish',
		'dv' => 'Divehi; Dhivehi; Maldivian',
		'nl' => 'Dutch; Flemish',
		'dz' => 'Dzongkha',
		'en' => 'English',
		'eo' => 'Esperanto',
		'et' => 'Estonian',
		'ee' => 'Ewe',
		'fo' => 'Faroese',
		'fj' => 'Fijjian',
		'fi' => 'Finnish',
		'fr' => 'French',
		'fy' => 'Western Frisian',
		'ff' => 'Fulah',
		'ka' => 'Georgian',
		'de' => 'German',
		'gd' => 'Gaelic; Scottish Gaelic',
		'ga' => 'Irish',
		'gl' => 'Galician',
		'gv' => 'Manx',
		'el' => 'Greek, Modern',
		'gn' => 'Guarani',
		'gu' => 'Gujarati',
		'ht' => 'Haitian; Haitian Creole',
		'ha' => 'Hausa',
		'he' => 'Hebrew',
		'hz' => 'Herero',
		'hi' => 'Hindi',
		'ho' => 'Hiri Motu',
		'hu' => 'Hungarian',
		'ig' => 'Igbo',
		'is' => 'Icelandic',
		'io' => 'Ido',
		'ii' => 'Sichuan Yi',
		'iu' => 'Inuktitut',
		'ie' => 'Interlingue',
		'ia' => 'Interlingua (International Auxiliary Language Association)',
		'id' => 'Indonesian',
		'ik' => 'Inupiaq',
		'it' => 'Italian',
		'jv' => 'Javanese',
		'ja' => 'Japanese',
		'kl' => 'Kalaallisut; Greenlandic',
		'kn' => 'Kannada',
		'ks' => 'Kashmiri',
		'kr' => 'Kanuri',
		'kk' => 'Kazakh',
		'km' => 'Central Khmer',
		'ki' => 'Kikuyu; Gikuyu',
		'rw' => 'Kinyarwanda',
		'ky' => 'Kirghiz; Kyrgyz',
		'kv' => 'Komi',
		'kg' => 'Kongo',
		'ko' => 'Korean',
		'kj' => 'Kuanyama; Kwanyama',
		'ku' => 'Kurdish',
		'lo' => 'Lao',
		'la' => 'Latin',
		'lv' => 'Latvian',
		'li' => 'Limburgan; Limburger; Limburgish',
		'ln' => 'Lingala',
		'lt' => 'Lithuanian',
		'lb' => 'Luxembourgish; Letzeburgesch',
		'lu' => 'Luba-Katanga',
		'lg' => 'Ganda',
		'mk' => 'Macedonian',
		'mh' => 'Marshallese',
		'ml' => 'Malayalam',
		'mi' => 'Maori',
		'mr' => 'Marathi',
		'ms' => 'Malay',
		'mg' => 'Malagasy',
		'mt' => 'Maltese',
		'mo' => 'Moldavian',
		'mn' => 'Mongolian',
		'na' => 'Nauru',
		'nv' => 'Navajo; Navaho',
		'nr' => 'Ndebele, South; South Ndebele',
		'nd' => 'Ndebele, North; North Ndebele',
		'ng' => 'Ndonga',
		'ne' => 'Nepali',
		'nn' => 'Norwegian Nynorsk; Nynorsk, Norwegian',
		'nb' => 'Bokmål, Norwegian, Norwegian Bokmål',
		'no' => 'Norwegian',
		'ny' => 'Chichewa; Chewa; Nyanja',
		'oc' => 'Occitan, Provençal',
		'oj' => 'Ojibwa',
		'or' => 'Oriya',
		'om' => 'Oromo',
		'os' => 'Ossetian; Ossetic',
		'pa' => 'Panjabi; Punjabi',
		'fa' => 'Persian',
		'pi' => 'Pali',
		'pl' => 'Polish',
		'pt' => 'Portuguese',
		'ps' => 'Pushto',
		'qu' => 'Quechua',
		'rm' => 'Romansh',
		'ro' => 'Romanian',
		'rn' => 'Rundi',
		'ru' => 'Russian',
		'sg' => 'Sango',
		'sa' => 'Sanskrit',
		'sr' => 'Serbian',
		'hr' => 'Croatian',
		'si' => 'Sinhala; Sinhalese',
		'sk' => 'Slovak',
		'sl' => 'Slovenian',
		'se' => 'Northern Sami',
		'sm' => 'Samoan',
		'sn' => 'Shona',
		'sd' => 'Sindhi',
		'so' => 'Somali',
		'st' => 'Sotho, Southern',
		'es' => 'Spanish; Castilian',
		'sc' => 'Sardinian',
		'ss' => 'Swati',
		'su' => 'Sundanese',
		'sw' => 'Swahili',
		'sv' => 'Swedish',
		'ty' => 'Tahitian',
		'ta' => 'Tamil',
		'tt' => 'Tatar',
		'te' => 'Telugu',
		'tg' => 'Tajik',
		'tl' => 'Tagalog',
		'th' => 'Thai',
		'bo' => 'Tibetan',
		'ti' => 'Tigrinya',
		'to' => 'Tonga (Tonga Islands)',
		'tn' => 'Tswana',
		'ts' => 'Tsonga',
		'tk' => 'Turkmen',
		'tr' => 'Turkish',
		'tw' => 'Twi',
		'ug' => 'Uighur; Uyghur',
		'uk' => 'Ukrainian',
		'ur' => 'Urdu',
		'uz' => 'Uzbek',
		've' => 'Venda',
		'vi' => 'Vietnamese',
		'vo' => 'Volapük',
		'cy' => 'Welsh',
		'wa' => 'Walloon',
		'wo' => 'Wolof',
		'xh' => 'Xhosa',
		'yi' => 'Yiddish',
		'yo' => 'Yoruba',
		'za' => 'Zhuang; Chuang',
		'zu' => 'Zulu',
	);

	/**
	 * Filters the language codes.
	 *
	 * @since MU (3.0.0)
	 *
	 * @param string[] $lang_codes Array of key/value pairs of language codes where key is the short version.
	 * @param string   $code       A two-letter designation of the language.
	 */
	$lang_codes = apply_filters( 'lang_codes', $lang_codes, $code );
	return strtr( $code, $lang_codes );
}

/**
 * Displays an access denied message when a user tries to view a site's dashboard they
 * do not have access to.
 *
 * @since 3.2.0
 * @access private
 */
function _access_denied_splash() {
	if ( ! is_user_logged_in() || is_network_admin() ) {
		return;
	}

	$blogs = get_blogs_of_user( get_current_user_id() );

	if ( wp_list_filter( $blogs, array( 'userblog_id' => get_current_blog_id() ) ) ) {
		return;
	}

	$blog_name = get_bloginfo( 'name' );

	if ( empty( $blogs ) ) {
		wp_die(
			sprintf(
				/* translators: 1: Site title. */
				__( 'You attempted to access the "%1$s" dashboard, but you do not currently have privileges on this site. If you believe you should be able to access the "%1$s" dashboard, please contact your network administrator.' ),
				$blog_name
			),
			403
		);
	}

	$output = '<p>' . sprintf(
		/* translators: 1: Site title. */
		__( 'You attempted to access the "%1$s" dashboard, but you do not currently have privileges on this site. If you believe you should be able to access the "%1$s" dashboard, please contact your network administrator.' ),
		$blog_name
	) . '</p>';
	$output .= '<p>' . __( 'If you reached this screen by accident and meant to visit one of your own sites, here are some shortcuts to help you find your way.' ) . '</p>';

	$output .= '<h3>' . __( 'Your Sites' ) . '</h3>';
	$output .= '<table>';

	foreach ( $blogs as $blog ) {
		$output .= '<tr>';
		$output .= "<td>{$blog->blogname}</td>";
		$output .= '<td><a href="' . esc_url( get_admin_url( $blog->userblog_id ) ) . '">' . __( 'Visit Dashboard' ) . '</a> | ' .
			'<a href="' . esc_url( get_home_url( $blog->userblog_id ) ) . '">' . __( 'View Site' ) . '</a></td>';
		$output .= '</tr>';
	}

	$output .= '</table>';

	wp_die( $output, 403 );
}

/**
 * Checks if the current user has permissions to import new users.
 *
 * @since 3.0.0
 *
 * @param string $permission A permission to be checked. Currently not used.
 * @return bool True if the user has proper permissions, false if they do not.
 */
function check_import_new_users( $permission ) {
	if ( ! current_user_can( 'manage_network_users' ) ) {
		return false;
	}

	return true;
}
// See "import_allow_fetch_attachments" and "import_attachment_size_limit" filters too.

/**
 * Generates and displays a drop-down of available languages.
 *
 * @since 3.0.0
 *
 * @param string[] $lang_files Optional. An array of the language files. Default empty array.
 * @param string   $current    Optional. The current language code. Default empty.
 */
function mu_dropdown_languages( $lang_files = array(), $current = '' ) {
	$flag   = false;
	$output = array();

	foreach ( (array) $lang_files as $val ) {
		$code_lang = basename( $val, '.mo' );

		if ( 'en_US' === $code_lang ) { // American English.
			$flag          = true;
			$ae            = __( 'American English' );
			$output[ $ae ] = '<option value="' . esc_attr( $code_lang ) . '"' . selected( $current, $code_lang, false ) . '> ' . $ae . '</option>';
		} elseif ( 'en_GB' === $code_lang ) { // British English.
			$flag          = true;
			$be            = __( 'British English' );
			$output[ $be ] = '<option value="' . esc_attr( $code_lang ) . '"' . selected( $current, $code_lang, false ) . '> ' . $be . '</option>';
		} else {
			$translated            = format_code_lang( $code_lang );
			$output[ $translated ] = '<option value="' . esc_attr( $code_lang ) . '"' . selected( $current, $code_lang, false ) . '> ' . esc_html( $translated ) . '</option>';
		}
	}

	if ( false === $flag ) { // WordPress English.
		$output[] = '<option value=""' . selected( $current, '', false ) . '>' . __( 'English' ) . '</option>';
	}

	// Order by name.
	uksort( $output, 'strnatcasecmp' );

	/**
	 * Filters the languages available in the dropdown.
	 *
	 * @since MU (3.0.0)
	 *
	 * @param string[] $output     Array of HTML output for the dropdown.
	 * @param string[] $lang_files Array of available language files.
	 * @param string   $current    The current language code.
	 */
	$output = apply_filters( 'mu_dropdown_languages', $output, $lang_files, $current );

	echo implode( "\n\t", $output );
}

/**
 * Displays an admin notice to upgrade all sites after a core upgrade.
 *
 * @since 3.0.0
 *
 * @global int    $wp_db_version WordPress database version.
 * @global string $pagenow       The filename of the current screen.
 *
 * @return void|false Void on success. False if the current user is not a super admin.
 */
function site_admin_notice() {
	global $wp_db_version, $pagenow;

	if ( ! current_user_can( 'upgrade_network' ) ) {
		return false;
	}

	if ( 'upgrade.php' === $pagenow ) {
		return;
	}

	if ( (int) get_site_option( 'wpmu_upgrade_site' ) !== $wp_db_version ) {
		$upgrade_network_message = sprintf(
			/* translators: %s: URL to Upgrade Network screen. */
			__( 'Thank you for Updating! Please visit the <a href="%s">Upgrade Network</a> page to update all your sites.' ),
			esc_url( network_admin_url( 'upgrade.php' ) )
		);

		wp_admin_notice(
			$upgrade_network_message,
			array(
				'type'               => 'warning',
				'additional_classes' => array( 'update-nag', 'inline' ),
				'paragraph_wrap'     => false,
			)
		);
	}
}

/**
 * Avoids a collision between a site slug and a permalink slug.
 *
 * In a subdirectory installation this will make sure that a site and a post do not use the
 * same subdirectory by checking for a site with the same name as a new post.
 *
 * @since 3.0.0
 *
 * @param array $data    An array of post data.
 * @param array $postarr An array of posts. Not currently used.
 * @return array The new array of post data after checking for collisions.
 */
function avoid_blog_page_permalink_collision( $data, $postarr ) {
	if ( is_subdomain_install() ) {
		return $data;
	}
	if ( 'page' !== $data['post_type'] ) {
		return $data;
	}
	if ( ! isset( $data['post_name'] ) || '' === $data['post_name'] ) {
		return $data;
	}
	if ( ! is_main_site() ) {
		return $data;
	}
	if ( isset( $data['post_parent'] ) && $data['post_parent'] ) {
		return $data;
	}

	$post_name = $data['post_name'];
	$c         = 0;

	while ( $c < 10 && get_id_from_blogname( $post_name ) ) {
		$post_name .= mt_rand( 1, 10 );
		++$c;
	}

	if ( $post_name !== $data['post_name'] ) {
		$data['post_name'] = $post_name;
	}

	return $data;
}

/**
 * Handles the display of choosing a user's primary site.
 *
 * This displays the user's primary site and allows the user to choose
 * which site is primary.
 *
 * @since 3.0.0
 */
function choose_primary_blog() {
	?>
	<table class="form-table" role="presentation">
	<tr>
	<?php /* translators: My Sites label. */ ?>
		<th scope="row"><label for="primary_blog"><?php _e( 'Primary Site' ); ?></label></th>
		<td>
		<?php
		$all_blogs    = get_blogs_of_user( get_current_user_id() );
		$primary_blog = (int) get_user_meta( get_current_user_id(), 'primary_blog', true );
		if ( count( $all_blogs ) > 1 ) {
			$found = false;
			?>
			<select name="primary_blog" id="primary_blog">
				<?php
				foreach ( (array) $all_blogs as $blog ) {
					if ( $blog->userblog_id === $primary_blog ) {
						$found = true;
					}
					?>
					<option value="<?php echo $blog->userblog_id; ?>"<?php selected( $primary_blog, $blog->userblog_id ); ?>><?php echo esc_url( get_home_url( $blog->userblog_id ) ); ?></option>
					<?php
				}
				?>
			</select>
			<?php
			if ( ! $found ) {
				$blog = reset( $all_blogs );
				update_user_meta( get_current_user_id(), 'primary_blog', $blog->userblog_id );
			}
		} elseif ( 1 === count( $all_blogs ) ) {
			$blog = reset( $all_blogs );
			echo esc_url( get_home_url( $blog->userblog_id ) );
			if ( $blog->userblog_id !== $primary_blog ) { // Set the primary blog again if it's out of sync with blog list.
				update_user_meta( get_current_user_id(), 'primary_blog', $blog->userblog_id );
			}
		} else {
			_e( 'Not available' );
		}
		?>
		</td>
	</tr>
	</table>
	<?php
}

/**
 * Determines whether or not this network from this page can be edited.
 *
 * By default editing of network is restricted to the Network Admin for that `$network_id`.
 * This function allows for this to be overridden.
 *
 * @since 3.1.0
 *
 * @param int $network_id The network ID to check.
 * @return bool True if network can be edited, false otherwise.
 */
function can_edit_network( $network_id ) {
	if ( get_current_network_id() === (int) $network_id ) {
		$result = true;
	} else {
		$result = false;
	}

	/**
	 * Filters whether this network can be edited from this page.
	 *
	 * @since 3.1.0
	 *
	 * @param bool $result     Whether the network can be edited from this page.
	 * @param int  $network_id The network ID to check.
	 */
	return apply_filters( 'can_edit_network', $result, $network_id );
}

/**
 * Prints thickbox image paths for Network Admin.
 *
 * @since 3.1.0
 *
 * @access private
 */
function _thickbox_path_admin_subfolder() {
	?>
<script type="text/javascript">
var tb_pathToImage = "<?php echo esc_js( includes_url( 'js/thickbox/loadingAnimation.gif', 'relative' ) ); ?>";
</script>
	<?php
}

/**
 * @since 3.0.0
 *
 * @param array $users
 * @return bool
 */
function confirm_delete_users( $users ) {
	$current_user = wp_get_current_user();
	if ( ! is_array( $users ) || empty( $users ) ) {
		return false;
	}
	?>
	<h1><?php esc_html_e( 'Users' ); ?></h1>

	<?php if ( 1 === count( $users ) ) : ?>
		<p><?php _e( 'You have chosen to delete the user from all networks and sites.' ); ?></p>
	<?php else : ?>
		<p><?php _e( 'You have chosen to delete the following users from all networks and sites.' ); ?></p>
	<?php endif; ?>

	<form action="users.php?action=dodelete" method="post">
	<input type="hidden" name="dodelete" />
	<?php
	wp_nonce_field( 'ms-users-delete' );
	$site_admins = get_super_admins();
	$admin_out   = '<option value="' . esc_attr( $current_user->ID ) . '">' . $current_user->user_login . '</option>';
	?>
	<table class="form-table" role="presentation">
	<?php
	$allusers = (array) $_POST['allusers'];
	foreach ( $allusers as $user_id ) {
		if ( '' !== $user_id && '0' !== $user_id ) {
			$delete_user = get_userdata( $user_id );

			if ( ! current_user_can( 'delete_user', $delete_user->ID ) ) {
				wp_die(
					sprintf(
						/* translators: %s: User login. */
						__( 'Warning! User %s cannot be deleted.' ),
						$delete_user->user_login
					)
				);
			}

			if ( in_array( $delete_user->user_login, $site_admins, true ) ) {
				wp_die(
					sprintf(
						/* translators: %s: User login. */
						__( 'Warning! User cannot be deleted. The user %s is a network administrator.' ),
						'<em>' . $delete_user->user_login . '</em>'
					)
				);
			}
			?>
			<tr>
				<th scope="row"><?php echo $delete_user->user_login; ?>
					<?php echo '<input type="hidden" name="user[]" value="' . esc_attr( $user_id ) . '" />' . "\n"; ?>
				</th>
			<?php
			$blogs = get_blogs_of_user( $user_id, true );

			if ( ! empty( $blogs ) ) {
				?>
				<td><fieldset><p><legend>
				<?php
				printf(
					/* translators: %s: User login. */
					__( 'What should be done with content owned by %s?' ),
					'<em>' . $delete_user->user_login . '</em>'
				);
				?>
				</legend></p>
				<?php
				foreach ( (array) $blogs as $key => $details ) {
					$blog_users = get_users(
						array(
							'blog_id' => $details->userblog_id,
							'fields'  => array( 'ID', 'user_login' ),
						)
					);

					if ( is_array( $blog_users ) && ! empty( $blog_users ) ) {
						$user_site     = "<a href='" . esc_url( get_home_url( $details->userblog_id ) ) . "'>{$details->blogname}</a>";
						$user_dropdown = '<label for="reassign_user" class="screen-reader-text">' .
								/* translators: Hidden accessibility text. */
								__( 'Select a user' ) .
							'</label>';
						$user_dropdown .= "<select name='blog[$user_id][$key]' id='reassign_user'>";
						$user_list      = '';

						foreach ( $blog_users as $user ) {
							if ( ! in_array( (int) $user->ID, $allusers, true ) ) {
								$user_list .= "<option value='{$user->ID}'>{$user->user_login}</option>";
							}
						}

						if ( '' === $user_list ) {
							$user_list = $admin_out;
						}

						$user_dropdown .= $user_list;
						$user_dropdown .= "</select>\n";
						?>
						<ul style="list-style:none;">
							<li>
								<?php
								/* translators: %s: Link to user's site. */
								printf( __( 'Site: %s' ), $user_site );
								?>
							</li>
							<li><label><input type="radio" id="delete_option0" name="delete[<?php echo $details->userblog_id . '][' . $delete_user->ID; ?>]" value="delete" checked="checked" />
							<?php _e( 'Delete all content.' ); ?></label></li>
							<li><label><input type="radio" id="delete_option1" name="delete[<?php echo $details->userblog_id . '][' . $delete_user->ID; ?>]" value="reassign" />
							<?php _e( 'Attribute all content to:' ); ?></label>
							<?php echo $user_dropdown; ?></li>
						</ul>
						<?php
					}
				}
				echo '</fieldset></td></tr>';
			} else {
				?>
				<td><p><?php _e( 'User has no sites or content and will be deleted.' ); ?></p></td>
			<?php } ?>
			</tr>
			<?php
		}
	}

	?>
	</table>
	<?php
	/** This action is documented in wp-admin/users.php */
	do_action( 'delete_user_form', $current_user, $allusers );

	if ( 1 === count( $users ) ) :
		?>
		<p><?php _e( 'Once you hit &#8220;Confirm Deletion&#8221;, the user will be permanently removed.' ); ?></p>
	<?php else : ?>
		<p><?php _e( 'Once you hit &#8220;Confirm Deletion&#8221;, these users will be permanently removed.' ); ?></p>
		<?php
	endif;

	submit_button( __( 'Confirm Deletion' ), 'primary' );
	?>
	</form>
	<?php
	return true;
}

/**
 * Prints JavaScript in the header on the Network Settings screen.
 *
 * @since 4.1.0
 */
function network_settings_add_js() {
	?>
<script type="text/javascript">
jQuery( function($) {
	var languageSelect = $( '#WPLANG' );
	$( 'form' ).on( 'submit', function() {
		/*
		 * Don't show a spinner for English and installed languages,
		 * as there is nothing to download.
		 */
		if ( ! languageSelect.find( 'option:selected' ).data( 'installed' ) ) {
			$( '#submit', this ).after( '<span class="spinner language-install-spinner is-active" />' );
		}
	});
} );
</script>
	<?php
}

/**
 * Outputs the HTML for a network's "Edit Site" tabular interface.
 *
 * @since 4.6.0
 *
 * @global string $pagenow The filename of the current screen.
 *
 * @param array $args {
 *     Optional. Array or string of Query parameters. Default empty array.
 *
 *     @type int    $blog_id  The site ID. Default is the current site.
 *     @type array  $links    The tabs to include with (label|url|cap) keys.
 *     @type string $selected The ID of the selected link.
 * }
 */
function network_edit_site_nav( $args = array() ) {

	/**
	 * Filters the links that appear on site-editing network pages.
	 *
	 * Default links: 'site-info', 'site-users', 'site-themes', and 'site-settings'.
	 *
	 * @since 4.6.0
	 *
	 * @param array $links {
	 *     An array of link data representing individual network admin pages.
	 *
	 *     @type array $link_slug {
	 *         An array of information about the individual link to a page.
	 *
	 *         $type string $label Label to use for the link.
	 *         $type string $url   URL, relative to `network_admin_url()` to use for the link.
	 *         $type string $cap   Capability required to see the link.
	 *     }
	 * }
	 */
	$links = apply_filters(
		'network_edit_site_nav_links',
		array(
			'site-info'     => array(
				'label' => __( 'Info' ),
				'url'   => 'site-info.php',
				'cap'   => 'manage_sites',
			),
			'site-users'    => array(
				'label' => __( 'Users' ),
				'url'   => 'site-users.php',
				'cap'   => 'manage_sites',
			),
			'site-themes'   => array(
				'label' => __( 'Themes' ),
				'url'   => 'site-themes.php',
				'cap'   => 'manage_sites',
			),
			'site-settings' => array(
				'label' => __( 'Settings' ),
				'url'   => 'site-settings.php',
				'cap'   => 'manage_sites',
			),
		)
	);

	// Parse arguments.
	$parsed_args = wp_parse_args(
		$args,
		array(
			'blog_id'  => isset( $_GET['blog_id'] ) ? (int) $_GET['blog_id'] : 0,
			'links'    => $links,
			'selected' => 'site-info',
		)
	);

	// Setup the links array.
	$screen_links = array();

	// Loop through tabs.
	foreach ( $parsed_args['links'] as $link_id => $link ) {

		// Skip link if user can't access.
		if ( ! current_user_can( $link['cap'], $parsed_args['blog_id'] ) ) {
			continue;
		}

		// Link classes.
		$classes = array( 'nav-tab' );

		// Aria-current attribute.
		$aria_current = '';

		// Selected is set by the parent OR assumed by the $pagenow global.
		if ( $parsed_args['selected'] === $link_id || $link['url'] === $GLOBALS['pagenow'] ) {
			$classes[]    = 'nav-tab-active';
			$aria_current = ' aria-current="page"';
		}

		// Escape each class.
		$esc_classes = implode( ' ', $classes );

		// Get the URL for this link.
		$url = add_query_arg( array( 'id' => $parsed_args['blog_id'] ), network_admin_url( $link['url'] ) );

		// Add link to nav links.
		$screen_links[ $link_id ] = '<a href="' . esc_url( $url ) . '" id="' . esc_attr( $link_id ) . '" class="' . $esc_classes . '"' . $aria_current . '>' . esc_html( $link['label'] ) . '</a>';
	}

	// All done!
	echo '<nav class="nav-tab-wrapper wp-clearfix" aria-label="' . esc_attr__( 'Secondary menu' ) . '">';
	echo implode( '', $screen_links );
	echo '</nav>';
}

/**
 * Returns the arguments for the help tab on the Edit Site screens.
 *
 * @since 4.9.0
 *
 * @return array Help tab arguments.
 */
function get_site_screen_help_tab_args() {
	return array(
		'id'      => 'overview',
		'title'   => __( 'Overview' ),
		'content' =>
			'<p>' . __( 'The menu is for editing information specific to individual sites, particularly if the admin area of a site is unavailable.' ) . '</p>' .
			'<p>' . __( '<strong>Info</strong> &mdash; The site URL is rarely edited as this can cause the site to not work properly. The Registered date and Last Updated date are displayed. Network admins can mark a site as archived, spam, deleted and mature, to remove from public listings or disable.' ) . '</p>' .
			'<p>' . __( '<strong>Users</strong> &mdash; This displays the users associated with this site. You can also change their role, reset their password, or remove them from the site. Removing the user from the site does not remove the user from the network.' ) . '</p>' .
			'<p>' . sprintf(
				/* translators: %s: URL to Network Themes screen. */
				__( '<strong>Themes</strong> &mdash; This area shows themes that are not already enabled across the network. Enabling a theme in this menu makes it accessible to this site. It does not activate the theme, but allows it to show in the site&#8217;s Appearance menu. To enable a theme for the entire network, see the <a href="%s">Network Themes</a> screen.' ),
				network_admin_url( 'themes.php' )
			) . '</p>' .
			'<p>' . __( '<strong>Settings</strong> &mdash; This page shows a list of all settings associated with this site. Some are created by WordPress and others are created by plugins you activate. Note that some fields are grayed out and say Serialized Data. You cannot modify these values due to the way the setting is stored in the database.' ) . '</p>',
	);
}

/**
 * Returns the content for the help sidebar on the Edit Site screens.
 *
 * @since 4.9.0
 *
 * @return string Help sidebar content.
 */
function get_site_screen_help_sidebar_content() {
	return '<p><strong>' . __( 'For more information:' ) . '</strong></p>' .
		'<p>' . __( '<a href="https://developer.wordpress.org/advanced-administration/multisite/admin/#network-admin-sites-screen">Documentation on Site Management</a>' ) . '</p>' .
		'<p>' . __( '<a href="https://wordpress.org/support/forum/multisite/">Support forums</a>' ) . '</p>';
}

/**
 * Stop execution if the role can not be assigned by the current user.
 *
 * @since 6.8.0
 *
 * @param string $role Role the user is attempting to assign.
 */
function wp_ensure_editable_role( $role ) {
	$roles = get_editable_roles();
	if ( ! isset( $roles[ $role ] ) ) {
		wp_die( __( 'Sorry, you are not allowed to give users that role.' ), 403 );
	}
}
class-wp-ms-themes-list-table.php000064400000067426151212616040012761 0ustar00<?php
/**
 * List Table API: WP_MS_Themes_List_Table class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 3.1.0
 */

/**
 * Core class used to implement displaying themes in a list table for the network admin.
 *
 * @since 3.1.0
 *
 * @see WP_List_Table
 */
class WP_MS_Themes_List_Table extends WP_List_Table {

	public $site_id;
	public $is_site_themes;

	private $has_items;

	/**
	 * Whether to show the auto-updates UI.
	 *
	 * @since 5.5.0
	 *
	 * @var bool True if auto-updates UI is to be shown, false otherwise.
	 */
	protected $show_autoupdates = true;

	/**
	 * Constructor.
	 *
	 * @since 3.1.0
	 *
	 * @see WP_List_Table::__construct() for more information on default arguments.
	 *
	 * @global string $status
	 * @global int    $page
	 *
	 * @param array $args An associative array of arguments.
	 */
	public function __construct( $args = array() ) {
		global $status, $page;

		parent::__construct(
			array(
				'plural' => 'themes',
				'screen' => isset( $args['screen'] ) ? $args['screen'] : null,
			)
		);

		$status = isset( $_REQUEST['theme_status'] ) ? $_REQUEST['theme_status'] : 'all';
		if ( ! in_array( $status, array( 'all', 'enabled', 'disabled', 'upgrade', 'search', 'broken', 'auto-update-enabled', 'auto-update-disabled' ), true ) ) {
			$status = 'all';
		}

		$page = $this->get_pagenum();

		$this->is_site_themes = ( 'site-themes-network' === $this->screen->id ) ? true : false;

		if ( $this->is_site_themes ) {
			$this->site_id = isset( $_REQUEST['id'] ) ? (int) $_REQUEST['id'] : 0;
		}

		$this->show_autoupdates = wp_is_auto_update_enabled_for_type( 'theme' ) &&
			! $this->is_site_themes && current_user_can( 'update_themes' );
	}

	/**
	 * @return array
	 */
	protected function get_table_classes() {
		// @todo Remove and add CSS for .themes.
		return array( 'widefat', 'plugins' );
	}

	/**
	 * @return bool
	 */
	public function ajax_user_can() {
		if ( $this->is_site_themes ) {
			return current_user_can( 'manage_sites' );
		} else {
			return current_user_can( 'manage_network_themes' );
		}
	}

	/**
	 * @global string $status
	 * @global array $totals
	 * @global int $page
	 * @global string $orderby
	 * @global string $order
	 * @global string $s
	 */
	public function prepare_items() {
		global $status, $totals, $page, $orderby, $order, $s;

		$orderby = ! empty( $_REQUEST['orderby'] ) ? sanitize_text_field( $_REQUEST['orderby'] ) : '';
		$order   = ! empty( $_REQUEST['order'] ) ? sanitize_text_field( $_REQUEST['order'] ) : '';
		$s       = ! empty( $_REQUEST['s'] ) ? sanitize_text_field( $_REQUEST['s'] ) : '';

		$themes = array(
			/**
			 * Filters the full array of WP_Theme objects to list in the Multisite
			 * themes list table.
			 *
			 * @since 3.1.0
			 *
			 * @param WP_Theme[] $all Array of WP_Theme objects to display in the list table.
			 */
			'all'      => apply_filters( 'all_themes', wp_get_themes() ),
			'search'   => array(),
			'enabled'  => array(),
			'disabled' => array(),
			'upgrade'  => array(),
			'broken'   => $this->is_site_themes ? array() : wp_get_themes( array( 'errors' => true ) ),
		);

		if ( $this->show_autoupdates ) {
			$auto_updates = (array) get_site_option( 'auto_update_themes', array() );

			$themes['auto-update-enabled']  = array();
			$themes['auto-update-disabled'] = array();
		}

		if ( $this->is_site_themes ) {
			$themes_per_page = $this->get_items_per_page( 'site_themes_network_per_page' );
			$allowed_where   = 'site';
		} else {
			$themes_per_page = $this->get_items_per_page( 'themes_network_per_page' );
			$allowed_where   = 'network';
		}

		$current      = get_site_transient( 'update_themes' );
		$maybe_update = current_user_can( 'update_themes' ) && ! $this->is_site_themes && $current;

		foreach ( (array) $themes['all'] as $key => $theme ) {
			if ( $this->is_site_themes && $theme->is_allowed( 'network' ) ) {
				unset( $themes['all'][ $key ] );
				continue;
			}

			if ( $maybe_update && isset( $current->response[ $key ] ) ) {
				$themes['all'][ $key ]->update = true;
				$themes['upgrade'][ $key ]     = $themes['all'][ $key ];
			}

			$filter                    = $theme->is_allowed( $allowed_where, $this->site_id ) ? 'enabled' : 'disabled';
			$themes[ $filter ][ $key ] = $themes['all'][ $key ];

			$theme_data = array(
				'update_supported' => isset( $theme->update_supported ) ? $theme->update_supported : true,
			);

			// Extra info if known. array_merge() ensures $theme_data has precedence if keys collide.
			if ( isset( $current->response[ $key ] ) ) {
				$theme_data = array_merge( (array) $current->response[ $key ], $theme_data );
			} elseif ( isset( $current->no_update[ $key ] ) ) {
				$theme_data = array_merge( (array) $current->no_update[ $key ], $theme_data );
			} else {
				$theme_data['update_supported'] = false;
			}

			$theme->update_supported = $theme_data['update_supported'];

			/*
			 * Create the expected payload for the auto_update_theme filter, this is the same data
			 * as contained within $updates or $no_updates but used when the Theme is not known.
			 */
			$filter_payload = array(
				'theme'        => $key,
				'new_version'  => '',
				'url'          => '',
				'package'      => '',
				'requires'     => '',
				'requires_php' => '',
			);

			$filter_payload = (object) array_merge( $filter_payload, array_intersect_key( $theme_data, $filter_payload ) );

			$auto_update_forced = wp_is_auto_update_forced_for_item( 'theme', null, $filter_payload );

			if ( ! is_null( $auto_update_forced ) ) {
				$theme->auto_update_forced = $auto_update_forced;
			}

			if ( $this->show_autoupdates ) {
				$enabled = in_array( $key, $auto_updates, true ) && $theme->update_supported;
				if ( isset( $theme->auto_update_forced ) ) {
					$enabled = (bool) $theme->auto_update_forced;
				}

				if ( $enabled ) {
					$themes['auto-update-enabled'][ $key ] = $theme;
				} else {
					$themes['auto-update-disabled'][ $key ] = $theme;
				}
			}
		}

		if ( $s ) {
			$status           = 'search';
			$themes['search'] = array_filter( array_merge( $themes['all'], $themes['broken'] ), array( $this, '_search_callback' ) );
		}

		$totals    = array();
		$js_themes = array();
		foreach ( $themes as $type => $list ) {
			$totals[ $type ]    = count( $list );
			$js_themes[ $type ] = array_keys( $list );
		}

		if ( empty( $themes[ $status ] ) && ! in_array( $status, array( 'all', 'search' ), true ) ) {
			$status = 'all';
		}

		$this->items = $themes[ $status ];
		WP_Theme::sort_by_name( $this->items );

		$this->has_items = ! empty( $themes['all'] );
		$total_this_page = $totals[ $status ];

		wp_localize_script(
			'updates',
			'_wpUpdatesItemCounts',
			array(
				'themes' => $js_themes,
				'totals' => wp_get_update_data(),
			)
		);

		if ( $orderby ) {
			$orderby = ucfirst( $orderby );
			$order   = strtoupper( $order );

			if ( 'Name' === $orderby ) {
				if ( 'ASC' === $order ) {
					$this->items = array_reverse( $this->items );
				}
			} else {
				uasort( $this->items, array( $this, '_order_callback' ) );
			}
		}

		$start = ( $page - 1 ) * $themes_per_page;

		if ( $total_this_page > $themes_per_page ) {
			$this->items = array_slice( $this->items, $start, $themes_per_page, true );
		}

		$this->set_pagination_args(
			array(
				'total_items' => $total_this_page,
				'per_page'    => $themes_per_page,
			)
		);
	}

	/**
	 * @param WP_Theme $theme
	 * @return bool
	 */
	public function _search_callback( $theme ) {
		static $term = null;
		if ( is_null( $term ) ) {
			$term = wp_unslash( $_REQUEST['s'] );
		}

		foreach ( array( 'Name', 'Description', 'Author', 'Author', 'AuthorURI' ) as $field ) {
			// Don't mark up; Do translate.
			if ( false !== stripos( $theme->display( $field, false, true ), $term ) ) {
				return true;
			}
		}

		if ( false !== stripos( $theme->get_stylesheet(), $term ) ) {
			return true;
		}

		if ( false !== stripos( $theme->get_template(), $term ) ) {
			return true;
		}

		return false;
	}

	// Not used by any core columns.
	/**
	 * @global string $orderby
	 * @global string $order
	 * @param array $theme_a
	 * @param array $theme_b
	 * @return int
	 */
	public function _order_callback( $theme_a, $theme_b ) {
		global $orderby, $order;

		$a = $theme_a[ $orderby ];
		$b = $theme_b[ $orderby ];

		if ( $a === $b ) {
			return 0;
		}

		if ( 'DESC' === $order ) {
			return ( $a < $b ) ? 1 : -1;
		} else {
			return ( $a < $b ) ? -1 : 1;
		}
	}

	/**
	 */
	public function no_items() {
		if ( $this->has_items ) {
			_e( 'No themes found.' );
		} else {
			_e( 'No themes are currently available.' );
		}
	}

	/**
	 * @return string[] Array of column titles keyed by their column name.
	 */
	public function get_columns() {
		$columns = array(
			'cb'          => '<input type="checkbox" />',
			'name'        => __( 'Theme' ),
			'description' => __( 'Description' ),
		);

		if ( $this->show_autoupdates ) {
			$columns['auto-updates'] = __( 'Automatic Updates' );
		}

		return $columns;
	}

	/**
	 * @return array
	 */
	protected function get_sortable_columns() {
		return array(
			'name' => array( 'name', false, __( 'Theme' ), __( 'Table ordered by Theme Name.' ), 'asc' ),
		);
	}

	/**
	 * Gets the name of the primary column.
	 *
	 * @since 4.3.0
	 *
	 * @return string Unalterable name of the primary column name, in this case, 'name'.
	 */
	protected function get_primary_column_name() {
		return 'name';
	}

	/**
	 * @global array $totals
	 * @global string $status
	 * @return array
	 */
	protected function get_views() {
		global $totals, $status;

		$status_links = array();
		foreach ( $totals as $type => $count ) {
			if ( ! $count ) {
				continue;
			}

			switch ( $type ) {
				case 'all':
					/* translators: %s: Number of themes. */
					$text = _nx(
						'All <span class="count">(%s)</span>',
						'All <span class="count">(%s)</span>',
						$count,
						'themes'
					);
					break;
				case 'enabled':
					/* translators: %s: Number of themes. */
					$text = _nx(
						'Enabled <span class="count">(%s)</span>',
						'Enabled <span class="count">(%s)</span>',
						$count,
						'themes'
					);
					break;
				case 'disabled':
					/* translators: %s: Number of themes. */
					$text = _nx(
						'Disabled <span class="count">(%s)</span>',
						'Disabled <span class="count">(%s)</span>',
						$count,
						'themes'
					);
					break;
				case 'upgrade':
					/* translators: %s: Number of themes. */
					$text = _nx(
						'Update Available <span class="count">(%s)</span>',
						'Update Available <span class="count">(%s)</span>',
						$count,
						'themes'
					);
					break;
				case 'broken':
					/* translators: %s: Number of themes. */
					$text = _nx(
						'Broken <span class="count">(%s)</span>',
						'Broken <span class="count">(%s)</span>',
						$count,
						'themes'
					);
					break;
				case 'auto-update-enabled':
					/* translators: %s: Number of themes. */
					$text = _n(
						'Auto-updates Enabled <span class="count">(%s)</span>',
						'Auto-updates Enabled <span class="count">(%s)</span>',
						$count
					);
					break;
				case 'auto-update-disabled':
					/* translators: %s: Number of themes. */
					$text = _n(
						'Auto-updates Disabled <span class="count">(%s)</span>',
						'Auto-updates Disabled <span class="count">(%s)</span>',
						$count
					);
					break;
			}

			if ( $this->is_site_themes ) {
				$url = 'site-themes.php?id=' . $this->site_id;
			} else {
				$url = 'themes.php';
			}

			if ( 'search' !== $type ) {
				$status_links[ $type ] = array(
					'url'     => esc_url( add_query_arg( 'theme_status', $type, $url ) ),
					'label'   => sprintf( $text, number_format_i18n( $count ) ),
					'current' => $type === $status,
				);
			}
		}

		return $this->get_views_links( $status_links );
	}

	/**
	 * @global string $status
	 *
	 * @return array
	 */
	protected function get_bulk_actions() {
		global $status;

		$actions = array();
		if ( 'enabled' !== $status ) {
			$actions['enable-selected'] = $this->is_site_themes ? __( 'Enable' ) : __( 'Network Enable' );
		}
		if ( 'disabled' !== $status ) {
			$actions['disable-selected'] = $this->is_site_themes ? __( 'Disable' ) : __( 'Network Disable' );
		}
		if ( ! $this->is_site_themes ) {
			if ( current_user_can( 'update_themes' ) ) {
				$actions['update-selected'] = __( 'Update' );
			}
			if ( current_user_can( 'delete_themes' ) ) {
				$actions['delete-selected'] = __( 'Delete' );
			}
		}

		if ( $this->show_autoupdates ) {
			if ( 'auto-update-enabled' !== $status ) {
				$actions['enable-auto-update-selected'] = __( 'Enable Auto-updates' );
			}

			if ( 'auto-update-disabled' !== $status ) {
				$actions['disable-auto-update-selected'] = __( 'Disable Auto-updates' );
			}
		}

		return $actions;
	}

	/**
	 * Generates the list table rows.
	 *
	 * @since 3.1.0
	 */
	public function display_rows() {
		foreach ( $this->items as $theme ) {
			$this->single_row( $theme );
		}
	}

	/**
	 * Handles the checkbox column output.
	 *
	 * @since 4.3.0
	 * @since 5.9.0 Renamed `$theme` to `$item` to match parent class for PHP 8 named parameter support.
	 *
	 * @param WP_Theme $item The current WP_Theme object.
	 */
	public function column_cb( $item ) {
		// Restores the more descriptive, specific name for use within this method.
		$theme = $item;

		$checkbox_id = 'checkbox_' . md5( $theme->get( 'Name' ) );
		?>
		<input type="checkbox" name="checked[]" value="<?php echo esc_attr( $theme->get_stylesheet() ); ?>" id="<?php echo $checkbox_id; ?>" />
		<label for="<?php echo $checkbox_id; ?>" >
			<span class="screen-reader-text">
			<?php
			printf(
				/* translators: Hidden accessibility text. %s: Theme name */
				__( 'Select %s' ),
				$theme->display( 'Name' )
			);
			?>
			</span>
		</label>
		<?php
	}

	/**
	 * Handles the name column output.
	 *
	 * @since 4.3.0
	 *
	 * @global string $status
	 * @global int    $page
	 * @global string $s
	 *
	 * @param WP_Theme $theme The current WP_Theme object.
	 */
	public function column_name( $theme ) {
		global $status, $page, $s;

		$context = $status;

		if ( $this->is_site_themes ) {
			$url     = "site-themes.php?id={$this->site_id}&amp;";
			$allowed = $theme->is_allowed( 'site', $this->site_id );
		} else {
			$url     = 'themes.php?';
			$allowed = $theme->is_allowed( 'network' );
		}

		// Pre-order.
		$actions = array(
			'enable'  => '',
			'disable' => '',
			'delete'  => '',
		);

		$stylesheet = $theme->get_stylesheet();
		$theme_key  = urlencode( $stylesheet );

		if ( ! $allowed ) {
			if ( ! $theme->errors() ) {
				$url = add_query_arg(
					array(
						'action' => 'enable',
						'theme'  => $theme_key,
						'paged'  => $page,
						's'      => $s,
					),
					$url
				);

				if ( $this->is_site_themes ) {
					/* translators: %s: Theme name. */
					$aria_label = sprintf( __( 'Enable %s' ), $theme->display( 'Name' ) );
				} else {
					/* translators: %s: Theme name. */
					$aria_label = sprintf( __( 'Network Enable %s' ), $theme->display( 'Name' ) );
				}

				$actions['enable'] = sprintf(
					'<a href="%s" class="edit" aria-label="%s">%s</a>',
					esc_url( wp_nonce_url( $url, 'enable-theme_' . $stylesheet ) ),
					esc_attr( $aria_label ),
					( $this->is_site_themes ? __( 'Enable' ) : __( 'Network Enable' ) )
				);
			}
		} else {
			$url = add_query_arg(
				array(
					'action' => 'disable',
					'theme'  => $theme_key,
					'paged'  => $page,
					's'      => $s,
				),
				$url
			);

			if ( $this->is_site_themes ) {
				/* translators: %s: Theme name. */
				$aria_label = sprintf( __( 'Disable %s' ), $theme->display( 'Name' ) );
			} else {
				/* translators: %s: Theme name. */
				$aria_label = sprintf( __( 'Network Disable %s' ), $theme->display( 'Name' ) );
			}

			$actions['disable'] = sprintf(
				'<a href="%s" aria-label="%s">%s</a>',
				esc_url( wp_nonce_url( $url, 'disable-theme_' . $stylesheet ) ),
				esc_attr( $aria_label ),
				( $this->is_site_themes ? __( 'Disable' ) : __( 'Network Disable' ) )
			);
		}

		if ( ! $allowed && ! $this->is_site_themes
			&& current_user_can( 'delete_themes' )
			&& get_option( 'stylesheet' ) !== $stylesheet
			&& get_option( 'template' ) !== $stylesheet
		) {
			$url = add_query_arg(
				array(
					'action'       => 'delete-selected',
					'checked[]'    => $theme_key,
					'theme_status' => $context,
					'paged'        => $page,
					's'            => $s,
				),
				'themes.php'
			);

			/* translators: %s: Theme name. */
			$aria_label = sprintf( _x( 'Delete %s', 'theme' ), $theme->display( 'Name' ) );

			$actions['delete'] = sprintf(
				'<a href="%s" class="delete" aria-label="%s">%s</a>',
				esc_url( wp_nonce_url( $url, 'bulk-themes' ) ),
				esc_attr( $aria_label ),
				__( 'Delete' )
			);
		}
		/**
		 * Filters the action links displayed for each theme in the Multisite
		 * themes list table.
		 *
		 * The action links displayed are determined by the theme's status, and
		 * which Multisite themes list table is being displayed - the Network
		 * themes list table (themes.php), which displays all installed themes,
		 * or the Site themes list table (site-themes.php), which displays the
		 * non-network enabled themes when editing a site in the Network admin.
		 *
		 * The default action links for the Network themes list table include
		 * 'Network Enable', 'Network Disable', and 'Delete'.
		 *
		 * The default action links for the Site themes list table include
		 * 'Enable', and 'Disable'.
		 *
		 * @since 2.8.0
		 *
		 * @param string[] $actions An array of action links.
		 * @param WP_Theme $theme   The current WP_Theme object.
		 * @param string   $context Status of the theme, one of 'all', 'enabled', or 'disabled'.
		 */
		$actions = apply_filters( 'theme_action_links', array_filter( $actions ), $theme, $context );

		/**
		 * Filters the action links of a specific theme in the Multisite themes
		 * list table.
		 *
		 * The dynamic portion of the hook name, `$stylesheet`, refers to the
		 * directory name of the theme, which in most cases is synonymous
		 * with the template name.
		 *
		 * @since 3.1.0
		 *
		 * @param string[] $actions An array of action links.
		 * @param WP_Theme $theme   The current WP_Theme object.
		 * @param string   $context Status of the theme, one of 'all', 'enabled', or 'disabled'.
		 */
		$actions = apply_filters( "theme_action_links_{$stylesheet}", $actions, $theme, $context );

		echo $this->row_actions( $actions, true );
	}

	/**
	 * Handles the description column output.
	 *
	 * @since 4.3.0
	 *
	 * @global string $status
	 * @global array  $totals
	 *
	 * @param WP_Theme $theme The current WP_Theme object.
	 */
	public function column_description( $theme ) {
		global $status, $totals;

		if ( $theme->errors() ) {
			$pre = 'broken' === $status ? '<strong class="error-message">' . __( 'Broken Theme:' ) . '</strong> ' : '';
			wp_admin_notice(
				$pre . $theme->errors()->get_error_message(),
				array(
					'type'               => 'error',
					'additional_classes' => 'inline',
				)
			);
		}

		if ( $this->is_site_themes ) {
			$allowed = $theme->is_allowed( 'site', $this->site_id );
		} else {
			$allowed = $theme->is_allowed( 'network' );
		}

		$class = ! $allowed ? 'inactive' : 'active';
		if ( ! empty( $totals['upgrade'] ) && ! empty( $theme->update ) ) {
			$class .= ' update';
		}

		echo "<div class='theme-description'><p>" . $theme->display( 'Description' ) . "</p></div>
			<div class='$class second theme-version-author-uri'>";

		$stylesheet = $theme->get_stylesheet();
		$theme_meta = array();

		if ( $theme->get( 'Version' ) ) {
			/* translators: %s: Theme version. */
			$theme_meta[] = sprintf( __( 'Version %s' ), $theme->display( 'Version' ) );
		}

		/* translators: %s: Theme author. */
		$theme_meta[] = sprintf( __( 'By %s' ), $theme->display( 'Author' ) );

		if ( $theme->get( 'ThemeURI' ) ) {
			/* translators: %s: Theme name. */
			$aria_label = sprintf( __( 'Visit theme site for %s' ), $theme->display( 'Name' ) );

			$theme_meta[] = sprintf(
				'<a href="%s" aria-label="%s">%s</a>',
				$theme->display( 'ThemeURI' ),
				esc_attr( $aria_label ),
				__( 'Visit Theme Site' )
			);
		}

		if ( $theme->parent() ) {
			$theme_meta[] = sprintf(
				/* translators: %s: Theme name. */
				__( 'Child theme of %s' ),
				'<strong>' . $theme->parent()->display( 'Name' ) . '</strong>'
			);
		}

		/**
		 * Filters the array of row meta for each theme in the Multisite themes
		 * list table.
		 *
		 * @since 3.1.0
		 *
		 * @param string[] $theme_meta An array of the theme's metadata, including
		 *                             the version, author, and theme URI.
		 * @param string   $stylesheet Directory name of the theme.
		 * @param WP_Theme $theme      WP_Theme object.
		 * @param string   $status     Status of the theme.
		 */
		$theme_meta = apply_filters( 'theme_row_meta', $theme_meta, $stylesheet, $theme, $status );

		echo implode( ' | ', $theme_meta );

		echo '</div>';
	}

	/**
	 * Handles the auto-updates column output.
	 *
	 * @since 5.5.0
	 *
	 * @global string $status
	 * @global int  $page
	 *
	 * @param WP_Theme $theme The current WP_Theme object.
	 */
	public function column_autoupdates( $theme ) {
		global $status, $page;

		static $auto_updates, $available_updates;

		if ( ! $auto_updates ) {
			$auto_updates = (array) get_site_option( 'auto_update_themes', array() );
		}
		if ( ! $available_updates ) {
			$available_updates = get_site_transient( 'update_themes' );
		}

		$stylesheet = $theme->get_stylesheet();

		if ( isset( $theme->auto_update_forced ) ) {
			if ( $theme->auto_update_forced ) {
				// Forced on.
				$text = __( 'Auto-updates enabled' );
			} else {
				$text = __( 'Auto-updates disabled' );
			}
			$action     = 'unavailable';
			$time_class = ' hidden';
		} elseif ( empty( $theme->update_supported ) ) {
			$text       = '';
			$action     = 'unavailable';
			$time_class = ' hidden';
		} elseif ( in_array( $stylesheet, $auto_updates, true ) ) {
			$text       = __( 'Disable auto-updates' );
			$action     = 'disable';
			$time_class = '';
		} else {
			$text       = __( 'Enable auto-updates' );
			$action     = 'enable';
			$time_class = ' hidden';
		}

		$query_args = array(
			'action'       => "{$action}-auto-update",
			'theme'        => $stylesheet,
			'paged'        => $page,
			'theme_status' => $status,
		);

		$url = add_query_arg( $query_args, 'themes.php' );

		if ( 'unavailable' === $action ) {
			$html[] = '<span class="label">' . $text . '</span>';
		} else {
			$html[] = sprintf(
				'<a href="%s" class="toggle-auto-update aria-button-if-js" data-wp-action="%s">',
				wp_nonce_url( $url, 'updates' ),
				$action
			);

			$html[] = '<span class="dashicons dashicons-update spin hidden" aria-hidden="true"></span>';
			$html[] = '<span class="label">' . $text . '</span>';
			$html[] = '</a>';

		}

		if ( isset( $available_updates->response[ $stylesheet ] ) ) {
			$html[] = sprintf(
				'<div class="auto-update-time%s">%s</div>',
				$time_class,
				wp_get_auto_update_message()
			);
		}

		$html = implode( '', $html );

		/**
		 * Filters the HTML of the auto-updates setting for each theme in the Themes list table.
		 *
		 * @since 5.5.0
		 *
		 * @param string   $html       The HTML for theme's auto-update setting, including
		 *                             toggle auto-update action link and time to next update.
		 * @param string   $stylesheet Directory name of the theme.
		 * @param WP_Theme $theme      WP_Theme object.
		 */
		echo apply_filters( 'theme_auto_update_setting_html', $html, $stylesheet, $theme );

		wp_admin_notice(
			'',
			array(
				'type'               => 'error',
				'additional_classes' => array( 'notice-alt', 'inline', 'hidden' ),
			)
		);
	}

	/**
	 * Handles default column output.
	 *
	 * @since 4.3.0
	 * @since 5.9.0 Renamed `$theme` to `$item` to match parent class for PHP 8 named parameter support.
	 *
	 * @param WP_Theme $item        The current WP_Theme object.
	 * @param string   $column_name The current column name.
	 */
	public function column_default( $item, $column_name ) {
		// Restores the more descriptive, specific name for use within this method.
		$theme = $item;

		$stylesheet = $theme->get_stylesheet();

		/**
		 * Fires inside each custom column of the Multisite themes list table.
		 *
		 * @since 3.1.0
		 *
		 * @param string   $column_name Name of the column.
		 * @param string   $stylesheet  Directory name of the theme.
		 * @param WP_Theme $theme       Current WP_Theme object.
		 */
		do_action( 'manage_themes_custom_column', $column_name, $stylesheet, $theme );
	}

	/**
	 * Handles the output for a single table row.
	 *
	 * @since 4.3.0
	 *
	 * @param WP_Theme $item The current WP_Theme object.
	 */
	public function single_row_columns( $item ) {
		list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();

		foreach ( $columns as $column_name => $column_display_name ) {
			$extra_classes = '';
			if ( in_array( $column_name, $hidden, true ) ) {
				$extra_classes .= ' hidden';
			}

			switch ( $column_name ) {
				case 'cb':
					echo '<th scope="row" class="check-column">';

					$this->column_cb( $item );

					echo '</th>';
					break;

				case 'name':
					$active_theme_label = '';

					/* The presence of the site_id property means that this is a subsite view and a label for the active theme needs to be added */
					if ( ! empty( $this->site_id ) ) {
						$stylesheet = get_blog_option( $this->site_id, 'stylesheet' );
						$template   = get_blog_option( $this->site_id, 'template' );

						/* Add a label for the active template */
						if ( $item->get_template() === $template ) {
							$active_theme_label = ' &mdash; ' . __( 'Active Theme' );
						}

						/* In case this is a child theme, label it properly */
						if ( $stylesheet !== $template && $item->get_stylesheet() === $stylesheet ) {
							$active_theme_label = ' &mdash; ' . __( 'Active Child Theme' );
						}
					}

					echo "<td class='theme-title column-primary{$extra_classes}'><strong>" . $item->display( 'Name' ) . $active_theme_label . '</strong>';

					$this->column_name( $item );

					echo '</td>';
					break;

				case 'description':
					echo "<td class='column-description desc{$extra_classes}'>";

					$this->column_description( $item );

					echo '</td>';
					break;

				case 'auto-updates':
					echo "<td class='column-auto-updates{$extra_classes}'>";

					$this->column_autoupdates( $item );

					echo '</td>';
					break;
				default:
					echo "<td class='$column_name column-$column_name{$extra_classes}'>";

					$this->column_default( $item, $column_name );

					echo '</td>';
					break;
			}
		}
	}

	/**
	 * @global string $status
	 * @global array  $totals
	 *
	 * @param WP_Theme $theme
	 */
	public function single_row( $theme ) {
		global $status, $totals;

		if ( $this->is_site_themes ) {
			$allowed = $theme->is_allowed( 'site', $this->site_id );
		} else {
			$allowed = $theme->is_allowed( 'network' );
		}

		$stylesheet = $theme->get_stylesheet();

		$class = ! $allowed ? 'inactive' : 'active';
		if ( ! empty( $totals['upgrade'] ) && ! empty( $theme->update ) ) {
			$class .= ' update';
		}

		printf(
			'<tr class="%s" data-slug="%s">',
			esc_attr( $class ),
			esc_attr( $stylesheet )
		);

		$this->single_row_columns( $theme );

		echo '</tr>';

		if ( $this->is_site_themes ) {
			remove_action( "after_theme_row_$stylesheet", 'wp_theme_update_row' );
		}

		/**
		 * Fires after each row in the Multisite themes list table.
		 *
		 * @since 3.1.0
		 *
		 * @param string   $stylesheet Directory name of the theme.
		 * @param WP_Theme $theme      Current WP_Theme object.
		 * @param string   $status     Status of the theme.
		 */
		do_action( 'after_theme_row', $stylesheet, $theme, $status );

		/**
		 * Fires after each specific row in the Multisite themes list table.
		 *
		 * The dynamic portion of the hook name, `$stylesheet`, refers to the
		 * directory name of the theme, most often synonymous with the template
		 * name of the theme.
		 *
		 * @since 3.5.0
		 *
		 * @param string   $stylesheet Directory name of the theme.
		 * @param WP_Theme $theme      Current WP_Theme object.
		 * @param string   $status     Status of the theme.
		 */
		do_action( "after_theme_row_{$stylesheet}", $stylesheet, $theme, $status );
	}
}
error_log000064400000243450151212616040006467 0ustar00[07-Feb-2024 01:46:26 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function __() in /home/nandedex/public_html/wp-admin/includes/file.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/file.php on line 16
[04-Mar-2024 22:08:05 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function __() in /home/nandedex/public_html/wp-admin/includes/file.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/file.php on line 16
[17-Mar-2024 13:12:20 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function __() in /home/nandedex/public_html/wp-admin/includes/file.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/file.php on line 16
[23-Apr-2024 01:15:16 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function __() in /home/nandedex/public_html/wp-admin/includes/file.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/file.php on line 16
[28-May-2024 21:57:59 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
[08-Jul-2024 08:42:23 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function add_action() in /home/nandedex/public_html/wp-admin/includes/admin-filters.php:11
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin-filters.php on line 11
[08-Jul-2024 08:42:35 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
[17-Aug-2024 01:03:28 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
[22-Aug-2024 10:37:59 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function add_action() in /home/nandedex/public_html/wp-admin/includes/admin-filters.php:11
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin-filters.php on line 11
[22-Aug-2024 10:38:01 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
[22-Aug-2024 10:38:03 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-automatic-upgrader-skin.php:21
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-automatic-upgrader-skin.php on line 21
[07-Sep-2024 06:58:36 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
[09-Nov-2024 18:01:05 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function add_action() in /home/nandedex/public_html/wp-admin/includes/admin-filters.php:11
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin-filters.php on line 11
[09-Nov-2024 18:01:05 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
[09-Nov-2024 18:01:09 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-automatic-upgrader-skin.php:21
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-automatic-upgrader-skin.php on line 21
[09-Nov-2024 18:01:09 UTC] PHP Fatal error:  Uncaught Error: Class 'Bulk_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-bulk-plugin-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-bulk-plugin-upgrader-skin.php on line 18
[09-Nov-2024 18:01:10 UTC] PHP Fatal error:  Uncaught Error: Class 'Bulk_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-bulk-theme-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-bulk-theme-upgrader-skin.php on line 18
[09-Nov-2024 18:01:10 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-bulk-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-bulk-upgrader-skin.php on line 18
[01-Dec-2024 05:35:20 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function add_action() in /home/nandedex/public_html/wp-admin/includes/admin-filters.php:11
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin-filters.php on line 11
[01-Dec-2024 05:35:23 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
[01-Dec-2024 05:35:30 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-automatic-upgrader-skin.php:21
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-automatic-upgrader-skin.php on line 21
[01-Dec-2024 05:35:32 UTC] PHP Fatal error:  Uncaught Error: Class 'Bulk_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-bulk-plugin-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-bulk-plugin-upgrader-skin.php on line 18
[01-Dec-2024 05:35:35 UTC] PHP Fatal error:  Uncaught Error: Class 'Bulk_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-bulk-theme-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-bulk-theme-upgrader-skin.php on line 18
[01-Dec-2024 05:35:37 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-bulk-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-bulk-upgrader-skin.php on line 18
[01-Dec-2024 05:35:39 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader' not found in /home/nandedex/public_html/wp-admin/includes/class-core-upgrader.php:25
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-core-upgrader.php on line 25
[01-Dec-2024 05:35:48 UTC] PHP Fatal error:  Uncaught Error: Class 'ftp_base' not found in /home/nandedex/public_html/wp-admin/includes/class-ftp-pure.php:28
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-ftp-pure.php on line 28
[01-Dec-2024 05:35:50 UTC] PHP Fatal error:  Uncaught Error: Class 'ftp_base' not found in /home/nandedex/public_html/wp-admin/includes/class-ftp-sockets.php:28
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-ftp-sockets.php on line 28
[01-Dec-2024 05:35:54 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-language-pack-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-language-pack-upgrader-skin.php on line 18
[01-Dec-2024 05:35:57 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader' not found in /home/nandedex/public_html/wp-admin/includes/class-language-pack-upgrader.php:19
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-language-pack-upgrader.php on line 19
[01-Dec-2024 05:36:01 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-plugin-installer-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-plugin-installer-skin.php on line 18
[01-Dec-2024 05:36:03 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-plugin-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-plugin-upgrader-skin.php on line 18
[01-Dec-2024 05:36:05 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader' not found in /home/nandedex/public_html/wp-admin/includes/class-plugin-upgrader.php:21
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-plugin-upgrader.php on line 21
[01-Dec-2024 05:36:08 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-theme-installer-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-theme-installer-skin.php on line 18
[01-Dec-2024 05:36:11 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-theme-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-theme-upgrader-skin.php on line 18
[01-Dec-2024 05:36:13 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader' not found in /home/nandedex/public_html/wp-admin/includes/class-theme-upgrader.php:21
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-theme-upgrader.php on line 21
[01-Dec-2024 05:36:15 UTC] PHP Fatal error:  Uncaught Error: Class 'Walker' not found in /home/nandedex/public_html/wp-admin/includes/class-walker-category-checklist.php:19
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-walker-category-checklist.php on line 19
[01-Dec-2024 05:36:18 UTC] PHP Fatal error:  Uncaught Error: Class 'Walker_Nav_Menu' not found in /home/nandedex/public_html/wp-admin/includes/class-walker-nav-menu-checklist.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-walker-nav-menu-checklist.php on line 16
[01-Dec-2024 05:36:20 UTC] PHP Fatal error:  Uncaught Error: Class 'Walker_Nav_Menu' not found in /home/nandedex/public_html/wp-admin/includes/class-walker-nav-menu-edit.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-walker-nav-menu-edit.php on line 17
[01-Dec-2024 05:36:22 UTC] PHP Fatal error:  Uncaught Error: Class 'Automatic_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-ajax-upgrader-skin.php:19
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-ajax-upgrader-skin.php on line 19
[01-Dec-2024 05:36:26 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-application-passwords-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-application-passwords-list-table.php on line 17
[01-Dec-2024 05:36:30 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-comments-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-comments-list-table.php on line 17
[01-Dec-2024 05:36:39 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Filesystem_Base' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-direct.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-direct.php on line 16
[01-Dec-2024 05:36:41 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Filesystem_Base' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ftpext.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ftpext.php on line 16
[01-Dec-2024 05:36:43 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Filesystem_Base' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ftpsockets.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ftpsockets.php on line 16
[01-Dec-2024 05:36:45 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Filesystem_Base' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ssh2.php:36
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ssh2.php on line 36
[01-Dec-2024 05:36:51 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-links-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-links-list-table.php on line 17
[01-Dec-2024 05:36:53 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-list-table-compat.php:15
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-list-table-compat.php on line 15
[01-Dec-2024 05:36:58 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-media-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-media-list-table.php on line 17
[01-Dec-2024 05:37:00 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-sites-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-sites-list-table.php on line 17
[01-Dec-2024 05:37:02 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-themes-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-themes-list-table.php on line 17
[01-Dec-2024 05:37:04 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-users-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-users-list-table.php on line 17
[01-Dec-2024 05:37:06 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-plugin-install-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-plugin-install-list-table.php on line 17
[01-Dec-2024 05:37:08 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-plugins-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-plugins-list-table.php on line 17
[01-Dec-2024 05:37:10 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Comments_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-post-comments-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-post-comments-list-table.php on line 17
[01-Dec-2024 05:37:12 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-posts-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-posts-list-table.php on line 17
[01-Dec-2024 05:37:14 UTC] PHP Warning:  Use of undefined constant ABSPATH - assumed 'ABSPATH' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-export-requests-list-table.php on line 11
[01-Dec-2024 05:37:14 UTC] PHP Warning:  require_once(ABSPATHwp-admin/includes/class-wp-privacy-requests-table.php): failed to open stream: No such file or directory in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-export-requests-list-table.php on line 11
[01-Dec-2024 05:37:14 UTC] PHP Fatal error:  require_once(): Failed opening required 'ABSPATHwp-admin/includes/class-wp-privacy-requests-table.php' (include_path='.:/opt/cpanel/ea-php74/root/usr/share/pear') in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-export-requests-list-table.php on line 11
[01-Dec-2024 05:37:17 UTC] PHP Warning:  Use of undefined constant ABSPATH - assumed 'ABSPATH' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-removal-requests-list-table.php on line 11
[01-Dec-2024 05:37:17 UTC] PHP Warning:  require_once(ABSPATHwp-admin/includes/class-wp-privacy-requests-table.php): failed to open stream: No such file or directory in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-removal-requests-list-table.php on line 11
[01-Dec-2024 05:37:17 UTC] PHP Fatal error:  require_once(): Failed opening required 'ABSPATHwp-admin/includes/class-wp-privacy-requests-table.php' (include_path='.:/opt/cpanel/ea-php74/root/usr/share/pear') in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-removal-requests-list-table.php on line 11
[01-Dec-2024 05:37:21 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-requests-table.php:10
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-requests-table.php on line 10
[01-Dec-2024 05:37:33 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-terms-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-terms-list-table.php on line 17
[01-Dec-2024 05:37:35 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Themes_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-theme-install-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-theme-install-list-table.php on line 17
[01-Dec-2024 05:37:36 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-themes-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-themes-list-table.php on line 17
[01-Dec-2024 05:37:41 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function _deprecated_file() in /home/nandedex/public_html/wp-admin/includes/class-wp-upgrader-skins.php:11
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-upgrader-skins.php on line 11
[01-Dec-2024 05:37:43 UTC] PHP Warning:  Use of undefined constant ABSPATH - assumed 'ABSPATH' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/class-wp-upgrader.php on line 13
[01-Dec-2024 05:37:43 UTC] PHP Warning:  require_once(ABSPATHwp-admin/includes/class-wp-upgrader-skin.php): failed to open stream: No such file or directory in /home/nandedex/public_html/wp-admin/includes/class-wp-upgrader.php on line 13
[01-Dec-2024 05:37:43 UTC] PHP Fatal error:  require_once(): Failed opening required 'ABSPATHwp-admin/includes/class-wp-upgrader-skin.php' (include_path='.:/opt/cpanel/ea-php74/root/usr/share/pear') in /home/nandedex/public_html/wp-admin/includes/class-wp-upgrader.php on line 13
[01-Dec-2024 05:37:45 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-users-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-users-list-table.php on line 17
[01-Dec-2024 05:37:50 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function __() in /home/nandedex/public_html/wp-admin/includes/continents-cities.php:12
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/continents-cities.php on line 12
[01-Dec-2024 05:37:56 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Privacy_Data_Export_Requests_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/deprecated.php:1535
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/deprecated.php on line 1535
[01-Dec-2024 05:37:57 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function __() in /home/nandedex/public_html/wp-admin/includes/edit-tag-messages.php:14
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/edit-tag-messages.php on line 14
[01-Dec-2024 05:38:01 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function __() in /home/nandedex/public_html/wp-admin/includes/file.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/file.php on line 16
[01-Dec-2024 05:38:14 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function is_network_admin() in /home/nandedex/public_html/wp-admin/includes/menu.php:9
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/menu.php on line 9
[01-Dec-2024 05:38:22 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function add_filter() in /home/nandedex/public_html/wp-admin/includes/ms-admin-filters.php:11
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/ms-admin-filters.php on line 11
[01-Dec-2024 05:38:28 UTC] PHP Warning:  Use of undefined constant ABSPATH - assumed 'ABSPATH' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/nav-menu.php on line 11
[01-Dec-2024 05:38:28 UTC] PHP Warning:  require_once(ABSPATHwp-admin/includes/class-walker-nav-menu-edit.php): failed to open stream: No such file or directory in /home/nandedex/public_html/wp-admin/includes/nav-menu.php on line 11
[01-Dec-2024 05:38:28 UTC] PHP Fatal error:  require_once(): Failed opening required 'ABSPATHwp-admin/includes/class-walker-nav-menu-edit.php' (include_path='.:/opt/cpanel/ea-php74/root/usr/share/pear') in /home/nandedex/public_html/wp-admin/includes/nav-menu.php on line 11
[01-Dec-2024 05:38:50 UTC] PHP Fatal error:  Uncaught Error: Call to a member function get_charset_collate() on null in /home/nandedex/public_html/wp-admin/includes/schema.php:23
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/schema.php on line 23
[01-Dec-2024 05:38:56 UTC] PHP Warning:  Use of undefined constant ABSPATH - assumed 'ABSPATH' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/template.php on line 12
[01-Dec-2024 05:38:56 UTC] PHP Warning:  require_once(ABSPATHwp-admin/includes/class-walker-category-checklist.php): failed to open stream: No such file or directory in /home/nandedex/public_html/wp-admin/includes/template.php on line 12
[01-Dec-2024 05:38:56 UTC] PHP Fatal error:  require_once(): Failed opening required 'ABSPATHwp-admin/includes/class-walker-category-checklist.php' (include_path='.:/opt/cpanel/ea-php74/root/usr/share/pear') in /home/nandedex/public_html/wp-admin/includes/template.php on line 12
[01-Dec-2024 05:39:08 UTC] PHP Warning:  Use of undefined constant WP_CONTENT_DIR - assumed 'WP_CONTENT_DIR' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/upgrade.php on line 12
[01-Dec-2024 05:39:08 UTC] PHP Warning:  Use of undefined constant ABSPATH - assumed 'ABSPATH' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/upgrade.php on line 17
[01-Dec-2024 05:39:08 UTC] PHP Warning:  require_once(ABSPATHwp-admin/includes/admin.php): failed to open stream: No such file or directory in /home/nandedex/public_html/wp-admin/includes/upgrade.php on line 17
[01-Dec-2024 05:39:08 UTC] PHP Fatal error:  require_once(): Failed opening required 'ABSPATHwp-admin/includes/admin.php' (include_path='.:/opt/cpanel/ea-php74/root/usr/share/pear') in /home/nandedex/public_html/wp-admin/includes/upgrade.php on line 17
[05-Feb-2025 18:01:43 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function add_action() in /home/nandedex/public_html/wp-admin/includes/admin-filters.php:11
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin-filters.php on line 11
[05-Feb-2025 18:01:45 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
[05-Feb-2025 18:01:48 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-automatic-upgrader-skin.php:21
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-automatic-upgrader-skin.php on line 21
[05-Feb-2025 18:01:48 UTC] PHP Fatal error:  Uncaught Error: Class 'Bulk_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-bulk-plugin-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-bulk-plugin-upgrader-skin.php on line 18
[05-Feb-2025 18:01:49 UTC] PHP Fatal error:  Uncaught Error: Class 'Bulk_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-bulk-theme-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-bulk-theme-upgrader-skin.php on line 18
[05-Feb-2025 18:01:49 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-bulk-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-bulk-upgrader-skin.php on line 18
[05-Feb-2025 18:01:50 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader' not found in /home/nandedex/public_html/wp-admin/includes/class-core-upgrader.php:25
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-core-upgrader.php on line 25
[05-Feb-2025 18:01:55 UTC] PHP Fatal error:  Uncaught Error: Class 'ftp_base' not found in /home/nandedex/public_html/wp-admin/includes/class-ftp-pure.php:28
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-ftp-pure.php on line 28
[05-Feb-2025 18:01:56 UTC] PHP Fatal error:  Uncaught Error: Class 'ftp_base' not found in /home/nandedex/public_html/wp-admin/includes/class-ftp-sockets.php:28
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-ftp-sockets.php on line 28
[05-Feb-2025 18:01:57 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-language-pack-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-language-pack-upgrader-skin.php on line 18
[05-Feb-2025 18:01:58 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader' not found in /home/nandedex/public_html/wp-admin/includes/class-language-pack-upgrader.php:19
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-language-pack-upgrader.php on line 19
[05-Feb-2025 18:01:59 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-plugin-installer-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-plugin-installer-skin.php on line 18
[05-Feb-2025 18:02:00 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-plugin-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-plugin-upgrader-skin.php on line 18
[05-Feb-2025 18:02:00 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader' not found in /home/nandedex/public_html/wp-admin/includes/class-plugin-upgrader.php:21
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-plugin-upgrader.php on line 21
[05-Feb-2025 18:02:01 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-theme-installer-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-theme-installer-skin.php on line 18
[05-Feb-2025 18:02:02 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-theme-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-theme-upgrader-skin.php on line 18
[05-Feb-2025 18:02:03 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader' not found in /home/nandedex/public_html/wp-admin/includes/class-theme-upgrader.php:21
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-theme-upgrader.php on line 21
[05-Feb-2025 18:02:04 UTC] PHP Fatal error:  Uncaught Error: Class 'Walker' not found in /home/nandedex/public_html/wp-admin/includes/class-walker-category-checklist.php:19
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-walker-category-checklist.php on line 19
[05-Feb-2025 18:02:05 UTC] PHP Fatal error:  Uncaught Error: Class 'Walker_Nav_Menu' not found in /home/nandedex/public_html/wp-admin/includes/class-walker-nav-menu-checklist.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-walker-nav-menu-checklist.php on line 16
[05-Feb-2025 18:02:05 UTC] PHP Fatal error:  Uncaught Error: Class 'Walker_Nav_Menu' not found in /home/nandedex/public_html/wp-admin/includes/class-walker-nav-menu-edit.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-walker-nav-menu-edit.php on line 17
[05-Feb-2025 18:02:05 UTC] PHP Fatal error:  Uncaught Error: Class 'Automatic_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-ajax-upgrader-skin.php:19
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-ajax-upgrader-skin.php on line 19
[05-Feb-2025 18:02:06 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-application-passwords-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-application-passwords-list-table.php on line 17
[05-Feb-2025 18:02:07 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-comments-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-comments-list-table.php on line 17
[05-Feb-2025 18:02:09 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Filesystem_Base' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-direct.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-direct.php on line 16
[05-Feb-2025 18:02:10 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Filesystem_Base' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ftpext.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ftpext.php on line 16
[05-Feb-2025 18:02:10 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Filesystem_Base' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ftpsockets.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ftpsockets.php on line 16
[05-Feb-2025 18:02:11 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Filesystem_Base' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ssh2.php:36
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ssh2.php on line 36
[05-Feb-2025 18:02:12 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-links-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-links-list-table.php on line 17
[05-Feb-2025 18:02:13 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-list-table-compat.php:15
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-list-table-compat.php on line 15
[05-Feb-2025 18:02:14 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-media-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-media-list-table.php on line 17
[05-Feb-2025 18:02:17 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-sites-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-sites-list-table.php on line 17
[05-Feb-2025 18:02:17 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-themes-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-themes-list-table.php on line 17
[05-Feb-2025 18:02:18 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-users-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-users-list-table.php on line 17
[05-Feb-2025 18:02:18 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-plugin-install-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-plugin-install-list-table.php on line 17
[05-Feb-2025 18:02:19 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-plugins-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-plugins-list-table.php on line 17
[05-Feb-2025 18:02:19 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Comments_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-post-comments-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-post-comments-list-table.php on line 17
[05-Feb-2025 18:02:20 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-posts-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-posts-list-table.php on line 17
[05-Feb-2025 18:02:21 UTC] PHP Warning:  Use of undefined constant ABSPATH - assumed 'ABSPATH' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-export-requests-list-table.php on line 11
[05-Feb-2025 18:02:21 UTC] PHP Warning:  require_once(ABSPATHwp-admin/includes/class-wp-privacy-requests-table.php): failed to open stream: No such file or directory in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-export-requests-list-table.php on line 11
[05-Feb-2025 18:02:21 UTC] PHP Fatal error:  require_once(): Failed opening required 'ABSPATHwp-admin/includes/class-wp-privacy-requests-table.php' (include_path='.:/opt/cpanel/ea-php74/root/usr/share/pear') in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-export-requests-list-table.php on line 11
[05-Feb-2025 18:02:22 UTC] PHP Warning:  Use of undefined constant ABSPATH - assumed 'ABSPATH' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-removal-requests-list-table.php on line 11
[05-Feb-2025 18:02:22 UTC] PHP Warning:  require_once(ABSPATHwp-admin/includes/class-wp-privacy-requests-table.php): failed to open stream: No such file or directory in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-removal-requests-list-table.php on line 11
[05-Feb-2025 18:02:22 UTC] PHP Fatal error:  require_once(): Failed opening required 'ABSPATHwp-admin/includes/class-wp-privacy-requests-table.php' (include_path='.:/opt/cpanel/ea-php74/root/usr/share/pear') in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-removal-requests-list-table.php on line 11
[05-Feb-2025 18:02:24 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-requests-table.php:10
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-requests-table.php on line 10
[05-Feb-2025 18:02:26 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-terms-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-terms-list-table.php on line 17
[05-Feb-2025 18:02:33 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Themes_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-theme-install-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-theme-install-list-table.php on line 17
[05-Feb-2025 18:02:34 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-themes-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-themes-list-table.php on line 17
[05-Feb-2025 18:02:36 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function _deprecated_file() in /home/nandedex/public_html/wp-admin/includes/class-wp-upgrader-skins.php:11
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-upgrader-skins.php on line 11
[05-Feb-2025 18:02:37 UTC] PHP Warning:  Use of undefined constant ABSPATH - assumed 'ABSPATH' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/class-wp-upgrader.php on line 13
[05-Feb-2025 18:02:37 UTC] PHP Warning:  require_once(ABSPATHwp-admin/includes/class-wp-upgrader-skin.php): failed to open stream: No such file or directory in /home/nandedex/public_html/wp-admin/includes/class-wp-upgrader.php on line 13
[05-Feb-2025 18:02:37 UTC] PHP Fatal error:  require_once(): Failed opening required 'ABSPATHwp-admin/includes/class-wp-upgrader-skin.php' (include_path='.:/opt/cpanel/ea-php74/root/usr/share/pear') in /home/nandedex/public_html/wp-admin/includes/class-wp-upgrader.php on line 13
[10-Feb-2025 16:48:55 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function add_action() in /home/nandedex/public_html/wp-admin/includes/admin-filters.php:11
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin-filters.php on line 11
[10-Feb-2025 16:48:55 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
[10-Feb-2025 20:45:03 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function add_action() in /home/nandedex/public_html/wp-admin/includes/admin-filters.php:11
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin-filters.php on line 11
[10-Feb-2025 20:45:04 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
[13-Feb-2025 03:58:16 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function add_action() in /home/nandedex/public_html/wp-admin/includes/admin-filters.php:11
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin-filters.php on line 11
[13-Feb-2025 03:58:18 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
[13-Feb-2025 03:58:28 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-automatic-upgrader-skin.php:21
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-automatic-upgrader-skin.php on line 21
[13-Feb-2025 03:58:31 UTC] PHP Fatal error:  Uncaught Error: Class 'Bulk_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-bulk-plugin-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-bulk-plugin-upgrader-skin.php on line 18
[13-Feb-2025 03:58:33 UTC] PHP Fatal error:  Uncaught Error: Class 'Bulk_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-bulk-theme-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-bulk-theme-upgrader-skin.php on line 18
[13-Feb-2025 03:58:35 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-bulk-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-bulk-upgrader-skin.php on line 18
[13-Feb-2025 03:58:36 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader' not found in /home/nandedex/public_html/wp-admin/includes/class-core-upgrader.php:25
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-core-upgrader.php on line 25
[13-Feb-2025 03:58:45 UTC] PHP Fatal error:  Uncaught Error: Class 'ftp_base' not found in /home/nandedex/public_html/wp-admin/includes/class-ftp-pure.php:28
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-ftp-pure.php on line 28
[13-Feb-2025 03:58:46 UTC] PHP Fatal error:  Uncaught Error: Class 'ftp_base' not found in /home/nandedex/public_html/wp-admin/includes/class-ftp-sockets.php:28
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-ftp-sockets.php on line 28
[13-Feb-2025 03:58:51 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-language-pack-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-language-pack-upgrader-skin.php on line 18
[13-Feb-2025 03:58:55 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader' not found in /home/nandedex/public_html/wp-admin/includes/class-language-pack-upgrader.php:19
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-language-pack-upgrader.php on line 19
[13-Feb-2025 03:59:02 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-plugin-installer-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-plugin-installer-skin.php on line 18
[13-Feb-2025 03:59:05 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-plugin-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-plugin-upgrader-skin.php on line 18
[13-Feb-2025 03:59:06 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader' not found in /home/nandedex/public_html/wp-admin/includes/class-plugin-upgrader.php:21
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-plugin-upgrader.php on line 21
[13-Feb-2025 03:59:08 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-theme-installer-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-theme-installer-skin.php on line 18
[13-Feb-2025 03:59:11 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-theme-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-theme-upgrader-skin.php on line 18
[13-Feb-2025 03:59:12 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader' not found in /home/nandedex/public_html/wp-admin/includes/class-theme-upgrader.php:21
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-theme-upgrader.php on line 21
[13-Feb-2025 03:59:15 UTC] PHP Fatal error:  Uncaught Error: Class 'Walker' not found in /home/nandedex/public_html/wp-admin/includes/class-walker-category-checklist.php:19
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-walker-category-checklist.php on line 19
[13-Feb-2025 03:59:17 UTC] PHP Fatal error:  Uncaught Error: Class 'Walker_Nav_Menu' not found in /home/nandedex/public_html/wp-admin/includes/class-walker-nav-menu-checklist.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-walker-nav-menu-checklist.php on line 16
[13-Feb-2025 03:59:19 UTC] PHP Fatal error:  Uncaught Error: Class 'Walker_Nav_Menu' not found in /home/nandedex/public_html/wp-admin/includes/class-walker-nav-menu-edit.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-walker-nav-menu-edit.php on line 17
[13-Feb-2025 03:59:21 UTC] PHP Fatal error:  Uncaught Error: Class 'Automatic_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-ajax-upgrader-skin.php:19
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-ajax-upgrader-skin.php on line 19
[13-Feb-2025 03:59:23 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-application-passwords-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-application-passwords-list-table.php on line 17
[13-Feb-2025 03:59:27 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-comments-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-comments-list-table.php on line 17
[13-Feb-2025 03:59:36 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Filesystem_Base' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-direct.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-direct.php on line 16
[13-Feb-2025 03:59:38 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Filesystem_Base' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ftpext.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ftpext.php on line 16
[13-Feb-2025 03:59:40 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Filesystem_Base' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ftpsockets.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ftpsockets.php on line 16
[13-Feb-2025 03:59:43 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Filesystem_Base' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ssh2.php:36
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ssh2.php on line 36
[13-Feb-2025 03:59:50 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-links-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-links-list-table.php on line 17
[13-Feb-2025 03:59:52 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-list-table-compat.php:15
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-list-table-compat.php on line 15
[13-Feb-2025 03:59:56 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-media-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-media-list-table.php on line 17
[13-Feb-2025 03:59:57 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-sites-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-sites-list-table.php on line 17
[13-Feb-2025 03:59:59 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-themes-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-themes-list-table.php on line 17
[13-Feb-2025 04:00:03 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-users-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-users-list-table.php on line 17
[13-Feb-2025 04:00:05 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-plugin-install-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-plugin-install-list-table.php on line 17
[13-Feb-2025 04:00:07 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-plugins-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-plugins-list-table.php on line 17
[13-Feb-2025 04:00:09 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Comments_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-post-comments-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-post-comments-list-table.php on line 17
[13-Feb-2025 04:00:11 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-posts-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-posts-list-table.php on line 17
[13-Feb-2025 04:00:13 UTC] PHP Warning:  Use of undefined constant ABSPATH - assumed 'ABSPATH' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-export-requests-list-table.php on line 11
[13-Feb-2025 04:00:13 UTC] PHP Warning:  require_once(ABSPATHwp-admin/includes/class-wp-privacy-requests-table.php): failed to open stream: No such file or directory in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-export-requests-list-table.php on line 11
[13-Feb-2025 04:00:13 UTC] PHP Fatal error:  require_once(): Failed opening required 'ABSPATHwp-admin/includes/class-wp-privacy-requests-table.php' (include_path='.:/opt/cpanel/ea-php74/root/usr/share/pear') in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-export-requests-list-table.php on line 11
[13-Feb-2025 04:00:17 UTC] PHP Warning:  Use of undefined constant ABSPATH - assumed 'ABSPATH' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-removal-requests-list-table.php on line 11
[13-Feb-2025 04:00:17 UTC] PHP Warning:  require_once(ABSPATHwp-admin/includes/class-wp-privacy-requests-table.php): failed to open stream: No such file or directory in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-removal-requests-list-table.php on line 11
[13-Feb-2025 04:00:17 UTC] PHP Fatal error:  require_once(): Failed opening required 'ABSPATHwp-admin/includes/class-wp-privacy-requests-table.php' (include_path='.:/opt/cpanel/ea-php74/root/usr/share/pear') in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-removal-requests-list-table.php on line 11
[13-Feb-2025 04:00:22 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-requests-table.php:10
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-requests-table.php on line 10
[13-Feb-2025 04:00:32 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-terms-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-terms-list-table.php on line 17
[13-Feb-2025 04:00:35 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Themes_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-theme-install-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-theme-install-list-table.php on line 17
[13-Feb-2025 04:00:37 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-themes-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-themes-list-table.php on line 17
[13-Feb-2025 04:00:41 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function _deprecated_file() in /home/nandedex/public_html/wp-admin/includes/class-wp-upgrader-skins.php:11
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-upgrader-skins.php on line 11
[13-Feb-2025 04:00:44 UTC] PHP Warning:  Use of undefined constant ABSPATH - assumed 'ABSPATH' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/class-wp-upgrader.php on line 13
[13-Feb-2025 04:00:44 UTC] PHP Warning:  require_once(ABSPATHwp-admin/includes/class-wp-upgrader-skin.php): failed to open stream: No such file or directory in /home/nandedex/public_html/wp-admin/includes/class-wp-upgrader.php on line 13
[13-Feb-2025 04:00:44 UTC] PHP Fatal error:  require_once(): Failed opening required 'ABSPATHwp-admin/includes/class-wp-upgrader-skin.php' (include_path='.:/opt/cpanel/ea-php74/root/usr/share/pear') in /home/nandedex/public_html/wp-admin/includes/class-wp-upgrader.php on line 13
[13-Feb-2025 04:00:48 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-users-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-users-list-table.php on line 17
[13-Feb-2025 04:00:54 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function __() in /home/nandedex/public_html/wp-admin/includes/continents-cities.php:12
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/continents-cities.php on line 12
[13-Feb-2025 04:01:01 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Privacy_Data_Export_Requests_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/deprecated.php:1535
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/deprecated.php on line 1535
[13-Feb-2025 04:01:07 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function __() in /home/nandedex/public_html/wp-admin/includes/edit-tag-messages.php:14
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/edit-tag-messages.php on line 14
[13-Feb-2025 04:01:12 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function __() in /home/nandedex/public_html/wp-admin/includes/file.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/file.php on line 16
[13-Feb-2025 04:01:31 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function is_network_admin() in /home/nandedex/public_html/wp-admin/includes/menu.php:9
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/menu.php on line 9
[13-Feb-2025 04:01:36 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function add_filter() in /home/nandedex/public_html/wp-admin/includes/ms-admin-filters.php:11
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/ms-admin-filters.php on line 11
[13-Feb-2025 04:01:47 UTC] PHP Warning:  Use of undefined constant ABSPATH - assumed 'ABSPATH' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/nav-menu.php on line 11
[13-Feb-2025 04:01:47 UTC] PHP Warning:  require_once(ABSPATHwp-admin/includes/class-walker-nav-menu-edit.php): failed to open stream: No such file or directory in /home/nandedex/public_html/wp-admin/includes/nav-menu.php on line 11
[13-Feb-2025 04:01:47 UTC] PHP Fatal error:  require_once(): Failed opening required 'ABSPATHwp-admin/includes/class-walker-nav-menu-edit.php' (include_path='.:/opt/cpanel/ea-php74/root/usr/share/pear') in /home/nandedex/public_html/wp-admin/includes/nav-menu.php on line 11
[13-Feb-2025 04:02:14 UTC] PHP Fatal error:  Uncaught Error: Call to a member function get_charset_collate() on null in /home/nandedex/public_html/wp-admin/includes/schema.php:23
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/schema.php on line 23
[13-Feb-2025 04:02:27 UTC] PHP Warning:  Use of undefined constant ABSPATH - assumed 'ABSPATH' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/template.php on line 12
[13-Feb-2025 04:02:27 UTC] PHP Warning:  require_once(ABSPATHwp-admin/includes/class-walker-category-checklist.php): failed to open stream: No such file or directory in /home/nandedex/public_html/wp-admin/includes/template.php on line 12
[13-Feb-2025 04:02:27 UTC] PHP Fatal error:  require_once(): Failed opening required 'ABSPATHwp-admin/includes/class-walker-category-checklist.php' (include_path='.:/opt/cpanel/ea-php74/root/usr/share/pear') in /home/nandedex/public_html/wp-admin/includes/template.php on line 12
[13-Feb-2025 04:02:48 UTC] PHP Warning:  Use of undefined constant WP_CONTENT_DIR - assumed 'WP_CONTENT_DIR' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/upgrade.php on line 12
[13-Feb-2025 04:02:48 UTC] PHP Warning:  Use of undefined constant ABSPATH - assumed 'ABSPATH' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/upgrade.php on line 17
[13-Feb-2025 04:02:48 UTC] PHP Warning:  require_once(ABSPATHwp-admin/includes/admin.php): failed to open stream: No such file or directory in /home/nandedex/public_html/wp-admin/includes/upgrade.php on line 17
[13-Feb-2025 04:02:48 UTC] PHP Fatal error:  require_once(): Failed opening required 'ABSPATHwp-admin/includes/admin.php' (include_path='.:/opt/cpanel/ea-php74/root/usr/share/pear') in /home/nandedex/public_html/wp-admin/includes/upgrade.php on line 17
[13-Feb-2025 09:26:22 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function add_action() in /home/nandedex/public_html/wp-admin/includes/admin-filters.php:11
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin-filters.php on line 11
[13-Feb-2025 09:26:25 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
[14-Mar-2025 15:29:18 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function add_action() in /home/nandedex/public_html/wp-admin/includes/admin-filters.php:11
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin-filters.php on line 11
[14-Mar-2025 15:29:19 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
[14-Mar-2025 15:29:22 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-automatic-upgrader-skin.php:21
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-automatic-upgrader-skin.php on line 21
[14-Mar-2025 15:29:23 UTC] PHP Fatal error:  Uncaught Error: Class 'Bulk_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-bulk-plugin-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-bulk-plugin-upgrader-skin.php on line 18
[14-Mar-2025 15:29:25 UTC] PHP Fatal error:  Uncaught Error: Class 'Bulk_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-bulk-theme-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-bulk-theme-upgrader-skin.php on line 18
[14-Mar-2025 15:29:26 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-bulk-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-bulk-upgrader-skin.php on line 18
[14-Mar-2025 15:29:27 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader' not found in /home/nandedex/public_html/wp-admin/includes/class-core-upgrader.php:25
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-core-upgrader.php on line 25
[14-Mar-2025 15:29:30 UTC] PHP Fatal error:  Uncaught Error: Class 'ftp_base' not found in /home/nandedex/public_html/wp-admin/includes/class-ftp-pure.php:28
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-ftp-pure.php on line 28
[14-Mar-2025 15:29:31 UTC] PHP Fatal error:  Uncaught Error: Class 'ftp_base' not found in /home/nandedex/public_html/wp-admin/includes/class-ftp-sockets.php:28
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-ftp-sockets.php on line 28
[14-Mar-2025 15:29:33 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-language-pack-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-language-pack-upgrader-skin.php on line 18
[14-Mar-2025 15:29:34 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader' not found in /home/nandedex/public_html/wp-admin/includes/class-language-pack-upgrader.php:19
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-language-pack-upgrader.php on line 19
[14-Mar-2025 15:29:39 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-plugin-installer-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-plugin-installer-skin.php on line 18
[14-Mar-2025 15:29:41 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-plugin-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-plugin-upgrader-skin.php on line 18
[14-Mar-2025 15:29:43 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader' not found in /home/nandedex/public_html/wp-admin/includes/class-plugin-upgrader.php:21
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-plugin-upgrader.php on line 21
[14-Mar-2025 15:29:44 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-theme-installer-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-theme-installer-skin.php on line 18
[14-Mar-2025 15:29:45 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-theme-upgrader-skin.php:18
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-theme-upgrader-skin.php on line 18
[14-Mar-2025 15:29:47 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Upgrader' not found in /home/nandedex/public_html/wp-admin/includes/class-theme-upgrader.php:21
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-theme-upgrader.php on line 21
[14-Mar-2025 15:29:48 UTC] PHP Fatal error:  Uncaught Error: Class 'Walker' not found in /home/nandedex/public_html/wp-admin/includes/class-walker-category-checklist.php:19
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-walker-category-checklist.php on line 19
[14-Mar-2025 15:29:50 UTC] PHP Fatal error:  Uncaught Error: Class 'Walker_Nav_Menu' not found in /home/nandedex/public_html/wp-admin/includes/class-walker-nav-menu-checklist.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-walker-nav-menu-checklist.php on line 16
[14-Mar-2025 15:29:51 UTC] PHP Fatal error:  Uncaught Error: Class 'Walker_Nav_Menu' not found in /home/nandedex/public_html/wp-admin/includes/class-walker-nav-menu-edit.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-walker-nav-menu-edit.php on line 17
[14-Mar-2025 15:29:54 UTC] PHP Fatal error:  Uncaught Error: Class 'Automatic_Upgrader_Skin' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-ajax-upgrader-skin.php:19
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-ajax-upgrader-skin.php on line 19
[14-Mar-2025 15:29:55 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-application-passwords-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-application-passwords-list-table.php on line 17
[14-Mar-2025 15:29:58 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-comments-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-comments-list-table.php on line 17
[14-Mar-2025 15:30:01 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Filesystem_Base' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-direct.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-direct.php on line 16
[14-Mar-2025 15:30:03 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Filesystem_Base' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ftpext.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ftpext.php on line 16
[14-Mar-2025 15:30:05 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Filesystem_Base' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ftpsockets.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ftpsockets.php on line 16
[14-Mar-2025 15:30:07 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Filesystem_Base' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ssh2.php:36
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-filesystem-ssh2.php on line 36
[14-Mar-2025 15:30:10 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-links-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-links-list-table.php on line 17
[14-Mar-2025 15:30:12 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-list-table-compat.php:15
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-list-table-compat.php on line 15
[14-Mar-2025 15:30:13 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-media-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-media-list-table.php on line 17
[14-Mar-2025 15:30:15 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-sites-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-sites-list-table.php on line 17
[14-Mar-2025 15:30:17 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-themes-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-themes-list-table.php on line 17
[14-Mar-2025 15:30:18 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-users-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-ms-users-list-table.php on line 17
[14-Mar-2025 15:30:19 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-plugin-install-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-plugin-install-list-table.php on line 17
[14-Mar-2025 15:30:21 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-plugins-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-plugins-list-table.php on line 17
[14-Mar-2025 15:30:23 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Comments_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-post-comments-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-post-comments-list-table.php on line 17
[14-Mar-2025 15:30:24 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-posts-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-posts-list-table.php on line 17
[14-Mar-2025 15:30:25 UTC] PHP Warning:  Use of undefined constant ABSPATH - assumed 'ABSPATH' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-export-requests-list-table.php on line 11
[14-Mar-2025 15:30:25 UTC] PHP Warning:  require_once(ABSPATHwp-admin/includes/class-wp-privacy-requests-table.php): failed to open stream: No such file or directory in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-export-requests-list-table.php on line 11
[14-Mar-2025 15:30:25 UTC] PHP Fatal error:  require_once(): Failed opening required 'ABSPATHwp-admin/includes/class-wp-privacy-requests-table.php' (include_path='.:/opt/cpanel/ea-php74/root/usr/share/pear') in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-export-requests-list-table.php on line 11
[14-Mar-2025 15:30:26 UTC] PHP Warning:  Use of undefined constant ABSPATH - assumed 'ABSPATH' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-removal-requests-list-table.php on line 11
[14-Mar-2025 15:30:26 UTC] PHP Warning:  require_once(ABSPATHwp-admin/includes/class-wp-privacy-requests-table.php): failed to open stream: No such file or directory in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-removal-requests-list-table.php on line 11
[14-Mar-2025 15:30:26 UTC] PHP Fatal error:  require_once(): Failed opening required 'ABSPATHwp-admin/includes/class-wp-privacy-requests-table.php' (include_path='.:/opt/cpanel/ea-php74/root/usr/share/pear') in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-data-removal-requests-list-table.php on line 11
[14-Mar-2025 15:30:28 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-requests-table.php:10
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-privacy-requests-table.php on line 10
[14-Mar-2025 15:30:33 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-terms-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-terms-list-table.php on line 17
[14-Mar-2025 15:30:34 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Themes_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-theme-install-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-theme-install-list-table.php on line 17
[14-Mar-2025 15:30:35 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-themes-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-themes-list-table.php on line 17
[14-Mar-2025 15:30:41 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function _deprecated_file() in /home/nandedex/public_html/wp-admin/includes/class-wp-upgrader-skins.php:11
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-upgrader-skins.php on line 11
[14-Mar-2025 15:30:42 UTC] PHP Warning:  Use of undefined constant ABSPATH - assumed 'ABSPATH' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/class-wp-upgrader.php on line 13
[14-Mar-2025 15:30:42 UTC] PHP Warning:  require_once(ABSPATHwp-admin/includes/class-wp-upgrader-skin.php): failed to open stream: No such file or directory in /home/nandedex/public_html/wp-admin/includes/class-wp-upgrader.php on line 13
[14-Mar-2025 15:30:42 UTC] PHP Fatal error:  require_once(): Failed opening required 'ABSPATHwp-admin/includes/class-wp-upgrader-skin.php' (include_path='.:/opt/cpanel/ea-php74/root/usr/share/pear') in /home/nandedex/public_html/wp-admin/includes/class-wp-upgrader.php on line 13
[14-Mar-2025 15:30:44 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/class-wp-users-list-table.php:17
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/class-wp-users-list-table.php on line 17
[14-Mar-2025 15:30:47 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function __() in /home/nandedex/public_html/wp-admin/includes/continents-cities.php:12
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/continents-cities.php on line 12
[14-Mar-2025 15:30:50 UTC] PHP Fatal error:  Uncaught Error: Class 'WP_Privacy_Data_Export_Requests_List_Table' not found in /home/nandedex/public_html/wp-admin/includes/deprecated.php:1535
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/deprecated.php on line 1535
[14-Mar-2025 15:30:51 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function __() in /home/nandedex/public_html/wp-admin/includes/edit-tag-messages.php:14
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/edit-tag-messages.php on line 14
[14-Mar-2025 15:30:53 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function __() in /home/nandedex/public_html/wp-admin/includes/file.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/file.php on line 16
[14-Mar-2025 15:30:57 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function is_network_admin() in /home/nandedex/public_html/wp-admin/includes/menu.php:9
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/menu.php on line 9
[14-Mar-2025 15:31:01 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function add_filter() in /home/nandedex/public_html/wp-admin/includes/ms-admin-filters.php:11
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/ms-admin-filters.php on line 11
[14-Mar-2025 15:31:04 UTC] PHP Warning:  Use of undefined constant ABSPATH - assumed 'ABSPATH' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/nav-menu.php on line 11
[14-Mar-2025 15:31:04 UTC] PHP Warning:  require_once(ABSPATHwp-admin/includes/class-walker-nav-menu-edit.php): failed to open stream: No such file or directory in /home/nandedex/public_html/wp-admin/includes/nav-menu.php on line 11
[14-Mar-2025 15:31:04 UTC] PHP Fatal error:  require_once(): Failed opening required 'ABSPATHwp-admin/includes/class-walker-nav-menu-edit.php' (include_path='.:/opt/cpanel/ea-php74/root/usr/share/pear') in /home/nandedex/public_html/wp-admin/includes/nav-menu.php on line 11
[14-Mar-2025 15:31:15 UTC] PHP Fatal error:  Uncaught Error: Call to a member function get_charset_collate() on null in /home/nandedex/public_html/wp-admin/includes/schema.php:23
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/schema.php on line 23
[14-Mar-2025 15:31:18 UTC] PHP Warning:  Use of undefined constant ABSPATH - assumed 'ABSPATH' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/template.php on line 12
[14-Mar-2025 15:31:18 UTC] PHP Warning:  require_once(ABSPATHwp-admin/includes/class-walker-category-checklist.php): failed to open stream: No such file or directory in /home/nandedex/public_html/wp-admin/includes/template.php on line 12
[14-Mar-2025 15:31:18 UTC] PHP Fatal error:  require_once(): Failed opening required 'ABSPATHwp-admin/includes/class-walker-category-checklist.php' (include_path='.:/opt/cpanel/ea-php74/root/usr/share/pear') in /home/nandedex/public_html/wp-admin/includes/template.php on line 12
[14-Mar-2025 15:31:23 UTC] PHP Warning:  Use of undefined constant WP_CONTENT_DIR - assumed 'WP_CONTENT_DIR' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/upgrade.php on line 12
[14-Mar-2025 15:31:23 UTC] PHP Warning:  Use of undefined constant ABSPATH - assumed 'ABSPATH' (this will throw an Error in a future version of PHP) in /home/nandedex/public_html/wp-admin/includes/upgrade.php on line 17
[14-Mar-2025 15:31:23 UTC] PHP Warning:  require_once(ABSPATHwp-admin/includes/admin.php): failed to open stream: No such file or directory in /home/nandedex/public_html/wp-admin/includes/upgrade.php on line 17
[14-Mar-2025 15:31:23 UTC] PHP Fatal error:  require_once(): Failed opening required 'ABSPATHwp-admin/includes/admin.php' (include_path='.:/opt/cpanel/ea-php74/root/usr/share/pear') in /home/nandedex/public_html/wp-admin/includes/upgrade.php on line 17
[23-Jul-2025 18:53:00 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
[26-Jul-2025 01:00:59 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
[30-Jul-2025 16:52:37 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
[03-Aug-2025 23:40:33 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
[09-Aug-2025 14:05:42 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function is_network_admin() in /home/nandedex/public_html/wp-admin/includes/menu.php:9
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/menu.php on line 9
[16-Aug-2025 19:14:06 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
[17-Aug-2025 01:54:56 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
[10-Oct-2025 11:44:02 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
[12-Oct-2025 11:07:28 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
[19-Oct-2025 17:25:26 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
[27-Oct-2025 22:15:50 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
[26-Nov-2025 04:18:54 UTC] PHP Fatal error:  Uncaught Error: Call to undefined function get_locale() in /home/nandedex/public_html/wp-admin/includes/admin.php:16
Stack trace:
#0 {main}
  thrown in /home/nandedex/public_html/wp-admin/includes/admin.php on line 16
update-core.php000064400000211513151212616040007466 0ustar00<?php
/**
 * WordPress core upgrade functionality.
 *
 * Note: Newly introduced functions and methods cannot be used here.
 * All functions must be present in the previous version being upgraded from
 * as this file is used there too.
 *
 * @package WordPress
 * @subpackage Administration
 * @since 2.7.0
 */

/**
 * Stores files to be deleted.
 *
 * Bundled theme files should not be included in this list.
 *
 * @since 2.7.0
 *
 * @global string[] $_old_files
 * @var string[]
 * @name $_old_files
 */
global $_old_files;

$_old_files = array(
	// 2.0
	'wp-admin/import-b2.php',
	'wp-admin/import-blogger.php',
	'wp-admin/import-greymatter.php',
	'wp-admin/import-livejournal.php',
	'wp-admin/import-mt.php',
	'wp-admin/import-rss.php',
	'wp-admin/import-textpattern.php',
	'wp-admin/quicktags.js',
	'wp-images/fade-butt.png',
	'wp-images/get-firefox.png',
	'wp-images/header-shadow.png',
	'wp-images/smilies',
	'wp-images/wp-small.png',
	'wp-images/wpminilogo.png',
	'wp.php',
	// 2.1
	'wp-admin/edit-form-ajax-cat.php',
	'wp-admin/execute-pings.php',
	'wp-admin/inline-uploading.php',
	'wp-admin/link-categories.php',
	'wp-admin/list-manipulation.js',
	'wp-admin/list-manipulation.php',
	'wp-includes/comment-functions.php',
	'wp-includes/feed-functions.php',
	'wp-includes/functions-compat.php',
	'wp-includes/functions-formatting.php',
	'wp-includes/functions-post.php',
	'wp-includes/js/dbx-key.js',
	'wp-includes/links.php',
	'wp-includes/pluggable-functions.php',
	'wp-includes/template-functions-author.php',
	'wp-includes/template-functions-category.php',
	'wp-includes/template-functions-general.php',
	'wp-includes/template-functions-links.php',
	'wp-includes/template-functions-post.php',
	'wp-includes/wp-l10n.php',
	// 2.2
	'wp-admin/cat-js.php',
	'wp-includes/js/autosave-js.php',
	'wp-includes/js/list-manipulation-js.php',
	'wp-includes/js/wp-ajax-js.php',
	// 2.3
	'wp-admin/admin-db.php',
	'wp-admin/cat.js',
	'wp-admin/categories.js',
	'wp-admin/custom-fields.js',
	'wp-admin/dbx-admin-key.js',
	'wp-admin/edit-comments.js',
	'wp-admin/install-rtl.css',
	'wp-admin/install.css',
	'wp-admin/upgrade-schema.php',
	'wp-admin/upload-functions.php',
	'wp-admin/upload-rtl.css',
	'wp-admin/upload.css',
	'wp-admin/upload.js',
	'wp-admin/users.js',
	'wp-admin/widgets-rtl.css',
	'wp-admin/widgets.css',
	'wp-admin/xfn.js',
	'wp-includes/js/tinymce/license.html',
	// 2.5
	'wp-admin/css/upload.css',
	'wp-admin/images/box-bg-left.gif',
	'wp-admin/images/box-bg-right.gif',
	'wp-admin/images/box-bg.gif',
	'wp-admin/images/box-butt-left.gif',
	'wp-admin/images/box-butt-right.gif',
	'wp-admin/images/box-butt.gif',
	'wp-admin/images/box-head-left.gif',
	'wp-admin/images/box-head-right.gif',
	'wp-admin/images/box-head.gif',
	'wp-admin/images/heading-bg.gif',
	'wp-admin/images/login-bkg-bottom.gif',
	'wp-admin/images/login-bkg-tile.gif',
	'wp-admin/images/notice.gif',
	'wp-admin/images/toggle.gif',
	'wp-admin/includes/upload.php',
	'wp-admin/js/dbx-admin-key.js',
	'wp-admin/js/link-cat.js',
	'wp-admin/profile-update.php',
	'wp-admin/templates.php',
	'wp-includes/js/dbx.js',
	'wp-includes/js/fat.js',
	'wp-includes/js/list-manipulation.js',
	'wp-includes/js/tinymce/langs/en.js',
	'wp-includes/js/tinymce/plugins/directionality/images',
	'wp-includes/js/tinymce/plugins/directionality/langs',
	'wp-includes/js/tinymce/plugins/paste/images',
	'wp-includes/js/tinymce/plugins/paste/jscripts',
	'wp-includes/js/tinymce/plugins/paste/langs',
	'wp-includes/js/tinymce/plugins/wordpress/images',
	'wp-includes/js/tinymce/plugins/wordpress/langs',
	'wp-includes/js/tinymce/plugins/wordpress/wordpress.css',
	'wp-includes/js/tinymce/plugins/wphelp',
	// 2.5.1
	'wp-includes/js/tinymce/tiny_mce_gzip.php',
	// 2.6
	'wp-admin/bookmarklet.php',
	'wp-includes/js/jquery/jquery.dimensions.min.js',
	'wp-includes/js/tinymce/plugins/wordpress/popups.css',
	'wp-includes/js/wp-ajax.js',
	// 2.7
	'wp-admin/css/press-this-ie-rtl.css',
	'wp-admin/css/press-this-ie.css',
	'wp-admin/css/upload-rtl.css',
	'wp-admin/edit-form.php',
	'wp-admin/images/comment-pill.gif',
	'wp-admin/images/comment-stalk-classic.gif',
	'wp-admin/images/comment-stalk-fresh.gif',
	'wp-admin/images/comment-stalk-rtl.gif',
	'wp-admin/images/del.png',
	'wp-admin/images/gear.png',
	'wp-admin/images/media-button-gallery.gif',
	'wp-admin/images/media-buttons.gif',
	'wp-admin/images/postbox-bg.gif',
	'wp-admin/images/tab.png',
	'wp-admin/images/tail.gif',
	'wp-admin/js/forms.js',
	'wp-admin/js/upload.js',
	'wp-admin/link-import.php',
	'wp-includes/images/audio.png',
	'wp-includes/images/css.png',
	'wp-includes/images/default.png',
	'wp-includes/images/doc.png',
	'wp-includes/images/exe.png',
	'wp-includes/images/html.png',
	'wp-includes/images/js.png',
	'wp-includes/images/pdf.png',
	'wp-includes/images/swf.png',
	'wp-includes/images/tar.png',
	'wp-includes/images/text.png',
	'wp-includes/images/video.png',
	'wp-includes/images/zip.png',
	'wp-includes/js/tinymce/tiny_mce_config.php',
	'wp-includes/js/tinymce/tiny_mce_ext.js',
	// 2.8
	'wp-admin/js/users.js',
	'wp-includes/js/swfupload/swfupload_f9.swf',
	'wp-includes/js/tinymce/plugins/autosave',
	'wp-includes/js/tinymce/plugins/paste/css',
	'wp-includes/js/tinymce/utils/mclayer.js',
	'wp-includes/js/tinymce/wordpress.css',
	// 2.9
	'wp-admin/js/page.dev.js',
	'wp-admin/js/page.js',
	'wp-admin/js/set-post-thumbnail-handler.dev.js',
	'wp-admin/js/set-post-thumbnail-handler.js',
	'wp-admin/js/slug.dev.js',
	'wp-admin/js/slug.js',
	'wp-includes/gettext.php',
	'wp-includes/js/tinymce/plugins/wordpress/js',
	'wp-includes/streams.php',
	// MU
	'README.txt',
	'htaccess.dist',
	'index-install.php',
	'wp-admin/css/mu-rtl.css',
	'wp-admin/css/mu.css',
	'wp-admin/images/site-admin.png',
	'wp-admin/includes/mu.php',
	'wp-admin/wpmu-admin.php',
	'wp-admin/wpmu-blogs.php',
	'wp-admin/wpmu-edit.php',
	'wp-admin/wpmu-options.php',
	'wp-admin/wpmu-themes.php',
	'wp-admin/wpmu-upgrade-site.php',
	'wp-admin/wpmu-users.php',
	'wp-includes/images/wordpress-mu.png',
	'wp-includes/wpmu-default-filters.php',
	'wp-includes/wpmu-functions.php',
	'wpmu-settings.php',
	// 3.0
	'wp-admin/categories.php',
	'wp-admin/edit-category-form.php',
	'wp-admin/edit-page-form.php',
	'wp-admin/edit-pages.php',
	'wp-admin/images/admin-header-footer.png',
	'wp-admin/images/browse-happy.gif',
	'wp-admin/images/ico-add.png',
	'wp-admin/images/ico-close.png',
	'wp-admin/images/ico-edit.png',
	'wp-admin/images/ico-viewpage.png',
	'wp-admin/images/fav-top.png',
	'wp-admin/images/screen-options-left.gif',
	'wp-admin/images/wp-logo-vs.gif',
	'wp-admin/images/wp-logo.gif',
	'wp-admin/import',
	'wp-admin/js/wp-gears.dev.js',
	'wp-admin/js/wp-gears.js',
	'wp-admin/options-misc.php',
	'wp-admin/page-new.php',
	'wp-admin/page.php',
	'wp-admin/rtl.css',
	'wp-admin/rtl.dev.css',
	'wp-admin/update-links.php',
	'wp-admin/wp-admin.css',
	'wp-admin/wp-admin.dev.css',
	'wp-includes/js/codepress',
	'wp-includes/js/jquery/autocomplete.dev.js',
	'wp-includes/js/jquery/autocomplete.js',
	'wp-includes/js/jquery/interface.js',
	// Following file added back in 5.1, see #45645.
	//'wp-includes/js/tinymce/wp-tinymce.js',
	// 3.1
	'wp-admin/edit-attachment-rows.php',
	'wp-admin/edit-link-categories.php',
	'wp-admin/edit-link-category-form.php',
	'wp-admin/edit-post-rows.php',
	'wp-admin/images/button-grad-active-vs.png',
	'wp-admin/images/button-grad-vs.png',
	'wp-admin/images/fav-arrow-vs-rtl.gif',
	'wp-admin/images/fav-arrow-vs.gif',
	'wp-admin/images/fav-top-vs.gif',
	'wp-admin/images/list-vs.png',
	'wp-admin/images/screen-options-right-up.gif',
	'wp-admin/images/screen-options-right.gif',
	'wp-admin/images/visit-site-button-grad-vs.gif',
	'wp-admin/images/visit-site-button-grad.gif',
	'wp-admin/link-category.php',
	'wp-admin/sidebar.php',
	'wp-includes/classes.php',
	'wp-includes/js/tinymce/blank.htm',
	'wp-includes/js/tinymce/plugins/media/img',
	'wp-includes/js/tinymce/plugins/safari',
	// 3.2
	'wp-admin/images/logo-login.gif',
	'wp-admin/images/star.gif',
	'wp-admin/js/list-table.dev.js',
	'wp-admin/js/list-table.js',
	'wp-includes/default-embeds.php',
	// 3.3
	'wp-admin/css/colors-classic-rtl.css',
	'wp-admin/css/colors-classic-rtl.dev.css',
	'wp-admin/css/colors-fresh-rtl.css',
	'wp-admin/css/colors-fresh-rtl.dev.css',
	'wp-admin/css/dashboard-rtl.dev.css',
	'wp-admin/css/dashboard.dev.css',
	'wp-admin/css/global-rtl.css',
	'wp-admin/css/global-rtl.dev.css',
	'wp-admin/css/global.css',
	'wp-admin/css/global.dev.css',
	'wp-admin/css/install-rtl.dev.css',
	'wp-admin/css/login-rtl.dev.css',
	'wp-admin/css/login.dev.css',
	'wp-admin/css/ms.css',
	'wp-admin/css/ms.dev.css',
	'wp-admin/css/nav-menu-rtl.css',
	'wp-admin/css/nav-menu-rtl.dev.css',
	'wp-admin/css/nav-menu.css',
	'wp-admin/css/nav-menu.dev.css',
	'wp-admin/css/plugin-install-rtl.css',
	'wp-admin/css/plugin-install-rtl.dev.css',
	'wp-admin/css/plugin-install.css',
	'wp-admin/css/plugin-install.dev.css',
	'wp-admin/css/press-this-rtl.dev.css',
	'wp-admin/css/press-this.dev.css',
	'wp-admin/css/theme-editor-rtl.css',
	'wp-admin/css/theme-editor-rtl.dev.css',
	'wp-admin/css/theme-editor.css',
	'wp-admin/css/theme-editor.dev.css',
	'wp-admin/css/theme-install-rtl.css',
	'wp-admin/css/theme-install-rtl.dev.css',
	'wp-admin/css/theme-install.css',
	'wp-admin/css/theme-install.dev.css',
	'wp-admin/css/widgets-rtl.dev.css',
	'wp-admin/css/widgets.dev.css',
	'wp-admin/includes/internal-linking.php',
	'wp-includes/images/admin-bar-sprite-rtl.png',
	'wp-includes/js/jquery/ui.button.js',
	'wp-includes/js/jquery/ui.core.js',
	'wp-includes/js/jquery/ui.dialog.js',
	'wp-includes/js/jquery/ui.draggable.js',
	'wp-includes/js/jquery/ui.droppable.js',
	'wp-includes/js/jquery/ui.mouse.js',
	'wp-includes/js/jquery/ui.position.js',
	'wp-includes/js/jquery/ui.resizable.js',
	'wp-includes/js/jquery/ui.selectable.js',
	'wp-includes/js/jquery/ui.sortable.js',
	'wp-includes/js/jquery/ui.tabs.js',
	'wp-includes/js/jquery/ui.widget.js',
	'wp-includes/js/l10n.dev.js',
	'wp-includes/js/l10n.js',
	'wp-includes/js/tinymce/plugins/wplink/css',
	'wp-includes/js/tinymce/plugins/wplink/img',
	'wp-includes/js/tinymce/plugins/wplink/js',
	// Don't delete, yet: 'wp-rss.php',
	// Don't delete, yet: 'wp-rdf.php',
	// Don't delete, yet: 'wp-rss2.php',
	// Don't delete, yet: 'wp-commentsrss2.php',
	// Don't delete, yet: 'wp-atom.php',
	// Don't delete, yet: 'wp-feed.php',
	// 3.4
	'wp-admin/images/gray-star.png',
	'wp-admin/images/logo-login.png',
	'wp-admin/images/star.png',
	'wp-admin/index-extra.php',
	'wp-admin/network/index-extra.php',
	'wp-admin/user/index-extra.php',
	'wp-includes/css/editor-buttons.css',
	'wp-includes/css/editor-buttons.dev.css',
	'wp-includes/js/tinymce/plugins/paste/blank.htm',
	'wp-includes/js/tinymce/plugins/wordpress/css',
	'wp-includes/js/tinymce/plugins/wordpress/editor_plugin.dev.js',
	'wp-includes/js/tinymce/plugins/wpdialogs/editor_plugin.dev.js',
	'wp-includes/js/tinymce/plugins/wpeditimage/editor_plugin.dev.js',
	'wp-includes/js/tinymce/plugins/wpgallery/editor_plugin.dev.js',
	'wp-includes/js/tinymce/plugins/wplink/editor_plugin.dev.js',
	// Don't delete, yet: 'wp-pass.php',
	// Don't delete, yet: 'wp-register.php',
	// 3.5
	'wp-admin/gears-manifest.php',
	'wp-admin/includes/manifest.php',
	'wp-admin/images/archive-link.png',
	'wp-admin/images/blue-grad.png',
	'wp-admin/images/button-grad-active.png',
	'wp-admin/images/button-grad.png',
	'wp-admin/images/ed-bg-vs.gif',
	'wp-admin/images/ed-bg.gif',
	'wp-admin/images/fade-butt.png',
	'wp-admin/images/fav-arrow-rtl.gif',
	'wp-admin/images/fav-arrow.gif',
	'wp-admin/images/fav-vs.png',
	'wp-admin/images/fav.png',
	'wp-admin/images/gray-grad.png',
	'wp-admin/images/loading-publish.gif',
	'wp-admin/images/logo-ghost.png',
	'wp-admin/images/logo.gif',
	'wp-admin/images/menu-arrow-frame-rtl.png',
	'wp-admin/images/menu-arrow-frame.png',
	'wp-admin/images/menu-arrows.gif',
	'wp-admin/images/menu-bits-rtl-vs.gif',
	'wp-admin/images/menu-bits-rtl.gif',
	'wp-admin/images/menu-bits-vs.gif',
	'wp-admin/images/menu-bits.gif',
	'wp-admin/images/menu-dark-rtl-vs.gif',
	'wp-admin/images/menu-dark-rtl.gif',
	'wp-admin/images/menu-dark-vs.gif',
	'wp-admin/images/menu-dark.gif',
	'wp-admin/images/required.gif',
	'wp-admin/images/screen-options-toggle-vs.gif',
	'wp-admin/images/screen-options-toggle.gif',
	'wp-admin/images/toggle-arrow-rtl.gif',
	'wp-admin/images/toggle-arrow.gif',
	'wp-admin/images/upload-classic.png',
	'wp-admin/images/upload-fresh.png',
	'wp-admin/images/white-grad-active.png',
	'wp-admin/images/white-grad.png',
	'wp-admin/images/widgets-arrow-vs.gif',
	'wp-admin/images/widgets-arrow.gif',
	'wp-admin/images/wpspin_dark.gif',
	'wp-includes/images/upload.png',
	'wp-includes/js/prototype.js',
	'wp-includes/js/scriptaculous',
	'wp-admin/css/wp-admin-rtl.dev.css',
	'wp-admin/css/wp-admin.dev.css',
	'wp-admin/css/media-rtl.dev.css',
	'wp-admin/css/media.dev.css',
	'wp-admin/css/colors-classic.dev.css',
	'wp-admin/css/customize-controls-rtl.dev.css',
	'wp-admin/css/customize-controls.dev.css',
	'wp-admin/css/ie-rtl.dev.css',
	'wp-admin/css/ie.dev.css',
	'wp-admin/css/install.dev.css',
	'wp-admin/css/colors-fresh.dev.css',
	'wp-includes/js/customize-base.dev.js',
	'wp-includes/js/json2.dev.js',
	'wp-includes/js/comment-reply.dev.js',
	'wp-includes/js/customize-preview.dev.js',
	'wp-includes/js/wplink.dev.js',
	'wp-includes/js/tw-sack.dev.js',
	'wp-includes/js/wp-list-revisions.dev.js',
	'wp-includes/js/autosave.dev.js',
	'wp-includes/js/admin-bar.dev.js',
	'wp-includes/js/quicktags.dev.js',
	'wp-includes/js/wp-ajax-response.dev.js',
	'wp-includes/js/wp-pointer.dev.js',
	'wp-includes/js/hoverIntent.dev.js',
	'wp-includes/js/colorpicker.dev.js',
	'wp-includes/js/wp-lists.dev.js',
	'wp-includes/js/customize-loader.dev.js',
	'wp-includes/js/jquery/jquery.table-hotkeys.dev.js',
	'wp-includes/js/jquery/jquery.color.dev.js',
	'wp-includes/js/jquery/jquery.color.js',
	'wp-includes/js/jquery/jquery.hotkeys.dev.js',
	'wp-includes/js/jquery/jquery.form.dev.js',
	'wp-includes/js/jquery/suggest.dev.js',
	'wp-admin/js/xfn.dev.js',
	'wp-admin/js/set-post-thumbnail.dev.js',
	'wp-admin/js/comment.dev.js',
	'wp-admin/js/theme.dev.js',
	'wp-admin/js/cat.dev.js',
	'wp-admin/js/password-strength-meter.dev.js',
	'wp-admin/js/user-profile.dev.js',
	'wp-admin/js/theme-preview.dev.js',
	'wp-admin/js/post.dev.js',
	'wp-admin/js/media-upload.dev.js',
	'wp-admin/js/word-count.dev.js',
	'wp-admin/js/plugin-install.dev.js',
	'wp-admin/js/edit-comments.dev.js',
	'wp-admin/js/media-gallery.dev.js',
	'wp-admin/js/custom-fields.dev.js',
	'wp-admin/js/custom-background.dev.js',
	'wp-admin/js/common.dev.js',
	'wp-admin/js/inline-edit-tax.dev.js',
	'wp-admin/js/gallery.dev.js',
	'wp-admin/js/utils.dev.js',
	'wp-admin/js/widgets.dev.js',
	'wp-admin/js/wp-fullscreen.dev.js',
	'wp-admin/js/nav-menu.dev.js',
	'wp-admin/js/dashboard.dev.js',
	'wp-admin/js/link.dev.js',
	'wp-admin/js/user-suggest.dev.js',
	'wp-admin/js/postbox.dev.js',
	'wp-admin/js/tags.dev.js',
	'wp-admin/js/image-edit.dev.js',
	'wp-admin/js/media.dev.js',
	'wp-admin/js/customize-controls.dev.js',
	'wp-admin/js/inline-edit-post.dev.js',
	'wp-admin/js/categories.dev.js',
	'wp-admin/js/editor.dev.js',
	'wp-includes/js/plupload/handlers.dev.js',
	'wp-includes/js/plupload/wp-plupload.dev.js',
	'wp-includes/js/swfupload/handlers.dev.js',
	'wp-includes/js/jcrop/jquery.Jcrop.dev.js',
	'wp-includes/js/jcrop/jquery.Jcrop.js',
	'wp-includes/js/jcrop/jquery.Jcrop.css',
	'wp-includes/js/imgareaselect/jquery.imgareaselect.dev.js',
	'wp-includes/css/wp-pointer.dev.css',
	'wp-includes/css/editor.dev.css',
	'wp-includes/css/jquery-ui-dialog.dev.css',
	'wp-includes/css/admin-bar-rtl.dev.css',
	'wp-includes/css/admin-bar.dev.css',
	'wp-includes/js/jquery/ui/jquery.effects.clip.min.js',
	'wp-includes/js/jquery/ui/jquery.effects.scale.min.js',
	'wp-includes/js/jquery/ui/jquery.effects.blind.min.js',
	'wp-includes/js/jquery/ui/jquery.effects.core.min.js',
	'wp-includes/js/jquery/ui/jquery.effects.shake.min.js',
	'wp-includes/js/jquery/ui/jquery.effects.fade.min.js',
	'wp-includes/js/jquery/ui/jquery.effects.explode.min.js',
	'wp-includes/js/jquery/ui/jquery.effects.slide.min.js',
	'wp-includes/js/jquery/ui/jquery.effects.drop.min.js',
	'wp-includes/js/jquery/ui/jquery.effects.highlight.min.js',
	'wp-includes/js/jquery/ui/jquery.effects.bounce.min.js',
	'wp-includes/js/jquery/ui/jquery.effects.pulsate.min.js',
	'wp-includes/js/jquery/ui/jquery.effects.transfer.min.js',
	'wp-includes/js/jquery/ui/jquery.effects.fold.min.js',
	'wp-admin/js/utils.js',
	// Added back in 5.3 [45448], see #43895.
	// 'wp-admin/options-privacy.php',
	'wp-app.php',
	'wp-includes/class-wp-atom-server.php',
	// 3.5.2
	'wp-includes/js/swfupload/swfupload-all.js',
	// 3.6
	'wp-admin/js/revisions-js.php',
	'wp-admin/images/screenshots',
	'wp-admin/js/categories.js',
	'wp-admin/js/categories.min.js',
	'wp-admin/js/custom-fields.js',
	'wp-admin/js/custom-fields.min.js',
	// 3.7
	'wp-admin/js/cat.js',
	'wp-admin/js/cat.min.js',
	// 3.8
	'wp-includes/js/thickbox/tb-close-2x.png',
	'wp-includes/js/thickbox/tb-close.png',
	'wp-includes/images/wpmini-blue-2x.png',
	'wp-includes/images/wpmini-blue.png',
	'wp-admin/css/colors-fresh.css',
	'wp-admin/css/colors-classic.css',
	'wp-admin/css/colors-fresh.min.css',
	'wp-admin/css/colors-classic.min.css',
	'wp-admin/js/about.min.js',
	'wp-admin/js/about.js',
	'wp-admin/images/arrows-dark-vs-2x.png',
	'wp-admin/images/wp-logo-vs.png',
	'wp-admin/images/arrows-dark-vs.png',
	'wp-admin/images/wp-logo.png',
	'wp-admin/images/arrows-pr.png',
	'wp-admin/images/arrows-dark.png',
	'wp-admin/images/press-this.png',
	'wp-admin/images/press-this-2x.png',
	'wp-admin/images/arrows-vs-2x.png',
	'wp-admin/images/welcome-icons.png',
	'wp-admin/images/wp-logo-2x.png',
	'wp-admin/images/stars-rtl-2x.png',
	'wp-admin/images/arrows-dark-2x.png',
	'wp-admin/images/arrows-pr-2x.png',
	'wp-admin/images/menu-shadow-rtl.png',
	'wp-admin/images/arrows-vs.png',
	'wp-admin/images/about-search-2x.png',
	'wp-admin/images/bubble_bg-rtl-2x.gif',
	'wp-admin/images/wp-badge-2x.png',
	'wp-admin/images/wordpress-logo-2x.png',
	'wp-admin/images/bubble_bg-rtl.gif',
	'wp-admin/images/wp-badge.png',
	'wp-admin/images/menu-shadow.png',
	'wp-admin/images/about-globe-2x.png',
	'wp-admin/images/welcome-icons-2x.png',
	'wp-admin/images/stars-rtl.png',
	'wp-admin/images/wp-logo-vs-2x.png',
	'wp-admin/images/about-updates-2x.png',
	// 3.9
	'wp-admin/css/colors.css',
	'wp-admin/css/colors.min.css',
	'wp-admin/css/colors-rtl.css',
	'wp-admin/css/colors-rtl.min.css',
	// Following files added back in 4.5, see #36083.
	// 'wp-admin/css/media-rtl.min.css',
	// 'wp-admin/css/media.min.css',
	// 'wp-admin/css/farbtastic-rtl.min.css',
	'wp-admin/images/lock-2x.png',
	'wp-admin/images/lock.png',
	'wp-admin/js/theme-preview.js',
	'wp-admin/js/theme-install.min.js',
	'wp-admin/js/theme-install.js',
	'wp-admin/js/theme-preview.min.js',
	'wp-includes/js/plupload/plupload.html4.js',
	'wp-includes/js/plupload/plupload.html5.js',
	'wp-includes/js/plupload/changelog.txt',
	'wp-includes/js/plupload/plupload.silverlight.js',
	'wp-includes/js/plupload/plupload.flash.js',
	// Added back in 4.9 [41328], see #41755.
	// 'wp-includes/js/plupload/plupload.js',
	'wp-includes/js/tinymce/plugins/spellchecker',
	'wp-includes/js/tinymce/plugins/inlinepopups',
	'wp-includes/js/tinymce/plugins/media/js',
	'wp-includes/js/tinymce/plugins/media/css',
	'wp-includes/js/tinymce/plugins/wordpress/img',
	'wp-includes/js/tinymce/plugins/wpdialogs/js',
	'wp-includes/js/tinymce/plugins/wpeditimage/img',
	'wp-includes/js/tinymce/plugins/wpeditimage/js',
	'wp-includes/js/tinymce/plugins/wpeditimage/css',
	'wp-includes/js/tinymce/plugins/wpgallery/img',
	'wp-includes/js/tinymce/plugins/paste/js',
	'wp-includes/js/tinymce/themes/advanced',
	'wp-includes/js/tinymce/tiny_mce.js',
	'wp-includes/js/tinymce/mark_loaded_src.js',
	'wp-includes/js/tinymce/wp-tinymce-schema.js',
	'wp-includes/js/tinymce/plugins/media/editor_plugin.js',
	'wp-includes/js/tinymce/plugins/media/editor_plugin_src.js',
	'wp-includes/js/tinymce/plugins/media/media.htm',
	'wp-includes/js/tinymce/plugins/wpview/editor_plugin_src.js',
	'wp-includes/js/tinymce/plugins/wpview/editor_plugin.js',
	'wp-includes/js/tinymce/plugins/directionality/editor_plugin.js',
	'wp-includes/js/tinymce/plugins/directionality/editor_plugin_src.js',
	'wp-includes/js/tinymce/plugins/wordpress/editor_plugin.js',
	'wp-includes/js/tinymce/plugins/wordpress/editor_plugin_src.js',
	'wp-includes/js/tinymce/plugins/wpdialogs/editor_plugin_src.js',
	'wp-includes/js/tinymce/plugins/wpdialogs/editor_plugin.js',
	'wp-includes/js/tinymce/plugins/wpeditimage/editimage.html',
	'wp-includes/js/tinymce/plugins/wpeditimage/editor_plugin.js',
	'wp-includes/js/tinymce/plugins/wpeditimage/editor_plugin_src.js',
	'wp-includes/js/tinymce/plugins/fullscreen/editor_plugin_src.js',
	'wp-includes/js/tinymce/plugins/fullscreen/fullscreen.htm',
	'wp-includes/js/tinymce/plugins/fullscreen/editor_plugin.js',
	'wp-includes/js/tinymce/plugins/wplink/editor_plugin_src.js',
	'wp-includes/js/tinymce/plugins/wplink/editor_plugin.js',
	'wp-includes/js/tinymce/plugins/wpgallery/editor_plugin_src.js',
	'wp-includes/js/tinymce/plugins/wpgallery/editor_plugin.js',
	'wp-includes/js/tinymce/plugins/tabfocus/editor_plugin.js',
	'wp-includes/js/tinymce/plugins/tabfocus/editor_plugin_src.js',
	'wp-includes/js/tinymce/plugins/paste/editor_plugin.js',
	'wp-includes/js/tinymce/plugins/paste/pasteword.htm',
	'wp-includes/js/tinymce/plugins/paste/editor_plugin_src.js',
	'wp-includes/js/tinymce/plugins/paste/pastetext.htm',
	'wp-includes/js/tinymce/langs/wp-langs.php',
	// 4.1
	'wp-includes/js/jquery/ui/jquery.ui.accordion.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.autocomplete.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.button.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.core.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.datepicker.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.dialog.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.draggable.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.droppable.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.effect-blind.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.effect-bounce.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.effect-clip.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.effect-drop.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.effect-explode.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.effect-fade.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.effect-fold.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.effect-highlight.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.effect-pulsate.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.effect-scale.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.effect-shake.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.effect-slide.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.effect-transfer.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.effect.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.menu.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.mouse.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.position.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.progressbar.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.resizable.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.selectable.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.slider.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.sortable.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.spinner.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.tabs.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.tooltip.min.js',
	'wp-includes/js/jquery/ui/jquery.ui.widget.min.js',
	'wp-includes/js/tinymce/skins/wordpress/images/dashicon-no-alt.png',
	// 4.3
	'wp-admin/js/wp-fullscreen.js',
	'wp-admin/js/wp-fullscreen.min.js',
	'wp-includes/js/tinymce/wp-mce-help.php',
	'wp-includes/js/tinymce/plugins/wpfullscreen',
	// 4.5
	'wp-includes/theme-compat/comments-popup.php',
	// 4.6
	'wp-admin/includes/class-wp-automatic-upgrader.php', // Wrong file name, see #37628.
	// 4.8
	'wp-includes/js/tinymce/plugins/wpembed',
	'wp-includes/js/tinymce/plugins/media/moxieplayer.swf',
	'wp-includes/js/tinymce/skins/lightgray/fonts/readme.md',
	'wp-includes/js/tinymce/skins/lightgray/fonts/tinymce-small.json',
	'wp-includes/js/tinymce/skins/lightgray/fonts/tinymce.json',
	'wp-includes/js/tinymce/skins/lightgray/skin.ie7.min.css',
	// 4.9
	'wp-admin/css/press-this-editor-rtl.css',
	'wp-admin/css/press-this-editor-rtl.min.css',
	'wp-admin/css/press-this-editor.css',
	'wp-admin/css/press-this-editor.min.css',
	'wp-admin/css/press-this-rtl.css',
	'wp-admin/css/press-this-rtl.min.css',
	'wp-admin/css/press-this.css',
	'wp-admin/css/press-this.min.css',
	'wp-admin/includes/class-wp-press-this.php',
	'wp-admin/js/bookmarklet.js',
	'wp-admin/js/bookmarklet.min.js',
	'wp-admin/js/press-this.js',
	'wp-admin/js/press-this.min.js',
	'wp-includes/js/mediaelement/background.png',
	'wp-includes/js/mediaelement/bigplay.png',
	'wp-includes/js/mediaelement/bigplay.svg',
	'wp-includes/js/mediaelement/controls.png',
	'wp-includes/js/mediaelement/controls.svg',
	'wp-includes/js/mediaelement/flashmediaelement.swf',
	'wp-includes/js/mediaelement/froogaloop.min.js',
	'wp-includes/js/mediaelement/jumpforward.png',
	'wp-includes/js/mediaelement/loading.gif',
	'wp-includes/js/mediaelement/silverlightmediaelement.xap',
	'wp-includes/js/mediaelement/skipback.png',
	'wp-includes/js/plupload/plupload.flash.swf',
	'wp-includes/js/plupload/plupload.full.min.js',
	'wp-includes/js/plupload/plupload.silverlight.xap',
	'wp-includes/js/swfupload/plugins',
	'wp-includes/js/swfupload/swfupload.swf',
	// 4.9.2
	'wp-includes/js/mediaelement/lang',
	'wp-includes/js/mediaelement/mediaelement-flash-audio-ogg.swf',
	'wp-includes/js/mediaelement/mediaelement-flash-audio.swf',
	'wp-includes/js/mediaelement/mediaelement-flash-video-hls.swf',
	'wp-includes/js/mediaelement/mediaelement-flash-video-mdash.swf',
	'wp-includes/js/mediaelement/mediaelement-flash-video.swf',
	'wp-includes/js/mediaelement/renderers/dailymotion.js',
	'wp-includes/js/mediaelement/renderers/dailymotion.min.js',
	'wp-includes/js/mediaelement/renderers/facebook.js',
	'wp-includes/js/mediaelement/renderers/facebook.min.js',
	'wp-includes/js/mediaelement/renderers/soundcloud.js',
	'wp-includes/js/mediaelement/renderers/soundcloud.min.js',
	'wp-includes/js/mediaelement/renderers/twitch.js',
	'wp-includes/js/mediaelement/renderers/twitch.min.js',
	// 5.0
	'wp-includes/js/codemirror/jshint.js',
	// 5.1
	'wp-includes/js/tinymce/wp-tinymce.js.gz',
	// 5.3
	'wp-includes/js/wp-a11y.js',     // Moved to: wp-includes/js/dist/a11y.js
	'wp-includes/js/wp-a11y.min.js', // Moved to: wp-includes/js/dist/a11y.min.js
	// 5.4
	'wp-admin/js/wp-fullscreen-stub.js',
	'wp-admin/js/wp-fullscreen-stub.min.js',
	// 5.5
	'wp-admin/css/ie.css',
	'wp-admin/css/ie.min.css',
	'wp-admin/css/ie-rtl.css',
	'wp-admin/css/ie-rtl.min.css',
	// 5.6
	'wp-includes/js/jquery/ui/position.min.js',
	'wp-includes/js/jquery/ui/widget.min.js',
	// 5.7
	'wp-includes/blocks/classic/block.json',
	// 5.8
	'wp-admin/images/freedoms.png',
	'wp-admin/images/privacy.png',
	'wp-admin/images/about-badge.svg',
	'wp-admin/images/about-color-palette.svg',
	'wp-admin/images/about-color-palette-vert.svg',
	'wp-admin/images/about-header-brushes.svg',
	'wp-includes/block-patterns/large-header.php',
	'wp-includes/block-patterns/heading-paragraph.php',
	'wp-includes/block-patterns/quote.php',
	'wp-includes/block-patterns/text-three-columns-buttons.php',
	'wp-includes/block-patterns/two-buttons.php',
	'wp-includes/block-patterns/two-images.php',
	'wp-includes/block-patterns/three-buttons.php',
	'wp-includes/block-patterns/text-two-columns-with-images.php',
	'wp-includes/block-patterns/text-two-columns.php',
	'wp-includes/block-patterns/large-header-button.php',
	'wp-includes/blocks/subhead',
	'wp-includes/css/dist/editor/editor-styles.css',
	'wp-includes/css/dist/editor/editor-styles.min.css',
	'wp-includes/css/dist/editor/editor-styles-rtl.css',
	'wp-includes/css/dist/editor/editor-styles-rtl.min.css',
	// 5.9
	'wp-includes/blocks/heading/editor.css',
	'wp-includes/blocks/heading/editor.min.css',
	'wp-includes/blocks/heading/editor-rtl.css',
	'wp-includes/blocks/heading/editor-rtl.min.css',
	'wp-includes/blocks/query-title/editor.css',
	'wp-includes/blocks/query-title/editor.min.css',
	'wp-includes/blocks/query-title/editor-rtl.css',
	'wp-includes/blocks/query-title/editor-rtl.min.css',
	/*
	 * Restored in WordPress 6.7
	 *
	 * 'wp-includes/blocks/tag-cloud/editor.css',
	 * 'wp-includes/blocks/tag-cloud/editor.min.css',
	 * 'wp-includes/blocks/tag-cloud/editor-rtl.css',
	 * 'wp-includes/blocks/tag-cloud/editor-rtl.min.css',
	 */
	// 6.1
	'wp-includes/blocks/post-comments.php',
	'wp-includes/blocks/post-comments',
	'wp-includes/blocks/comments-query-loop',
	// 6.3
	'wp-includes/images/wlw',
	'wp-includes/wlwmanifest.xml',
	'wp-includes/random_compat',
	// 6.4
	'wp-includes/navigation-fallback.php',
	'wp-includes/blocks/navigation/view-modal.min.js',
	'wp-includes/blocks/navigation/view-modal.js',
	// 6.5
	'wp-includes/ID3/license.commercial.txt',
	'wp-includes/blocks/query/style-rtl.min.css',
	'wp-includes/blocks/query/style.min.css',
	'wp-includes/blocks/query/style-rtl.css',
	'wp-includes/blocks/query/style.css',
	'wp-admin/images/about-header-privacy.svg',
	'wp-admin/images/about-header-about.svg',
	'wp-admin/images/about-header-credits.svg',
	'wp-admin/images/about-header-freedoms.svg',
	'wp-admin/images/about-header-contribute.svg',
	'wp-admin/images/about-header-background.svg',
	// 6.6
	'wp-includes/blocks/block/editor.css',
	'wp-includes/blocks/block/editor.min.css',
	'wp-includes/blocks/block/editor-rtl.css',
	'wp-includes/blocks/block/editor-rtl.min.css',
	/*
	 * 6.7
	 *
	 * WordPress 6.7 included a SimplePie upgrade that included a major
	 * refactoring of the file structure and library. The old files are
	 * split in to two sections to account for this: files and directories.
	 *
	 * See https://core.trac.wordpress.org/changeset/59141
	 */
	// 6.7 - files
	'wp-includes/js/dist/interactivity-router.asset.php',
	'wp-includes/js/dist/interactivity-router.js',
	'wp-includes/js/dist/interactivity-router.min.js',
	'wp-includes/js/dist/interactivity-router.min.asset.php',
	'wp-includes/js/dist/interactivity.js',
	'wp-includes/js/dist/interactivity.min.js',
	'wp-includes/js/dist/vendor/react-dom.min.js.LICENSE.txt',
	'wp-includes/js/dist/vendor/react.min.js.LICENSE.txt',
	'wp-includes/js/dist/vendor/wp-polyfill-importmap.js',
	'wp-includes/js/dist/vendor/wp-polyfill-importmap.min.js',
	'wp-includes/sodium_compat/src/Core/Base64/Common.php',
	'wp-includes/SimplePie/Author.php',
	'wp-includes/SimplePie/Cache.php',
	'wp-includes/SimplePie/Caption.php',
	'wp-includes/SimplePie/Category.php',
	'wp-includes/SimplePie/Copyright.php',
	'wp-includes/SimplePie/Core.php',
	'wp-includes/SimplePie/Credit.php',
	'wp-includes/SimplePie/Enclosure.php',
	'wp-includes/SimplePie/Exception.php',
	'wp-includes/SimplePie/File.php',
	'wp-includes/SimplePie/gzdecode.php',
	'wp-includes/SimplePie/IRI.php',
	'wp-includes/SimplePie/Item.php',
	'wp-includes/SimplePie/Locator.php',
	'wp-includes/SimplePie/Misc.php',
	'wp-includes/SimplePie/Parser.php',
	'wp-includes/SimplePie/Rating.php',
	'wp-includes/SimplePie/Registry.php',
	'wp-includes/SimplePie/Restriction.php',
	'wp-includes/SimplePie/Sanitize.php',
	'wp-includes/SimplePie/Source.php',
	// 6.7 - directories
	'wp-includes/SimplePie/Cache/',
	'wp-includes/SimplePie/Content/',
	'wp-includes/SimplePie/Decode/',
	'wp-includes/SimplePie/HTTP/',
	'wp-includes/SimplePie/Net/',
	'wp-includes/SimplePie/Parse/',
	'wp-includes/SimplePie/XML/',
	// 6.8
	'wp-includes/blocks/post-content/editor.css',
	'wp-includes/blocks/post-content/editor.min.css',
	'wp-includes/blocks/post-content/editor-rtl.css',
	'wp-includes/blocks/post-content/editor-rtl.min.css',
	'wp-includes/blocks/post-template/editor.css',
	'wp-includes/blocks/post-template/editor.min.css',
	'wp-includes/blocks/post-template/editor-rtl.css',
	'wp-includes/blocks/post-template/editor-rtl.min.css',
	'wp-includes/js/dist/undo-manager.js',
	'wp-includes/js/dist/undo-manager.min.js',
	'wp-includes/js/dist/fields.min.js',
	'wp-includes/js/dist/fields.js',
	// 6.9
	'wp-includes/blocks/post-author/editor.css',
	'wp-includes/blocks/post-author/editor.min.css',
	'wp-includes/blocks/post-author/editor-rtl.css',
	'wp-includes/blocks/post-author/editor-rtl.min.css',
	'wp-includes/SimplePie/src/Decode',
);

/**
 * Stores Requests files to be preloaded and deleted.
 *
 * For classes/interfaces, use the class/interface name
 * as the array key.
 *
 * All other files/directories should not have a key.
 *
 * @since 6.2.0
 *
 * @global string[] $_old_requests_files
 * @var string[]
 * @name $_old_requests_files
 */
global $_old_requests_files;

$_old_requests_files = array(
	// Interfaces.
	'Requests_Auth'                              => 'wp-includes/Requests/Auth.php',
	'Requests_Hooker'                            => 'wp-includes/Requests/Hooker.php',
	'Requests_Proxy'                             => 'wp-includes/Requests/Proxy.php',
	'Requests_Transport'                         => 'wp-includes/Requests/Transport.php',

	// Classes.
	'Requests_Auth_Basic'                        => 'wp-includes/Requests/Auth/Basic.php',
	'Requests_Cookie_Jar'                        => 'wp-includes/Requests/Cookie/Jar.php',
	'Requests_Exception_HTTP'                    => 'wp-includes/Requests/Exception/HTTP.php',
	'Requests_Exception_Transport'               => 'wp-includes/Requests/Exception/Transport.php',
	'Requests_Exception_HTTP_304'                => 'wp-includes/Requests/Exception/HTTP/304.php',
	'Requests_Exception_HTTP_305'                => 'wp-includes/Requests/Exception/HTTP/305.php',
	'Requests_Exception_HTTP_306'                => 'wp-includes/Requests/Exception/HTTP/306.php',
	'Requests_Exception_HTTP_400'                => 'wp-includes/Requests/Exception/HTTP/400.php',
	'Requests_Exception_HTTP_401'                => 'wp-includes/Requests/Exception/HTTP/401.php',
	'Requests_Exception_HTTP_402'                => 'wp-includes/Requests/Exception/HTTP/402.php',
	'Requests_Exception_HTTP_403'                => 'wp-includes/Requests/Exception/HTTP/403.php',
	'Requests_Exception_HTTP_404'                => 'wp-includes/Requests/Exception/HTTP/404.php',
	'Requests_Exception_HTTP_405'                => 'wp-includes/Requests/Exception/HTTP/405.php',
	'Requests_Exception_HTTP_406'                => 'wp-includes/Requests/Exception/HTTP/406.php',
	'Requests_Exception_HTTP_407'                => 'wp-includes/Requests/Exception/HTTP/407.php',
	'Requests_Exception_HTTP_408'                => 'wp-includes/Requests/Exception/HTTP/408.php',
	'Requests_Exception_HTTP_409'                => 'wp-includes/Requests/Exception/HTTP/409.php',
	'Requests_Exception_HTTP_410'                => 'wp-includes/Requests/Exception/HTTP/410.php',
	'Requests_Exception_HTTP_411'                => 'wp-includes/Requests/Exception/HTTP/411.php',
	'Requests_Exception_HTTP_412'                => 'wp-includes/Requests/Exception/HTTP/412.php',
	'Requests_Exception_HTTP_413'                => 'wp-includes/Requests/Exception/HTTP/413.php',
	'Requests_Exception_HTTP_414'                => 'wp-includes/Requests/Exception/HTTP/414.php',
	'Requests_Exception_HTTP_415'                => 'wp-includes/Requests/Exception/HTTP/415.php',
	'Requests_Exception_HTTP_416'                => 'wp-includes/Requests/Exception/HTTP/416.php',
	'Requests_Exception_HTTP_417'                => 'wp-includes/Requests/Exception/HTTP/417.php',
	'Requests_Exception_HTTP_418'                => 'wp-includes/Requests/Exception/HTTP/418.php',
	'Requests_Exception_HTTP_428'                => 'wp-includes/Requests/Exception/HTTP/428.php',
	'Requests_Exception_HTTP_429'                => 'wp-includes/Requests/Exception/HTTP/429.php',
	'Requests_Exception_HTTP_431'                => 'wp-includes/Requests/Exception/HTTP/431.php',
	'Requests_Exception_HTTP_500'                => 'wp-includes/Requests/Exception/HTTP/500.php',
	'Requests_Exception_HTTP_501'                => 'wp-includes/Requests/Exception/HTTP/501.php',
	'Requests_Exception_HTTP_502'                => 'wp-includes/Requests/Exception/HTTP/502.php',
	'Requests_Exception_HTTP_503'                => 'wp-includes/Requests/Exception/HTTP/503.php',
	'Requests_Exception_HTTP_504'                => 'wp-includes/Requests/Exception/HTTP/504.php',
	'Requests_Exception_HTTP_505'                => 'wp-includes/Requests/Exception/HTTP/505.php',
	'Requests_Exception_HTTP_511'                => 'wp-includes/Requests/Exception/HTTP/511.php',
	'Requests_Exception_HTTP_Unknown'            => 'wp-includes/Requests/Exception/HTTP/Unknown.php',
	'Requests_Exception_Transport_cURL'          => 'wp-includes/Requests/Exception/Transport/cURL.php',
	'Requests_Proxy_HTTP'                        => 'wp-includes/Requests/Proxy/HTTP.php',
	'Requests_Response_Headers'                  => 'wp-includes/Requests/Response/Headers.php',
	'Requests_Transport_cURL'                    => 'wp-includes/Requests/Transport/cURL.php',
	'Requests_Transport_fsockopen'               => 'wp-includes/Requests/Transport/fsockopen.php',
	'Requests_Utility_CaseInsensitiveDictionary' => 'wp-includes/Requests/Utility/CaseInsensitiveDictionary.php',
	'Requests_Utility_FilteredIterator'          => 'wp-includes/Requests/Utility/FilteredIterator.php',
	'Requests_Cookie'                            => 'wp-includes/Requests/Cookie.php',
	'Requests_Exception'                         => 'wp-includes/Requests/Exception.php',
	'Requests_Hooks'                             => 'wp-includes/Requests/Hooks.php',
	'Requests_IDNAEncoder'                       => 'wp-includes/Requests/IDNAEncoder.php',
	'Requests_IPv6'                              => 'wp-includes/Requests/IPv6.php',
	'Requests_IRI'                               => 'wp-includes/Requests/IRI.php',
	'Requests_Response'                          => 'wp-includes/Requests/Response.php',
	'Requests_SSL'                               => 'wp-includes/Requests/SSL.php',
	'Requests_Session'                           => 'wp-includes/Requests/Session.php',

	// Directories.
	'wp-includes/Requests/Auth/',
	'wp-includes/Requests/Cookie/',
	'wp-includes/Requests/Exception/HTTP/',
	'wp-includes/Requests/Exception/Transport/',
	'wp-includes/Requests/Exception/',
	'wp-includes/Requests/Proxy/',
	'wp-includes/Requests/Response/',
	'wp-includes/Requests/Transport/',
	'wp-includes/Requests/Utility/',
);

/**
 * Stores new files in wp-content to copy
 *
 * The contents of this array indicate any new bundled plugins/themes which
 * should be installed with the WordPress Upgrade. These items will not be
 * re-installed in future upgrades, this behavior is controlled by the
 * introduced version present here being older than the current installed version.
 *
 * The content of this array should follow the following format:
 * Filename (relative to wp-content) => Introduced version
 * Directories should be noted by suffixing it with a trailing slash (/)
 *
 * @since 3.2.0
 * @since 4.7.0 New themes were not automatically installed for 4.4-4.6 on
 *              upgrade. New themes are now installed again. To disable new
 *              themes from being installed on upgrade, explicitly define
 *              CORE_UPGRADE_SKIP_NEW_BUNDLED as true.
 * @global string[] $_new_bundled_files
 * @var string[]
 * @name $_new_bundled_files
 */
global $_new_bundled_files;

$_new_bundled_files = array(
	'plugins/akismet/'          => '2.0',
	'themes/twentyten/'         => '3.0',
	'themes/twentyeleven/'      => '3.2',
	'themes/twentytwelve/'      => '3.5',
	'themes/twentythirteen/'    => '3.6',
	'themes/twentyfourteen/'    => '3.8',
	'themes/twentyfifteen/'     => '4.1',
	'themes/twentysixteen/'     => '4.4',
	'themes/twentyseventeen/'   => '4.7',
	'themes/twentynineteen/'    => '5.0',
	'themes/twentytwenty/'      => '5.3',
	'themes/twentytwentyone/'   => '5.6',
	'themes/twentytwentytwo/'   => '5.9',
	'themes/twentytwentythree/' => '6.1',
	'themes/twentytwentyfour/'  => '6.4',
	'themes/twentytwentyfive/'  => '6.7',
);

/**
 * Upgrades the core of WordPress.
 *
 * This will create a .maintenance file at the base of the WordPress directory
 * to ensure that people can not access the website, when the files are being
 * copied to their locations.
 *
 * The files in the `$_old_files` list will be removed and the new files
 * copied from the zip file after the database is upgraded.
 *
 * The files in the `$_new_bundled_files` list will be added to the installation
 * if the version is greater than or equal to the old version being upgraded.
 *
 * The steps for the upgrader for after the new release is downloaded and
 * unzipped is:
 *
 *   1. Test unzipped location for select files to ensure that unzipped worked.
 *   2. Create the .maintenance file in current WordPress base.
 *   3. Copy new WordPress directory over old WordPress files.
 *   4. Upgrade WordPress to new version.
 *      1. Copy all files/folders other than wp-content
 *      2. Copy any language files to `WP_LANG_DIR` (which may differ from `WP_CONTENT_DIR`
 *      3. Copy any new bundled themes/plugins to their respective locations
 *   5. Delete new WordPress directory path.
 *   6. Delete .maintenance file.
 *   7. Remove old files.
 *   8. Delete 'update_core' option.
 *
 * There are several areas of failure. For instance if PHP times out before step
 * 6, then you will not be able to access any portion of your site. Also, since
 * the upgrade will not continue where it left off, you will not be able to
 * automatically remove old files and remove the 'update_core' option. This
 * isn't that bad.
 *
 * If the copy of the new WordPress over the old fails, then the worse is that
 * the new WordPress directory will remain.
 *
 * If it is assumed that every file will be copied over, including plugins and
 * themes, then if you edit the default theme, you should rename it, so that
 * your changes remain.
 *
 * @since 2.7.0
 *
 * @global WP_Filesystem_Base $wp_filesystem          WordPress filesystem subclass.
 * @global string[]           $_old_files
 * @global string[]           $_old_requests_files
 * @global string[]           $_new_bundled_files
 * @global wpdb               $wpdb                   WordPress database abstraction object.
 * @global string             $wp_version             The WordPress version string.
 *
 * @param string $from New release unzipped path.
 * @param string $to   Path to old WordPress installation.
 * @return string|WP_Error New WordPress version on success, WP_Error on failure.
 */
function update_core( $from, $to ) {
	global $wp_filesystem, $_old_files, $_old_requests_files, $_new_bundled_files, $wpdb;

	/*
	 * Give core update script an additional 300 seconds (5 minutes)
	 * to finish updating large files when running on slower servers.
	 */
	if ( function_exists( 'set_time_limit' ) ) {
		set_time_limit( 300 );
	}

	/*
	 * Merge the old Requests files and directories into the `$_old_files`.
	 * Then preload these Requests files first, before the files are deleted
	 * and replaced to ensure the code is in memory if needed.
	 */
	$_old_files = array_merge( $_old_files, array_values( $_old_requests_files ) );
	_preload_old_requests_classes_and_interfaces( $to );

	/**
	 * Filters feedback messages displayed during the core update process.
	 *
	 * The filter is first evaluated after the zip file for the latest version
	 * has been downloaded and unzipped. It is evaluated five more times during
	 * the process:
	 *
	 * 1. Before WordPress begins the core upgrade process.
	 * 2. Before Maintenance Mode is enabled.
	 * 3. Before WordPress begins copying over the necessary files.
	 * 4. Before Maintenance Mode is disabled.
	 * 5. Before the database is upgraded.
	 *
	 * @since 2.5.0
	 *
	 * @param string $feedback The core update feedback messages.
	 */
	apply_filters( 'update_feedback', __( 'Verifying the unpacked files&#8230;' ) );

	// Confidence check the unzipped distribution.
	$distro = '';
	$roots  = array( '/wordpress/', '/wordpress-mu/' );

	foreach ( $roots as $root ) {
		if ( $wp_filesystem->exists( $from . $root . 'readme.html' )
			&& $wp_filesystem->exists( $from . $root . 'wp-includes/version.php' )
		) {
			$distro = $root;
			break;
		}
	}

	if ( ! $distro ) {
		$wp_filesystem->delete( $from, true );

		return new WP_Error( 'insane_distro', __( 'The update could not be unpacked' ) );
	}

	/*
	 * Import $wp_version, $required_php_version, $required_php_extensions, and $required_mysql_version from the new version.
	 * DO NOT globalize any variables imported from `version-current.php` in this function.
	 *
	 * BC Note: $wp_filesystem->wp_content_dir() returned unslashed pre-2.8.
	 */
	$versions_file = trailingslashit( $wp_filesystem->wp_content_dir() ) . 'upgrade/version-current.php';

	if ( ! $wp_filesystem->copy( $from . $distro . 'wp-includes/version.php', $versions_file ) ) {
		$wp_filesystem->delete( $from, true );

		return new WP_Error(
			'copy_failed_for_version_file',
			__( 'The update cannot be installed because some files could not be copied. This is usually due to inconsistent file permissions.' ),
			'wp-includes/version.php'
		);
	}

	$wp_filesystem->chmod( $versions_file, FS_CHMOD_FILE );

	/*
	 * `wp_opcache_invalidate()` only exists in WordPress 5.5 or later,
	 * so don't run it when upgrading from older versions.
	 */
	if ( function_exists( 'wp_opcache_invalidate' ) ) {
		wp_opcache_invalidate( $versions_file );
	}

	require WP_CONTENT_DIR . '/upgrade/version-current.php';
	$wp_filesystem->delete( $versions_file );

	$php_version    = PHP_VERSION;
	$mysql_version  = $wpdb->db_version();
	$old_wp_version = $GLOBALS['wp_version']; // The version of WordPress we're updating from.
	/*
	 * Note: str_contains() is not used here, as this file is included
	 * when updating from older WordPress versions, in which case
	 * the polyfills from wp-includes/compat.php may not be available.
	 */
	$development_build = ( false !== strpos( $old_wp_version . $wp_version, '-' ) ); // A dash in the version indicates a development release.
	$php_compat        = version_compare( $php_version, $required_php_version, '>=' );

	if ( file_exists( WP_CONTENT_DIR . '/db.php' ) && empty( $wpdb->is_mysql ) ) {
		$mysql_compat = true;
	} else {
		$mysql_compat = version_compare( $mysql_version, $required_mysql_version, '>=' );
	}

	if ( ! $mysql_compat || ! $php_compat ) {
		$wp_filesystem->delete( $from, true );
	}

	$php_update_message = '';

	if ( function_exists( 'wp_get_update_php_url' ) ) {
		$php_update_message = '</p><p>' . sprintf(
			/* translators: %s: URL to Update PHP page. */
			__( '<a href="%s">Learn more about updating PHP</a>.' ),
			esc_url( wp_get_update_php_url() )
		);

		if ( function_exists( 'wp_get_update_php_annotation' ) ) {
			$annotation = wp_get_update_php_annotation();

			if ( $annotation ) {
				$php_update_message .= '</p><p><em>' . $annotation . '</em>';
			}
		}
	}

	if ( ! $mysql_compat && ! $php_compat ) {
		return new WP_Error(
			'php_mysql_not_compatible',
			sprintf(
				/* translators: 1: WordPress version number, 2: Minimum required PHP version number, 3: Minimum required MySQL version number, 4: Current PHP version number, 5: Current MySQL version number. */
				__( 'The update cannot be installed because WordPress %1$s requires PHP version %2$s or higher and MySQL version %3$s or higher. You are running PHP version %4$s and MySQL version %5$s.' ),
				$wp_version,
				$required_php_version,
				$required_mysql_version,
				$php_version,
				$mysql_version
			) . $php_update_message
		);
	} elseif ( ! $php_compat ) {
		return new WP_Error(
			'php_not_compatible',
			sprintf(
				/* translators: 1: WordPress version number, 2: Minimum required PHP version number, 3: Current PHP version number. */
				__( 'The update cannot be installed because WordPress %1$s requires PHP version %2$s or higher. You are running version %3$s.' ),
				$wp_version,
				$required_php_version,
				$php_version
			) . $php_update_message
		);
	} elseif ( ! $mysql_compat ) {
		return new WP_Error(
			'mysql_not_compatible',
			sprintf(
				/* translators: 1: WordPress version number, 2: Minimum required MySQL version number, 3: Current MySQL version number. */
				__( 'The update cannot be installed because WordPress %1$s requires MySQL version %2$s or higher. You are running version %3$s.' ),
				$wp_version,
				$required_mysql_version,
				$mysql_version
			)
		);
	}

	if ( isset( $required_php_extensions ) && is_array( $required_php_extensions ) ) {
		$missing_extensions = new WP_Error();

		foreach ( $required_php_extensions as $extension ) {
			if ( extension_loaded( $extension ) ) {
				continue;
			}

			$missing_extensions->add(
				"php_not_compatible_{$extension}",
				sprintf(
					/* translators: 1: WordPress version number, 2: The PHP extension name needed. */
					__( 'The update cannot be installed because WordPress %1$s requires the %2$s PHP extension.' ),
					$wp_version,
					$extension
				)
			);
		}

		// Add a warning when required PHP extensions are missing.
		if ( ! empty( $missing_extensions->errors ) ) {
			return $missing_extensions;
		}
	}

	/** This filter is documented in wp-admin/includes/update-core.php */
	apply_filters( 'update_feedback', __( 'Preparing to install the latest version&#8230;' ) );

	/*
	 * Don't copy wp-content, we'll deal with that below.
	 * We also copy version.php last so failed updates report their old version.
	 */
	$skip              = array( 'wp-content', 'wp-includes/version.php' );
	$check_is_writable = array();

	// Check to see which files don't really need updating - only available for 3.7 and higher.
	if ( function_exists( 'get_core_checksums' ) ) {
		// Find the local version of the working directory.
		$working_dir_local = WP_CONTENT_DIR . '/upgrade/' . basename( $from ) . $distro;

		$checksums = get_core_checksums( $wp_version, isset( $wp_local_package ) ? $wp_local_package : 'en_US' );

		if ( is_array( $checksums ) && isset( $checksums[ $wp_version ] ) ) {
			$checksums = $checksums[ $wp_version ]; // Compat code for 3.7-beta2.
		}

		if ( is_array( $checksums ) ) {
			foreach ( $checksums as $file => $checksum ) {
				/*
				 * Note: str_starts_with() is not used here, as this file is included
				 * when updating from older WordPress versions, in which case
				 * the polyfills from wp-includes/compat.php may not be available.
				 */
				if ( 'wp-content' === substr( $file, 0, 10 ) ) {
					continue;
				}

				if ( ! file_exists( ABSPATH . $file ) ) {
					continue;
				}

				if ( ! file_exists( $working_dir_local . $file ) ) {
					continue;
				}

				if ( '.' === dirname( $file )
					&& in_array( pathinfo( $file, PATHINFO_EXTENSION ), array( 'html', 'txt' ), true )
				) {
					continue;
				}

				if ( md5_file( ABSPATH . $file ) === $checksum ) {
					$skip[] = $file;
				} else {
					$check_is_writable[ $file ] = ABSPATH . $file;
				}
			}
		}
	}

	// If we're using the direct method, we can predict write failures that are due to permissions.
	if ( $check_is_writable && 'direct' === $wp_filesystem->method ) {
		$files_writable = array_filter( $check_is_writable, array( $wp_filesystem, 'is_writable' ) );

		if ( $files_writable !== $check_is_writable ) {
			$files_not_writable = array_diff_key( $check_is_writable, $files_writable );

			foreach ( $files_not_writable as $relative_file_not_writable => $file_not_writable ) {
				// If the writable check failed, chmod file to 0644 and try again, same as copy_dir().
				$wp_filesystem->chmod( $file_not_writable, FS_CHMOD_FILE );

				if ( $wp_filesystem->is_writable( $file_not_writable ) ) {
					unset( $files_not_writable[ $relative_file_not_writable ] );
				}
			}

			// Store package-relative paths (the key) of non-writable files in the WP_Error object.
			$error_data = version_compare( $old_wp_version, '3.7-beta2', '>' ) ? array_keys( $files_not_writable ) : '';

			if ( $files_not_writable ) {
				return new WP_Error(
					'files_not_writable',
					__( 'The update cannot be installed because your site is unable to copy some files. This is usually due to inconsistent file permissions.' ),
					implode( ', ', $error_data )
				);
			}
		}
	}

	/** This filter is documented in wp-admin/includes/update-core.php */
	apply_filters( 'update_feedback', __( 'Enabling Maintenance mode&#8230;' ) );

	// Create maintenance file to signal that we are upgrading.
	$maintenance_string = '<?php $upgrading = ' . time() . '; ?>';
	$maintenance_file   = $to . '.maintenance';
	$wp_filesystem->delete( $maintenance_file );
	$wp_filesystem->put_contents( $maintenance_file, $maintenance_string, FS_CHMOD_FILE );

	/** This filter is documented in wp-admin/includes/update-core.php */
	apply_filters( 'update_feedback', __( 'Copying the required files&#8230;' ) );

	// Copy new versions of WP files into place.
	$result = copy_dir( $from . $distro, $to, $skip );

	if ( is_wp_error( $result ) ) {
		$result = new WP_Error(
			$result->get_error_code(),
			$result->get_error_message(),
			substr( $result->get_error_data(), strlen( $to ) )
		);
	}

	// Since we know the core files have copied over, we can now copy the version file.
	if ( ! is_wp_error( $result ) ) {
		if ( ! $wp_filesystem->copy( $from . $distro . 'wp-includes/version.php', $to . 'wp-includes/version.php', true /* overwrite */ ) ) {
			$wp_filesystem->delete( $from, true );
			$result = new WP_Error(
				'copy_failed_for_version_file',
				__( 'The update cannot be installed because your site is unable to copy some files. This is usually due to inconsistent file permissions.' ),
				'wp-includes/version.php'
			);
		}

		$wp_filesystem->chmod( $to . 'wp-includes/version.php', FS_CHMOD_FILE );

		/*
		 * `wp_opcache_invalidate()` only exists in WordPress 5.5 or later,
		 * so don't run it when upgrading from older versions.
		 */
		if ( function_exists( 'wp_opcache_invalidate' ) ) {
			wp_opcache_invalidate( $to . 'wp-includes/version.php' );
		}
	}

	// Check to make sure everything copied correctly, ignoring the contents of wp-content.
	$skip   = array( 'wp-content' );
	$failed = array();

	if ( isset( $checksums ) && is_array( $checksums ) ) {
		foreach ( $checksums as $file => $checksum ) {
			/*
			 * Note: str_starts_with() is not used here, as this file is included
			 * when updating from older WordPress versions, in which case
			 * the polyfills from wp-includes/compat.php may not be available.
			 */
			if ( 'wp-content' === substr( $file, 0, 10 ) ) {
				continue;
			}

			if ( ! file_exists( $working_dir_local . $file ) ) {
				continue;
			}

			if ( '.' === dirname( $file )
				&& in_array( pathinfo( $file, PATHINFO_EXTENSION ), array( 'html', 'txt' ), true )
			) {
				$skip[] = $file;
				continue;
			}

			if ( file_exists( ABSPATH . $file ) && md5_file( ABSPATH . $file ) === $checksum ) {
				$skip[] = $file;
			} else {
				$failed[] = $file;
			}
		}
	}

	// Some files didn't copy properly.
	if ( ! empty( $failed ) ) {
		$total_size = 0;

		foreach ( $failed as $file ) {
			if ( file_exists( $working_dir_local . $file ) ) {
				$total_size += filesize( $working_dir_local . $file );
			}
		}

		/*
		 * If we don't have enough free space, it isn't worth trying again.
		 * Unlikely to be hit due to the check in unzip_file().
		 */
		$available_space = function_exists( 'disk_free_space' ) ? @disk_free_space( ABSPATH ) : false;

		if ( $available_space && $total_size >= $available_space ) {
			$result = new WP_Error( 'disk_full', __( 'There is not enough free disk space to complete the update.' ) );
		} else {
			$result = copy_dir( $from . $distro, $to, $skip );

			if ( is_wp_error( $result ) ) {
				$result = new WP_Error(
					$result->get_error_code() . '_retry',
					$result->get_error_message(),
					substr( $result->get_error_data(), strlen( $to ) )
				);
			}
		}
	}

	/*
	 * Custom content directory needs updating now.
	 * Copy languages.
	 */
	if ( ! is_wp_error( $result ) && $wp_filesystem->is_dir( $from . $distro . 'wp-content/languages' ) ) {
		if ( WP_LANG_DIR !== ABSPATH . WPINC . '/languages' || @is_dir( WP_LANG_DIR ) ) {
			$lang_dir = WP_LANG_DIR;
		} else {
			$lang_dir = WP_CONTENT_DIR . '/languages';
		}
		/*
		 * Note: str_starts_with() is not used here, as this file is included
		 * when updating from older WordPress versions, in which case
		 * the polyfills from wp-includes/compat.php may not be available.
		 */
		// Check if the language directory exists first.
		if ( ! @is_dir( $lang_dir ) && 0 === strpos( $lang_dir, ABSPATH ) ) {
			// If it's within the ABSPATH we can handle it here, otherwise they're out of luck.
			$wp_filesystem->mkdir( $to . str_replace( ABSPATH, '', $lang_dir ), FS_CHMOD_DIR );
			clearstatcache(); // For FTP, need to clear the stat cache.
		}

		if ( @is_dir( $lang_dir ) ) {
			$wp_lang_dir = $wp_filesystem->find_folder( $lang_dir );

			if ( $wp_lang_dir ) {
				$result = copy_dir( $from . $distro . 'wp-content/languages/', $wp_lang_dir );

				if ( is_wp_error( $result ) ) {
					$result = new WP_Error(
						$result->get_error_code() . '_languages',
						$result->get_error_message(),
						substr( $result->get_error_data(), strlen( $wp_lang_dir ) )
					);
				}
			}
		}
	}

	/** This filter is documented in wp-admin/includes/update-core.php */
	apply_filters( 'update_feedback', __( 'Disabling Maintenance mode&#8230;' ) );

	// Remove maintenance file, we're done with potential site-breaking changes.
	$wp_filesystem->delete( $maintenance_file );

	/*
	 * 3.5 -> 3.5+ - an empty twentytwelve directory was created upon upgrade to 3.5 for some users,
	 * preventing installation of Twenty Twelve.
	 */
	if ( '3.5' === $old_wp_version ) {
		if ( is_dir( WP_CONTENT_DIR . '/themes/twentytwelve' )
			&& ! file_exists( WP_CONTENT_DIR . '/themes/twentytwelve/style.css' )
		) {
			$wp_filesystem->delete( $wp_filesystem->wp_themes_dir() . 'twentytwelve/' );
		}
	}

	/*
	 * Copy new bundled plugins & themes.
	 * This gives us the ability to install new plugins & themes bundled with
	 * future versions of WordPress whilst avoiding the re-install upon upgrade issue.
	 * $development_build controls us overwriting bundled themes and plugins when a non-stable release is being updated.
	 */
	if ( ! is_wp_error( $result )
		&& ( ! defined( 'CORE_UPGRADE_SKIP_NEW_BUNDLED' ) || ! CORE_UPGRADE_SKIP_NEW_BUNDLED )
	) {
		foreach ( (array) $_new_bundled_files as $file => $introduced_version ) {
			// If a $development_build or if $introduced version is greater than what the site was previously running.
			if ( $development_build || version_compare( $introduced_version, $old_wp_version, '>' ) ) {
				$directory = ( '/' === $file[ strlen( $file ) - 1 ] );

				list( $type, $filename ) = explode( '/', $file, 2 );

				// Check to see if the bundled items exist before attempting to copy them.
				if ( ! $wp_filesystem->exists( $from . $distro . 'wp-content/' . $file ) ) {
					continue;
				}

				if ( 'plugins' === $type ) {
					$dest = $wp_filesystem->wp_plugins_dir();
				} elseif ( 'themes' === $type ) {
					// Back-compat, ::wp_themes_dir() did not return trailingslash'd pre-3.2.
					$dest = trailingslashit( $wp_filesystem->wp_themes_dir() );
				} else {
					continue;
				}

				if ( ! $directory ) {
					if ( ! $development_build && $wp_filesystem->exists( $dest . $filename ) ) {
						continue;
					}

					if ( ! $wp_filesystem->copy( $from . $distro . 'wp-content/' . $file, $dest . $filename, FS_CHMOD_FILE ) ) {
						$result = new WP_Error( "copy_failed_for_new_bundled_$type", __( 'Could not copy file.' ), $dest . $filename );
					}
				} else {
					if ( ! $development_build && $wp_filesystem->is_dir( $dest . $filename ) ) {
						continue;
					}

					$wp_filesystem->mkdir( $dest . $filename, FS_CHMOD_DIR );
					$_result = copy_dir( $from . $distro . 'wp-content/' . $file, $dest . $filename );

					/*
					 * If an error occurs partway through this final step,
					 * keep the error flowing through, but keep the process going.
					 */
					if ( is_wp_error( $_result ) ) {
						if ( ! is_wp_error( $result ) ) {
							$result = new WP_Error();
						}

						$result->add(
							$_result->get_error_code() . "_$type",
							$_result->get_error_message(),
							substr( $_result->get_error_data(), strlen( $dest ) )
						);
					}
				}
			}
		} // End foreach.
	}

	// Handle $result error from the above blocks.
	if ( is_wp_error( $result ) ) {
		$wp_filesystem->delete( $from, true );

		return $result;
	}

	// Remove old files.
	foreach ( $_old_files as $old_file ) {
		$old_file = $to . $old_file;

		if ( ! $wp_filesystem->exists( $old_file ) ) {
			continue;
		}

		// If the file isn't deleted, try writing an empty string to the file instead.
		if ( ! $wp_filesystem->delete( $old_file, true ) && $wp_filesystem->is_file( $old_file ) ) {
			$wp_filesystem->put_contents( $old_file, '' );
		}
	}

	// Remove any Genericons example.html's from the filesystem.
	_upgrade_422_remove_genericons();

	// Deactivate the REST API plugin if its version is 2.0 Beta 4 or lower.
	_upgrade_440_force_deactivate_incompatible_plugins();

	// Deactivate incompatible plugins.
	_upgrade_core_deactivate_incompatible_plugins();

	// Upgrade DB with separate request.
	/** This filter is documented in wp-admin/includes/update-core.php */
	apply_filters( 'update_feedback', __( 'Upgrading database&#8230;' ) );

	$db_upgrade_url = admin_url( 'upgrade.php?step=upgrade_db' );
	wp_remote_post( $db_upgrade_url, array( 'timeout' => 60 ) );

	// Clear the cache to prevent an update_option() from saving a stale db_version to the cache.
	wp_cache_flush();
	// Not all cache back ends listen to 'flush'.
	wp_cache_delete( 'alloptions', 'options' );

	// Remove working directory.
	$wp_filesystem->delete( $from, true );

	// Force refresh of update information.
	if ( function_exists( 'delete_site_transient' ) ) {
		delete_site_transient( 'update_core' );
	} else {
		delete_option( 'update_core' );
	}

	/**
	 * Fires after WordPress core has been successfully updated.
	 *
	 * @since 3.3.0
	 *
	 * @param string $wp_version The current WordPress version.
	 */
	do_action( '_core_updated_successfully', $wp_version );

	// Clear the option that blocks auto-updates after failures, now that we've been successful.
	if ( function_exists( 'delete_site_option' ) ) {
		delete_site_option( 'auto_core_update_failed' );
	}

	return $wp_version;
}

/**
 * Preloads old Requests classes and interfaces.
 *
 * This function preloads the old Requests code into memory before the
 * upgrade process deletes the files. Why? Requests code is loaded into
 * memory via an autoloader, meaning when a class or interface is needed
 * If a request is in process, Requests could attempt to access code. If
 * the file is not there, a fatal error could occur. If the file was
 * replaced, the new code is not compatible with the old, resulting in
 * a fatal error. Preloading ensures the code is in memory before the
 * code is updated.
 *
 * @since 6.2.0
 *
 * @global string[]           $_old_requests_files Requests files to be preloaded.
 * @global WP_Filesystem_Base $wp_filesystem       WordPress filesystem subclass.
 * @global string             $wp_version          The WordPress version string.
 *
 * @param string $to Path to old WordPress installation.
 */
function _preload_old_requests_classes_and_interfaces( $to ) {
	global $_old_requests_files, $wp_filesystem, $wp_version;

	/*
	 * Requests was introduced in WordPress 4.6.
	 *
	 * Skip preloading if the website was previously using
	 * an earlier version of WordPress.
	 */
	if ( version_compare( $wp_version, '4.6', '<' ) ) {
		return;
	}

	if ( ! defined( 'REQUESTS_SILENCE_PSR0_DEPRECATIONS' ) ) {
		define( 'REQUESTS_SILENCE_PSR0_DEPRECATIONS', true );
	}

	foreach ( $_old_requests_files as $name => $file ) {
		// Skip files that aren't interfaces or classes.
		if ( is_int( $name ) ) {
			continue;
		}

		// Skip if it's already loaded.
		if ( class_exists( $name ) || interface_exists( $name ) ) {
			continue;
		}

		// Skip if the file is missing.
		if ( ! $wp_filesystem->is_file( $to . $file ) ) {
			continue;
		}

		require_once $to . $file;
	}
}

/**
 * Redirect to the About WordPress page after a successful upgrade.
 *
 * This function is only needed when the existing installation is older than 3.4.0.
 *
 * @since 3.3.0
 *
 * @global string $wp_version The WordPress version string.
 * @global string $pagenow    The filename of the current screen.
 * @global string $action
 *
 * @param string $new_version
 */
function _redirect_to_about_wordpress( $new_version ) {
	global $wp_version, $pagenow, $action;

	if ( version_compare( $wp_version, '3.4-RC1', '>=' ) ) {
		return;
	}

	// Ensure we only run this on the update-core.php page. The Core_Upgrader may be used in other contexts.
	if ( 'update-core.php' !== $pagenow ) {
		return;
	}

	if ( 'do-core-upgrade' !== $action && 'do-core-reinstall' !== $action ) {
		return;
	}

	// Load the updated default text localization domain for new strings.
	load_default_textdomain();

	// See do_core_upgrade().
	show_message( __( 'WordPress updated successfully.' ) );

	// self_admin_url() won't exist when upgrading from <= 3.0, so relative URLs are intentional.
	show_message(
		'<span class="hide-if-no-js">' . sprintf(
			/* translators: 1: WordPress version, 2: URL to About screen. */
			__( 'Welcome to WordPress %1$s. You will be redirected to the About WordPress screen. If not, click <a href="%2$s">here</a>.' ),
			$new_version,
			'about.php?updated'
		) . '</span>'
	);
	show_message(
		'<span class="hide-if-js">' . sprintf(
			/* translators: 1: WordPress version, 2: URL to About screen. */
			__( 'Welcome to WordPress %1$s. <a href="%2$s">Learn more</a>.' ),
			$new_version,
			'about.php?updated'
		) . '</span>'
	);
	echo '</div>';
	?>
<script type="text/javascript">
window.location = 'about.php?updated';
</script>
	<?php

	// Include admin-footer.php and exit.
	require_once ABSPATH . 'wp-admin/admin-footer.php';
	exit;
}

/**
 * Cleans up Genericons example files.
 *
 * @since 4.2.2
 *
 * @global string[]           $wp_theme_directories
 * @global WP_Filesystem_Base $wp_filesystem
 */
function _upgrade_422_remove_genericons() {
	global $wp_theme_directories, $wp_filesystem;

	// A list of the affected files using the filesystem absolute paths.
	$affected_files = array();

	// Themes.
	foreach ( $wp_theme_directories as $directory ) {
		$affected_theme_files = _upgrade_422_find_genericons_files_in_folder( $directory );
		$affected_files       = array_merge( $affected_files, $affected_theme_files );
	}

	// Plugins.
	$affected_plugin_files = _upgrade_422_find_genericons_files_in_folder( WP_PLUGIN_DIR );
	$affected_files        = array_merge( $affected_files, $affected_plugin_files );

	foreach ( $affected_files as $file ) {
		$gen_dir = $wp_filesystem->find_folder( trailingslashit( dirname( $file ) ) );

		if ( empty( $gen_dir ) ) {
			continue;
		}

		// The path when the file is accessed via WP_Filesystem may differ in the case of FTP.
		$remote_file = $gen_dir . basename( $file );

		if ( ! $wp_filesystem->exists( $remote_file ) ) {
			continue;
		}

		if ( ! $wp_filesystem->delete( $remote_file, false, 'f' ) ) {
			$wp_filesystem->put_contents( $remote_file, '' );
		}
	}
}

/**
 * Recursively find Genericons example files in a given folder.
 *
 * @ignore
 * @since 4.2.2
 *
 * @param string $directory Directory path. Expects trailingslashed.
 * @return string[]
 */
function _upgrade_422_find_genericons_files_in_folder( $directory ) {
	$directory = trailingslashit( $directory );
	$files     = array();

	if ( file_exists( "{$directory}example.html" )
		/*
		 * Note: str_contains() is not used here, as this file is included
		 * when updating from older WordPress versions, in which case
		 * the polyfills from wp-includes/compat.php may not be available.
		 */
		&& false !== strpos( file_get_contents( "{$directory}example.html" ), '<title>Genericons</title>' )
	) {
		$files[] = "{$directory}example.html";
	}

	$dirs = glob( $directory . '*', GLOB_ONLYDIR );
	$dirs = array_filter(
		$dirs,
		static function ( $dir ) {
			/*
			 * Skip any node_modules directories.
			 *
			 * Note: str_contains() is not used here, as this file is included
			 * when updating from older WordPress versions, in which case
			 * the polyfills from wp-includes/compat.php may not be available.
			 */
			return false === strpos( $dir, 'node_modules' );
		}
	);

	if ( $dirs ) {
		foreach ( $dirs as $dir ) {
			$files = array_merge( $files, _upgrade_422_find_genericons_files_in_folder( $dir ) );
		}
	}

	return $files;
}

/**
 * @ignore
 * @since 4.4.0
 */
function _upgrade_440_force_deactivate_incompatible_plugins() {
	if ( defined( 'REST_API_VERSION' ) && version_compare( REST_API_VERSION, '2.0-beta4', '<=' ) ) {
		deactivate_plugins( array( 'rest-api/plugin.php' ), true );
	}
}

/**
 * @access private
 * @ignore
 * @since 5.8.0
 * @since 5.9.0 The minimum compatible version of Gutenberg is 11.9.
 * @since 6.1.1 The minimum compatible version of Gutenberg is 14.1.
 * @since 6.4.0 The minimum compatible version of Gutenberg is 16.5.
 * @since 6.5.0 The minimum compatible version of Gutenberg is 17.6.
 */
function _upgrade_core_deactivate_incompatible_plugins() {
	if ( defined( 'GUTENBERG_VERSION' ) && version_compare( GUTENBERG_VERSION, '17.6', '<' ) ) {
		$deactivated_gutenberg['gutenberg'] = array(
			'plugin_name'         => 'Gutenberg',
			'version_deactivated' => GUTENBERG_VERSION,
			'version_compatible'  => '17.6',
		);
		if ( is_plugin_active_for_network( 'gutenberg/gutenberg.php' ) ) {
			$deactivated_plugins = get_site_option( 'wp_force_deactivated_plugins', array() );
			$deactivated_plugins = array_merge( $deactivated_plugins, $deactivated_gutenberg );
			update_site_option( 'wp_force_deactivated_plugins', $deactivated_plugins );
		} else {
			$deactivated_plugins = get_option( 'wp_force_deactivated_plugins', array() );
			$deactivated_plugins = array_merge( $deactivated_plugins, $deactivated_gutenberg );
			update_option( 'wp_force_deactivated_plugins', $deactivated_plugins, false );
		}
		deactivate_plugins( array( 'gutenberg/gutenberg.php' ), true );
	}
}
class-wp-filesystem-base.php000064400000057532151212616050012113 0ustar00<?php
/**
 * Base WordPress Filesystem
 *
 * @package WordPress
 * @subpackage Filesystem
 */

/**
 * Base WordPress Filesystem class which Filesystem implementations extend.
 *
 * @since 2.5.0
 */
#[AllowDynamicProperties]
class WP_Filesystem_Base {

	/**
	 * Whether to display debug data for the connection.
	 *
	 * @since 2.5.0
	 * @var bool
	 */
	public $verbose = false;

	/**
	 * Cached list of local filepaths to mapped remote filepaths.
	 *
	 * @since 2.7.0
	 * @var array
	 */
	public $cache = array();

	/**
	 * The Access method of the current connection, Set automatically.
	 *
	 * @since 2.5.0
	 * @var string
	 */
	public $method = '';

	/**
	 * @var WP_Error
	 */
	public $errors = null;

	/**
	 */
	public $options = array();

	/**
	 * Returns the path on the remote filesystem of ABSPATH.
	 *
	 * @since 2.7.0
	 *
	 * @return string The location of the remote path.
	 */
	public function abspath() {
		$folder = $this->find_folder( ABSPATH );

		/*
		 * Perhaps the FTP folder is rooted at the WordPress install.
		 * Check for wp-includes folder in root. Could have some false positives, but rare.
		 */
		if ( ! $folder && $this->is_dir( '/' . WPINC ) ) {
			$folder = '/';
		}

		return $folder;
	}

	/**
	 * Returns the path on the remote filesystem of WP_CONTENT_DIR.
	 *
	 * @since 2.7.0
	 *
	 * @return string The location of the remote path.
	 */
	public function wp_content_dir() {
		return $this->find_folder( WP_CONTENT_DIR );
	}

	/**
	 * Returns the path on the remote filesystem of WP_PLUGIN_DIR.
	 *
	 * @since 2.7.0
	 *
	 * @return string The location of the remote path.
	 */
	public function wp_plugins_dir() {
		return $this->find_folder( WP_PLUGIN_DIR );
	}

	/**
	 * Returns the path on the remote filesystem of the Themes Directory.
	 *
	 * @since 2.7.0
	 *
	 * @param string|false $theme Optional. The theme stylesheet or template for the directory.
	 *                            Default false.
	 * @return string The location of the remote path.
	 */
	public function wp_themes_dir( $theme = false ) {
		$theme_root = get_theme_root( $theme );

		// Account for relative theme roots.
		if ( '/themes' === $theme_root || ! is_dir( $theme_root ) ) {
			$theme_root = WP_CONTENT_DIR . $theme_root;
		}

		return $this->find_folder( $theme_root );
	}

	/**
	 * Returns the path on the remote filesystem of WP_LANG_DIR.
	 *
	 * @since 3.2.0
	 *
	 * @return string The location of the remote path.
	 */
	public function wp_lang_dir() {
		return $this->find_folder( WP_LANG_DIR );
	}

	/**
	 * Locates a folder on the remote filesystem.
	 *
	 * @since 2.5.0
	 * @deprecated 2.7.0 use WP_Filesystem_Base::abspath() or WP_Filesystem_Base::wp_*_dir() instead.
	 * @see WP_Filesystem_Base::abspath()
	 * @see WP_Filesystem_Base::wp_content_dir()
	 * @see WP_Filesystem_Base::wp_plugins_dir()
	 * @see WP_Filesystem_Base::wp_themes_dir()
	 * @see WP_Filesystem_Base::wp_lang_dir()
	 *
	 * @param string $base    Optional. The folder to start searching from. Default '.'.
	 * @param bool   $verbose Optional. True to display debug information. Default false.
	 * @return string The location of the remote path.
	 */
	public function find_base_dir( $base = '.', $verbose = false ) {
		_deprecated_function( __FUNCTION__, '2.7.0', 'WP_Filesystem_Base::abspath() or WP_Filesystem_Base::wp_*_dir()' );
		$this->verbose = $verbose;
		return $this->abspath();
	}

	/**
	 * Locates a folder on the remote filesystem.
	 *
	 * @since 2.5.0
	 * @deprecated 2.7.0 use WP_Filesystem_Base::abspath() or WP_Filesystem_Base::wp_*_dir() methods instead.
	 * @see WP_Filesystem_Base::abspath()
	 * @see WP_Filesystem_Base::wp_content_dir()
	 * @see WP_Filesystem_Base::wp_plugins_dir()
	 * @see WP_Filesystem_Base::wp_themes_dir()
	 * @see WP_Filesystem_Base::wp_lang_dir()
	 *
	 * @param string $base    Optional. The folder to start searching from. Default '.'.
	 * @param bool   $verbose Optional. True to display debug information. Default false.
	 * @return string The location of the remote path.
	 */
	public function get_base_dir( $base = '.', $verbose = false ) {
		_deprecated_function( __FUNCTION__, '2.7.0', 'WP_Filesystem_Base::abspath() or WP_Filesystem_Base::wp_*_dir()' );
		$this->verbose = $verbose;
		return $this->abspath();
	}

	/**
	 * Locates a folder on the remote filesystem.
	 *
	 * Assumes that on Windows systems, Stripping off the Drive
	 * letter is OK Sanitizes \\ to / in Windows filepaths.
	 *
	 * @since 2.7.0
	 *
	 * @param string $folder the folder to locate.
	 * @return string|false The location of the remote path, false on failure.
	 */
	public function find_folder( $folder ) {
		if ( isset( $this->cache[ $folder ] ) ) {
			return $this->cache[ $folder ];
		}

		if ( stripos( $this->method, 'ftp' ) !== false ) {
			$constant_overrides = array(
				'FTP_BASE'        => ABSPATH,
				'FTP_CONTENT_DIR' => WP_CONTENT_DIR,
				'FTP_PLUGIN_DIR'  => WP_PLUGIN_DIR,
				'FTP_LANG_DIR'    => WP_LANG_DIR,
			);

			// Direct matches ( folder = CONSTANT/ ).
			foreach ( $constant_overrides as $constant => $dir ) {
				if ( ! defined( $constant ) ) {
					continue;
				}

				if ( $folder === $dir ) {
					return trailingslashit( constant( $constant ) );
				}
			}

			// Prefix matches ( folder = CONSTANT/subdir ),
			foreach ( $constant_overrides as $constant => $dir ) {
				if ( ! defined( $constant ) ) {
					continue;
				}

				if ( 0 === stripos( $folder, $dir ) ) { // $folder starts with $dir.
					$potential_folder = preg_replace( '#^' . preg_quote( $dir, '#' ) . '/#i', trailingslashit( constant( $constant ) ), $folder );
					$potential_folder = trailingslashit( $potential_folder );

					if ( $this->is_dir( $potential_folder ) ) {
						$this->cache[ $folder ] = $potential_folder;

						return $potential_folder;
					}
				}
			}
		} elseif ( 'direct' === $this->method ) {
			$folder = str_replace( '\\', '/', $folder ); // Windows path sanitization.

			return trailingslashit( $folder );
		}

		$folder = preg_replace( '|^([a-z]{1}):|i', '', $folder ); // Strip out Windows drive letter if it's there.
		$folder = str_replace( '\\', '/', $folder ); // Windows path sanitization.

		if ( isset( $this->cache[ $folder ] ) ) {
			return $this->cache[ $folder ];
		}

		if ( $this->exists( $folder ) ) { // Folder exists at that absolute path.
			$folder                 = trailingslashit( $folder );
			$this->cache[ $folder ] = $folder;

			return $folder;
		}

		$return = $this->search_for_folder( $folder );

		if ( $return ) {
			$this->cache[ $folder ] = $return;
		}

		return $return;
	}

	/**
	 * Locates a folder on the remote filesystem.
	 *
	 * Expects Windows sanitized path.
	 *
	 * @since 2.7.0
	 *
	 * @param string $folder The folder to locate.
	 * @param string $base   The folder to start searching from.
	 * @param bool   $loop   If the function has recursed. Internal use only.
	 * @return string|false The location of the remote path, false to cease looping.
	 */
	public function search_for_folder( $folder, $base = '.', $loop = false ) {
		if ( empty( $base ) || '.' === $base ) {
			$base = trailingslashit( $this->cwd() );
		}

		$folder = untrailingslashit( $folder );

		if ( $this->verbose ) {
			/* translators: 1: Folder to locate, 2: Folder to start searching from. */
			printf( "\n" . __( 'Looking for %1$s in %2$s' ) . "<br />\n", $folder, $base );
		}

		$folder_parts     = explode( '/', $folder );
		$folder_part_keys = array_keys( $folder_parts );
		$last_index       = array_pop( $folder_part_keys );
		$last_path        = $folder_parts[ $last_index ];

		$files = $this->dirlist( $base );

		foreach ( $folder_parts as $index => $key ) {
			if ( $index === $last_index ) {
				continue; // We want this to be caught by the next code block.
			}

			/*
			 * Working from /home/ to /user/ to /wordpress/ see if that file exists within
			 * the current folder, If it's found, change into it and follow through looking
			 * for it. If it can't find WordPress down that route, it'll continue onto the next
			 * folder level, and see if that matches, and so on. If it reaches the end, and still
			 * can't find it, it'll return false for the entire function.
			 */
			if ( isset( $files[ $key ] ) ) {

				// Let's try that folder:
				$newdir = trailingslashit( path_join( $base, $key ) );

				if ( $this->verbose ) {
					/* translators: %s: Directory name. */
					printf( "\n" . __( 'Changing to %s' ) . "<br />\n", $newdir );
				}

				// Only search for the remaining path tokens in the directory, not the full path again.
				$newfolder = implode( '/', array_slice( $folder_parts, $index + 1 ) );
				$ret       = $this->search_for_folder( $newfolder, $newdir, $loop );

				if ( $ret ) {
					return $ret;
				}
			}
		}

		/*
		 * Only check this as a last resort, to prevent locating the incorrect install.
		 * All above procedures will fail quickly if this is the right branch to take.
		 */
		if ( isset( $files[ $last_path ] ) ) {
			if ( $this->verbose ) {
				/* translators: %s: Directory name. */
				printf( "\n" . __( 'Found %s' ) . "<br />\n", $base . $last_path );
			}

			return trailingslashit( $base . $last_path );
		}

		/*
		 * Prevent this function from looping again.
		 * No need to proceed if we've just searched in `/`.
		 */
		if ( $loop || '/' === $base ) {
			return false;
		}

		/*
		 * As an extra last resort, Change back to / if the folder wasn't found.
		 * This comes into effect when the CWD is /home/user/ but WP is at /var/www/....
		 */
		return $this->search_for_folder( $folder, '/', true );
	}

	/**
	 * Returns the *nix-style file permissions for a file.
	 *
	 * From the PHP documentation page for fileperms().
	 *
	 * @link https://www.php.net/manual/en/function.fileperms.php
	 *
	 * @since 2.5.0
	 *
	 * @param string $file String filename.
	 * @return string The *nix-style representation of permissions.
	 */
	public function gethchmod( $file ) {
		$perms = intval( $this->getchmod( $file ), 8 );

		if ( ( $perms & 0xC000 ) === 0xC000 ) { // Socket.
			$info = 's';
		} elseif ( ( $perms & 0xA000 ) === 0xA000 ) { // Symbolic Link.
			$info = 'l';
		} elseif ( ( $perms & 0x8000 ) === 0x8000 ) { // Regular.
			$info = '-';
		} elseif ( ( $perms & 0x6000 ) === 0x6000 ) { // Block special.
			$info = 'b';
		} elseif ( ( $perms & 0x4000 ) === 0x4000 ) { // Directory.
			$info = 'd';
		} elseif ( ( $perms & 0x2000 ) === 0x2000 ) { // Character special.
			$info = 'c';
		} elseif ( ( $perms & 0x1000 ) === 0x1000 ) { // FIFO pipe.
			$info = 'p';
		} else { // Unknown.
			$info = 'u';
		}

		// Owner.
		$info .= ( ( $perms & 0x0100 ) ? 'r' : '-' );
		$info .= ( ( $perms & 0x0080 ) ? 'w' : '-' );
		$info .= ( ( $perms & 0x0040 ) ?
					( ( $perms & 0x0800 ) ? 's' : 'x' ) :
					( ( $perms & 0x0800 ) ? 'S' : '-' ) );

		// Group.
		$info .= ( ( $perms & 0x0020 ) ? 'r' : '-' );
		$info .= ( ( $perms & 0x0010 ) ? 'w' : '-' );
		$info .= ( ( $perms & 0x0008 ) ?
					( ( $perms & 0x0400 ) ? 's' : 'x' ) :
					( ( $perms & 0x0400 ) ? 'S' : '-' ) );

		// World.
		$info .= ( ( $perms & 0x0004 ) ? 'r' : '-' );
		$info .= ( ( $perms & 0x0002 ) ? 'w' : '-' );
		$info .= ( ( $perms & 0x0001 ) ?
					( ( $perms & 0x0200 ) ? 't' : 'x' ) :
					( ( $perms & 0x0200 ) ? 'T' : '-' ) );

		return $info;
	}

	/**
	 * Gets the permissions of the specified file or filepath in their octal format.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to the file.
	 * @return string Mode of the file (the last 3 digits).
	 */
	public function getchmod( $file ) {
		return '777';
	}

	/**
	 * Converts *nix-style file permissions to an octal number.
	 *
	 * Converts '-rw-r--r--' to 0644
	 * From "info at rvgate dot nl"'s comment on the PHP documentation for chmod()
	 *
	 * @link https://www.php.net/manual/en/function.chmod.php#49614
	 *
	 * @since 2.5.0
	 *
	 * @param string $mode string The *nix-style file permissions.
	 * @return string Octal representation of permissions.
	 */
	public function getnumchmodfromh( $mode ) {
		$realmode = '';
		$legal    = array( '', 'w', 'r', 'x', '-' );
		$attarray = preg_split( '//', $mode );

		for ( $i = 0, $c = count( $attarray ); $i < $c; $i++ ) {
			$key = array_search( $attarray[ $i ], $legal, true );

			if ( $key ) {
				$realmode .= $legal[ $key ];
			}
		}

		$mode  = str_pad( $realmode, 10, '-', STR_PAD_LEFT );
		$trans = array(
			'-' => '0',
			'r' => '4',
			'w' => '2',
			'x' => '1',
		);
		$mode  = strtr( $mode, $trans );

		$newmode  = $mode[0];
		$newmode .= $mode[1] + $mode[2] + $mode[3];
		$newmode .= $mode[4] + $mode[5] + $mode[6];
		$newmode .= $mode[7] + $mode[8] + $mode[9];

		return $newmode;
	}

	/**
	 * Determines if the string provided contains binary characters.
	 *
	 * @since 2.7.0
	 *
	 * @param string $text String to test against.
	 * @return bool True if string is binary, false otherwise.
	 */
	public function is_binary( $text ) {
		return (bool) preg_match( '|[^\x20-\x7E]|', $text ); // chr(32)..chr(127)
	}

	/**
	 * Changes the owner of a file or directory.
	 *
	 * Default behavior is to do nothing, override this in your subclass, if desired.
	 *
	 * @since 2.5.0
	 *
	 * @param string     $file      Path to the file or directory.
	 * @param string|int $owner     A user name or number.
	 * @param bool       $recursive Optional. If set to true, changes file owner recursively.
	 *                              Default false.
	 * @return bool True on success, false on failure.
	 */
	public function chown( $file, $owner, $recursive = false ) {
		return false;
	}

	/**
	 * Connects filesystem.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @return bool True on success, false on failure (always true for WP_Filesystem_Direct).
	 */
	public function connect() {
		return true;
	}

	/**
	 * Reads entire file into a string.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @param string $file Name of the file to read.
	 * @return string|false Read data on success, false on failure.
	 */
	public function get_contents( $file ) {
		return false;
	}

	/**
	 * Reads entire file into an array.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @param string $file Path to the file.
	 * @return array|false File contents in an array on success, false on failure.
	 */
	public function get_contents_array( $file ) {
		return false;
	}

	/**
	 * Writes a string to a file.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @param string    $file     Remote path to the file where to write the data.
	 * @param string    $contents The data to write.
	 * @param int|false $mode     Optional. The file permissions as octal number, usually 0644.
	 *                            Default false.
	 * @return bool True on success, false on failure.
	 */
	public function put_contents( $file, $contents, $mode = false ) {
		return false;
	}

	/**
	 * Gets the current working directory.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @return string|false The current working directory on success, false on failure.
	 */
	public function cwd() {
		return false;
	}

	/**
	 * Changes current directory.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @param string $dir The new current directory.
	 * @return bool True on success, false on failure.
	 */
	public function chdir( $dir ) {
		return false;
	}

	/**
	 * Changes the file group.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @param string     $file      Path to the file.
	 * @param string|int $group     A group name or number.
	 * @param bool       $recursive Optional. If set to true, changes file group recursively.
	 *                              Default false.
	 * @return bool True on success, false on failure.
	 */
	public function chgrp( $file, $group, $recursive = false ) {
		return false;
	}

	/**
	 * Changes filesystem permissions.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @param string    $file      Path to the file.
	 * @param int|false $mode      Optional. The permissions as octal number, usually 0644 for files,
	 *                             0755 for directories. Default false.
	 * @param bool      $recursive Optional. If set to true, changes file permissions recursively.
	 *                             Default false.
	 * @return bool True on success, false on failure.
	 */
	public function chmod( $file, $mode = false, $recursive = false ) {
		return false;
	}

	/**
	 * Gets the file owner.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @param string $file Path to the file.
	 * @return string|false Username of the owner on success, false on failure.
	 */
	public function owner( $file ) {
		return false;
	}

	/**
	 * Gets the file's group.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @param string $file Path to the file.
	 * @return string|false The group on success, false on failure.
	 */
	public function group( $file ) {
		return false;
	}

	/**
	 * Copies a file.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @param string    $source      Path to the source file.
	 * @param string    $destination Path to the destination file.
	 * @param bool      $overwrite   Optional. Whether to overwrite the destination file if it exists.
	 *                               Default false.
	 * @param int|false $mode        Optional. The permissions as octal number, usually 0644 for files,
	 *                               0755 for dirs. Default false.
	 * @return bool True on success, false on failure.
	 */
	public function copy( $source, $destination, $overwrite = false, $mode = false ) {
		return false;
	}

	/**
	 * Moves a file.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @param string $source      Path to the source file.
	 * @param string $destination Path to the destination file.
	 * @param bool   $overwrite   Optional. Whether to overwrite the destination file if it exists.
	 *                            Default false.
	 * @return bool True on success, false on failure.
	 */
	public function move( $source, $destination, $overwrite = false ) {
		return false;
	}

	/**
	 * Deletes a file or directory.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @param string       $file      Path to the file or directory.
	 * @param bool         $recursive Optional. If set to true, deletes files and folders recursively.
	 *                                Default false.
	 * @param string|false $type      Type of resource. 'f' for file, 'd' for directory.
	 *                                Default false.
	 * @return bool True on success, false on failure.
	 */
	public function delete( $file, $recursive = false, $type = false ) {
		return false;
	}

	/**
	 * Checks if a file or directory exists.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @param string $path Path to file or directory.
	 * @return bool Whether $path exists or not.
	 */
	public function exists( $path ) {
		return false;
	}

	/**
	 * Checks if resource is a file.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @param string $file File path.
	 * @return bool Whether $file is a file.
	 */
	public function is_file( $file ) {
		return false;
	}

	/**
	 * Checks if resource is a directory.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @param string $path Directory path.
	 * @return bool Whether $path is a directory.
	 */
	public function is_dir( $path ) {
		return false;
	}

	/**
	 * Checks if a file is readable.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @param string $file Path to file.
	 * @return bool Whether $file is readable.
	 */
	public function is_readable( $file ) {
		return false;
	}

	/**
	 * Checks if a file or directory is writable.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @param string $path Path to file or directory.
	 * @return bool Whether $path is writable.
	 */
	public function is_writable( $path ) {
		return false;
	}

	/**
	 * Gets the file's last access time.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @param string $file Path to file.
	 * @return int|false Unix timestamp representing last access time, false on failure.
	 */
	public function atime( $file ) {
		return false;
	}

	/**
	 * Gets the file modification time.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @param string $file Path to file.
	 * @return int|false Unix timestamp representing modification time, false on failure.
	 */
	public function mtime( $file ) {
		return false;
	}

	/**
	 * Gets the file size (in bytes).
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @param string $file Path to file.
	 * @return int|false Size of the file in bytes on success, false on failure.
	 */
	public function size( $file ) {
		return false;
	}

	/**
	 * Sets the access and modification times of a file.
	 *
	 * Note: If $file doesn't exist, it will be created.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @param string $file  Path to file.
	 * @param int    $time  Optional. Modified time to set for file.
	 *                      Default 0.
	 * @param int    $atime Optional. Access time to set for file.
	 *                      Default 0.
	 * @return bool True on success, false on failure.
	 */
	public function touch( $file, $time = 0, $atime = 0 ) {
		return false;
	}

	/**
	 * Creates a directory.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @param string           $path  Path for new directory.
	 * @param int|false        $chmod Optional. The permissions as octal number (or false to skip chmod).
	 *                                Default false.
	 * @param string|int|false $chown Optional. A user name or number (or false to skip chown).
	 *                                Default false.
	 * @param string|int|false $chgrp Optional. A group name or number (or false to skip chgrp).
	 *                                Default false.
	 * @return bool True on success, false on failure.
	 */
	public function mkdir( $path, $chmod = false, $chown = false, $chgrp = false ) {
		return false;
	}

	/**
	 * Deletes a directory.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @param string $path      Path to directory.
	 * @param bool   $recursive Optional. Whether to recursively remove files/directories.
	 *                          Default false.
	 * @return bool True on success, false on failure.
	 */
	public function rmdir( $path, $recursive = false ) {
		return false;
	}

	/**
	 * Gets details for files in a directory or a specific file.
	 *
	 * @since 2.5.0
	 * @abstract
	 *
	 * @param string $path           Path to directory or file.
	 * @param bool   $include_hidden Optional. Whether to include details of hidden ("." prefixed) files.
	 *                               Default true.
	 * @param bool   $recursive      Optional. Whether to recursively include file details in nested directories.
	 *                               Default false.
	 * @return array|false {
	 *     Array of arrays containing file information. False if unable to list directory contents.
	 *
	 *     @type array ...$0 {
	 *         Array of file information. Note that some elements may not be available on all filesystems.
	 *
	 *         @type string           $name        Name of the file or directory.
	 *         @type string           $perms       *nix representation of permissions.
	 *         @type string           $permsn      Octal representation of permissions.
	 *         @type int|string|false $number      File number. May be a numeric string. False if not available.
	 *         @type string|false     $owner       Owner name or ID, or false if not available.
	 *         @type string|false     $group       File permissions group, or false if not available.
	 *         @type int|string|false $size        Size of file in bytes. May be a numeric string.
	 *                                             False if not available.
	 *         @type int|string|false $lastmodunix Last modified unix timestamp. May be a numeric string.
	 *                                             False if not available.
	 *         @type string|false     $lastmod     Last modified month (3 letters) and day (without leading 0), or
	 *                                             false if not available.
	 *         @type string|false     $time        Last modified time, or false if not available.
	 *         @type string           $type        Type of resource. 'f' for file, 'd' for directory, 'l' for link.
	 *         @type array|false      $files       If a directory and `$recursive` is true, contains another array of
	 *                                             files. False if unable to list directory contents.
	 *     }
	 * }
	 */
	public function dirlist( $path, $include_hidden = true, $recursive = false ) {
		return false;
	}
}
deprecated.php000064400000121460151212616050007360 0ustar00<?php
/**
 * Deprecated admin functions from past WordPress versions. You shouldn't use these
 * functions and look for the alternatives instead. The functions will be removed
 * in a later version.
 *
 * @package WordPress
 * @subpackage Deprecated
 */

/*
 * Deprecated functions come here to die.
 */

/**
 * @since 2.1.0
 * @deprecated 2.1.0 Use wp_editor()
 * @see wp_editor()
 */
function tinymce_include() {
	_deprecated_function( __FUNCTION__, '2.1.0', 'wp_editor()' );

	wp_tiny_mce();
}

/**
 * Unused Admin function.
 *
 * @since 2.0.0
 * @deprecated 2.5.0
 *
 */
function documentation_link() {
	_deprecated_function( __FUNCTION__, '2.5.0' );
}

/**
 * Calculates the new dimensions for a downsampled image.
 *
 * @since 2.0.0
 * @deprecated 3.0.0 Use wp_constrain_dimensions()
 * @see wp_constrain_dimensions()
 *
 * @param int $width Current width of the image
 * @param int $height Current height of the image
 * @param int $wmax Maximum wanted width
 * @param int $hmax Maximum wanted height
 * @return array Shrunk dimensions (width, height).
 */
function wp_shrink_dimensions( $width, $height, $wmax = 128, $hmax = 96 ) {
	_deprecated_function( __FUNCTION__, '3.0.0', 'wp_constrain_dimensions()' );
	return wp_constrain_dimensions( $width, $height, $wmax, $hmax );
}

/**
 * Calculates the new dimensions for a downsampled image.
 *
 * @since 2.0.0
 * @deprecated 3.5.0 Use wp_constrain_dimensions()
 * @see wp_constrain_dimensions()
 *
 * @param int $width Current width of the image
 * @param int $height Current height of the image
 * @return array Shrunk dimensions (width, height).
 */
function get_udims( $width, $height ) {
	_deprecated_function( __FUNCTION__, '3.5.0', 'wp_constrain_dimensions()' );
	return wp_constrain_dimensions( $width, $height, 128, 96 );
}

/**
 * Legacy function used to generate the categories checklist control.
 *
 * @since 0.71
 * @deprecated 2.6.0 Use wp_category_checklist()
 * @see wp_category_checklist()
 *
 * @global int $post_ID
 *
 * @param int   $default_category Unused.
 * @param int   $category_parent  Unused.
 * @param array $popular_ids      Unused.
 */
function dropdown_categories( $default_category = 0, $category_parent = 0, $popular_ids = array() ) {
	_deprecated_function( __FUNCTION__, '2.6.0', 'wp_category_checklist()' );
	global $post_ID;
	wp_category_checklist( $post_ID );
}

/**
 * Legacy function used to generate a link categories checklist control.
 *
 * @since 2.1.0
 * @deprecated 2.6.0 Use wp_link_category_checklist()
 * @see wp_link_category_checklist()
 *
 * @global int $link_id
 *
 * @param int $default_link_category Unused.
 */
function dropdown_link_categories( $default_link_category = 0 ) {
	_deprecated_function( __FUNCTION__, '2.6.0', 'wp_link_category_checklist()' );
	global $link_id;
	wp_link_category_checklist( $link_id );
}

/**
 * Get the real filesystem path to a file to edit within the admin.
 *
 * @since 1.5.0
 * @deprecated 2.9.0
 * @uses WP_CONTENT_DIR Full filesystem path to the wp-content directory.
 *
 * @param string $file Filesystem path relative to the wp-content directory.
 * @return string Full filesystem path to edit.
 */
function get_real_file_to_edit( $file ) {
	_deprecated_function( __FUNCTION__, '2.9.0' );

	return WP_CONTENT_DIR . $file;
}

/**
 * Legacy function used for generating a categories drop-down control.
 *
 * @since 1.2.0
 * @deprecated 3.0.0 Use wp_dropdown_categories()
 * @see wp_dropdown_categories()
 *
 * @param int $current_cat     Optional. ID of the current category. Default 0.
 * @param int $current_parent  Optional. Current parent category ID. Default 0.
 * @param int $category_parent Optional. Parent ID to retrieve categories for. Default 0.
 * @param int $level           Optional. Number of levels deep to display. Default 0.
 * @param array $categories    Optional. Categories to include in the control. Default 0.
 * @return void|false Void on success, false if no categories were found.
 */
function wp_dropdown_cats( $current_cat = 0, $current_parent = 0, $category_parent = 0, $level = 0, $categories = 0 ) {
	_deprecated_function( __FUNCTION__, '3.0.0', 'wp_dropdown_categories()' );
	if (!$categories )
		$categories = get_categories( array('hide_empty' => 0) );

	if ( $categories ) {
		foreach ( $categories as $category ) {
			if ( $current_cat != $category->term_id && $category_parent == $category->parent) {
				$pad = str_repeat( '&#8211; ', $level );
				$category->name = esc_html( $category->name );
				echo "\n\t<option value='$category->term_id'";
				if ( $current_parent == $category->term_id )
					echo " selected='selected'";
				echo ">$pad$category->name</option>";
				wp_dropdown_cats( $current_cat, $current_parent, $category->term_id, $level +1, $categories );
			}
		}
	} else {
		return false;
	}
}

/**
 * Register a setting and its sanitization callback
 *
 * @since 2.7.0
 * @deprecated 3.0.0 Use register_setting()
 * @see register_setting()
 *
 * @param string   $option_group      A settings group name. Should correspond to an allowed option key name.
 *                                    Default allowed option key names include 'general', 'discussion', 'media',
 *                                    'reading', 'writing', and 'options'.
 * @param string   $option_name       The name of an option to sanitize and save.
 * @param callable $sanitize_callback Optional. A callback function that sanitizes the option's value.
 */
function add_option_update_handler( $option_group, $option_name, $sanitize_callback = '' ) {
	_deprecated_function( __FUNCTION__, '3.0.0', 'register_setting()' );
	register_setting( $option_group, $option_name, $sanitize_callback );
}

/**
 * Unregister a setting
 *
 * @since 2.7.0
 * @deprecated 3.0.0 Use unregister_setting()
 * @see unregister_setting()
 *
 * @param string   $option_group      The settings group name used during registration.
 * @param string   $option_name       The name of the option to unregister.
 * @param callable $sanitize_callback Optional. Deprecated.
 */
function remove_option_update_handler( $option_group, $option_name, $sanitize_callback = '' ) {
	_deprecated_function( __FUNCTION__, '3.0.0', 'unregister_setting()' );
	unregister_setting( $option_group, $option_name, $sanitize_callback );
}

/**
 * Determines the language to use for CodePress syntax highlighting.
 *
 * @since 2.8.0
 * @deprecated 3.0.0
 *
 * @param string $filename
 */
function codepress_get_lang( $filename ) {
	_deprecated_function( __FUNCTION__, '3.0.0' );
}

/**
 * Adds JavaScript required to make CodePress work on the theme/plugin file editors.
 *
 * @since 2.8.0
 * @deprecated 3.0.0
 */
function codepress_footer_js() {
	_deprecated_function( __FUNCTION__, '3.0.0' );
}

/**
 * Determine whether to use CodePress.
 *
 * @since 2.8.0
 * @deprecated 3.0.0
 */
function use_codepress() {
	_deprecated_function( __FUNCTION__, '3.0.0' );
}

/**
 * Get all user IDs.
 *
 * @deprecated 3.1.0 Use get_users()
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @return array List of user IDs.
 */
function get_author_user_ids() {
	_deprecated_function( __FUNCTION__, '3.1.0', 'get_users()' );

	global $wpdb;
	if ( !is_multisite() )
		$level_key = $wpdb->get_blog_prefix() . 'user_level';
	else
		$level_key = $wpdb->get_blog_prefix() . 'capabilities'; // WPMU site admins don't have user_levels.

	return $wpdb->get_col( $wpdb->prepare("SELECT user_id FROM $wpdb->usermeta WHERE meta_key = %s AND meta_value != '0'", $level_key) );
}

/**
 * Gets author users who can edit posts.
 *
 * @deprecated 3.1.0 Use get_users()
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int $user_id User ID.
 * @return array|false List of editable authors. False if no editable users.
 */
function get_editable_authors( $user_id ) {
	_deprecated_function( __FUNCTION__, '3.1.0', 'get_users()' );

	global $wpdb;

	$editable = get_editable_user_ids( $user_id );

	if ( !$editable ) {
		return false;
	} else {
		$editable = join(',', $editable);
		$authors = $wpdb->get_results( "SELECT * FROM $wpdb->users WHERE ID IN ($editable) ORDER BY display_name" );
	}

	return apply_filters('get_editable_authors', $authors);
}

/**
 * Gets the IDs of any users who can edit posts.
 *
 * @deprecated 3.1.0 Use get_users()
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int  $user_id       User ID.
 * @param bool $exclude_zeros Optional. Whether to exclude zeroes. Default true.
 * @return array Array of editable user IDs, empty array otherwise.
 */
function get_editable_user_ids( $user_id, $exclude_zeros = true, $post_type = 'post' ) {
	_deprecated_function( __FUNCTION__, '3.1.0', 'get_users()' );

	global $wpdb;

	if ( ! $user = get_userdata( $user_id ) )
		return array();
	$post_type_obj = get_post_type_object($post_type);

	if ( ! $user->has_cap($post_type_obj->cap->edit_others_posts) ) {
		if ( $user->has_cap($post_type_obj->cap->edit_posts) || ! $exclude_zeros )
			return array($user->ID);
		else
			return array();
	}

	if ( !is_multisite() )
		$level_key = $wpdb->get_blog_prefix() . 'user_level';
	else
		$level_key = $wpdb->get_blog_prefix() . 'capabilities'; // WPMU site admins don't have user_levels.

	$query = $wpdb->prepare("SELECT user_id FROM $wpdb->usermeta WHERE meta_key = %s", $level_key);
	if ( $exclude_zeros )
		$query .= " AND meta_value != '0'";

	return $wpdb->get_col( $query );
}

/**
 * Gets all users who are not authors.
 *
 * @deprecated 3.1.0 Use get_users()
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 */
function get_nonauthor_user_ids() {
	_deprecated_function( __FUNCTION__, '3.1.0', 'get_users()' );

	global $wpdb;

	if ( !is_multisite() )
		$level_key = $wpdb->get_blog_prefix() . 'user_level';
	else
		$level_key = $wpdb->get_blog_prefix() . 'capabilities'; // WPMU site admins don't have user_levels.

	return $wpdb->get_col( $wpdb->prepare("SELECT user_id FROM $wpdb->usermeta WHERE meta_key = %s AND meta_value = '0'", $level_key) );
}

if ( ! class_exists( 'WP_User_Search', false ) ) :
/**
 * WordPress User Search class.
 *
 * @since 2.1.0
 * @deprecated 3.1.0 Use WP_User_Query
 */
class WP_User_Search {

	/**
	 * {@internal Missing Description}}
	 *
	 * @since 2.1.0
	 * @access private
	 * @var mixed
	 */
	var $results;

	/**
	 * {@internal Missing Description}}
	 *
	 * @since 2.1.0
	 * @access private
	 * @var string
	 */
	var $search_term;

	/**
	 * Page number.
	 *
	 * @since 2.1.0
	 * @access private
	 * @var int
	 */
	var $page;

	/**
	 * Role name that users have.
	 *
	 * @since 2.5.0
	 * @access private
	 * @var string
	 */
	var $role;

	/**
	 * Raw page number.
	 *
	 * @since 2.1.0
	 * @access private
	 * @var int|bool
	 */
	var $raw_page;

	/**
	 * Amount of users to display per page.
	 *
	 * @since 2.1.0
	 * @access public
	 * @var int
	 */
	var $users_per_page = 50;

	/**
	 * {@internal Missing Description}}
	 *
	 * @since 2.1.0
	 * @access private
	 * @var int
	 */
	var $first_user;

	/**
	 * {@internal Missing Description}}
	 *
	 * @since 2.1.0
	 * @access private
	 * @var int
	 */
	var $last_user;

	/**
	 * {@internal Missing Description}}
	 *
	 * @since 2.1.0
	 * @access private
	 * @var string
	 */
	var $query_limit;

	/**
	 * {@internal Missing Description}}
	 *
	 * @since 3.0.0
	 * @access private
	 * @var string
	 */
	var $query_orderby;

	/**
	 * {@internal Missing Description}}
	 *
	 * @since 3.0.0
	 * @access private
	 * @var string
	 */
	var $query_from;

	/**
	 * {@internal Missing Description}}
	 *
	 * @since 3.0.0
	 * @access private
	 * @var string
	 */
	var $query_where;

	/**
	 * {@internal Missing Description}}
	 *
	 * @since 2.1.0
	 * @access private
	 * @var int
	 */
	var $total_users_for_query = 0;

	/**
	 * {@internal Missing Description}}
	 *
	 * @since 2.1.0
	 * @access private
	 * @var bool
	 */
	var $too_many_total_users = false;

	/**
	 * {@internal Missing Description}}
	 *
	 * @since 2.1.0
	 * @access private
	 * @var WP_Error
	 */
	var $search_errors;

	/**
	 * {@internal Missing Description}}
	 *
	 * @since 2.7.0
	 * @access private
	 * @var string
	 */
	var $paging_text;

	/**
	 * PHP5 Constructor - Sets up the object properties.
	 *
	 * @since 2.1.0
	 *
	 * @param string $search_term Search terms string.
	 * @param int $page Optional. Page ID.
	 * @param string $role Role name.
	 * @return WP_User_Search
	 */
	function __construct( $search_term = '', $page = '', $role = '' ) {
		_deprecated_class( 'WP_User_Search', '3.1.0', 'WP_User_Query' );

		$this->search_term = wp_unslash( $search_term );
		$this->raw_page = ( '' == $page ) ? false : (int) $page;
		$this->page = ( '' == $page ) ? 1 : (int) $page;
		$this->role = $role;

		$this->prepare_query();
		$this->query();
		$this->do_paging();
	}

	/**
	 * PHP4 Constructor - Sets up the object properties.
	 *
	 * @since 2.1.0
	 *
	 * @param string $search_term Search terms string.
	 * @param int $page Optional. Page ID.
	 * @param string $role Role name.
	 * @return WP_User_Search
	 */
	public function WP_User_Search( $search_term = '', $page = '', $role = '' ) {
		_deprecated_constructor( 'WP_User_Search', '3.1.0', get_class( $this ) );
		self::__construct( $search_term, $page, $role );
	}

	/**
	 * Prepares the user search query (legacy).
	 *
	 * @since 2.1.0
	 * @access public
	 *
	 * @global wpdb $wpdb WordPress database abstraction object.
	 */
	public function prepare_query() {
		global $wpdb;
		$this->first_user = ($this->page - 1) * $this->users_per_page;

		$this->query_limit = $wpdb->prepare(" LIMIT %d, %d", $this->first_user, $this->users_per_page);
		$this->query_orderby = ' ORDER BY user_login';

		$search_sql = '';
		if ( $this->search_term ) {
			$searches = array();
			$search_sql = 'AND (';
			foreach ( array('user_login', 'user_nicename', 'user_email', 'user_url', 'display_name') as $col )
				$searches[] = $wpdb->prepare( $col . ' LIKE %s', '%' . like_escape($this->search_term) . '%' );
			$search_sql .= implode(' OR ', $searches);
			$search_sql .= ')';
		}

		$this->query_from = " FROM $wpdb->users";
		$this->query_where = " WHERE 1=1 $search_sql";

		if ( $this->role ) {
			$this->query_from .= " INNER JOIN $wpdb->usermeta ON $wpdb->users.ID = $wpdb->usermeta.user_id";
			$this->query_where .= $wpdb->prepare(" AND $wpdb->usermeta.meta_key = '{$wpdb->prefix}capabilities' AND $wpdb->usermeta.meta_value LIKE %s", '%' . $this->role . '%');
		} elseif ( is_multisite() ) {
			$level_key = $wpdb->prefix . 'capabilities'; // WPMU site admins don't have user_levels.
			$this->query_from .= ", $wpdb->usermeta";
			$this->query_where .= " AND $wpdb->users.ID = $wpdb->usermeta.user_id AND meta_key = '{$level_key}'";
		}

		do_action_ref_array( 'pre_user_search', array( &$this ) );
	}

	/**
	 * Executes the user search query.
	 *
	 * @since 2.1.0
	 * @access public
	 *
	 * @global wpdb $wpdb WordPress database abstraction object.
	 */
	public function query() {
		global $wpdb;

		$this->results = $wpdb->get_col("SELECT DISTINCT($wpdb->users.ID)" . $this->query_from . $this->query_where . $this->query_orderby . $this->query_limit);

		if ( $this->results )
			$this->total_users_for_query = $wpdb->get_var("SELECT COUNT(DISTINCT($wpdb->users.ID))" . $this->query_from . $this->query_where); // No limit.
		else
			$this->search_errors = new WP_Error('no_matching_users_found', __('No users found.'));
	}

	/**
	 * Prepares variables for use in templates.
	 *
	 * @since 2.1.0
	 * @access public
	 */
	function prepare_vars_for_template_usage() {}

	/**
	 * Handles paging for the user search query.
	 *
	 * @since 2.1.0
	 * @access public
	 */
	public function do_paging() {
		if ( $this->total_users_for_query > $this->users_per_page ) { // Have to page the results.
			$args = array();
			if ( ! empty($this->search_term) )
				$args['usersearch'] = urlencode($this->search_term);
			if ( ! empty($this->role) )
				$args['role'] = urlencode($this->role);

			$this->paging_text = paginate_links( array(
				'total' => ceil($this->total_users_for_query / $this->users_per_page),
				'current' => $this->page,
				'base' => 'users.php?%_%',
				'format' => 'userspage=%#%',
				'add_args' => $args
			) );
			if ( $this->paging_text ) {
				$this->paging_text = sprintf(
					/* translators: 1: Starting number of users on the current page, 2: Ending number of users, 3: Total number of users. */
					'<span class="displaying-num">' . __( 'Displaying %1$s&#8211;%2$s of %3$s' ) . '</span>%s',
					number_format_i18n( ( $this->page - 1 ) * $this->users_per_page + 1 ),
					number_format_i18n( min( $this->page * $this->users_per_page, $this->total_users_for_query ) ),
					number_format_i18n( $this->total_users_for_query ),
					$this->paging_text
				);
			}
		}
	}

	/**
	 * Retrieves the user search query results.
	 *
	 * @since 2.1.0
	 * @access public
	 *
	 * @return array
	 */
	public function get_results() {
		return (array) $this->results;
	}

	/**
	 * Displaying paging text.
	 *
	 * @see do_paging() Builds paging text.
	 *
	 * @since 2.1.0
	 * @access public
	 */
	function page_links() {
		echo $this->paging_text;
	}

	/**
	 * Whether paging is enabled.
	 *
	 * @see do_paging() Builds paging text.
	 *
	 * @since 2.1.0
	 * @access public
	 *
	 * @return bool
	 */
	function results_are_paged() {
		if ( $this->paging_text )
			return true;
		return false;
	}

	/**
	 * Whether there are search terms.
	 *
	 * @since 2.1.0
	 * @access public
	 *
	 * @return bool
	 */
	function is_search() {
		if ( $this->search_term )
			return true;
		return false;
	}
}
endif;

/**
 * Retrieves editable posts from other users.
 *
 * @since 2.3.0
 * @deprecated 3.1.0 Use get_posts()
 * @see get_posts()
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int    $user_id User ID to not retrieve posts from.
 * @param string $type    Optional. Post type to retrieve. Accepts 'draft', 'pending' or 'any' (all).
 *                        Default 'any'.
 * @return array List of posts from others.
 */
function get_others_unpublished_posts( $user_id, $type = 'any' ) {
	_deprecated_function( __FUNCTION__, '3.1.0' );

	global $wpdb;

	$editable = get_editable_user_ids( $user_id );

	if ( in_array($type, array('draft', 'pending')) )
		$type_sql = " post_status = '$type' ";
	else
		$type_sql = " ( post_status = 'draft' OR post_status = 'pending' ) ";

	$dir = ( 'pending' == $type ) ? 'ASC' : 'DESC';

	if ( !$editable ) {
		$other_unpubs = '';
	} else {
		$editable = join(',', $editable);
		$other_unpubs = $wpdb->get_results( $wpdb->prepare("SELECT ID, post_title, post_author FROM $wpdb->posts WHERE post_type = 'post' AND $type_sql AND post_author IN ($editable) AND post_author != %d ORDER BY post_modified $dir", $user_id) );
	}

	return apply_filters('get_others_drafts', $other_unpubs);
}

/**
 * Retrieve drafts from other users.
 *
 * @deprecated 3.1.0 Use get_posts()
 * @see get_posts()
 *
 * @param int $user_id User ID.
 * @return array List of drafts from other users.
 */
function get_others_drafts($user_id) {
	_deprecated_function( __FUNCTION__, '3.1.0' );

	return get_others_unpublished_posts($user_id, 'draft');
}

/**
 * Retrieve pending review posts from other users.
 *
 * @deprecated 3.1.0 Use get_posts()
 * @see get_posts()
 *
 * @param int $user_id User ID.
 * @return array List of posts with pending review post type from other users.
 */
function get_others_pending($user_id) {
	_deprecated_function( __FUNCTION__, '3.1.0' );

	return get_others_unpublished_posts($user_id, 'pending');
}

/**
 * Output the QuickPress dashboard widget.
 *
 * @since 3.0.0
 * @deprecated 3.2.0 Use wp_dashboard_quick_press()
 * @see wp_dashboard_quick_press()
 */
function wp_dashboard_quick_press_output() {
	_deprecated_function( __FUNCTION__, '3.2.0', 'wp_dashboard_quick_press()' );
	wp_dashboard_quick_press();
}

/**
 * Outputs the TinyMCE editor.
 *
 * @since 2.7.0
 * @deprecated 3.3.0 Use wp_editor()
 * @see wp_editor()
 */
function wp_tiny_mce( $teeny = false, $settings = false ) {
	_deprecated_function( __FUNCTION__, '3.3.0', 'wp_editor()' );

	static $num = 1;

	if ( ! class_exists( '_WP_Editors', false ) )
		require_once ABSPATH . WPINC . '/class-wp-editor.php';

	$editor_id = 'content' . $num++;

	$set = array(
		'teeny' => $teeny,
		'tinymce' => $settings ? $settings : true,
		'quicktags' => false
	);

	$set = _WP_Editors::parse_settings($editor_id, $set);
	_WP_Editors::editor_settings($editor_id, $set);
}

/**
 * Preloads TinyMCE dialogs.
 *
 * @deprecated 3.3.0 Use wp_editor()
 * @see wp_editor()
 */
function wp_preload_dialogs() {
	_deprecated_function( __FUNCTION__, '3.3.0', 'wp_editor()' );
}

/**
 * Prints TinyMCE editor JS.
 *
 * @deprecated 3.3.0 Use wp_editor()
 * @see wp_editor()
 */
function wp_print_editor_js() {
	_deprecated_function( __FUNCTION__, '3.3.0', 'wp_editor()' );
}

/**
 * Handles quicktags.
 *
 * @deprecated 3.3.0 Use wp_editor()
 * @see wp_editor()
 */
function wp_quicktags() {
	_deprecated_function( __FUNCTION__, '3.3.0', 'wp_editor()' );
}

/**
 * Returns the screen layout options.
 *
 * @since 2.8.0
 * @deprecated 3.3.0 WP_Screen::render_screen_layout()
 * @see WP_Screen::render_screen_layout()
 */
function screen_layout( $screen ) {
	_deprecated_function( __FUNCTION__, '3.3.0', '$current_screen->render_screen_layout()' );

	$current_screen = get_current_screen();

	if ( ! $current_screen )
		return '';

	ob_start();
	$current_screen->render_screen_layout();
	return ob_get_clean();
}

/**
 * Returns the screen's per-page options.
 *
 * @since 2.8.0
 * @deprecated 3.3.0 Use WP_Screen::render_per_page_options()
 * @see WP_Screen::render_per_page_options()
 */
function screen_options( $screen ) {
	_deprecated_function( __FUNCTION__, '3.3.0', '$current_screen->render_per_page_options()' );

	$current_screen = get_current_screen();

	if ( ! $current_screen )
		return '';

	ob_start();
	$current_screen->render_per_page_options();
	return ob_get_clean();
}

/**
 * Renders the screen's help.
 *
 * @since 2.7.0
 * @deprecated 3.3.0 Use WP_Screen::render_screen_meta()
 * @see WP_Screen::render_screen_meta()
 */
function screen_meta( $screen ) {
	$current_screen = get_current_screen();
	$current_screen->render_screen_meta();
}

/**
 * Favorite actions were deprecated in version 3.2. Use the admin bar instead.
 *
 * @since 2.7.0
 * @deprecated 3.2.0 Use WP_Admin_Bar
 * @see WP_Admin_Bar
 */
function favorite_actions() {
	_deprecated_function( __FUNCTION__, '3.2.0', 'WP_Admin_Bar' );
}

/**
 * Handles uploading an image.
 *
 * @deprecated 3.3.0 Use wp_media_upload_handler()
 * @see wp_media_upload_handler()
 *
 * @return null|string
 */
function media_upload_image() {
	_deprecated_function( __FUNCTION__, '3.3.0', 'wp_media_upload_handler()' );
	return wp_media_upload_handler();
}

/**
 * Handles uploading an audio file.
 *
 * @deprecated 3.3.0 Use wp_media_upload_handler()
 * @see wp_media_upload_handler()
 *
 * @return null|string
 */
function media_upload_audio() {
	_deprecated_function( __FUNCTION__, '3.3.0', 'wp_media_upload_handler()' );
	return wp_media_upload_handler();
}

/**
 * Handles uploading a video file.
 *
 * @deprecated 3.3.0 Use wp_media_upload_handler()
 * @see wp_media_upload_handler()
 *
 * @return null|string
 */
function media_upload_video() {
	_deprecated_function( __FUNCTION__, '3.3.0', 'wp_media_upload_handler()' );
	return wp_media_upload_handler();
}

/**
 * Handles uploading a generic file.
 *
 * @deprecated 3.3.0 Use wp_media_upload_handler()
 * @see wp_media_upload_handler()
 *
 * @return null|string
 */
function media_upload_file() {
	_deprecated_function( __FUNCTION__, '3.3.0', 'wp_media_upload_handler()' );
	return wp_media_upload_handler();
}

/**
 * Handles retrieving the insert-from-URL form for an image.
 *
 * @deprecated 3.3.0 Use wp_media_insert_url_form()
 * @see wp_media_insert_url_form()
 *
 * @return string
 */
function type_url_form_image() {
	_deprecated_function( __FUNCTION__, '3.3.0', "wp_media_insert_url_form('image')" );
	return wp_media_insert_url_form( 'image' );
}

/**
 * Handles retrieving the insert-from-URL form for an audio file.
 *
 * @deprecated 3.3.0 Use wp_media_insert_url_form()
 * @see wp_media_insert_url_form()
 *
 * @return string
 */
function type_url_form_audio() {
	_deprecated_function( __FUNCTION__, '3.3.0', "wp_media_insert_url_form('audio')" );
	return wp_media_insert_url_form( 'audio' );
}

/**
 * Handles retrieving the insert-from-URL form for a video file.
 *
 * @deprecated 3.3.0 Use wp_media_insert_url_form()
 * @see wp_media_insert_url_form()
 *
 * @return string
 */
function type_url_form_video() {
	_deprecated_function( __FUNCTION__, '3.3.0', "wp_media_insert_url_form('video')" );
	return wp_media_insert_url_form( 'video' );
}

/**
 * Handles retrieving the insert-from-URL form for a generic file.
 *
 * @deprecated 3.3.0 Use wp_media_insert_url_form()
 * @see wp_media_insert_url_form()
 *
 * @return string
 */
function type_url_form_file() {
	_deprecated_function( __FUNCTION__, '3.3.0', "wp_media_insert_url_form('file')" );
	return wp_media_insert_url_form( 'file' );
}

/**
 * Add contextual help text for a page.
 *
 * Creates an 'Overview' help tab.
 *
 * @since 2.7.0
 * @deprecated 3.3.0 Use WP_Screen::add_help_tab()
 * @see WP_Screen::add_help_tab()
 *
 * @param string    $screen The handle for the screen to add help to. This is usually
 *                          the hook name returned by the `add_*_page()` functions.
 * @param string    $help   The content of an 'Overview' help tab.
 */
function add_contextual_help( $screen, $help ) {
	_deprecated_function( __FUNCTION__, '3.3.0', 'get_current_screen()->add_help_tab()' );

	if ( is_string( $screen ) )
		$screen = convert_to_screen( $screen );

	WP_Screen::add_old_compat_help( $screen, $help );
}

/**
 * Get the allowed themes for the current site.
 *
 * @since 3.0.0
 * @deprecated 3.4.0 Use wp_get_themes()
 * @see wp_get_themes()
 *
 * @return WP_Theme[] Array of WP_Theme objects keyed by their name.
 */
function get_allowed_themes() {
	_deprecated_function( __FUNCTION__, '3.4.0', "wp_get_themes( array( 'allowed' => true ) )" );

	$themes = wp_get_themes( array( 'allowed' => true ) );

	$wp_themes = array();
	foreach ( $themes as $theme ) {
		$wp_themes[ $theme->get('Name') ] = $theme;
	}

	return $wp_themes;
}

/**
 * Retrieves a list of broken themes.
 *
 * @since 1.5.0
 * @deprecated 3.4.0 Use wp_get_themes()
 * @see wp_get_themes()
 *
 * @return array
 */
function get_broken_themes() {
	_deprecated_function( __FUNCTION__, '3.4.0', "wp_get_themes( array( 'errors' => true )" );

	$themes = wp_get_themes( array( 'errors' => true ) );
	$broken = array();
	foreach ( $themes as $theme ) {
		$name = $theme->get('Name');
		$broken[ $name ] = array(
			'Name' => $name,
			'Title' => $name,
			'Description' => $theme->errors()->get_error_message(),
		);
	}
	return $broken;
}

/**
 * Retrieves information on the current active theme.
 *
 * @since 2.0.0
 * @deprecated 3.4.0 Use wp_get_theme()
 * @see wp_get_theme()
 *
 * @return WP_Theme
 */
function current_theme_info() {
	_deprecated_function( __FUNCTION__, '3.4.0', 'wp_get_theme()' );

	return wp_get_theme();
}

/**
 * This was once used to display an 'Insert into Post' button.
 *
 * Now it is deprecated and stubbed.
 *
 * @deprecated 3.5.0
 */
function _insert_into_post_button( $type ) {
	_deprecated_function( __FUNCTION__, '3.5.0' );
}

/**
 * This was once used to display a media button.
 *
 * Now it is deprecated and stubbed.
 *
 * @deprecated 3.5.0
 */
function _media_button($title, $icon, $type, $id) {
	_deprecated_function( __FUNCTION__, '3.5.0' );
}

/**
 * Gets an existing post and format it for editing.
 *
 * @since 2.0.0
 * @deprecated 3.5.0 Use get_post()
 * @see get_post()
 *
 * @param int $id
 * @return WP_Post
 */
function get_post_to_edit( $id ) {
	_deprecated_function( __FUNCTION__, '3.5.0', 'get_post()' );

	return get_post( $id, OBJECT, 'edit' );
}

/**
 * Gets the default page information to use.
 *
 * @since 2.5.0
 * @deprecated 3.5.0 Use get_default_post_to_edit()
 * @see get_default_post_to_edit()
 *
 * @return WP_Post Post object containing all the default post data as attributes
 */
function get_default_page_to_edit() {
	_deprecated_function( __FUNCTION__, '3.5.0', "get_default_post_to_edit( 'page' )" );

	$page = get_default_post_to_edit();
	$page->post_type = 'page';
	return $page;
}

/**
 * This was once used to create a thumbnail from an Image given a maximum side size.
 *
 * @since 1.2.0
 * @deprecated 3.5.0 Use image_resize()
 * @see image_resize()
 *
 * @param mixed $file Filename of the original image, Or attachment ID.
 * @param int $max_side Maximum length of a single side for the thumbnail.
 * @param mixed $deprecated Never used.
 * @return string Thumbnail path on success, Error string on failure.
 */
function wp_create_thumbnail( $file, $max_side, $deprecated = '' ) {
	_deprecated_function( __FUNCTION__, '3.5.0', 'image_resize()' );
	return apply_filters( 'wp_create_thumbnail', image_resize( $file, $max_side, $max_side ) );
}

/**
 * This was once used to display a meta box for the nav menu theme locations.
 *
 * Deprecated in favor of a 'Manage Locations' tab added to nav menus management screen.
 *
 * @since 3.0.0
 * @deprecated 3.6.0
 */
function wp_nav_menu_locations_meta_box() {
	_deprecated_function( __FUNCTION__, '3.6.0' );
}

/**
 * This was once used to kick-off the Core Updater.
 *
 * Deprecated in favor of instantiating a Core_Upgrader instance directly,
 * and calling the 'upgrade' method.
 *
 * @since 2.7.0
 * @deprecated 3.7.0 Use Core_Upgrader
 * @see Core_Upgrader
 */
function wp_update_core($current, $feedback = '') {
	_deprecated_function( __FUNCTION__, '3.7.0', 'new Core_Upgrader();' );

	if ( !empty($feedback) )
		add_filter('update_feedback', $feedback);

	require ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
	$upgrader = new Core_Upgrader();
	return $upgrader->upgrade($current);

}

/**
 * This was once used to kick-off the Plugin Updater.
 *
 * Deprecated in favor of instantiating a Plugin_Upgrader instance directly,
 * and calling the 'upgrade' method.
 * Unused since 2.8.0.
 *
 * @since 2.5.0
 * @deprecated 3.7.0 Use Plugin_Upgrader
 * @see Plugin_Upgrader
 */
function wp_update_plugin($plugin, $feedback = '') {
	_deprecated_function( __FUNCTION__, '3.7.0', 'new Plugin_Upgrader();' );

	if ( !empty($feedback) )
		add_filter('update_feedback', $feedback);

	require ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
	$upgrader = new Plugin_Upgrader();
	return $upgrader->upgrade($plugin);
}

/**
 * This was once used to kick-off the Theme Updater.
 *
 * Deprecated in favor of instantiating a Theme_Upgrader instance directly,
 * and calling the 'upgrade' method.
 * Unused since 2.8.0.
 *
 * @since 2.7.0
 * @deprecated 3.7.0 Use Theme_Upgrader
 * @see Theme_Upgrader
 */
function wp_update_theme($theme, $feedback = '') {
	_deprecated_function( __FUNCTION__, '3.7.0', 'new Theme_Upgrader();' );

	if ( !empty($feedback) )
		add_filter('update_feedback', $feedback);

	require ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
	$upgrader = new Theme_Upgrader();
	return $upgrader->upgrade($theme);
}

/**
 * This was once used to display attachment links. Now it is deprecated and stubbed.
 *
 * @since 2.0.0
 * @deprecated 3.7.0
 *
 * @param int|bool $id
 */
function the_attachment_links( $id = false ) {
	_deprecated_function( __FUNCTION__, '3.7.0' );
}

/**
 * Displays a screen icon.
 *
 * @since 2.7.0
 * @deprecated 3.8.0
 */
function screen_icon() {
	_deprecated_function( __FUNCTION__, '3.8.0' );
	echo get_screen_icon();
}

/**
 * Retrieves the screen icon (no longer used in 3.8+).
 *
 * @since 3.2.0
 * @deprecated 3.8.0
 *
 * @return string An HTML comment explaining that icons are no longer used.
 */
function get_screen_icon() {
	_deprecated_function( __FUNCTION__, '3.8.0' );
	return '<!-- Screen icons are no longer used as of WordPress 3.8. -->';
}

/**
 * Deprecated dashboard widget controls.
 *
 * @since 2.5.0
 * @deprecated 3.8.0
 */
function wp_dashboard_incoming_links_output() {}

/**
 * Deprecated dashboard secondary output.
 *
 * @deprecated 3.8.0
 */
function wp_dashboard_secondary_output() {}

/**
 * Deprecated dashboard widget controls.
 *
 * @since 2.7.0
 * @deprecated 3.8.0
 */
function wp_dashboard_incoming_links() {}

/**
 * Deprecated dashboard incoming links control.
 *
 * @deprecated 3.8.0
 */
function wp_dashboard_incoming_links_control() {}

/**
 * Deprecated dashboard plugins control.
 *
 * @deprecated 3.8.0
 */
function wp_dashboard_plugins() {}

/**
 * Deprecated dashboard primary control.
 *
 * @deprecated 3.8.0
 */
function wp_dashboard_primary_control() {}

/**
 * Deprecated dashboard recent comments control.
 *
 * @deprecated 3.8.0
 */
function wp_dashboard_recent_comments_control() {}

/**
 * Deprecated dashboard secondary section.
 *
 * @deprecated 3.8.0
 */
function wp_dashboard_secondary() {}

/**
 * Deprecated dashboard secondary control.
 *
 * @deprecated 3.8.0
 */
function wp_dashboard_secondary_control() {}

/**
 * Display plugins text for the WordPress news widget.
 *
 * @since 2.5.0
 * @deprecated 4.8.0
 *
 * @param string $rss  The RSS feed URL.
 * @param array  $args Array of arguments for this RSS feed.
 */
function wp_dashboard_plugins_output( $rss, $args = array() ) {
	_deprecated_function( __FUNCTION__, '4.8.0' );

	// Plugin feeds plus link to install them.
	$popular = fetch_feed( $args['url']['popular'] );

	if ( false === $plugin_slugs = get_transient( 'plugin_slugs' ) ) {
		$plugin_slugs = array_keys( get_plugins() );
		set_transient( 'plugin_slugs', $plugin_slugs, DAY_IN_SECONDS );
	}

	echo '<ul>';

	foreach ( array( $popular ) as $feed ) {
		if ( is_wp_error( $feed ) || ! $feed->get_item_quantity() )
			continue;

		$items = $feed->get_items(0, 5);

		// Pick a random, non-installed plugin.
		while ( true ) {
			// Abort this foreach loop iteration if there's no plugins left of this type.
			if ( 0 === count($items) )
				continue 2;

			$item_key = array_rand($items);
			$item = $items[$item_key];

			list($link, $frag) = explode( '#', $item->get_link() );

			$link = esc_url($link);
			if ( preg_match( '|/([^/]+?)/?$|', $link, $matches ) )
				$slug = $matches[1];
			else {
				unset( $items[$item_key] );
				continue;
			}

			// Is this random plugin's slug already installed? If so, try again.
			reset( $plugin_slugs );
			foreach ( $plugin_slugs as $plugin_slug ) {
				if ( str_starts_with( $plugin_slug, $slug ) ) {
					unset( $items[$item_key] );
					continue 2;
				}
			}

			// If we get to this point, then the random plugin isn't installed and we can stop the while().
			break;
		}

		// Eliminate some common badly formed plugin descriptions.
		while ( ( null !== $item_key = array_rand($items) ) && str_contains( $items[$item_key]->get_description(), 'Plugin Name:' ) )
			unset($items[$item_key]);

		if ( !isset($items[$item_key]) )
			continue;

		$raw_title = $item->get_title();

		$ilink = wp_nonce_url('plugin-install.php?tab=plugin-information&plugin=' . $slug, 'install-plugin_' . $slug) . '&amp;TB_iframe=true&amp;width=600&amp;height=800';
		echo '<li class="dashboard-news-plugin"><span>' . __( 'Popular Plugin' ) . ':</span> ' . esc_html( $raw_title ) .
			'&nbsp;<a href="' . $ilink . '" class="thickbox open-plugin-details-modal" aria-label="' .
			/* translators: %s: Plugin name. */
			esc_attr( sprintf( _x( 'Install %s', 'plugin' ), $raw_title ) ) . '">(' . __( 'Install' ) . ')</a></li>';

		$feed->__destruct();
		unset( $feed );
	}

	echo '</ul>';
}

/**
 * This was once used to move child posts to a new parent.
 *
 * @since 2.3.0
 * @deprecated 3.9.0
 * @access private
 *
 * @param int $old_ID
 * @param int $new_ID
 */
function _relocate_children( $old_ID, $new_ID ) {
	_deprecated_function( __FUNCTION__, '3.9.0' );
}

/**
 * Add a top-level menu page in the 'objects' section.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 2.7.0
 *
 * @deprecated 4.5.0 Use add_menu_page()
 * @see add_menu_page()
 * @global int $_wp_last_object_menu
 *
 * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
 * @param string   $menu_title The text to be used for the menu.
 * @param string   $capability The capability required for this menu to be displayed to the user.
 * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
 * @param callable $callback   Optional. The function to be called to output the content for this page.
 * @param string   $icon_url   Optional. The URL to the icon to be used for this menu.
 * @return string The resulting page's hook_suffix.
 */
function add_object_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $icon_url = '') {
	_deprecated_function( __FUNCTION__, '4.5.0', 'add_menu_page()' );

	global $_wp_last_object_menu;

	$_wp_last_object_menu++;

	return add_menu_page($page_title, $menu_title, $capability, $menu_slug, $callback, $icon_url, $_wp_last_object_menu);
}

/**
 * Add a top-level menu page in the 'utility' section.
 *
 * This function takes a capability which will be used to determine whether
 * or not a page is included in the menu.
 *
 * The function which is hooked in to handle the output of the page must check
 * that the user has the required capability as well.
 *
 * @since 2.7.0
 *
 * @deprecated 4.5.0 Use add_menu_page()
 * @see add_menu_page()
 * @global int $_wp_last_utility_menu
 *
 * @param string   $page_title The text to be displayed in the title tags of the page when the menu is selected.
 * @param string   $menu_title The text to be used for the menu.
 * @param string   $capability The capability required for this menu to be displayed to the user.
 * @param string   $menu_slug  The slug name to refer to this menu by (should be unique for this menu).
 * @param callable $callback   Optional. The function to be called to output the content for this page.
 * @param string   $icon_url   Optional. The URL to the icon to be used for this menu.
 * @return string The resulting page's hook_suffix.
 */
function add_utility_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $icon_url = '') {
	_deprecated_function( __FUNCTION__, '4.5.0', 'add_menu_page()' );

	global $_wp_last_utility_menu;

	$_wp_last_utility_menu++;

	return add_menu_page($page_title, $menu_title, $capability, $menu_slug, $callback, $icon_url, $_wp_last_utility_menu);
}

/**
 * Disables autocomplete on the 'post' form (Add/Edit Post screens) for WebKit browsers,
 * as they disregard the autocomplete setting on the editor textarea. That can break the editor
 * when the user navigates to it with the browser's Back button. See #28037
 *
 * Replaced with wp_page_reload_on_back_button_js() that also fixes this problem.
 *
 * @since 4.0.0
 * @deprecated 4.6.0
 *
 * @link https://core.trac.wordpress.org/ticket/35852
 *
 * @global bool $is_safari
 * @global bool $is_chrome
 */
function post_form_autocomplete_off() {
	global $is_safari, $is_chrome;

	_deprecated_function( __FUNCTION__, '4.6.0' );

	if ( $is_safari || $is_chrome ) {
		echo ' autocomplete="off"';
	}
}

/**
 * Display JavaScript on the page.
 *
 * @since 3.5.0
 * @deprecated 4.9.0
 */
function options_permalink_add_js() {
	?>
	<script type="text/javascript">
		jQuery( function() {
			jQuery('.permalink-structure input:radio').change(function() {
				if ( 'custom' == this.value )
					return;
				jQuery('#permalink_structure').val( this.value );
			});
			jQuery( '#permalink_structure' ).on( 'click input', function() {
				jQuery( '#custom_selection' ).prop( 'checked', true );
			});
		} );
	</script>
	<?php
}

/**
 * Previous class for list table for privacy data export requests.
 *
 * @since 4.9.6
 * @deprecated 5.3.0
 */
class WP_Privacy_Data_Export_Requests_Table extends WP_Privacy_Data_Export_Requests_List_Table {
	function __construct( $args ) {
		_deprecated_function( __CLASS__, '5.3.0', 'WP_Privacy_Data_Export_Requests_List_Table' );

		if ( ! isset( $args['screen'] ) || $args['screen'] === 'export_personal_data' ) {
			$args['screen'] = 'export-personal-data';
		}

		parent::__construct( $args );
	}
}

/**
 * Previous class for list table for privacy data erasure requests.
 *
 * @since 4.9.6
 * @deprecated 5.3.0
 */
class WP_Privacy_Data_Removal_Requests_Table extends WP_Privacy_Data_Removal_Requests_List_Table {
	function __construct( $args ) {
		_deprecated_function( __CLASS__, '5.3.0', 'WP_Privacy_Data_Removal_Requests_List_Table' );

		if ( ! isset( $args['screen'] ) || $args['screen'] === 'remove_personal_data' ) {
			$args['screen'] = 'erase-personal-data';
		}

		parent::__construct( $args );
	}
}

/**
 * Was used to add options for the privacy requests screens before they were separate files.
 *
 * @since 4.9.8
 * @access private
 * @deprecated 5.3.0
 */
function _wp_privacy_requests_screen_options() {
	_deprecated_function( __FUNCTION__, '5.3.0' );
}

/**
 * Was used to filter input from media_upload_form_handler() and to assign a default
 * post_title from the file name if none supplied.
 *
 * @since 2.5.0
 * @deprecated 6.0.0
 *
 * @param array $post       The WP_Post attachment object converted to an array.
 * @param array $attachment An array of attachment metadata.
 * @return array Attachment post object converted to an array.
 */
function image_attachment_fields_to_save( $post, $attachment ) {
	_deprecated_function( __FUNCTION__, '6.0.0' );

	return $post;
}
class-bulk-plugin-upgrader-skin.php000064400000005036151212616050013365 0ustar00<?php
/**
 * Upgrader API: Bulk_Plugin_Upgrader_Skin class
 *
 * @package WordPress
 * @subpackage Upgrader
 * @since 4.6.0
 */

/**
 * Bulk Plugin Upgrader Skin for WordPress Plugin Upgrades.
 *
 * @since 3.0.0
 * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader-skins.php.
 *
 * @see Bulk_Upgrader_Skin
 */
class Bulk_Plugin_Upgrader_Skin extends Bulk_Upgrader_Skin {

	/**
	 * Plugin info.
	 *
	 * The Plugin_Upgrader::bulk_upgrade() method will fill this in
	 * with info retrieved from the get_plugin_data() function.
	 *
	 * @since 3.0.0
	 * @var array Plugin data. Values will be empty if not supplied by the plugin.
	 */
	public $plugin_info = array();

	/**
	 * Sets up the strings used in the update process.
	 *
	 * @since 3.0.0
	 */
	public function add_strings() {
		parent::add_strings();
		/* translators: 1: Plugin name, 2: Number of the plugin, 3: Total number of plugins being updated. */
		$this->upgrader->strings['skin_before_update_header'] = __( 'Updating Plugin %1$s (%2$d/%3$d)' );
	}

	/**
	 * Performs an action before a bulk plugin update.
	 *
	 * @since 3.0.0
	 *
	 * @param string $title
	 */
	public function before( $title = '' ) {
		parent::before( $this->plugin_info['Title'] );
	}

	/**
	 * Performs an action following a bulk plugin update.
	 *
	 * @since 3.0.0
	 *
	 * @param string $title
	 */
	public function after( $title = '' ) {
		parent::after( $this->plugin_info['Title'] );
		$this->decrement_update_count( 'plugin' );
	}

	/**
	 * Displays the footer following the bulk update process.
	 *
	 * @since 3.0.0
	 */
	public function bulk_footer() {
		parent::bulk_footer();

		$update_actions = array(
			'plugins_page' => sprintf(
				'<a href="%s" target="_parent">%s</a>',
				self_admin_url( 'plugins.php' ),
				__( 'Go to Plugins page' )
			),
			'updates_page' => sprintf(
				'<a href="%s" target="_parent">%s</a>',
				self_admin_url( 'update-core.php' ),
				__( 'Go to WordPress Updates page' )
			),
		);

		if ( ! current_user_can( 'activate_plugins' ) ) {
			unset( $update_actions['plugins_page'] );
		}

		/**
		 * Filters the list of action links available following bulk plugin updates.
		 *
		 * @since 3.0.0
		 *
		 * @param string[] $update_actions Array of plugin action links.
		 * @param array    $plugin_info    Array of information for the last-updated plugin.
		 */
		$update_actions = apply_filters( 'update_bulk_plugins_complete_actions', $update_actions, $this->plugin_info );

		if ( ! empty( $update_actions ) ) {
			$this->feedback( implode( ' | ', (array) $update_actions ) );
		}
	}
}
update.php000064400000103205151212616050006537 0ustar00<?php
/**
 * WordPress Administration Update API
 *
 * @package WordPress
 * @subpackage Administration
 */

/**
 * Selects the first update version from the update_core option.
 *
 * @since 2.7.0
 *
 * @return object|array|false The response from the API on success, false on failure.
 */
function get_preferred_from_update_core() {
	$updates = get_core_updates();

	if ( ! is_array( $updates ) ) {
		return false;
	}

	if ( empty( $updates ) ) {
		return (object) array( 'response' => 'latest' );
	}

	return $updates[0];
}

/**
 * Gets available core updates.
 *
 * @since 2.7.0
 *
 * @param array $options Set $options['dismissed'] to true to show dismissed upgrades too,
 *                       set $options['available'] to false to skip not-dismissed updates.
 * @return array|false Array of the update objects on success, false on failure.
 */
function get_core_updates( $options = array() ) {
	$options = array_merge(
		array(
			'available' => true,
			'dismissed' => false,
		),
		$options
	);

	$dismissed = get_site_option( 'dismissed_update_core' );

	if ( ! is_array( $dismissed ) ) {
		$dismissed = array();
	}

	$from_api = get_site_transient( 'update_core' );

	if ( ! isset( $from_api->updates ) || ! is_array( $from_api->updates ) ) {
		return false;
	}

	$updates = $from_api->updates;
	$result  = array();

	foreach ( $updates as $update ) {
		if ( 'autoupdate' === $update->response ) {
			continue;
		}

		if ( array_key_exists( $update->current . '|' . $update->locale, $dismissed ) ) {
			if ( $options['dismissed'] ) {
				$update->dismissed = true;
				$result[]          = $update;
			}
		} else {
			if ( $options['available'] ) {
				$update->dismissed = false;
				$result[]          = $update;
			}
		}
	}

	return $result;
}

/**
 * Gets the best available (and enabled) Auto-Update for WordPress core.
 *
 * If there's 1.2.3 and 1.3 on offer, it'll choose 1.3 if the installation allows it, else, 1.2.3.
 *
 * @since 3.7.0
 *
 * @return object|false The core update offering on success, false on failure.
 */
function find_core_auto_update() {
	$updates = get_site_transient( 'update_core' );

	if ( ! $updates || empty( $updates->updates ) ) {
		return false;
	}

	require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';

	$auto_update = false;
	$upgrader    = new WP_Automatic_Updater();

	foreach ( $updates->updates as $update ) {
		if ( 'autoupdate' !== $update->response ) {
			continue;
		}

		if ( ! $upgrader->should_update( 'core', $update, ABSPATH ) ) {
			continue;
		}

		if ( ! $auto_update || version_compare( $update->current, $auto_update->current, '>' ) ) {
			$auto_update = $update;
		}
	}

	return $auto_update;
}

/**
 * Gets and caches the checksums for the given version of WordPress.
 *
 * @since 3.7.0
 *
 * @param string $version Version string to query.
 * @param string $locale  Locale to query.
 * @return array|false An array of checksums on success, false on failure.
 */
function get_core_checksums( $version, $locale ) {
	$http_url = 'http://api.wordpress.org/core/checksums/1.0/?' . http_build_query( compact( 'version', 'locale' ), '', '&' );
	$url      = $http_url;

	$ssl = wp_http_supports( array( 'ssl' ) );

	if ( $ssl ) {
		$url = set_url_scheme( $url, 'https' );
	}

	$options = array(
		'timeout' => wp_doing_cron() ? 30 : 3,
	);

	$response = wp_remote_get( $url, $options );

	if ( $ssl && is_wp_error( $response ) ) {
		wp_trigger_error(
			__FUNCTION__,
			sprintf(
				/* translators: %s: Support forums URL. */
				__( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.' ),
				__( 'https://wordpress.org/support/forums/' )
			) . ' ' . __( '(WordPress could not establish a secure connection to WordPress.org. Please contact your server administrator.)' ),
			headers_sent() || WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE
		);

		$response = wp_remote_get( $http_url, $options );
	}

	if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
		return false;
	}

	$body = trim( wp_remote_retrieve_body( $response ) );
	$body = json_decode( $body, true );

	if ( ! is_array( $body ) || ! isset( $body['checksums'] ) || ! is_array( $body['checksums'] ) ) {
		return false;
	}

	return $body['checksums'];
}

/**
 * Dismisses core update.
 *
 * @since 2.7.0
 *
 * @param object $update
 * @return bool
 */
function dismiss_core_update( $update ) {
	$dismissed = get_site_option( 'dismissed_update_core' );
	$dismissed[ $update->current . '|' . $update->locale ] = true;

	return update_site_option( 'dismissed_update_core', $dismissed );
}

/**
 * Undismisses core update.
 *
 * @since 2.7.0
 *
 * @param string $version
 * @param string $locale
 * @return bool
 */
function undismiss_core_update( $version, $locale ) {
	$dismissed = get_site_option( 'dismissed_update_core' );
	$key       = $version . '|' . $locale;

	if ( ! isset( $dismissed[ $key ] ) ) {
		return false;
	}

	unset( $dismissed[ $key ] );

	return update_site_option( 'dismissed_update_core', $dismissed );
}

/**
 * Finds the available update for WordPress core.
 *
 * @since 2.7.0
 *
 * @param string $version Version string to find the update for.
 * @param string $locale  Locale to find the update for.
 * @return object|false The core update offering on success, false on failure.
 */
function find_core_update( $version, $locale ) {
	$from_api = get_site_transient( 'update_core' );

	if ( ! isset( $from_api->updates ) || ! is_array( $from_api->updates ) ) {
		return false;
	}

	$updates = $from_api->updates;

	foreach ( $updates as $update ) {
		if ( $update->current === $version && $update->locale === $locale ) {
			return $update;
		}
	}

	return false;
}

/**
 * Returns core update footer message.
 *
 * @since 2.3.0
 *
 * @param string $msg
 * @return string
 */
function core_update_footer( $msg = '' ) {
	if ( ! current_user_can( 'update_core' ) ) {
		/* translators: %s: WordPress version. */
		return sprintf( __( 'Version %s' ), get_bloginfo( 'version', 'display' ) );
	}

	$cur = get_preferred_from_update_core();

	if ( ! is_object( $cur ) ) {
		$cur = new stdClass();
	}

	if ( ! isset( $cur->current ) ) {
		$cur->current = '';
	}

	if ( ! isset( $cur->response ) ) {
		$cur->response = '';
	}

	$is_development_version = preg_match( '/alpha|beta|RC/', wp_get_wp_version() );

	if ( $is_development_version ) {
		return sprintf(
			/* translators: 1: WordPress version number, 2: URL to WordPress Updates screen. */
			__( 'You are using a development version (%1$s). Cool! Please <a href="%2$s">stay updated</a>.' ),
			get_bloginfo( 'version', 'display' ),
			network_admin_url( 'update-core.php' )
		);
	}

	switch ( $cur->response ) {
		case 'upgrade':
			return sprintf(
				'<strong><a href="%s">%s</a></strong>',
				network_admin_url( 'update-core.php' ),
				/* translators: %s: WordPress version. */
				sprintf( __( 'Get Version %s' ), $cur->current )
			);

		case 'latest':
		default:
			/* translators: %s: WordPress version. */
			return sprintf( __( 'Version %s' ), get_bloginfo( 'version', 'display' ) );
	}
}

/**
 * Returns core update notification message.
 *
 * @since 2.3.0
 *
 * @global string $pagenow The filename of the current screen.
 * @return void|false
 */
function update_nag() {
	global $pagenow;

	if ( is_multisite() && ! current_user_can( 'update_core' ) ) {
		return false;
	}

	if ( 'update-core.php' === $pagenow ) {
		return;
	}

	$cur = get_preferred_from_update_core();

	if ( ! isset( $cur->response ) || 'upgrade' !== $cur->response ) {
		return false;
	}

	$version_url = sprintf(
		/* translators: %s: WordPress version. */
		esc_url( __( 'https://wordpress.org/documentation/wordpress-version/version-%s/' ) ),
		sanitize_title( $cur->current )
	);

	if ( current_user_can( 'update_core' ) ) {
		$msg = sprintf(
			/* translators: 1: URL to WordPress release notes, 2: New WordPress version, 3: URL to network admin, 4: Accessibility text. */
			__( '<a href="%1$s">WordPress %2$s</a> is available! <a href="%3$s" aria-label="%4$s">Please update now</a>.' ),
			$version_url,
			$cur->current,
			network_admin_url( 'update-core.php' ),
			esc_attr__( 'Please update WordPress now' )
		);
	} else {
		$msg = sprintf(
			/* translators: 1: URL to WordPress release notes, 2: New WordPress version. */
			__( '<a href="%1$s">WordPress %2$s</a> is available! Please notify the site administrator.' ),
			$version_url,
			$cur->current
		);
	}

	wp_admin_notice(
		$msg,
		array(
			'type'               => 'warning',
			'additional_classes' => array( 'update-nag', 'inline' ),
			'paragraph_wrap'     => false,
		)
	);
}

/**
 * Displays WordPress version and active theme in the 'At a Glance' dashboard widget.
 *
 * @since 2.5.0
 */
function update_right_now_message() {
	$theme_name = wp_get_theme();

	if ( current_user_can( 'switch_themes' ) ) {
		$theme_name = sprintf( '<a href="themes.php">%1$s</a>', $theme_name );
	}

	$msg = '';

	if ( current_user_can( 'update_core' ) ) {
		$cur = get_preferred_from_update_core();

		if ( isset( $cur->response ) && 'upgrade' === $cur->response ) {
			$msg .= sprintf(
				'<a href="%s" class="button" aria-describedby="wp-version">%s</a> ',
				network_admin_url( 'update-core.php' ),
				/* translators: %s: WordPress version number, or 'Latest' string. */
				sprintf( __( 'Update to %s' ), $cur->current ? $cur->current : __( 'Latest' ) )
			);
		}
	}

	/* translators: 1: Version number, 2: Theme name. */
	$content = __( 'WordPress %1$s running %2$s theme.' );

	/**
	 * Filters the text displayed in the 'At a Glance' dashboard widget.
	 *
	 * Prior to 3.8.0, the widget was named 'Right Now'.
	 *
	 * @since 4.4.0
	 *
	 * @param string $content Default text.
	 */
	$content = apply_filters( 'update_right_now_text', $content );

	$msg .= sprintf( '<span id="wp-version">' . $content . '</span>', get_bloginfo( 'version', 'display' ), $theme_name );

	echo "<p id='wp-version-message'>$msg</p>";
}

/**
 * Retrieves plugins with updates available.
 *
 * @since 2.9.0
 *
 * @return object[]
 */
function get_plugin_updates() {
	$all_plugins     = get_plugins();
	$upgrade_plugins = array();
	$current         = get_site_transient( 'update_plugins' );

	foreach ( (array) $all_plugins as $plugin_file => $plugin_data ) {
		if ( isset( $current->response[ $plugin_file ] ) ) {
			$upgrade_plugins[ $plugin_file ]         = (object) $plugin_data;
			$upgrade_plugins[ $plugin_file ]->update = $current->response[ $plugin_file ];
		}
	}

	return $upgrade_plugins;
}

/**
 * Adds a callback to display update information for plugins with updates available.
 *
 * @since 2.9.0
 */
function wp_plugin_update_rows() {
	if ( ! current_user_can( 'update_plugins' ) ) {
		return;
	}

	$plugins = get_site_transient( 'update_plugins' );

	if ( isset( $plugins->response ) && is_array( $plugins->response ) ) {
		$plugins = array_keys( $plugins->response );

		foreach ( $plugins as $plugin_file ) {
			add_action( "after_plugin_row_{$plugin_file}", 'wp_plugin_update_row', 10, 2 );
		}
	}
}

/**
 * Displays update information for a plugin.
 *
 * @since 2.3.0
 *
 * @param string $file        Plugin basename.
 * @param array  $plugin_data Plugin information.
 * @return void|false
 */
function wp_plugin_update_row( $file, $plugin_data ) {
	$current = get_site_transient( 'update_plugins' );

	if ( ! isset( $current->response[ $file ] ) ) {
		return false;
	}

	$response = $current->response[ $file ];

	$plugins_allowedtags = array(
		'a'       => array(
			'href'  => array(),
			'title' => array(),
		),
		'abbr'    => array( 'title' => array() ),
		'acronym' => array( 'title' => array() ),
		'code'    => array(),
		'em'      => array(),
		'strong'  => array(),
	);

	$plugin_name = wp_kses( $plugin_data['Name'], $plugins_allowedtags );
	$plugin_slug = isset( $response->slug ) ? $response->slug : $response->id;

	if ( isset( $response->slug ) ) {
		$details_url = self_admin_url( 'plugin-install.php?tab=plugin-information&plugin=' . $plugin_slug . '&section=changelog' );
	} elseif ( isset( $response->url ) ) {
		$details_url = $response->url;
	} else {
		$details_url = $plugin_data['PluginURI'];
	}

	$details_url = add_query_arg(
		array(
			'TB_iframe' => 'true',
			'width'     => 600,
			'height'    => 800,
		),
		$details_url
	);

	/** @var WP_Plugins_List_Table $wp_list_table */
	$wp_list_table = _get_list_table(
		'WP_Plugins_List_Table',
		array(
			'screen' => get_current_screen(),
		)
	);

	if ( is_network_admin() || ! is_multisite() ) {
		if ( is_network_admin() ) {
			$active_class = is_plugin_active_for_network( $file ) ? ' active' : '';
		} else {
			$active_class = is_plugin_active( $file ) ? ' active' : '';
		}

		$requires_php   = isset( $response->requires_php ) ? $response->requires_php : null;
		$compatible_php = is_php_version_compatible( $requires_php );
		$notice_type    = $compatible_php ? 'notice-warning' : 'notice-error';

		printf(
			'<tr class="plugin-update-tr%s" id="%s" data-slug="%s" data-plugin="%s">' .
			'<td colspan="%s" class="plugin-update colspanchange">' .
			'<div class="update-message notice inline %s notice-alt"><p>',
			$active_class,
			esc_attr( $plugin_slug . '-update' ),
			esc_attr( $plugin_slug ),
			esc_attr( $file ),
			esc_attr( $wp_list_table->get_column_count() ),
			$notice_type
		);

		if ( ! current_user_can( 'update_plugins' ) ) {
			printf(
				/* translators: 1: Plugin name, 2: Details URL, 3: Additional link attributes, 4: Version number. */
				__( 'There is a new version of %1$s available. <a href="%2$s" %3$s>View version %4$s details</a>.' ),
				$plugin_name,
				esc_url( $details_url ),
				sprintf(
					'class="thickbox open-plugin-details-modal" aria-label="%s"',
					/* translators: 1: Plugin name, 2: Version number. */
					esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $plugin_name, $response->new_version ) )
				),
				esc_attr( $response->new_version )
			);
		} elseif ( empty( $response->package ) ) {
			printf(
				/* translators: 1: Plugin name, 2: Details URL, 3: Additional link attributes, 4: Version number. */
				__( 'There is a new version of %1$s available. <a href="%2$s" %3$s>View version %4$s details</a>. <em>Automatic update is unavailable for this plugin.</em>' ),
				$plugin_name,
				esc_url( $details_url ),
				sprintf(
					'class="thickbox open-plugin-details-modal" aria-label="%s"',
					/* translators: 1: Plugin name, 2: Version number. */
					esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $plugin_name, $response->new_version ) )
				),
				esc_attr( $response->new_version )
			);
		} else {
			if ( $compatible_php ) {
				printf(
					/* translators: 1: Plugin name, 2: Details URL, 3: Additional link attributes, 4: Version number, 5: Update URL, 6: Additional link attributes. */
					__( 'There is a new version of %1$s available. <a href="%2$s" %3$s>View version %4$s details</a> or <a href="%5$s" %6$s>update now</a>.' ),
					$plugin_name,
					esc_url( $details_url ),
					sprintf(
						'class="thickbox open-plugin-details-modal" aria-label="%s"',
						/* translators: 1: Plugin name, 2: Version number. */
						esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $plugin_name, $response->new_version ) )
					),
					esc_attr( $response->new_version ),
					wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $file, 'upgrade-plugin_' . $file ),
					sprintf(
						'class="update-link" aria-label="%s"',
						/* translators: %s: Plugin name. */
						esc_attr( sprintf( _x( 'Update %s now', 'plugin' ), $plugin_name ) )
					)
				);
			} else {
				printf(
					/* translators: 1: Plugin name, 2: Details URL, 3: Additional link attributes, 4: Version number 5: URL to Update PHP page. */
					__( 'There is a new version of %1$s available, but it does not work with your version of PHP. <a href="%2$s" %3$s>View version %4$s details</a> or <a href="%5$s">learn more about updating PHP</a>.' ),
					$plugin_name,
					esc_url( $details_url ),
					sprintf(
						'class="thickbox open-plugin-details-modal" aria-label="%s"',
						/* translators: 1: Plugin name, 2: Version number. */
						esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $plugin_name, $response->new_version ) )
					),
					esc_attr( $response->new_version ),
					esc_url( wp_get_update_php_url() )
				);
				wp_update_php_annotation( '<br><em>', '</em>' );
			}
		}

		/**
		 * Fires at the end of the update message container in each
		 * row of the plugins list table.
		 *
		 * The dynamic portion of the hook name, `$file`, refers to the path
		 * of the plugin's primary file relative to the plugins directory.
		 *
		 * @since 2.8.0
		 *
		 * @param array  $plugin_data An array of plugin metadata. See get_plugin_data()
		 *                            and the {@see 'plugin_row_meta'} filter for the list
		 *                            of possible values.
		 * @param object $response {
		 *     An object of metadata about the available plugin update.
		 *
		 *     @type string   $id           Plugin ID, e.g. `w.org/plugins/[plugin-name]`.
		 *     @type string   $slug         Plugin slug.
		 *     @type string   $plugin       Plugin basename.
		 *     @type string   $new_version  New plugin version.
		 *     @type string   $url          Plugin URL.
		 *     @type string   $package      Plugin update package URL.
		 *     @type string[] $icons        An array of plugin icon URLs.
		 *     @type string[] $banners      An array of plugin banner URLs.
		 *     @type string[] $banners_rtl  An array of plugin RTL banner URLs.
		 *     @type string   $requires     The version of WordPress which the plugin requires.
		 *     @type string   $tested       The version of WordPress the plugin is tested against.
		 *     @type string   $requires_php The version of PHP which the plugin requires.
		 * }
		 */
		do_action( "in_plugin_update_message-{$file}", $plugin_data, $response ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores

		echo '</p></div></td></tr>';
	}
}

/**
 * Retrieves themes with updates available.
 *
 * @since 2.9.0
 *
 * @return WP_Theme[]
 */
function get_theme_updates() {
	$current = get_site_transient( 'update_themes' );

	if ( ! isset( $current->response ) ) {
		return array();
	}

	$update_themes = array();

	foreach ( $current->response as $stylesheet => $data ) {
		$update_themes[ $stylesheet ]         = wp_get_theme( $stylesheet );
		$update_themes[ $stylesheet ]->update = $data;
	}

	return $update_themes;
}

/**
 * Adds a callback to display update information for themes with updates available.
 *
 * @since 3.1.0
 */
function wp_theme_update_rows() {
	if ( ! current_user_can( 'update_themes' ) ) {
		return;
	}

	$themes = get_site_transient( 'update_themes' );

	if ( isset( $themes->response ) && is_array( $themes->response ) ) {
		$themes = array_keys( $themes->response );

		foreach ( $themes as $theme ) {
			add_action( "after_theme_row_{$theme}", 'wp_theme_update_row', 10, 2 );
		}
	}
}

/**
 * Displays update information for a theme.
 *
 * @since 3.1.0
 *
 * @param string   $theme_key Theme stylesheet.
 * @param WP_Theme $theme     Theme object.
 * @return void|false
 */
function wp_theme_update_row( $theme_key, $theme ) {
	$current = get_site_transient( 'update_themes' );

	if ( ! isset( $current->response[ $theme_key ] ) ) {
		return false;
	}

	$response = $current->response[ $theme_key ];

	$details_url = add_query_arg(
		array(
			'TB_iframe' => 'true',
			'width'     => 1024,
			'height'    => 800,
		),
		$current->response[ $theme_key ]['url']
	);

	/** @var WP_MS_Themes_List_Table $wp_list_table */
	$wp_list_table = _get_list_table( 'WP_MS_Themes_List_Table' );

	$active = $theme->is_allowed( 'network' ) ? ' active' : '';

	$requires_wp  = isset( $response['requires'] ) ? $response['requires'] : null;
	$requires_php = isset( $response['requires_php'] ) ? $response['requires_php'] : null;

	$compatible_wp  = is_wp_version_compatible( $requires_wp );
	$compatible_php = is_php_version_compatible( $requires_php );

	printf(
		'<tr class="plugin-update-tr%s" id="%s" data-slug="%s">' .
		'<td colspan="%s" class="plugin-update colspanchange">' .
		'<div class="update-message notice inline notice-warning notice-alt"><p>',
		$active,
		esc_attr( $theme->get_stylesheet() . '-update' ),
		esc_attr( $theme->get_stylesheet() ),
		$wp_list_table->get_column_count()
	);

	if ( $compatible_wp && $compatible_php ) {
		if ( ! current_user_can( 'update_themes' ) ) {
			printf(
				/* translators: 1: Theme name, 2: Details URL, 3: Additional link attributes, 4: Version number. */
				__( 'There is a new version of %1$s available. <a href="%2$s" %3$s>View version %4$s details</a>.' ),
				$theme['Name'],
				esc_url( $details_url ),
				sprintf(
					'class="thickbox open-plugin-details-modal" aria-label="%s"',
					/* translators: 1: Theme name, 2: Version number. */
					esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme['Name'], $response['new_version'] ) )
				),
				$response['new_version']
			);
		} elseif ( empty( $response['package'] ) ) {
			printf(
				/* translators: 1: Theme name, 2: Details URL, 3: Additional link attributes, 4: Version number. */
				__( 'There is a new version of %1$s available. <a href="%2$s" %3$s>View version %4$s details</a>. <em>Automatic update is unavailable for this theme.</em>' ),
				$theme['Name'],
				esc_url( $details_url ),
				sprintf(
					'class="thickbox open-plugin-details-modal" aria-label="%s"',
					/* translators: 1: Theme name, 2: Version number. */
					esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme['Name'], $response['new_version'] ) )
				),
				$response['new_version']
			);
		} else {
			printf(
				/* translators: 1: Theme name, 2: Details URL, 3: Additional link attributes, 4: Version number, 5: Update URL, 6: Additional link attributes. */
				__( 'There is a new version of %1$s available. <a href="%2$s" %3$s>View version %4$s details</a> or <a href="%5$s" %6$s>update now</a>.' ),
				$theme['Name'],
				esc_url( $details_url ),
				sprintf(
					'class="thickbox open-plugin-details-modal" aria-label="%s"',
					/* translators: 1: Theme name, 2: Version number. */
					esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $theme['Name'], $response['new_version'] ) )
				),
				$response['new_version'],
				wp_nonce_url( self_admin_url( 'update.php?action=upgrade-theme&theme=' ) . $theme_key, 'upgrade-theme_' . $theme_key ),
				sprintf(
					'class="update-link" aria-label="%s"',
					/* translators: %s: Theme name. */
					esc_attr( sprintf( _x( 'Update %s now', 'theme' ), $theme['Name'] ) )
				)
			);
		}
	} else {
		if ( ! $compatible_wp && ! $compatible_php ) {
			printf(
				/* translators: %s: Theme name. */
				__( 'There is a new version of %s available, but it does not work with your versions of WordPress and PHP.' ),
				$theme['Name']
			);
			if ( current_user_can( 'update_core' ) && current_user_can( 'update_php' ) ) {
				printf(
					/* translators: 1: URL to WordPress Updates screen, 2: URL to Update PHP page. */
					' ' . __( '<a href="%1$s">Please update WordPress</a>, and then <a href="%2$s">learn more about updating PHP</a>.' ),
					self_admin_url( 'update-core.php' ),
					esc_url( wp_get_update_php_url() )
				);
				wp_update_php_annotation( '</p><p><em>', '</em>' );
			} elseif ( current_user_can( 'update_core' ) ) {
				printf(
					/* translators: %s: URL to WordPress Updates screen. */
					' ' . __( '<a href="%s">Please update WordPress</a>.' ),
					self_admin_url( 'update-core.php' )
				);
			} elseif ( current_user_can( 'update_php' ) ) {
				printf(
					/* translators: %s: URL to Update PHP page. */
					' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
					esc_url( wp_get_update_php_url() )
				);
				wp_update_php_annotation( '</p><p><em>', '</em>' );
			}
		} elseif ( ! $compatible_wp ) {
			printf(
				/* translators: %s: Theme name. */
				__( 'There is a new version of %s available, but it does not work with your version of WordPress.' ),
				$theme['Name']
			);
			if ( current_user_can( 'update_core' ) ) {
				printf(
					/* translators: %s: URL to WordPress Updates screen. */
					' ' . __( '<a href="%s">Please update WordPress</a>.' ),
					self_admin_url( 'update-core.php' )
				);
			}
		} elseif ( ! $compatible_php ) {
			printf(
				/* translators: %s: Theme name. */
				__( 'There is a new version of %s available, but it does not work with your version of PHP.' ),
				$theme['Name']
			);
			if ( current_user_can( 'update_php' ) ) {
				printf(
					/* translators: %s: URL to Update PHP page. */
					' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
					esc_url( wp_get_update_php_url() )
				);
				wp_update_php_annotation( '</p><p><em>', '</em>' );
			}
		}
	}

	/**
	 * Fires at the end of the update message container in each
	 * row of the themes list table.
	 *
	 * The dynamic portion of the hook name, `$theme_key`, refers to
	 * the theme slug as found in the WordPress.org themes repository.
	 *
	 * @since 3.1.0
	 *
	 * @param WP_Theme $theme    The WP_Theme object.
	 * @param array    $response {
	 *     An array of metadata about the available theme update.
	 *
	 *     @type string $new_version New theme version.
	 *     @type string $url         Theme URL.
	 *     @type string $package     Theme update package URL.
	 * }
	 */
	do_action( "in_theme_update_message-{$theme_key}", $theme, $response ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores

	echo '</p></div></td></tr>';
}

/**
 * Displays maintenance nag HTML message.
 *
 * @since 2.7.0
 *
 * @global int $upgrading
 *
 * @return void|false
 */
function maintenance_nag() {
	global $upgrading;

	$nag = isset( $upgrading );

	if ( ! $nag ) {
		$failed = get_site_option( 'auto_core_update_failed' );
		/*
		 * If an update failed critically, we may have copied over version.php but not other files.
		 * In that case, if the installation claims we're running the version we attempted, nag.
		 * This is serious enough to err on the side of nagging.
		 *
		 * If we simply failed to update before we tried to copy any files, then assume things are
		 * OK if they are now running the latest.
		 *
		 * This flag is cleared whenever a successful update occurs using Core_Upgrader.
		 */
		$comparison = ! empty( $failed['critical'] ) ? '>=' : '>';
		if ( isset( $failed['attempted'] ) && version_compare( $failed['attempted'], wp_get_wp_version(), $comparison ) ) {
			$nag = true;
		}
	}

	if ( ! $nag ) {
		return false;
	}

	if ( current_user_can( 'update_core' ) ) {
		$msg = sprintf(
			/* translators: %s: URL to WordPress Updates screen. */
			__( 'An automated WordPress update has failed to complete - <a href="%s">please attempt the update again now</a>.' ),
			'update-core.php'
		);
	} else {
		$msg = __( 'An automated WordPress update has failed to complete! Please notify the site administrator.' );
	}

	wp_admin_notice(
		$msg,
		array(
			'type'               => 'warning',
			'additional_classes' => array( 'update-nag', 'inline' ),
			'paragraph_wrap'     => false,
		)
	);
}

/**
 * Prints the JavaScript templates for update admin notices.
 *
 * @since 4.6.0
 *
 * Template takes one argument with four values:
 *
 *     param {object} data {
 *         Arguments for admin notice.
 *
 *         @type string id        ID of the notice.
 *         @type string className Class names for the notice.
 *         @type string message   The notice's message.
 *         @type string type      The type of update the notice is for. Either 'plugin' or 'theme'.
 *     }
 */
function wp_print_admin_notice_templates() {
	?>
	<script id="tmpl-wp-updates-admin-notice" type="text/html">
		<div <# if ( data.id ) { #>id="{{ data.id }}"<# } #> class="notice {{ data.className }}"><p>{{{ data.message }}}</p></div>
	</script>
	<script id="tmpl-wp-bulk-updates-admin-notice" type="text/html">
		<div id="{{ data.id }}" class="{{ data.className }} notice <# if ( data.errorMessage ) { #>notice-error<# } else { #>notice-success<# } #>">
			<p>
				<# if ( data.successMessage ) { #>
					{{{ data.successMessage }}}
				<# } #>
				<# if ( data.errorMessage ) { #>
					<button class="button-link bulk-action-errors-collapsed" aria-expanded="false">
						{{{ data.errorMessage }}}
						<span class="screen-reader-text">
							<?php
							/* translators: Hidden accessibility text. */
							_e( 'Show more details' );
							?>
						</span>
						<span class="toggle-indicator" aria-hidden="true"></span>
					</button>
				<# } #>
			</p>
			<# if ( data.errorMessages ) { #>
				<ul class="bulk-action-errors hidden">
					<# _.each( data.errorMessages, function( errorMessage ) { #>
						<li>{{ errorMessage }}</li>
					<# } ); #>
				</ul>
			<# } #>
		</div>
	</script>
	<?php
}

/**
 * Prints the JavaScript templates for update and deletion rows in list tables.
 *
 * @since 4.6.0
 *
 * The update template takes one argument with four values:
 *
 *     param {object} data {
 *         Arguments for the update row
 *
 *         @type string slug    Plugin slug.
 *         @type string plugin  Plugin base name.
 *         @type string colspan The number of table columns this row spans.
 *         @type string content The row content.
 *     }
 *
 * The delete template takes one argument with four values:
 *
 *     param {object} data {
 *         Arguments for the update row
 *
 *         @type string slug    Plugin slug.
 *         @type string plugin  Plugin base name.
 *         @type string name    Plugin name.
 *         @type string colspan The number of table columns this row spans.
 *     }
 */
function wp_print_update_row_templates() {
	?>
	<script id="tmpl-item-update-row" type="text/template">
		<tr class="plugin-update-tr update" id="{{ data.slug }}-update" data-slug="{{ data.slug }}" <# if ( data.plugin ) { #>data-plugin="{{ data.plugin }}"<# } #>>
			<td colspan="{{ data.colspan }}" class="plugin-update colspanchange">
				{{{ data.content }}}
			</td>
		</tr>
	</script>
	<script id="tmpl-item-deleted-row" type="text/template">
		<tr class="plugin-deleted-tr inactive deleted" id="{{ data.slug }}-deleted" data-slug="{{ data.slug }}" <# if ( data.plugin ) { #>data-plugin="{{ data.plugin }}"<# } #>>
			<td colspan="{{ data.colspan }}" class="plugin-update colspanchange">
				<# if ( data.plugin ) { #>
					<?php
					printf(
						/* translators: %s: Plugin name. */
						_x( '%s was successfully deleted.', 'plugin' ),
						'<strong>{{{ data.name }}}</strong>'
					);
					?>
				<# } else { #>
					<?php
					printf(
						/* translators: %s: Theme name. */
						_x( '%s was successfully deleted.', 'theme' ),
						'<strong>{{{ data.name }}}</strong>'
					);
					?>
				<# } #>
			</td>
		</tr>
	</script>
	<?php
}

/**
 * Displays a notice when the user is in recovery mode.
 *
 * @since 5.2.0
 */
function wp_recovery_mode_nag() {
	if ( ! wp_is_recovery_mode() ) {
		return;
	}

	$url = wp_login_url();
	$url = add_query_arg( 'action', WP_Recovery_Mode::EXIT_ACTION, $url );
	$url = wp_nonce_url( $url, WP_Recovery_Mode::EXIT_ACTION );

	$message = sprintf(
		/* translators: %s: Recovery Mode exit link. */
		__( 'You are in recovery mode. This means there may be an error with a theme or plugin. To exit recovery mode, log out or use the Exit button. <a href="%s">Exit Recovery Mode</a>' ),
		esc_url( $url )
	);
	wp_admin_notice( $message, array( 'type' => 'info' ) );
}

/**
 * Checks whether auto-updates are enabled.
 *
 * @since 5.5.0
 *
 * @param string $type The type of update being checked: Either 'theme' or 'plugin'.
 * @return bool True if auto-updates are enabled for `$type`, false otherwise.
 */
function wp_is_auto_update_enabled_for_type( $type ) {
	if ( ! class_exists( 'WP_Automatic_Updater' ) ) {
		require_once ABSPATH . 'wp-admin/includes/class-wp-automatic-updater.php';
	}

	$updater = new WP_Automatic_Updater();
	$enabled = ! $updater->is_disabled();

	switch ( $type ) {
		case 'plugin':
			/**
			 * Filters whether plugins auto-update is enabled.
			 *
			 * @since 5.5.0
			 *
			 * @param bool $enabled True if plugins auto-update is enabled, false otherwise.
			 */
			return apply_filters( 'plugins_auto_update_enabled', $enabled );
		case 'theme':
			/**
			 * Filters whether themes auto-update is enabled.
			 *
			 * @since 5.5.0
			 *
			 * @param bool $enabled True if themes auto-update is enabled, false otherwise.
			 */
			return apply_filters( 'themes_auto_update_enabled', $enabled );
	}

	return false;
}

/**
 * Checks whether auto-updates are forced for an item.
 *
 * @since 5.6.0
 *
 * @param string    $type   The type of update being checked: Either 'theme' or 'plugin'.
 * @param bool|null $update Whether to update. The value of null is internally used
 *                          to detect whether nothing has hooked into this filter.
 * @param object    $item   The update offer.
 * @return bool True if auto-updates are forced for `$item`, false otherwise.
 */
function wp_is_auto_update_forced_for_item( $type, $update, $item ) {
	/** This filter is documented in wp-admin/includes/class-wp-automatic-updater.php */
	return apply_filters( "auto_update_{$type}", $update, $item );
}

/**
 * Determines the appropriate auto-update message to be displayed.
 *
 * @since 5.5.0
 *
 * @return string The update message to be shown.
 */
function wp_get_auto_update_message() {
	$next_update_time = wp_next_scheduled( 'wp_version_check' );

	// Check if the event exists.
	if ( false === $next_update_time ) {
		$message = __( 'Automatic update not scheduled. There may be a problem with WP-Cron.' );
	} else {
		$time_to_next_update = human_time_diff( (int) $next_update_time );

		// See if cron is overdue.
		$overdue = ( time() - $next_update_time ) > 0;

		if ( $overdue ) {
			$message = sprintf(
				/* translators: %s: Duration that WP-Cron has been overdue. */
				__( 'Automatic update overdue by %s. There may be a problem with WP-Cron.' ),
				$time_to_next_update
			);
		} else {
			$message = sprintf(
				/* translators: %s: Time until the next update. */
				__( 'Automatic update scheduled in %s.' ),
				$time_to_next_update
			);
		}
	}

	return $message;
}
noop.php000064400000002174151212616050006233 0ustar00<?php
/**
 * Noop functions for load-scripts.php and load-styles.php.
 *
 * @package WordPress
 * @subpackage Administration
 * @since 4.4.0
 */

/**
 * @ignore
 */
function __() {}

/**
 * @ignore
 */
function _x() {}

/**
 * @ignore
 */
function add_filter() {}

/**
 * @ignore
 */
function has_filter() {
	return false;
}

/**
 * @ignore
 */
function esc_attr() {}

/**
 * @ignore
 */
function apply_filters() {}

/**
 * @ignore
 */
function get_option() {}

/**
 * @ignore
 */
function is_lighttpd_before_150() {}

/**
 * @ignore
 */
function add_action() {}

/**
 * @ignore
 */
function did_action() {}

/**
 * @ignore
 */
function do_action_ref_array() {}

/**
 * @ignore
 */
function get_bloginfo() {}

/**
 * @ignore
 */
function is_admin() {
	return true;
}

/**
 * @ignore
 */
function site_url() {}

/**
 * @ignore
 */
function admin_url() {}

/**
 * @ignore
 */
function home_url() {}

/**
 * @ignore
 */
function includes_url() {}

/**
 * @ignore
 */
function wp_guess_url() {}

function get_file( $path ) {

	$path = realpath( $path );

	if ( ! $path || ! @is_file( $path ) ) {
		return '';
	}

	return @file_get_contents( $path );
}
class-ftp-sockets.php000064400000020437151212616050010627 0ustar00<?php
/**
 * PemFTP - An Ftp implementation in pure PHP
 *
 * @package PemFTP
 * @since 2.5.0
 *
 * @version 1.0
 * @copyright Alexey Dotsenko
 * @author Alexey Dotsenko
 * @link https://www.phpclasses.org/package/1743-PHP-FTP-client-in-pure-PHP.html
 * @license LGPL https://opensource.org/licenses/lgpl-license.html
 */

/**
 * Socket Based FTP implementation
 *
 * @package PemFTP
 * @subpackage Socket
 * @since 2.5.0
 *
 * @version 1.0
 * @copyright Alexey Dotsenko
 * @author Alexey Dotsenko
 * @link https://www.phpclasses.org/package/1743-PHP-FTP-client-in-pure-PHP.html
 * @license LGPL https://opensource.org/licenses/lgpl-license.html
 */
class ftp_sockets extends ftp_base {

	function __construct($verb=FALSE, $le=FALSE) {
		parent::__construct(true, $verb, $le);
	}

// <!-- --------------------------------------------------------------------------------------- -->
// <!--       Private functions                                                                 -->
// <!-- --------------------------------------------------------------------------------------- -->

	function _settimeout($sock) {
		if(!@socket_set_option($sock, SOL_SOCKET, SO_RCVTIMEO, array("sec"=>$this->_timeout, "usec"=>0))) {
			$this->PushError('_connect','socket set receive timeout',socket_strerror(socket_last_error($sock)));
			@socket_close($sock);
			return FALSE;
		}
		if(!@socket_set_option($sock, SOL_SOCKET , SO_SNDTIMEO, array("sec"=>$this->_timeout, "usec"=>0))) {
			$this->PushError('_connect','socket set send timeout',socket_strerror(socket_last_error($sock)));
			@socket_close($sock);
			return FALSE;
		}
		return true;
	}

	function _connect($host, $port) {
		$this->SendMSG("Creating socket");
		if(!($sock = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP))) {
			$this->PushError('_connect','socket create failed',socket_strerror(socket_last_error($sock)));
			return FALSE;
		}
		if(!$this->_settimeout($sock)) return FALSE;
		$this->SendMSG("Connecting to \"".$host.":".$port."\"");
		if (!($res = @socket_connect($sock, $host, $port))) {
			$this->PushError('_connect','socket connect failed',socket_strerror(socket_last_error($sock)));
			@socket_close($sock);
			return FALSE;
		}
		$this->_connected=true;
		return $sock;
	}

	function _readmsg($fnction="_readmsg"){
		if(!$this->_connected) {
			$this->PushError($fnction,'Connect first');
			return FALSE;
		}
		$result=true;
		$this->_message="";
		$this->_code=0;
		$go=true;
		do {
			$tmp=@socket_read($this->_ftp_control_sock, 4096, PHP_BINARY_READ);
			if($tmp===false) {
				$go=$result=false;
				$this->PushError($fnction,'Read failed', socket_strerror(socket_last_error($this->_ftp_control_sock)));
			} else {
				$this->_message.=$tmp;
				$go = !preg_match("/^([0-9]{3})(-.+\\1)? [^".CRLF."]+".CRLF."$/Us", $this->_message, $regs);
			}
		} while($go);
		if($this->LocalEcho) echo "GET < ".rtrim($this->_message, CRLF).CRLF;
		$this->_code=(int)$regs[1];
		return $result;
	}

	function _exec($cmd, $fnction="_exec") {
		if(!$this->_ready) {
			$this->PushError($fnction,'Connect first');
			return FALSE;
		}
		if($this->LocalEcho) echo "PUT > ",$cmd,CRLF;
		$status=@socket_write($this->_ftp_control_sock, $cmd.CRLF);
		if($status===false) {
			$this->PushError($fnction,'socket write failed', socket_strerror(socket_last_error($this->stream)));
			return FALSE;
		}
		$this->_lastaction=time();
		if(!$this->_readmsg($fnction)) return FALSE;
		return TRUE;
	}

	function _data_prepare($mode=FTP_ASCII) {
		if(!$this->_settype($mode)) return FALSE;
		$this->SendMSG("Creating data socket");
		$this->_ftp_data_sock = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
		if ($this->_ftp_data_sock < 0) {
			$this->PushError('_data_prepare','socket create failed',socket_strerror(socket_last_error($this->_ftp_data_sock)));
			return FALSE;
		}
		if(!$this->_settimeout($this->_ftp_data_sock)) {
			$this->_data_close();
			return FALSE;
		}
		if($this->_passive) {
			if(!$this->_exec("PASV", "pasv")) {
				$this->_data_close();
				return FALSE;
			}
			if(!$this->_checkCode()) {
				$this->_data_close();
				return FALSE;
			}
			$ip_port = explode(",", preg_replace("/^.+ \\(?([0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]+,[0-9]+)\\)?.*$/s", "\\1", $this->_message));
			$this->_datahost=$ip_port[0].".".$ip_port[1].".".$ip_port[2].".".$ip_port[3];
			$this->_dataport=(((int)$ip_port[4])<<8) + ((int)$ip_port[5]);
			$this->SendMSG("Connecting to ".$this->_datahost.":".$this->_dataport);
			if(!@socket_connect($this->_ftp_data_sock, $this->_datahost, $this->_dataport)) {
				$this->PushError("_data_prepare","socket_connect", socket_strerror(socket_last_error($this->_ftp_data_sock)));
				$this->_data_close();
				return FALSE;
			}
			else $this->_ftp_temp_sock=$this->_ftp_data_sock;
		} else {
			if(!@socket_getsockname($this->_ftp_control_sock, $addr, $port)) {
				$this->PushError("_data_prepare","cannot get control socket information", socket_strerror(socket_last_error($this->_ftp_control_sock)));
				$this->_data_close();
				return FALSE;
			}
			if(!@socket_bind($this->_ftp_data_sock,$addr)){
				$this->PushError("_data_prepare","cannot bind data socket", socket_strerror(socket_last_error($this->_ftp_data_sock)));
				$this->_data_close();
				return FALSE;
			}
			if(!@socket_listen($this->_ftp_data_sock)) {
				$this->PushError("_data_prepare","cannot listen data socket", socket_strerror(socket_last_error($this->_ftp_data_sock)));
				$this->_data_close();
				return FALSE;
			}
			if(!@socket_getsockname($this->_ftp_data_sock, $this->_datahost, $this->_dataport)) {
				$this->PushError("_data_prepare","cannot get data socket information", socket_strerror(socket_last_error($this->_ftp_data_sock)));
				$this->_data_close();
				return FALSE;
			}
			if(!$this->_exec('PORT '.str_replace('.',',',$this->_datahost.'.'.($this->_dataport>>8).'.'.($this->_dataport&0x00FF)), "_port")) {
				$this->_data_close();
				return FALSE;
			}
			if(!$this->_checkCode()) {
				$this->_data_close();
				return FALSE;
			}
		}
		return TRUE;
	}

	function _data_read($mode=FTP_ASCII, $fp=NULL) {
		$NewLine=$this->_eol_code[$this->OS_local];
		if(is_resource($fp)) $out=0;
		else $out="";
		if(!$this->_passive) {
			$this->SendMSG("Connecting to ".$this->_datahost.":".$this->_dataport);
			$this->_ftp_temp_sock=socket_accept($this->_ftp_data_sock);
			if($this->_ftp_temp_sock===FALSE) {
				$this->PushError("_data_read","socket_accept", socket_strerror(socket_last_error($this->_ftp_temp_sock)));
				$this->_data_close();
				return FALSE;
			}
		}

		while(($block=@socket_read($this->_ftp_temp_sock, $this->_ftp_buff_size, PHP_BINARY_READ))!==false) {
			if($block==="") break;
			if($mode!=FTP_BINARY) $block=preg_replace("/\r\n|\r|\n/", $this->_eol_code[$this->OS_local], $block);
			if(is_resource($fp)) $out+=fwrite($fp, $block, strlen($block));
			else $out.=$block;
		}
		return $out;
	}

	function _data_write($mode=FTP_ASCII, $fp=NULL) {
		$NewLine=$this->_eol_code[$this->OS_local];
		if(is_resource($fp)) $out=0;
		else $out="";
		if(!$this->_passive) {
			$this->SendMSG("Connecting to ".$this->_datahost.":".$this->_dataport);
			$this->_ftp_temp_sock=socket_accept($this->_ftp_data_sock);
			if($this->_ftp_temp_sock===FALSE) {
				$this->PushError("_data_write","socket_accept", socket_strerror(socket_last_error($this->_ftp_temp_sock)));
				$this->_data_close();
				return false;
			}
		}
		if(is_resource($fp)) {
			while(!feof($fp)) {
				$block=fread($fp, $this->_ftp_buff_size);
				if(!$this->_data_write_block($mode, $block)) return false;
			}
		} elseif(!$this->_data_write_block($mode, $fp)) return false;
		return true;
	}

	function _data_write_block($mode, $block) {
		if($mode!=FTP_BINARY) $block=preg_replace("/\r\n|\r|\n/", $this->_eol_code[$this->OS_remote], $block);
		do {
			if(($t=@socket_write($this->_ftp_temp_sock, $block))===FALSE) {
				$this->PushError("_data_write","socket_write", socket_strerror(socket_last_error($this->_ftp_temp_sock)));
				$this->_data_close();
				return FALSE;
			}
			$block=substr($block, $t);
		} while(!empty($block));
		return true;
	}

	function _data_close() {
		@socket_close($this->_ftp_temp_sock);
		@socket_close($this->_ftp_data_sock);
		$this->SendMSG("Disconnected data from remote host");
		return TRUE;
	}

	function _quit() {
		if($this->_connected) {
			@socket_close($this->_ftp_control_sock);
			$this->_connected=false;
			$this->SendMSG("Socket closed");
		}
	}
}
?>
class-wp-debug-data.php000064400000204010151212616050010775 0ustar00<?php
/**
 * Class for providing debug data based on a users WordPress environment.
 *
 * @package WordPress
 * @subpackage Site_Health
 * @since 5.2.0
 */

#[AllowDynamicProperties]
class WP_Debug_Data {
	/**
	 * Calls all core functions to check for updates.
	 *
	 * @since 5.2.0
	 */
	public static function check_for_updates() {
		wp_version_check();
		wp_update_plugins();
		wp_update_themes();
	}

	/**
	 * Static function for generating site debug data when required.
	 *
	 * @since 5.2.0
	 * @since 5.3.0 Added database charset, database collation,
	 *              and timezone information.
	 * @since 5.5.0 Added pretty permalinks support information.
	 * @since 6.7.0 Modularized into separate theme-oriented methods.
	 *
	 * @throws ImagickException
	 *
	 * @return array The debug data for the site.
	 */
	public static function debug_data() {
		/*
		 * Set up the array that holds all debug information.
		 *
		 * When iterating through the debug data, the ordering of the sections
		 * occurs in insertion-order of the assignments into this array.
		 *
		 * This is the single assignment of the sections before filtering. Null-entries will
		 * be automatically be removed.
		 */
		$info = array(
			'wp-core'             => self::get_wp_core(),
			'wp-paths-sizes'      => self::get_wp_paths_sizes(),
			'wp-dropins'          => self::get_wp_dropins(),
			'wp-active-theme'     => self::get_wp_active_theme(),
			'wp-parent-theme'     => self::get_wp_parent_theme(),
			'wp-themes-inactive'  => self::get_wp_themes_inactive(),
			'wp-mu-plugins'       => self::get_wp_mu_plugins(),
			'wp-plugins-active'   => self::get_wp_plugins_active(),
			'wp-plugins-inactive' => self::get_wp_plugins_inactive(),
			'wp-media'            => self::get_wp_media(),
			'wp-server'           => self::get_wp_server(),
			'wp-database'         => self::get_wp_database(),
			'wp-constants'        => self::get_wp_constants(),
			'wp-filesystem'       => self::get_wp_filesystem(),
		);

		/*
		 * Remove null elements from the array. The individual methods are
		 * allowed to return `null`, which communicates that the category
		 * of debug data isn't relevant and shouldn't be passed through.
		 */
		$info = array_filter(
			$info,
			static function ( $section ) {
				return isset( $section );
			}
		);

		/**
		 * Filters the debug information shown on the Tools -> Site Health -> Info screen.
		 *
		 * Plugin or themes may wish to introduce their own debug information without creating
		 * additional admin pages. They can utilize this filter to introduce their own sections
		 * or add more data to existing sections.
		 *
		 * Array keys for sections added by core are all prefixed with `wp-`. Plugins and themes
		 * should use their own slug as a prefix, both for consistency as well as avoiding
		 * key collisions. Note that the array keys are used as labels for the copied data.
		 *
		 * All strings are expected to be plain text except `$description` that can contain
		 * inline HTML tags (see below).
		 *
		 * @since 5.2.0
		 *
		 * @param array $args {
		 *     The debug information to be added to the core information page.
		 *
		 *     This is an associative multi-dimensional array, up to three levels deep.
		 *     The topmost array holds the sections, keyed by section ID.
		 *
		 *     @type array ...$0 {
		 *         Each section has a `$fields` associative array (see below), and each `$value` in `$fields`
		 *         can be another associative array of name/value pairs when there is more structured data
		 *         to display.
		 *
		 *         @type string $label       Required. The title for this section of the debug output.
		 *         @type string $description Optional. A description for your information section which
		 *                                   may contain basic HTML markup, inline tags only as it is
		 *                                   outputted in a paragraph.
		 *         @type bool   $show_count  Optional. If set to `true`, the amount of fields will be included
		 *                                   in the title for this section. Default false.
		 *         @type bool   $private     Optional. If set to `true`, the section and all associated fields
		 *                                   will be excluded from the copied data. Default false.
		 *         @type array  $fields {
		 *             Required. An associative array containing the fields to be displayed in the section,
		 *             keyed by field ID.
		 *
		 *             @type array ...$0 {
		 *                 An associative array containing the data to be displayed for the field.
		 *
		 *                 @type string $label    Required. The label for this piece of information.
		 *                 @type mixed  $value    Required. The output that is displayed for this field.
		 *                                        Text should be translated. Can be an associative array
		 *                                        that is displayed as name/value pairs.
		 *                                        Accepted types: `string|int|float|(string|int|float)[]`.
		 *                 @type string $debug    Optional. The output that is used for this field when
		 *                                        the user copies the data. It should be more concise and
		 *                                        not translated. If not set, the content of `$value`
		 *                                        is used. Note that the array keys are used as labels
		 *                                        for the copied data.
		 *                 @type bool   $private  Optional. If set to `true`, the field will be excluded
		 *                                        from the copied data, allowing you to show, for example,
		 *                                        API keys here. Default false.
		 *             }
		 *         }
		 *     }
		 * }
		 */
		$info = apply_filters( 'debug_information', $info );

		return $info;
	}

	/**
	 * Gets the WordPress core section of the debug data.
	 *
	 * @since 6.7.0
	 *
	 * @return array
	 */
	private static function get_wp_core(): array {
		// Save few function calls.
		$permalink_structure    = get_option( 'permalink_structure' );
		$is_ssl                 = is_ssl();
		$users_can_register     = get_option( 'users_can_register' );
		$blog_public            = get_option( 'blog_public' );
		$default_comment_status = get_option( 'default_comment_status' );
		$environment_type       = wp_get_environment_type();
		$core_version           = wp_get_wp_version();
		$core_updates           = get_core_updates();
		$core_update_needed     = '';

		if ( is_array( $core_updates ) ) {
			foreach ( $core_updates as $core => $update ) {
				if ( 'upgrade' === $update->response ) {
					/* translators: %s: Latest WordPress version number. */
					$core_update_needed = ' ' . sprintf( __( '(Latest version: %s)' ), $update->version );
				} else {
					$core_update_needed = '';
				}
			}
		}

		$fields = array(
			'version'                => array(
				'label' => __( 'Version' ),
				'value' => $core_version . $core_update_needed,
				'debug' => $core_version,
			),
			'site_language'          => array(
				'label' => __( 'Site Language' ),
				'value' => get_locale(),
			),
			'user_language'          => array(
				'label' => __( 'User Language' ),
				'value' => get_user_locale(),
			),
			'timezone'               => array(
				'label' => __( 'Timezone' ),
				'value' => wp_timezone_string(),
			),
			'home_url'               => array(
				'label'   => __( 'Home URL' ),
				'value'   => get_bloginfo( 'url' ),
				'private' => true,
			),
			'site_url'               => array(
				'label'   => __( 'Site URL' ),
				'value'   => get_bloginfo( 'wpurl' ),
				'private' => true,
			),
			'permalink'              => array(
				'label' => __( 'Permalink structure' ),
				'value' => $permalink_structure ? $permalink_structure : __( 'No permalink structure set' ),
				'debug' => $permalink_structure,
			),
			'https_status'           => array(
				'label' => __( 'Is this site using HTTPS?' ),
				'value' => $is_ssl ? __( 'Yes' ) : __( 'No' ),
				'debug' => $is_ssl,
			),
			'multisite'              => array(
				'label' => __( 'Is this a multisite?' ),
				'value' => is_multisite() ? __( 'Yes' ) : __( 'No' ),
				'debug' => is_multisite(),
			),
			'user_registration'      => array(
				'label' => __( 'Can anyone register on this site?' ),
				'value' => $users_can_register ? __( 'Yes' ) : __( 'No' ),
				'debug' => $users_can_register,
			),
			'blog_public'            => array(
				'label' => __( 'Is this site discouraging search engines?' ),
				'value' => $blog_public ? __( 'No' ) : __( 'Yes' ),
				'debug' => $blog_public,
			),
			'default_comment_status' => array(
				'label' => __( 'Default comment status' ),
				'value' => 'open' === $default_comment_status ? _x( 'Open', 'comment status' ) : _x( 'Closed', 'comment status' ),
				'debug' => $default_comment_status,
			),
			'environment_type'       => array(
				'label' => __( 'Environment type' ),
				'value' => $environment_type,
				'debug' => $environment_type,
			),
		);

		// Conditionally add debug information for multisite setups.
		if ( is_multisite() ) {
			$site_id = get_current_blog_id();

			$fields['site_id'] = array(
				'label' => __( 'Site ID' ),
				'value' => $site_id,
				'debug' => $site_id,
			);

			$network_query = new WP_Network_Query();
			$network_ids   = $network_query->query(
				array(
					'fields'        => 'ids',
					'number'        => 100,
					'no_found_rows' => false,
				)
			);

			$site_count = 0;
			foreach ( $network_ids as $network_id ) {
				$site_count += get_blog_count( $network_id );
			}

			$fields['site_count'] = array(
				'label' => __( 'Site count' ),
				'value' => $site_count,
			);

			$fields['network_count'] = array(
				'label' => __( 'Network count' ),
				'value' => $network_query->found_networks,
			);
		}

		$fields['user_count'] = array(
			'label' => __( 'User count' ),
			'value' => get_user_count(),
		);

		// WordPress features requiring processing.
		$wp_dotorg = wp_remote_get( 'https://wordpress.org', array( 'timeout' => 10 ) );

		if ( ! is_wp_error( $wp_dotorg ) ) {
			$fields['dotorg_communication'] = array(
				'label' => __( 'Communication with WordPress.org' ),
				'value' => __( 'WordPress.org is reachable' ),
				'debug' => 'true',
			);
		} else {
			$fields['dotorg_communication'] = array(
				'label' => __( 'Communication with WordPress.org' ),
				'value' => sprintf(
				/* translators: 1: The IP address WordPress.org resolves to. 2: The error returned by the lookup. */
					__( 'Unable to reach WordPress.org at %1$s: %2$s' ),
					gethostbyname( 'wordpress.org' ),
					$wp_dotorg->get_error_message()
				),
				'debug' => $wp_dotorg->get_error_message(),
			);
		}

		return array(
			'label'  => __( 'WordPress' ),
			'fields' => $fields,
		);
	}

	/**
	 * Gets the WordPress drop-in section of the debug data.
	 *
	 * @since 6.7.0
	 *
	 * @return array
	 */
	private static function get_wp_dropins(): array {
		// Get a list of all drop-in replacements.
		$dropins = get_dropins();

		// Get drop-ins descriptions.
		$dropin_descriptions = _get_dropins();

		$fields = array();
		foreach ( $dropins as $dropin_key => $dropin ) {
			$fields[ sanitize_text_field( $dropin_key ) ] = array(
				'label' => $dropin_key,
				'value' => $dropin_descriptions[ $dropin_key ][0],
				'debug' => 'true',
			);
		}

		return array(
			'label'       => __( 'Drop-ins' ),
			'show_count'  => true,
			'description' => sprintf(
				/* translators: %s: wp-content directory name. */
				__( 'Drop-ins are single files, found in the %s directory, that replace or enhance WordPress features in ways that are not possible for traditional plugins.' ),
				'<code>' . str_replace( ABSPATH, '', WP_CONTENT_DIR ) . '</code>'
			),
			'fields'      => $fields,
		);
	}

	/**
	 * Gets the WordPress server section of the debug data.
	 *
	 * @since 6.7.0
	 *
	 * @return array
	 */
	private static function get_wp_server(): array {
		// Populate the server debug fields.
		if ( function_exists( 'php_uname' ) ) {
			$server_architecture = sprintf( '%s %s %s', php_uname( 's' ), php_uname( 'r' ), php_uname( 'm' ) );
		} else {
			$server_architecture = 'unknown';
		}

		$php_version_debug = PHP_VERSION;
		// Whether PHP supports 64-bit.
		$php64bit = ( PHP_INT_SIZE * 8 === 64 );

		$php_version = sprintf(
			'%s %s',
			$php_version_debug,
			( $php64bit ? __( '(Supports 64bit values)' ) : __( '(Does not support 64bit values)' ) )
		);

		if ( $php64bit ) {
			$php_version_debug .= ' 64bit';
		}

		$fields = array();

		$fields['server_architecture'] = array(
			'label' => __( 'Server architecture' ),
			'value' => ( 'unknown' !== $server_architecture ? $server_architecture : __( 'Unable to determine server architecture' ) ),
			'debug' => $server_architecture,
		);
		$fields['httpd_software']      = array(
			'label' => __( 'Web server' ),
			'value' => ( isset( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : __( 'Unable to determine what web server software is used' ) ),
			'debug' => ( isset( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : 'unknown' ),
		);
		$fields['php_version']         = array(
			'label' => __( 'PHP version' ),
			'value' => $php_version,
			'debug' => $php_version_debug,
		);
		$fields['php_sapi']            = array(
			'label' => __( 'PHP SAPI' ),
			'value' => PHP_SAPI,
			'debug' => PHP_SAPI,
		);

		// Some servers disable `ini_set()` and `ini_get()`, we check this before trying to get configuration values.
		if ( ! function_exists( 'ini_get' ) ) {
			$fields['ini_get'] = array(
				'label' => __( 'Server settings' ),
				'value' => sprintf(
				/* translators: %s: ini_get() */
					__( 'Unable to determine some settings, as the %s function has been disabled.' ),
					'ini_get()'
				),
				'debug' => 'ini_get() is disabled',
			);
		} else {
			$fields['max_input_variables'] = array(
				'label' => __( 'PHP max input variables' ),
				'value' => ini_get( 'max_input_vars' ),
			);
			$fields['time_limit']          = array(
				'label' => __( 'PHP time limit' ),
				'value' => ini_get( 'max_execution_time' ),
			);

			if ( WP_Site_Health::get_instance()->php_memory_limit !== ini_get( 'memory_limit' ) ) {
				$fields['memory_limit']       = array(
					'label' => __( 'PHP memory limit' ),
					'value' => WP_Site_Health::get_instance()->php_memory_limit,
				);
				$fields['admin_memory_limit'] = array(
					'label' => __( 'PHP memory limit (only for admin screens)' ),
					'value' => ini_get( 'memory_limit' ),
				);
			} else {
				$fields['memory_limit'] = array(
					'label' => __( 'PHP memory limit' ),
					'value' => ini_get( 'memory_limit' ),
				);
			}

			$fields['max_input_time']      = array(
				'label' => __( 'Max input time' ),
				'value' => ini_get( 'max_input_time' ),
			);
			$fields['upload_max_filesize'] = array(
				'label' => __( 'Upload max filesize' ),
				'value' => ini_get( 'upload_max_filesize' ),
			);
			$fields['php_post_max_size']   = array(
				'label' => __( 'PHP post max size' ),
				'value' => ini_get( 'post_max_size' ),
			);
		}

		if ( function_exists( 'curl_version' ) ) {
			$curl = curl_version();

			$fields['curl_version'] = array(
				'label' => __( 'cURL version' ),
				'value' => sprintf( '%s %s', $curl['version'], $curl['ssl_version'] ),
			);
		} else {
			$fields['curl_version'] = array(
				'label' => __( 'cURL version' ),
				'value' => __( 'Not available' ),
				'debug' => 'not available',
			);
		}

		// SUHOSIN.
		$suhosin_loaded = ( extension_loaded( 'suhosin' ) || ( defined( 'SUHOSIN_PATCH' ) && constant( 'SUHOSIN_PATCH' ) ) );

		$fields['suhosin'] = array(
			'label' => __( 'Is SUHOSIN installed?' ),
			'value' => ( $suhosin_loaded ? __( 'Yes' ) : __( 'No' ) ),
			'debug' => $suhosin_loaded,
		);

		// Imagick.
		$imagick_loaded = extension_loaded( 'imagick' );

		$fields['imagick_availability'] = array(
			'label' => __( 'Is the Imagick library available?' ),
			'value' => ( $imagick_loaded ? __( 'Yes' ) : __( 'No' ) ),
			'debug' => $imagick_loaded,
		);

		// Pretty permalinks.
		$pretty_permalinks_supported = got_url_rewrite();

		$fields['pretty_permalinks'] = array(
			'label' => __( 'Are pretty permalinks supported?' ),
			'value' => ( $pretty_permalinks_supported ? __( 'Yes' ) : __( 'No' ) ),
			'debug' => $pretty_permalinks_supported,
		);

		// Check if a .htaccess file exists.
		if ( is_file( ABSPATH . '.htaccess' ) ) {
			// If the file exists, grab the content of it.
			$htaccess_content = file_get_contents( ABSPATH . '.htaccess' );

			// Filter away the core WordPress rules.
			$filtered_htaccess_content = trim( preg_replace( '/\# BEGIN WordPress[\s\S]+?# END WordPress/si', '', $htaccess_content ) );
			$filtered_htaccess_content = ! empty( $filtered_htaccess_content );

			if ( $filtered_htaccess_content ) {
				/* translators: %s: .htaccess */
				$htaccess_rules_string = sprintf( __( 'Custom rules have been added to your %s file.' ), '.htaccess' );
			} else {
				/* translators: %s: .htaccess */
				$htaccess_rules_string = sprintf( __( 'Your %s file contains only core WordPress features.' ), '.htaccess' );
			}

			$fields['htaccess_extra_rules'] = array(
				'label' => __( '.htaccess rules' ),
				'value' => $htaccess_rules_string,
				'debug' => $filtered_htaccess_content,
			);
		}

		// Check if a robots.txt file exists.
		if ( is_file( ABSPATH . 'robots.txt' ) ) {
			// If the file exists, turn debug info to true.
			$robotstxt_debug = true;

			/* translators: %s: robots.txt */
			$robotstxt_string = sprintf( __( 'There is a static %s file in your installation folder. WordPress cannot dynamically serve one.' ), 'robots.txt' );
		} elseif ( got_url_rewrite() ) {
			// No robots.txt file available and rewrite rules in place, turn debug info to false.
			$robotstxt_debug = false;

			/* translators: %s: robots.txt */
			$robotstxt_string = sprintf( __( 'Your site is using the dynamic %s file which is generated by WordPress.' ), 'robots.txt' );
		} else {
			// No robots.txt file, but without rewrite rules WP can't serve one.
			$robotstxt_debug = true;

			/* translators: %s: robots.txt */
			$robotstxt_string = sprintf( __( 'WordPress cannot dynamically serve a %s file due to a lack of rewrite rule support' ), 'robots.txt' );

		}

		$fields['static_robotstxt_file'] = array(
			'label' => __( 'robots.txt' ),
			'value' => $robotstxt_string,
			'debug' => $robotstxt_debug,
		);

		// Server time.
		$date = new DateTime( 'now', new DateTimeZone( 'UTC' ) );

		$fields['current']     = array(
			'label' => __( 'Current time' ),
			'value' => $date->format( DateTime::ATOM ),
		);
		$fields['utc-time']    = array(
			'label' => __( 'Current UTC time' ),
			'value' => $date->format( DateTime::RFC850 ),
		);
		$fields['server-time'] = array(
			'label' => __( 'Current Server time' ),
			'value' => wp_date( 'c', $_SERVER['REQUEST_TIME'] ),
		);

		return array(
			'label'       => __( 'Server' ),
			'description' => __( 'The options shown below relate to your server setup. If changes are required, you may need your web host&#8217;s assistance.' ),
			'fields'      => $fields,
		);
	}

	/**
	 * Gets the WordPress media section of the debug data.
	 *
	 * @since 6.7.0
	 *
	 * @throws ImagickException
	 * @return array
	 */
	private static function get_wp_media(): array {
		// Spare few function calls.
		$not_available = __( 'Not available' );

		// Populate the media fields.
		$fields['image_editor'] = array(
			'label' => __( 'Active editor' ),
			'value' => _wp_image_editor_choose(),
		);

		// Get ImageMagic information, if available.
		if ( class_exists( 'Imagick' ) ) {
			// Save the Imagick instance for later use.
			$imagick             = new Imagick();
			$imagemagick_version = $imagick->getVersion();
		} else {
			$imagemagick_version = __( 'Not available' );
		}

		$fields['imagick_module_version'] = array(
			'label' => __( 'ImageMagick version number' ),
			'value' => ( is_array( $imagemagick_version ) ? $imagemagick_version['versionNumber'] : $imagemagick_version ),
		);

		$fields['imagemagick_version'] = array(
			'label' => __( 'ImageMagick version string' ),
			'value' => ( is_array( $imagemagick_version ) ? $imagemagick_version['versionString'] : $imagemagick_version ),
		);

		$imagick_version = phpversion( 'imagick' );

		$fields['imagick_version'] = array(
			'label' => __( 'Imagick version' ),
			'value' => ( $imagick_version ) ? $imagick_version : __( 'Not available' ),
		);

		if ( ! function_exists( 'ini_get' ) ) {
			$fields['ini_get'] = array(
				'label' => __( 'File upload settings' ),
				'value' => sprintf(
				/* translators: %s: ini_get() */
					__( 'Unable to determine some settings, as the %s function has been disabled.' ),
					'ini_get()'
				),
				'debug' => 'ini_get() is disabled',
			);
		} else {
			// Get the PHP ini directive values.
			$file_uploads        = ini_get( 'file_uploads' );
			$post_max_size       = ini_get( 'post_max_size' );
			$upload_max_filesize = ini_get( 'upload_max_filesize' );
			$max_file_uploads    = ini_get( 'max_file_uploads' );
			$effective           = min( wp_convert_hr_to_bytes( $post_max_size ), wp_convert_hr_to_bytes( $upload_max_filesize ) );

			// Add info in Media section.
			$fields['file_uploads']        = array(
				'label' => __( 'File uploads' ),
				'value' => $file_uploads ? __( 'Enabled' ) : __( 'Disabled' ),
				'debug' => $file_uploads,
			);
			$fields['post_max_size']       = array(
				'label' => __( 'Max size of post data allowed' ),
				'value' => $post_max_size,
			);
			$fields['upload_max_filesize'] = array(
				'label' => __( 'Max size of an uploaded file' ),
				'value' => $upload_max_filesize,
			);
			$fields['max_effective_size']  = array(
				'label' => __( 'Max effective file size' ),
				'value' => size_format( $effective ),
			);
			$fields['max_file_uploads']    = array(
				'label' => __( 'Max simultaneous file uploads' ),
				'value' => $max_file_uploads,
			);
		}

		// If Imagick is used as our editor, provide some more information about its limitations.
		if ( 'WP_Image_Editor_Imagick' === _wp_image_editor_choose() && isset( $imagick ) && $imagick instanceof Imagick ) {
			$limits = array(
				'area'   => ( defined( 'imagick::RESOURCETYPE_AREA' ) ? size_format( $imagick->getResourceLimit( imagick::RESOURCETYPE_AREA ) ) : $not_available ),
				'disk'   => ( defined( 'imagick::RESOURCETYPE_DISK' ) ? $imagick->getResourceLimit( imagick::RESOURCETYPE_DISK ) : $not_available ),
				'file'   => ( defined( 'imagick::RESOURCETYPE_FILE' ) ? $imagick->getResourceLimit( imagick::RESOURCETYPE_FILE ) : $not_available ),
				'map'    => ( defined( 'imagick::RESOURCETYPE_MAP' ) ? size_format( $imagick->getResourceLimit( imagick::RESOURCETYPE_MAP ) ) : $not_available ),
				'memory' => ( defined( 'imagick::RESOURCETYPE_MEMORY' ) ? size_format( $imagick->getResourceLimit( imagick::RESOURCETYPE_MEMORY ) ) : $not_available ),
				'thread' => ( defined( 'imagick::RESOURCETYPE_THREAD' ) ? $imagick->getResourceLimit( imagick::RESOURCETYPE_THREAD ) : $not_available ),
				'time'   => ( defined( 'imagick::RESOURCETYPE_TIME' ) ? $imagick->getResourceLimit( imagick::RESOURCETYPE_TIME ) : $not_available ),
			);

			$limits_debug = array(
				'imagick::RESOURCETYPE_AREA'   => ( defined( 'imagick::RESOURCETYPE_AREA' ) ? size_format( $imagick->getResourceLimit( imagick::RESOURCETYPE_AREA ) ) : 'not available' ),
				'imagick::RESOURCETYPE_DISK'   => ( defined( 'imagick::RESOURCETYPE_DISK' ) ? $imagick->getResourceLimit( imagick::RESOURCETYPE_DISK ) : 'not available' ),
				'imagick::RESOURCETYPE_FILE'   => ( defined( 'imagick::RESOURCETYPE_FILE' ) ? $imagick->getResourceLimit( imagick::RESOURCETYPE_FILE ) : 'not available' ),
				'imagick::RESOURCETYPE_MAP'    => ( defined( 'imagick::RESOURCETYPE_MAP' ) ? size_format( $imagick->getResourceLimit( imagick::RESOURCETYPE_MAP ) ) : 'not available' ),
				'imagick::RESOURCETYPE_MEMORY' => ( defined( 'imagick::RESOURCETYPE_MEMORY' ) ? size_format( $imagick->getResourceLimit( imagick::RESOURCETYPE_MEMORY ) ) : 'not available' ),
				'imagick::RESOURCETYPE_THREAD' => ( defined( 'imagick::RESOURCETYPE_THREAD' ) ? $imagick->getResourceLimit( imagick::RESOURCETYPE_THREAD ) : 'not available' ),
				'imagick::RESOURCETYPE_TIME'   => ( defined( 'imagick::RESOURCETYPE_TIME' ) ? $imagick->getResourceLimit( imagick::RESOURCETYPE_TIME ) : 'not available' ),
			);

			$fields['imagick_limits'] = array(
				'label' => __( 'Imagick Resource Limits' ),
				'value' => $limits,
				'debug' => $limits_debug,
			);

			try {
				$formats = Imagick::queryFormats( '*' );
			} catch ( Exception $e ) {
				$formats = array();
			}

			$fields['imagemagick_file_formats'] = array(
				'label' => __( 'ImageMagick supported file formats' ),
				'value' => ( empty( $formats ) ) ? __( 'Unable to determine' ) : implode( ', ', $formats ),
				'debug' => ( empty( $formats ) ) ? 'Unable to determine' : implode( ', ', $formats ),
			);
		}

		// Get the image format transforms.
		$mappings           = wp_get_image_editor_output_format( '', '' );
		$formatted_mappings = array();

		if ( ! empty( $mappings ) ) {
			foreach ( $mappings as $format => $mime_type ) {
				$formatted_mappings[] = sprintf( '%s &rarr; %s', $format, $mime_type );
			}
			$mappings_display = implode( ', ', $formatted_mappings );
		} else {
			$mappings_display = __( 'No format transforms defined' );
		}

		$fields['image_format_transforms'] = array(
			'label' => __( 'Image format transforms' ),
			'value' => $mappings_display,
			'debug' => ( empty( $mappings ) ) ? 'No format transforms defined' : $mappings_display,
		);

		// Get GD information, if available.
		if ( function_exists( 'gd_info' ) ) {
			$gd = gd_info();
		} else {
			$gd = false;
		}

		$fields['gd_version'] = array(
			'label' => __( 'GD version' ),
			'value' => ( is_array( $gd ) ? $gd['GD Version'] : $not_available ),
			'debug' => ( is_array( $gd ) ? $gd['GD Version'] : 'not available' ),
		);

		$gd_image_formats     = array();
		$gd_supported_formats = array(
			'GIF Create' => 'GIF',
			'JPEG'       => 'JPEG',
			'PNG'        => 'PNG',
			'WebP'       => 'WebP',
			'BMP'        => 'BMP',
			'AVIF'       => 'AVIF',
			'HEIF'       => 'HEIF',
			'TIFF'       => 'TIFF',
			'XPM'        => 'XPM',
		);

		foreach ( $gd_supported_formats as $format_key => $format ) {
			$index = $format_key . ' Support';
			if ( isset( $gd[ $index ] ) && $gd[ $index ] ) {
				array_push( $gd_image_formats, $format );
			}
		}

		if ( ! empty( $gd_image_formats ) ) {
			$fields['gd_formats'] = array(
				'label' => __( 'GD supported file formats' ),
				'value' => implode( ', ', $gd_image_formats ),
			);
		}

		// Get Ghostscript information, if available.
		if ( function_exists( 'exec' ) ) {
			$gs = exec( 'gs --version' );

			if ( empty( $gs ) ) {
				$gs       = $not_available;
				$gs_debug = 'not available';
			} else {
				$gs_debug = $gs;
			}
		} else {
			$gs       = __( 'Unable to determine if Ghostscript is installed' );
			$gs_debug = 'unknown';
		}

		$fields['ghostscript_version'] = array(
			'label' => __( 'Ghostscript version' ),
			'value' => $gs,
			'debug' => $gs_debug,
		);

		return array(
			'label'  => __( 'Media Handling' ),
			'fields' => $fields,
		);
	}

	/**
	 * Gets the WordPress MU plugins section of the debug data.
	 *
	 * @since 6.7.0
	 *
	 * @return array
	 */
	private static function get_wp_mu_plugins(): array {
		// List must use plugins if there are any.
		$mu_plugins = get_mu_plugins();
		$fields     = array();

		foreach ( $mu_plugins as $plugin_path => $plugin ) {
			$plugin_version = $plugin['Version'];
			$plugin_author  = $plugin['Author'];

			$plugin_version_string       = __( 'No version or author information is available.' );
			$plugin_version_string_debug = 'author: (undefined), version: (undefined)';

			if ( ! empty( $plugin_version ) && ! empty( $plugin_author ) ) {
				/* translators: 1: Plugin version number. 2: Plugin author name. */
				$plugin_version_string       = sprintf( __( 'Version %1$s by %2$s' ), $plugin_version, $plugin_author );
				$plugin_version_string_debug = sprintf( 'version: %s, author: %s', $plugin_version, $plugin_author );
			} else {
				if ( ! empty( $plugin_author ) ) {
					/* translators: %s: Plugin author name. */
					$plugin_version_string       = sprintf( __( 'By %s' ), $plugin_author );
					$plugin_version_string_debug = sprintf( 'author: %s, version: (undefined)', $plugin_author );
				}

				if ( ! empty( $plugin_version ) ) {
					/* translators: %s: Plugin version number. */
					$plugin_version_string       = sprintf( __( 'Version %s' ), $plugin_version );
					$plugin_version_string_debug = sprintf( 'author: (undefined), version: %s', $plugin_version );
				}
			}

			$fields[ sanitize_text_field( $plugin['Name'] ) ] = array(
				'label' => $plugin['Name'],
				'value' => $plugin_version_string,
				'debug' => $plugin_version_string_debug,
			);
		}

		return array(
			'label'      => __( 'Must Use Plugins' ),
			'show_count' => true,
			'fields'     => $fields,
		);
	}

	/**
	 * Gets the WordPress paths and sizes section of the debug data.
	 *
	 * @since 6.7.0
	 *
	 * @return array|null Paths and sizes debug data for single sites,
	 *                    otherwise `null` for multi-site installs.
	 */
	private static function get_wp_paths_sizes(): ?array {
		if ( is_multisite() ) {
			return null;
		}

		$loading = __( 'Loading&hellip;' );

		$fields = array(
			'wordpress_path' => array(
				'label' => __( 'WordPress directory location' ),
				'value' => untrailingslashit( ABSPATH ),
			),
			'wordpress_size' => array(
				'label' => __( 'WordPress directory size' ),
				'value' => $loading,
				'debug' => 'loading...',
			),
			'uploads_path'   => array(
				'label' => __( 'Uploads directory location' ),
				'value' => wp_upload_dir()['basedir'],
			),
			'uploads_size'   => array(
				'label' => __( 'Uploads directory size' ),
				'value' => $loading,
				'debug' => 'loading...',
			),
			'themes_path'    => array(
				'label' => __( 'Themes directory location' ),
				'value' => get_theme_root(),
			),
			'themes_size'    => array(
				'label' => __( 'Themes directory size' ),
				'value' => $loading,
				'debug' => 'loading...',
			),
			'plugins_path'   => array(
				'label' => __( 'Plugins directory location' ),
				'value' => WP_PLUGIN_DIR,
			),
			'plugins_size'   => array(
				'label' => __( 'Plugins directory size' ),
				'value' => $loading,
				'debug' => 'loading...',
			),
			'fonts_path'     => array(
				'label' => __( 'Fonts directory location' ),
				'value' => wp_get_font_dir()['basedir'],
			),
			'fonts_size'     => array(
				'label' => __( 'Fonts directory size' ),
				'value' => $loading,
				'debug' => 'loading...',
			),
			'database_size'  => array(
				'label' => __( 'Database size' ),
				'value' => $loading,
				'debug' => 'loading...',
			),
			'total_size'     => array(
				'label' => __( 'Total installation size' ),
				'value' => $loading,
				'debug' => 'loading...',
			),
		);

		return array(
			/* translators: Filesystem directory paths and storage sizes. */
			'label'  => __( 'Directories and Sizes' ),
			'fields' => $fields,
		);
	}

	/**
	 * Gets the WordPress active plugins section of the debug data.
	 *
	 * @since 6.7.0
	 *
	 * @return array
	 */
	private static function get_wp_plugins_active(): array {
		return array(
			'label'      => __( 'Active Plugins' ),
			'show_count' => true,
			'fields'     => self::get_wp_plugins_raw_data()['wp-plugins-active'],
		);
	}

	/**
	 * Gets the WordPress inactive plugins section of the debug data.
	 *
	 * @since 6.7.0
	 *
	 * @return array
	 */
	private static function get_wp_plugins_inactive(): array {
		return array(
			'label'      => __( 'Inactive Plugins' ),
			'show_count' => true,
			'fields'     => self::get_wp_plugins_raw_data()['wp-plugins-inactive'],
		);
	}

	/**
	 * Gets the raw plugin data for the WordPress active and inactive sections of the debug data.
	 *
	 * @since 6.7.0
	 *
	 * @return array
	 */
	private static function get_wp_plugins_raw_data(): array {
		// List all available plugins.
		$plugins        = get_plugins();
		$plugin_updates = get_plugin_updates();
		$transient      = get_site_transient( 'update_plugins' );

		$auto_updates = array();
		$fields       = array(
			'wp-plugins-active'   => array(),
			'wp-plugins-inactive' => array(),
		);

		$auto_updates_enabled = wp_is_auto_update_enabled_for_type( 'plugin' );

		if ( $auto_updates_enabled ) {
			$auto_updates = (array) get_site_option( 'auto_update_plugins', array() );
		}

		foreach ( $plugins as $plugin_path => $plugin ) {
			$plugin_part = ( is_plugin_active( $plugin_path ) ) ? 'wp-plugins-active' : 'wp-plugins-inactive';

			$plugin_version = $plugin['Version'];
			$plugin_author  = $plugin['Author'];

			$plugin_version_string       = __( 'No version or author information is available.' );
			$plugin_version_string_debug = 'author: (undefined), version: (undefined)';

			if ( ! empty( $plugin_version ) && ! empty( $plugin_author ) ) {
				/* translators: 1: Plugin version number. 2: Plugin author name. */
				$plugin_version_string       = sprintf( __( 'Version %1$s by %2$s' ), $plugin_version, $plugin_author );
				$plugin_version_string_debug = sprintf( 'version: %s, author: %s', $plugin_version, $plugin_author );
			} else {
				if ( ! empty( $plugin_author ) ) {
					/* translators: %s: Plugin author name. */
					$plugin_version_string       = sprintf( __( 'By %s' ), $plugin_author );
					$plugin_version_string_debug = sprintf( 'author: %s, version: (undefined)', $plugin_author );
				}

				if ( ! empty( $plugin_version ) ) {
					/* translators: %s: Plugin version number. */
					$plugin_version_string       = sprintf( __( 'Version %s' ), $plugin_version );
					$plugin_version_string_debug = sprintf( 'author: (undefined), version: %s', $plugin_version );
				}
			}

			if ( array_key_exists( $plugin_path, $plugin_updates ) ) {
				/* translators: %s: Latest plugin version number. */
				$plugin_version_string       .= ' ' . sprintf( __( '(Latest version: %s)' ), $plugin_updates[ $plugin_path ]->update->new_version );
				$plugin_version_string_debug .= sprintf( ' (latest version: %s)', $plugin_updates[ $plugin_path ]->update->new_version );
			}

			if ( $auto_updates_enabled ) {
				if ( isset( $transient->response[ $plugin_path ] ) ) {
					$item = $transient->response[ $plugin_path ];
				} elseif ( isset( $transient->no_update[ $plugin_path ] ) ) {
					$item = $transient->no_update[ $plugin_path ];
				} else {
					$item = array(
						'id'            => $plugin_path,
						'slug'          => '',
						'plugin'        => $plugin_path,
						'new_version'   => '',
						'url'           => '',
						'package'       => '',
						'icons'         => array(),
						'banners'       => array(),
						'banners_rtl'   => array(),
						'tested'        => '',
						'requires_php'  => '',
						'compatibility' => new stdClass(),
					);
					$item = wp_parse_args( $plugin, $item );
				}

				$auto_update_forced = wp_is_auto_update_forced_for_item( 'plugin', null, (object) $item );

				if ( ! is_null( $auto_update_forced ) ) {
					$enabled = $auto_update_forced;
				} else {
					$enabled = in_array( $plugin_path, $auto_updates, true );
				}

				if ( $enabled ) {
					$auto_updates_string = __( 'Auto-updates enabled' );
				} else {
					$auto_updates_string = __( 'Auto-updates disabled' );
				}

				/**
				 * Filters the text string of the auto-updates setting for each plugin in the Site Health debug data.
				 *
				 * @since 5.5.0
				 *
				 * @param string $auto_updates_string The string output for the auto-updates column.
				 * @param string $plugin_path         The path to the plugin file.
				 * @param array  $plugin              An array of plugin data.
				 * @param bool   $enabled             Whether auto-updates are enabled for this item.
				 */
				$auto_updates_string = apply_filters( 'plugin_auto_update_debug_string', $auto_updates_string, $plugin_path, $plugin, $enabled );

				$plugin_version_string       .= ' | ' . $auto_updates_string;
				$plugin_version_string_debug .= ', ' . $auto_updates_string;
			}

			$fields[ $plugin_part ][ sanitize_text_field( $plugin['Name'] ) ] = array(
				'label' => $plugin['Name'],
				'value' => $plugin_version_string,
				'debug' => $plugin_version_string_debug,
			);
		}

		return $fields;
	}

	/**
	 * Gets the WordPress active theme section of the debug data.
	 *
	 * @since 6.7.0
	 *
	 * @global array $_wp_theme_features
	 *
	 * @return array
	 */
	private static function get_wp_active_theme(): array {
		global $_wp_theme_features;

		// Populate the section for the currently active theme.
		$theme_features = array();

		if ( ! empty( $_wp_theme_features ) ) {
			foreach ( $_wp_theme_features as $feature => $options ) {
				$theme_features[] = $feature;
			}
		}

		$active_theme  = wp_get_theme();
		$theme_updates = get_theme_updates();
		$transient     = get_site_transient( 'update_themes' );

		$active_theme_version       = $active_theme->version;
		$active_theme_version_debug = $active_theme_version;

		$auto_updates         = array();
		$auto_updates_enabled = wp_is_auto_update_enabled_for_type( 'theme' );
		if ( $auto_updates_enabled ) {
			$auto_updates = (array) get_site_option( 'auto_update_themes', array() );
		}

		if ( array_key_exists( $active_theme->stylesheet, $theme_updates ) ) {
			$theme_update_new_version = $theme_updates[ $active_theme->stylesheet ]->update['new_version'];

			/* translators: %s: Latest theme version number. */
			$active_theme_version       .= ' ' . sprintf( __( '(Latest version: %s)' ), $theme_update_new_version );
			$active_theme_version_debug .= sprintf( ' (latest version: %s)', $theme_update_new_version );
		}

		$active_theme_author_uri = $active_theme->display( 'AuthorURI' );

		if ( $active_theme->parent_theme ) {
			$active_theme_parent_theme = sprintf(
				/* translators: 1: Theme name. 2: Theme slug. */
				__( '%1$s (%2$s)' ),
				$active_theme->parent_theme,
				$active_theme->template
			);
			$active_theme_parent_theme_debug = sprintf(
				'%s (%s)',
				$active_theme->parent_theme,
				$active_theme->template
			);
		} else {
			$active_theme_parent_theme       = __( 'None' );
			$active_theme_parent_theme_debug = 'none';
		}

		$fields = array(
			'name'           => array(
				'label' => __( 'Name' ),
				'value' => sprintf(
					/* translators: 1: Theme name. 2: Theme slug. */
					__( '%1$s (%2$s)' ),
					$active_theme->name,
					$active_theme->stylesheet
				),
			),
			'version'        => array(
				'label' => __( 'Version' ),
				'value' => $active_theme_version,
				'debug' => $active_theme_version_debug,
			),
			'author'         => array(
				'label' => __( 'Author' ),
				'value' => wp_kses( $active_theme->author, array() ),
			),
			'author_website' => array(
				'label' => __( 'Author website' ),
				'value' => ( $active_theme_author_uri ? $active_theme_author_uri : __( 'Undefined' ) ),
				'debug' => ( $active_theme_author_uri ? $active_theme_author_uri : '(undefined)' ),
			),
			'parent_theme'   => array(
				'label' => __( 'Parent theme' ),
				'value' => $active_theme_parent_theme,
				'debug' => $active_theme_parent_theme_debug,
			),
			'theme_features' => array(
				'label' => __( 'Theme features' ),
				'value' => implode( ', ', $theme_features ),
			),
			'theme_path'     => array(
				'label' => __( 'Theme directory location' ),
				'value' => get_stylesheet_directory(),
			),
		);

		if ( $auto_updates_enabled ) {
			if ( isset( $transient->response[ $active_theme->stylesheet ] ) ) {
				$item = $transient->response[ $active_theme->stylesheet ];
			} elseif ( isset( $transient->no_update[ $active_theme->stylesheet ] ) ) {
				$item = $transient->no_update[ $active_theme->stylesheet ];
			} else {
				$item = array(
					'theme'        => $active_theme->stylesheet,
					'new_version'  => $active_theme->version,
					'url'          => '',
					'package'      => '',
					'requires'     => '',
					'requires_php' => '',
				);
			}

			$auto_update_forced = wp_is_auto_update_forced_for_item( 'theme', null, (object) $item );

			if ( ! is_null( $auto_update_forced ) ) {
				$enabled = $auto_update_forced;
			} else {
				$enabled = in_array( $active_theme->stylesheet, $auto_updates, true );
			}

			if ( $enabled ) {
				$auto_updates_string = __( 'Enabled' );
			} else {
				$auto_updates_string = __( 'Disabled' );
			}

			/** This filter is documented in wp-admin/includes/class-wp-debug-data.php */
			$auto_updates_string = apply_filters( 'theme_auto_update_debug_string', $auto_updates_string, $active_theme, $enabled );

			$fields['auto_update'] = array(
				'label' => __( 'Auto-updates' ),
				'value' => $auto_updates_string,
				'debug' => $auto_updates_string,
			);
		}

		return array(
			'label'  => __( 'Active Theme' ),
			'fields' => $fields,
		);
	}

	/**
	 * Gets the WordPress parent theme section of the debug data.
	 *
	 * @since 6.7.0
	 *
	 * @return array
	 */
	private static function get_wp_parent_theme(): array {
		$theme_updates = get_theme_updates();
		$transient     = get_site_transient( 'update_themes' );

		$auto_updates         = array();
		$auto_updates_enabled = wp_is_auto_update_enabled_for_type( 'theme' );
		if ( $auto_updates_enabled ) {
			$auto_updates = (array) get_site_option( 'auto_update_themes', array() );
		}

		$active_theme = wp_get_theme();
		$parent_theme = $active_theme->parent();
		$fields       = array();

		if ( $parent_theme ) {
			$parent_theme_version       = $parent_theme->version;
			$parent_theme_version_debug = $parent_theme_version;

			if ( array_key_exists( $parent_theme->stylesheet, $theme_updates ) ) {
				$parent_theme_update_new_version = $theme_updates[ $parent_theme->stylesheet ]->update['new_version'];

				/* translators: %s: Latest theme version number. */
				$parent_theme_version       .= ' ' . sprintf( __( '(Latest version: %s)' ), $parent_theme_update_new_version );
				$parent_theme_version_debug .= sprintf( ' (latest version: %s)', $parent_theme_update_new_version );
			}

			$parent_theme_author_uri = $parent_theme->display( 'AuthorURI' );

			$fields = array(
				'name'           => array(
					'label' => __( 'Name' ),
					'value' => sprintf(
						/* translators: 1: Theme name. 2: Theme slug. */
						__( '%1$s (%2$s)' ),
						$parent_theme->name,
						$parent_theme->stylesheet
					),
				),
				'version'        => array(
					'label' => __( 'Version' ),
					'value' => $parent_theme_version,
					'debug' => $parent_theme_version_debug,
				),
				'author'         => array(
					'label' => __( 'Author' ),
					'value' => wp_kses( $parent_theme->author, array() ),
				),
				'author_website' => array(
					'label' => __( 'Author website' ),
					'value' => ( $parent_theme_author_uri ? $parent_theme_author_uri : __( 'Undefined' ) ),
					'debug' => ( $parent_theme_author_uri ? $parent_theme_author_uri : '(undefined)' ),
				),
				'theme_path'     => array(
					'label' => __( 'Theme directory location' ),
					'value' => get_template_directory(),
				),
			);

			if ( $auto_updates_enabled ) {
				if ( isset( $transient->response[ $parent_theme->stylesheet ] ) ) {
					$item = $transient->response[ $parent_theme->stylesheet ];
				} elseif ( isset( $transient->no_update[ $parent_theme->stylesheet ] ) ) {
					$item = $transient->no_update[ $parent_theme->stylesheet ];
				} else {
					$item = array(
						'theme'        => $parent_theme->stylesheet,
						'new_version'  => $parent_theme->version,
						'url'          => '',
						'package'      => '',
						'requires'     => '',
						'requires_php' => '',
					);
				}

				$auto_update_forced = wp_is_auto_update_forced_for_item( 'theme', null, (object) $item );

				if ( ! is_null( $auto_update_forced ) ) {
					$enabled = $auto_update_forced;
				} else {
					$enabled = in_array( $parent_theme->stylesheet, $auto_updates, true );
				}

				if ( $enabled ) {
					$parent_theme_auto_update_string = __( 'Enabled' );
				} else {
					$parent_theme_auto_update_string = __( 'Disabled' );
				}

				/** This filter is documented in wp-admin/includes/class-wp-debug-data.php */
				$parent_theme_auto_update_string = apply_filters( 'theme_auto_update_debug_string', $parent_theme_auto_update_string, $parent_theme, $enabled );

				$fields['auto_update'] = array(
					'label' => __( 'Auto-update' ),
					'value' => $parent_theme_auto_update_string,
					'debug' => $parent_theme_auto_update_string,
				);
			}
		}

		return array(
			'label'  => __( 'Parent Theme' ),
			'fields' => $fields,
		);
	}

	/**
	 * Gets the WordPress inactive themes section of the debug data.
	 *
	 * @since 6.7.0
	 *
	 * @return array
	 */
	private static function get_wp_themes_inactive(): array {
		$active_theme  = wp_get_theme();
		$parent_theme  = $active_theme->parent();
		$theme_updates = get_theme_updates();
		$transient     = get_site_transient( 'update_themes' );

		$auto_updates         = array();
		$auto_updates_enabled = wp_is_auto_update_enabled_for_type( 'theme' );
		if ( $auto_updates_enabled ) {
			$auto_updates = (array) get_site_option( 'auto_update_themes', array() );
		}

		// Populate a list of all themes available in the installation.
		$all_themes = wp_get_themes();
		$fields     = array();

		foreach ( $all_themes as $theme_slug => $theme ) {
			// Exclude the currently active theme from the list of all themes.
			if ( $active_theme->stylesheet === $theme_slug ) {
				continue;
			}

			// Exclude the currently active parent theme from the list of all themes.
			if ( ! empty( $parent_theme ) && $parent_theme->stylesheet === $theme_slug ) {
				continue;
			}

			$theme_version = $theme->version;
			$theme_author  = $theme->author;

			// Sanitize.
			$theme_author = wp_kses( $theme_author, array() );

			$theme_version_string       = __( 'No version or author information is available.' );
			$theme_version_string_debug = 'undefined';

			if ( ! empty( $theme_version ) && ! empty( $theme_author ) ) {
				/* translators: 1: Theme version number. 2: Theme author name. */
				$theme_version_string       = sprintf( __( 'Version %1$s by %2$s' ), $theme_version, $theme_author );
				$theme_version_string_debug = sprintf( 'version: %s, author: %s', $theme_version, $theme_author );
			} else {
				if ( ! empty( $theme_author ) ) {
					/* translators: %s: Theme author name. */
					$theme_version_string       = sprintf( __( 'By %s' ), $theme_author );
					$theme_version_string_debug = sprintf( 'author: %s, version: (undefined)', $theme_author );
				}

				if ( ! empty( $theme_version ) ) {
					/* translators: %s: Theme version number. */
					$theme_version_string       = sprintf( __( 'Version %s' ), $theme_version );
					$theme_version_string_debug = sprintf( 'author: (undefined), version: %s', $theme_version );
				}
			}

			if ( array_key_exists( $theme_slug, $theme_updates ) ) {
				/* translators: %s: Latest theme version number. */
				$theme_version_string       .= ' ' . sprintf( __( '(Latest version: %s)' ), $theme_updates[ $theme_slug ]->update['new_version'] );
				$theme_version_string_debug .= sprintf( ' (latest version: %s)', $theme_updates[ $theme_slug ]->update['new_version'] );
			}

			if ( $auto_updates_enabled ) {
				if ( isset( $transient->response[ $theme_slug ] ) ) {
					$item = $transient->response[ $theme_slug ];
				} elseif ( isset( $transient->no_update[ $theme_slug ] ) ) {
					$item = $transient->no_update[ $theme_slug ];
				} else {
					$item = array(
						'theme'        => $theme_slug,
						'new_version'  => $theme->version,
						'url'          => '',
						'package'      => '',
						'requires'     => '',
						'requires_php' => '',
					);
				}

				$auto_update_forced = wp_is_auto_update_forced_for_item( 'theme', null, (object) $item );

				if ( ! is_null( $auto_update_forced ) ) {
					$enabled = $auto_update_forced;
				} else {
					$enabled = in_array( $theme_slug, $auto_updates, true );
				}

				if ( $enabled ) {
					$auto_updates_string = __( 'Auto-updates enabled' );
				} else {
					$auto_updates_string = __( 'Auto-updates disabled' );
				}

				/**
				 * Filters the text string of the auto-updates setting for each theme in the Site Health debug data.
				 *
				 * @since 5.5.0
				 *
				 * @param string   $auto_updates_string The string output for the auto-updates column.
				 * @param WP_Theme $theme               An object of theme data.
				 * @param bool     $enabled             Whether auto-updates are enabled for this item.
				 */
				$auto_updates_string = apply_filters( 'theme_auto_update_debug_string', $auto_updates_string, $theme, $enabled );

				$theme_version_string       .= ' | ' . $auto_updates_string;
				$theme_version_string_debug .= ', ' . $auto_updates_string;
			}

			$fields[ sanitize_text_field( $theme->name ) ] = array(
				'label' => sprintf(
					/* translators: 1: Theme name. 2: Theme slug. */
					__( '%1$s (%2$s)' ),
					$theme->name,
					$theme_slug
				),
				'value' => $theme_version_string,
				'debug' => $theme_version_string_debug,
			);
		}

		return array(
			'label'      => __( 'Inactive Themes' ),
			'show_count' => true,
			'fields'     => $fields,
		);
	}

	/**
	 * Gets the WordPress constants section of the debug data.
	 *
	 * @since 6.7.0
	 *
	 * @return array
	 */
	private static function get_wp_constants(): array {
		// Check if WP_DEBUG_LOG is set.
		$wp_debug_log_value = __( 'Disabled' );
		if ( is_string( WP_DEBUG_LOG ) ) {
			$wp_debug_log_value = WP_DEBUG_LOG;
		} elseif ( WP_DEBUG_LOG ) {
			$wp_debug_log_value = __( 'Enabled' );
		}

		// Check CONCATENATE_SCRIPTS.
		if ( defined( 'CONCATENATE_SCRIPTS' ) ) {
			$concatenate_scripts       = CONCATENATE_SCRIPTS ? __( 'Enabled' ) : __( 'Disabled' );
			$concatenate_scripts_debug = CONCATENATE_SCRIPTS ? 'true' : 'false';
		} else {
			$concatenate_scripts       = __( 'Undefined' );
			$concatenate_scripts_debug = 'undefined';
		}

		// Check COMPRESS_SCRIPTS.
		if ( defined( 'COMPRESS_SCRIPTS' ) ) {
			$compress_scripts       = COMPRESS_SCRIPTS ? __( 'Enabled' ) : __( 'Disabled' );
			$compress_scripts_debug = COMPRESS_SCRIPTS ? 'true' : 'false';
		} else {
			$compress_scripts       = __( 'Undefined' );
			$compress_scripts_debug = 'undefined';
		}

		// Check COMPRESS_CSS.
		if ( defined( 'COMPRESS_CSS' ) ) {
			$compress_css       = COMPRESS_CSS ? __( 'Enabled' ) : __( 'Disabled' );
			$compress_css_debug = COMPRESS_CSS ? 'true' : 'false';
		} else {
			$compress_css       = __( 'Undefined' );
			$compress_css_debug = 'undefined';
		}

		// Check WP_ENVIRONMENT_TYPE.
		if ( defined( 'WP_ENVIRONMENT_TYPE' ) ) {
			$wp_environment_type       = WP_ENVIRONMENT_TYPE ? WP_ENVIRONMENT_TYPE : __( 'Empty value' );
			$wp_environment_type_debug = WP_ENVIRONMENT_TYPE;
		} else {
			$wp_environment_type       = __( 'Undefined' );
			$wp_environment_type_debug = 'undefined';
		}

		// Check DB_COLLATE.
		if ( defined( 'DB_COLLATE' ) ) {
			$db_collate       = DB_COLLATE ? DB_COLLATE : __( 'Empty value' );
			$db_collate_debug = DB_COLLATE;
		} else {
			$db_collate       = __( 'Undefined' );
			$db_collate_debug = 'undefined';
		}

		$fields = array(
			'ABSPATH'             => array(
				'label'   => 'ABSPATH',
				'value'   => ABSPATH,
				'private' => true,
			),
			'WP_HOME'             => array(
				'label' => 'WP_HOME',
				'value' => ( defined( 'WP_HOME' ) ? WP_HOME : __( 'Undefined' ) ),
				'debug' => ( defined( 'WP_HOME' ) ? WP_HOME : 'undefined' ),
			),
			'WP_SITEURL'          => array(
				'label' => 'WP_SITEURL',
				'value' => ( defined( 'WP_SITEURL' ) ? WP_SITEURL : __( 'Undefined' ) ),
				'debug' => ( defined( 'WP_SITEURL' ) ? WP_SITEURL : 'undefined' ),
			),
			'WP_CONTENT_DIR'      => array(
				'label' => 'WP_CONTENT_DIR',
				'value' => WP_CONTENT_DIR,
			),
			'WP_PLUGIN_DIR'       => array(
				'label' => 'WP_PLUGIN_DIR',
				'value' => WP_PLUGIN_DIR,
			),
			'WP_MEMORY_LIMIT'     => array(
				'label' => 'WP_MEMORY_LIMIT',
				'value' => WP_MEMORY_LIMIT,
			),
			'WP_MAX_MEMORY_LIMIT' => array(
				'label' => 'WP_MAX_MEMORY_LIMIT',
				'value' => WP_MAX_MEMORY_LIMIT,
			),
			'WP_DEBUG'            => array(
				'label' => 'WP_DEBUG',
				'value' => WP_DEBUG ? __( 'Enabled' ) : __( 'Disabled' ),
				'debug' => WP_DEBUG,
			),
			'WP_DEBUG_DISPLAY'    => array(
				'label' => 'WP_DEBUG_DISPLAY',
				'value' => WP_DEBUG_DISPLAY ? __( 'Enabled' ) : __( 'Disabled' ),
				'debug' => WP_DEBUG_DISPLAY,
			),
			'WP_DEBUG_LOG'        => array(
				'label' => 'WP_DEBUG_LOG',
				'value' => $wp_debug_log_value,
				'debug' => WP_DEBUG_LOG,
			),
			'SCRIPT_DEBUG'        => array(
				'label' => 'SCRIPT_DEBUG',
				'value' => SCRIPT_DEBUG ? __( 'Enabled' ) : __( 'Disabled' ),
				'debug' => SCRIPT_DEBUG,
			),
			'WP_CACHE'            => array(
				'label' => 'WP_CACHE',
				'value' => WP_CACHE ? __( 'Enabled' ) : __( 'Disabled' ),
				'debug' => WP_CACHE,
			),
			'CONCATENATE_SCRIPTS' => array(
				'label' => 'CONCATENATE_SCRIPTS',
				'value' => $concatenate_scripts,
				'debug' => $concatenate_scripts_debug,
			),
			'COMPRESS_SCRIPTS'    => array(
				'label' => 'COMPRESS_SCRIPTS',
				'value' => $compress_scripts,
				'debug' => $compress_scripts_debug,
			),
			'COMPRESS_CSS'        => array(
				'label' => 'COMPRESS_CSS',
				'value' => $compress_css,
				'debug' => $compress_css_debug,
			),
			'WP_ENVIRONMENT_TYPE' => array(
				'label' => 'WP_ENVIRONMENT_TYPE',
				'value' => $wp_environment_type,
				'debug' => $wp_environment_type_debug,
			),
			'WP_DEVELOPMENT_MODE' => array(
				'label' => 'WP_DEVELOPMENT_MODE',
				'value' => WP_DEVELOPMENT_MODE ? WP_DEVELOPMENT_MODE : __( 'Disabled' ),
				'debug' => WP_DEVELOPMENT_MODE,
			),
			'DB_CHARSET'          => array(
				'label' => 'DB_CHARSET',
				'value' => ( defined( 'DB_CHARSET' ) ? DB_CHARSET : __( 'Undefined' ) ),
				'debug' => ( defined( 'DB_CHARSET' ) ? DB_CHARSET : 'undefined' ),
			),
			'DB_COLLATE'          => array(
				'label' => 'DB_COLLATE',
				'value' => $db_collate,
				'debug' => $db_collate_debug,
			),
		);

		return array(
			'label'       => __( 'WordPress Constants' ),
			'description' => __( 'These settings alter where and how parts of WordPress are loaded.' ),
			'fields'      => $fields,
		);
	}

	/**
	 * Gets the WordPress database section of the debug data.
	 *
	 * @since 6.7.0
	 *
	 * @global wpdb $wpdb WordPress database abstraction object.
	 *
	 * @return array
	 */
	private static function get_wp_database(): array {
		global $wpdb;

		// Populate the database debug fields.
		if ( is_object( $wpdb->dbh ) ) {
			// mysqli or PDO.
			$extension = get_class( $wpdb->dbh );
		} else {
			// Unknown sql extension.
			$extension = null;
		}

		$server = $wpdb->get_var( 'SELECT VERSION()' );

		$client_version = $wpdb->dbh->client_info;

		$fields = array(
			'extension'          => array(
				'label' => __( 'Database Extension' ),
				'value' => $extension,
			),
			'server_version'     => array(
				'label' => __( 'Server version' ),
				'value' => $server,
			),
			'client_version'     => array(
				'label' => __( 'Client version' ),
				'value' => $client_version,
			),
			'database_user'      => array(
				'label'   => __( 'Database username' ),
				'value'   => $wpdb->dbuser,
				'private' => true,
			),
			'database_host'      => array(
				'label'   => __( 'Database host' ),
				'value'   => $wpdb->dbhost,
				'private' => true,
			),
			'database_name'      => array(
				'label'   => __( 'Database name' ),
				'value'   => $wpdb->dbname,
				'private' => true,
			),
			'database_prefix'    => array(
				'label'   => __( 'Table prefix' ),
				'value'   => $wpdb->prefix,
				'private' => true,
			),
			'database_charset'   => array(
				'label'   => __( 'Database charset' ),
				'value'   => $wpdb->charset,
				'private' => true,
			),
			'database_collate'   => array(
				'label'   => __( 'Database collation' ),
				'value'   => $wpdb->collate,
				'private' => true,
			),
			'max_allowed_packet' => array(
				'label' => __( 'Max allowed packet size' ),
				'value' => self::get_mysql_var( 'max_allowed_packet' ),
			),
			'max_connections'    => array(
				'label' => __( 'Max connections number' ),
				'value' => self::get_mysql_var( 'max_connections' ),
			),
		);

		return array(
			'label'  => __( 'Database' ),
			'fields' => $fields,
		);
	}

	/**
	 * Gets the file system section of the debug data.
	 *
	 * @since 6.7.0
	 *
	 * @return array
	 */
	private static function get_wp_filesystem(): array {
		$upload_dir                     = wp_upload_dir();
		$fonts_dir_exists               = file_exists( wp_get_font_dir()['basedir'] );
		$is_writable_abspath            = wp_is_writable( ABSPATH );
		$is_writable_wp_content_dir     = wp_is_writable( WP_CONTENT_DIR );
		$is_writable_upload_dir         = wp_is_writable( $upload_dir['basedir'] );
		$is_writable_wp_plugin_dir      = wp_is_writable( WP_PLUGIN_DIR );
		$is_writable_template_directory = wp_is_writable( get_theme_root( get_template() ) );
		$is_writable_fonts_dir          = $fonts_dir_exists ? wp_is_writable( wp_get_font_dir()['basedir'] ) : false;

		$fields = array(
			'wordpress'  => array(
				'label' => __( 'The main WordPress directory' ),
				'value' => ( $is_writable_abspath ? __( 'Writable' ) : __( 'Not writable' ) ),
				'debug' => ( $is_writable_abspath ? 'writable' : 'not writable' ),
			),
			'wp-content' => array(
				'label' => __( 'The wp-content directory' ),
				'value' => ( $is_writable_wp_content_dir ? __( 'Writable' ) : __( 'Not writable' ) ),
				'debug' => ( $is_writable_wp_content_dir ? 'writable' : 'not writable' ),
			),
			'uploads'    => array(
				'label' => __( 'The uploads directory' ),
				'value' => ( $is_writable_upload_dir ? __( 'Writable' ) : __( 'Not writable' ) ),
				'debug' => ( $is_writable_upload_dir ? 'writable' : 'not writable' ),
			),
			'plugins'    => array(
				'label' => __( 'The plugins directory' ),
				'value' => ( $is_writable_wp_plugin_dir ? __( 'Writable' ) : __( 'Not writable' ) ),
				'debug' => ( $is_writable_wp_plugin_dir ? 'writable' : 'not writable' ),
			),
			'themes'     => array(
				'label' => __( 'The themes directory' ),
				'value' => ( $is_writable_template_directory ? __( 'Writable' ) : __( 'Not writable' ) ),
				'debug' => ( $is_writable_template_directory ? 'writable' : 'not writable' ),
			),
			'fonts'      => array(
				'label' => __( 'The fonts directory' ),
				'value' => $fonts_dir_exists
					? ( $is_writable_fonts_dir ? __( 'Writable' ) : __( 'Not writable' ) )
					: __( 'Does not exist' ),
				'debug' => $fonts_dir_exists
					? ( $is_writable_fonts_dir ? 'writable' : 'not writable' )
					: 'does not exist',
			),
		);

		// Add more filesystem checks.
		if ( defined( 'WPMU_PLUGIN_DIR' ) && is_dir( WPMU_PLUGIN_DIR ) ) {
			$is_writable_wpmu_plugin_dir = wp_is_writable( WPMU_PLUGIN_DIR );

			$fields['mu-plugins'] = array(
				'label' => __( 'The must use plugins directory' ),
				'value' => ( $is_writable_wpmu_plugin_dir ? __( 'Writable' ) : __( 'Not writable' ) ),
				'debug' => ( $is_writable_wpmu_plugin_dir ? 'writable' : 'not writable' ),
			);
		}

		return array(
			'label'       => __( 'Filesystem Permissions' ),
			'description' => __( 'Shows whether WordPress is able to write to the directories it needs access to.' ),
			'fields'      => $fields,
		);
	}

	/**
	 * Returns the value of a MySQL system variable.
	 *
	 * @since 5.9.0
	 *
	 * @global wpdb $wpdb WordPress database abstraction object.
	 *
	 * @param string $mysql_var Name of the MySQL system variable.
	 * @return string|null The variable value on success. Null if the variable does not exist.
	 */
	public static function get_mysql_var( $mysql_var ) {
		global $wpdb;

		$result = $wpdb->get_row(
			$wpdb->prepare( 'SHOW VARIABLES LIKE %s', $mysql_var ),
			ARRAY_A
		);

		if ( ! empty( $result ) && array_key_exists( 'Value', $result ) ) {
			return $result['Value'];
		}

		return null;
	}

	/**
	 * Formats the information gathered for debugging, in a manner suitable for copying to a forum or support ticket.
	 *
	 * @since 5.2.0
	 *
	 * @param array  $info_array Information gathered from the `WP_Debug_Data::debug_data()` function.
	 * @param string $data_type  The data type to return, either 'info' or 'debug'.
	 * @return string The formatted data.
	 */
	public static function format( $info_array, $data_type ) {
		$return = "`\n";

		foreach ( $info_array as $section => $details ) {
			// Skip this section if there are no fields, or the section has been declared as private.
			if ( empty( $details['fields'] ) || ( isset( $details['private'] ) && $details['private'] ) ) {
				continue;
			}

			$section_label = 'debug' === $data_type ? $section : $details['label'];

			$return .= sprintf(
				"### %s%s ###\n\n",
				$section_label,
				( isset( $details['show_count'] ) && $details['show_count'] ? sprintf( ' (%d)', count( $details['fields'] ) ) : '' )
			);

			foreach ( $details['fields'] as $field_name => $field ) {
				if ( isset( $field['private'] ) && true === $field['private'] ) {
					continue;
				}

				if ( 'debug' === $data_type && isset( $field['debug'] ) ) {
					$debug_data = $field['debug'];
				} else {
					$debug_data = $field['value'];
				}

				// Can be array, one level deep only.
				if ( is_array( $debug_data ) ) {
					$value = '';

					foreach ( $debug_data as $sub_field_name => $sub_field_value ) {
						$value .= sprintf( "\n\t%s: %s", $sub_field_name, $sub_field_value );
					}
				} elseif ( is_bool( $debug_data ) ) {
					$value = $debug_data ? 'true' : 'false';
				} elseif ( empty( $debug_data ) && '0' !== $debug_data ) {
					$value = 'undefined';
				} else {
					$value = $debug_data;
				}

				if ( 'debug' === $data_type ) {
					$label = $field_name;
				} else {
					$label = $field['label'];
				}

				$return .= sprintf( "%s: %s\n", $label, $value );
			}

			$return .= "\n";
		}

		$return .= '`';

		return $return;
	}

	/**
	 * Fetches the total size of all the database tables for the active database user.
	 *
	 * @since 5.2.0
	 *
	 * @global wpdb $wpdb WordPress database abstraction object.
	 *
	 * @return int The size of the database, in bytes.
	 */
	public static function get_database_size() {
		global $wpdb;
		$size = 0;
		$rows = $wpdb->get_results( 'SHOW TABLE STATUS', ARRAY_A );

		if ( $wpdb->num_rows > 0 ) {
			foreach ( $rows as $row ) {
				$size += $row['Data_length'] + $row['Index_length'];
			}
		}

		return (int) $size;
	}

	/**
	 * Fetches the sizes of the WordPress directories: `wordpress` (ABSPATH), `plugins`, `themes`, and `uploads`.
	 * Intended to supplement the array returned by `WP_Debug_Data::debug_data()`.
	 *
	 * @since 5.2.0
	 * @deprecated 5.6.0 Use WP_REST_Site_Health_Controller::get_directory_sizes()
	 * @see WP_REST_Site_Health_Controller::get_directory_sizes()
	 *
	 * @return array The sizes of the directories, also the database size and total installation size.
	 */
	public static function get_sizes() {
		_deprecated_function( __METHOD__, '5.6.0', 'WP_REST_Site_Health_Controller::get_directory_sizes()' );

		$size_db    = self::get_database_size();
		$upload_dir = wp_get_upload_dir();

		/*
		 * We will be using the PHP max execution time to prevent the size calculations
		 * from causing a timeout. The default value is 30 seconds, and some
		 * hosts do not allow you to read configuration values.
		 */
		if ( function_exists( 'ini_get' ) ) {
			$max_execution_time = ini_get( 'max_execution_time' );
		}

		/*
		 * The max_execution_time defaults to 0 when PHP runs from cli.
		 * We still want to limit it below.
		 */
		if ( empty( $max_execution_time ) ) {
			$max_execution_time = 30; // 30 seconds.
		}

		if ( $max_execution_time > 20 ) {
			/*
			 * If the max_execution_time is set to lower than 20 seconds, reduce it a bit to prevent
			 * edge-case timeouts that may happen after the size loop has finished running.
			 */
			$max_execution_time -= 2;
		}

		/*
		 * Go through the various installation directories and calculate their sizes.
		 * No trailing slashes.
		 */
		$paths = array(
			'wordpress_size' => untrailingslashit( ABSPATH ),
			'themes_size'    => get_theme_root(),
			'plugins_size'   => WP_PLUGIN_DIR,
			'uploads_size'   => $upload_dir['basedir'],
			'fonts_size'     => wp_get_font_dir()['basedir'],
		);

		$exclude = $paths;
		unset( $exclude['wordpress_size'] );
		$exclude = array_values( $exclude );

		$size_total = 0;
		$all_sizes  = array();

		// Loop over all the directories we want to gather the sizes for.
		foreach ( $paths as $name => $path ) {
			$dir_size = null; // Default to timeout.
			$results  = array(
				'path' => $path,
				'raw'  => 0,
			);

			// If the directory does not exist, skip checking it, as it will skew the other results.
			if ( ! is_dir( $path ) ) {
				$all_sizes[ $name ] = array(
					'path'  => $path,
					'raw'   => 0,
					'size'  => __( 'The directory does not exist.' ),
					'debug' => 'directory not found',
				);

				continue;
			}

			if ( microtime( true ) - WP_START_TIMESTAMP < $max_execution_time ) {
				if ( 'wordpress_size' === $name ) {
					$dir_size = recurse_dirsize( $path, $exclude, $max_execution_time );
				} else {
					$dir_size = recurse_dirsize( $path, null, $max_execution_time );
				}
			}

			if ( false === $dir_size ) {
				// Error reading.
				$results['size']  = __( 'The size cannot be calculated. The directory is not accessible. Usually caused by invalid permissions.' );
				$results['debug'] = 'not accessible';

				// Stop total size calculation.
				$size_total = null;
			} elseif ( null === $dir_size ) {
				// Timeout.
				$results['size']  = __( 'The directory size calculation has timed out. Usually caused by a very large number of sub-directories and files.' );
				$results['debug'] = 'timeout while calculating size';

				// Stop total size calculation.
				$size_total = null;
			} else {
				if ( null !== $size_total ) {
					$size_total += $dir_size;
				}

				$results['raw']   = $dir_size;
				$results['size']  = size_format( $dir_size, 2 );
				$results['debug'] = $results['size'] . " ({$dir_size} bytes)";
			}

			$all_sizes[ $name ] = $results;
		}

		if ( $size_db > 0 ) {
			$database_size = size_format( $size_db, 2 );

			$all_sizes['database_size'] = array(
				'raw'   => $size_db,
				'size'  => $database_size,
				'debug' => $database_size . " ({$size_db} bytes)",
			);
		} else {
			$all_sizes['database_size'] = array(
				'size'  => __( 'Not available' ),
				'debug' => 'not available',
			);
		}

		if ( null !== $size_total && $size_db > 0 ) {
			$total_size    = $size_total + $size_db;
			$total_size_mb = size_format( $total_size, 2 );

			$all_sizes['total_size'] = array(
				'raw'   => $total_size,
				'size'  => $total_size_mb,
				'debug' => $total_size_mb . " ({$total_size} bytes)",
			);
		} else {
			$all_sizes['total_size'] = array(
				'size'  => __( 'Total size is not available. Some errors were encountered when determining the size of your installation.' ),
				'debug' => 'not available',
			);
		}

		return $all_sizes;
	}
}
export.php000064400000062333151212616050006604 0ustar00<?php
/**
 * WordPress Export Administration API
 *
 * @package WordPress
 * @subpackage Administration
 */

/**
 * Version number for the export format.
 *
 * Bump this when something changes that might affect compatibility.
 *
 * @since 2.5.0
 */
define( 'WXR_VERSION', '1.2' );

/**
 * Generates the WXR export file for download.
 *
 * Default behavior is to export all content, however, note that post content will only
 * be exported for post types with the `can_export` argument enabled. Any posts with the
 * 'auto-draft' status will be skipped.
 *
 * @since 2.1.0
 * @since 5.7.0 Added the `post_modified` and `post_modified_gmt` fields to the export file.
 *
 * @global wpdb    $wpdb WordPress database abstraction object.
 * @global WP_Post $post Global post object.
 *
 * @param array $args {
 *     Optional. Arguments for generating the WXR export file for download. Default empty array.
 *
 *     @type string $content    Type of content to export. If set, only the post content of this post type
 *                              will be exported. Accepts 'all', 'post', 'page', 'attachment', or a defined
 *                              custom post. If an invalid custom post type is supplied, every post type for
 *                              which `can_export` is enabled will be exported instead. If a valid custom post
 *                              type is supplied but `can_export` is disabled, then 'posts' will be exported
 *                              instead. When 'all' is supplied, only post types with `can_export` enabled will
 *                              be exported. Default 'all'.
 *     @type string $author     Author to export content for. Only used when `$content` is 'post', 'page', or
 *                              'attachment'. Accepts false (all) or a specific author ID. Default false (all).
 *     @type string $category   Category (slug) to export content for. Used only when `$content` is 'post'. If
 *                              set, only post content assigned to `$category` will be exported. Accepts false
 *                              or a specific category slug. Default is false (all categories).
 *     @type string $start_date Start date to export content from. Expected date format is 'Y-m-d'. Used only
 *                              when `$content` is 'post', 'page' or 'attachment'. Default false (since the
 *                              beginning of time).
 *     @type string $end_date   End date to export content to. Expected date format is 'Y-m-d'. Used only when
 *                              `$content` is 'post', 'page' or 'attachment'. Default false (latest publish date).
 *     @type string $status     Post status to export posts for. Used only when `$content` is 'post' or 'page'.
 *                              Accepts false (all statuses except 'auto-draft'), or a specific status, i.e.
 *                              'publish', 'pending', 'draft', 'auto-draft', 'future', 'private', 'inherit', or
 *                              'trash'. Default false (all statuses except 'auto-draft').
 * }
 */
function export_wp( $args = array() ) {
	global $wpdb, $post;

	$defaults = array(
		'content'    => 'all',
		'author'     => false,
		'category'   => false,
		'start_date' => false,
		'end_date'   => false,
		'status'     => false,
	);
	$args     = wp_parse_args( $args, $defaults );

	/**
	 * Fires at the beginning of an export, before any headers are sent.
	 *
	 * @since 2.3.0
	 *
	 * @param array $args An array of export arguments.
	 */
	do_action( 'export_wp', $args );

	$sitename = sanitize_key( get_bloginfo( 'name' ) );
	if ( ! empty( $sitename ) ) {
		$sitename .= '.';
	}
	$date        = gmdate( 'Y-m-d' );
	$wp_filename = $sitename . 'WordPress.' . $date . '.xml';
	/**
	 * Filters the export filename.
	 *
	 * @since 4.4.0
	 *
	 * @param string $wp_filename The name of the file for download.
	 * @param string $sitename    The site name.
	 * @param string $date        Today's date, formatted.
	 */
	$filename = apply_filters( 'export_wp_filename', $wp_filename, $sitename, $date );

	header( 'Content-Description: File Transfer' );
	header( 'Content-Disposition: attachment; filename=' . $filename );
	header( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ), true );

	if ( 'all' !== $args['content'] && post_type_exists( $args['content'] ) ) {
		$ptype = get_post_type_object( $args['content'] );
		if ( ! $ptype->can_export ) {
			$args['content'] = 'post';
		}

		$where = $wpdb->prepare( "{$wpdb->posts}.post_type = %s", $args['content'] );
	} else {
		$post_types = get_post_types( array( 'can_export' => true ) );
		$esses      = array_fill( 0, count( $post_types ), '%s' );

		// phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
		$where = $wpdb->prepare( "{$wpdb->posts}.post_type IN (" . implode( ',', $esses ) . ')', $post_types );
	}

	if ( $args['status'] && ( 'post' === $args['content'] || 'page' === $args['content'] ) ) {
		$where .= $wpdb->prepare( " AND {$wpdb->posts}.post_status = %s", $args['status'] );
	} else {
		$where .= " AND {$wpdb->posts}.post_status != 'auto-draft'";
	}

	$join = '';
	if ( $args['category'] && 'post' === $args['content'] ) {
		$term = term_exists( $args['category'], 'category' );
		if ( $term ) {
			$join   = "INNER JOIN {$wpdb->term_relationships} ON ({$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id)";
			$where .= $wpdb->prepare( " AND {$wpdb->term_relationships}.term_taxonomy_id = %d", $term['term_taxonomy_id'] );
		}
	}

	if ( in_array( $args['content'], array( 'post', 'page', 'attachment' ), true ) ) {
		if ( $args['author'] ) {
			$where .= $wpdb->prepare( " AND {$wpdb->posts}.post_author = %d", $args['author'] );
		}

		if ( $args['start_date'] ) {
			$where .= $wpdb->prepare( " AND {$wpdb->posts}.post_date >= %s", gmdate( 'Y-m-d', strtotime( $args['start_date'] ) ) );
		}

		if ( $args['end_date'] ) {
			$where .= $wpdb->prepare( " AND {$wpdb->posts}.post_date < %s", gmdate( 'Y-m-d', strtotime( '+1 month', strtotime( $args['end_date'] ) ) ) );
		}
	}

	// Grab a snapshot of post IDs, just in case it changes during the export.
	$post_ids = $wpdb->get_col( "SELECT ID FROM {$wpdb->posts} $join WHERE $where" );

	// Get IDs for the attachments of each post, unless all content is already being exported.
	if ( ! in_array( $args['content'], array( 'all', 'attachment' ), true ) ) {
		// Array to hold all additional IDs (attachments and thumbnails).
		$additional_ids = array();

		// Create a copy of the post IDs array to avoid modifying the original array.
		$processing_ids = $post_ids;

		while ( $next_posts = array_splice( $processing_ids, 0, 20 ) ) {
			$posts_in     = array_map( 'absint', $next_posts );
			$placeholders = array_fill( 0, count( $posts_in ), '%d' );

			// Create a string for the placeholders.
			$in_placeholder = implode( ',', $placeholders );

			// Prepare the SQL statement for attachment ids.
			$attachment_ids = $wpdb->get_col(
				$wpdb->prepare(
					"
				SELECT ID
				FROM $wpdb->posts
				WHERE post_parent IN ($in_placeholder) AND post_type = 'attachment'
					",
					$posts_in
				)
			);

			$thumbnails_ids = $wpdb->get_col(
				$wpdb->prepare(
					"
				SELECT meta_value
				FROM $wpdb->postmeta
				WHERE $wpdb->postmeta.post_id IN ($in_placeholder)
				AND $wpdb->postmeta.meta_key = '_thumbnail_id'
					",
					$posts_in
				)
			);

			$additional_ids = array_merge( $additional_ids, $attachment_ids, $thumbnails_ids );
		}

		// Merge the additional IDs back with the original post IDs after processing all posts
		$post_ids = array_unique( array_merge( $post_ids, $additional_ids ) );
	}

	/*
	 * Get the requested terms ready, empty unless posts filtered by category
	 * or all content.
	 */
	$cats  = array();
	$tags  = array();
	$terms = array();
	if ( isset( $term ) && $term ) {
		$cat  = get_term( $term['term_id'], 'category' );
		$cats = array( $cat->term_id => $cat );
		unset( $term, $cat );
	} elseif ( 'all' === $args['content'] ) {
		$categories = (array) get_categories( array( 'get' => 'all' ) );
		$tags       = (array) get_tags( array( 'get' => 'all' ) );

		$custom_taxonomies = get_taxonomies( array( '_builtin' => false ) );
		$custom_terms      = (array) get_terms(
			array(
				'taxonomy' => $custom_taxonomies,
				'get'      => 'all',
			)
		);

		// Put categories in order with no child going before its parent.
		while ( $cat = array_shift( $categories ) ) {
			if ( ! $cat->parent || isset( $cats[ $cat->parent ] ) ) {
				$cats[ $cat->term_id ] = $cat;
			} else {
				$categories[] = $cat;
			}
		}

		// Put terms in order with no child going before its parent.
		while ( $t = array_shift( $custom_terms ) ) {
			if ( ! $t->parent || isset( $terms[ $t->parent ] ) ) {
				$terms[ $t->term_id ] = $t;
			} else {
				$custom_terms[] = $t;
			}
		}

		unset( $categories, $custom_taxonomies, $custom_terms );
	}

	/**
	 * Wraps given string in XML CDATA tag.
	 *
	 * @since 2.1.0
	 *
	 * @param string $str String to wrap in XML CDATA tag.
	 * @return string
	 */
	function wxr_cdata( $str ) {
		if ( ! wp_is_valid_utf8( $str ) ) {
			$str = utf8_encode( $str );
		}
		// $str = ent2ncr(esc_html($str));
		$str = '<![CDATA[' . str_replace( ']]>', ']]]]><![CDATA[>', $str ) . ']]>';

		return $str;
	}

	/**
	 * Returns the URL of the site.
	 *
	 * @since 2.5.0
	 *
	 * @return string Site URL.
	 */
	function wxr_site_url() {
		if ( is_multisite() ) {
			// Multisite: the base URL.
			return network_home_url();
		} else {
			// WordPress (single site): the site URL.
			return get_bloginfo_rss( 'url' );
		}
	}

	/**
	 * Outputs a cat_name XML tag from a given category object.
	 *
	 * @since 2.1.0
	 *
	 * @param WP_Term $category Category Object.
	 */
	function wxr_cat_name( $category ) {
		if ( empty( $category->name ) ) {
			return;
		}

		echo '<wp:cat_name>' . wxr_cdata( $category->name ) . "</wp:cat_name>\n";
	}

	/**
	 * Outputs a category_description XML tag from a given category object.
	 *
	 * @since 2.1.0
	 *
	 * @param WP_Term $category Category Object.
	 */
	function wxr_category_description( $category ) {
		if ( empty( $category->description ) ) {
			return;
		}

		echo '<wp:category_description>' . wxr_cdata( $category->description ) . "</wp:category_description>\n";
	}

	/**
	 * Outputs a tag_name XML tag from a given tag object.
	 *
	 * @since 2.3.0
	 *
	 * @param WP_Term $tag Tag Object.
	 */
	function wxr_tag_name( $tag ) {
		if ( empty( $tag->name ) ) {
			return;
		}

		echo '<wp:tag_name>' . wxr_cdata( $tag->name ) . "</wp:tag_name>\n";
	}

	/**
	 * Outputs a tag_description XML tag from a given tag object.
	 *
	 * @since 2.3.0
	 *
	 * @param WP_Term $tag Tag Object.
	 */
	function wxr_tag_description( $tag ) {
		if ( empty( $tag->description ) ) {
			return;
		}

		echo '<wp:tag_description>' . wxr_cdata( $tag->description ) . "</wp:tag_description>\n";
	}

	/**
	 * Outputs a term_name XML tag from a given term object.
	 *
	 * @since 2.9.0
	 *
	 * @param WP_Term $term Term Object.
	 */
	function wxr_term_name( $term ) {
		if ( empty( $term->name ) ) {
			return;
		}

		echo '<wp:term_name>' . wxr_cdata( $term->name ) . "</wp:term_name>\n";
	}

	/**
	 * Outputs a term_description XML tag from a given term object.
	 *
	 * @since 2.9.0
	 *
	 * @param WP_Term $term Term Object.
	 */
	function wxr_term_description( $term ) {
		if ( empty( $term->description ) ) {
			return;
		}

		echo "\t\t<wp:term_description>" . wxr_cdata( $term->description ) . "</wp:term_description>\n";
	}

	/**
	 * Outputs term meta XML tags for a given term object.
	 *
	 * @since 4.6.0
	 *
	 * @global wpdb $wpdb WordPress database abstraction object.
	 *
	 * @param WP_Term $term Term object.
	 */
	function wxr_term_meta( $term ) {
		global $wpdb;

		$termmeta = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->termmeta WHERE term_id = %d", $term->term_id ) );

		foreach ( $termmeta as $meta ) {
			/**
			 * Filters whether to selectively skip term meta used for WXR exports.
			 *
			 * Returning a truthy value from the filter will skip the current meta
			 * object from being exported.
			 *
			 * @since 4.6.0
			 *
			 * @param bool   $skip     Whether to skip the current piece of term meta. Default false.
			 * @param string $meta_key Current meta key.
			 * @param object $meta     Current meta object.
			 */
			if ( ! apply_filters( 'wxr_export_skip_termmeta', false, $meta->meta_key, $meta ) ) {
				printf( "\t\t<wp:termmeta>\n\t\t\t<wp:meta_key>%s</wp:meta_key>\n\t\t\t<wp:meta_value>%s</wp:meta_value>\n\t\t</wp:termmeta>\n", wxr_cdata( $meta->meta_key ), wxr_cdata( $meta->meta_value ) );
			}
		}
	}

	/**
	 * Outputs list of authors with posts.
	 *
	 * @since 3.1.0
	 *
	 * @global wpdb $wpdb WordPress database abstraction object.
	 *
	 * @param int[] $post_ids Optional. Array of post IDs to filter the query by.
	 */
	function wxr_authors_list( ?array $post_ids = null ) {
		global $wpdb;

		if ( ! empty( $post_ids ) ) {
			$post_ids       = array_map( 'absint', $post_ids );
			$post_id_chunks = array_chunk( $post_ids, 20 );
		} else {
			$post_id_chunks = array( array() );
		}

		$authors = array();

		foreach ( $post_id_chunks as $next_posts ) {
			$and = ! empty( $next_posts ) ? 'AND ID IN (' . implode( ', ', $next_posts ) . ')' : '';

			$results = $wpdb->get_results( "SELECT DISTINCT post_author FROM $wpdb->posts WHERE post_status != 'auto-draft' $and" );

			foreach ( (array) $results as $result ) {
				$authors[] = get_userdata( $result->post_author );
			}
		}

		$authors = array_filter( $authors );
		$authors = array_unique( $authors, SORT_REGULAR ); // Remove duplicate authors.

		foreach ( $authors as $author ) {
			echo "\t<wp:author>";
			echo '<wp:author_id>' . (int) $author->ID . '</wp:author_id>';
			echo '<wp:author_login>' . wxr_cdata( $author->user_login ) . '</wp:author_login>';
			echo '<wp:author_email>' . wxr_cdata( $author->user_email ) . '</wp:author_email>';
			echo '<wp:author_display_name>' . wxr_cdata( $author->display_name ) . '</wp:author_display_name>';
			echo '<wp:author_first_name>' . wxr_cdata( $author->first_name ) . '</wp:author_first_name>';
			echo '<wp:author_last_name>' . wxr_cdata( $author->last_name ) . '</wp:author_last_name>';
			echo "</wp:author>\n";
		}
	}

	/**
	 * Outputs all navigation menu terms.
	 *
	 * @since 3.1.0
	 */
	function wxr_nav_menu_terms() {
		$nav_menus = wp_get_nav_menus();
		if ( empty( $nav_menus ) || ! is_array( $nav_menus ) ) {
			return;
		}

		foreach ( $nav_menus as $menu ) {
			echo "\t<wp:term>";
			echo '<wp:term_id>' . (int) $menu->term_id . '</wp:term_id>';
			echo '<wp:term_taxonomy>nav_menu</wp:term_taxonomy>';
			echo '<wp:term_slug>' . wxr_cdata( $menu->slug ) . '</wp:term_slug>';
			wxr_term_name( $menu );
			echo "</wp:term>\n";
		}
	}

	/**
	 * Outputs list of taxonomy terms, in XML tag format, associated with a post.
	 *
	 * @since 2.3.0
	 */
	function wxr_post_taxonomy() {
		$post = get_post();

		$taxonomies = get_object_taxonomies( $post->post_type );
		if ( empty( $taxonomies ) ) {
			return;
		}
		$terms = wp_get_object_terms( $post->ID, $taxonomies );

		foreach ( (array) $terms as $term ) {
			echo "\t\t<category domain=\"{$term->taxonomy}\" nicename=\"{$term->slug}\">" . wxr_cdata( $term->name ) . "</category>\n";
		}
	}

	/**
	 * Determines whether to selectively skip post meta used for WXR exports.
	 *
	 * @since 3.3.0
	 *
	 * @param bool   $return_me Whether to skip the current post meta. Default false.
	 * @param string $meta_key  Meta key.
	 * @return bool
	 */
	function wxr_filter_postmeta( $return_me, $meta_key ) {
		if ( '_edit_lock' === $meta_key ) {
			$return_me = true;
		}
		return $return_me;
	}
	add_filter( 'wxr_export_skip_postmeta', 'wxr_filter_postmeta', 10, 2 );

	echo '<?xml version="1.0" encoding="' . get_bloginfo( 'charset' ) . "\" ?>\n";

	?>
<!-- This is a WordPress eXtended RSS file generated by WordPress as an export of your site. -->
<!-- It contains information about your site's posts, pages, comments, categories, and other content. -->
<!-- You may use this file to transfer that content from one site to another. -->
<!-- This file is not intended to serve as a complete backup of your site. -->

<!-- To import this information into a WordPress site follow these steps: -->
<!-- 1. Log in to that site as an administrator. -->
<!-- 2. Go to Tools: Import in the WordPress admin panel. -->
<!-- 3. Install the "WordPress" importer from the list. -->
<!-- 4. Activate & Run Importer. -->
<!-- 5. Upload this file using the form provided on that page. -->
<!-- 6. You will first be asked to map the authors in this export file to users -->
<!--    on the site. For each author, you may choose to map to an -->
<!--    existing user on the site or to create a new user. -->
<!-- 7. WordPress will then import each of the posts, pages, comments, categories, etc. -->
<!--    contained in this file into your site. -->

	<?php the_generator( 'export' ); ?>
<rss version="2.0"
	xmlns:excerpt="http://wordpress.org/export/<?php echo WXR_VERSION; ?>/excerpt/"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:wp="http://wordpress.org/export/<?php echo WXR_VERSION; ?>/"
>

<channel>
	<title><?php bloginfo_rss( 'name' ); ?></title>
	<link><?php bloginfo_rss( 'url' ); ?></link>
	<description><?php bloginfo_rss( 'description' ); ?></description>
	<pubDate><?php echo gmdate( 'D, d M Y H:i:s +0000' ); ?></pubDate>
	<language><?php bloginfo_rss( 'language' ); ?></language>
	<wp:wxr_version><?php echo WXR_VERSION; ?></wp:wxr_version>
	<wp:base_site_url><?php echo wxr_site_url(); ?></wp:base_site_url>
	<wp:base_blog_url><?php bloginfo_rss( 'url' ); ?></wp:base_blog_url>

	<?php wxr_authors_list( $post_ids ); ?>

	<?php foreach ( $cats as $c ) : ?>
	<wp:category>
		<wp:term_id><?php echo (int) $c->term_id; ?></wp:term_id>
		<wp:category_nicename><?php echo wxr_cdata( $c->slug ); ?></wp:category_nicename>
		<wp:category_parent><?php echo wxr_cdata( $c->parent ? $cats[ $c->parent ]->slug : '' ); ?></wp:category_parent>
		<?php
		wxr_cat_name( $c );
		wxr_category_description( $c );
		wxr_term_meta( $c );
		?>
	</wp:category>
	<?php endforeach; ?>
	<?php foreach ( $tags as $t ) : ?>
	<wp:tag>
		<wp:term_id><?php echo (int) $t->term_id; ?></wp:term_id>
		<wp:tag_slug><?php echo wxr_cdata( $t->slug ); ?></wp:tag_slug>
		<?php
		wxr_tag_name( $t );
		wxr_tag_description( $t );
		wxr_term_meta( $t );
		?>
	</wp:tag>
	<?php endforeach; ?>
	<?php foreach ( $terms as $t ) : ?>
	<wp:term>
		<wp:term_id><?php echo (int) $t->term_id; ?></wp:term_id>
		<wp:term_taxonomy><?php echo wxr_cdata( $t->taxonomy ); ?></wp:term_taxonomy>
		<wp:term_slug><?php echo wxr_cdata( $t->slug ); ?></wp:term_slug>
		<wp:term_parent><?php echo wxr_cdata( $t->parent ? $terms[ $t->parent ]->slug : '' ); ?></wp:term_parent>
		<?php
		wxr_term_name( $t );
		wxr_term_description( $t );
		wxr_term_meta( $t );
		?>
	</wp:term>
	<?php endforeach; ?>
	<?php
	if ( 'all' === $args['content'] ) {
		wxr_nav_menu_terms();
	}
	?>

	<?php
	/** This action is documented in wp-includes/feed-rss2.php */
	do_action( 'rss2_head' );
	?>

	<?php
	if ( $post_ids ) {
		/**
		 * @global WP_Query $wp_query WordPress Query object.
		 */
		global $wp_query;

		// Fake being in the loop.
		$wp_query->in_the_loop = true;

		// Fetch 20 posts at a time rather than loading the entire table into memory.
		while ( $next_posts = array_splice( $post_ids, 0, 20 ) ) {
			$where = 'WHERE ID IN (' . implode( ',', $next_posts ) . ')';
			$posts = $wpdb->get_results( "SELECT * FROM {$wpdb->posts} $where" );

			// Begin Loop.
			foreach ( $posts as $post ) {
				setup_postdata( $post );

				/**
				 * Filters the post title used for WXR exports.
				 *
				 * @since 5.7.0
				 *
				 * @param string $post_title Title of the current post.
				 */
				$title = wxr_cdata( apply_filters( 'the_title_export', $post->post_title ) );

				/**
				 * Filters the post content used for WXR exports.
				 *
				 * @since 2.5.0
				 *
				 * @param string $post_content Content of the current post.
				 */
				$content = wxr_cdata( apply_filters( 'the_content_export', $post->post_content ) );

				/**
				 * Filters the post excerpt used for WXR exports.
				 *
				 * @since 2.6.0
				 *
				 * @param string $post_excerpt Excerpt for the current post.
				 */
				$excerpt = wxr_cdata( apply_filters( 'the_excerpt_export', $post->post_excerpt ) );

				$is_sticky = is_sticky( $post->ID ) ? 1 : 0;
				?>
	<item>
		<title><?php echo $title; ?></title>
		<link><?php the_permalink_rss(); ?></link>
		<pubDate><?php echo mysql2date( 'D, d M Y H:i:s +0000', get_post_time( 'Y-m-d H:i:s', true ), false ); ?></pubDate>
		<dc:creator><?php echo wxr_cdata( get_the_author_meta( 'login' ) ); ?></dc:creator>
		<guid isPermaLink="false"><?php the_guid(); ?></guid>
		<description></description>
		<content:encoded><?php echo $content; ?></content:encoded>
		<excerpt:encoded><?php echo $excerpt; ?></excerpt:encoded>
		<wp:post_id><?php echo (int) $post->ID; ?></wp:post_id>
		<wp:post_date><?php echo wxr_cdata( $post->post_date ); ?></wp:post_date>
		<wp:post_date_gmt><?php echo wxr_cdata( $post->post_date_gmt ); ?></wp:post_date_gmt>
		<wp:post_modified><?php echo wxr_cdata( $post->post_modified ); ?></wp:post_modified>
		<wp:post_modified_gmt><?php echo wxr_cdata( $post->post_modified_gmt ); ?></wp:post_modified_gmt>
		<wp:comment_status><?php echo wxr_cdata( $post->comment_status ); ?></wp:comment_status>
		<wp:ping_status><?php echo wxr_cdata( $post->ping_status ); ?></wp:ping_status>
		<wp:post_name><?php echo wxr_cdata( $post->post_name ); ?></wp:post_name>
		<wp:status><?php echo wxr_cdata( $post->post_status ); ?></wp:status>
		<wp:post_parent><?php echo (int) $post->post_parent; ?></wp:post_parent>
		<wp:menu_order><?php echo (int) $post->menu_order; ?></wp:menu_order>
		<wp:post_type><?php echo wxr_cdata( $post->post_type ); ?></wp:post_type>
		<wp:post_password><?php echo wxr_cdata( $post->post_password ); ?></wp:post_password>
		<wp:is_sticky><?php echo (int) $is_sticky; ?></wp:is_sticky>
				<?php	if ( 'attachment' === $post->post_type ) : ?>
		<wp:attachment_url><?php echo wxr_cdata( wp_get_attachment_url( $post->ID ) ); ?></wp:attachment_url>
	<?php endif; ?>
				<?php wxr_post_taxonomy(); ?>
				<?php
				$postmeta = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->postmeta WHERE post_id = %d", $post->ID ) );
				foreach ( $postmeta as $meta ) :
					/**
					 * Filters whether to selectively skip post meta used for WXR exports.
					 *
					 * Returning a truthy value from the filter will skip the current meta
					 * object from being exported.
					 *
					 * @since 3.3.0
					 *
					 * @param bool   $skip     Whether to skip the current post meta. Default false.
					 * @param string $meta_key Current meta key.
					 * @param object $meta     Current meta object.
					 */
					if ( apply_filters( 'wxr_export_skip_postmeta', false, $meta->meta_key, $meta ) ) {
						continue;
					}
					?>
		<wp:postmeta>
		<wp:meta_key><?php echo wxr_cdata( $meta->meta_key ); ?></wp:meta_key>
		<wp:meta_value><?php echo wxr_cdata( $meta->meta_value ); ?></wp:meta_value>
		</wp:postmeta>
					<?php
	endforeach;

				$_comments = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved <> 'spam'", $post->ID ) );
				$comments  = array_map( 'get_comment', $_comments );
				foreach ( $comments as $c ) :
					?>
		<wp:comment>
			<wp:comment_id><?php echo (int) $c->comment_ID; ?></wp:comment_id>
			<wp:comment_author><?php echo wxr_cdata( $c->comment_author ); ?></wp:comment_author>
			<wp:comment_author_email><?php echo wxr_cdata( $c->comment_author_email ); ?></wp:comment_author_email>
			<wp:comment_author_url><?php echo sanitize_url( $c->comment_author_url ); ?></wp:comment_author_url>
			<wp:comment_author_IP><?php echo wxr_cdata( $c->comment_author_IP ); ?></wp:comment_author_IP>
			<wp:comment_date><?php echo wxr_cdata( $c->comment_date ); ?></wp:comment_date>
			<wp:comment_date_gmt><?php echo wxr_cdata( $c->comment_date_gmt ); ?></wp:comment_date_gmt>
			<wp:comment_content><?php echo wxr_cdata( $c->comment_content ); ?></wp:comment_content>
			<wp:comment_approved><?php echo wxr_cdata( $c->comment_approved ); ?></wp:comment_approved>
			<wp:comment_type><?php echo wxr_cdata( $c->comment_type ); ?></wp:comment_type>
			<wp:comment_parent><?php echo (int) $c->comment_parent; ?></wp:comment_parent>
			<wp:comment_user_id><?php echo (int) $c->user_id; ?></wp:comment_user_id>
					<?php
					$c_meta = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->commentmeta WHERE comment_id = %d", $c->comment_ID ) );
					foreach ( $c_meta as $meta ) :
						/**
						 * Filters whether to selectively skip comment meta used for WXR exports.
						 *
						 * Returning a truthy value from the filter will skip the current meta
						 * object from being exported.
						 *
						 * @since 4.0.0
						 *
						 * @param bool   $skip     Whether to skip the current comment meta. Default false.
						 * @param string $meta_key Current meta key.
						 * @param object $meta     Current meta object.
						 */
						if ( apply_filters( 'wxr_export_skip_commentmeta', false, $meta->meta_key, $meta ) ) {
							continue;
						}
						?>
	<wp:commentmeta>
	<wp:meta_key><?php echo wxr_cdata( $meta->meta_key ); ?></wp:meta_key>
			<wp:meta_value><?php echo wxr_cdata( $meta->meta_value ); ?></wp:meta_value>
			</wp:commentmeta>
					<?php	endforeach; ?>
		</wp:comment>
			<?php	endforeach; ?>
		</item>
				<?php
			}
		}
	}
	?>
</channel>
</rss>
	<?php
}
class-wp-post-comments-list-table.php000064400000002655151212616050013661 0ustar00<?php
/**
 * List Table API: WP_Post_Comments_List_Table class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 4.4.0
 */

/**
 * Core class used to implement displaying post comments in a list table.
 *
 * @since 3.1.0
 *
 * @see WP_Comments_List_Table
 */
class WP_Post_Comments_List_Table extends WP_Comments_List_Table {

	/**
	 * @return array
	 */
	protected function get_column_info() {
		return array(
			array(
				'author'  => __( 'Author' ),
				'comment' => _x( 'Comment', 'column name' ),
			),
			array(),
			array(),
			'comment',
		);
	}

	/**
	 * @return array
	 */
	protected function get_table_classes() {
		$classes   = parent::get_table_classes();
		$classes[] = 'wp-list-table';
		$classes[] = 'comments-box';
		return $classes;
	}

	/**
	 * @param bool $output_empty
	 */
	public function display( $output_empty = false ) {
		$singular = $this->_args['singular'];

		wp_nonce_field( 'fetch-list-' . get_class( $this ), '_ajax_fetch_list_nonce' );
		?>
<table class="<?php echo implode( ' ', $this->get_table_classes() ); ?>" style="display:none;">
	<tbody id="the-comment-list"
		<?php
		if ( $singular ) {
			echo " data-wp-lists='list:$singular'";
		}
		?>
		>
		<?php
		if ( ! $output_empty ) {
			$this->display_rows_or_placeholder();
		}
		?>
	</tbody>
</table>
		<?php
	}

	/**
	 * @param bool $comment_status
	 * @return int
	 */
	public function get_per_page( $comment_status = false ) {
		return 10;
	}
}
class-wp-ms-users-list-table.php000064400000036547151212616050012636 0ustar00<?php
/**
 * List Table API: WP_MS_Users_List_Table class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 3.1.0
 */

/**
 * Core class used to implement displaying users in a list table for the network admin.
 *
 * @since 3.1.0
 *
 * @see WP_List_Table
 */
class WP_MS_Users_List_Table extends WP_List_Table {
	/**
	 * @return bool
	 */
	public function ajax_user_can() {
		return current_user_can( 'manage_network_users' );
	}

	/**
	 * @global string $mode       List table view mode.
	 * @global string $usersearch
	 * @global string $role
	 */
	public function prepare_items() {
		global $mode, $usersearch, $role;

		if ( ! empty( $_REQUEST['mode'] ) ) {
			$mode = 'excerpt' === $_REQUEST['mode'] ? 'excerpt' : 'list';
			set_user_setting( 'network_users_list_mode', $mode );
		} else {
			$mode = get_user_setting( 'network_users_list_mode', 'list' );
		}

		$usersearch = isset( $_REQUEST['s'] ) ? wp_unslash( trim( $_REQUEST['s'] ) ) : '';

		$users_per_page = $this->get_items_per_page( 'users_network_per_page' );

		$role = isset( $_REQUEST['role'] ) ? $_REQUEST['role'] : '';

		$paged = $this->get_pagenum();

		$args = array(
			'number'  => $users_per_page,
			'offset'  => ( $paged - 1 ) * $users_per_page,
			'search'  => $usersearch,
			'blog_id' => 0,
			'fields'  => 'all_with_meta',
		);

		if ( wp_is_large_network( 'users' ) ) {
			$args['search'] = ltrim( $args['search'], '*' );
		} elseif ( '' !== $args['search'] ) {
			$args['search'] = trim( $args['search'], '*' );
			$args['search'] = '*' . $args['search'] . '*';
		}

		if ( 'super' === $role ) {
			$args['login__in'] = get_super_admins();
		}

		/*
		 * If the network is large and a search is not being performed,
		 * show only the latest users with no paging in order to avoid
		 * expensive count queries.
		 */
		if ( ! $usersearch && wp_is_large_network( 'users' ) ) {
			if ( ! isset( $_REQUEST['orderby'] ) ) {
				$_GET['orderby']     = 'id';
				$_REQUEST['orderby'] = 'id';
			}
			if ( ! isset( $_REQUEST['order'] ) ) {
				$_GET['order']     = 'DESC';
				$_REQUEST['order'] = 'DESC';
			}
			$args['count_total'] = false;
		}

		if ( isset( $_REQUEST['orderby'] ) ) {
			$args['orderby'] = $_REQUEST['orderby'];
		}

		if ( isset( $_REQUEST['order'] ) ) {
			$args['order'] = $_REQUEST['order'];
		}

		/** This filter is documented in wp-admin/includes/class-wp-users-list-table.php */
		$args = apply_filters( 'users_list_table_query_args', $args );

		// Query the user IDs for this page.
		$wp_user_search = new WP_User_Query( $args );

		$this->items = $wp_user_search->get_results();

		$this->set_pagination_args(
			array(
				'total_items' => $wp_user_search->get_total(),
				'per_page'    => $users_per_page,
			)
		);
	}

	/**
	 * @return array
	 */
	protected function get_bulk_actions() {
		$actions = array();
		if ( current_user_can( 'delete_users' ) ) {
			$actions['delete'] = __( 'Delete' );
		}
		$actions['spam']    = _x( 'Mark as spam', 'user' );
		$actions['notspam'] = _x( 'Not spam', 'user' );

		return $actions;
	}

	/**
	 */
	public function no_items() {
		_e( 'No users found.' );
	}

	/**
	 * @global string $role
	 * @return array
	 */
	protected function get_views() {
		global $role;

		$total_users  = get_user_count();
		$super_admins = get_super_admins();
		$total_admins = count( $super_admins );

		$role_links        = array();
		$role_links['all'] = array(
			'url'     => network_admin_url( 'users.php' ),
			'label'   => sprintf(
				/* translators: Number of users. */
				_nx(
					'All <span class="count">(%s)</span>',
					'All <span class="count">(%s)</span>',
					$total_users,
					'users'
				),
				number_format_i18n( $total_users )
			),
			'current' => 'super' !== $role,
		);

		$role_links['super'] = array(
			'url'     => network_admin_url( 'users.php?role=super' ),
			'label'   => sprintf(
				/* translators: Number of users. */
				_n(
					'Super Admin <span class="count">(%s)</span>',
					'Super Admins <span class="count">(%s)</span>',
					$total_admins
				),
				number_format_i18n( $total_admins )
			),
			'current' => 'super' === $role,
		);

		return $this->get_views_links( $role_links );
	}

	/**
	 * @global string $mode List table view mode.
	 *
	 * @param string $which
	 */
	protected function pagination( $which ) {
		global $mode;

		parent::pagination( $which );

		if ( 'top' === $which ) {
			$this->view_switcher( $mode );
		}
	}

	/**
	 * @return string[] Array of column titles keyed by their column name.
	 */
	public function get_columns() {
		$users_columns = array(
			'cb'         => '<input type="checkbox" />',
			'username'   => __( 'Username' ),
			'name'       => __( 'Name' ),
			'email'      => __( 'Email' ),
			'registered' => _x( 'Registered', 'user' ),
			'blogs'      => __( 'Sites' ),
		);
		/**
		 * Filters the columns displayed in the Network Admin Users list table.
		 *
		 * @since MU (3.0.0)
		 *
		 * @param string[] $users_columns An array of user columns. Default 'cb', 'username',
		 *                                'name', 'email', 'registered', 'blogs'.
		 */
		return apply_filters( 'wpmu_users_columns', $users_columns );
	}

	/**
	 * @return array
	 */
	protected function get_sortable_columns() {
		return array(
			'username'   => array( 'login', false, __( 'Username' ), __( 'Table ordered by Username.' ), 'asc' ),
			'name'       => array( 'name', false, __( 'Name' ), __( 'Table ordered by Name.' ) ),
			'email'      => array( 'email', false, __( 'E-mail' ), __( 'Table ordered by E-mail.' ) ),
			'registered' => array( 'id', false, _x( 'Registered', 'user' ), __( 'Table ordered by User Registered Date.' ) ),
		);
	}

	/**
	 * Handles the checkbox column output.
	 *
	 * @since 4.3.0
	 * @since 5.9.0 Renamed `$user` to `$item` to match parent class for PHP 8 named parameter support.
	 *
	 * @param WP_User $item The current WP_User object.
	 */
	public function column_cb( $item ) {
		// Restores the more descriptive, specific name for use within this method.
		$user = $item;

		if ( is_super_admin( $user->ID ) ) {
			return;
		}
		?>
		<input type="checkbox" id="blog_<?php echo $user->ID; ?>" name="allusers[]" value="<?php echo esc_attr( $user->ID ); ?>" />
		<label for="blog_<?php echo $user->ID; ?>">
			<span class="screen-reader-text">
			<?php
			/* translators: Hidden accessibility text. %s: User login. */
			printf( __( 'Select %s' ), $user->user_login );
			?>
			</span>
		</label>
		<?php
	}

	/**
	 * Handles the ID column output.
	 *
	 * @since 4.4.0
	 *
	 * @param WP_User $user The current WP_User object.
	 */
	public function column_id( $user ) {
		echo $user->ID;
	}

	/**
	 * Handles the username column output.
	 *
	 * @since 4.3.0
	 *
	 * @param WP_User $user The current WP_User object.
	 */
	public function column_username( $user ) {
		$super_admins = get_super_admins();
		$avatar       = get_avatar( $user->user_email, 32 );

		echo $avatar;

		if ( current_user_can( 'edit_user', $user->ID ) ) {
			$edit_link = esc_url( add_query_arg( 'wp_http_referer', urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ), get_edit_user_link( $user->ID ) ) );
			$edit      = "<a href=\"{$edit_link}\">{$user->user_login}</a>";
		} else {
			$edit = $user->user_login;
		}

		?>
		<strong>
			<?php
			echo $edit;

			if ( in_array( $user->user_login, $super_admins, true ) ) {
				echo ' &mdash; ' . __( 'Super Admin' );
			}
			?>
		</strong>
		<?php
	}

	/**
	 * Handles the name column output.
	 *
	 * @since 4.3.0
	 *
	 * @param WP_User $user The current WP_User object.
	 */
	public function column_name( $user ) {
		if ( $user->first_name && $user->last_name ) {
			printf(
				/* translators: 1: User's first name, 2: Last name. */
				_x( '%1$s %2$s', 'Display name based on first name and last name' ),
				$user->first_name,
				$user->last_name
			);
		} elseif ( $user->first_name ) {
			echo $user->first_name;
		} elseif ( $user->last_name ) {
			echo $user->last_name;
		} else {
			echo '<span aria-hidden="true">&#8212;</span><span class="screen-reader-text">' .
				/* translators: Hidden accessibility text. */
				_x( 'Unknown', 'name' ) .
			'</span>';
		}
	}

	/**
	 * Handles the email column output.
	 *
	 * @since 4.3.0
	 *
	 * @param WP_User $user The current WP_User object.
	 */
	public function column_email( $user ) {
		echo "<a href='" . esc_url( "mailto:$user->user_email" ) . "'>$user->user_email</a>";
	}

	/**
	 * Handles the registered date column output.
	 *
	 * @since 4.3.0
	 *
	 * @global string $mode List table view mode.
	 *
	 * @param WP_User $user The current WP_User object.
	 */
	public function column_registered( $user ) {
		global $mode;
		if ( 'list' === $mode ) {
			$date = __( 'Y/m/d' );
		} else {
			$date = __( 'Y/m/d g:i:s a' );
		}
		echo mysql2date( $date, $user->user_registered );
	}

	/**
	 * @since 4.3.0
	 *
	 * @param WP_User $user
	 * @param string  $classes
	 * @param string  $data
	 * @param string  $primary
	 */
	protected function _column_blogs( $user, $classes, $data, $primary ) {
		echo '<td class="', $classes, ' has-row-actions" ', $data, '>';
		echo $this->column_blogs( $user );
		echo $this->handle_row_actions( $user, 'blogs', $primary );
		echo '</td>';
	}

	/**
	 * Handles the sites column output.
	 *
	 * @since 4.3.0
	 *
	 * @param WP_User $user The current WP_User object.
	 */
	public function column_blogs( $user ) {
		$blogs = get_blogs_of_user( $user->ID, true );
		if ( ! is_array( $blogs ) ) {
			return;
		}

		foreach ( $blogs as $site ) {
			if ( ! can_edit_network( $site->site_id ) ) {
				continue;
			}

			$path         = ( '/' === $site->path ) ? '' : $site->path;
			$site_classes = array( 'site-' . $site->site_id );

			/**
			 * Filters the span class for a site listing on the multisite user list table.
			 *
			 * @since 5.2.0
			 *
			 * @param string[] $site_classes Array of class names used within the span tag.
			 *                               Default "site-#" with the site's network ID.
			 * @param int      $site_id      Site ID.
			 * @param int      $network_id   Network ID.
			 * @param WP_User  $user         WP_User object.
			 */
			$site_classes = apply_filters( 'ms_user_list_site_class', $site_classes, $site->userblog_id, $site->site_id, $user );

			if ( is_array( $site_classes ) && ! empty( $site_classes ) ) {
				$site_classes = array_map( 'sanitize_html_class', array_unique( $site_classes ) );
				echo '<span class="' . esc_attr( implode( ' ', $site_classes ) ) . '">';
			} else {
				echo '<span>';
			}

			echo '<a href="' . esc_url( network_admin_url( 'site-info.php?id=' . $site->userblog_id ) ) . '">' . str_replace( '.' . get_network()->domain, '', $site->domain . $path ) . '</a>';
			echo ' <small class="row-actions">';

			$actions         = array();
			$actions['edit'] = '<a href="' . esc_url( network_admin_url( 'site-info.php?id=' . $site->userblog_id ) ) . '">' . __( 'Edit' ) . '</a>';

			$class = '';
			if ( 1 === (int) $site->spam ) {
				$class .= 'site-spammed ';
			}
			if ( 1 === (int) $site->mature ) {
				$class .= 'site-mature ';
			}
			if ( 1 === (int) $site->deleted ) {
				$class .= 'site-deleted ';
			}
			if ( 1 === (int) $site->archived ) {
				$class .= 'site-archived ';
			}

			$actions['view'] = '<a class="' . $class . '" href="' . esc_url( get_home_url( $site->userblog_id ) ) . '">' . __( 'View' ) . '</a>';

			/**
			 * Filters the action links displayed next the sites a user belongs to
			 * in the Network Admin Users list table.
			 *
			 * @since 3.1.0
			 *
			 * @param string[] $actions     An array of action links to be displayed. Default 'Edit', 'View'.
			 * @param int      $userblog_id The site ID.
			 */
			$actions = apply_filters( 'ms_user_list_site_actions', $actions, $site->userblog_id );

			$action_count = count( $actions );

			$i = 0;

			foreach ( $actions as $action => $link ) {
				++$i;

				$separator = ( $i < $action_count ) ? ' | ' : '';

				echo "<span class='$action'>{$link}{$separator}</span>";
			}

			echo '</small></span><br />';
		}
	}

	/**
	 * Handles the default column output.
	 *
	 * @since 4.3.0
	 * @since 5.9.0 Renamed `$user` to `$item` to match parent class for PHP 8 named parameter support.
	 *
	 * @param WP_User $item        The current WP_User object.
	 * @param string  $column_name The current column name.
	 */
	public function column_default( $item, $column_name ) {
		// Restores the more descriptive, specific name for use within this method.
		$user = $item;

		/** This filter is documented in wp-admin/includes/class-wp-users-list-table.php */
		$column_output = apply_filters( 'manage_users_custom_column', '', $column_name, $user->ID );

		/**
		 * Filters the display output of custom columns in the Network Users list table.
		 *
		 * @since 6.8.0
		 *
		 * @param string $output      Custom column output. Default empty.
		 * @param string $column_name Name of the custom column.
		 * @param int    $user_id     ID of the currently-listed user.
		 */
		echo apply_filters( 'manage_users-network_custom_column', $column_output, $column_name, $user->ID );
	}

	/**
	 * Generates the list table rows.
	 *
	 * @since 3.1.0
	 */
	public function display_rows() {
		foreach ( $this->items as $user ) {
			$class = '';

			$status_list = array(
				'spam'    => 'site-spammed',
				'deleted' => 'site-deleted',
			);

			foreach ( $status_list as $status => $col ) {
				if ( $user->$status ) {
					$class .= " $col";
				}
			}

			?>
			<tr class="<?php echo trim( $class ); ?>">
				<?php $this->single_row_columns( $user ); ?>
			</tr>
			<?php
		}
	}

	/**
	 * Gets the name of the default primary column.
	 *
	 * @since 4.3.0
	 *
	 * @return string Name of the default primary column, in this case, 'username'.
	 */
	protected function get_default_primary_column_name() {
		return 'username';
	}

	/**
	 * Generates and displays row action links.
	 *
	 * @since 4.3.0
	 * @since 5.9.0 Renamed `$user` to `$item` to match parent class for PHP 8 named parameter support.
	 *
	 * @param WP_User $item        User being acted upon.
	 * @param string  $column_name Current column name.
	 * @param string  $primary     Primary column name.
	 * @return string Row actions output for users in Multisite, or an empty string
	 *                if the current column is not the primary column.
	 */
	protected function handle_row_actions( $item, $column_name, $primary ) {
		if ( $primary !== $column_name ) {
			return '';
		}

		// Restores the more descriptive, specific name for use within this method.
		$user = $item;

		$super_admins = get_super_admins();
		$actions      = array();

		if ( current_user_can( 'edit_user', $user->ID ) ) {
			$edit_link       = esc_url( add_query_arg( 'wp_http_referer', urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ), get_edit_user_link( $user->ID ) ) );
			$actions['edit'] = '<a href="' . $edit_link . '">' . __( 'Edit' ) . '</a>';
		}

		if ( current_user_can( 'delete_user', $user->ID ) && ! in_array( $user->user_login, $super_admins, true ) ) {
			$actions['delete'] = '<a href="' . esc_url( network_admin_url( add_query_arg( '_wp_http_referer', urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ), wp_nonce_url( 'users.php', 'deleteuser' ) . '&amp;action=deleteuser&amp;id=' . $user->ID ) ) ) . '" class="delete">' . __( 'Delete' ) . '</a>';
		}

		/**
		 * Filters the action links displayed under each user in the Network Admin Users list table.
		 *
		 * @since 3.2.0
		 *
		 * @param string[] $actions An array of action links to be displayed. Default 'Edit', 'Delete'.
		 * @param WP_User  $user    WP_User object.
		 */
		$actions = apply_filters( 'ms_user_row_actions', $actions, $user );

		return $this->row_actions( $actions );
	}
}
class-wp-plugins-list-table.php000064400000160702151212616050012530 0ustar00<?php
/**
 * List Table API: WP_Plugins_List_Table class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 3.1.0
 */

/**
 * Core class used to implement displaying installed plugins in a list table.
 *
 * @since 3.1.0
 *
 * @see WP_List_Table
 */
class WP_Plugins_List_Table extends WP_List_Table {
	/**
	 * Whether to show the auto-updates UI.
	 *
	 * @since 5.5.0
	 *
	 * @var bool True if auto-updates UI is to be shown, false otherwise.
	 */
	protected $show_autoupdates = true;

	/**
	 * Constructor.
	 *
	 * @since 3.1.0
	 *
	 * @see WP_List_Table::__construct() for more information on default arguments.
	 *
	 * @global string $status
	 * @global int    $page
	 *
	 * @param array $args An associative array of arguments.
	 */
	public function __construct( $args = array() ) {
		global $status, $page;

		parent::__construct(
			array(
				'plural' => 'plugins',
				'screen' => isset( $args['screen'] ) ? $args['screen'] : null,
			)
		);

		$allowed_statuses = array( 'active', 'inactive', 'recently_activated', 'upgrade', 'mustuse', 'dropins', 'search', 'paused', 'auto-update-enabled', 'auto-update-disabled' );

		$status = 'all';
		if ( isset( $_REQUEST['plugin_status'] ) && in_array( $_REQUEST['plugin_status'], $allowed_statuses, true ) ) {
			$status = $_REQUEST['plugin_status'];
		}

		if ( isset( $_REQUEST['s'] ) ) {
			$_SERVER['REQUEST_URI'] = add_query_arg( 's', wp_unslash( $_REQUEST['s'] ) );
		}

		$page = $this->get_pagenum();

		$this->show_autoupdates = wp_is_auto_update_enabled_for_type( 'plugin' )
			&& current_user_can( 'update_plugins' )
			&& ( ! is_multisite() || $this->screen->in_admin( 'network' ) );
	}

	/**
	 * @return array
	 */
	protected function get_table_classes() {
		return array( 'widefat', $this->_args['plural'] );
	}

	/**
	 * @return bool
	 */
	public function ajax_user_can() {
		return current_user_can( 'activate_plugins' );
	}

	/**
	 * @global string $status
	 * @global array  $plugins
	 * @global array  $totals
	 * @global int    $page
	 * @global string $orderby
	 * @global string $order
	 * @global string $s
	 */
	public function prepare_items() {
		global $status, $plugins, $totals, $page, $orderby, $order, $s;

		$orderby = ! empty( $_REQUEST['orderby'] ) ? sanitize_text_field( $_REQUEST['orderby'] ) : '';
		$order   = ! empty( $_REQUEST['order'] ) ? sanitize_text_field( $_REQUEST['order'] ) : '';

		/**
		 * Filters the full array of plugins to list in the Plugins list table.
		 *
		 * @since 3.0.0
		 *
		 * @see get_plugins()
		 *
		 * @param array $all_plugins An array of plugins to display in the list table.
		 */
		$all_plugins = apply_filters( 'all_plugins', get_plugins() );

		$plugins = array(
			'all'                => $all_plugins,
			'search'             => array(),
			'active'             => array(),
			'inactive'           => array(),
			'recently_activated' => array(),
			'upgrade'            => array(),
			'mustuse'            => array(),
			'dropins'            => array(),
			'paused'             => array(),
		);
		if ( $this->show_autoupdates ) {
			$auto_updates = (array) get_site_option( 'auto_update_plugins', array() );

			$plugins['auto-update-enabled']  = array();
			$plugins['auto-update-disabled'] = array();
		}

		$screen = $this->screen;

		if ( ! is_multisite() || ( $screen->in_admin( 'network' ) && current_user_can( 'manage_network_plugins' ) ) ) {

			/**
			 * Filters whether to display the advanced plugins list table.
			 *
			 * There are two types of advanced plugins - must-use and drop-ins -
			 * which can be used in a single site or Multisite network.
			 *
			 * The $type parameter allows you to differentiate between the type of advanced
			 * plugins to filter the display of. Contexts include 'mustuse' and 'dropins'.
			 *
			 * @since 3.0.0
			 *
			 * @param bool   $show Whether to show the advanced plugins for the specified
			 *                     plugin type. Default true.
			 * @param string $type The plugin type. Accepts 'mustuse', 'dropins'.
			 */
			if ( apply_filters( 'show_advanced_plugins', true, 'mustuse' ) ) {
				$plugins['mustuse'] = get_mu_plugins();
			}

			/** This action is documented in wp-admin/includes/class-wp-plugins-list-table.php */
			if ( apply_filters( 'show_advanced_plugins', true, 'dropins' ) ) {
				$plugins['dropins'] = get_dropins();
			}

			if ( current_user_can( 'update_plugins' ) ) {
				$current = get_site_transient( 'update_plugins' );
				foreach ( (array) $plugins['all'] as $plugin_file => $plugin_data ) {
					if ( isset( $current->response[ $plugin_file ] ) ) {
						$plugins['all'][ $plugin_file ]['update'] = true;
						$plugins['upgrade'][ $plugin_file ]       = $plugins['all'][ $plugin_file ];
					}
				}
			}
		}

		if ( ! $screen->in_admin( 'network' ) ) {
			$show = current_user_can( 'manage_network_plugins' );
			/**
			 * Filters whether to display network-active plugins alongside plugins active for the current site.
			 *
			 * This also controls the display of inactive network-only plugins (plugins with
			 * "Network: true" in the plugin header).
			 *
			 * Plugins cannot be network-activated or network-deactivated from this screen.
			 *
			 * @since 4.4.0
			 *
			 * @param bool $show Whether to show network-active plugins. Default is whether the current
			 *                   user can manage network plugins (ie. a Super Admin).
			 */
			$show_network_active = apply_filters( 'show_network_active_plugins', $show );
		}

		if ( $screen->in_admin( 'network' ) ) {
			$recently_activated = get_site_option( 'recently_activated', array() );
		} else {
			$recently_activated = get_option( 'recently_activated', array() );
		}

		foreach ( $recently_activated as $key => $time ) {
			if ( $time + WEEK_IN_SECONDS < time() ) {
				unset( $recently_activated[ $key ] );
			}
		}

		if ( $screen->in_admin( 'network' ) ) {
			update_site_option( 'recently_activated', $recently_activated );
		} else {
			update_option( 'recently_activated', $recently_activated, false );
		}

		$plugin_info = get_site_transient( 'update_plugins' );

		foreach ( (array) $plugins['all'] as $plugin_file => $plugin_data ) {
			// Extra info if known. array_merge() ensures $plugin_data has precedence if keys collide.
			if ( isset( $plugin_info->response[ $plugin_file ] ) ) {
				$plugin_data = array_merge( (array) $plugin_info->response[ $plugin_file ], array( 'update-supported' => true ), $plugin_data );
			} elseif ( isset( $plugin_info->no_update[ $plugin_file ] ) ) {
				$plugin_data = array_merge( (array) $plugin_info->no_update[ $plugin_file ], array( 'update-supported' => true ), $plugin_data );
			} elseif ( empty( $plugin_data['update-supported'] ) ) {
				$plugin_data['update-supported'] = false;
			}

			/*
			 * Create the payload that's used for the auto_update_plugin filter.
			 * This is the same data contained within $plugin_info->(response|no_update) however
			 * not all plugins will be contained in those keys, this avoids unexpected warnings.
			 */
			$filter_payload = array(
				'id'            => $plugin_file,
				'slug'          => '',
				'plugin'        => $plugin_file,
				'new_version'   => '',
				'url'           => '',
				'package'       => '',
				'icons'         => array(),
				'banners'       => array(),
				'banners_rtl'   => array(),
				'tested'        => '',
				'requires_php'  => '',
				'compatibility' => new stdClass(),
			);

			$filter_payload = (object) wp_parse_args( $plugin_data, $filter_payload );

			$auto_update_forced = wp_is_auto_update_forced_for_item( 'plugin', null, $filter_payload );

			if ( ! is_null( $auto_update_forced ) ) {
				$plugin_data['auto-update-forced'] = $auto_update_forced;
			}

			$plugins['all'][ $plugin_file ] = $plugin_data;
			// Make sure that $plugins['upgrade'] also receives the extra info since it is used on ?plugin_status=upgrade.
			if ( isset( $plugins['upgrade'][ $plugin_file ] ) ) {
				$plugins['upgrade'][ $plugin_file ] = $plugin_data;
			}

			// Filter into individual sections.
			if ( is_multisite() && ! $screen->in_admin( 'network' ) && is_network_only_plugin( $plugin_file ) && ! is_plugin_active( $plugin_file ) ) {
				if ( $show_network_active ) {
					// On the non-network screen, show inactive network-only plugins if allowed.
					$plugins['inactive'][ $plugin_file ] = $plugin_data;
				} else {
					// On the non-network screen, filter out network-only plugins as long as they're not individually active.
					unset( $plugins['all'][ $plugin_file ] );
				}
			} elseif ( ! $screen->in_admin( 'network' ) && is_plugin_active_for_network( $plugin_file ) ) {
				if ( $show_network_active ) {
					// On the non-network screen, show network-active plugins if allowed.
					$plugins['active'][ $plugin_file ] = $plugin_data;
				} else {
					// On the non-network screen, filter out network-active plugins.
					unset( $plugins['all'][ $plugin_file ] );
				}
			} elseif ( ( ! $screen->in_admin( 'network' ) && is_plugin_active( $plugin_file ) )
				|| ( $screen->in_admin( 'network' ) && is_plugin_active_for_network( $plugin_file ) ) ) {
				/*
				 * On the non-network screen, populate the active list with plugins that are individually activated.
				 * On the network admin screen, populate the active list with plugins that are network-activated.
				 */
				$plugins['active'][ $plugin_file ] = $plugin_data;

				if ( ! $screen->in_admin( 'network' ) && is_plugin_paused( $plugin_file ) ) {
					$plugins['paused'][ $plugin_file ] = $plugin_data;
				}
			} else {
				if ( isset( $recently_activated[ $plugin_file ] ) ) {
					// Populate the recently activated list with plugins that have been recently activated.
					$plugins['recently_activated'][ $plugin_file ] = $plugin_data;
				}
				// Populate the inactive list with plugins that aren't activated.
				$plugins['inactive'][ $plugin_file ] = $plugin_data;
			}

			if ( $this->show_autoupdates ) {
				$enabled = in_array( $plugin_file, $auto_updates, true ) && $plugin_data['update-supported'];
				if ( isset( $plugin_data['auto-update-forced'] ) ) {
					$enabled = (bool) $plugin_data['auto-update-forced'];
				}

				if ( $enabled ) {
					$plugins['auto-update-enabled'][ $plugin_file ] = $plugin_data;
				} else {
					$plugins['auto-update-disabled'][ $plugin_file ] = $plugin_data;
				}
			}
		}

		if ( strlen( $s ) ) {
			$status            = 'search';
			$plugins['search'] = array_filter( $plugins['all'], array( $this, '_search_callback' ) );
		}

		/**
		 * Filters the array of plugins for the list table.
		 *
		 * @since 6.3.0
		 *
		 * @param array[] $plugins An array of arrays of plugin data, keyed by context.
		 */
		$plugins = apply_filters( 'plugins_list', $plugins );

		$totals = array();
		foreach ( $plugins as $type => $list ) {
			$totals[ $type ] = count( $list );
		}

		if ( empty( $plugins[ $status ] ) && ! in_array( $status, array( 'all', 'search' ), true ) ) {
			$status = 'all';
		}

		$this->items = array();
		foreach ( $plugins[ $status ] as $plugin_file => $plugin_data ) {
			// Translate, don't apply markup, sanitize HTML.
			$this->items[ $plugin_file ] = _get_plugin_data_markup_translate( $plugin_file, $plugin_data, false, true );
		}

		$total_this_page = $totals[ $status ];

		$js_plugins = array();
		foreach ( $plugins as $key => $list ) {
			$js_plugins[ $key ] = array_keys( $list );
		}

		wp_localize_script(
			'updates',
			'_wpUpdatesItemCounts',
			array(
				'plugins' => $js_plugins,
				'totals'  => wp_get_update_data(),
			)
		);

		if ( ! $orderby ) {
			$orderby = 'Name';
		} else {
			$orderby = ucfirst( $orderby );
		}

		$order = strtoupper( $order );

		uasort( $this->items, array( $this, '_order_callback' ) );

		$plugins_per_page = $this->get_items_per_page( str_replace( '-', '_', $screen->id . '_per_page' ), 999 );

		$start = ( $page - 1 ) * $plugins_per_page;

		if ( $total_this_page > $plugins_per_page ) {
			$this->items = array_slice( $this->items, $start, $plugins_per_page );
		}

		$this->set_pagination_args(
			array(
				'total_items' => $total_this_page,
				'per_page'    => $plugins_per_page,
			)
		);
	}

	/**
	 * @global string $s URL encoded search term.
	 *
	 * @param array $plugin
	 * @return bool
	 */
	public function _search_callback( $plugin ) {
		global $s;

		foreach ( $plugin as $value ) {
			if ( is_string( $value ) && false !== stripos( strip_tags( $value ), urldecode( $s ) ) ) {
				return true;
			}
		}

		return false;
	}

	/**
	 * @global string $orderby
	 * @global string $order
	 * @param array $plugin_a
	 * @param array $plugin_b
	 * @return int
	 */
	public function _order_callback( $plugin_a, $plugin_b ) {
		global $orderby, $order;

		$a = $plugin_a[ $orderby ];
		$b = $plugin_b[ $orderby ];

		if ( $a === $b ) {
			return 0;
		}

		if ( 'DESC' === $order ) {
			return strcasecmp( $b, $a );
		} else {
			return strcasecmp( $a, $b );
		}
	}

	/**
	 * @global array $plugins
	 */
	public function no_items() {
		global $plugins;

		if ( ! empty( $_REQUEST['s'] ) ) {
			$s = esc_html( urldecode( wp_unslash( $_REQUEST['s'] ) ) );

			/* translators: %s: Plugin search term. */
			printf( __( 'No plugins found for: %s.' ), '<strong>' . $s . '</strong>' );

			// We assume that somebody who can install plugins in multisite is experienced enough to not need this helper link.
			if ( ! is_multisite() && current_user_can( 'install_plugins' ) ) {
				echo ' <a href="' . esc_url( admin_url( 'plugin-install.php?tab=search&s=' . urlencode( $s ) ) ) . '">' . __( 'Search for plugins in the WordPress Plugin Directory.' ) . '</a>';
			}
		} elseif ( ! empty( $plugins['all'] ) ) {
			_e( 'No plugins found.' );
		} else {
			_e( 'No plugins are currently available.' );
		}
	}

	/**
	 * Displays the search box.
	 *
	 * @since 4.6.0
	 *
	 * @param string $text     The 'submit' button label.
	 * @param string $input_id ID attribute value for the search input field.
	 */
	public function search_box( $text, $input_id ) {
		if ( empty( $_REQUEST['s'] ) && ! $this->has_items() ) {
			return;
		}

		$input_id = $input_id . '-search-input';

		if ( ! empty( $_REQUEST['orderby'] ) ) {
			echo '<input type="hidden" name="orderby" value="' . esc_attr( $_REQUEST['orderby'] ) . '" />';
		}
		if ( ! empty( $_REQUEST['order'] ) ) {
			echo '<input type="hidden" name="order" value="' . esc_attr( $_REQUEST['order'] ) . '" />';
		}
		?>
		<p class="search-box">
			<label for="<?php echo esc_attr( $input_id ); ?>"><?php echo $text; ?></label>
			<input type="search" id="<?php echo esc_attr( $input_id ); ?>" class="wp-filter-search" name="s" value="<?php _admin_search_query(); ?>" />
			<?php submit_button( $text, 'hide-if-js', '', false, array( 'id' => 'search-submit' ) ); ?>
		</p>
		<?php
	}

	/**
	 * @global string $status
	 *
	 * @return string[] Array of column titles keyed by their column name.
	 */
	public function get_columns() {
		global $status;

		$columns = array(
			'cb'          => ! in_array( $status, array( 'mustuse', 'dropins' ), true ) ? '<input type="checkbox" />' : '',
			'name'        => __( 'Plugin' ),
			'description' => __( 'Description' ),
		);

		if ( $this->show_autoupdates && ! in_array( $status, array( 'mustuse', 'dropins' ), true ) ) {
			$columns['auto-updates'] = __( 'Automatic Updates' );
		}

		return $columns;
	}

	/**
	 * @return array
	 */
	protected function get_sortable_columns() {
		return array();
	}

	/**
	 * @global array $totals
	 * @global string $status
	 * @return array
	 */
	protected function get_views() {
		global $totals, $status;

		$status_links = array();
		foreach ( $totals as $type => $count ) {
			if ( ! $count ) {
				continue;
			}

			switch ( $type ) {
				case 'all':
					/* translators: %s: Number of plugins. */
					$text = _nx(
						'All <span class="count">(%s)</span>',
						'All <span class="count">(%s)</span>',
						$count,
						'plugins'
					);
					break;
				case 'active':
					/* translators: %s: Number of plugins. */
					$text = _n(
						'Active <span class="count">(%s)</span>',
						'Active <span class="count">(%s)</span>',
						$count
					);
					break;
				case 'recently_activated':
					/* translators: %s: Number of plugins. */
					$text = _n(
						'Recently Active <span class="count">(%s)</span>',
						'Recently Active <span class="count">(%s)</span>',
						$count
					);
					break;
				case 'inactive':
					/* translators: %s: Number of plugins. */
					$text = _n(
						'Inactive <span class="count">(%s)</span>',
						'Inactive <span class="count">(%s)</span>',
						$count
					);
					break;
				case 'mustuse':
					/* translators: %s: Number of plugins. */
					$text = _n(
						'Must-Use <span class="count">(%s)</span>',
						'Must-Use <span class="count">(%s)</span>',
						$count
					);
					break;
				case 'dropins':
					/* translators: %s: Number of plugins. */
					$text = _n(
						'Drop-in <span class="count">(%s)</span>',
						'Drop-ins <span class="count">(%s)</span>',
						$count
					);
					break;
				case 'paused':
					/* translators: %s: Number of plugins. */
					$text = _n(
						'Paused <span class="count">(%s)</span>',
						'Paused <span class="count">(%s)</span>',
						$count
					);
					break;
				case 'upgrade':
					/* translators: %s: Number of plugins. */
					$text = _n(
						'Update Available <span class="count">(%s)</span>',
						'Update Available <span class="count">(%s)</span>',
						$count
					);
					break;
				case 'auto-update-enabled':
					/* translators: %s: Number of plugins. */
					$text = _n(
						'Auto-updates Enabled <span class="count">(%s)</span>',
						'Auto-updates Enabled <span class="count">(%s)</span>',
						$count
					);
					break;
				case 'auto-update-disabled':
					/* translators: %s: Number of plugins. */
					$text = _n(
						'Auto-updates Disabled <span class="count">(%s)</span>',
						'Auto-updates Disabled <span class="count">(%s)</span>',
						$count
					);
					break;
			}

			if ( 'search' !== $type ) {
				$status_links[ $type ] = array(
					'url'     => add_query_arg( 'plugin_status', $type, 'plugins.php' ),
					'label'   => sprintf( $text, number_format_i18n( $count ) ),
					'current' => $type === $status,
				);
			}
		}

		return $this->get_views_links( $status_links );
	}

	/**
	 * @global string $status
	 * @return array
	 */
	protected function get_bulk_actions() {
		global $status;

		$actions = array();

		if ( 'active' !== $status ) {
			$actions['activate-selected'] = $this->screen->in_admin( 'network' ) ? _x( 'Network Activate', 'plugin' ) : _x( 'Activate', 'plugin' );
		}

		if ( 'inactive' !== $status && 'recent' !== $status ) {
			$actions['deactivate-selected'] = $this->screen->in_admin( 'network' ) ? _x( 'Network Deactivate', 'plugin' ) : _x( 'Deactivate', 'plugin' );
		}

		if ( ! is_multisite() || $this->screen->in_admin( 'network' ) ) {
			if ( current_user_can( 'update_plugins' ) ) {
				$actions['update-selected'] = __( 'Update' );
			}

			if ( current_user_can( 'delete_plugins' ) && ( 'active' !== $status ) ) {
				$actions['delete-selected'] = __( 'Delete' );
			}

			if ( $this->show_autoupdates ) {
				if ( 'auto-update-enabled' !== $status ) {
					$actions['enable-auto-update-selected'] = __( 'Enable Auto-updates' );
				}
				if ( 'auto-update-disabled' !== $status ) {
					$actions['disable-auto-update-selected'] = __( 'Disable Auto-updates' );
				}
			}
		}

		return $actions;
	}

	/**
	 * @global string $status
	 * @param string $which
	 */
	public function bulk_actions( $which = '' ) {
		global $status;

		if ( in_array( $status, array( 'mustuse', 'dropins' ), true ) ) {
			return;
		}

		parent::bulk_actions( $which );
	}

	/**
	 * @global string $status
	 * @param string $which
	 */
	protected function extra_tablenav( $which ) {
		global $status;

		if ( ! in_array( $status, array( 'recently_activated', 'mustuse', 'dropins' ), true ) ) {
			return;
		}

		echo '<div class="alignleft actions">';

		if ( 'recently_activated' === $status ) {
			submit_button( __( 'Clear List' ), '', 'clear-recent-list', false );
		} elseif ( 'top' === $which && 'mustuse' === $status ) {
			echo '<p>' . sprintf(
				/* translators: %s: mu-plugins directory name. */
				__( 'Files in the %s directory are executed automatically.' ),
				'<code>' . str_replace( ABSPATH, '/', WPMU_PLUGIN_DIR ) . '</code>'
			) . '</p>';
		} elseif ( 'top' === $which && 'dropins' === $status ) {
			echo '<p>' . sprintf(
				/* translators: %s: wp-content directory name. */
				__( 'Drop-ins are single files, found in the %s directory, that replace or enhance WordPress features in ways that are not possible for traditional plugins.' ),
				'<code>' . str_replace( ABSPATH, '', WP_CONTENT_DIR ) . '</code>'
			) . '</p>';
		}
		echo '</div>';
	}

	/**
	 * @return string
	 */
	public function current_action() {
		if ( isset( $_POST['clear-recent-list'] ) ) {
			return 'clear-recent-list';
		}

		return parent::current_action();
	}

	/**
	 * Generates the list table rows.
	 *
	 * @since 3.1.0
	 *
	 * @global string $status
	 */
	public function display_rows() {
		global $status;

		if ( is_multisite() && ! $this->screen->in_admin( 'network' ) && in_array( $status, array( 'mustuse', 'dropins' ), true ) ) {
			return;
		}

		foreach ( $this->items as $plugin_file => $plugin_data ) {
			$this->single_row( array( $plugin_file, $plugin_data ) );
		}
	}

	/**
	 * @global string $status
	 * @global int $page
	 * @global string $s
	 * @global array $totals
	 *
	 * @param array $item
	 */
	public function single_row( $item ) {
		global $status, $page, $s, $totals;
		static $plugin_id_attrs = array();

		list( $plugin_file, $plugin_data ) = $item;

		$plugin_slug    = isset( $plugin_data['slug'] ) ? $plugin_data['slug'] : sanitize_title( $plugin_data['Name'] );
		$plugin_id_attr = $plugin_slug;

		// Ensure the ID attribute is unique.
		$suffix = 2;
		while ( in_array( $plugin_id_attr, $plugin_id_attrs, true ) ) {
			$plugin_id_attr = "$plugin_slug-$suffix";
			++$suffix;
		}

		$plugin_id_attrs[] = $plugin_id_attr;

		$context = $status;
		$screen  = $this->screen;

		// Pre-order.
		$actions = array(
			'deactivate' => '',
			'activate'   => '',
			'details'    => '',
			'delete'     => '',
		);

		// Do not restrict by default.
		$restrict_network_active = false;
		$restrict_network_only   = false;

		$requires_php = isset( $plugin_data['RequiresPHP'] ) ? $plugin_data['RequiresPHP'] : null;
		$requires_wp  = isset( $plugin_data['RequiresWP'] ) ? $plugin_data['RequiresWP'] : null;

		$compatible_php = is_php_version_compatible( $requires_php );
		$compatible_wp  = is_wp_version_compatible( $requires_wp );

		$has_dependents          = WP_Plugin_Dependencies::has_dependents( $plugin_file );
		$has_active_dependents   = WP_Plugin_Dependencies::has_active_dependents( $plugin_file );
		$has_unmet_dependencies  = WP_Plugin_Dependencies::has_unmet_dependencies( $plugin_file );
		$has_circular_dependency = WP_Plugin_Dependencies::has_circular_dependency( $plugin_file );

		if ( 'mustuse' === $context ) {
			$is_active = true;
		} elseif ( 'dropins' === $context ) {
			$dropins     = _get_dropins();
			$plugin_name = $plugin_file;

			if ( $plugin_file !== $plugin_data['Name'] ) {
				$plugin_name .= '<br />' . $plugin_data['Name'];
			}

			if ( true === ( $dropins[ $plugin_file ][1] ) ) { // Doesn't require a constant.
				$is_active   = true;
				$description = '<p><strong>' . $dropins[ $plugin_file ][0] . '</strong></p>';
			} elseif ( defined( $dropins[ $plugin_file ][1] ) && constant( $dropins[ $plugin_file ][1] ) ) { // Constant is true.
				$is_active   = true;
				$description = '<p><strong>' . $dropins[ $plugin_file ][0] . '</strong></p>';
			} else {
				$is_active   = false;
				$description = '<p><strong>' . $dropins[ $plugin_file ][0] . ' <span class="error-message">' . __( 'Inactive:' ) . '</span></strong> ' .
					sprintf(
						/* translators: 1: Drop-in constant name, 2: wp-config.php */
						__( 'Requires %1$s in %2$s file.' ),
						"<code>define('" . $dropins[ $plugin_file ][1] . "', true);</code>",
						'<code>wp-config.php</code>'
					) . '</p>';
			}

			if ( $plugin_data['Description'] ) {
				$description .= '<p>' . $plugin_data['Description'] . '</p>';
			}
		} else {
			if ( $screen->in_admin( 'network' ) ) {
				$is_active = is_plugin_active_for_network( $plugin_file );
			} else {
				$is_active               = is_plugin_active( $plugin_file );
				$restrict_network_active = ( is_multisite() && is_plugin_active_for_network( $plugin_file ) );
				$restrict_network_only   = ( is_multisite() && is_network_only_plugin( $plugin_file ) && ! $is_active );
			}

			if ( $screen->in_admin( 'network' ) ) {
				if ( $is_active ) {
					if ( current_user_can( 'manage_network_plugins' ) ) {
						if ( $has_active_dependents ) {
							$actions['deactivate'] = __( 'Network Deactivate' ) .
								'<span class="screen-reader-text">' .
								__( 'You cannot deactivate this plugin as other plugins require it.' ) .
								'</span>';

						} else {
							$deactivate_url = 'plugins.php?action=deactivate' .
								'&amp;plugin=' . urlencode( $plugin_file ) .
								'&amp;plugin_status=' . $context .
								'&amp;paged=' . $page .
								'&amp;s=' . $s;

							$actions['deactivate'] = sprintf(
								'<a href="%s" id="deactivate-%s" aria-label="%s">%s</a>',
								wp_nonce_url( $deactivate_url, 'deactivate-plugin_' . $plugin_file ),
								esc_attr( $plugin_id_attr ),
								/* translators: %s: Plugin name. */
								esc_attr( sprintf( _x( 'Network Deactivate %s', 'plugin' ), $plugin_data['Name'] ) ),
								_x( 'Network Deactivate', 'plugin' )
							);
						}
					}
				} else {
					if ( current_user_can( 'manage_network_plugins' ) ) {
						if ( $compatible_php && $compatible_wp ) {
							if ( $has_unmet_dependencies ) {
								$actions['activate'] = _x( 'Network Activate', 'plugin' ) .
									'<span class="screen-reader-text">' .
									__( 'You cannot activate this plugin as it has unmet requirements.' ) .
									'</span>';
							} else {
								$activate_url = 'plugins.php?action=activate' .
									'&amp;plugin=' . urlencode( $plugin_file ) .
									'&amp;plugin_status=' . $context .
									'&amp;paged=' . $page .
									'&amp;s=' . $s;

								$actions['activate'] = sprintf(
									'<a href="%s" id="activate-%s" class="edit" aria-label="%s">%s</a>',
									wp_nonce_url( $activate_url, 'activate-plugin_' . $plugin_file ),
									esc_attr( $plugin_id_attr ),
									/* translators: %s: Plugin name. */
									esc_attr( sprintf( _x( 'Network Activate %s', 'plugin' ), $plugin_data['Name'] ) ),
									_x( 'Network Activate', 'plugin' )
								);
							}
						} else {
							$actions['activate'] = sprintf(
								'<span>%s</span>',
								_x( 'Cannot Activate', 'plugin' )
							);
						}
					}

					if ( current_user_can( 'delete_plugins' ) && ! is_plugin_active( $plugin_file ) ) {
						if ( $has_dependents && ! $has_circular_dependency ) {
							$actions['delete'] = __( 'Delete' ) .
								'<span class="screen-reader-text">' .
								__( 'You cannot delete this plugin as other plugins require it.' ) .
								'</span>';
						} else {
							$delete_url = 'plugins.php?action=delete-selected' .
								'&amp;checked[]=' . urlencode( $plugin_file ) .
								'&amp;plugin_status=' . $context .
								'&amp;paged=' . $page .
								'&amp;s=' . $s;

							$actions['delete'] = sprintf(
								'<a href="%s" id="delete-%s" class="delete" aria-label="%s">%s</a>',
								wp_nonce_url( $delete_url, 'bulk-plugins' ),
								esc_attr( $plugin_id_attr ),
								/* translators: %s: Plugin name. */
								esc_attr( sprintf( _x( 'Delete %s', 'plugin' ), $plugin_data['Name'] ) ),
								__( 'Delete' )
							);
						}
					}
				}
			} else {
				if ( $restrict_network_active ) {
					$actions = array(
						'network_active' => __( 'Network Active' ),
					);
				} elseif ( $restrict_network_only ) {
					$actions = array(
						'network_only' => __( 'Network Only' ),
					);
				} elseif ( $is_active ) {
					if ( current_user_can( 'deactivate_plugin', $plugin_file ) ) {
						if ( $has_active_dependents ) {
							$actions['deactivate'] = __( 'Deactivate' ) .
								'<span class="screen-reader-text">' .
								__( 'You cannot deactivate this plugin as other plugins depend on it.' ) .
								'</span>';
						} else {
							$deactivate_url = 'plugins.php?action=deactivate' .
								'&amp;plugin=' . urlencode( $plugin_file ) .
								'&amp;plugin_status=' . $context .
								'&amp;paged=' . $page .
								'&amp;s=' . $s;

							$actions['deactivate'] = sprintf(
								'<a href="%s" id="deactivate-%s" aria-label="%s">%s</a>',
								wp_nonce_url( $deactivate_url, 'deactivate-plugin_' . $plugin_file ),
								esc_attr( $plugin_id_attr ),
								/* translators: %s: Plugin name. */
								esc_attr( sprintf( _x( 'Deactivate %s', 'plugin' ), $plugin_data['Name'] ) ),
								__( 'Deactivate' )
							);
						}
					}

					if ( current_user_can( 'resume_plugin', $plugin_file ) && is_plugin_paused( $plugin_file ) ) {
						$resume_url = 'plugins.php?action=resume' .
							'&amp;plugin=' . urlencode( $plugin_file ) .
							'&amp;plugin_status=' . $context .
							'&amp;paged=' . $page .
							'&amp;s=' . $s;

						$actions['resume'] = sprintf(
							'<a href="%s" id="resume-%s" class="resume-link" aria-label="%s">%s</a>',
							wp_nonce_url( $resume_url, 'resume-plugin_' . $plugin_file ),
							esc_attr( $plugin_id_attr ),
							/* translators: %s: Plugin name. */
							esc_attr( sprintf( _x( 'Resume %s', 'plugin' ), $plugin_data['Name'] ) ),
							__( 'Resume' )
						);
					}
				} else {
					if ( current_user_can( 'activate_plugin', $plugin_file ) ) {
						if ( $compatible_php && $compatible_wp ) {
							if ( $has_unmet_dependencies ) {
								$actions['activate'] = _x( 'Activate', 'plugin' ) .
									'<span class="screen-reader-text">' .
									__( 'You cannot activate this plugin as it has unmet requirements.' ) .
									'</span>';
							} else {
								$activate_url = 'plugins.php?action=activate' .
									'&amp;plugin=' . urlencode( $plugin_file ) .
									'&amp;plugin_status=' . $context .
									'&amp;paged=' . $page .
									'&amp;s=' . $s;

								$actions['activate'] = sprintf(
									'<a href="%s" id="activate-%s" class="edit" aria-label="%s">%s</a>',
									wp_nonce_url( $activate_url, 'activate-plugin_' . $plugin_file ),
									esc_attr( $plugin_id_attr ),
									/* translators: %s: Plugin name. */
									esc_attr( sprintf( _x( 'Activate %s', 'plugin' ), $plugin_data['Name'] ) ),
									_x( 'Activate', 'plugin' )
								);
							}
						} else {
							$actions['activate'] = sprintf(
								'<span>%s</span>',
								_x( 'Cannot Activate', 'plugin' )
							);
						}
					}

					if ( ! is_multisite() && current_user_can( 'delete_plugins' ) ) {
						if ( $has_dependents && ! $has_circular_dependency ) {
							$actions['delete'] = __( 'Delete' ) .
								'<span class="screen-reader-text">' .
								__( 'You cannot delete this plugin as other plugins require it.' ) .
								'</span>';
						} else {
							$delete_url = 'plugins.php?action=delete-selected' .
								'&amp;checked[]=' . urlencode( $plugin_file ) .
								'&amp;plugin_status=' . $context .
								'&amp;paged=' . $page .
								'&amp;s=' . $s;

							$actions['delete'] = sprintf(
								'<a href="%s" id="delete-%s" class="delete" aria-label="%s">%s</a>',
								wp_nonce_url( $delete_url, 'bulk-plugins' ),
								esc_attr( $plugin_id_attr ),
								/* translators: %s: Plugin name. */
								esc_attr( sprintf( _x( 'Delete %s', 'plugin' ), $plugin_data['Name'] ) ),
								__( 'Delete' )
							);
						}
					}
				} // End if $is_active.
			} // End if $screen->in_admin( 'network' ).
		} // End if $context.

		$actions = array_filter( $actions );

		if ( $screen->in_admin( 'network' ) ) {

			/**
			 * Filters the action links displayed for each plugin in the Network Admin Plugins list table.
			 *
			 * @since 3.1.0
			 *
			 * @param string[] $actions     An array of plugin action links. By default this can include
			 *                              'activate', 'deactivate', and 'delete'.
			 * @param string   $plugin_file Path to the plugin file relative to the plugins directory.
			 * @param array    $plugin_data An array of plugin data. See get_plugin_data()
			 *                              and the {@see 'plugin_row_meta'} filter for the list
			 *                              of possible values.
			 * @param string   $context     The plugin context. By default this can include 'all',
			 *                              'active', 'inactive', 'recently_activated', 'upgrade',
			 *                              'mustuse', 'dropins', and 'search'.
			 */
			$actions = apply_filters( 'network_admin_plugin_action_links', $actions, $plugin_file, $plugin_data, $context );

			/**
			 * Filters the list of action links displayed for a specific plugin in the Network Admin Plugins list table.
			 *
			 * The dynamic portion of the hook name, `$plugin_file`, refers to the path
			 * to the plugin file, relative to the plugins directory.
			 *
			 * @since 3.1.0
			 *
			 * @param string[] $actions     An array of plugin action links. By default this can include
			 *                              'activate', 'deactivate', and 'delete'.
			 * @param string   $plugin_file Path to the plugin file relative to the plugins directory.
			 * @param array    $plugin_data An array of plugin data. See get_plugin_data()
			 *                              and the {@see 'plugin_row_meta'} filter for the list
			 *                              of possible values.
			 * @param string   $context     The plugin context. By default this can include 'all',
			 *                              'active', 'inactive', 'recently_activated', 'upgrade',
			 *                              'mustuse', 'dropins', and 'search'.
			 */
			$actions = apply_filters( "network_admin_plugin_action_links_{$plugin_file}", $actions, $plugin_file, $plugin_data, $context );

		} else {

			/**
			 * Filters the action links displayed for each plugin in the Plugins list table.
			 *
			 * @since 2.5.0
			 * @since 2.6.0 The `$context` parameter was added.
			 * @since 4.9.0 The 'Edit' link was removed from the list of action links.
			 *
			 * @param string[] $actions     An array of plugin action links. By default this can include
			 *                              'activate', 'deactivate', and 'delete'. With Multisite active
			 *                              this can also include 'network_active' and 'network_only' items.
			 * @param string   $plugin_file Path to the plugin file relative to the plugins directory.
			 * @param array    $plugin_data An array of plugin data. See get_plugin_data()
			 *                              and the {@see 'plugin_row_meta'} filter for the list
			 *                              of possible values.
			 * @param string   $context     The plugin context. By default this can include 'all',
			 *                              'active', 'inactive', 'recently_activated', 'upgrade',
			 *                              'mustuse', 'dropins', and 'search'.
			 */
			$actions = apply_filters( 'plugin_action_links', $actions, $plugin_file, $plugin_data, $context );

			/**
			 * Filters the list of action links displayed for a specific plugin in the Plugins list table.
			 *
			 * The dynamic portion of the hook name, `$plugin_file`, refers to the path
			 * to the plugin file, relative to the plugins directory.
			 *
			 * @since 2.7.0
			 * @since 4.9.0 The 'Edit' link was removed from the list of action links.
			 *
			 * @param string[] $actions     An array of plugin action links. By default this can include
			 *                              'activate', 'deactivate', and 'delete'. With Multisite active
			 *                              this can also include 'network_active' and 'network_only' items.
			 * @param string   $plugin_file Path to the plugin file relative to the plugins directory.
			 * @param array    $plugin_data An array of plugin data. See get_plugin_data()
			 *                              and the {@see 'plugin_row_meta'} filter for the list
			 *                              of possible values.
			 * @param string   $context     The plugin context. By default this can include 'all',
			 *                              'active', 'inactive', 'recently_activated', 'upgrade',
			 *                              'mustuse', 'dropins', and 'search'.
			 */
			$actions = apply_filters( "plugin_action_links_{$plugin_file}", $actions, $plugin_file, $plugin_data, $context );

		}

		$class       = $is_active ? 'active' : 'inactive';
		$checkbox_id = 'checkbox_' . md5( $plugin_file );
		$disabled    = '';

		if ( $has_dependents || $has_unmet_dependencies ) {
			$disabled = 'disabled';
		}

		if (
			$restrict_network_active ||
			$restrict_network_only ||
			in_array( $status, array( 'mustuse', 'dropins' ), true ) ||
			! $compatible_php
		) {
			$checkbox = '';
		} else {
			$checkbox = sprintf(
				'<label class="label-covers-full-cell" for="%1$s">' .
				'<span class="screen-reader-text">%2$s</span></label>' .
				'<input type="checkbox" name="checked[]" value="%3$s" id="%1$s" ' . $disabled . '/>',
				$checkbox_id,
				/* translators: Hidden accessibility text. %s: Plugin name. */
				sprintf( __( 'Select %s' ), $plugin_data['Name'] ),
				esc_attr( $plugin_file )
			);
		}

		if ( 'dropins' !== $context ) {
			$description = '<p>' . ( $plugin_data['Description'] ? $plugin_data['Description'] : '&nbsp;' ) . '</p>';
			$plugin_name = $plugin_data['Name'];
		}

		if (
			! empty( $totals['upgrade'] ) &&
			! empty( $plugin_data['update'] ) ||
			! $compatible_php ||
			! $compatible_wp
		) {
			$class .= ' update';
		}

		$paused = ! $screen->in_admin( 'network' ) && is_plugin_paused( $plugin_file );

		if ( $paused ) {
			$class .= ' paused';
		}

		if ( is_uninstallable_plugin( $plugin_file ) ) {
			$class .= ' is-uninstallable';
		}

		printf(
			'<tr class="%s" data-slug="%s" data-plugin="%s">',
			esc_attr( $class ),
			esc_attr( $plugin_slug ),
			esc_attr( $plugin_file )
		);

		list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();

		$auto_updates = (array) get_site_option( 'auto_update_plugins', array() );

		foreach ( $columns as $column_name => $column_display_name ) {
			$extra_classes = '';
			if ( in_array( $column_name, $hidden, true ) ) {
				$extra_classes = ' hidden';
			}

			switch ( $column_name ) {
				case 'cb':
					echo "<th scope='row' class='check-column'>$checkbox</th>";
					break;
				case 'name':
					echo "<td class='plugin-title column-primary'><strong>$plugin_name</strong>";
					echo $this->row_actions( $actions, true );
					echo '</td>';
					break;
				case 'description':
					$classes = 'column-description desc';

					echo "<td class='$classes{$extra_classes}'>
						<div class='plugin-description'>$description</div>
						<div class='$class second plugin-version-author-uri'>";

					$plugin_meta = array();

					if ( ! empty( $plugin_data['Version'] ) ) {
						/* translators: %s: Plugin version number. */
						$plugin_meta[] = sprintf( __( 'Version %s' ), $plugin_data['Version'] );
					}

					if ( ! empty( $plugin_data['Author'] ) ) {
						$author = $plugin_data['Author'];

						if ( ! empty( $plugin_data['AuthorURI'] ) ) {
							$author = '<a href="' . $plugin_data['AuthorURI'] . '">' . $plugin_data['Author'] . '</a>';
						}

						/* translators: %s: Plugin author name. */
						$plugin_meta[] = sprintf( __( 'By %s' ), $author );
					}

					// Details link using API info, if available.
					if ( isset( $plugin_data['slug'] ) && current_user_can( 'install_plugins' ) ) {
						$plugin_meta[] = sprintf(
							'<a href="%s" class="thickbox open-plugin-details-modal" aria-label="%s" data-title="%s">%s</a>',
							esc_url(
								network_admin_url(
									'plugin-install.php?tab=plugin-information&plugin=' . $plugin_data['slug'] .
									'&TB_iframe=true&width=600&height=550'
								)
							),
							/* translators: %s: Plugin name. */
							esc_attr( sprintf( __( 'More information about %s' ), $plugin_name ) ),
							esc_attr( $plugin_name ),
							__( 'View details' )
						);
					} elseif ( ! empty( $plugin_data['PluginURI'] ) ) {
						/* translators: %s: Plugin name. */
						$aria_label = sprintf( __( 'Visit plugin site for %s' ), $plugin_name );

						$plugin_meta[] = sprintf(
							'<a href="%s" aria-label="%s">%s</a>',
							esc_url( $plugin_data['PluginURI'] ),
							esc_attr( $aria_label ),
							__( 'Visit plugin site' )
						);
					}

					/**
					 * Filters the array of row meta for each plugin in the Plugins list table.
					 *
					 * @since 2.8.0
					 *
					 * @param string[] $plugin_meta An array of the plugin's metadata, including
					 *                              the version, author, author URI, and plugin URI.
					 * @param string   $plugin_file Path to the plugin file relative to the plugins directory.
					 * @param array    $plugin_data {
					 *     An array of plugin data.
					 *
					 *     @type string   $id               Plugin ID, e.g. `w.org/plugins/[plugin-name]`.
					 *     @type string   $slug             Plugin slug.
					 *     @type string   $plugin           Plugin basename.
					 *     @type string   $new_version      New plugin version.
					 *     @type string   $url              Plugin URL.
					 *     @type string   $package          Plugin update package URL.
					 *     @type string[] $icons            An array of plugin icon URLs.
					 *     @type string[] $banners          An array of plugin banner URLs.
					 *     @type string[] $banners_rtl      An array of plugin RTL banner URLs.
					 *     @type string   $requires         The version of WordPress which the plugin requires.
					 *     @type string   $tested           The version of WordPress the plugin is tested against.
					 *     @type string   $requires_php     The version of PHP which the plugin requires.
					 *     @type string   $upgrade_notice   The upgrade notice for the new plugin version.
					 *     @type bool     $update-supported Whether the plugin supports updates.
					 *     @type string   $Name             The human-readable name of the plugin.
					 *     @type string   $PluginURI        Plugin URI.
					 *     @type string   $Version          Plugin version.
					 *     @type string   $Description      Plugin description.
					 *     @type string   $Author           Plugin author.
					 *     @type string   $AuthorURI        Plugin author URI.
					 *     @type string   $TextDomain       Plugin textdomain.
					 *     @type string   $DomainPath       Relative path to the plugin's .mo file(s).
					 *     @type bool     $Network          Whether the plugin can only be activated network-wide.
					 *     @type string   $RequiresWP       The version of WordPress which the plugin requires.
					 *     @type string   $RequiresPHP      The version of PHP which the plugin requires.
					 *     @type string   $UpdateURI        ID of the plugin for update purposes, should be a URI.
					 *     @type string   $Title            The human-readable title of the plugin.
					 *     @type string   $AuthorName       Plugin author's name.
					 *     @type bool     $update           Whether there's an available update. Default null.
					 * }
					 * @param string   $status      Status filter currently applied to the plugin list. Possible
					 *                              values are: 'all', 'active', 'inactive', 'recently_activated',
					 *                              'upgrade', 'mustuse', 'dropins', 'search', 'paused',
					 *                              'auto-update-enabled', 'auto-update-disabled'.
					 */
					$plugin_meta = apply_filters( 'plugin_row_meta', $plugin_meta, $plugin_file, $plugin_data, $status );

					echo implode( ' | ', $plugin_meta );

					echo '</div>';

					if ( $has_dependents ) {
						$this->add_dependents_to_dependency_plugin_row( $plugin_file );
					}

					if ( WP_Plugin_Dependencies::has_dependencies( $plugin_file ) ) {
						$this->add_dependencies_to_dependent_plugin_row( $plugin_file );
					}

					/**
					 * Fires after plugin row meta.
					 *
					 * @since 6.5.0
					 *
					 * @param string $plugin_file Refer to {@see 'plugin_row_meta'} filter.
					 * @param array  $plugin_data Refer to {@see 'plugin_row_meta'} filter.
					 */
					do_action( 'after_plugin_row_meta', $plugin_file, $plugin_data );

					if ( $paused ) {
						$notice_text = __( 'This plugin failed to load properly and is paused during recovery mode.' );

						printf( '<p><span class="dashicons dashicons-warning"></span> <strong>%s</strong></p>', $notice_text );

						$error = wp_get_plugin_error( $plugin_file );

						if ( false !== $error ) {
							printf( '<div class="error-display"><p>%s</p></div>', wp_get_extension_error_description( $error ) );
						}
					}

					echo '</td>';
					break;
				case 'auto-updates':
					if ( ! $this->show_autoupdates || in_array( $status, array( 'mustuse', 'dropins' ), true ) ) {
						break;
					}

					echo "<td class='column-auto-updates{$extra_classes}'>";

					$html = array();

					if ( isset( $plugin_data['auto-update-forced'] ) ) {
						if ( $plugin_data['auto-update-forced'] ) {
							// Forced on.
							$text = __( 'Auto-updates enabled' );
						} else {
							$text = __( 'Auto-updates disabled' );
						}
						$action     = 'unavailable';
						$time_class = ' hidden';
					} elseif ( empty( $plugin_data['update-supported'] ) ) {
						$text       = '';
						$action     = 'unavailable';
						$time_class = ' hidden';
					} elseif ( in_array( $plugin_file, $auto_updates, true ) ) {
						$text       = __( 'Disable auto-updates' );
						$action     = 'disable';
						$time_class = '';
					} else {
						$text       = __( 'Enable auto-updates' );
						$action     = 'enable';
						$time_class = ' hidden';
					}

					$query_args = array(
						'action'        => "{$action}-auto-update",
						'plugin'        => $plugin_file,
						'paged'         => $page,
						'plugin_status' => $status,
					);

					$url = add_query_arg( $query_args, 'plugins.php' );

					if ( 'unavailable' === $action ) {
						$html[] = '<span class="label">' . $text . '</span>';
					} else {
						$html[] = sprintf(
							'<a href="%s" class="toggle-auto-update aria-button-if-js" data-wp-action="%s">',
							wp_nonce_url( $url, 'updates' ),
							$action
						);

						$html[] = '<span class="dashicons dashicons-update spin hidden" aria-hidden="true"></span>';
						$html[] = '<span class="label">' . $text . '</span>';
						$html[] = '</a>';
					}

					if ( ! empty( $plugin_data['update'] ) ) {
						$html[] = sprintf(
							'<div class="auto-update-time%s">%s</div>',
							$time_class,
							wp_get_auto_update_message()
						);
					}

					$html = implode( '', $html );

					/**
					 * Filters the HTML of the auto-updates setting for each plugin in the Plugins list table.
					 *
					 * @since 5.5.0
					 *
					 * @param string $html        The HTML of the plugin's auto-update column content,
					 *                            including toggle auto-update action links and
					 *                            time to next update.
					 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
					 * @param array  $plugin_data An array of plugin data. See get_plugin_data()
					 *                            and the {@see 'plugin_row_meta'} filter for the list
					 *                            of possible values.
					 */
					echo apply_filters( 'plugin_auto_update_setting_html', $html, $plugin_file, $plugin_data );

					wp_admin_notice(
						'',
						array(
							'type'               => 'error',
							'additional_classes' => array( 'notice-alt', 'inline', 'hidden' ),
						)
					);

					echo '</td>';

					break;
				default:
					$classes = "$column_name column-$column_name $class";

					echo "<td class='$classes{$extra_classes}'>";

					/**
					 * Fires inside each custom column of the Plugins list table.
					 *
					 * @since 3.1.0
					 *
					 * @param string $column_name Name of the column.
					 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
					 * @param array  $plugin_data An array of plugin data. See get_plugin_data()
					 *                            and the {@see 'plugin_row_meta'} filter for the list
					 *                            of possible values.
					 */
					do_action( 'manage_plugins_custom_column', $column_name, $plugin_file, $plugin_data );

					echo '</td>';
			}
		}

		echo '</tr>';

		if ( ! $compatible_php || ! $compatible_wp ) {
			printf(
				'<tr class="plugin-update-tr"><td colspan="%s" class="plugin-update colspanchange">',
				esc_attr( $this->get_column_count() )
			);

			$incompatible_message = '';
			if ( ! $compatible_php && ! $compatible_wp ) {
				$incompatible_message .= __( 'This plugin does not work with your versions of WordPress and PHP.' );
				if ( current_user_can( 'update_core' ) && current_user_can( 'update_php' ) ) {
					$incompatible_message .= sprintf(
						/* translators: 1: URL to WordPress Updates screen, 2: URL to Update PHP page. */
						' ' . __( '<a href="%1$s">Please update WordPress</a>, and then <a href="%2$s">learn more about updating PHP</a>.' ),
						self_admin_url( 'update-core.php' ),
						esc_url( wp_get_update_php_url() )
					);
					$incompatible_message .= wp_update_php_annotation( '</p><p><em>', '</em>', false );
				} elseif ( current_user_can( 'update_core' ) ) {
					$incompatible_message .= sprintf(
						/* translators: %s: URL to WordPress Updates screen. */
						' ' . __( '<a href="%s">Please update WordPress</a>.' ),
						self_admin_url( 'update-core.php' )
					);
				} elseif ( current_user_can( 'update_php' ) ) {
					$incompatible_message .= sprintf(
						/* translators: %s: URL to Update PHP page. */
						' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
						esc_url( wp_get_update_php_url() )
					);
					$incompatible_message .= wp_update_php_annotation( '</p><p><em>', '</em>', false );
				}
			} elseif ( ! $compatible_wp ) {
				$incompatible_message .= __( 'This plugin does not work with your version of WordPress.' );
				if ( current_user_can( 'update_core' ) ) {
					$incompatible_message .= sprintf(
						/* translators: %s: URL to WordPress Updates screen. */
						' ' . __( '<a href="%s">Please update WordPress</a>.' ),
						self_admin_url( 'update-core.php' )
					);
				}
			} elseif ( ! $compatible_php ) {
				$incompatible_message .= __( 'This plugin does not work with your version of PHP.' );
				if ( current_user_can( 'update_php' ) ) {
					$incompatible_message .= sprintf(
						/* translators: %s: URL to Update PHP page. */
						' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
						esc_url( wp_get_update_php_url() )
					);
					$incompatible_message .= wp_update_php_annotation( '</p><p><em>', '</em>', false );
				}
			}

			wp_admin_notice(
				$incompatible_message,
				array(
					'type'               => 'error',
					'additional_classes' => array( 'notice-alt', 'inline', 'update-message' ),
				)
			);

			echo '</td></tr>';
		}

		/**
		 * Fires after each row in the Plugins list table.
		 *
		 * @since 2.3.0
		 * @since 5.5.0 Added 'auto-update-enabled' and 'auto-update-disabled'
		 *              to possible values for `$status`.
		 *
		 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
		 * @param array  $plugin_data An array of plugin data. See get_plugin_data()
		 *                            and the {@see 'plugin_row_meta'} filter for the list
		 *                            of possible values.
		 * @param string $status      Status filter currently applied to the plugin list.
		 *                            Possible values are: 'all', 'active', 'inactive',
		 *                            'recently_activated', 'upgrade', 'mustuse', 'dropins',
		 *                            'search', 'paused', 'auto-update-enabled', 'auto-update-disabled'.
		 */
		do_action( 'after_plugin_row', $plugin_file, $plugin_data, $status );

		/**
		 * Fires after each specific row in the Plugins list table.
		 *
		 * The dynamic portion of the hook name, `$plugin_file`, refers to the path
		 * to the plugin file, relative to the plugins directory.
		 *
		 * @since 2.7.0
		 * @since 5.5.0 Added 'auto-update-enabled' and 'auto-update-disabled'
		 *              to possible values for `$status`.
		 *
		 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
		 * @param array  $plugin_data An array of plugin data. See get_plugin_data()
		 *                            and the {@see 'plugin_row_meta'} filter for the list
		 *                            of possible values.
		 * @param string $status      Status filter currently applied to the plugin list.
		 *                            Possible values are: 'all', 'active', 'inactive',
		 *                            'recently_activated', 'upgrade', 'mustuse', 'dropins',
		 *                            'search', 'paused', 'auto-update-enabled', 'auto-update-disabled'.
		 */
		do_action( "after_plugin_row_{$plugin_file}", $plugin_file, $plugin_data, $status );
	}

	/**
	 * Gets the name of the primary column for this specific list table.
	 *
	 * @since 4.3.0
	 *
	 * @return string Unalterable name for the primary column, in this case, 'name'.
	 */
	protected function get_primary_column_name() {
		return 'name';
	}

	/**
	 * Prints a list of other plugins that depend on the plugin.
	 *
	 * @since 6.5.0
	 *
	 * @param string $dependency The dependency's filepath, relative to the plugins directory.
	 */
	protected function add_dependents_to_dependency_plugin_row( $dependency ) {
		$dependent_names = WP_Plugin_Dependencies::get_dependent_names( $dependency );

		if ( empty( $dependent_names ) ) {
			return;
		}

		$dependency_note = __( 'Note: This plugin cannot be deactivated or deleted until the plugins that require it are deactivated or deleted.' );

		$comma       = wp_get_list_item_separator();
		$required_by = sprintf(
			/* translators: %s: List of dependencies. */
			__( '<strong>Required by:</strong> %s' ),
			implode( $comma, $dependent_names )
		);

		printf(
			'<div class="required-by"><p>%1$s</p><p>%2$s</p></div>',
			$required_by,
			$dependency_note
		);
	}

	/**
	 * Prints a list of other plugins that the plugin depends on.
	 *
	 * @since 6.5.0
	 *
	 * @param string $dependent The dependent plugin's filepath, relative to the plugins directory.
	 */
	protected function add_dependencies_to_dependent_plugin_row( $dependent ) {
		$dependency_names = WP_Plugin_Dependencies::get_dependency_names( $dependent );

		if ( array() === $dependency_names ) {
			return;
		}

		$links = array();
		foreach ( $dependency_names as $slug => $name ) {
			$links[] = $this->get_dependency_view_details_link( $name, $slug );
		}

		$is_active = is_multisite() ? is_plugin_active_for_network( $dependent ) : is_plugin_active( $dependent );
		$comma     = wp_get_list_item_separator();
		$requires  = sprintf(
			/* translators: %s: List of dependency names. */
			__( '<strong>Requires:</strong> %s' ),
			implode( $comma, $links )
		);

		$notice        = '';
		$error_message = '';
		if ( WP_Plugin_Dependencies::has_unmet_dependencies( $dependent ) ) {
			if ( $is_active ) {
				$error_message = __( 'This plugin is active but may not function correctly because required plugins are missing or inactive.' );
			} else {
				$error_message = __( 'This plugin cannot be activated because required plugins are missing or inactive.' );
			}
			$notice = wp_get_admin_notice(
				$error_message,
				array(
					'type'               => 'error',
					'additional_classes' => array( 'inline', 'notice-alt' ),
				)
			);
		}

		printf(
			'<div class="requires"><p>%1$s</p>%2$s</div>',
			$requires,
			$notice
		);
	}

	/**
	 * Returns a 'View details' like link for a dependency.
	 *
	 * @since 6.5.0
	 *
	 * @param string $name The dependency's name.
	 * @param string $slug The dependency's slug.
	 * @return string A 'View details' link for the dependency.
	 */
	protected function get_dependency_view_details_link( $name, $slug ) {
		$dependency_data = WP_Plugin_Dependencies::get_dependency_data( $slug );

		if ( false === $dependency_data
			|| $name === $slug
			|| $name !== $dependency_data['name']
			|| empty( $dependency_data['version'] )
		) {
			return $name;
		}

		return $this->get_view_details_link( $name, $slug );
	}

	/**
	 * Returns a 'View details' link for the plugin.
	 *
	 * @since 6.5.0
	 *
	 * @param string $name The plugin's name.
	 * @param string $slug The plugin's slug.
	 * @return string A 'View details' link for the plugin.
	 */
	protected function get_view_details_link( $name, $slug ) {
		$url = add_query_arg(
			array(
				'tab'       => 'plugin-information',
				'plugin'    => $slug,
				'TB_iframe' => 'true',
				'width'     => '600',
				'height'    => '550',
			),
			network_admin_url( 'plugin-install.php' )
		);

		$name_attr = esc_attr( $name );
		return sprintf(
			"<a href='%s' class='thickbox open-plugin-details-modal' aria-label='%s' data-title='%s'>%s</a>",
			esc_url( $url ),
			/* translators: %s: Plugin name. */
			sprintf( __( 'More information about %s' ), $name_attr ),
			$name_attr,
			esc_html( $name )
		);
	}
}
theme-install.php000064400000015516151212616050010032 0ustar00<?php
/**
 * WordPress Theme Installation Administration API
 *
 * @package WordPress
 * @subpackage Administration
 */

$themes_allowedtags = array(
	'a'       => array(
		'href'   => array(),
		'title'  => array(),
		'target' => array(),
	),
	'abbr'    => array( 'title' => array() ),
	'acronym' => array( 'title' => array() ),
	'code'    => array(),
	'pre'     => array(),
	'em'      => array(),
	'strong'  => array(),
	'div'     => array(),
	'p'       => array(),
	'ul'      => array(),
	'ol'      => array(),
	'li'      => array(),
	'h1'      => array(),
	'h2'      => array(),
	'h3'      => array(),
	'h4'      => array(),
	'h5'      => array(),
	'h6'      => array(),
	'img'     => array(
		'src'   => array(),
		'class' => array(),
		'alt'   => array(),
	),
);

$theme_field_defaults = array(
	'description'  => true,
	'sections'     => false,
	'tested'       => true,
	'requires'     => true,
	'rating'       => true,
	'downloaded'   => true,
	'downloadlink' => true,
	'last_updated' => true,
	'homepage'     => true,
	'tags'         => true,
	'num_ratings'  => true,
);

/**
 * Retrieves the list of WordPress theme features (aka theme tags).
 *
 * @since 2.8.0
 *
 * @deprecated 3.1.0 Use get_theme_feature_list() instead.
 *
 * @return array
 */
function install_themes_feature_list() {
	_deprecated_function( __FUNCTION__, '3.1.0', 'get_theme_feature_list()' );

	$cache = get_transient( 'wporg_theme_feature_list' );
	if ( ! $cache ) {
		set_transient( 'wporg_theme_feature_list', array(), 3 * HOUR_IN_SECONDS );
	}

	if ( $cache ) {
		return $cache;
	}

	$feature_list = themes_api( 'feature_list', array() );
	if ( is_wp_error( $feature_list ) ) {
		return array();
	}

	set_transient( 'wporg_theme_feature_list', $feature_list, 3 * HOUR_IN_SECONDS );

	return $feature_list;
}

/**
 * Displays search form for searching themes.
 *
 * @since 2.8.0
 *
 * @param bool $type_selector
 */
function install_theme_search_form( $type_selector = true ) {
	$type = isset( $_REQUEST['type'] ) ? wp_unslash( $_REQUEST['type'] ) : 'term';
	$term = isset( $_REQUEST['s'] ) ? wp_unslash( $_REQUEST['s'] ) : '';
	if ( ! $type_selector ) {
		echo '<p class="install-help">' . __( 'Search for themes by keyword.' ) . '</p>';
	}
	?>
<form id="search-themes" method="get">
	<input type="hidden" name="tab" value="search" />
	<?php if ( $type_selector ) : ?>
	<label class="screen-reader-text" for="typeselector">
		<?php
		/* translators: Hidden accessibility text. */
		_e( 'Type of search' );
		?>
	</label>
	<select	name="type" id="typeselector">
	<option value="term" <?php selected( 'term', $type ); ?>><?php _e( 'Keyword' ); ?></option>
	<option value="author" <?php selected( 'author', $type ); ?>><?php _e( 'Author' ); ?></option>
	<option value="tag" <?php selected( 'tag', $type ); ?>><?php _ex( 'Tag', 'Theme Installer' ); ?></option>
	</select>
	<label class="screen-reader-text" for="s">
		<?php
		switch ( $type ) {
			case 'term':
				/* translators: Hidden accessibility text. */
				_e( 'Search by keyword' );
				break;
			case 'author':
				/* translators: Hidden accessibility text. */
				_e( 'Search by author' );
				break;
			case 'tag':
				/* translators: Hidden accessibility text. */
				_e( 'Search by tag' );
				break;
		}
		?>
	</label>
	<?php else : ?>
	<label class="screen-reader-text" for="s">
		<?php
		/* translators: Hidden accessibility text. */
		_e( 'Search by keyword' );
		?>
	</label>
	<?php endif; ?>
	<input type="search" name="s" id="s" size="30" value="<?php echo esc_attr( $term ); ?>" autofocus="autofocus" />
	<?php submit_button( __( 'Search' ), '', 'search', false ); ?>
</form>
	<?php
}

/**
 * Displays tags filter for themes.
 *
 * @since 2.8.0
 */
function install_themes_dashboard() {
	install_theme_search_form( false );
	?>
<h4><?php _e( 'Feature Filter' ); ?></h4>
<p class="install-help"><?php _e( 'Find a theme based on specific features.' ); ?></p>

<form method="get">
	<input type="hidden" name="tab" value="search" />
	<?php
	$feature_list = get_theme_feature_list();
	echo '<div class="feature-filter">';

	foreach ( (array) $feature_list as $feature_name => $features ) {
		$feature_name = esc_html( $feature_name );
		echo '<div class="feature-name">' . $feature_name . '</div>';

		echo '<ol class="feature-group">';
		foreach ( $features as $feature => $feature_name ) {
			$feature_name = esc_html( $feature_name );
			$feature      = esc_attr( $feature );
			?>

<li>
	<input type="checkbox" name="features[]" id="feature-id-<?php echo $feature; ?>" value="<?php echo $feature; ?>" />
	<label for="feature-id-<?php echo $feature; ?>"><?php echo $feature_name; ?></label>
</li>

<?php	} ?>
</ol>
<br class="clear" />
		<?php
	}
	?>

</div>
<br class="clear" />
	<?php submit_button( __( 'Find Themes' ), '', 'search' ); ?>
</form>
	<?php
}

/**
 * Displays a form to upload themes from zip files.
 *
 * @since 2.8.0
 */
function install_themes_upload() {
	?>
<p class="install-help"><?php _e( 'If you have a theme in a .zip format, you may install or update it by uploading it here.' ); ?></p>
<form method="post" enctype="multipart/form-data" class="wp-upload-form" action="<?php echo esc_url( self_admin_url( 'update.php?action=upload-theme' ) ); ?>">
	<?php wp_nonce_field( 'theme-upload' ); ?>
	<label class="screen-reader-text" for="themezip">
		<?php
		/* translators: Hidden accessibility text. */
		_e( 'Theme zip file' );
		?>
	</label>
	<input type="file" id="themezip" name="themezip" accept=".zip" />
	<?php submit_button( _x( 'Install Now', 'theme' ), '', 'install-theme-submit', false ); ?>
</form>
	<?php
}

/**
 * Prints a theme on the Install Themes pages.
 *
 * @deprecated 3.4.0
 *
 * @global WP_Theme_Install_List_Table $wp_list_table
 *
 * @param object $theme
 */
function display_theme( $theme ) {
	_deprecated_function( __FUNCTION__, '3.4.0' );
	global $wp_list_table;
	if ( ! isset( $wp_list_table ) ) {
		$wp_list_table = _get_list_table( 'WP_Theme_Install_List_Table' );
	}
	$wp_list_table->prepare_items();
	$wp_list_table->single_row( $theme );
}

/**
 * Displays theme content based on theme list.
 *
 * @since 2.8.0
 *
 * @global WP_Theme_Install_List_Table $wp_list_table
 */
function display_themes() {
	global $wp_list_table;

	if ( ! isset( $wp_list_table ) ) {
		$wp_list_table = _get_list_table( 'WP_Theme_Install_List_Table' );
	}
	$wp_list_table->prepare_items();
	$wp_list_table->display();
}

/**
 * Displays theme information in dialog box form.
 *
 * @since 2.8.0
 *
 * @global WP_Theme_Install_List_Table $wp_list_table
 */
function install_theme_information() {
	global $wp_list_table;

	$theme = themes_api( 'theme_information', array( 'slug' => wp_unslash( $_REQUEST['theme'] ) ) );

	if ( is_wp_error( $theme ) ) {
		wp_die( $theme );
	}

	iframe_header( __( 'Theme Installation' ) );
	if ( ! isset( $wp_list_table ) ) {
		$wp_list_table = _get_list_table( 'WP_Theme_Install_List_Table' );
	}
	$wp_list_table->theme_installer_single( $theme );
	iframe_footer();
	exit;
}
widgets.php000064400000025240151212616050006725 0ustar00<?php
/**
 * WordPress Widgets Administration API
 *
 * @package WordPress
 * @subpackage Administration
 */

/**
 * Display list of the available widgets.
 *
 * @since 2.5.0
 *
 * @global array $wp_registered_widgets
 * @global array $wp_registered_widget_controls
 */
function wp_list_widgets() {
	global $wp_registered_widgets, $wp_registered_widget_controls;

	$sort = $wp_registered_widgets;
	usort( $sort, '_sort_name_callback' );
	$done = array();

	foreach ( $sort as $widget ) {
		if ( in_array( $widget['callback'], $done, true ) ) { // We already showed this multi-widget.
			continue;
		}

		$sidebar = is_active_widget( $widget['callback'], $widget['id'], false, false );
		$done[]  = $widget['callback'];

		if ( ! isset( $widget['params'][0] ) ) {
			$widget['params'][0] = array();
		}

		$args = array(
			'widget_id'   => $widget['id'],
			'widget_name' => $widget['name'],
			'_display'    => 'template',
		);

		if ( isset( $wp_registered_widget_controls[ $widget['id'] ]['id_base'] ) && isset( $widget['params'][0]['number'] ) ) {
			$id_base            = $wp_registered_widget_controls[ $widget['id'] ]['id_base'];
			$args['_temp_id']   = "$id_base-__i__";
			$args['_multi_num'] = next_widget_id_number( $id_base );
			$args['_add']       = 'multi';
		} else {
			$args['_add'] = 'single';
			if ( $sidebar ) {
				$args['_hide'] = '1';
			}
		}

		$control_args = array(
			0 => $args,
			1 => $widget['params'][0],
		);
		$sidebar_args = wp_list_widget_controls_dynamic_sidebar( $control_args );

		wp_widget_control( ...$sidebar_args );
	}
}

/**
 * Callback to sort array by a 'name' key.
 *
 * @since 3.1.0
 * @access private
 *
 * @param array $a First array.
 * @param array $b Second array.
 * @return int
 */
function _sort_name_callback( $a, $b ) {
	return strnatcasecmp( $a['name'], $b['name'] );
}

/**
 * Show the widgets and their settings for a sidebar.
 * Used in the admin widget config screen.
 *
 * @since 2.5.0
 *
 * @param string $sidebar      Sidebar ID.
 * @param string $sidebar_name Optional. Sidebar name. Default empty.
 */
function wp_list_widget_controls( $sidebar, $sidebar_name = '' ) {
	add_filter( 'dynamic_sidebar_params', 'wp_list_widget_controls_dynamic_sidebar' );

	$description = wp_sidebar_description( $sidebar );

	echo '<div id="' . esc_attr( $sidebar ) . '" class="widgets-sortables">';

	if ( $sidebar_name ) {
		$add_to = sprintf(
			/* translators: %s: Widgets sidebar name. */
			__( 'Add to: %s' ),
			$sidebar_name
		);
		?>
		<div class="sidebar-name" data-add-to="<?php echo esc_attr( $add_to ); ?>">
			<button type="button" class="handlediv hide-if-no-js" aria-expanded="true">
				<span class="screen-reader-text"><?php echo esc_html( $sidebar_name ); ?></span>
				<span class="toggle-indicator" aria-hidden="true"></span>
			</button>
			<h2><?php echo esc_html( $sidebar_name ); ?> <span class="spinner"></span></h2>
		</div>
		<?php
	}

	if ( ! empty( $description ) ) {
		?>
		<div class="sidebar-description">
			<p class="description"><?php echo $description; ?></p>
		</div>
		<?php
	}

	dynamic_sidebar( $sidebar );

	echo '</div>';
}

/**
 * Retrieves the widget control arguments.
 *
 * @since 2.5.0
 *
 * @global array $wp_registered_widgets
 *
 * @param array $params
 * @return array
 */
function wp_list_widget_controls_dynamic_sidebar( $params ) {
	global $wp_registered_widgets;
	static $i = 0;
	++$i;

	$widget_id = $params[0]['widget_id'];
	$id        = isset( $params[0]['_temp_id'] ) ? $params[0]['_temp_id'] : $widget_id;
	$hidden    = isset( $params[0]['_hide'] ) ? ' style="display:none;"' : '';

	$params[0]['before_widget'] = "<div id='widget-{$i}_{$id}' class='widget'$hidden>";
	$params[0]['after_widget']  = '</div>';
	$params[0]['before_title']  = '%BEG_OF_TITLE%'; // Deprecated.
	$params[0]['after_title']   = '%END_OF_TITLE%'; // Deprecated.

	if ( is_callable( $wp_registered_widgets[ $widget_id ]['callback'] ) ) {
		$wp_registered_widgets[ $widget_id ]['_callback'] = $wp_registered_widgets[ $widget_id ]['callback'];
		$wp_registered_widgets[ $widget_id ]['callback']  = 'wp_widget_control';
	}

	return $params;
}

/**
 * @global array $wp_registered_widgets
 *
 * @param string $id_base
 * @return int
 */
function next_widget_id_number( $id_base ) {
	global $wp_registered_widgets;
	$number = 1;

	foreach ( $wp_registered_widgets as $widget_id => $widget ) {
		if ( preg_match( '/' . preg_quote( $id_base, '/' ) . '-([0-9]+)$/', $widget_id, $matches ) ) {
			$number = max( $number, $matches[1] );
		}
	}
	++$number;

	return $number;
}

/**
 * Meta widget used to display the control form for a widget.
 *
 * Called from dynamic_sidebar().
 *
 * @since 2.5.0
 *
 * @global array $wp_registered_widgets
 * @global array $wp_registered_widget_controls
 * @global array $sidebars_widgets
 *
 * @param array $sidebar_args
 * @return array
 */
function wp_widget_control( $sidebar_args ) {
	global $wp_registered_widgets, $wp_registered_widget_controls, $sidebars_widgets;

	$widget_id  = $sidebar_args['widget_id'];
	$sidebar_id = isset( $sidebar_args['id'] ) ? $sidebar_args['id'] : false;
	$key        = $sidebar_id ? array_search( $widget_id, $sidebars_widgets[ $sidebar_id ], true ) : '-1'; // Position of widget in sidebar.
	$control    = isset( $wp_registered_widget_controls[ $widget_id ] ) ? $wp_registered_widget_controls[ $widget_id ] : array();
	$widget     = $wp_registered_widgets[ $widget_id ];

	$id_format     = $widget['id'];
	$widget_number = isset( $control['params'][0]['number'] ) ? $control['params'][0]['number'] : '';
	$id_base       = isset( $control['id_base'] ) ? $control['id_base'] : $widget_id;
	$width         = isset( $control['width'] ) ? $control['width'] : '';
	$height        = isset( $control['height'] ) ? $control['height'] : '';
	$multi_number  = isset( $sidebar_args['_multi_num'] ) ? $sidebar_args['_multi_num'] : '';
	$add_new       = isset( $sidebar_args['_add'] ) ? $sidebar_args['_add'] : '';

	$before_form           = isset( $sidebar_args['before_form'] ) ? $sidebar_args['before_form'] : '<form method="post">';
	$after_form            = isset( $sidebar_args['after_form'] ) ? $sidebar_args['after_form'] : '</form>';
	$before_widget_content = isset( $sidebar_args['before_widget_content'] ) ? $sidebar_args['before_widget_content'] : '<div class="widget-content">';
	$after_widget_content  = isset( $sidebar_args['after_widget_content'] ) ? $sidebar_args['after_widget_content'] : '</div>';

	$query_arg = array( 'editwidget' => $widget['id'] );
	if ( $add_new ) {
		$query_arg['addnew'] = 1;
		if ( $multi_number ) {
			$query_arg['num']  = $multi_number;
			$query_arg['base'] = $id_base;
		}
	} else {
		$query_arg['sidebar'] = $sidebar_id;
		$query_arg['key']     = $key;
	}

	/*
	 * We aren't showing a widget control, we're outputting a template
	 * for a multi-widget control.
	 */
	if ( isset( $sidebar_args['_display'] ) && 'template' === $sidebar_args['_display'] && $widget_number ) {
		// number == -1 implies a template where id numbers are replaced by a generic '__i__'.
		$control['params'][0]['number'] = -1;
		// With id_base widget ID's are constructed like {$id_base}-{$id_number}.
		if ( isset( $control['id_base'] ) ) {
			$id_format = $control['id_base'] . '-__i__';
		}
	}

	$wp_registered_widgets[ $widget_id ]['callback'] = $wp_registered_widgets[ $widget_id ]['_callback'];
	unset( $wp_registered_widgets[ $widget_id ]['_callback'] );

	$widget_title = esc_html( strip_tags( $sidebar_args['widget_name'] ) );
	$has_form     = 'noform';

	echo $sidebar_args['before_widget'];
	?>
	<div class="widget-top">
	<div class="widget-title-action">
		<button type="button" class="widget-action hide-if-no-js" aria-expanded="false">
			<span class="screen-reader-text edit">
				<?php
				/* translators: Hidden accessibility text. %s: Widget title. */
				printf( __( 'Edit widget: %s' ), $widget_title );
				?>
			</span>
			<span class="screen-reader-text add">
				<?php
				/* translators: Hidden accessibility text. %s: Widget title. */
				printf( __( 'Add widget: %s' ), $widget_title );
				?>
			</span>
			<span class="toggle-indicator" aria-hidden="true"></span>
		</button>
		<a class="widget-control-edit hide-if-js" href="<?php echo esc_url( add_query_arg( $query_arg ) ); ?>">
			<span class="edit"><?php _ex( 'Edit', 'widget' ); ?></span>
			<span class="add"><?php _ex( 'Add', 'widget' ); ?></span>
			<span class="screen-reader-text"><?php echo $widget_title; ?></span>
		</a>
	</div>
	<div class="widget-title"><h3><?php echo $widget_title; ?><span class="in-widget-title"></span></h3></div>
	</div>

	<div class="widget-inside">
	<?php echo $before_form; ?>
	<?php echo $before_widget_content; ?>
	<?php
	if ( isset( $control['callback'] ) ) {
		$has_form = call_user_func_array( $control['callback'], $control['params'] );
	} else {
		echo "\t\t<p>" . __( 'There are no options for this widget.' ) . "</p>\n";
	}

	$noform_class = '';
	if ( 'noform' === $has_form ) {
		$noform_class = ' widget-control-noform';
	}
	?>
	<?php echo $after_widget_content; ?>
	<input type="hidden" name="widget-id" class="widget-id" value="<?php echo esc_attr( $id_format ); ?>" />
	<input type="hidden" name="id_base" class="id_base" value="<?php echo esc_attr( $id_base ); ?>" />
	<input type="hidden" name="widget-width" class="widget-width" value="<?php echo esc_attr( $width ); ?>" />
	<input type="hidden" name="widget-height" class="widget-height" value="<?php echo esc_attr( $height ); ?>" />
	<input type="hidden" name="widget_number" class="widget_number" value="<?php echo esc_attr( $widget_number ); ?>" />
	<input type="hidden" name="multi_number" class="multi_number" value="<?php echo esc_attr( $multi_number ); ?>" />
	<input type="hidden" name="add_new" class="add_new" value="<?php echo esc_attr( $add_new ); ?>" />

	<div class="widget-control-actions">
		<div class="alignleft">
			<button type="button" class="button-link button-link-delete widget-control-remove"><?php _e( 'Delete' ); ?></button>
			<span class="widget-control-close-wrapper">
				| <button type="button" class="button-link widget-control-close"><?php _e( 'Done' ); ?></button>
			</span>
		</div>
		<div class="alignright<?php echo $noform_class; ?>">
			<?php submit_button( __( 'Save' ), 'primary widget-control-save right', 'savewidget', false, array( 'id' => 'widget-' . esc_attr( $id_format ) . '-savewidget' ) ); ?>
			<span class="spinner"></span>
		</div>
		<br class="clear" />
	</div>
	<?php echo $after_form; ?>
	</div>

	<div class="widget-description">
	<?php
	$widget_description = wp_widget_description( $widget_id );
	echo ( $widget_description ) ? "$widget_description\n" : "$widget_title\n";
	?>
	</div>
	<?php
	echo $sidebar_args['after_widget'];

	return $sidebar_args;
}

/**
 * @param string $classes
 * @return string
 */
function wp_widgets_access_body_class( $classes ) {
	return "$classes widgets_access ";
}
class-walker-category-checklist.php000064400000011743151212616050013434 0ustar00<?php
/**
 * Taxonomy API: Walker_Category_Checklist class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 4.4.0
 */

/**
 * Core walker class to output an unordered list of category checkbox input elements.
 *
 * @since 2.5.1
 *
 * @see Walker
 * @see wp_category_checklist()
 * @see wp_terms_checklist()
 */
class Walker_Category_Checklist extends Walker {
	public $tree_type = 'category';
	public $db_fields = array(
		'parent' => 'parent',
		'id'     => 'term_id',
	); // TODO: Decouple this.

	/**
	 * Starts the list before the elements are added.
	 *
	 * @see Walker:start_lvl()
	 *
	 * @since 2.5.1
	 *
	 * @param string $output Used to append additional content (passed by reference).
	 * @param int    $depth  Depth of category. Used for tab indentation.
	 * @param array  $args   An array of arguments. See {@see wp_terms_checklist()}.
	 */
	public function start_lvl( &$output, $depth = 0, $args = array() ) {
		$indent  = str_repeat( "\t", $depth );
		$output .= "$indent<ul class='children'>\n";
	}

	/**
	 * Ends the list of after the elements are added.
	 *
	 * @see Walker::end_lvl()
	 *
	 * @since 2.5.1
	 *
	 * @param string $output Used to append additional content (passed by reference).
	 * @param int    $depth  Depth of category. Used for tab indentation.
	 * @param array  $args   An array of arguments. See {@see wp_terms_checklist()}.
	 */
	public function end_lvl( &$output, $depth = 0, $args = array() ) {
		$indent  = str_repeat( "\t", $depth );
		$output .= "$indent</ul>\n";
	}

	/**
	 * Start the element output.
	 *
	 * @see Walker::start_el()
	 *
	 * @since 2.5.1
	 * @since 5.9.0 Renamed `$category` to `$data_object` and `$id` to `$current_object_id`
	 *              to match parent class for PHP 8 named parameter support.
	 *
	 * @param string  $output            Used to append additional content (passed by reference).
	 * @param WP_Term $data_object       The current term object.
	 * @param int     $depth             Depth of the term in reference to parents. Default 0.
	 * @param array   $args              An array of arguments. See {@see wp_terms_checklist()}.
	 * @param int     $current_object_id Optional. ID of the current term. Default 0.
	 */
	public function start_el( &$output, $data_object, $depth = 0, $args = array(), $current_object_id = 0 ) {
		// Restores the more descriptive, specific name for use within this method.
		$category = $data_object;

		if ( empty( $args['taxonomy'] ) ) {
			$taxonomy = 'category';
		} else {
			$taxonomy = $args['taxonomy'];
		}

		if ( 'category' === $taxonomy ) {
			$name = 'post_category';
		} else {
			$name = 'tax_input[' . $taxonomy . ']';
		}

		$args['popular_cats'] = ! empty( $args['popular_cats'] ) ? array_map( 'intval', $args['popular_cats'] ) : array();

		$class = in_array( $category->term_id, $args['popular_cats'], true ) ? ' class="popular-category"' : '';

		$args['selected_cats'] = ! empty( $args['selected_cats'] ) ? array_map( 'intval', $args['selected_cats'] ) : array();

		if ( ! empty( $args['list_only'] ) ) {
			$aria_checked = 'false';
			$inner_class  = 'category';

			if ( in_array( $category->term_id, $args['selected_cats'], true ) ) {
				$inner_class .= ' selected';
				$aria_checked = 'true';
			}

			$output .= "\n" . '<li' . $class . '>' .
				'<div class="' . $inner_class . '" data-term-id=' . $category->term_id .
				' tabindex="0" role="checkbox" aria-checked="' . $aria_checked . '">' .
				/** This filter is documented in wp-includes/category-template.php */
				esc_html( apply_filters( 'the_category', $category->name, '', '' ) ) . '</div>';
		} else {
			$is_selected         = in_array( $category->term_id, $args['selected_cats'], true );
			$is_disabled         = ! empty( $args['disabled'] );
			$li_element_id       = wp_unique_prefixed_id( "in-{$taxonomy}-{$category->term_id}-" );
			$checkbox_element_id = wp_unique_prefixed_id( "in-{$taxonomy}-{$category->term_id}-" );

			$output .= "\n<li id='" . esc_attr( $li_element_id ) . "'$class>" .
				'<label class="selectit"><input value="' . $category->term_id . '" type="checkbox" name="' . $name . '[]" id="' . esc_attr( $checkbox_element_id ) . '"' .
				checked( $is_selected, true, false ) .
				disabled( $is_disabled, true, false ) . ' /> ' .
				/** This filter is documented in wp-includes/category-template.php */
				esc_html( apply_filters( 'the_category', $category->name, '', '' ) ) . '</label>';
		}
	}

	/**
	 * Ends the element output, if needed.
	 *
	 * @see Walker::end_el()
	 *
	 * @since 2.5.1
	 * @since 5.9.0 Renamed `$category` to `$data_object` to match parent class for PHP 8 named parameter support.
	 *
	 * @param string  $output      Used to append additional content (passed by reference).
	 * @param WP_Term $data_object The current term object.
	 * @param int     $depth       Depth of the term in reference to parents. Default 0.
	 * @param array   $args        An array of arguments. See {@see wp_terms_checklist()}.
	 */
	public function end_el( &$output, $data_object, $depth = 0, $args = array() ) {
		$output .= "</li>\n";
	}
}
edit-tag-messages.php000064400000002706151212616050010564 0ustar00<?php
/**
 * Edit Tags Administration: Messages
 *
 * @package WordPress
 * @subpackage Administration
 * @since 4.4.0
 */

$messages = array();
// 0 = unused. Messages start at index 1.
$messages['_item'] = array(
	0 => '',
	1 => __( 'Item added.' ),
	2 => __( 'Item deleted.' ),
	3 => __( 'Item updated.' ),
	4 => __( 'Item not added.' ),
	5 => __( 'Item not updated.' ),
	6 => __( 'Items deleted.' ),
);

$messages['category'] = array(
	0 => '',
	1 => __( 'Category added.' ),
	2 => __( 'Category deleted.' ),
	3 => __( 'Category updated.' ),
	4 => __( 'Category not added.' ),
	5 => __( 'Category not updated.' ),
	6 => __( 'Categories deleted.' ),
);

$messages['post_tag'] = array(
	0 => '',
	1 => __( 'Tag added.' ),
	2 => __( 'Tag deleted.' ),
	3 => __( 'Tag updated.' ),
	4 => __( 'Tag not added.' ),
	5 => __( 'Tag not updated.' ),
	6 => __( 'Tags deleted.' ),
);

/**
 * Filters the messages displayed when a tag is updated.
 *
 * @since 3.7.0
 *
 * @param array[] $messages Array of arrays of messages to be displayed, keyed by taxonomy name.
 */
$messages = apply_filters( 'term_updated_messages', $messages );

$message = false;
if ( isset( $_REQUEST['message'] ) && (int) $_REQUEST['message'] ) {
	$msg = (int) $_REQUEST['message'];
	if ( isset( $messages[ $taxonomy ][ $msg ] ) ) {
		$message = $messages[ $taxonomy ][ $msg ];
	} elseif ( ! isset( $messages[ $taxonomy ] ) && isset( $messages['_item'][ $msg ] ) ) {
		$message = $messages['_item'][ $msg ];
	}
}
class-wp-upgrader-skins.php000064400000002705151212616050011745 0ustar00<?php
/**
 * The User Interface "Skins" for the WordPress File Upgrader
 *
 * @package WordPress
 * @subpackage Upgrader
 * @since 2.8.0
 * @deprecated 4.7.0
 */

_deprecated_file( basename( __FILE__ ), '4.7.0', 'class-wp-upgrader.php' );

/** WP_Upgrader_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader-skin.php';

/** Plugin_Upgrader_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-plugin-upgrader-skin.php';

/** Theme_Upgrader_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-theme-upgrader-skin.php';

/** Bulk_Upgrader_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-bulk-upgrader-skin.php';

/** Bulk_Plugin_Upgrader_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-bulk-plugin-upgrader-skin.php';

/** Bulk_Theme_Upgrader_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-bulk-theme-upgrader-skin.php';

/** Plugin_Installer_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-plugin-installer-skin.php';

/** Theme_Installer_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-theme-installer-skin.php';

/** Language_Pack_Upgrader_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-language-pack-upgrader-skin.php';

/** Automatic_Upgrader_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-automatic-upgrader-skin.php';

/** WP_Ajax_Upgrader_Skin class */
require_once ABSPATH . 'wp-admin/includes/class-wp-ajax-upgrader-skin.php';
class-wp-ms-sites-list-table.php000064400000053165151212616050012617 0ustar00<?php
/**
 * List Table API: WP_MS_Sites_List_Table class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 3.1.0
 */

/**
 * Core class used to implement displaying sites in a list table for the network admin.
 *
 * @since 3.1.0
 *
 * @see WP_List_Table
 */
class WP_MS_Sites_List_Table extends WP_List_Table {

	/**
	 * Site status list.
	 *
	 * @since 4.3.0
	 * @var array
	 */
	public $status_list;

	/**
	 * Constructor.
	 *
	 * @since 3.1.0
	 *
	 * @see WP_List_Table::__construct() for more information on default arguments.
	 *
	 * @param array $args An associative array of arguments.
	 */
	public function __construct( $args = array() ) {
		$this->status_list = array(
			'archived' => array( 'site-archived', __( 'Archived' ) ),
			'spam'     => array( 'site-spammed', _x( 'Spam', 'site' ) ),
			'deleted'  => array( 'site-deleted', __( 'Flagged for Deletion' ) ),
			'mature'   => array( 'site-mature', __( 'Mature' ) ),
		);

		parent::__construct(
			array(
				'plural' => 'sites',
				'screen' => isset( $args['screen'] ) ? $args['screen'] : null,
			)
		);
	}

	/**
	 * @return bool
	 */
	public function ajax_user_can() {
		return current_user_can( 'manage_sites' );
	}

	/**
	 * Prepares the list of sites for display.
	 *
	 * @since 3.1.0
	 *
	 * @global string $mode List table view mode.
	 * @global string $s
	 * @global wpdb   $wpdb WordPress database abstraction object.
	 */
	public function prepare_items() {
		global $mode, $s, $wpdb;

		if ( ! empty( $_REQUEST['mode'] ) ) {
			$mode = 'excerpt' === $_REQUEST['mode'] ? 'excerpt' : 'list';
			set_user_setting( 'sites_list_mode', $mode );
		} else {
			$mode = get_user_setting( 'sites_list_mode', 'list' );
		}

		$per_page = $this->get_items_per_page( 'sites_network_per_page' );

		$pagenum = $this->get_pagenum();

		$s    = isset( $_REQUEST['s'] ) ? wp_unslash( trim( $_REQUEST['s'] ) ) : '';
		$wild = '';
		if ( str_contains( $s, '*' ) ) {
			$wild = '*';
			$s    = trim( $s, '*' );
		}

		/*
		 * If the network is large and a search is not being performed, show only
		 * the latest sites with no paging in order to avoid expensive count queries.
		 */
		if ( ! $s && wp_is_large_network() ) {
			if ( ! isset( $_REQUEST['orderby'] ) ) {
				$_GET['orderby']     = '';
				$_REQUEST['orderby'] = '';
			}
			if ( ! isset( $_REQUEST['order'] ) ) {
				$_GET['order']     = 'DESC';
				$_REQUEST['order'] = 'DESC';
			}
		}

		$args = array(
			'number'     => (int) $per_page,
			'offset'     => (int) ( ( $pagenum - 1 ) * $per_page ),
			'network_id' => get_current_network_id(),
		);

		if ( empty( $s ) ) {
			// Nothing to do.
		} elseif ( preg_match( '/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $s )
			|| preg_match( '/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.?$/', $s )
			|| preg_match( '/^[0-9]{1,3}\.[0-9]{1,3}\.?$/', $s )
			|| preg_match( '/^[0-9]{1,3}\.$/', $s )
		) {
			// IPv4 address.
			$reg_blog_ids = $wpdb->get_col(
				$wpdb->prepare(
					"SELECT blog_id FROM {$wpdb->registration_log} WHERE {$wpdb->registration_log}.IP LIKE %s",
					$wpdb->esc_like( $s ) . ( ! empty( $wild ) ? '%' : '' )
				)
			);

			if ( $reg_blog_ids ) {
				$args['site__in'] = $reg_blog_ids;
			}
		} elseif ( is_numeric( $s ) && empty( $wild ) ) {
			$args['ID'] = $s;
		} else {
			$args['search'] = $s;

			if ( ! is_subdomain_install() ) {
				$args['search_columns'] = array( 'path' );
			}
		}

		$order_by = isset( $_REQUEST['orderby'] ) ? $_REQUEST['orderby'] : '';
		if ( 'registered' === $order_by ) {
			// 'registered' is a valid field name.
		} elseif ( 'lastupdated' === $order_by ) {
			$order_by = 'last_updated';
		} elseif ( 'blogname' === $order_by ) {
			if ( is_subdomain_install() ) {
				$order_by = 'domain';
			} else {
				$order_by = 'path';
			}
		} elseif ( 'blog_id' === $order_by ) {
			$order_by = 'id';
		} elseif ( ! $order_by ) {
			$order_by = false;
		}

		$args['orderby'] = $order_by;

		if ( $order_by ) {
			$args['order'] = ( isset( $_REQUEST['order'] ) && 'DESC' === strtoupper( $_REQUEST['order'] ) ) ? 'DESC' : 'ASC';
		}

		if ( wp_is_large_network() ) {
			$args['no_found_rows'] = true;
		} else {
			$args['no_found_rows'] = false;
		}

		// Take into account the role the user has selected.
		$status = isset( $_REQUEST['status'] ) ? wp_unslash( trim( $_REQUEST['status'] ) ) : '';
		if ( in_array( $status, array( 'public', 'archived', 'mature', 'spam', 'deleted' ), true ) ) {
			$args[ $status ] = 1;
		}

		/**
		 * Filters the arguments for the site query in the sites list table.
		 *
		 * @since 4.6.0
		 *
		 * @param array $args An array of get_sites() arguments.
		 */
		$args = apply_filters( 'ms_sites_list_table_query_args', $args );

		$_sites = get_sites( $args );
		if ( is_array( $_sites ) ) {
			update_site_cache( $_sites );

			$this->items = array_slice( $_sites, 0, $per_page );
		}

		$total_sites = get_sites(
			array_merge(
				$args,
				array(
					'count'  => true,
					'offset' => 0,
					'number' => 0,
				)
			)
		);

		$this->set_pagination_args(
			array(
				'total_items' => $total_sites,
				'per_page'    => $per_page,
			)
		);
	}

	/**
	 */
	public function no_items() {
		_e( 'No sites found.' );
	}

	/**
	 * Gets links to filter sites by status.
	 *
	 * @since 5.3.0
	 *
	 * @return array
	 */
	protected function get_views() {
		$counts = wp_count_sites();

		$statuses = array(
			/* translators: %s: Number of sites. */
			'all'      => _nx_noop(
				'All <span class="count">(%s)</span>',
				'All <span class="count">(%s)</span>',
				'sites'
			),

			/* translators: %s: Number of sites. */
			'public'   => _n_noop(
				'Public <span class="count">(%s)</span>',
				'Public <span class="count">(%s)</span>'
			),

			/* translators: %s: Number of sites. */
			'archived' => _n_noop(
				'Archived <span class="count">(%s)</span>',
				'Archived <span class="count">(%s)</span>'
			),

			/* translators: %s: Number of sites. */
			'mature'   => _n_noop(
				'Mature <span class="count">(%s)</span>',
				'Mature <span class="count">(%s)</span>'
			),

			/* translators: %s: Number of sites. */
			'spam'     => _nx_noop(
				'Spam <span class="count">(%s)</span>',
				'Spam <span class="count">(%s)</span>',
				'sites'
			),

			/* translators: %s: Number of sites. */
			'deleted'  => _n_noop(
				'Flagged for Deletion <span class="count">(%s)</span>',
				'Flagged for Deletion <span class="count">(%s)</span>'
			),
		);

		$view_links       = array();
		$requested_status = isset( $_REQUEST['status'] ) ? wp_unslash( trim( $_REQUEST['status'] ) ) : '';
		$url              = 'sites.php';

		foreach ( $statuses as $status => $label_count ) {
			if ( (int) $counts[ $status ] > 0 ) {
				$label = sprintf(
					translate_nooped_plural( $label_count, $counts[ $status ] ),
					number_format_i18n( $counts[ $status ] )
				);

				$full_url = 'all' === $status ? $url : add_query_arg( 'status', $status, $url );

				$view_links[ $status ] = array(
					'url'     => esc_url( $full_url ),
					'label'   => $label,
					'current' => $requested_status === $status || ( '' === $requested_status && 'all' === $status ),
				);
			}
		}

		return $this->get_views_links( $view_links );
	}

	/**
	 * @return array
	 */
	protected function get_bulk_actions() {
		$actions = array();
		if ( current_user_can( 'delete_sites' ) ) {
			$actions['delete'] = __( 'Delete' );
		}
		$actions['spam']    = _x( 'Mark as spam', 'site' );
		$actions['notspam'] = _x( 'Not spam', 'site' );

		return $actions;
	}

	/**
	 * @global string $mode List table view mode.
	 *
	 * @param string $which The location of the pagination nav markup: Either 'top' or 'bottom'.
	 */
	protected function pagination( $which ) {
		global $mode;

		parent::pagination( $which );

		if ( 'top' === $which ) {
			$this->view_switcher( $mode );
		}
	}

	/**
	 * Displays extra controls between bulk actions and pagination.
	 *
	 * @since 5.3.0
	 *
	 * @param string $which The location of the extra table nav markup: Either 'top' or 'bottom'.
	 */
	protected function extra_tablenav( $which ) {
		?>
		<div class="alignleft actions">
		<?php
		if ( 'top' === $which ) {
			ob_start();

			/**
			 * Fires before the Filter button on the MS sites list table.
			 *
			 * @since 5.3.0
			 *
			 * @param string $which The location of the extra table nav markup: Either 'top' or 'bottom'.
			 */
			do_action( 'restrict_manage_sites', $which );

			$output = ob_get_clean();

			if ( ! empty( $output ) ) {
				echo $output;
				submit_button( __( 'Filter' ), '', 'filter_action', false, array( 'id' => 'site-query-submit' ) );
			}
		}
		?>
		</div>
		<?php
		/**
		 * Fires immediately following the closing "actions" div in the tablenav for the
		 * MS sites list table.
		 *
		 * @since 5.3.0
		 *
		 * @param string $which The location of the extra table nav markup: Either 'top' or 'bottom'.
		 */
		do_action( 'manage_sites_extra_tablenav', $which );
	}

	/**
	 * @return string[] Array of column titles keyed by their column name.
	 */
	public function get_columns() {
		$sites_columns = array(
			'cb'          => '<input type="checkbox" />',
			'blogname'    => __( 'URL' ),
			'lastupdated' => __( 'Last Updated' ),
			'registered'  => _x( 'Registered', 'site' ),
			'users'       => __( 'Users' ),
		);

		if ( has_filter( 'wpmublogsaction' ) ) {
			$sites_columns['plugins'] = __( 'Actions' );
		}

		/**
		 * Filters the displayed site columns in Sites list table.
		 *
		 * @since MU (3.0.0)
		 *
		 * @param string[] $sites_columns An array of displayed site columns. Default 'cb',
		 *                               'blogname', 'lastupdated', 'registered', 'users'.
		 */
		return apply_filters( 'wpmu_blogs_columns', $sites_columns );
	}

	/**
	 * @return array
	 */
	protected function get_sortable_columns() {

		if ( is_subdomain_install() ) {
			$blogname_abbr         = __( 'Domain' );
			$blogname_orderby_text = __( 'Table ordered by Site Domain Name.' );
		} else {
			$blogname_abbr         = __( 'Path' );
			$blogname_orderby_text = __( 'Table ordered by Site Path.' );
		}

		return array(
			'blogname'    => array( 'blogname', false, $blogname_abbr, $blogname_orderby_text ),
			'lastupdated' => array( 'lastupdated', true, __( 'Last Updated' ), __( 'Table ordered by Last Updated.' ) ),
			'registered'  => array( 'blog_id', true, _x( 'Registered', 'site' ), __( 'Table ordered by Site Registered Date.' ), 'desc' ),
		);
	}

	/**
	 * Handles the checkbox column output.
	 *
	 * @since 4.3.0
	 * @since 5.9.0 Renamed `$blog` to `$item` to match parent class for PHP 8 named parameter support.
	 *
	 * @param array $item Current site.
	 */
	public function column_cb( $item ) {
		// Restores the more descriptive, specific name for use within this method.
		$blog = $item;

		if ( ! is_main_site( $blog['blog_id'] ) ) :
			$blogname = untrailingslashit( $blog['domain'] . $blog['path'] );
			?>
			<input type="checkbox" id="blog_<?php echo $blog['blog_id']; ?>" name="allblogs[]" value="<?php echo esc_attr( $blog['blog_id'] ); ?>" />
			<label for="blog_<?php echo $blog['blog_id']; ?>">
				<span class="screen-reader-text">
				<?php
				/* translators: %s: Site URL. */
				printf( __( 'Select %s' ), $blogname );
				?>
				</span>
			</label>
			<?php
		endif;
	}

	/**
	 * Handles the ID column output.
	 *
	 * @since 4.4.0
	 *
	 * @param array $blog Current site.
	 */
	public function column_id( $blog ) {
		echo $blog['blog_id'];
	}

	/**
	 * Handles the site name column output.
	 *
	 * @since 4.3.0
	 *
	 * @global string $mode List table view mode.
	 *
	 * @param array $blog Current site.
	 */
	public function column_blogname( $blog ) {
		global $mode;

		$blogname = untrailingslashit( $blog['domain'] . $blog['path'] );

		?>
		<strong>
			<?php
			printf(
				'<a href="%1$s" class="edit">%2$s</a>',
				esc_url( network_admin_url( 'site-info.php?id=' . $blog['blog_id'] ) ),
				$blogname
			);

			$this->site_states( $blog );
			?>
		</strong>
		<?php
		if ( 'list' !== $mode ) {
			switch_to_blog( $blog['blog_id'] );
			echo '<p>';
			printf(
				/* translators: 1: Site title, 2: Site tagline. */
				__( '%1$s &#8211; %2$s' ),
				get_option( 'blogname' ),
				'<em>' . get_option( 'blogdescription' ) . '</em>'
			);
			echo '</p>';
			restore_current_blog();
		}
	}

	/**
	 * Handles the lastupdated column output.
	 *
	 * @since 4.3.0
	 *
	 * @global string $mode List table view mode.
	 *
	 * @param array $blog Current site.
	 */
	public function column_lastupdated( $blog ) {
		global $mode;

		if ( 'list' === $mode ) {
			$date = __( 'Y/m/d' );
		} else {
			$date = __( 'Y/m/d g:i:s a' );
		}

		if ( '0000-00-00 00:00:00' === $blog['last_updated'] ) {
			_e( 'Never' );
		} else {
			echo mysql2date( $date, $blog['last_updated'] );
		}
	}

	/**
	 * Handles the registered column output.
	 *
	 * @since 4.3.0
	 *
	 * @global string $mode List table view mode.
	 *
	 * @param array $blog Current site.
	 */
	public function column_registered( $blog ) {
		global $mode;

		if ( 'list' === $mode ) {
			$date = __( 'Y/m/d' );
		} else {
			$date = __( 'Y/m/d g:i:s a' );
		}

		if ( '0000-00-00 00:00:00' === $blog['registered'] ) {
			echo '&#x2014;';
		} else {
			echo mysql2date( $date, $blog['registered'] );
		}
	}

	/**
	 * Handles the users column output.
	 *
	 * @since 4.3.0
	 *
	 * @param array $blog Current site.
	 */
	public function column_users( $blog ) {
		$user_count = wp_cache_get( $blog['blog_id'] . '_user_count', 'blog-details' );
		if ( ! $user_count ) {
			$blog_users = new WP_User_Query(
				array(
					'blog_id'     => $blog['blog_id'],
					'fields'      => 'ID',
					'number'      => 1,
					'count_total' => true,
				)
			);
			$user_count = $blog_users->get_total();
			wp_cache_set( $blog['blog_id'] . '_user_count', $user_count, 'blog-details', 12 * HOUR_IN_SECONDS );
		}

		printf(
			'<a href="%1$s">%2$s</a>',
			esc_url( network_admin_url( 'site-users.php?id=' . $blog['blog_id'] ) ),
			number_format_i18n( $user_count )
		);
	}

	/**
	 * Handles the plugins column output.
	 *
	 * @since 4.3.0
	 *
	 * @param array $blog Current site.
	 */
	public function column_plugins( $blog ) {
		if ( has_filter( 'wpmublogsaction' ) ) {
			/**
			 * Fires inside the auxiliary 'Actions' column of the Sites list table.
			 *
			 * By default this column is hidden unless something is hooked to the action.
			 *
			 * @since MU (3.0.0)
			 *
			 * @param int $blog_id The site ID.
			 */
			do_action( 'wpmublogsaction', $blog['blog_id'] );
		}
	}

	/**
	 * Handles output for the default column.
	 *
	 * @since 4.3.0
	 * @since 5.9.0 Renamed `$blog` to `$item` to match parent class for PHP 8 named parameter support.
	 *
	 * @param array  $item        Current site.
	 * @param string $column_name Current column name.
	 */
	public function column_default( $item, $column_name ) {
		// Restores the more descriptive, specific name for use within this method.
		$blog = $item;

		/**
		 * Fires for each registered custom column in the Sites list table.
		 *
		 * @since 3.1.0
		 *
		 * @param string $column_name The name of the column to display.
		 * @param int    $blog_id     The site ID.
		 */
		do_action( 'manage_sites_custom_column', $column_name, $blog['blog_id'] );
	}

	/**
	 * Generates the list table rows.
	 *
	 * @since 3.1.0
	 */
	public function display_rows() {
		foreach ( $this->items as $blog ) {
			$blog  = $blog->to_array();
			$class = '';
			reset( $this->status_list );

			foreach ( $this->status_list as $status => $col ) {
				if ( '1' === $blog[ $status ] ) {
					$class = " class='{$col[0]}'";
				}
			}

			echo "<tr{$class}>";

			$this->single_row_columns( $blog );

			echo '</tr>';
		}
	}

	/**
	 * Determines whether to output comma-separated site states.
	 *
	 * @since 5.3.0
	 *
	 * @param array $site
	 */
	protected function site_states( $site ) {
		$site_states = array();

		// $site is still an array, so get the object.
		$_site = WP_Site::get_instance( $site['blog_id'] );

		if ( is_main_site( $_site->id ) ) {
			$site_states['main'] = __( 'Main' );
		}

		reset( $this->status_list );

		$site_status = isset( $_REQUEST['status'] ) ? wp_unslash( trim( $_REQUEST['status'] ) ) : '';
		foreach ( $this->status_list as $status => $col ) {
			if ( '1' === $_site->{$status} && $site_status !== $status ) {
				$site_states[ $col[0] ] = $col[1];
			}
		}

		/**
		 * Filters the default site display states for items in the Sites list table.
		 *
		 * @since 5.3.0
		 *
		 * @param string[] $site_states An array of site states. Default 'Main',
		 *                              'Archived', 'Mature', 'Spam', 'Flagged for Deletion'.
		 * @param WP_Site  $site        The current site object.
		 */
		$site_states = apply_filters( 'display_site_states', $site_states, $_site );

		if ( ! empty( $site_states ) ) {
			$state_count = count( $site_states );

			$i = 0;

			echo ' &mdash; ';

			foreach ( $site_states as $state ) {
				++$i;

				$separator = ( $i < $state_count ) ? ', ' : '';

				echo "<span class='post-state'>{$state}{$separator}</span>";
			}
		}
	}

	/**
	 * Gets the name of the default primary column.
	 *
	 * @since 4.3.0
	 *
	 * @return string Name of the default primary column, in this case, 'blogname'.
	 */
	protected function get_default_primary_column_name() {
		return 'blogname';
	}

	/**
	 * Generates and displays row action links.
	 *
	 * @since 4.3.0
	 * @since 5.9.0 Renamed `$blog` to `$item` to match parent class for PHP 8 named parameter support.
	 *
	 * @param array  $item        Site being acted upon.
	 * @param string $column_name Current column name.
	 * @param string $primary     Primary column name.
	 * @return string Row actions output for sites in Multisite, or an empty string
	 *                if the current column is not the primary column.
	 */
	protected function handle_row_actions( $item, $column_name, $primary ) {
		if ( $primary !== $column_name ) {
			return '';
		}

		// Restores the more descriptive, specific name for use within this method.
		$blog = $item;

		$blogname = untrailingslashit( $blog['domain'] . $blog['path'] );

		// Preordered.
		$actions = array(
			'edit'       => '',
			'backend'    => '',
			'activate'   => '',
			'deactivate' => '',
			'archive'    => '',
			'unarchive'  => '',
			'spam'       => '',
			'unspam'     => '',
			'delete'     => '',
			'visit'      => '',
		);

		$actions['edit'] = sprintf(
			'<a href="%1$s">%2$s</a>',
			esc_url( network_admin_url( 'site-info.php?id=' . $blog['blog_id'] ) ),
			__( 'Edit' )
		);

		$actions['backend'] = sprintf(
			'<a href="%1$s" class="edit">%2$s</a>',
			esc_url( get_admin_url( $blog['blog_id'] ) ),
			__( 'Dashboard' )
		);

		if ( ! is_main_site( $blog['blog_id'] ) ) {
			if ( '1' === $blog['deleted'] ) {
				$actions['activate'] = sprintf(
					'<a href="%1$s">%2$s</a>',
					esc_url(
						wp_nonce_url(
							network_admin_url( 'sites.php?action=confirm&amp;action2=activateblog&amp;id=' . $blog['blog_id'] ),
							'activateblog_' . $blog['blog_id']
						)
					),
					_x( 'Remove Deletion Flag', 'site' )
				);
			} else {
				$actions['deactivate'] = sprintf(
					'<a href="%1$s">%2$s</a>',
					esc_url(
						wp_nonce_url(
							network_admin_url( 'sites.php?action=confirm&amp;action2=deactivateblog&amp;id=' . $blog['blog_id'] ),
							'deactivateblog_' . $blog['blog_id']
						)
					),
					__( 'Flag for Deletion' )
				);
			}

			if ( '1' === $blog['archived'] ) {
				$actions['unarchive'] = sprintf(
					'<a href="%1$s">%2$s</a>',
					esc_url(
						wp_nonce_url(
							network_admin_url( 'sites.php?action=confirm&amp;action2=unarchiveblog&amp;id=' . $blog['blog_id'] ),
							'unarchiveblog_' . $blog['blog_id']
						)
					),
					__( 'Unarchive' )
				);
			} else {
				$actions['archive'] = sprintf(
					'<a href="%1$s">%2$s</a>',
					esc_url(
						wp_nonce_url(
							network_admin_url( 'sites.php?action=confirm&amp;action2=archiveblog&amp;id=' . $blog['blog_id'] ),
							'archiveblog_' . $blog['blog_id']
						)
					),
					_x( 'Archive', 'verb; site' )
				);
			}

			if ( '1' === $blog['spam'] ) {
				$actions['unspam'] = sprintf(
					'<a href="%1$s">%2$s</a>',
					esc_url(
						wp_nonce_url(
							network_admin_url( 'sites.php?action=confirm&amp;action2=unspamblog&amp;id=' . $blog['blog_id'] ),
							'unspamblog_' . $blog['blog_id']
						)
					),
					_x( 'Not Spam', 'site' )
				);
			} else {
				$actions['spam'] = sprintf(
					'<a href="%1$s">%2$s</a>',
					esc_url(
						wp_nonce_url(
							network_admin_url( 'sites.php?action=confirm&amp;action2=spamblog&amp;id=' . $blog['blog_id'] ),
							'spamblog_' . $blog['blog_id']
						)
					),
					_x( 'Spam', 'site' )
				);
			}

			if ( current_user_can( 'delete_site', $blog['blog_id'] ) ) {
				$actions['delete'] = sprintf(
					'<a href="%1$s">%2$s</a>',
					esc_url(
						wp_nonce_url(
							network_admin_url( 'sites.php?action=confirm&amp;action2=deleteblog&amp;id=' . $blog['blog_id'] ),
							'deleteblog_' . $blog['blog_id']
						)
					),
					__( 'Delete Permanently' )
				);
			}
		}

		$actions['visit'] = sprintf(
			'<a href="%1$s" rel="bookmark">%2$s</a>',
			esc_url( get_home_url( $blog['blog_id'], '/' ) ),
			__( 'Visit' )
		);

		/**
		 * Filters the action links displayed for each site in the Sites list table.
		 *
		 * The 'Edit', 'Dashboard', 'Delete Permanently', and 'Visit' links are displayed by
		 * default for each site. The site's status determines whether to show the
		 * 'Remove Deletion Flag' or 'Flag for Deletion' link, 'Unarchive' or 'Archive' links, and
		 * 'Not Spam' or 'Spam' link for each site.
		 *
		 * @since 3.1.0
		 *
		 * @param string[] $actions  An array of action links to be displayed.
		 * @param int      $blog_id  The site ID.
		 * @param string   $blogname Site path, formatted depending on whether it is a sub-domain
		 *                           or subdirectory multisite installation.
		 */
		$actions = apply_filters( 'manage_sites_action_links', array_filter( $actions ), $blog['blog_id'], $blogname );

		return $this->row_actions( $actions );
	}
}
file.php000064400000277534151212616050006215 0ustar00<?php
/**
 * Filesystem API: Top-level functionality
 *
 * Functions for reading, writing, modifying, and deleting files on the file system.
 * Includes functionality for theme-specific files as well as operations for uploading,
 * archiving, and rendering output when necessary.
 *
 * @package WordPress
 * @subpackage Filesystem
 * @since 2.3.0
 */

/** The descriptions for theme files. */
$wp_file_descriptions = array(
	'functions.php'         => __( 'Theme Functions' ),
	'header.php'            => __( 'Theme Header' ),
	'footer.php'            => __( 'Theme Footer' ),
	'sidebar.php'           => __( 'Sidebar' ),
	'comments.php'          => __( 'Comments' ),
	'searchform.php'        => __( 'Search Form' ),
	'404.php'               => __( '404 Template' ),
	'link.php'              => __( 'Links Template' ),
	'theme.json'            => __( 'Theme Styles & Block Settings' ),
	// Archives.
	'index.php'             => __( 'Main Index Template' ),
	'archive.php'           => __( 'Archives' ),
	'author.php'            => __( 'Author Template' ),
	'taxonomy.php'          => __( 'Taxonomy Template' ),
	'category.php'          => __( 'Category Template' ),
	'tag.php'               => __( 'Tag Template' ),
	'home.php'              => __( 'Posts Page' ),
	'search.php'            => __( 'Search Results' ),
	'date.php'              => __( 'Date Template' ),
	// Content.
	'singular.php'          => __( 'Singular Template' ),
	'single.php'            => __( 'Single Post' ),
	'page.php'              => __( 'Single Page' ),
	'front-page.php'        => __( 'Homepage' ),
	'privacy-policy.php'    => __( 'Privacy Policy Page' ),
	// Attachments.
	'attachment.php'        => __( 'Attachment Template' ),
	'image.php'             => __( 'Image Attachment Template' ),
	'video.php'             => __( 'Video Attachment Template' ),
	'audio.php'             => __( 'Audio Attachment Template' ),
	'application.php'       => __( 'Application Attachment Template' ),
	// Embeds.
	'embed.php'             => __( 'Embed Template' ),
	'embed-404.php'         => __( 'Embed 404 Template' ),
	'embed-content.php'     => __( 'Embed Content Template' ),
	'header-embed.php'      => __( 'Embed Header Template' ),
	'footer-embed.php'      => __( 'Embed Footer Template' ),
	// Stylesheets.
	'style.css'             => __( 'Stylesheet' ),
	'editor-style.css'      => __( 'Visual Editor Stylesheet' ),
	'editor-style-rtl.css'  => __( 'Visual Editor RTL Stylesheet' ),
	'rtl.css'               => __( 'RTL Stylesheet' ),
	// Other.
	'my-hacks.php'          => __( 'my-hacks.php (legacy hacks support)' ),
	'.htaccess'             => __( '.htaccess (for rewrite rules )' ),
	// Deprecated files.
	'wp-layout.css'         => __( 'Stylesheet' ),
	'wp-comments.php'       => __( 'Comments Template' ),
	'wp-comments-popup.php' => __( 'Popup Comments Template' ),
	'comments-popup.php'    => __( 'Popup Comments' ),
);

/**
 * Gets the description for standard WordPress theme files.
 *
 * @since 1.5.0
 *
 * @global array $wp_file_descriptions Theme file descriptions.
 * @global array $allowed_files        List of allowed files.
 *
 * @param string $file Filesystem path or filename.
 * @return string Description of file from $wp_file_descriptions or basename of $file if description doesn't exist.
 *                Appends 'Page Template' to basename of $file if the file is a page template.
 */
function get_file_description( $file ) {
	global $wp_file_descriptions, $allowed_files;

	$dirname   = pathinfo( $file, PATHINFO_DIRNAME );
	$file_path = $allowed_files[ $file ];

	if ( isset( $wp_file_descriptions[ basename( $file ) ] ) && '.' === $dirname ) {
		return $wp_file_descriptions[ basename( $file ) ];
	} elseif ( file_exists( $file_path ) && is_file( $file_path ) ) {
		$template_data = implode( '', file( $file_path ) );

		if ( preg_match( '|Template Name:(.*)$|mi', $template_data, $name ) ) {
			/* translators: %s: Template name. */
			return sprintf( __( '%s Page Template' ), _cleanup_header_comment( $name[1] ) );
		}
	}

	return trim( basename( $file ) );
}

/**
 * Gets the absolute filesystem path to the root of the WordPress installation.
 *
 * @since 1.5.0
 *
 * @return string Full filesystem path to the root of the WordPress installation.
 */
function get_home_path() {
	$home    = set_url_scheme( get_option( 'home' ), 'http' );
	$siteurl = set_url_scheme( get_option( 'siteurl' ), 'http' );

	if ( ! empty( $home ) && 0 !== strcasecmp( $home, $siteurl ) ) {
		$wp_path_rel_to_home = str_ireplace( $home, '', $siteurl ); /* $siteurl - $home */
		$pos                 = strripos( str_replace( '\\', '/', $_SERVER['SCRIPT_FILENAME'] ), trailingslashit( $wp_path_rel_to_home ) );
		$home_path           = substr( $_SERVER['SCRIPT_FILENAME'], 0, $pos );
		$home_path           = trailingslashit( $home_path );
	} else {
		$home_path = ABSPATH;
	}

	return str_replace( '\\', '/', $home_path );
}

/**
 * Returns a listing of all files in the specified folder and all subdirectories up to 100 levels deep.
 *
 * The depth of the recursiveness can be controlled by the $levels param.
 *
 * @since 2.6.0
 * @since 4.9.0 Added the `$exclusions` parameter.
 * @since 6.3.0 Added the `$include_hidden` parameter.
 *
 * @param string   $folder         Optional. Full path to folder. Default empty.
 * @param int      $levels         Optional. Levels of folders to follow, Default 100 (PHP Loop limit).
 * @param string[] $exclusions     Optional. List of folders and files to skip.
 * @param bool     $include_hidden Optional. Whether to include details of hidden ("." prefixed) files.
 *                                 Default false.
 * @return string[]|false Array of files on success, false on failure.
 */
function list_files( $folder = '', $levels = 100, $exclusions = array(), $include_hidden = false ) {
	if ( empty( $folder ) ) {
		return false;
	}

	$folder = trailingslashit( $folder );

	if ( ! $levels ) {
		return false;
	}

	$files = array();

	$dir = @opendir( $folder );

	if ( $dir ) {
		while ( ( $file = readdir( $dir ) ) !== false ) {
			// Skip current and parent folder links.
			if ( in_array( $file, array( '.', '..' ), true ) ) {
				continue;
			}

			// Skip hidden and excluded files.
			if ( ( ! $include_hidden && '.' === $file[0] ) || in_array( $file, $exclusions, true ) ) {
				continue;
			}

			if ( is_dir( $folder . $file ) ) {
				$files2 = list_files( $folder . $file, $levels - 1, array(), $include_hidden );
				if ( $files2 ) {
					$files = array_merge( $files, $files2 );
				} else {
					$files[] = $folder . $file . '/';
				}
			} else {
				$files[] = $folder . $file;
			}
		}

		closedir( $dir );
	}

	return $files;
}

/**
 * Gets the list of file extensions that are editable in plugins.
 *
 * @since 4.9.0
 *
 * @param string $plugin Path to the plugin file relative to the plugins directory.
 * @return string[] Array of editable file extensions.
 */
function wp_get_plugin_file_editable_extensions( $plugin ) {

	$default_types = array(
		'bash',
		'conf',
		'css',
		'diff',
		'htm',
		'html',
		'http',
		'inc',
		'include',
		'js',
		'json',
		'jsx',
		'less',
		'md',
		'patch',
		'php',
		'php3',
		'php4',
		'php5',
		'php7',
		'phps',
		'phtml',
		'sass',
		'scss',
		'sh',
		'sql',
		'svg',
		'text',
		'txt',
		'xml',
		'yaml',
		'yml',
	);

	/**
	 * Filters the list of file types allowed for editing in the plugin file editor.
	 *
	 * @since 2.8.0
	 * @since 4.9.0 Added the `$plugin` parameter.
	 *
	 * @param string[] $default_types An array of editable plugin file extensions.
	 * @param string   $plugin        Path to the plugin file relative to the plugins directory.
	 */
	$file_types = (array) apply_filters( 'editable_extensions', $default_types, $plugin );

	return $file_types;
}

/**
 * Gets the list of file extensions that are editable for a given theme.
 *
 * @since 4.9.0
 *
 * @param WP_Theme $theme Theme object.
 * @return string[] Array of editable file extensions.
 */
function wp_get_theme_file_editable_extensions( $theme ) {

	$default_types = array(
		'bash',
		'conf',
		'css',
		'diff',
		'htm',
		'html',
		'http',
		'inc',
		'include',
		'js',
		'json',
		'jsx',
		'less',
		'md',
		'patch',
		'php',
		'php3',
		'php4',
		'php5',
		'php7',
		'phps',
		'phtml',
		'sass',
		'scss',
		'sh',
		'sql',
		'svg',
		'text',
		'txt',
		'xml',
		'yaml',
		'yml',
	);

	/**
	 * Filters the list of file types allowed for editing in the theme file editor.
	 *
	 * @since 4.4.0
	 *
	 * @param string[] $default_types An array of editable theme file extensions.
	 * @param WP_Theme $theme         The active theme object.
	 */
	$file_types = apply_filters( 'wp_theme_editor_filetypes', $default_types, $theme );

	// Ensure that default types are still there.
	return array_unique( array_merge( $file_types, $default_types ) );
}

/**
 * Prints file editor templates (for plugins and themes).
 *
 * @since 4.9.0
 */
function wp_print_file_editor_templates() {
	?>
	<script type="text/html" id="tmpl-wp-file-editor-notice">
		<div class="notice inline notice-{{ data.type || 'info' }} {{ data.alt ? 'notice-alt' : '' }} {{ data.dismissible ? 'is-dismissible' : '' }} {{ data.classes || '' }}">
			<# if ( 'php_error' === data.code ) { #>
				<p>
					<?php
					printf(
						/* translators: 1: Line number, 2: File path. */
						__( 'Your PHP code changes were not applied due to an error on line %1$s of file %2$s. Please fix and try saving again.' ),
						'{{ data.line }}',
						'{{ data.file }}'
					);
					?>
				</p>
				<pre>{{ data.message }}</pre>
			<# } else if ( 'file_not_writable' === data.code ) { #>
				<p>
					<?php
					printf(
						/* translators: %s: Documentation URL. */
						__( 'You need to make this file writable before you can save your changes. See <a href="%s">Changing File Permissions</a> for more information.' ),
						__( 'https://developer.wordpress.org/advanced-administration/server/file-permissions/' )
					);
					?>
				</p>
			<# } else { #>
				<p>{{ data.message || data.code }}</p>

				<# if ( 'lint_errors' === data.code ) { #>
					<p>
						<# var elementId = 'el-' + String( Math.random() ); #>
						<input id="{{ elementId }}"  type="checkbox">
						<label for="{{ elementId }}"><?php _e( 'Update anyway, even though it might break your site?' ); ?></label>
					</p>
				<# } #>
			<# } #>
			<# if ( data.dismissible ) { #>
				<button type="button" class="notice-dismiss"><span class="screen-reader-text">
					<?php
					/* translators: Hidden accessibility text. */
					_e( 'Dismiss' );
					?>
				</span></button>
			<# } #>
		</div>
	</script>
	<?php
}

/**
 * Attempts to edit a file for a theme or plugin.
 *
 * When editing a PHP file, loopback requests will be made to the admin and the homepage
 * to attempt to see if there is a fatal error introduced. If so, the PHP change will be
 * reverted.
 *
 * @since 4.9.0
 *
 * @param string[] $args {
 *     Args. Note that all of the arg values are already unslashed. They are, however,
 *     coming straight from `$_POST` and are not validated or sanitized in any way.
 *
 *     @type string $file       Relative path to file.
 *     @type string $plugin     Path to the plugin file relative to the plugins directory.
 *     @type string $theme      Theme being edited.
 *     @type string $newcontent New content for the file.
 *     @type string $nonce      Nonce.
 * }
 * @return true|WP_Error True on success or `WP_Error` on failure.
 */
function wp_edit_theme_plugin_file( $args ) {
	if ( empty( $args['file'] ) ) {
		return new WP_Error( 'missing_file' );
	}

	if ( 0 !== validate_file( $args['file'] ) ) {
		return new WP_Error( 'bad_file' );
	}

	if ( ! isset( $args['newcontent'] ) ) {
		return new WP_Error( 'missing_content' );
	}

	if ( ! isset( $args['nonce'] ) ) {
		return new WP_Error( 'missing_nonce' );
	}

	$file    = $args['file'];
	$content = $args['newcontent'];

	$plugin    = null;
	$theme     = null;
	$real_file = null;

	if ( ! empty( $args['plugin'] ) ) {
		$plugin = $args['plugin'];

		if ( ! current_user_can( 'edit_plugins' ) ) {
			return new WP_Error( 'unauthorized', __( 'Sorry, you are not allowed to edit plugins for this site.' ) );
		}

		if ( ! wp_verify_nonce( $args['nonce'], 'edit-plugin_' . $file ) ) {
			return new WP_Error( 'nonce_failure' );
		}

		if ( ! array_key_exists( $plugin, get_plugins() ) ) {
			return new WP_Error( 'invalid_plugin' );
		}

		if ( 0 !== validate_file( $file, get_plugin_files( $plugin ) ) ) {
			return new WP_Error( 'bad_plugin_file_path', __( 'Sorry, that file cannot be edited.' ) );
		}

		$editable_extensions = wp_get_plugin_file_editable_extensions( $plugin );

		$real_file = WP_PLUGIN_DIR . '/' . $file;

		$is_active = in_array(
			$plugin,
			(array) get_option( 'active_plugins', array() ),
			true
		);

	} elseif ( ! empty( $args['theme'] ) ) {
		$stylesheet = $args['theme'];

		if ( 0 !== validate_file( $stylesheet ) ) {
			return new WP_Error( 'bad_theme_path' );
		}

		if ( ! current_user_can( 'edit_themes' ) ) {
			return new WP_Error( 'unauthorized', __( 'Sorry, you are not allowed to edit templates for this site.' ) );
		}

		$theme = wp_get_theme( $stylesheet );
		if ( ! $theme->exists() ) {
			return new WP_Error( 'non_existent_theme', __( 'The requested theme does not exist.' ) );
		}

		if ( ! wp_verify_nonce( $args['nonce'], 'edit-theme_' . $stylesheet . '_' . $file ) ) {
			return new WP_Error( 'nonce_failure' );
		}

		if ( $theme->errors() && 'theme_no_stylesheet' === $theme->errors()->get_error_code() ) {
			return new WP_Error(
				'theme_no_stylesheet',
				__( 'The requested theme does not exist.' ) . ' ' . $theme->errors()->get_error_message()
			);
		}

		$editable_extensions = wp_get_theme_file_editable_extensions( $theme );

		$allowed_files = array();
		foreach ( $editable_extensions as $type ) {
			switch ( $type ) {
				case 'php':
					$allowed_files = array_merge( $allowed_files, $theme->get_files( 'php', -1 ) );
					break;
				case 'css':
					$style_files                = $theme->get_files( 'css', -1 );
					$allowed_files['style.css'] = $style_files['style.css'];
					$allowed_files              = array_merge( $allowed_files, $style_files );
					break;
				default:
					$allowed_files = array_merge( $allowed_files, $theme->get_files( $type, -1 ) );
					break;
			}
		}

		// Compare based on relative paths.
		if ( 0 !== validate_file( $file, array_keys( $allowed_files ) ) ) {
			return new WP_Error( 'disallowed_theme_file', __( 'Sorry, that file cannot be edited.' ) );
		}

		$real_file = $theme->get_stylesheet_directory() . '/' . $file;

		$is_active = ( get_stylesheet() === $stylesheet || get_template() === $stylesheet );

	} else {
		return new WP_Error( 'missing_theme_or_plugin' );
	}

	// Ensure file is real.
	if ( ! is_file( $real_file ) ) {
		return new WP_Error( 'file_does_not_exist', __( 'File does not exist! Please double check the name and try again.' ) );
	}

	// Ensure file extension is allowed.
	$extension = null;
	if ( preg_match( '/\.([^.]+)$/', $real_file, $matches ) ) {
		$extension = strtolower( $matches[1] );
		if ( ! in_array( $extension, $editable_extensions, true ) ) {
			return new WP_Error( 'illegal_file_type', __( 'Files of this type are not editable.' ) );
		}
	}

	$previous_content = file_get_contents( $real_file );

	if ( ! is_writable( $real_file ) ) {
		return new WP_Error( 'file_not_writable' );
	}

	$f = fopen( $real_file, 'w+' );

	if ( false === $f ) {
		return new WP_Error( 'file_not_writable' );
	}

	$written = fwrite( $f, $content );
	fclose( $f );

	if ( false === $written ) {
		return new WP_Error( 'unable_to_write', __( 'Unable to write to file.' ) );
	}

	wp_opcache_invalidate( $real_file, true );

	if ( $is_active && 'php' === $extension ) {

		$scrape_key   = md5( rand() );
		$transient    = 'scrape_key_' . $scrape_key;
		$scrape_nonce = (string) rand();
		// It shouldn't take more than 60 seconds to make the two loopback requests.
		set_transient( $transient, $scrape_nonce, 60 );

		$cookies       = wp_unslash( $_COOKIE );
		$scrape_params = array(
			'wp_scrape_key'   => $scrape_key,
			'wp_scrape_nonce' => $scrape_nonce,
		);
		$headers       = array(
			'Cache-Control' => 'no-cache',
		);

		/** This filter is documented in wp-includes/class-wp-http-streams.php */
		$sslverify = apply_filters( 'https_local_ssl_verify', false );

		// Include Basic auth in loopback requests.
		if ( isset( $_SERVER['PHP_AUTH_USER'] ) && isset( $_SERVER['PHP_AUTH_PW'] ) ) {
			$headers['Authorization'] = 'Basic ' . base64_encode( wp_unslash( $_SERVER['PHP_AUTH_USER'] ) . ':' . wp_unslash( $_SERVER['PHP_AUTH_PW'] ) );
		}

		// Make sure PHP process doesn't die before loopback requests complete.
		if ( function_exists( 'set_time_limit' ) ) {
			set_time_limit( 5 * MINUTE_IN_SECONDS );
		}

		// Time to wait for loopback requests to finish.
		$timeout = 100; // 100 seconds.

		$needle_start = "###### wp_scraping_result_start:$scrape_key ######";
		$needle_end   = "###### wp_scraping_result_end:$scrape_key ######";

		// Attempt loopback request to editor to see if user just whitescreened themselves.
		if ( $plugin ) {
			$url = add_query_arg( compact( 'plugin', 'file' ), admin_url( 'plugin-editor.php' ) );
		} elseif ( isset( $stylesheet ) ) {
			$url = add_query_arg(
				array(
					'theme' => $stylesheet,
					'file'  => $file,
				),
				admin_url( 'theme-editor.php' )
			);
		} else {
			$url = admin_url();
		}

		if ( function_exists( 'session_status' ) && PHP_SESSION_ACTIVE === session_status() ) {
			/*
			 * Close any active session to prevent HTTP requests from timing out
			 * when attempting to connect back to the site.
			 */
			session_write_close();
		}

		$url                    = add_query_arg( $scrape_params, $url );
		$r                      = wp_remote_get( $url, compact( 'cookies', 'headers', 'timeout', 'sslverify' ) );
		$body                   = wp_remote_retrieve_body( $r );
		$scrape_result_position = strpos( $body, $needle_start );

		$loopback_request_failure = array(
			'code'    => 'loopback_request_failed',
			'message' => __( 'Unable to communicate back with site to check for fatal errors, so the PHP change was reverted. You will need to upload your PHP file change by some other means, such as by using SFTP.' ),
		);
		$json_parse_failure       = array(
			'code' => 'json_parse_error',
		);

		$result = null;

		if ( false === $scrape_result_position ) {
			$result = $loopback_request_failure;
		} else {
			$error_output = substr( $body, $scrape_result_position + strlen( $needle_start ) );
			$error_output = substr( $error_output, 0, strpos( $error_output, $needle_end ) );
			$result       = json_decode( trim( $error_output ), true );
			if ( empty( $result ) ) {
				$result = $json_parse_failure;
			}
		}

		// Try making request to homepage as well to see if visitors have been whitescreened.
		if ( true === $result ) {
			$url                    = home_url( '/' );
			$url                    = add_query_arg( $scrape_params, $url );
			$r                      = wp_remote_get( $url, compact( 'cookies', 'headers', 'timeout', 'sslverify' ) );
			$body                   = wp_remote_retrieve_body( $r );
			$scrape_result_position = strpos( $body, $needle_start );

			if ( false === $scrape_result_position ) {
				$result = $loopback_request_failure;
			} else {
				$error_output = substr( $body, $scrape_result_position + strlen( $needle_start ) );
				$error_output = substr( $error_output, 0, strpos( $error_output, $needle_end ) );
				$result       = json_decode( trim( $error_output ), true );
				if ( empty( $result ) ) {
					$result = $json_parse_failure;
				}
			}
		}

		delete_transient( $transient );

		if ( true !== $result ) {
			// Roll-back file change.
			file_put_contents( $real_file, $previous_content );
			wp_opcache_invalidate( $real_file, true );

			if ( ! isset( $result['message'] ) ) {
				$message = __( 'An error occurred. Please try again later.' );
			} else {
				$message = $result['message'];
				unset( $result['message'] );
			}

			return new WP_Error( 'php_error', $message, $result );
		}
	}

	if ( $theme instanceof WP_Theme ) {
		$theme->cache_delete();
	}

	return true;
}


/**
 * Returns a filename of a temporary unique file.
 *
 * Please note that the calling function must delete or move the file.
 *
 * The filename is based off the passed parameter or defaults to the current unix timestamp,
 * while the directory can either be passed as well, or by leaving it blank, default to a writable
 * temporary directory.
 *
 * @since 2.6.0
 *
 * @param string $filename Optional. Filename to base the Unique file off. Default empty.
 * @param string $dir      Optional. Directory to store the file in. Default empty.
 * @return string A writable filename.
 */
function wp_tempnam( $filename = '', $dir = '' ) {
	if ( empty( $dir ) ) {
		$dir = get_temp_dir();
	}

	if ( empty( $filename ) || in_array( $filename, array( '.', '/', '\\' ), true ) ) {
		$filename = uniqid();
	}

	// Use the basename of the given file without the extension as the name for the temporary directory.
	$temp_filename = basename( $filename );
	$temp_filename = preg_replace( '|\.[^.]*$|', '', $temp_filename );

	// If the folder is falsey, use its parent directory name instead.
	if ( ! $temp_filename ) {
		return wp_tempnam( dirname( $filename ), $dir );
	}

	// Suffix some random data to avoid filename conflicts.
	$temp_filename .= '-' . wp_generate_password( 6, false );
	$temp_filename .= '.tmp';
	$temp_filename  = wp_unique_filename( $dir, $temp_filename );

	/*
	 * Filesystems typically have a limit of 255 characters for a filename.
	 *
	 * If the generated unique filename exceeds this, truncate the initial
	 * filename and try again.
	 *
	 * As it's possible that the truncated filename may exist, producing a
	 * suffix of "-1" or "-10" which could exceed the limit again, truncate
	 * it to 252 instead.
	 */
	$characters_over_limit = strlen( $temp_filename ) - 252;
	if ( $characters_over_limit > 0 ) {
		$filename = substr( $filename, 0, -$characters_over_limit );
		return wp_tempnam( $filename, $dir );
	}

	$temp_filename = $dir . $temp_filename;

	$fp = @fopen( $temp_filename, 'x' );

	if ( ! $fp && is_writable( $dir ) && file_exists( $temp_filename ) ) {
		return wp_tempnam( $filename, $dir );
	}

	if ( $fp ) {
		fclose( $fp );
	}

	return $temp_filename;
}

/**
 * Makes sure that the file that was requested to be edited is allowed to be edited.
 *
 * Function will die if you are not allowed to edit the file.
 *
 * @since 1.5.0
 *
 * @param string   $file          File the user is attempting to edit.
 * @param string[] $allowed_files Optional. Array of allowed files to edit.
 *                                `$file` must match an entry exactly.
 * @return string|void Returns the file name on success, dies on failure.
 */
function validate_file_to_edit( $file, $allowed_files = array() ) {
	$code = validate_file( $file, $allowed_files );

	if ( ! $code ) {
		return $file;
	}

	switch ( $code ) {
		case 1:
			wp_die( __( 'Sorry, that file cannot be edited.' ) );

			// case 2 :
			// wp_die( __('Sorry, cannot call files with their real path.' ));

		case 3:
			wp_die( __( 'Sorry, that file cannot be edited.' ) );
	}
}

/**
 * Handles PHP uploads in WordPress.
 *
 * Sanitizes file names, checks extensions for mime type, and moves the file
 * to the appropriate directory within the uploads directory.
 *
 * @access private
 * @since 4.0.0
 *
 * @see wp_handle_upload_error
 *
 * @param array       $file      {
 *     Reference to a single element from `$_FILES`. Call the function once for each uploaded file.
 *
 *     @type string $name     The original name of the file on the client machine.
 *     @type string $type     The mime type of the file, if the browser provided this information.
 *     @type string $tmp_name The temporary filename of the file in which the uploaded file was stored on the server.
 *     @type int    $size     The size, in bytes, of the uploaded file.
 *     @type int    $error    The error code associated with this file upload.
 * }
 * @param array|false $overrides {
 *     An array of override parameters for this file, or boolean false if none are provided.
 *
 *     @type callable $upload_error_handler     Function to call when there is an error during the upload process.
 *                                              See {@see wp_handle_upload_error()}.
 *     @type callable $unique_filename_callback Function to call when determining a unique file name for the file.
 *                                              See {@see wp_unique_filename()}.
 *     @type string[] $upload_error_strings     The strings that describe the error indicated in
 *                                              `$_FILES[{form field}]['error']`.
 *     @type bool     $test_form                Whether to test that the `$_POST['action']` parameter is as expected.
 *     @type bool     $test_size                Whether to test that the file size is greater than zero bytes.
 *     @type bool     $test_type                Whether to test that the mime type of the file is as expected.
 *     @type string[] $mimes                    Array of allowed mime types keyed by their file extension regex.
 * }
 * @param string      $time      Time formatted in 'yyyy/mm'.
 * @param string      $action    Expected value for `$_POST['action']`.
 * @return array {
 *     On success, returns an associative array of file attributes.
 *     On failure, returns `$overrides['upload_error_handler']( &$file, $message )`
 *     or `array( 'error' => $message )`.
 *
 *     @type string $file Filename of the newly-uploaded file.
 *     @type string $url  URL of the newly-uploaded file.
 *     @type string $type Mime type of the newly-uploaded file.
 * }
 */
function _wp_handle_upload( &$file, $overrides, $time, $action ) {
	// The default error handler.
	if ( ! function_exists( 'wp_handle_upload_error' ) ) {
		function wp_handle_upload_error( &$file, $message ) {
			return array( 'error' => $message );
		}
	}

	/**
	 * Filters the data for a file before it is uploaded to WordPress.
	 *
	 * The dynamic portion of the hook name, `$action`, refers to the post action.
	 *
	 * Possible hook names include:
	 *
	 *  - `wp_handle_sideload_prefilter`
	 *  - `wp_handle_upload_prefilter`
	 *
	 * @since 2.9.0 as 'wp_handle_upload_prefilter'.
	 * @since 4.0.0 Converted to a dynamic hook with `$action`.
	 *
	 * @param array $file {
	 *     Reference to a single element from `$_FILES`.
	 *
	 *     @type string $name     The original name of the file on the client machine.
	 *     @type string $type     The mime type of the file, if the browser provided this information.
	 *     @type string $tmp_name The temporary filename of the file in which the uploaded file was stored on the server.
	 *     @type int    $size     The size, in bytes, of the uploaded file.
	 *     @type int    $error    The error code associated with this file upload.
	 * }
	 */
	$file = apply_filters( "{$action}_prefilter", $file );

	/**
	 * Filters the override parameters for a file before it is uploaded to WordPress.
	 *
	 * The dynamic portion of the hook name, `$action`, refers to the post action.
	 *
	 * Possible hook names include:
	 *
	 *  - `wp_handle_sideload_overrides`
	 *  - `wp_handle_upload_overrides`
	 *
	 * @since 5.7.0
	 *
	 * @param array|false $overrides An array of override parameters for this file. Boolean false if none are
	 *                               provided. See {@see _wp_handle_upload()}.
	 * @param array       $file      {
	 *     Reference to a single element from `$_FILES`.
	 *
	 *     @type string $name     The original name of the file on the client machine.
	 *     @type string $type     The mime type of the file, if the browser provided this information.
	 *     @type string $tmp_name The temporary filename of the file in which the uploaded file was stored on the server.
	 *     @type int    $size     The size, in bytes, of the uploaded file.
	 *     @type int    $error    The error code associated with this file upload.
	 * }
	 */
	$overrides = apply_filters( "{$action}_overrides", $overrides, $file );

	// You may define your own function and pass the name in $overrides['upload_error_handler'].
	$upload_error_handler = 'wp_handle_upload_error';
	if ( isset( $overrides['upload_error_handler'] ) ) {
		$upload_error_handler = $overrides['upload_error_handler'];
	}

	// You may have had one or more 'wp_handle_upload_prefilter' functions error out the file. Handle that gracefully.
	if ( isset( $file['error'] ) && ! is_numeric( $file['error'] ) && $file['error'] ) {
		return call_user_func_array( $upload_error_handler, array( &$file, $file['error'] ) );
	}

	// Install user overrides. Did we mention that this voids your warranty?

	// You may define your own function and pass the name in $overrides['unique_filename_callback'].
	$unique_filename_callback = null;
	if ( isset( $overrides['unique_filename_callback'] ) ) {
		$unique_filename_callback = $overrides['unique_filename_callback'];
	}

	/*
	 * This may not have originally been intended to be overridable,
	 * but historically has been.
	 */
	if ( isset( $overrides['upload_error_strings'] ) ) {
		$upload_error_strings = $overrides['upload_error_strings'];
	} else {
		// Courtesy of php.net, the strings that describe the error indicated in $_FILES[{form field}]['error'].
		$upload_error_strings = array(
			false,
			sprintf(
				/* translators: 1: upload_max_filesize, 2: php.ini */
				__( 'The uploaded file exceeds the %1$s directive in %2$s.' ),
				'upload_max_filesize',
				'php.ini'
			),
			sprintf(
				/* translators: %s: MAX_FILE_SIZE */
				__( 'The uploaded file exceeds the %s directive that was specified in the HTML form.' ),
				'MAX_FILE_SIZE'
			),
			__( 'The uploaded file was only partially uploaded.' ),
			__( 'No file was uploaded.' ),
			'',
			__( 'Missing a temporary folder.' ),
			__( 'Failed to write file to disk.' ),
			__( 'File upload stopped by extension.' ),
		);
	}

	// All tests are on by default. Most can be turned off by $overrides[{test_name}] = false;
	$test_form = isset( $overrides['test_form'] ) ? $overrides['test_form'] : true;
	$test_size = isset( $overrides['test_size'] ) ? $overrides['test_size'] : true;

	// If you override this, you must provide $ext and $type!!
	$test_type = isset( $overrides['test_type'] ) ? $overrides['test_type'] : true;
	$mimes     = isset( $overrides['mimes'] ) ? $overrides['mimes'] : null;

	// A correct form post will pass this test.
	if ( $test_form && ( ! isset( $_POST['action'] ) || $_POST['action'] !== $action ) ) {
		return call_user_func_array( $upload_error_handler, array( &$file, __( 'Invalid form submission.' ) ) );
	}

	// A successful upload will pass this test. It makes no sense to override this one.
	if ( isset( $file['error'] ) && $file['error'] > 0 ) {
		return call_user_func_array( $upload_error_handler, array( &$file, $upload_error_strings[ $file['error'] ] ) );
	}

	// A properly uploaded file will pass this test. There should be no reason to override this one.
	$test_uploaded_file = 'wp_handle_upload' === $action ? is_uploaded_file( $file['tmp_name'] ) : @is_readable( $file['tmp_name'] );
	if ( ! $test_uploaded_file ) {
		return call_user_func_array( $upload_error_handler, array( &$file, __( 'Specified file failed upload test.' ) ) );
	}

	$test_file_size = 'wp_handle_upload' === $action ? $file['size'] : filesize( $file['tmp_name'] );
	// A non-empty file will pass this test.
	if ( $test_size && ! ( $test_file_size > 0 ) ) {
		if ( is_multisite() ) {
			$error_msg = __( 'File is empty. Please upload something more substantial.' );
		} else {
			$error_msg = sprintf(
				/* translators: 1: php.ini, 2: post_max_size, 3: upload_max_filesize */
				__( 'File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your %1$s file or by %2$s being defined as smaller than %3$s in %1$s.' ),
				'php.ini',
				'post_max_size',
				'upload_max_filesize'
			);
		}

		return call_user_func_array( $upload_error_handler, array( &$file, $error_msg ) );
	}

	// A correct MIME type will pass this test. Override $mimes or use the upload_mimes filter.
	if ( $test_type ) {
		$wp_filetype     = wp_check_filetype_and_ext( $file['tmp_name'], $file['name'], $mimes );
		$ext             = empty( $wp_filetype['ext'] ) ? '' : $wp_filetype['ext'];
		$type            = empty( $wp_filetype['type'] ) ? '' : $wp_filetype['type'];
		$proper_filename = empty( $wp_filetype['proper_filename'] ) ? '' : $wp_filetype['proper_filename'];

		// Check to see if wp_check_filetype_and_ext() determined the filename was incorrect.
		if ( $proper_filename ) {
			$file['name'] = $proper_filename;
		}

		if ( ( ! $type || ! $ext ) && ! current_user_can( 'unfiltered_upload' ) ) {
			return call_user_func_array( $upload_error_handler, array( &$file, __( 'Sorry, you are not allowed to upload this file type.' ) ) );
		}

		if ( ! $type ) {
			$type = $file['type'];
		}
	} else {
		$type = '';
	}

	/*
	 * A writable uploads dir will pass this test. Again, there's no point
	 * overriding this one.
	 */
	$uploads = wp_upload_dir( $time );
	if ( ! ( $uploads && false === $uploads['error'] ) ) {
		return call_user_func_array( $upload_error_handler, array( &$file, $uploads['error'] ) );
	}

	$filename = wp_unique_filename( $uploads['path'], $file['name'], $unique_filename_callback );

	// Move the file to the uploads dir.
	$new_file = $uploads['path'] . "/$filename";

	/**
	 * Filters whether to short-circuit moving the uploaded file after passing all checks.
	 *
	 * If a non-null value is returned from the filter, moving the file and any related
	 * error reporting will be completely skipped.
	 *
	 * @since 4.9.0
	 *
	 * @param mixed    $move_new_file If null (default) move the file after the upload.
	 * @param array    $file          {
	 *     Reference to a single element from `$_FILES`.
	 *
	 *     @type string $name     The original name of the file on the client machine.
	 *     @type string $type     The mime type of the file, if the browser provided this information.
	 *     @type string $tmp_name The temporary filename of the file in which the uploaded file was stored on the server.
	 *     @type int    $size     The size, in bytes, of the uploaded file.
	 *     @type int    $error    The error code associated with this file upload.
	 * }
	 * @param string   $new_file      Filename of the newly-uploaded file.
	 * @param string   $type          Mime type of the newly-uploaded file.
	 */
	$move_new_file = apply_filters( 'pre_move_uploaded_file', null, $file, $new_file, $type );

	if ( null === $move_new_file ) {
		if ( 'wp_handle_upload' === $action ) {
			$move_new_file = @move_uploaded_file( $file['tmp_name'], $new_file );
		} else {
			// Use copy and unlink because rename breaks streams.
			// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
			$move_new_file = @copy( $file['tmp_name'], $new_file );
			unlink( $file['tmp_name'] );
		}

		if ( false === $move_new_file ) {
			if ( str_starts_with( $uploads['basedir'], ABSPATH ) ) {
				$error_path = str_replace( ABSPATH, '', $uploads['basedir'] ) . $uploads['subdir'];
			} else {
				$error_path = basename( $uploads['basedir'] ) . $uploads['subdir'];
			}

			return $upload_error_handler(
				$file,
				sprintf(
					/* translators: %s: Destination file path. */
					__( 'The uploaded file could not be moved to %s.' ),
					$error_path
				)
			);
		}
	}

	// Set correct file permissions.
	$stat  = stat( dirname( $new_file ) );
	$perms = $stat['mode'] & 0000666;
	chmod( $new_file, $perms );

	// Compute the URL.
	$url = $uploads['url'] . "/$filename";

	if ( is_multisite() ) {
		clean_dirsize_cache( $new_file );
	}

	/**
	 * Filters the data array for the uploaded file.
	 *
	 * @since 2.1.0
	 *
	 * @param array  $upload {
	 *     Array of upload data.
	 *
	 *     @type string $file Filename of the newly-uploaded file.
	 *     @type string $url  URL of the newly-uploaded file.
	 *     @type string $type Mime type of the newly-uploaded file.
	 * }
	 * @param string $context The type of upload action. Values include 'upload' or 'sideload'.
	 */
	return apply_filters(
		'wp_handle_upload',
		array(
			'file' => $new_file,
			'url'  => $url,
			'type' => $type,
		),
		'wp_handle_sideload' === $action ? 'sideload' : 'upload'
	);
}

/**
 * Wrapper for _wp_handle_upload().
 *
 * Passes the {@see 'wp_handle_upload'} action.
 *
 * @since 2.0.0
 *
 * @see _wp_handle_upload()
 *
 * @param array       $file      Reference to a single element of `$_FILES`.
 *                               Call the function once for each uploaded file.
 *                               See _wp_handle_upload() for accepted values.
 * @param array|false $overrides Optional. An associative array of names => values
 *                               to override default variables. Default false.
 *                               See _wp_handle_upload() for accepted values.
 * @param string|null $time      Optional. Time formatted in 'yyyy/mm'. Default null.
 * @return array See _wp_handle_upload() for return value.
 */
function wp_handle_upload( &$file, $overrides = false, $time = null ) {
	/*
	 *  $_POST['action'] must be set and its value must equal $overrides['action']
	 *  or this:
	 */
	$action = 'wp_handle_upload';
	if ( isset( $overrides['action'] ) ) {
		$action = $overrides['action'];
	}

	return _wp_handle_upload( $file, $overrides, $time, $action );
}

/**
 * Wrapper for _wp_handle_upload().
 *
 * Passes the {@see 'wp_handle_sideload'} action.
 *
 * @since 2.6.0
 *
 * @see _wp_handle_upload()
 *
 * @param array       $file      Reference to a single element of `$_FILES`.
 *                               Call the function once for each uploaded file.
 *                               See _wp_handle_upload() for accepted values.
 * @param array|false $overrides Optional. An associative array of names => values
 *                               to override default variables. Default false.
 *                               See _wp_handle_upload() for accepted values.
 * @param string|null $time      Optional. Time formatted in 'yyyy/mm'. Default null.
 * @return array See _wp_handle_upload() for return value.
 */
function wp_handle_sideload( &$file, $overrides = false, $time = null ) {
	/*
	 *  $_POST['action'] must be set and its value must equal $overrides['action']
	 *  or this:
	 */
	$action = 'wp_handle_sideload';
	if ( isset( $overrides['action'] ) ) {
		$action = $overrides['action'];
	}

	return _wp_handle_upload( $file, $overrides, $time, $action );
}

/**
 * Downloads a URL to a local temporary file using the WordPress HTTP API.
 *
 * Please note that the calling function must delete or move the file.
 *
 * @since 2.5.0
 * @since 5.2.0 Signature Verification with SoftFail was added.
 * @since 5.9.0 Support for Content-Disposition filename was added.
 *
 * @param string $url                    The URL of the file to download.
 * @param int    $timeout                The timeout for the request to download the file.
 *                                       Default 300 seconds.
 * @param bool   $signature_verification Whether to perform Signature Verification.
 *                                       Default false.
 * @return string|WP_Error Filename on success, WP_Error on failure.
 */
function download_url( $url, $timeout = 300, $signature_verification = false ) {
	// WARNING: The file is not automatically deleted, the script must delete or move the file.
	if ( ! $url ) {
		return new WP_Error( 'http_no_url', __( 'No URL Provided.' ) );
	}

	$url_path     = parse_url( $url, PHP_URL_PATH );
	$url_filename = '';
	if ( is_string( $url_path ) && '' !== $url_path ) {
		$url_filename = basename( $url_path );
	}

	$tmpfname = wp_tempnam( $url_filename );
	if ( ! $tmpfname ) {
		return new WP_Error( 'http_no_file', __( 'Could not create temporary file.' ) );
	}

	$response = wp_safe_remote_get(
		$url,
		array(
			'timeout'  => $timeout,
			'stream'   => true,
			'filename' => $tmpfname,
		)
	);

	if ( is_wp_error( $response ) ) {
		unlink( $tmpfname );
		return $response;
	}

	$response_code = wp_remote_retrieve_response_code( $response );

	if ( 200 !== $response_code ) {
		$data = array(
			'code' => $response_code,
		);

		// Retrieve a sample of the response body for debugging purposes.
		$tmpf = fopen( $tmpfname, 'rb' );

		if ( $tmpf ) {
			/**
			 * Filters the maximum error response body size in `download_url()`.
			 *
			 * @since 5.1.0
			 *
			 * @see download_url()
			 *
			 * @param int $size The maximum error response body size. Default 1 KB.
			 */
			$response_size = apply_filters( 'download_url_error_max_body_size', KB_IN_BYTES );

			$data['body'] = fread( $tmpf, $response_size );
			fclose( $tmpf );
		}

		unlink( $tmpfname );

		return new WP_Error( 'http_404', trim( wp_remote_retrieve_response_message( $response ) ), $data );
	}

	$content_disposition = wp_remote_retrieve_header( $response, 'Content-Disposition' );

	if ( $content_disposition ) {
		$content_disposition = strtolower( $content_disposition );

		if ( str_starts_with( $content_disposition, 'attachment; filename=' ) ) {
			$tmpfname_disposition = sanitize_file_name( substr( $content_disposition, 21 ) );
		} else {
			$tmpfname_disposition = '';
		}

		// Potential file name must be valid string.
		if ( $tmpfname_disposition && is_string( $tmpfname_disposition )
			&& ( 0 === validate_file( $tmpfname_disposition ) )
		) {
			$tmpfname_disposition = dirname( $tmpfname ) . '/' . $tmpfname_disposition;

			if ( rename( $tmpfname, $tmpfname_disposition ) ) {
				$tmpfname = $tmpfname_disposition;
			}

			if ( ( $tmpfname !== $tmpfname_disposition ) && file_exists( $tmpfname_disposition ) ) {
				unlink( $tmpfname_disposition );
			}
		}
	}

	$mime_type = wp_remote_retrieve_header( $response, 'content-type' );
	if ( $mime_type && 'tmp' === pathinfo( $tmpfname, PATHINFO_EXTENSION ) ) {
		$valid_mime_types = array_flip( get_allowed_mime_types() );
		if ( ! empty( $valid_mime_types[ $mime_type ] ) ) {
			$extensions     = explode( '|', $valid_mime_types[ $mime_type ] );
			$new_image_name = substr( $tmpfname, 0, -4 ) . ".{$extensions[0]}";
			if ( 0 === validate_file( $new_image_name ) ) {
				if ( rename( $tmpfname, $new_image_name ) ) {
					$tmpfname = $new_image_name;
				}

				if ( ( $tmpfname !== $new_image_name ) && file_exists( $new_image_name ) ) {
					unlink( $new_image_name );
				}
			}
		}
	}

	$content_md5 = wp_remote_retrieve_header( $response, 'Content-MD5' );

	if ( $content_md5 ) {
		$md5_check = verify_file_md5( $tmpfname, $content_md5 );

		if ( is_wp_error( $md5_check ) ) {
			unlink( $tmpfname );
			return $md5_check;
		}
	}

	// If the caller expects signature verification to occur, check to see if this URL supports it.
	if ( $signature_verification ) {
		/**
		 * Filters the list of hosts which should have Signature Verification attempted on.
		 *
		 * @since 5.2.0
		 *
		 * @param string[] $hostnames List of hostnames.
		 */
		$signed_hostnames = apply_filters( 'wp_signature_hosts', array( 'wordpress.org', 'downloads.wordpress.org', 's.w.org' ) );

		$signature_verification = in_array( parse_url( $url, PHP_URL_HOST ), $signed_hostnames, true );
	}

	// Perform signature validation if supported.
	if ( $signature_verification ) {
		$signature = wp_remote_retrieve_header( $response, 'X-Content-Signature' );

		if ( ! $signature ) {
			/*
			 * Retrieve signatures from a file if the header wasn't included.
			 * WordPress.org stores signatures at $package_url.sig.
			 */

			$signature_url = false;

			if ( is_string( $url_path ) && ( str_ends_with( $url_path, '.zip' ) || str_ends_with( $url_path, '.tar.gz' ) ) ) {
				$signature_url = str_replace( $url_path, $url_path . '.sig', $url );
			}

			/**
			 * Filters the URL where the signature for a file is located.
			 *
			 * @since 5.2.0
			 *
			 * @param false|string $signature_url The URL where signatures can be found for a file, or false if none are known.
			 * @param string $url                 The URL being verified.
			 */
			$signature_url = apply_filters( 'wp_signature_url', $signature_url, $url );

			if ( $signature_url ) {
				$signature_request = wp_safe_remote_get(
					$signature_url,
					array(
						'limit_response_size' => 10 * KB_IN_BYTES, // 10KB should be large enough for quite a few signatures.
					)
				);

				if ( ! is_wp_error( $signature_request ) && 200 === wp_remote_retrieve_response_code( $signature_request ) ) {
					$signature = explode( "\n", wp_remote_retrieve_body( $signature_request ) );
				}
			}
		}

		// Perform the checks.
		$signature_verification = verify_file_signature( $tmpfname, $signature, $url_filename );
	}

	if ( is_wp_error( $signature_verification ) ) {
		if (
			/**
			 * Filters whether Signature Verification failures should be allowed to soft fail.
			 *
			 * WARNING: This may be removed from a future release.
			 *
			 * @since 5.2.0
			 *
			 * @param bool   $signature_softfail If a softfail is allowed.
			 * @param string $url                The url being accessed.
			 */
			apply_filters( 'wp_signature_softfail', true, $url )
		) {
			$signature_verification->add_data( $tmpfname, 'softfail-filename' );
		} else {
			// Hard-fail.
			unlink( $tmpfname );
		}

		return $signature_verification;
	}

	return $tmpfname;
}

/**
 * Calculates and compares the MD5 of a file to its expected value.
 *
 * @since 3.7.0
 *
 * @param string $filename     The filename to check the MD5 of.
 * @param string $expected_md5 The expected MD5 of the file, either a base64-encoded raw md5,
 *                             or a hex-encoded md5.
 * @return bool|WP_Error True on success, false when the MD5 format is unknown/unexpected,
 *                       WP_Error on failure.
 */
function verify_file_md5( $filename, $expected_md5 ) {
	if ( 32 === strlen( $expected_md5 ) ) {
		$expected_raw_md5 = pack( 'H*', $expected_md5 );
	} elseif ( 24 === strlen( $expected_md5 ) ) {
		$expected_raw_md5 = base64_decode( $expected_md5 );
	} else {
		return false; // Unknown format.
	}

	$file_md5 = md5_file( $filename, true );

	if ( $file_md5 === $expected_raw_md5 ) {
		return true;
	}

	return new WP_Error(
		'md5_mismatch',
		sprintf(
			/* translators: 1: File checksum, 2: Expected checksum value. */
			__( 'The checksum of the file (%1$s) does not match the expected checksum value (%2$s).' ),
			bin2hex( $file_md5 ),
			bin2hex( $expected_raw_md5 )
		)
	);
}

/**
 * Verifies the contents of a file against its ED25519 signature.
 *
 * @since 5.2.0
 *
 * @param string       $filename            The file to validate.
 * @param string|array $signatures          A Signature provided for the file.
 * @param string|false $filename_for_errors Optional. A friendly filename for errors.
 * @return bool|WP_Error True on success, false if verification not attempted,
 *                       or WP_Error describing an error condition.
 */
function verify_file_signature( $filename, $signatures, $filename_for_errors = false ) {
	if ( ! $filename_for_errors ) {
		$filename_for_errors = wp_basename( $filename );
	}

	// Check we can process signatures.
	if ( ! function_exists( 'sodium_crypto_sign_verify_detached' ) || ! in_array( 'sha384', array_map( 'strtolower', hash_algos() ), true ) ) {
		return new WP_Error(
			'signature_verification_unsupported',
			sprintf(
				/* translators: %s: The filename of the package. */
				__( 'The authenticity of %s could not be verified as signature verification is unavailable on this system.' ),
				'<span class="code">' . esc_html( $filename_for_errors ) . '</span>'
			),
			( ! function_exists( 'sodium_crypto_sign_verify_detached' ) ? 'sodium_crypto_sign_verify_detached' : 'sha384' )
		);
	}

	// Verify runtime speed of Sodium_Compat is acceptable.
	if ( ! extension_loaded( 'sodium' ) && ! ParagonIE_Sodium_Compat::polyfill_is_fast() ) {
		$sodium_compat_is_fast = false;

		// Allow for an old version of Sodium_Compat being loaded before the bundled WordPress one.
		if ( method_exists( 'ParagonIE_Sodium_Compat', 'runtime_speed_test' ) ) {
			/*
			 * Run `ParagonIE_Sodium_Compat::runtime_speed_test()` in optimized integer mode,
			 * as that's what WordPress utilizes during signing verifications.
			 */
			// phpcs:disable WordPress.NamingConventions.ValidVariableName
			$old_fastMult                      = ParagonIE_Sodium_Compat::$fastMult;
			ParagonIE_Sodium_Compat::$fastMult = true;
			$sodium_compat_is_fast             = ParagonIE_Sodium_Compat::runtime_speed_test( 100, 10 );
			ParagonIE_Sodium_Compat::$fastMult = $old_fastMult;
			// phpcs:enable
		}

		/*
		 * This cannot be performed in a reasonable amount of time.
		 * https://github.com/paragonie/sodium_compat#help-sodium_compat-is-slow-how-can-i-make-it-fast
		 */
		if ( ! $sodium_compat_is_fast ) {
			return new WP_Error(
				'signature_verification_unsupported',
				sprintf(
					/* translators: %s: The filename of the package. */
					__( 'The authenticity of %s could not be verified as signature verification is unavailable on this system.' ),
					'<span class="code">' . esc_html( $filename_for_errors ) . '</span>'
				),
				array(
					'php'                => PHP_VERSION,
					'sodium'             => defined( 'SODIUM_LIBRARY_VERSION' ) ? SODIUM_LIBRARY_VERSION : ( defined( 'ParagonIE_Sodium_Compat::VERSION_STRING' ) ? ParagonIE_Sodium_Compat::VERSION_STRING : false ),
					'polyfill_is_fast'   => false,
					'max_execution_time' => ini_get( 'max_execution_time' ),
				)
			);
		}
	}

	if ( ! $signatures ) {
		return new WP_Error(
			'signature_verification_no_signature',
			sprintf(
				/* translators: %s: The filename of the package. */
				__( 'The authenticity of %s could not be verified as no signature was found.' ),
				'<span class="code">' . esc_html( $filename_for_errors ) . '</span>'
			),
			array(
				'filename' => $filename_for_errors,
			)
		);
	}

	$trusted_keys = wp_trusted_keys();
	$file_hash    = hash_file( 'sha384', $filename, true );

	mbstring_binary_safe_encoding();

	$skipped_key       = 0;
	$skipped_signature = 0;

	foreach ( (array) $signatures as $signature ) {
		$signature_raw = base64_decode( $signature );

		// Ensure only valid-length signatures are considered.
		if ( SODIUM_CRYPTO_SIGN_BYTES !== strlen( $signature_raw ) ) {
			++$skipped_signature;
			continue;
		}

		foreach ( (array) $trusted_keys as $key ) {
			$key_raw = base64_decode( $key );

			// Only pass valid public keys through.
			if ( SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES !== strlen( $key_raw ) ) {
				++$skipped_key;
				continue;
			}

			if ( sodium_crypto_sign_verify_detached( $signature_raw, $file_hash, $key_raw ) ) {
				reset_mbstring_encoding();
				return true;
			}
		}
	}

	reset_mbstring_encoding();

	return new WP_Error(
		'signature_verification_failed',
		sprintf(
			/* translators: %s: The filename of the package. */
			__( 'The authenticity of %s could not be verified.' ),
			'<span class="code">' . esc_html( $filename_for_errors ) . '</span>'
		),
		// Error data helpful for debugging:
		array(
			'filename'    => $filename_for_errors,
			'keys'        => $trusted_keys,
			'signatures'  => $signatures,
			'hash'        => bin2hex( $file_hash ),
			'skipped_key' => $skipped_key,
			'skipped_sig' => $skipped_signature,
			'php'         => PHP_VERSION,
			'sodium'      => defined( 'SODIUM_LIBRARY_VERSION' ) ? SODIUM_LIBRARY_VERSION : ( defined( 'ParagonIE_Sodium_Compat::VERSION_STRING' ) ? ParagonIE_Sodium_Compat::VERSION_STRING : false ),
		)
	);
}

/**
 * Retrieves the list of signing keys trusted by WordPress.
 *
 * @since 5.2.0
 *
 * @return string[] Array of base64-encoded signing keys.
 */
function wp_trusted_keys() {
	$trusted_keys = array();

	if ( time() < 1617235200 ) {
		// WordPress.org Key #1 - This key is only valid before April 1st, 2021.
		$trusted_keys[] = 'fRPyrxb/MvVLbdsYi+OOEv4xc+Eqpsj+kkAS6gNOkI0=';
	}

	// TODO: Add key #2 with longer expiration.

	/**
	 * Filters the valid signing keys used to verify the contents of files.
	 *
	 * @since 5.2.0
	 *
	 * @param string[] $trusted_keys The trusted keys that may sign packages.
	 */
	return apply_filters( 'wp_trusted_keys', $trusted_keys );
}

/**
 * Determines whether the given file is a valid ZIP file.
 *
 * This function does not test to ensure that a file exists. Non-existent files
 * are not valid ZIPs, so those will also return false.
 *
 * @since 6.4.4
 *
 * @param string $file Full path to the ZIP file.
 * @return bool Whether the file is a valid ZIP file.
 */
function wp_zip_file_is_valid( $file ) {
	/** This filter is documented in wp-admin/includes/file.php */
	if ( class_exists( 'ZipArchive', false ) && apply_filters( 'unzip_file_use_ziparchive', true ) ) {
		$archive          = new ZipArchive();
		$archive_is_valid = $archive->open( $file, ZipArchive::CHECKCONS );
		if ( true === $archive_is_valid ) {
			$archive->close();
			return true;
		}
	}

	// Fall through to PclZip if ZipArchive is not available, or encountered an error opening the file.
	require_once ABSPATH . 'wp-admin/includes/class-pclzip.php';

	$archive          = new PclZip( $file );
	$archive_is_valid = is_array( $archive->properties() );

	return $archive_is_valid;
}

/**
 * Unzips a specified ZIP file to a location on the filesystem via the WordPress
 * Filesystem Abstraction.
 *
 * Assumes that WP_Filesystem() has already been called and set up. Does not extract
 * a root-level __MACOSX directory, if present.
 *
 * Attempts to increase the PHP memory limit to 256M before uncompressing. However,
 * the most memory required shouldn't be much larger than the archive itself.
 *
 * @since 2.5.0
 *
 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
 *
 * @param string $file Full path and filename of ZIP archive.
 * @param string $to   Full path on the filesystem to extract archive to.
 * @return true|WP_Error True on success, WP_Error on failure.
 */
function unzip_file( $file, $to ) {
	global $wp_filesystem;

	if ( ! $wp_filesystem || ! is_object( $wp_filesystem ) ) {
		return new WP_Error( 'fs_unavailable', __( 'Could not access filesystem.' ) );
	}

	// Unzip can use a lot of memory, but not this much hopefully.
	wp_raise_memory_limit( 'admin' );

	$needed_dirs = array();
	$to          = trailingslashit( $to );

	// Determine any parent directories needed (of the upgrade directory).
	if ( ! $wp_filesystem->is_dir( $to ) ) { // Only do parents if no children exist.
		$path = preg_split( '![/\\\]!', untrailingslashit( $to ) );
		for ( $i = count( $path ); $i >= 0; $i-- ) {
			if ( empty( $path[ $i ] ) ) {
				continue;
			}

			$dir = implode( '/', array_slice( $path, 0, $i + 1 ) );
			if ( preg_match( '!^[a-z]:$!i', $dir ) ) { // Skip it if it looks like a Windows Drive letter.
				continue;
			}

			if ( ! $wp_filesystem->is_dir( $dir ) ) {
				$needed_dirs[] = $dir;
			} else {
				break; // A folder exists, therefore we don't need to check the levels below this.
			}
		}
	}

	/**
	 * Filters whether to use ZipArchive to unzip archives.
	 *
	 * @since 3.0.0
	 *
	 * @param bool $ziparchive Whether to use ZipArchive. Default true.
	 */
	if ( class_exists( 'ZipArchive', false ) && apply_filters( 'unzip_file_use_ziparchive', true ) ) {
		$result = _unzip_file_ziparchive( $file, $to, $needed_dirs );
		if ( true === $result ) {
			return $result;
		} elseif ( is_wp_error( $result ) ) {
			if ( 'incompatible_archive' !== $result->get_error_code() ) {
				return $result;
			}
		}
	}
	// Fall through to PclZip if ZipArchive is not available, or encountered an error opening the file.
	return _unzip_file_pclzip( $file, $to, $needed_dirs );
}

/**
 * Attempts to unzip an archive using the ZipArchive class.
 *
 * This function should not be called directly, use `unzip_file()` instead.
 *
 * Assumes that WP_Filesystem() has already been called and set up.
 *
 * @since 3.0.0
 * @access private
 *
 * @see unzip_file()
 *
 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
 *
 * @param string   $file        Full path and filename of ZIP archive.
 * @param string   $to          Full path on the filesystem to extract archive to.
 * @param string[] $needed_dirs A partial list of required folders needed to be created.
 * @return true|WP_Error True on success, WP_Error on failure.
 */
function _unzip_file_ziparchive( $file, $to, $needed_dirs = array() ) {
	global $wp_filesystem;

	$z = new ZipArchive();

	$zopen = $z->open( $file, ZIPARCHIVE::CHECKCONS );

	if ( true !== $zopen ) {
		return new WP_Error( 'incompatible_archive', __( 'Incompatible Archive.' ), array( 'ziparchive_error' => $zopen ) );
	}

	$uncompressed_size = 0;

	for ( $i = 0; $i < $z->numFiles; $i++ ) {
		$info = $z->statIndex( $i );

		if ( ! $info ) {
			$z->close();
			return new WP_Error( 'stat_failed_ziparchive', __( 'Could not retrieve file from archive.' ) );
		}

		if ( str_starts_with( $info['name'], '__MACOSX/' ) ) { // Skip the OS X-created __MACOSX directory.
			continue;
		}

		// Don't extract invalid files:
		if ( 0 !== validate_file( $info['name'] ) ) {
			continue;
		}

		$uncompressed_size += $info['size'];

		$dirname = dirname( $info['name'] );

		if ( str_ends_with( $info['name'], '/' ) ) {
			// Directory.
			$needed_dirs[] = $to . untrailingslashit( $info['name'] );
		} elseif ( '.' !== $dirname ) {
			// Path to a file.
			$needed_dirs[] = $to . untrailingslashit( $dirname );
		}
	}

	// Enough space to unzip the file and copy its contents, with a 10% buffer.
	$required_space = $uncompressed_size * 2.1;

	/*
	 * disk_free_space() could return false. Assume that any falsey value is an error.
	 * A disk that has zero free bytes has bigger problems.
	 * Require we have enough space to unzip the file and copy its contents, with a 10% buffer.
	 */
	if ( wp_doing_cron() ) {
		$available_space = function_exists( 'disk_free_space' ) ? @disk_free_space( WP_CONTENT_DIR ) : false;

		if ( $available_space && ( $required_space > $available_space ) ) {
			$z->close();
			return new WP_Error(
				'disk_full_unzip_file',
				__( 'Could not copy files. You may have run out of disk space.' ),
				compact( 'uncompressed_size', 'available_space' )
			);
		}
	}

	$needed_dirs = array_unique( $needed_dirs );

	foreach ( $needed_dirs as $dir ) {
		// Check the parent folders of the folders all exist within the creation array.
		if ( untrailingslashit( $to ) === $dir ) { // Skip over the working directory, we know this exists (or will exist).
			continue;
		}

		if ( ! str_contains( $dir, $to ) ) { // If the directory is not within the working directory, skip it.
			continue;
		}

		$parent_folder = dirname( $dir );

		while ( ! empty( $parent_folder )
			&& untrailingslashit( $to ) !== $parent_folder
			&& ! in_array( $parent_folder, $needed_dirs, true )
		) {
			$needed_dirs[] = $parent_folder;
			$parent_folder = dirname( $parent_folder );
		}
	}

	asort( $needed_dirs );

	// Create those directories if need be:
	foreach ( $needed_dirs as $_dir ) {
		// Only check to see if the Dir exists upon creation failure. Less I/O this way.
		if ( ! $wp_filesystem->mkdir( $_dir, FS_CHMOD_DIR ) && ! $wp_filesystem->is_dir( $_dir ) ) {
			$z->close();
			return new WP_Error( 'mkdir_failed_ziparchive', __( 'Could not create directory.' ), $_dir );
		}
	}

	/**
	 * Filters archive unzipping to override with a custom process.
	 *
	 * @since 6.4.0
	 *
	 * @param null|true|WP_Error $result         The result of the override. True on success, otherwise WP Error. Default null.
	 * @param string             $file           Full path and filename of ZIP archive.
	 * @param string             $to             Full path on the filesystem to extract archive to.
	 * @param string[]           $needed_dirs    A full list of required folders that need to be created.
	 * @param float              $required_space The space required to unzip the file and copy its contents, with a 10% buffer.
	 */
	$pre = apply_filters( 'pre_unzip_file', null, $file, $to, $needed_dirs, $required_space );

	if ( null !== $pre ) {
		// Ensure the ZIP file archive has been closed.
		$z->close();

		return $pre;
	}

	for ( $i = 0; $i < $z->numFiles; $i++ ) {
		$info = $z->statIndex( $i );

		if ( ! $info ) {
			$z->close();
			return new WP_Error( 'stat_failed_ziparchive', __( 'Could not retrieve file from archive.' ) );
		}

		if ( str_ends_with( $info['name'], '/' ) ) { // Directory.
			continue;
		}

		if ( str_starts_with( $info['name'], '__MACOSX/' ) ) { // Don't extract the OS X-created __MACOSX directory files.
			continue;
		}

		// Don't extract invalid files:
		if ( 0 !== validate_file( $info['name'] ) ) {
			continue;
		}

		$contents = $z->getFromIndex( $i );

		if ( false === $contents ) {
			$z->close();
			return new WP_Error( 'extract_failed_ziparchive', __( 'Could not extract file from archive.' ), $info['name'] );
		}

		if ( ! $wp_filesystem->put_contents( $to . $info['name'], $contents, FS_CHMOD_FILE ) ) {
			$z->close();
			return new WP_Error( 'copy_failed_ziparchive', __( 'Could not copy file.' ), $info['name'] );
		}
	}

	$z->close();

	/**
	 * Filters the result of unzipping an archive.
	 *
	 * @since 6.4.0
	 *
	 * @param true|WP_Error $result         The result of unzipping the archive. True on success, otherwise WP_Error. Default true.
	 * @param string        $file           Full path and filename of ZIP archive.
	 * @param string        $to             Full path on the filesystem the archive was extracted to.
	 * @param string[]      $needed_dirs    A full list of required folders that were created.
	 * @param float         $required_space The space required to unzip the file and copy its contents, with a 10% buffer.
	 */
	$result = apply_filters( 'unzip_file', true, $file, $to, $needed_dirs, $required_space );

	unset( $needed_dirs );

	return $result;
}

/**
 * Attempts to unzip an archive using the PclZip library.
 *
 * This function should not be called directly, use `unzip_file()` instead.
 *
 * Assumes that WP_Filesystem() has already been called and set up.
 *
 * @since 3.0.0
 * @access private
 *
 * @see unzip_file()
 *
 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
 *
 * @param string   $file        Full path and filename of ZIP archive.
 * @param string   $to          Full path on the filesystem to extract archive to.
 * @param string[] $needed_dirs A partial list of required folders needed to be created.
 * @return true|WP_Error True on success, WP_Error on failure.
 */
function _unzip_file_pclzip( $file, $to, $needed_dirs = array() ) {
	global $wp_filesystem;

	mbstring_binary_safe_encoding();

	require_once ABSPATH . 'wp-admin/includes/class-pclzip.php';

	$archive = new PclZip( $file );

	$archive_files = $archive->extract( PCLZIP_OPT_EXTRACT_AS_STRING );

	reset_mbstring_encoding();

	// Is the archive valid?
	if ( ! is_array( $archive_files ) ) {
		return new WP_Error( 'incompatible_archive', __( 'Incompatible Archive.' ), $archive->errorInfo( true ) );
	}

	if ( 0 === count( $archive_files ) ) {
		return new WP_Error( 'empty_archive_pclzip', __( 'Empty archive.' ) );
	}

	$uncompressed_size = 0;

	// Determine any children directories needed (From within the archive).
	foreach ( $archive_files as $file ) {
		if ( str_starts_with( $file['filename'], '__MACOSX/' ) ) { // Skip the OS X-created __MACOSX directory.
			continue;
		}

		$uncompressed_size += $file['size'];

		$needed_dirs[] = $to . untrailingslashit( $file['folder'] ? $file['filename'] : dirname( $file['filename'] ) );
	}

	// Enough space to unzip the file and copy its contents, with a 10% buffer.
	$required_space = $uncompressed_size * 2.1;

	/*
	 * disk_free_space() could return false. Assume that any falsey value is an error.
	 * A disk that has zero free bytes has bigger problems.
	 * Require we have enough space to unzip the file and copy its contents, with a 10% buffer.
	 */
	if ( wp_doing_cron() ) {
		$available_space = function_exists( 'disk_free_space' ) ? @disk_free_space( WP_CONTENT_DIR ) : false;

		if ( $available_space && ( $required_space > $available_space ) ) {
			return new WP_Error(
				'disk_full_unzip_file',
				__( 'Could not copy files. You may have run out of disk space.' ),
				compact( 'uncompressed_size', 'available_space' )
			);
		}
	}

	$needed_dirs = array_unique( $needed_dirs );

	foreach ( $needed_dirs as $dir ) {
		// Check the parent folders of the folders all exist within the creation array.
		if ( untrailingslashit( $to ) === $dir ) { // Skip over the working directory, we know this exists (or will exist).
			continue;
		}

		if ( ! str_contains( $dir, $to ) ) { // If the directory is not within the working directory, skip it.
			continue;
		}

		$parent_folder = dirname( $dir );

		while ( ! empty( $parent_folder )
			&& untrailingslashit( $to ) !== $parent_folder
			&& ! in_array( $parent_folder, $needed_dirs, true )
		) {
			$needed_dirs[] = $parent_folder;
			$parent_folder = dirname( $parent_folder );
		}
	}

	asort( $needed_dirs );

	// Create those directories if need be:
	foreach ( $needed_dirs as $_dir ) {
		// Only check to see if the dir exists upon creation failure. Less I/O this way.
		if ( ! $wp_filesystem->mkdir( $_dir, FS_CHMOD_DIR ) && ! $wp_filesystem->is_dir( $_dir ) ) {
			return new WP_Error( 'mkdir_failed_pclzip', __( 'Could not create directory.' ), $_dir );
		}
	}

	/** This filter is documented in src/wp-admin/includes/file.php */
	$pre = apply_filters( 'pre_unzip_file', null, $file, $to, $needed_dirs, $required_space );

	if ( null !== $pre ) {
		return $pre;
	}

	// Extract the files from the zip.
	foreach ( $archive_files as $file ) {
		if ( $file['folder'] ) {
			continue;
		}

		if ( str_starts_with( $file['filename'], '__MACOSX/' ) ) { // Don't extract the OS X-created __MACOSX directory files.
			continue;
		}

		// Don't extract invalid files:
		if ( 0 !== validate_file( $file['filename'] ) ) {
			continue;
		}

		if ( ! $wp_filesystem->put_contents( $to . $file['filename'], $file['content'], FS_CHMOD_FILE ) ) {
			return new WP_Error( 'copy_failed_pclzip', __( 'Could not copy file.' ), $file['filename'] );
		}
	}

	/** This action is documented in src/wp-admin/includes/file.php */
	$result = apply_filters( 'unzip_file', true, $file, $to, $needed_dirs, $required_space );

	unset( $needed_dirs );

	return $result;
}

/**
 * Copies a directory from one location to another via the WordPress Filesystem
 * Abstraction.
 *
 * Assumes that WP_Filesystem() has already been called and setup.
 *
 * @since 2.5.0
 *
 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
 *
 * @param string   $from      Source directory.
 * @param string   $to        Destination directory.
 * @param string[] $skip_list An array of files/folders to skip copying.
 * @return true|WP_Error True on success, WP_Error on failure.
 */
function copy_dir( $from, $to, $skip_list = array() ) {
	global $wp_filesystem;

	$dirlist = $wp_filesystem->dirlist( $from );

	if ( false === $dirlist ) {
		return new WP_Error( 'dirlist_failed_copy_dir', __( 'Directory listing failed.' ), basename( $from ) );
	}

	$from = trailingslashit( $from );
	$to   = trailingslashit( $to );

	if ( ! $wp_filesystem->exists( $to ) && ! $wp_filesystem->mkdir( $to ) ) {
		return new WP_Error(
			'mkdir_destination_failed_copy_dir',
			__( 'Could not create the destination directory.' ),
			basename( $to )
		);
	}

	foreach ( (array) $dirlist as $filename => $fileinfo ) {
		if ( in_array( $filename, $skip_list, true ) ) {
			continue;
		}

		if ( 'f' === $fileinfo['type'] ) {
			if ( ! $wp_filesystem->copy( $from . $filename, $to . $filename, true, FS_CHMOD_FILE ) ) {
				// If copy failed, chmod file to 0644 and try again.
				$wp_filesystem->chmod( $to . $filename, FS_CHMOD_FILE );

				if ( ! $wp_filesystem->copy( $from . $filename, $to . $filename, true, FS_CHMOD_FILE ) ) {
					return new WP_Error( 'copy_failed_copy_dir', __( 'Could not copy file.' ), $to . $filename );
				}
			}

			wp_opcache_invalidate( $to . $filename );
		} elseif ( 'd' === $fileinfo['type'] ) {
			if ( ! $wp_filesystem->is_dir( $to . $filename ) ) {
				if ( ! $wp_filesystem->mkdir( $to . $filename, FS_CHMOD_DIR ) ) {
					return new WP_Error( 'mkdir_failed_copy_dir', __( 'Could not create directory.' ), $to . $filename );
				}
			}

			// Generate the $sub_skip_list for the subdirectory as a sub-set of the existing $skip_list.
			$sub_skip_list = array();

			foreach ( $skip_list as $skip_item ) {
				if ( str_starts_with( $skip_item, $filename . '/' ) ) {
					$sub_skip_list[] = preg_replace( '!^' . preg_quote( $filename, '!' ) . '/!i', '', $skip_item );
				}
			}

			$result = copy_dir( $from . $filename, $to . $filename, $sub_skip_list );

			if ( is_wp_error( $result ) ) {
				return $result;
			}
		}
	}

	return true;
}

/**
 * Moves a directory from one location to another.
 *
 * Recursively invalidates OPcache on success.
 *
 * If the renaming failed, falls back to copy_dir().
 *
 * Assumes that WP_Filesystem() has already been called and setup.
 *
 * This function is not designed to merge directories, copy_dir() should be used instead.
 *
 * @since 6.2.0
 *
 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
 *
 * @param string $from      Source directory.
 * @param string $to        Destination directory.
 * @param bool   $overwrite Optional. Whether to overwrite the destination directory if it exists.
 *                          Default false.
 * @return true|WP_Error True on success, WP_Error on failure.
 */
function move_dir( $from, $to, $overwrite = false ) {
	global $wp_filesystem;

	if ( trailingslashit( strtolower( $from ) ) === trailingslashit( strtolower( $to ) ) ) {
		return new WP_Error( 'source_destination_same_move_dir', __( 'The source and destination are the same.' ) );
	}

	if ( $wp_filesystem->exists( $to ) ) {
		if ( ! $overwrite ) {
			return new WP_Error( 'destination_already_exists_move_dir', __( 'The destination folder already exists.' ), $to );
		} elseif ( ! $wp_filesystem->delete( $to, true ) ) {
			// Can't overwrite if the destination couldn't be deleted.
			return new WP_Error( 'destination_not_deleted_move_dir', __( 'The destination directory already exists and could not be removed.' ) );
		}
	}

	if ( $wp_filesystem->move( $from, $to ) ) {
		/*
		 * When using an environment with shared folders,
		 * there is a delay in updating the filesystem's cache.
		 *
		 * This is a known issue in environments with a VirtualBox provider.
		 *
		 * A 200ms delay gives time for the filesystem to update its cache,
		 * prevents "Operation not permitted", and "No such file or directory" warnings.
		 *
		 * This delay is used in other projects, including Composer.
		 * @link https://github.com/composer/composer/blob/2.5.1/src/Composer/Util/Platform.php#L228-L233
		 */
		usleep( 200000 );
		wp_opcache_invalidate_directory( $to );

		return true;
	}

	// Fall back to a recursive copy.
	if ( ! $wp_filesystem->is_dir( $to ) ) {
		if ( ! $wp_filesystem->mkdir( $to, FS_CHMOD_DIR ) ) {
			return new WP_Error( 'mkdir_failed_move_dir', __( 'Could not create directory.' ), $to );
		}
	}

	$result = copy_dir( $from, $to, array( basename( $to ) ) );

	// Clear the source directory.
	if ( true === $result ) {
		$wp_filesystem->delete( $from, true );
	}

	return $result;
}

/**
 * Initializes and connects the WordPress Filesystem Abstraction classes.
 *
 * This function will include the chosen transport and attempt connecting.
 *
 * Plugins may add extra transports, And force WordPress to use them by returning
 * the filename via the {@see 'filesystem_method_file'} filter.
 *
 * @since 2.5.0
 *
 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
 *
 * @param array|false  $args                         Optional. Connection args, These are passed
 *                                                   directly to the `WP_Filesystem_*()` classes.
 *                                                   Default false.
 * @param string|false $context                      Optional. Context for get_filesystem_method().
 *                                                   Default false.
 * @param bool         $allow_relaxed_file_ownership Optional. Whether to allow Group/World writable.
 *                                                   Default false.
 * @return bool|null True on success, false on failure,
 *                   null if the filesystem method class file does not exist.
 */
function WP_Filesystem( $args = false, $context = false, $allow_relaxed_file_ownership = false ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionNameInvalid
	global $wp_filesystem;

	require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php';

	$method = get_filesystem_method( $args, $context, $allow_relaxed_file_ownership );

	if ( ! $method ) {
		return false;
	}

	if ( ! class_exists( "WP_Filesystem_$method" ) ) {

		/**
		 * Filters the path for a specific filesystem method class file.
		 *
		 * @since 2.6.0
		 *
		 * @see get_filesystem_method()
		 *
		 * @param string $path   Path to the specific filesystem method class file.
		 * @param string $method The filesystem method to use.
		 */
		$abstraction_file = apply_filters( 'filesystem_method_file', ABSPATH . 'wp-admin/includes/class-wp-filesystem-' . $method . '.php', $method );

		if ( ! file_exists( $abstraction_file ) ) {
			return;
		}

		require_once $abstraction_file;
	}
	$method = "WP_Filesystem_$method";

	$wp_filesystem = new $method( $args );

	/*
	 * Define the timeouts for the connections. Only available after the constructor is called
	 * to allow for per-transport overriding of the default.
	 */
	if ( ! defined( 'FS_CONNECT_TIMEOUT' ) ) {
		define( 'FS_CONNECT_TIMEOUT', 30 ); // 30 seconds.
	}
	if ( ! defined( 'FS_TIMEOUT' ) ) {
		define( 'FS_TIMEOUT', 30 ); // 30 seconds.
	}

	if ( is_wp_error( $wp_filesystem->errors ) && $wp_filesystem->errors->has_errors() ) {
		return false;
	}

	if ( ! $wp_filesystem->connect() ) {
		return false; // There was an error connecting to the server.
	}

	// Set the permission constants if not already set.
	if ( ! defined( 'FS_CHMOD_DIR' ) ) {
		define( 'FS_CHMOD_DIR', ( fileperms( ABSPATH ) & 0777 | 0755 ) );
	}
	if ( ! defined( 'FS_CHMOD_FILE' ) ) {
		define( 'FS_CHMOD_FILE', ( fileperms( ABSPATH . 'index.php' ) & 0777 | 0644 ) );
	}

	return true;
}

/**
 * Determines which method to use for reading, writing, modifying, or deleting
 * files on the filesystem.
 *
 * The priority of the transports are: Direct, SSH2, FTP PHP Extension, FTP Sockets
 * (Via Sockets class, or `fsockopen()`). Valid values for these are: 'direct', 'ssh2',
 * 'ftpext' or 'ftpsockets'.
 *
 * The return value can be overridden by defining the `FS_METHOD` constant in `wp-config.php`,
 * or filtering via {@see 'filesystem_method'}.
 *
 * @link https://developer.wordpress.org/advanced-administration/wordpress/wp-config/#wordpress-upgrade-constants
 *
 * Plugins may define a custom transport handler, See WP_Filesystem().
 *
 * @since 2.5.0
 *
 * @global callable $_wp_filesystem_direct_method
 *
 * @param array  $args                         Optional. Connection details. Default empty array.
 * @param string $context                      Optional. Full path to the directory that is tested
 *                                             for being writable. Default empty.
 * @param bool   $allow_relaxed_file_ownership Optional. Whether to allow Group/World writable.
 *                                             Default false.
 * @return string The transport to use, see description for valid return values.
 */
function get_filesystem_method( $args = array(), $context = '', $allow_relaxed_file_ownership = false ) {
	// Please ensure that this is either 'direct', 'ssh2', 'ftpext', or 'ftpsockets'.
	$method = defined( 'FS_METHOD' ) ? FS_METHOD : false;

	if ( ! $context ) {
		$context = WP_CONTENT_DIR;
	}

	// If the directory doesn't exist (wp-content/languages) then use the parent directory as we'll create it.
	if ( WP_LANG_DIR === $context && ! is_dir( $context ) ) {
		$context = dirname( $context );
	}

	$context = trailingslashit( $context );

	if ( ! $method ) {

		$temp_file_name = $context . 'temp-write-test-' . str_replace( '.', '-', uniqid( '', true ) );
		$temp_handle    = @fopen( $temp_file_name, 'w' );
		if ( $temp_handle ) {

			// Attempt to determine the file owner of the WordPress files, and that of newly created files.
			$wp_file_owner   = false;
			$temp_file_owner = false;
			if ( function_exists( 'fileowner' ) ) {
				$wp_file_owner   = @fileowner( __FILE__ );
				$temp_file_owner = @fileowner( $temp_file_name );
			}

			if ( false !== $wp_file_owner && $wp_file_owner === $temp_file_owner ) {
				/*
				 * WordPress is creating files as the same owner as the WordPress files,
				 * this means it's safe to modify & create new files via PHP.
				 */
				$method                                  = 'direct';
				$GLOBALS['_wp_filesystem_direct_method'] = 'file_owner';
			} elseif ( $allow_relaxed_file_ownership ) {
				/*
				 * The $context directory is writable, and $allow_relaxed_file_ownership is set,
				 * this means we can modify files safely in this directory.
				 * This mode doesn't create new files, only alter existing ones.
				 */
				$method                                  = 'direct';
				$GLOBALS['_wp_filesystem_direct_method'] = 'relaxed_ownership';
			}

			fclose( $temp_handle );
			@unlink( $temp_file_name );
		}
	}

	if ( ! $method && isset( $args['connection_type'] ) && 'ssh' === $args['connection_type'] && extension_loaded( 'ssh2' ) ) {
		$method = 'ssh2';
	}
	if ( ! $method && extension_loaded( 'ftp' ) ) {
		$method = 'ftpext';
	}
	if ( ! $method && ( extension_loaded( 'sockets' ) || function_exists( 'fsockopen' ) ) ) {
		$method = 'ftpsockets'; // Sockets: Socket extension; PHP Mode: FSockopen / fwrite / fread.
	}

	/**
	 * Filters the filesystem method to use.
	 *
	 * @since 2.6.0
	 *
	 * @param string $method                       Filesystem method to return.
	 * @param array  $args                         An array of connection details for the method.
	 * @param string $context                      Full path to the directory that is tested for being writable.
	 * @param bool   $allow_relaxed_file_ownership Whether to allow Group/World writable.
	 */
	return apply_filters( 'filesystem_method', $method, $args, $context, $allow_relaxed_file_ownership );
}

/**
 * Displays a form to the user to request for their FTP/SSH details in order
 * to connect to the filesystem.
 *
 * All chosen/entered details are saved, excluding the password.
 *
 * Hostnames may be in the form of hostname:portnumber (eg: wordpress.org:2467)
 * to specify an alternate FTP/SSH port.
 *
 * Plugins may override this form by returning true|false via the {@see 'request_filesystem_credentials'} filter.
 *
 * @since 2.5.0
 * @since 4.6.0 The `$context` parameter default changed from `false` to an empty string.
 *
 * @global string $pagenow The filename of the current screen.
 *
 * @param string        $form_post                    The URL to post the form to.
 * @param string        $type                         Optional. Chosen type of filesystem. Default empty.
 * @param bool|WP_Error $error                        Optional. Whether the current request has failed
 *                                                    to connect, or an error object. Default false.
 * @param string        $context                      Optional. Full path to the directory that is tested
 *                                                    for being writable. Default empty.
 * @param array         $extra_fields                 Optional. Extra `POST` fields to be checked
 *                                                    for inclusion in the post. Default null.
 * @param bool          $allow_relaxed_file_ownership Optional. Whether to allow Group/World writable.
 *                                                    Default false.
 * @return bool|array True if no filesystem credentials are required,
 *                    false if they are required but have not been provided,
 *                    array of credentials if they are required and have been provided.
 */
function request_filesystem_credentials( $form_post, $type = '', $error = false, $context = '', $extra_fields = null, $allow_relaxed_file_ownership = false ) {
	global $pagenow;

	/**
	 * Filters the filesystem credentials.
	 *
	 * Returning anything other than an empty string will effectively short-circuit
	 * output of the filesystem credentials form, returning that value instead.
	 *
	 * A filter should return true if no filesystem credentials are required, false if they are required but have not been
	 * provided, or an array of credentials if they are required and have been provided.
	 *
	 * @since 2.5.0
	 * @since 4.6.0 The `$context` parameter default changed from `false` to an empty string.
	 *
	 * @param mixed         $credentials                  Credentials to return instead. Default empty string.
	 * @param string        $form_post                    The URL to post the form to.
	 * @param string        $type                         Chosen type of filesystem.
	 * @param bool|WP_Error $error                        Whether the current request has failed to connect,
	 *                                                    or an error object.
	 * @param string        $context                      Full path to the directory that is tested for
	 *                                                    being writable.
	 * @param array         $extra_fields                 Extra POST fields.
	 * @param bool          $allow_relaxed_file_ownership Whether to allow Group/World writable.
	 */
	$req_cred = apply_filters( 'request_filesystem_credentials', '', $form_post, $type, $error, $context, $extra_fields, $allow_relaxed_file_ownership );

	if ( '' !== $req_cred ) {
		return $req_cred;
	}

	if ( empty( $type ) ) {
		$type = get_filesystem_method( array(), $context, $allow_relaxed_file_ownership );
	}

	if ( 'direct' === $type ) {
		return true;
	}

	if ( is_null( $extra_fields ) ) {
		$extra_fields = array( 'version', 'locale' );
	}

	$credentials = get_option(
		'ftp_credentials',
		array(
			'hostname' => '',
			'username' => '',
		)
	);

	$submitted_form = wp_unslash( $_POST );

	// Verify nonce, or unset submitted form field values on failure.
	if ( ! isset( $_POST['_fs_nonce'] ) || ! wp_verify_nonce( $_POST['_fs_nonce'], 'filesystem-credentials' ) ) {
		unset(
			$submitted_form['hostname'],
			$submitted_form['username'],
			$submitted_form['password'],
			$submitted_form['public_key'],
			$submitted_form['private_key'],
			$submitted_form['connection_type']
		);
	}

	$ftp_constants = array(
		'hostname'    => 'FTP_HOST',
		'username'    => 'FTP_USER',
		'password'    => 'FTP_PASS',
		'public_key'  => 'FTP_PUBKEY',
		'private_key' => 'FTP_PRIKEY',
	);

	/*
	 * If defined, set it to that. Else, if POST'd, set it to that. If not, set it to an empty string.
	 * Otherwise, keep it as it previously was (saved details in option).
	 */
	foreach ( $ftp_constants as $key => $constant ) {
		if ( defined( $constant ) ) {
			$credentials[ $key ] = constant( $constant );
		} elseif ( ! empty( $submitted_form[ $key ] ) ) {
			$credentials[ $key ] = $submitted_form[ $key ];
		} elseif ( ! isset( $credentials[ $key ] ) ) {
			$credentials[ $key ] = '';
		}
	}

	// Sanitize the hostname, some people might pass in odd data.
	$credentials['hostname'] = preg_replace( '|\w+://|', '', $credentials['hostname'] ); // Strip any schemes off.

	if ( strpos( $credentials['hostname'], ':' ) ) {
		list( $credentials['hostname'], $credentials['port'] ) = explode( ':', $credentials['hostname'], 2 );
		if ( ! is_numeric( $credentials['port'] ) ) {
			unset( $credentials['port'] );
		}
	} else {
		unset( $credentials['port'] );
	}

	if ( ( defined( 'FTP_SSH' ) && FTP_SSH ) || ( defined( 'FS_METHOD' ) && 'ssh2' === FS_METHOD ) ) {
		$credentials['connection_type'] = 'ssh';
	} elseif ( ( defined( 'FTP_SSL' ) && FTP_SSL ) && 'ftpext' === $type ) { // Only the FTP Extension understands SSL.
		$credentials['connection_type'] = 'ftps';
	} elseif ( ! empty( $submitted_form['connection_type'] ) ) {
		$credentials['connection_type'] = $submitted_form['connection_type'];
	} elseif ( ! isset( $credentials['connection_type'] ) ) { // All else fails (and it's not defaulted to something else saved), default to FTP.
		$credentials['connection_type'] = 'ftp';
	}

	if ( ! $error
		&& ( ! empty( $credentials['hostname'] ) && ! empty( $credentials['username'] ) && ! empty( $credentials['password'] )
			|| 'ssh' === $credentials['connection_type'] && ! empty( $credentials['public_key'] ) && ! empty( $credentials['private_key'] )
		)
	) {
		$stored_credentials = $credentials;

		if ( ! empty( $stored_credentials['port'] ) ) { // Save port as part of hostname to simplify above code.
			$stored_credentials['hostname'] .= ':' . $stored_credentials['port'];
		}

		unset(
			$stored_credentials['password'],
			$stored_credentials['port'],
			$stored_credentials['private_key'],
			$stored_credentials['public_key']
		);

		if ( ! wp_installing() ) {
			update_option( 'ftp_credentials', $stored_credentials, false );
		}

		return $credentials;
	}

	$hostname        = isset( $credentials['hostname'] ) ? $credentials['hostname'] : '';
	$username        = isset( $credentials['username'] ) ? $credentials['username'] : '';
	$public_key      = isset( $credentials['public_key'] ) ? $credentials['public_key'] : '';
	$private_key     = isset( $credentials['private_key'] ) ? $credentials['private_key'] : '';
	$port            = isset( $credentials['port'] ) ? $credentials['port'] : '';
	$connection_type = isset( $credentials['connection_type'] ) ? $credentials['connection_type'] : '';

	if ( $error ) {
		$error_string = __( '<strong>Error:</strong> Could not connect to the server. Please verify the settings are correct.' );
		if ( is_wp_error( $error ) ) {
			$error_string = esc_html( $error->get_error_message() );
		}
		wp_admin_notice(
			$error_string,
			array(
				'id'                 => 'message',
				'additional_classes' => array( 'error' ),
			)
		);
	}

	$types = array();
	if ( extension_loaded( 'ftp' ) || extension_loaded( 'sockets' ) || function_exists( 'fsockopen' ) ) {
		$types['ftp'] = __( 'FTP' );
	}
	if ( extension_loaded( 'ftp' ) ) { // Only this supports FTPS.
		$types['ftps'] = __( 'FTPS (SSL)' );
	}
	if ( extension_loaded( 'ssh2' ) ) {
		$types['ssh'] = __( 'SSH2' );
	}

	/**
	 * Filters the connection types to output to the filesystem credentials form.
	 *
	 * @since 2.9.0
	 * @since 4.6.0 The `$context` parameter default changed from `false` to an empty string.
	 *
	 * @param string[]      $types       Types of connections.
	 * @param array         $credentials Credentials to connect with.
	 * @param string        $type        Chosen filesystem method.
	 * @param bool|WP_Error $error       Whether the current request has failed to connect,
	 *                                   or an error object.
	 * @param string        $context     Full path to the directory that is tested for being writable.
	 */
	$types = apply_filters( 'fs_ftp_connection_types', $types, $credentials, $type, $error, $context );
	?>
<form action="<?php echo esc_url( $form_post ); ?>" method="post">
<div id="request-filesystem-credentials-form" class="request-filesystem-credentials-form">
	<?php
	// Print a H1 heading in the FTP credentials modal dialog, default is a H2.
	$heading_tag = 'h2';
	if ( 'plugins.php' === $pagenow || 'plugin-install.php' === $pagenow ) {
		$heading_tag = 'h1';
	}
	echo "<$heading_tag id='request-filesystem-credentials-title'>" . __( 'Connection Information' ) . "</$heading_tag>";
	?>
<p id="request-filesystem-credentials-desc">
	<?php
	$label_user = __( 'Username' );
	$label_pass = __( 'Password' );
	_e( 'To perform the requested action, WordPress needs to access your web server.' );
	echo ' ';
	if ( ( isset( $types['ftp'] ) || isset( $types['ftps'] ) ) ) {
		if ( isset( $types['ssh'] ) ) {
			_e( 'Please enter your FTP or SSH credentials to proceed.' );
			$label_user = __( 'FTP/SSH Username' );
			$label_pass = __( 'FTP/SSH Password' );
		} else {
			_e( 'Please enter your FTP credentials to proceed.' );
			$label_user = __( 'FTP Username' );
			$label_pass = __( 'FTP Password' );
		}
		echo ' ';
	}
	_e( 'If you do not remember your credentials, you should contact your web host.' );

	$hostname_value = esc_attr( $hostname );
	if ( ! empty( $port ) ) {
		$hostname_value .= ":$port";
	}

	$password_value = '';
	if ( defined( 'FTP_PASS' ) ) {
		$password_value = '*****';
	}
	?>
</p>
<label for="hostname">
	<span class="field-title"><?php _e( 'Hostname' ); ?></span>
	<input name="hostname" type="text" id="hostname" aria-describedby="request-filesystem-credentials-desc" class="code" placeholder="<?php esc_attr_e( 'example: www.wordpress.org' ); ?>" value="<?php echo $hostname_value; ?>"<?php disabled( defined( 'FTP_HOST' ) ); ?> />
</label>
<div class="ftp-username">
	<label for="username">
		<span class="field-title"><?php echo $label_user; ?></span>
		<input name="username" type="text" id="username" value="<?php echo esc_attr( $username ); ?>"<?php disabled( defined( 'FTP_USER' ) ); ?> />
	</label>
</div>
<div class="ftp-password">
	<label for="password">
		<span class="field-title"><?php echo $label_pass; ?></span>
		<input name="password" type="password" id="password" value="<?php echo $password_value; ?>"<?php disabled( defined( 'FTP_PASS' ) ); ?> spellcheck="false" />
		<?php
		if ( ! defined( 'FTP_PASS' ) ) {
			_e( 'This password will not be stored on the server.' );
		}
		?>
	</label>
</div>
<fieldset>
<legend><?php _e( 'Connection Type' ); ?></legend>
	<?php
	$disabled = disabled( ( defined( 'FTP_SSL' ) && FTP_SSL ) || ( defined( 'FTP_SSH' ) && FTP_SSH ), true, false );
	foreach ( $types as $name => $text ) :
		?>
	<label for="<?php echo esc_attr( $name ); ?>">
		<input type="radio" name="connection_type" id="<?php echo esc_attr( $name ); ?>" value="<?php echo esc_attr( $name ); ?>" <?php checked( $name, $connection_type ); ?> <?php echo $disabled; ?> />
		<?php echo $text; ?>
	</label>
		<?php
	endforeach;
	?>
</fieldset>
	<?php
	if ( isset( $types['ssh'] ) ) {
		$hidden_class = '';
		if ( 'ssh' !== $connection_type ) {
			$hidden_class = ' class="hidden"';
		}
		?>
<fieldset id="ssh-keys"<?php echo $hidden_class; ?>>
<legend><?php _e( 'Authentication Keys' ); ?></legend>
<label for="public_key">
	<span class="field-title"><?php _e( 'Public Key:' ); ?></span>
	<input name="public_key" type="text" id="public_key" aria-describedby="auth-keys-desc" value="<?php echo esc_attr( $public_key ); ?>"<?php disabled( defined( 'FTP_PUBKEY' ) ); ?> />
</label>
<label for="private_key">
	<span class="field-title"><?php _e( 'Private Key:' ); ?></span>
	<input name="private_key" type="text" id="private_key" value="<?php echo esc_attr( $private_key ); ?>"<?php disabled( defined( 'FTP_PRIKEY' ) ); ?> />
</label>
<p id="auth-keys-desc"><?php _e( 'Enter the location on the server where the public and private keys are located. If a passphrase is needed, enter that in the password field above.' ); ?></p>
</fieldset>
		<?php
	}

	foreach ( (array) $extra_fields as $field ) {
		if ( isset( $submitted_form[ $field ] ) ) {
			echo '<input type="hidden" name="' . esc_attr( $field ) . '" value="' . esc_attr( $submitted_form[ $field ] ) . '" />';
		}
	}

	/*
	 * Make sure the `submit_button()` function is available during the REST API call
	 * from WP_Site_Health_Auto_Updates::test_check_wp_filesystem_method().
	 */
	if ( ! function_exists( 'submit_button' ) ) {
		require_once ABSPATH . 'wp-admin/includes/template.php';
	}
	?>
	<p class="request-filesystem-credentials-action-buttons">
		<?php wp_nonce_field( 'filesystem-credentials', '_fs_nonce', false, true ); ?>
		<button class="button cancel-button" data-js-action="close" type="button"><?php _e( 'Cancel' ); ?></button>
		<?php submit_button( __( 'Proceed' ), 'primary', 'upgrade', false ); ?>
	</p>
</div>
</form>
	<?php
	return false;
}

/**
 * Prints the filesystem credentials modal when needed.
 *
 * @since 4.2.0
 */
function wp_print_request_filesystem_credentials_modal() {
	$filesystem_method = get_filesystem_method();

	ob_start();
	$filesystem_credentials_are_stored = request_filesystem_credentials( self_admin_url() );
	ob_end_clean();

	$request_filesystem_credentials = ( 'direct' !== $filesystem_method && ! $filesystem_credentials_are_stored );
	if ( ! $request_filesystem_credentials ) {
		return;
	}
	?>
	<div id="request-filesystem-credentials-dialog" class="notification-dialog-wrap request-filesystem-credentials-dialog">
		<div class="notification-dialog-background"></div>
		<div class="notification-dialog" role="dialog" aria-labelledby="request-filesystem-credentials-title" tabindex="0">
			<div class="request-filesystem-credentials-dialog-content">
				<?php request_filesystem_credentials( site_url() ); ?>
			</div>
		</div>
	</div>
	<?php
}

/**
 * Attempts to clear the opcode cache for an individual PHP file.
 *
 * This function can be called safely without having to check the file extension
 * or availability of the OPcache extension.
 *
 * Whether or not invalidation is possible is cached to improve performance.
 *
 * @since 5.5.0
 *
 * @link https://www.php.net/manual/en/function.opcache-invalidate.php
 *
 * @param string $filepath Path to the file, including extension, for which the opcode cache is to be cleared.
 * @param bool   $force    Invalidate even if the modification time is not newer than the file in cache.
 *                         Default false.
 * @return bool True if opcache was invalidated for `$filepath`, or there was nothing to invalidate.
 *              False if opcache invalidation is not available, or is disabled via filter.
 */
function wp_opcache_invalidate( $filepath, $force = false ) {
	static $can_invalidate = null;

	/*
	 * Check to see if WordPress is able to run `opcache_invalidate()` or not, and cache the value.
	 *
	 * First, check to see if the function is available to call, then if the host has restricted
	 * the ability to run the function to avoid a PHP warning.
	 *
	 * `opcache.restrict_api` can specify the path for files allowed to call `opcache_invalidate()`.
	 *
	 * If the host has this set, check whether the path in `opcache.restrict_api` matches
	 * the beginning of the path of the origin file.
	 *
	 * `$_SERVER['SCRIPT_FILENAME']` approximates the origin file's path, but `realpath()`
	 * is necessary because `SCRIPT_FILENAME` can be a relative path when run from CLI.
	 *
	 * For more details, see:
	 * - https://www.php.net/manual/en/opcache.configuration.php
	 * - https://www.php.net/manual/en/reserved.variables.server.php
	 * - https://core.trac.wordpress.org/ticket/36455
	 */
	if ( null === $can_invalidate
		&& function_exists( 'opcache_invalidate' )
		&& ( ! ini_get( 'opcache.restrict_api' )
			|| stripos( realpath( $_SERVER['SCRIPT_FILENAME'] ), ini_get( 'opcache.restrict_api' ) ) === 0 )
	) {
		$can_invalidate = true;
	}

	// If invalidation is not available, return early.
	if ( ! $can_invalidate ) {
		return false;
	}

	// Verify that file to be invalidated has a PHP extension.
	if ( '.php' !== strtolower( substr( $filepath, -4 ) ) ) {
		return false;
	}

	/**
	 * Filters whether to invalidate a file from the opcode cache.
	 *
	 * @since 5.5.0
	 *
	 * @param bool   $will_invalidate Whether WordPress will invalidate `$filepath`. Default true.
	 * @param string $filepath        The path to the PHP file to invalidate.
	 */
	if ( apply_filters( 'wp_opcache_invalidate_file', true, $filepath ) ) {
		return opcache_invalidate( $filepath, $force );
	}

	return false;
}

/**
 * Attempts to clear the opcode cache for a directory of files.
 *
 * @since 6.2.0
 *
 * @see wp_opcache_invalidate()
 * @link https://www.php.net/manual/en/function.opcache-invalidate.php
 *
 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
 *
 * @param string $dir The path to the directory for which the opcode cache is to be cleared.
 */
function wp_opcache_invalidate_directory( $dir ) {
	global $wp_filesystem;

	if ( ! is_string( $dir ) || '' === trim( $dir ) ) {
		if ( WP_DEBUG ) {
			$error_message = sprintf(
				/* translators: %s: The function name. */
				__( '%s expects a non-empty string.' ),
				'<code>wp_opcache_invalidate_directory()</code>'
			);
			wp_trigger_error( '', $error_message );
		}
		return;
	}

	$dirlist = $wp_filesystem->dirlist( $dir, false, true );

	if ( empty( $dirlist ) ) {
		return;
	}

	/*
	 * Recursively invalidate opcache of files in a directory.
	 *
	 * WP_Filesystem_*::dirlist() returns an array of file and directory information.
	 *
	 * This does not include a path to the file or directory.
	 * To invalidate files within sub-directories, recursion is needed
	 * to prepend an absolute path containing the sub-directory's name.
	 *
	 * @param array  $dirlist Array of file/directory information from WP_Filesystem_Base::dirlist(),
	 *                        with sub-directories represented as nested arrays.
	 * @param string $path    Absolute path to the directory.
	 */
	$invalidate_directory = static function ( $dirlist, $path ) use ( &$invalidate_directory ) {
		$path = trailingslashit( $path );

		foreach ( $dirlist as $name => $details ) {
			if ( 'f' === $details['type'] ) {
				wp_opcache_invalidate( $path . $name, true );
			} elseif ( is_array( $details['files'] ) && ! empty( $details['files'] ) ) {
				$invalidate_directory( $details['files'], $path . $name );
			}
		}
	};

	$invalidate_directory( $dirlist, $dir );
}
admin-filters.php000064400000017542151212616050010023 0ustar00<?php
/**
 * Administration API: Default admin hooks
 *
 * @package WordPress
 * @subpackage Administration
 * @since 4.3.0
 */

// Bookmark hooks.
add_action( 'admin_page_access_denied', 'wp_link_manager_disabled_message' );

// Dashboard hooks.
add_action( 'activity_box_end', 'wp_dashboard_quota' );
add_action( 'welcome_panel', 'wp_welcome_panel' );

// Media hooks.
add_action( 'attachment_submitbox_misc_actions', 'attachment_submitbox_metadata' );
add_filter( 'plupload_init', 'wp_show_heic_upload_error' );

add_action( 'media_upload_image', 'wp_media_upload_handler' );
add_action( 'media_upload_audio', 'wp_media_upload_handler' );
add_action( 'media_upload_video', 'wp_media_upload_handler' );
add_action( 'media_upload_file', 'wp_media_upload_handler' );

add_action( 'post-plupload-upload-ui', 'media_upload_flash_bypass' );

add_action( 'post-html-upload-ui', 'media_upload_html_bypass' );

add_filter( 'async_upload_image', 'get_media_item', 10, 2 );
add_filter( 'async_upload_audio', 'get_media_item', 10, 2 );
add_filter( 'async_upload_video', 'get_media_item', 10, 2 );
add_filter( 'async_upload_file', 'get_media_item', 10, 2 );

add_filter( 'media_upload_gallery', 'media_upload_gallery' );
add_filter( 'media_upload_library', 'media_upload_library' );

add_filter( 'media_upload_tabs', 'update_gallery_tab' );

// Admin color schemes.
add_action( 'admin_init', 'register_admin_color_schemes', 1 );
add_action( 'admin_head', 'wp_color_scheme_settings' );
add_action( 'admin_color_scheme_picker', 'admin_color_scheme_picker' );

// Misc hooks.
add_action( 'admin_init', 'wp_admin_headers' );
add_action( 'admin_init', 'send_frame_options_header', 10, 0 );
add_action( 'admin_head', 'wp_admin_canonical_url' );
add_action( 'admin_head', 'wp_site_icon' );
add_action( 'admin_head', 'wp_admin_viewport_meta' );
add_action( 'customize_controls_head', 'wp_admin_viewport_meta' );
add_filter( 'nav_menu_meta_box_object', '_wp_nav_menu_meta_box_object' );

// Prerendering.
if ( ! is_customize_preview() ) {
	add_filter( 'admin_print_styles', 'wp_resource_hints', 1 );
}

add_action( 'admin_print_scripts', 'print_emoji_detection_script' );
add_action( 'admin_print_scripts', 'print_head_scripts', 20 );
add_action( 'admin_print_footer_scripts', '_wp_footer_scripts' );
add_action( 'admin_enqueue_scripts', 'wp_enqueue_emoji_styles' );
add_action( 'admin_print_styles', 'print_emoji_styles' ); // Retained for backwards-compatibility. Unhooked by wp_enqueue_emoji_styles().
add_action( 'admin_print_styles', 'print_admin_styles', 20 );

add_action( 'admin_print_scripts-index.php', 'wp_localize_community_events' );
add_action( 'admin_print_scripts-post.php', 'wp_page_reload_on_back_button_js' );
add_action( 'admin_print_scripts-post-new.php', 'wp_page_reload_on_back_button_js' );

add_action( 'update_option_home', 'update_home_siteurl', 10, 2 );
add_action( 'update_option_siteurl', 'update_home_siteurl', 10, 2 );
add_action( 'update_option_page_on_front', 'update_home_siteurl', 10, 2 );
add_action( 'update_option_admin_email', 'wp_site_admin_email_change_notification', 10, 3 );

add_action( 'add_option_new_admin_email', 'update_option_new_admin_email', 10, 2 );
add_action( 'update_option_new_admin_email', 'update_option_new_admin_email', 10, 2 );

add_filter( 'heartbeat_received', 'wp_check_locked_posts', 10, 3 );
add_filter( 'heartbeat_received', 'wp_refresh_post_lock', 10, 3 );
add_filter( 'heartbeat_received', 'heartbeat_autosave', 500, 2 );

add_filter( 'wp_refresh_nonces', 'wp_refresh_post_nonces', 10, 3 );
add_filter( 'wp_refresh_nonces', 'wp_refresh_metabox_loader_nonces', 10, 2 );
add_filter( 'wp_refresh_nonces', 'wp_refresh_heartbeat_nonces' );

add_filter( 'heartbeat_settings', 'wp_heartbeat_set_suspension' );

add_action( 'use_block_editor_for_post_type', '_disable_block_editor_for_navigation_post_type', 10, 2 );
add_action( 'edit_form_after_title', '_disable_content_editor_for_navigation_post_type' );
add_action( 'edit_form_after_editor', '_enable_content_editor_for_navigation_post_type' );

// Nav Menu hooks.
add_action( 'admin_head-nav-menus.php', '_wp_delete_orphaned_draft_menu_items' );

// Plugin hooks.
add_filter( 'allowed_options', 'option_update_filter' );

// Plugin Install hooks.
add_action( 'install_plugins_featured', 'install_dashboard' );
add_action( 'install_plugins_upload', 'install_plugins_upload' );
add_action( 'install_plugins_search', 'display_plugins_table' );
add_action( 'install_plugins_popular', 'display_plugins_table' );
add_action( 'install_plugins_recommended', 'display_plugins_table' );
add_action( 'install_plugins_new', 'display_plugins_table' );
add_action( 'install_plugins_beta', 'display_plugins_table' );
add_action( 'install_plugins_favorites', 'display_plugins_table' );
add_action( 'install_plugins_pre_plugin-information', 'install_plugin_information' );

// Template hooks.
add_action( 'admin_enqueue_scripts', array( 'WP_Internal_Pointers', 'enqueue_scripts' ) );
add_action( 'user_register', array( 'WP_Internal_Pointers', 'dismiss_pointers_for_new_users' ) );

// Theme hooks.
add_action( 'customize_controls_print_footer_scripts', 'customize_themes_print_templates' );

// Theme Install hooks.
add_action( 'install_themes_pre_theme-information', 'install_theme_information' );

// User hooks.
add_action( 'admin_init', 'default_password_nag_handler' );

add_action( 'admin_notices', 'default_password_nag' );
add_action( 'admin_notices', 'new_user_email_admin_notice' );

add_action( 'profile_update', 'default_password_nag_edit_user', 10, 2 );

add_action( 'personal_options_update', 'send_confirmation_on_profile_email' );

// Update hooks.
add_action( 'load-plugins.php', 'wp_plugin_update_rows', 20 ); // After wp_update_plugins() is called.
add_action( 'load-themes.php', 'wp_theme_update_rows', 20 ); // After wp_update_themes() is called.

add_action( 'admin_notices', 'update_nag', 3 );
add_action( 'admin_notices', 'deactivated_plugins_notice', 5 );
add_action( 'admin_notices', 'paused_plugins_notice', 5 );
add_action( 'admin_notices', 'paused_themes_notice', 5 );
add_action( 'admin_notices', 'maintenance_nag', 10 );
add_action( 'admin_notices', 'wp_recovery_mode_nag', 1 );

add_filter( 'update_footer', 'core_update_footer' );

// Update Core hooks.
add_action( '_core_updated_successfully', '_redirect_to_about_wordpress' );

// Upgrade hooks.
add_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
add_action( 'upgrader_process_complete', 'wp_version_check', 10, 0 );
add_action( 'upgrader_process_complete', 'wp_update_plugins', 10, 0 );
add_action( 'upgrader_process_complete', 'wp_update_themes', 10, 0 );

// Privacy hooks.
add_filter( 'wp_privacy_personal_data_erasure_page', 'wp_privacy_process_personal_data_erasure_page', 10, 5 );
add_filter( 'wp_privacy_personal_data_export_page', 'wp_privacy_process_personal_data_export_page', 10, 7 );
add_action( 'wp_privacy_personal_data_export_file', 'wp_privacy_generate_personal_data_export_file', 10 );
add_action( 'wp_privacy_personal_data_erased', '_wp_privacy_send_erasure_fulfillment_notification', 10 );

// Privacy policy text changes check.
add_action( 'admin_init', array( 'WP_Privacy_Policy_Content', 'text_change_check' ), 100 );

// Show a "postbox" with the text suggestions for a privacy policy.
add_action( 'admin_notices', array( 'WP_Privacy_Policy_Content', 'notice' ) );

// Add the suggested policy text from WordPress.
add_action( 'admin_init', array( 'WP_Privacy_Policy_Content', 'add_suggested_content' ), 1 );

// Update the cached policy info when the policy page is updated.
add_action( 'post_updated', array( 'WP_Privacy_Policy_Content', '_policy_page_updated' ) );

// Append '(Draft)' to draft page titles in the privacy page dropdown.
add_filter( 'list_pages', '_wp_privacy_settings_filter_draft_page_titles', 10, 2 );

// Font management.
add_action( 'admin_print_styles', 'wp_print_font_faces', 50 );
add_action( 'admin_print_styles', 'wp_print_font_faces_from_style_variations', 50 );
class-wp-theme-install-list-table.php000064400000036357151212616050013625 0ustar00<?php
/**
 * List Table API: WP_Theme_Install_List_Table class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 3.1.0
 */

/**
 * Core class used to implement displaying themes to install in a list table.
 *
 * @since 3.1.0
 *
 * @see WP_Themes_List_Table
 */
class WP_Theme_Install_List_Table extends WP_Themes_List_Table {

	public $features = array();

	/**
	 * @return bool
	 */
	public function ajax_user_can() {
		return current_user_can( 'install_themes' );
	}

	/**
	 * @global array  $tabs
	 * @global string $tab
	 * @global int    $paged
	 * @global string $type
	 * @global array  $theme_field_defaults
	 */
	public function prepare_items() {
		require ABSPATH . 'wp-admin/includes/theme-install.php';

		global $tabs, $tab, $paged, $type, $theme_field_defaults;

		$tab = ! empty( $_REQUEST['tab'] ) ? sanitize_text_field( $_REQUEST['tab'] ) : '';

		$search_terms  = array();
		$search_string = '';
		if ( ! empty( $_REQUEST['s'] ) ) {
			$search_string = strtolower( wp_unslash( $_REQUEST['s'] ) );
			$search_terms  = array_unique( array_filter( array_map( 'trim', explode( ',', $search_string ) ) ) );
		}

		if ( ! empty( $_REQUEST['features'] ) ) {
			$this->features = $_REQUEST['features'];
		}

		$paged = $this->get_pagenum();

		$per_page = 36;

		// These are the tabs which are shown on the page,
		$tabs              = array();
		$tabs['dashboard'] = __( 'Search' );
		if ( 'search' === $tab ) {
			$tabs['search'] = __( 'Search Results' );
		}
		$tabs['upload']   = _x( 'Upload', 'noun' );
		$tabs['featured'] = _x( 'Featured', 'themes' );
		//$tabs['popular']  = _x( 'Popular', 'themes' );
		$tabs['new']     = _x( 'Latest', 'themes' );
		$tabs['updated'] = _x( 'Recently Updated', 'themes' );

		$nonmenu_tabs = array( 'theme-information' ); // Valid actions to perform which do not have a Menu item.

		/** This filter is documented in wp-admin/theme-install.php */
		$tabs = apply_filters( 'install_themes_tabs', $tabs );

		/**
		 * Filters tabs not associated with a menu item on the Install Themes screen.
		 *
		 * @since 2.8.0
		 *
		 * @param string[] $nonmenu_tabs The tabs that don't have a menu item on
		 *                               the Install Themes screen.
		 */
		$nonmenu_tabs = apply_filters( 'install_themes_nonmenu_tabs', $nonmenu_tabs );

		// If a non-valid menu tab has been selected, And it's not a non-menu action.
		if ( empty( $tab ) || ( ! isset( $tabs[ $tab ] ) && ! in_array( $tab, (array) $nonmenu_tabs, true ) ) ) {
			$tab = key( $tabs );
		}

		$args = array(
			'page'     => $paged,
			'per_page' => $per_page,
			'fields'   => $theme_field_defaults,
		);

		switch ( $tab ) {
			case 'search':
				$type = isset( $_REQUEST['type'] ) ? wp_unslash( $_REQUEST['type'] ) : 'term';
				switch ( $type ) {
					case 'tag':
						$args['tag'] = array_map( 'sanitize_key', $search_terms );
						break;
					case 'term':
						$args['search'] = $search_string;
						break;
					case 'author':
						$args['author'] = $search_string;
						break;
				}

				if ( ! empty( $this->features ) ) {
					$args['tag']      = $this->features;
					$_REQUEST['s']    = implode( ',', $this->features );
					$_REQUEST['type'] = 'tag';
				}

				add_action( 'install_themes_table_header', 'install_theme_search_form', 10, 0 );
				break;

			case 'featured':
				// case 'popular':
			case 'new':
			case 'updated':
				$args['browse'] = $tab;
				break;

			default:
				$args = false;
				break;
		}

		/**
		 * Filters API request arguments for each Install Themes screen tab.
		 *
		 * The dynamic portion of the hook name, `$tab`, refers to the theme install
		 * tab.
		 *
		 * Possible hook names include:
		 *
		 *  - `install_themes_table_api_args_dashboard`
		 *  - `install_themes_table_api_args_featured`
		 *  - `install_themes_table_api_args_new`
		 *  - `install_themes_table_api_args_search`
		 *  - `install_themes_table_api_args_updated`
		 *  - `install_themes_table_api_args_upload`
		 *
		 * @since 3.7.0
		 *
		 * @param array|false $args Theme install API arguments.
		 */
		$args = apply_filters( "install_themes_table_api_args_{$tab}", $args );

		if ( ! $args ) {
			return;
		}

		$api = themes_api( 'query_themes', $args );

		if ( is_wp_error( $api ) ) {
			wp_die( '<p>' . $api->get_error_message() . '</p> <p><a href="#" onclick="document.location.reload(); return false;">' . __( 'Try Again' ) . '</a></p>' );
		}

		$this->items = $api->themes;

		$this->set_pagination_args(
			array(
				'total_items'     => $api->info['results'],
				'per_page'        => $args['per_page'],
				'infinite_scroll' => true,
			)
		);
	}

	/**
	 */
	public function no_items() {
		_e( 'No themes match your request.' );
	}

	/**
	 * @global array $tabs
	 * @global string $tab
	 * @return array
	 */
	protected function get_views() {
		global $tabs, $tab;

		$display_tabs = array();
		foreach ( (array) $tabs as $action => $text ) {
			$display_tabs[ 'theme-install-' . $action ] = array(
				'url'     => self_admin_url( 'theme-install.php?tab=' . $action ),
				'label'   => $text,
				'current' => $action === $tab,
			);
		}

		return $this->get_views_links( $display_tabs );
	}

	/**
	 * Displays the theme install table.
	 *
	 * Overrides the parent display() method to provide a different container.
	 *
	 * @since 3.1.0
	 */
	public function display() {
		wp_nonce_field( 'fetch-list-' . get_class( $this ), '_ajax_fetch_list_nonce' );
		?>
		<div class="tablenav top themes">
			<div class="alignleft actions">
				<?php
				/**
				 * Fires in the Install Themes list table header.
				 *
				 * @since 2.8.0
				 */
				do_action( 'install_themes_table_header' );
				?>
			</div>
			<?php $this->pagination( 'top' ); ?>
			<br class="clear" />
		</div>

		<div id="availablethemes">
			<?php $this->display_rows_or_placeholder(); ?>
		</div>

		<?php
		$this->tablenav( 'bottom' );
	}

	/**
	 * Generates the list table rows.
	 *
	 * @since 3.1.0
	 */
	public function display_rows() {
		$themes = $this->items;
		foreach ( $themes as $theme ) {
			?>
				<div class="available-theme installable-theme">
				<?php
					$this->single_row( $theme );
				?>
				</div>
			<?php
		} // End foreach $theme_names.

		$this->theme_installer();
	}

	/**
	 * Prints a theme from the WordPress.org API.
	 *
	 * @since 3.1.0
	 *
	 * @global array $themes_allowedtags
	 *
	 * @param stdClass $theme {
	 *     An object that contains theme data returned by the WordPress.org API.
	 *
	 *     @type string $name           Theme name, e.g. 'Twenty Twenty-One'.
	 *     @type string $slug           Theme slug, e.g. 'twentytwentyone'.
	 *     @type string $version        Theme version, e.g. '1.1'.
	 *     @type string $author         Theme author username, e.g. 'melchoyce'.
	 *     @type string $preview_url    Preview URL, e.g. 'https://2021.wordpress.net/'.
	 *     @type string $screenshot_url Screenshot URL, e.g. 'https://wordpress.org/themes/twentytwentyone/'.
	 *     @type float  $rating         Rating score.
	 *     @type int    $num_ratings    The number of ratings.
	 *     @type string $homepage       Theme homepage, e.g. 'https://wordpress.org/themes/twentytwentyone/'.
	 *     @type string $description    Theme description.
	 *     @type string $download_link  Theme ZIP download URL.
	 * }
	 */
	public function single_row( $theme ) {
		global $themes_allowedtags;

		if ( empty( $theme ) ) {
			return;
		}

		$name   = wp_kses( $theme->name, $themes_allowedtags );
		$author = wp_kses( $theme->author, $themes_allowedtags );

		/* translators: %s: Theme name. */
		$preview_title = sprintf( __( 'Preview &#8220;%s&#8221;' ), $name );
		$preview_url   = add_query_arg(
			array(
				'tab'   => 'theme-information',
				'theme' => $theme->slug,
			),
			self_admin_url( 'theme-install.php' )
		);

		$actions = array();

		$install_url = add_query_arg(
			array(
				'action' => 'install-theme',
				'theme'  => $theme->slug,
			),
			self_admin_url( 'update.php' )
		);

		$update_url = add_query_arg(
			array(
				'action' => 'upgrade-theme',
				'theme'  => $theme->slug,
			),
			self_admin_url( 'update.php' )
		);

		$status = $this->_get_theme_status( $theme );

		switch ( $status ) {
			case 'update_available':
				$actions[] = sprintf(
					'<a class="install-now" href="%s" aria-label="%s">%s</a>',
					esc_url( wp_nonce_url( $update_url, 'upgrade-theme_' . $theme->slug ) ),
					/* translators: %s: Theme version. */
					esc_attr( sprintf( __( 'Update to version %s' ), $theme->version ) ),
					__( 'Update' )
				);
				break;
			case 'newer_installed':
			case 'latest_installed':
				$actions[] = sprintf(
					'<span class="install-now">%s</span>',
					_x( 'Installed', 'theme' )
				);
				break;
			case 'install':
			default:
				$actions[] = sprintf(
					'<a class="install-now" href="%s" aria-label="%s">%s</a>',
					esc_url( wp_nonce_url( $install_url, 'install-theme_' . $theme->slug ) ),
					/* translators: %s: Theme name. */
					esc_attr( sprintf( _x( 'Install %s', 'theme' ), $name ) ),
					_x( 'Install Now', 'theme' )
				);
				break;
		}

		$actions[] = sprintf(
			'<a class="install-theme-preview" href="%s" aria-label="%s">%s</a>',
			esc_url( $preview_url ),
			esc_attr( $preview_title ),
			__( 'Preview' )
		);

		/**
		 * Filters the install action links for a theme in the Install Themes list table.
		 *
		 * @since 3.4.0
		 *
		 * @param string[] $actions An array of theme action links. Defaults are
		 *                          links to Install Now, Preview, and Details.
		 * @param stdClass $theme   An object that contains theme data returned by the
		 *                          WordPress.org API.
		 */
		$actions = apply_filters( 'theme_install_actions', $actions, $theme );

		?>
		<a class="screenshot install-theme-preview" href="<?php echo esc_url( $preview_url ); ?>" aria-label="<?php echo esc_attr( $preview_title ); ?>">
			<img src="<?php echo esc_url( $theme->screenshot_url . '?ver=' . $theme->version ); ?>" width="150" alt="" />
		</a>

		<h3><?php echo $name; ?></h3>
		<div class="theme-author">
		<?php
			/* translators: %s: Theme author. */
			printf( __( 'By %s' ), $author );
		?>
		</div>

		<div class="action-links">
			<ul>
				<?php foreach ( $actions as $action ) : ?>
					<li><?php echo $action; ?></li>
				<?php endforeach; ?>
				<li class="hide-if-no-js"><a href="#" class="theme-detail"><?php _e( 'Details' ); ?></a></li>
			</ul>
		</div>

		<?php
		$this->install_theme_info( $theme );
	}

	/**
	 * Prints the wrapper for the theme installer.
	 */
	public function theme_installer() {
		?>
		<div id="theme-installer" class="wp-full-overlay expanded">
			<div class="wp-full-overlay-sidebar">
				<div class="wp-full-overlay-header">
					<a href="#" class="close-full-overlay button"><?php _e( 'Close' ); ?></a>
					<span class="theme-install"></span>
				</div>
				<div class="wp-full-overlay-sidebar-content">
					<div class="install-theme-info"></div>
				</div>
				<div class="wp-full-overlay-footer">
					<button type="button" class="collapse-sidebar button" aria-expanded="true" aria-label="<?php esc_attr_e( 'Collapse Sidebar' ); ?>">
						<span class="collapse-sidebar-arrow"></span>
						<span class="collapse-sidebar-label"><?php _e( 'Collapse' ); ?></span>
					</button>
				</div>
			</div>
			<div class="wp-full-overlay-main"></div>
		</div>
		<?php
	}

	/**
	 * Prints the wrapper for the theme installer with a provided theme's data.
	 * Used to make the theme installer work for no-js.
	 *
	 * @param stdClass $theme A WordPress.org Theme API object.
	 */
	public function theme_installer_single( $theme ) {
		?>
		<div id="theme-installer" class="wp-full-overlay single-theme">
			<div class="wp-full-overlay-sidebar">
				<?php $this->install_theme_info( $theme ); ?>
			</div>
			<div class="wp-full-overlay-main">
				<iframe src="<?php echo esc_url( $theme->preview_url ); ?>"></iframe>
			</div>
		</div>
		<?php
	}

	/**
	 * Prints the info for a theme (to be used in the theme installer modal).
	 *
	 * @global array $themes_allowedtags
	 *
	 * @param stdClass $theme A WordPress.org Theme API object.
	 */
	public function install_theme_info( $theme ) {
		global $themes_allowedtags;

		if ( empty( $theme ) ) {
			return;
		}

		$name   = wp_kses( $theme->name, $themes_allowedtags );
		$author = wp_kses( $theme->author, $themes_allowedtags );

		$install_url = add_query_arg(
			array(
				'action' => 'install-theme',
				'theme'  => $theme->slug,
			),
			self_admin_url( 'update.php' )
		);

		$update_url = add_query_arg(
			array(
				'action' => 'upgrade-theme',
				'theme'  => $theme->slug,
			),
			self_admin_url( 'update.php' )
		);

		$status = $this->_get_theme_status( $theme );

		?>
		<div class="install-theme-info">
		<?php
		switch ( $status ) {
			case 'update_available':
				printf(
					'<a class="theme-install button button-primary" href="%s" aria-label="%s">%s</a>',
					esc_url( wp_nonce_url( $update_url, 'upgrade-theme_' . $theme->slug ) ),
					/* translators: %s: Theme version. */
					esc_attr( sprintf( __( 'Update to version %s' ), $theme->version ) ),
					__( 'Update' )
				);
				break;
			case 'newer_installed':
			case 'latest_installed':
				printf(
					'<span class="theme-install">%s</span>',
					_x( 'Installed', 'theme' )
				);
				break;
			case 'install':
			default:
				printf(
					'<a class="theme-install button button-primary" href="%s">%s</a>',
					esc_url( wp_nonce_url( $install_url, 'install-theme_' . $theme->slug ) ),
					__( 'Install' )
				);
				break;
		}
		?>
			<h3 class="theme-name"><?php echo $name; ?></h3>
			<span class="theme-by">
			<?php
				/* translators: %s: Theme author. */
				printf( __( 'By %s' ), $author );
			?>
			</span>
			<?php if ( isset( $theme->screenshot_url ) ) : ?>
				<img class="theme-screenshot" src="<?php echo esc_url( $theme->screenshot_url . '?ver=' . $theme->version ); ?>" alt="" />
			<?php endif; ?>
			<div class="theme-details">
				<?php
				wp_star_rating(
					array(
						'rating' => $theme->rating,
						'type'   => 'percent',
						'number' => $theme->num_ratings,
					)
				);
				?>
				<div class="theme-version">
					<strong><?php _e( 'Version:' ); ?> </strong>
					<?php echo wp_kses( $theme->version, $themes_allowedtags ); ?>
				</div>
				<div class="theme-description">
					<?php echo wp_kses( $theme->description, $themes_allowedtags ); ?>
				</div>
			</div>
			<input class="theme-preview-url" type="hidden" value="<?php echo esc_url( $theme->preview_url ); ?>" />
		</div>
		<?php
	}

	/**
	 * Send required variables to JavaScript land
	 *
	 * @since 3.4.0
	 *
	 * @global string $tab  Current tab within Themes->Install screen
	 * @global string $type Type of search.
	 *
	 * @param array $extra_args Unused.
	 */
	public function _js_vars( $extra_args = array() ) {
		global $tab, $type;
		parent::_js_vars( compact( 'tab', 'type' ) );
	}

	/**
	 * Checks to see if the theme is already installed.
	 *
	 * @since 3.4.0
	 *
	 * @param stdClass $theme A WordPress.org Theme API object.
	 * @return string Theme status.
	 */
	private function _get_theme_status( $theme ) {
		$status = 'install';

		$installed_theme = wp_get_theme( $theme->slug );
		if ( $installed_theme->exists() ) {
			if ( version_compare( $installed_theme->get( 'Version' ), $theme->version, '=' ) ) {
				$status = 'latest_installed';
			} elseif ( version_compare( $installed_theme->get( 'Version' ), $theme->version, '>' ) ) {
				$status = 'newer_installed';
			} else {
				$status = 'update_available';
			}
		}

		return $status;
	}
}
class-walker-nav-menu-edit.php000064400000033543151212616050012323 0ustar00<?php
/**
 * Navigation Menu API: Walker_Nav_Menu_Edit class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 4.4.0
 */

/**
 * Create HTML list of nav menu input items.
 *
 * @since 3.0.0
 *
 * @see Walker_Nav_Menu
 */
class Walker_Nav_Menu_Edit extends Walker_Nav_Menu {
	/**
	 * Starts the list before the elements are added.
	 *
	 * @see Walker_Nav_Menu::start_lvl()
	 *
	 * @since 3.0.0
	 *
	 * @param string   $output Passed by reference.
	 * @param int      $depth  Depth of menu item. Used for padding.
	 * @param stdClass $args   Not used.
	 */
	public function start_lvl( &$output, $depth = 0, $args = null ) {}

	/**
	 * Ends the list of after the elements are added.
	 *
	 * @see Walker_Nav_Menu::end_lvl()
	 *
	 * @since 3.0.0
	 *
	 * @param string   $output Passed by reference.
	 * @param int      $depth  Depth of menu item. Used for padding.
	 * @param stdClass $args   Not used.
	 */
	public function end_lvl( &$output, $depth = 0, $args = null ) {}

	/**
	 * Start the element output.
	 *
	 * @see Walker_Nav_Menu::start_el()
	 * @since 3.0.0
	 * @since 5.9.0 Renamed `$item` to `$data_object` and `$id` to `$current_object_id`
	 *              to match parent class for PHP 8 named parameter support.
	 *
	 * @global int $_wp_nav_menu_max_depth
	 *
	 * @param string   $output            Used to append additional content (passed by reference).
	 * @param WP_Post  $data_object       Menu item data object.
	 * @param int      $depth             Depth of menu item. Used for padding.
	 * @param stdClass $args              Not used.
	 * @param int      $current_object_id Optional. ID of the current menu item. Default 0.
	 */
	public function start_el( &$output, $data_object, $depth = 0, $args = null, $current_object_id = 0 ) {
		global $_wp_nav_menu_max_depth;

		// Restores the more descriptive, specific name for use within this method.
		$menu_item = $data_object;

		$_wp_nav_menu_max_depth = $depth > $_wp_nav_menu_max_depth ? $depth : $_wp_nav_menu_max_depth;

		ob_start();
		$item_id      = esc_attr( $menu_item->ID );
		$removed_args = array(
			'action',
			'customlink-tab',
			'edit-menu-item',
			'menu-item',
			'page-tab',
			'_wpnonce',
		);

		$original_title = false;

		if ( 'taxonomy' === $menu_item->type ) {
			$original_object = get_term( (int) $menu_item->object_id, $menu_item->object );
			if ( $original_object && ! is_wp_error( $original_object ) ) {
				$original_title = $original_object->name;
			}
		} elseif ( 'post_type' === $menu_item->type ) {
			$original_object = get_post( $menu_item->object_id );
			if ( $original_object ) {
				$original_title = get_the_title( $original_object->ID );
			}
		} elseif ( 'post_type_archive' === $menu_item->type ) {
			$original_object = get_post_type_object( $menu_item->object );
			if ( $original_object ) {
				$original_title = $original_object->labels->archives;
			}
		}

		$classes = array(
			'menu-item menu-item-depth-' . $depth,
			'menu-item-' . esc_attr( $menu_item->object ),
			'menu-item-edit-' . ( ( isset( $_GET['edit-menu-item'] ) && $item_id === $_GET['edit-menu-item'] ) ? 'active' : 'inactive' ),
		);

		$title = $menu_item->title;

		if ( ! empty( $menu_item->_invalid ) ) {
			$classes[] = 'menu-item-invalid';
			/* translators: %s: Title of an invalid menu item. */
			$title = sprintf( __( '%s (Invalid)' ), $menu_item->title );
		} elseif ( isset( $menu_item->post_status ) && 'draft' === $menu_item->post_status ) {
			$classes[] = 'pending';
			/* translators: %s: Title of a menu item in draft status. */
			$title = sprintf( __( '%s (Pending)' ), $menu_item->title );
		}

		$title = ( ! isset( $menu_item->label ) || '' === $menu_item->label ) ? $title : $menu_item->label;

		$submenu_text = '';
		if ( 0 === $depth ) {
			$submenu_text = 'style="display: none;"';
		}

		?>
		<li id="menu-item-<?php echo $item_id; ?>" class="<?php echo implode( ' ', $classes ); ?>">
			<div class="menu-item-bar">
				<div class="menu-item-handle">
					<label class="item-title" for="menu-item-checkbox-<?php echo $item_id; ?>">
						<input id="menu-item-checkbox-<?php echo $item_id; ?>" type="checkbox" class="menu-item-checkbox" data-menu-item-id="<?php echo $item_id; ?>" disabled="disabled" />
						<span class="menu-item-title"><?php echo esc_html( $title ); ?></span>
						<span class="is-submenu" <?php echo $submenu_text; ?>><?php _e( 'sub item' ); ?></span>
					</label>
					<span class="item-controls">
						<span class="item-type"><?php echo esc_html( $menu_item->type_label ); ?></span>
						<span class="item-order hide-if-js">
							<?php
							printf(
								'<a href="%s" class="item-move-up" aria-label="%s">&#8593;</a>',
								wp_nonce_url(
									add_query_arg(
										array(
											'action'    => 'move-up-menu-item',
											'menu-item' => $item_id,
										),
										remove_query_arg( $removed_args, admin_url( 'nav-menus.php' ) )
									),
									'move-menu_item'
								),
								esc_attr__( 'Move up' )
							);
							?>
							|
							<?php
							printf(
								'<a href="%s" class="item-move-down" aria-label="%s">&#8595;</a>',
								wp_nonce_url(
									add_query_arg(
										array(
											'action'    => 'move-down-menu-item',
											'menu-item' => $item_id,
										),
										remove_query_arg( $removed_args, admin_url( 'nav-menus.php' ) )
									),
									'move-menu_item'
								),
								esc_attr__( 'Move down' )
							);
							?>
						</span>
						<?php
						if ( isset( $_GET['edit-menu-item'] ) && $item_id === $_GET['edit-menu-item'] ) {
							$edit_url = admin_url( 'nav-menus.php' );
						} else {
							$edit_url = add_query_arg(
								array(
									'edit-menu-item' => $item_id,
								),
								remove_query_arg( $removed_args, admin_url( 'nav-menus.php#menu-item-settings-' . $item_id ) )
							);
						}

						printf(
							'<a class="item-edit" id="edit-%s" href="%s" aria-label="%s"><span class="screen-reader-text">%s</span></a>',
							$item_id,
							esc_url( $edit_url ),
							esc_attr__( 'Edit menu item' ),
							/* translators: Hidden accessibility text. */
							__( 'Edit' )
						);
						?>
					</span>
				</div>
			</div>

			<div class="menu-item-settings wp-clearfix" id="menu-item-settings-<?php echo $item_id; ?>">
				<?php if ( 'custom' === $menu_item->type ) : ?>
					<p class="field-url description description-wide">
						<label for="edit-menu-item-url-<?php echo $item_id; ?>">
							<?php _e( 'URL' ); ?><br />
							<input type="text" id="edit-menu-item-url-<?php echo $item_id; ?>" class="widefat code edit-menu-item-url" name="menu-item-url[<?php echo $item_id; ?>]" value="<?php echo esc_url( $menu_item->url ); ?>" />
						</label>
					</p>
				<?php endif; ?>
				<p class="description description-wide">
					<label for="edit-menu-item-title-<?php echo $item_id; ?>">
						<?php _e( 'Navigation Label' ); ?><br />
						<input type="text" id="edit-menu-item-title-<?php echo $item_id; ?>" class="widefat edit-menu-item-title" name="menu-item-title[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $menu_item->title ); ?>" />
					</label>
				</p>
				<p class="field-title-attribute field-attr-title description description-wide">
					<label for="edit-menu-item-attr-title-<?php echo $item_id; ?>">
						<?php _e( 'Title Attribute' ); ?><br />
						<input type="text" id="edit-menu-item-attr-title-<?php echo $item_id; ?>" class="widefat edit-menu-item-attr-title" name="menu-item-attr-title[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $menu_item->post_excerpt ); ?>" />
					</label>
				</p>
				<p class="field-link-target description">
					<label for="edit-menu-item-target-<?php echo $item_id; ?>">
						<input type="checkbox" id="edit-menu-item-target-<?php echo $item_id; ?>" value="_blank" name="menu-item-target[<?php echo $item_id; ?>]"<?php checked( $menu_item->target, '_blank' ); ?> />
						<?php _e( 'Open link in a new tab' ); ?>
					</label>
				</p>
				<div class="description-group">
					<p class="field-css-classes description description-thin">
						<label for="edit-menu-item-classes-<?php echo $item_id; ?>">
							<?php _e( 'CSS Classes (optional)' ); ?><br />
							<input type="text" id="edit-menu-item-classes-<?php echo $item_id; ?>" class="widefat code edit-menu-item-classes" name="menu-item-classes[<?php echo $item_id; ?>]" value="<?php echo esc_attr( implode( ' ', $menu_item->classes ) ); ?>" />
						</label>
					</p>
					<p class="field-xfn description description-thin">
						<label for="edit-menu-item-xfn-<?php echo $item_id; ?>">
							<?php _e( 'Link Relationship (XFN)' ); ?><br />
							<input type="text" id="edit-menu-item-xfn-<?php echo $item_id; ?>" class="widefat code edit-menu-item-xfn" name="menu-item-xfn[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $menu_item->xfn ); ?>" />
						</label>
					</p>
				</div>
				<p class="field-description description description-wide">
					<label for="edit-menu-item-description-<?php echo $item_id; ?>">
						<?php _e( 'Description' ); ?><br />
						<textarea id="edit-menu-item-description-<?php echo $item_id; ?>" class="widefat edit-menu-item-description" rows="3" cols="20" name="menu-item-description[<?php echo $item_id; ?>]"><?php echo esc_html( $menu_item->description ); // textarea_escaped ?></textarea>
						<span class="description"><?php _e( 'The description will be displayed in the menu if the active theme supports it.' ); ?></span>
					</label>
				</p>

				<?php
				/**
				 * Update parent and order of menu item using select inputs.
				 *
				 * @since 6.7.0
				 */
				?>
	
				<div class="field-move-combo description-group">
					<p class="description description-wide">
						<label for="edit-menu-item-parent-<?php echo $item_id; ?>">
							<?php _e( 'Menu Parent' ); ?>
						</label>
						<select class="edit-menu-item-parent widefat" id="edit-menu-item-parent-<?php echo $item_id; ?>" name="menu-item-parent[<?php echo $item_id; ?>]">
						</select>
					</p>
					<p class="description description-wide">
						<label for="edit-menu-item-order-<?php echo $item_id; ?>">
							<?php _e( 'Menu Order' ); ?>
						</label>
						<select class="edit-menu-item-order widefat" id="edit-menu-item-order-<?php echo $item_id; ?>" name="menu-item-order[<?php echo $item_id; ?>]">
						</select>
					</p>
				</div>

				<?php
				/**
				 * Fires just before the move buttons of a nav menu item in the menu editor.
				 *
				 * @since 5.4.0
				 *
				 * @param string        $item_id           Menu item ID as a numeric string.
				 * @param WP_Post       $menu_item         Menu item data object.
				 * @param int           $depth             Depth of menu item. Used for padding.
				 * @param stdClass|null $args              An object of menu item arguments.
				 * @param int           $current_object_id Nav menu ID.
				 */
				do_action( 'wp_nav_menu_item_custom_fields', $item_id, $menu_item, $depth, $args, $current_object_id );
				?>

				<fieldset class="field-move hide-if-no-js description description-wide">
					<span class="field-move-visual-label" aria-hidden="true"><?php _e( 'Move' ); ?></span>
					<button type="button" class="button-link menus-move menus-move-up" data-dir="up"><?php _e( 'Up one' ); ?></button>
					<button type="button" class="button-link menus-move menus-move-down" data-dir="down"><?php _e( 'Down one' ); ?></button>
					<button type="button" class="button-link menus-move menus-move-left" data-dir="left"></button>
					<button type="button" class="button-link menus-move menus-move-right" data-dir="right"></button>
					<button type="button" class="button-link menus-move menus-move-top" data-dir="top"><?php _e( 'To the top' ); ?></button>
				</fieldset>

				<div class="menu-item-actions description-wide submitbox">
					<?php if ( 'custom' !== $menu_item->type && false !== $original_title ) : ?>
						<p class="link-to-original">
							<?php
							/* translators: %s: Link to menu item's original object. */
							printf( __( 'Original: %s' ), '<a href="' . esc_url( $menu_item->url ) . '">' . esc_html( $original_title ) . '</a>' );
							?>
						</p>
					<?php endif; ?>

					<?php
					printf(
						'<a class="item-delete submitdelete deletion" id="delete-%s" href="%s">%s</a>',
						$item_id,
						wp_nonce_url(
							add_query_arg(
								array(
									'action'    => 'delete-menu-item',
									'menu-item' => $item_id,
								),
								admin_url( 'nav-menus.php' )
							),
							'delete-menu_item_' . $item_id
						),
						__( 'Remove' )
					);
					?>
					<span class="meta-sep hide-if-no-js"> | </span>
					<?php
					printf(
						'<a class="item-cancel submitcancel hide-if-no-js" id="cancel-%s" href="%s#menu-item-settings-%s">%s</a>',
						$item_id,
						esc_url(
							add_query_arg(
								array(
									'edit-menu-item' => $item_id,
									'cancel'         => time(),
								),
								admin_url( 'nav-menus.php' )
							)
						),
						$item_id,
						__( 'Cancel' )
					);
					?>
				</div>

				<input class="menu-item-data-db-id" type="hidden" name="menu-item-db-id[<?php echo $item_id; ?>]" value="<?php echo $item_id; ?>" />
				<input class="menu-item-data-object-id" type="hidden" name="menu-item-object-id[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $menu_item->object_id ); ?>" />
				<input class="menu-item-data-object" type="hidden" name="menu-item-object[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $menu_item->object ); ?>" />
				<input class="menu-item-data-parent-id" type="hidden" name="menu-item-parent-id[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $menu_item->menu_item_parent ); ?>" />
				<input class="menu-item-data-position" type="hidden" name="menu-item-position[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $menu_item->menu_order ); ?>" />
				<input class="menu-item-data-type" type="hidden" name="menu-item-type[<?php echo $item_id; ?>]" value="<?php echo esc_attr( $menu_item->type ); ?>" />
			</div><!-- .menu-item-settings-->
			<ul class="menu-item-transport"></ul>
		<?php
		$output .= ob_get_clean();
	}
}class-wp-privacy-policy-content.php000064400000077631151212616050013443 0ustar00<?php
/**
 * WP_Privacy_Policy_Content class.
 *
 * @package WordPress
 * @subpackage Administration
 * @since 4.9.6
 */

#[AllowDynamicProperties]
final class WP_Privacy_Policy_Content {

	private static $policy_content = array();

	/**
	 * Constructor
	 *
	 * @since 4.9.6
	 */
	private function __construct() {}

	/**
	 * Adds content to the postbox shown when editing the privacy policy.
	 *
	 * Plugins and themes should suggest text for inclusion in the site's privacy policy.
	 * The suggested text should contain information about any functionality that affects user privacy,
	 * and will be shown in the Suggested Privacy Policy Content postbox.
	 *
	 * Intended for use from `wp_add_privacy_policy_content()`.
	 *
	 * @since 4.9.6
	 *
	 * @param string $plugin_name The name of the plugin or theme that is suggesting content for the site's privacy policy.
	 * @param string $policy_text The suggested content for inclusion in the policy.
	 */
	public static function add( $plugin_name, $policy_text ) {
		if ( empty( $plugin_name ) || empty( $policy_text ) ) {
			return;
		}

		$data = array(
			'plugin_name' => $plugin_name,
			'policy_text' => $policy_text,
		);

		if ( ! in_array( $data, self::$policy_content, true ) ) {
			self::$policy_content[] = $data;
		}
	}

	/**
	 * Performs a quick check to determine whether any privacy info has changed.
	 *
	 * @since 4.9.6
	 */
	public static function text_change_check() {

		$policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' );

		// The site doesn't have a privacy policy.
		if ( empty( $policy_page_id ) ) {
			return false;
		}

		if ( ! current_user_can( 'edit_post', $policy_page_id ) ) {
			return false;
		}

		$old = (array) get_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content' );

		// Updates are not relevant if the user has not reviewed any suggestions yet.
		if ( empty( $old ) ) {
			return false;
		}

		$cached = get_option( '_wp_suggested_policy_text_has_changed' );

		/*
		 * When this function is called before `admin_init`, `self::$policy_content`
		 * has not been populated yet, so use the cached result from the last
		 * execution instead.
		 */
		if ( ! did_action( 'admin_init' ) ) {
			return 'changed' === $cached;
		}

		$new = self::$policy_content;

		// Remove the extra values added to the meta.
		foreach ( $old as $key => $data ) {
			if ( ! is_array( $data ) || ! empty( $data['removed'] ) ) {
				unset( $old[ $key ] );
				continue;
			}

			$old[ $key ] = array(
				'plugin_name' => $data['plugin_name'],
				'policy_text' => $data['policy_text'],
			);
		}

		// Normalize the order of texts, to facilitate comparison.
		sort( $old );
		sort( $new );

		/*
		 * The == operator (equal, not identical) was used intentionally.
		 * See https://www.php.net/manual/en/language.operators.array.php
		 */
		if ( $new != $old ) {
			/*
			 * A plugin was activated or deactivated, or some policy text has changed.
			 * Show a notice on the relevant screens to inform the admin.
			 */
			add_action( 'admin_notices', array( 'WP_Privacy_Policy_Content', 'policy_text_changed_notice' ) );
			$state = 'changed';
		} else {
			$state = 'not-changed';
		}

		// Cache the result for use before `admin_init` (see above).
		if ( $cached !== $state ) {
			update_option( '_wp_suggested_policy_text_has_changed', $state, false );
		}

		return 'changed' === $state;
	}

	/**
	 * Outputs a warning when some privacy info has changed.
	 *
	 * @since 4.9.6
	 */
	public static function policy_text_changed_notice() {
		$screen = get_current_screen()->id;

		if ( 'privacy' !== $screen ) {
			return;
		}

		$privacy_message = sprintf(
			/* translators: %s: Privacy Policy Guide URL. */
			__( 'The suggested privacy policy text has changed. Please <a href="%s">review the guide</a> and update your privacy policy.' ),
			esc_url( admin_url( 'privacy-policy-guide.php?tab=policyguide' ) )
		);

		wp_admin_notice(
			$privacy_message,
			array(
				'type'               => 'warning',
				'additional_classes' => array( 'policy-text-updated' ),
				'dismissible'        => true,
			)
		);
	}

	/**
	 * Updates the cached policy info when the policy page is updated.
	 *
	 * @since 4.9.6
	 * @access private
	 *
	 * @param int $post_id The ID of the updated post.
	 */
	public static function _policy_page_updated( $post_id ) {
		$policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' );

		if ( ! $policy_page_id || $policy_page_id !== (int) $post_id ) {
			return;
		}

		// Remove updated|removed status.
		$old          = (array) get_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content' );
		$done         = array();
		$update_cache = false;

		foreach ( $old as $old_key => $old_data ) {
			if ( ! empty( $old_data['removed'] ) ) {
				// Remove the old policy text.
				$update_cache = true;
				continue;
			}

			if ( ! empty( $old_data['updated'] ) ) {
				// 'updated' is now 'added'.
				$done[]       = array(
					'plugin_name' => $old_data['plugin_name'],
					'policy_text' => $old_data['policy_text'],
					'added'       => $old_data['updated'],
				);
				$update_cache = true;
			} else {
				$done[] = $old_data;
			}
		}

		if ( $update_cache ) {
			delete_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content' );
			// Update the cache.
			foreach ( $done as $data ) {
				add_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content', $data );
			}
		}
	}

	/**
	 * Checks for updated, added or removed privacy policy information from plugins.
	 *
	 * Caches the current info in post_meta of the policy page.
	 *
	 * @since 4.9.6
	 *
	 * @return array The privacy policy text/information added by core and plugins.
	 */
	public static function get_suggested_policy_text() {
		$policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' );
		$checked        = array();
		$time           = time();
		$update_cache   = false;
		$new            = self::$policy_content;
		$old            = array();

		if ( $policy_page_id ) {
			$old = (array) get_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content' );
		}

		// Check for no-changes and updates.
		foreach ( $new as $new_key => $new_data ) {
			foreach ( $old as $old_key => $old_data ) {
				$found = false;

				if ( $new_data['policy_text'] === $old_data['policy_text'] ) {
					// Use the new plugin name in case it was changed, translated, etc.
					if ( $old_data['plugin_name'] !== $new_data['plugin_name'] ) {
						$old_data['plugin_name'] = $new_data['plugin_name'];
						$update_cache            = true;
					}

					// A plugin was re-activated.
					if ( ! empty( $old_data['removed'] ) ) {
						unset( $old_data['removed'] );
						$old_data['added'] = $time;
						$update_cache      = true;
					}

					$checked[] = $old_data;
					$found     = true;
				} elseif ( $new_data['plugin_name'] === $old_data['plugin_name'] ) {
					// The info for the policy was updated.
					$checked[]    = array(
						'plugin_name' => $new_data['plugin_name'],
						'policy_text' => $new_data['policy_text'],
						'updated'     => $time,
					);
					$found        = true;
					$update_cache = true;
				}

				if ( $found ) {
					unset( $new[ $new_key ], $old[ $old_key ] );
					continue 2;
				}
			}
		}

		if ( ! empty( $new ) ) {
			// A plugin was activated.
			foreach ( $new as $new_data ) {
				if ( ! empty( $new_data['plugin_name'] ) && ! empty( $new_data['policy_text'] ) ) {
					$new_data['added'] = $time;
					$checked[]         = $new_data;
				}
			}
			$update_cache = true;
		}

		if ( ! empty( $old ) ) {
			// A plugin was deactivated.
			foreach ( $old as $old_data ) {
				if ( ! empty( $old_data['plugin_name'] ) && ! empty( $old_data['policy_text'] ) ) {
					$data = array(
						'plugin_name' => $old_data['plugin_name'],
						'policy_text' => $old_data['policy_text'],
						'removed'     => $time,
					);

					$checked[] = $data;
				}
			}
			$update_cache = true;
		}

		if ( $update_cache && $policy_page_id ) {
			delete_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content' );
			// Update the cache.
			foreach ( $checked as $data ) {
				add_post_meta( $policy_page_id, '_wp_suggested_privacy_policy_content', $data );
			}
		}

		return $checked;
	}

	/**
	 * Adds a notice with a link to the guide when editing the privacy policy page.
	 *
	 * @since 4.9.6
	 * @since 5.0.0 The `$post` parameter was made optional.
	 *
	 * @global WP_Post $post Global post object.
	 *
	 * @param WP_Post|null $post The currently edited post. Default null.
	 */
	public static function notice( $post = null ) {
		if ( is_null( $post ) ) {
			global $post;
		} else {
			$post = get_post( $post );
		}

		if ( ! ( $post instanceof WP_Post ) ) {
			return;
		}

		if ( ! current_user_can( 'manage_privacy_options' ) ) {
			return;
		}

		$current_screen = get_current_screen();
		$policy_page_id = (int) get_option( 'wp_page_for_privacy_policy' );

		if ( 'post' !== $current_screen->base || $policy_page_id !== $post->ID ) {
			return;
		}

		$message = __( 'Need help putting together your new Privacy Policy page? Check out the guide for recommendations on what content to include, along with policies suggested by your plugins and theme.' );
		$url     = esc_url( admin_url( 'options-privacy.php?tab=policyguide' ) );
		$label   = __( 'View Privacy Policy Guide.' );

		if ( get_current_screen()->is_block_editor() ) {
			wp_enqueue_script( 'wp-notices' );
			$action = array(
				'url'   => $url,
				'label' => $label,
			);
			wp_add_inline_script(
				'wp-notices',
				sprintf(
					'wp.data.dispatch( "core/notices" ).createWarningNotice( "%s", { actions: [ %s ], isDismissible: false } )',
					$message,
					wp_json_encode( $action, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES )
				),
				'after'
			);
		} else {
			$message .= sprintf(
				' <a href="%s" target="_blank">%s <span class="screen-reader-text">%s</span></a>',
				$url,
				$label,
				/* translators: Hidden accessibility text. */
				__( '(opens in a new tab)' )
			);
			wp_admin_notice(
				$message,
				array(
					'type'               => 'warning',
					'additional_classes' => array( 'inline', 'wp-pp-notice' ),
				)
			);
		}
	}

	/**
	 * Outputs the privacy policy guide together with content from the theme and plugins.
	 *
	 * @since 4.9.6
	 */
	public static function privacy_policy_guide() {

		$content_array = self::get_suggested_policy_text();
		$date_format   = __( 'F j, Y' );

		$i = 0;

		foreach ( $content_array as $section ) {
			++$i;

			$removed = '';
			if ( ! empty( $section['removed'] ) ) {
				$badge_class = ' red';
				$date        = date_i18n( $date_format, $section['removed'] );
				/* translators: %s: Date of plugin deactivation. */
				$badge_title = sprintf( __( 'Removed %s.' ), $date );

				/* translators: %s: Date of plugin deactivation. */
				$removed = sprintf( __( 'You deactivated this plugin on %s and may no longer need this policy.' ), $date );
				$removed = wp_get_admin_notice(
					$removed,
					array(
						'type'               => 'info',
						'additional_classes' => array( 'inline' ),
					)
				);
			} elseif ( ! empty( $section['updated'] ) ) {
				$badge_class = ' blue';
				$date        = date_i18n( $date_format, $section['updated'] );
				/* translators: %s: Date of privacy policy text update. */
				$badge_title = sprintf( __( 'Updated %s.' ), $date );
			}

			$plugin_name = esc_html( $section['plugin_name'] );
			?>
			<h4 class="privacy-settings-accordion-heading">
				<button aria-expanded="false" class="privacy-settings-accordion-trigger" aria-controls="privacy-settings-accordion-block-<?php echo $i; ?>" type="button">
				<span class="title"><?php echo $plugin_name; ?></span>
				<?php if ( ! empty( $section['removed'] ) || ! empty( $section['updated'] ) ) : ?>
				<span class="badge <?php echo $badge_class; ?>"> <?php echo $badge_title; ?></span>
				<?php endif; ?>
				<span class="icon"></span>
			</button>
			</h4>
			<div id="privacy-settings-accordion-block-<?php echo $i; ?>" class="privacy-settings-accordion-panel privacy-text-box-body" hidden="hidden">
				<?php
				echo $removed;
				echo $section['policy_text'];
				?>
				<?php if ( empty( $section['removed'] ) ) : ?>
				<div class="privacy-settings-accordion-actions">
					<span class="success" aria-hidden="true"><?php _e( 'Copied!' ); ?></span>
					<button type="button" class="privacy-text-copy button">
						<span aria-hidden="true"><?php _e( 'Copy suggested policy text to clipboard' ); ?></span>
						<span class="screen-reader-text">
							<?php
							/* translators: Hidden accessibility text. %s: Plugin name. */
							printf( __( 'Copy suggested policy text from %s.' ), $plugin_name );
							?>
						</span>
					</button>
				</div>
				<?php endif; ?>
			</div>
			<?php
		}
	}

	/**
	 * Returns the default suggested privacy policy content.
	 *
	 * @since 4.9.6
	 * @since 5.0.0 Added the `$blocks` parameter.
	 *
	 * @param bool $description Whether to include the descriptions under the section headings. Default false.
	 * @param bool $blocks      Whether to format the content for the block editor. Default true.
	 * @return string The default policy content.
	 */
	public static function get_default_content( $description = false, $blocks = true ) {
		$suggested_text = '<strong class="privacy-policy-tutorial">' . __( 'Suggested text:' ) . ' </strong>';
		$content        = '';
		$strings        = array();

		// Start of the suggested privacy policy text.
		if ( $description ) {
			$strings[] = '<div class="wp-suggested-text">';
		}

		/* translators: Default privacy policy heading. */
		$strings[] = '<h2 class="wp-block-heading">' . __( 'Who we are' ) . '</h2>';

		if ( $description ) {
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this section you should note your site URL, as well as the name of the company, organization, or individual behind it, and some accurate contact information.' ) . '</p>';
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'The amount of information you may be required to show will vary depending on your local or national business regulations. You may, for example, be required to display a physical address, a registered address, or your company registration number.' ) . '</p>';
		} else {
			/* translators: Default privacy policy text. %s: Site URL. */
			$strings[] = '<p>' . $suggested_text . sprintf( __( 'Our website address is: %s.' ), get_bloginfo( 'url', 'display' ) ) . '</p>';
		}

		if ( $description ) {
			/* translators: Default privacy policy heading. */
			$strings[] = '<h2>' . __( 'What personal data we collect and why we collect it' ) . '</h2>';
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this section you should note what personal data you collect from users and site visitors. This may include personal data, such as name, email address, personal account preferences; transactional data, such as purchase information; and technical data, such as information about cookies.' ) . '</p>';
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'You should also note any collection and retention of sensitive personal data, such as data concerning health.' ) . '</p>';
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In addition to listing what personal data you collect, you need to note why you collect it. These explanations must note either the legal basis for your data collection and retention or the active consent the user has given.' ) . '</p>';
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'Personal data is not just created by a user&#8217;s interactions with your site. Personal data is also generated from technical processes such as contact forms, comments, cookies, analytics, and third party embeds.' ) . '</p>';
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'By default WordPress does not collect any personal data about visitors, and only collects the data shown on the User Profile screen from registered users. However some of your plugins may collect personal data. You should add the relevant information below.' ) . '</p>';
		}

		/* translators: Default privacy policy heading. */
		$strings[] = '<h2 class="wp-block-heading">' . __( 'Comments' ) . '</h2>';

		if ( $description ) {
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this subsection you should note what information is captured through comments. We have noted the data which WordPress collects by default.' ) . '</p>';
		} else {
			/* translators: Default privacy policy text. */
			$strings[] = '<p>' . $suggested_text . __( 'When visitors leave comments on the site we collect the data shown in the comments form, and also the visitor&#8217;s IP address and browser user agent string to help spam detection.' ) . '</p>';
			/* translators: Default privacy policy text. */
			$strings[] = '<p>' . __( 'An anonymized string created from your email address (also called a hash) may be provided to the Gravatar service to see if you are using it. The Gravatar service privacy policy is available here: https://automattic.com/privacy/. After approval of your comment, your profile picture is visible to the public in the context of your comment.' ) . '</p>';
		}

		/* translators: Default privacy policy heading. */
		$strings[] = '<h2 class="wp-block-heading">' . __( 'Media' ) . '</h2>';

		if ( $description ) {
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this subsection you should note what information may be disclosed by users who can upload media files. All uploaded files are usually publicly accessible.' ) . '</p>';
		} else {
			/* translators: Default privacy policy text. */
			$strings[] = '<p>' . $suggested_text . __( 'If you upload images to the website, you should avoid uploading images with embedded location data (EXIF GPS) included. Visitors to the website can download and extract any location data from images on the website.' ) . '</p>';
		}

		if ( $description ) {
			/* translators: Default privacy policy heading. */
			$strings[] = '<h2>' . __( 'Contact forms' ) . '</h2>';
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'By default, WordPress does not include a contact form. If you use a contact form plugin, use this subsection to note what personal data is captured when someone submits a contact form, and how long you keep it. For example, you may note that you keep contact form submissions for a certain period for customer service purposes, but you do not use the information submitted through them for marketing purposes.' ) . '</p>';
		}

		/* translators: Default privacy policy heading. */
		$strings[] = '<h2 class="wp-block-heading">' . __( 'Cookies' ) . '</h2>';

		if ( $description ) {
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this subsection you should list the cookies your website uses, including those set by your plugins, social media, and analytics. We have provided the cookies which WordPress installs by default.' ) . '</p>';
		} else {
			/* translators: Default privacy policy text. */
			$strings[] = '<p>' . $suggested_text . __( 'If you leave a comment on our site you may opt-in to saving your name, email address and website in cookies. These are for your convenience so that you do not have to fill in your details again when you leave another comment. These cookies will last for one year.' ) . '</p>';
			/* translators: Default privacy policy text. */
			$strings[] = '<p>' . __( 'If you visit our login page, we will set a temporary cookie to determine if your browser accepts cookies. This cookie contains no personal data and is discarded when you close your browser.' ) . '</p>';
			/* translators: Default privacy policy text. */
			$strings[] = '<p>' . __( 'When you log in, we will also set up several cookies to save your login information and your screen display choices. Login cookies last for two days, and screen options cookies last for a year. If you select &quot;Remember Me&quot;, your login will persist for two weeks. If you log out of your account, the login cookies will be removed.' ) . '</p>';
			/* translators: Default privacy policy text. */
			$strings[] = '<p>' . __( 'If you edit or publish an article, an additional cookie will be saved in your browser. This cookie includes no personal data and simply indicates the post ID of the article you just edited. It expires after 1 day.' ) . '</p>';
		}

		if ( ! $description ) {
			/* translators: Default privacy policy heading. */
			$strings[] = '<h2 class="wp-block-heading">' . __( 'Embedded content from other websites' ) . '</h2>';
			/* translators: Default privacy policy text. */
			$strings[] = '<p>' . $suggested_text . __( 'Articles on this site may include embedded content (e.g. videos, images, articles, etc.). Embedded content from other websites behaves in the exact same way as if the visitor has visited the other website.' ) . '</p>';
			/* translators: Default privacy policy text. */
			$strings[] = '<p>' . __( 'These websites may collect data about you, use cookies, embed additional third-party tracking, and monitor your interaction with that embedded content, including tracking your interaction with the embedded content if you have an account and are logged in to that website.' ) . '</p>';
		}

		if ( $description ) {
			/* translators: Default privacy policy heading. */
			$strings[] = '<h2>' . __( 'Analytics' ) . '</h2>';
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this subsection you should note what analytics package you use, how users can opt out of analytics tracking, and a link to your analytics provider&#8217;s privacy policy, if any.' ) . '</p>';
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'By default WordPress does not collect any analytics data. However, many web hosting accounts collect some anonymous analytics data. You may also have installed a WordPress plugin that provides analytics services. In that case, add information from that plugin here.' ) . '</p>';
		}

		/* translators: Default privacy policy heading. */
		$strings[] = '<h2 class="wp-block-heading">' . __( 'Who we share your data with' ) . '</h2>';

		if ( $description ) {
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this section you should name and list all third party providers with whom you share site data, including partners, cloud-based services, payment processors, and third party service providers, and note what data you share with them and why. Link to their own privacy policies if possible.' ) . '</p>';
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'By default WordPress does not share any personal data with anyone.' ) . '</p>';
		} else {
			/* translators: Default privacy policy text. */
			$strings[] = '<p>' . $suggested_text . __( 'If you request a password reset, your IP address will be included in the reset email.' ) . '</p>';
		}

		/* translators: Default privacy policy heading. */
		$strings[] = '<h2 class="wp-block-heading">' . __( 'How long we retain your data' ) . '</h2>';

		if ( $description ) {
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this section you should explain how long you retain personal data collected or processed by the website. While it is your responsibility to come up with the schedule of how long you keep each dataset for and why you keep it, that information does need to be listed here. For example, you may want to say that you keep contact form entries for six months, analytics records for a year, and customer purchase records for ten years.' ) . '</p>';
		} else {
			/* translators: Default privacy policy text. */
			$strings[] = '<p>' . $suggested_text . __( 'If you leave a comment, the comment and its metadata are retained indefinitely. This is so we can recognize and approve any follow-up comments automatically instead of holding them in a moderation queue.' ) . '</p>';
			/* translators: Default privacy policy text. */
			$strings[] = '<p>' . __( 'For users that register on our website (if any), we also store the personal information they provide in their user profile. All users can see, edit, or delete their personal information at any time (except they cannot change their username). Website administrators can also see and edit that information.' ) . '</p>';
		}

		/* translators: Default privacy policy heading. */
		$strings[] = '<h2 class="wp-block-heading">' . __( 'What rights you have over your data' ) . '</h2>';

		if ( $description ) {
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this section you should explain what rights your users have over their data and how they can invoke those rights.' ) . '</p>';
		} else {
			/* translators: Default privacy policy text. */
			$strings[] = '<p>' . $suggested_text . __( 'If you have an account on this site, or have left comments, you can request to receive an exported file of the personal data we hold about you, including any data you have provided to us. You can also request that we erase any personal data we hold about you. This does not include any data we are obliged to keep for administrative, legal, or security purposes.' ) . '</p>';
		}

		/* translators: Default privacy policy heading. */
		$strings[] = '<h2 class="wp-block-heading">' . __( 'Where your data is sent' ) . '</h2>';

		if ( $description ) {
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this section you should list all transfers of your site data outside the European Union and describe the means by which that data is safeguarded to European data protection standards. This could include your web hosting, cloud storage, or other third party services.' ) . '</p>';
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'European data protection law requires data about European residents which is transferred outside the European Union to be safeguarded to the same standards as if the data was in Europe. So in addition to listing where data goes, you should describe how you ensure that these standards are met either by yourself or by your third party providers, whether that is through an agreement such as Privacy Shield, model clauses in your contracts, or binding corporate rules.' ) . '</p>';
		} else {
			/* translators: Default privacy policy text. */
			$strings[] = '<p>' . $suggested_text . __( 'Visitor comments may be checked through an automated spam detection service.' ) . '</p>';
		}

		if ( $description ) {
			/* translators: Default privacy policy heading. */
			$strings[] = '<h2>' . __( 'Contact information' ) . '</h2>';
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this section you should provide a contact method for privacy-specific concerns. If you are required to have a Data Protection Officer, list their name and full contact details here as well.' ) . '</p>';
		}

		if ( $description ) {
			/* translators: Default privacy policy heading. */
			$strings[] = '<h2>' . __( 'Additional information' ) . '</h2>';
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'If you use your site for commercial purposes and you engage in more complex collection or processing of personal data, you should note the following information in your privacy policy in addition to the information we have already discussed.' ) . '</p>';
		}

		if ( $description ) {
			/* translators: Default privacy policy heading. */
			$strings[] = '<h2>' . __( 'How we protect your data' ) . '</h2>';
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this section you should explain what measures you have taken to protect your users&#8217; data. This could include technical measures such as encryption; security measures such as two factor authentication; and measures such as staff training in data protection. If you have carried out a Privacy Impact Assessment, you can mention it here too.' ) . '</p>';
		}

		if ( $description ) {
			/* translators: Default privacy policy heading. */
			$strings[] = '<h2>' . __( 'What data breach procedures we have in place' ) . '</h2>';
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'In this section you should explain what procedures you have in place to deal with data breaches, either potential or real, such as internal reporting systems, contact mechanisms, or bug bounties.' ) . '</p>';
		}

		if ( $description ) {
			/* translators: Default privacy policy heading. */
			$strings[] = '<h2>' . __( 'What third parties we receive data from' ) . '</h2>';
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'If your website receives data about users from third parties, including advertisers, this information must be included within the section of your privacy policy dealing with third party data.' ) . '</p>';
		}

		if ( $description ) {
			/* translators: Default privacy policy heading. */
			$strings[] = '<h2>' . __( 'What automated decision making and/or profiling we do with user data' ) . '</h2>';
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'If your website provides a service which includes automated decision making - for example, allowing customers to apply for credit, or aggregating their data into an advertising profile - you must note that this is taking place, and include information about how that information is used, what decisions are made with that aggregated data, and what rights users have over decisions made without human intervention.' ) . '</p>';
		}

		if ( $description ) {
			/* translators: Default privacy policy heading. */
			$strings[] = '<h2>' . __( 'Industry regulatory disclosure requirements' ) . '</h2>';
			/* translators: Privacy policy tutorial. */
			$strings[] = '<p class="privacy-policy-tutorial">' . __( 'If you are a member of a regulated industry, or if you are subject to additional privacy laws, you may be required to disclose that information here.' ) . '</p>';
			$strings[] = '</div>';
		}

		if ( $blocks ) {
			foreach ( $strings as $key => $string ) {
				if ( str_starts_with( $string, '<p>' ) ) {
					$strings[ $key ] = "<!-- wp:paragraph -->\n" . $string . "\n<!-- /wp:paragraph -->\n";
				}

				if ( str_starts_with( $string, '<h2 ' ) ) {
					$strings[ $key ] = "<!-- wp:heading -->\n" . $string . "\n<!-- /wp:heading -->\n";
				}
			}
		}

		$content = implode( '', $strings );
		// End of the suggested privacy policy text.

		/**
		 * Filters the default content suggested for inclusion in a privacy policy.
		 *
		 * @since 4.9.6
		 * @since 5.0.0 Added the `$strings`, `$description`, and `$blocks` parameters.
		 * @deprecated 5.7.0 Use wp_add_privacy_policy_content() instead.
		 *
		 * @param string   $content     The default policy content.
		 * @param string[] $strings     An array of privacy policy content strings.
		 * @param bool     $description Whether policy descriptions should be included.
		 * @param bool     $blocks      Whether the content should be formatted for the block editor.
		 */
		return apply_filters_deprecated(
			'wp_get_default_privacy_policy_content',
			array( $content, $strings, $description, $blocks ),
			'5.7.0',
			'wp_add_privacy_policy_content()'
		);
	}

	/**
	 * Adds the suggested privacy policy text to the policy postbox.
	 *
	 * @since 4.9.6
	 */
	public static function add_suggested_content() {
		$content = self::get_default_content( false, false );
		wp_add_privacy_policy_content( __( 'WordPress' ), $content );
	}
}
schema.php000064400000130731151212616050006521 0ustar00<?php
/**
 * WordPress Administration Scheme API
 *
 * Here we keep the DB structure and option values.
 *
 * @package WordPress
 * @subpackage Administration
 */

/**
 * Declare these as global in case schema.php is included from a function.
 *
 * @global wpdb   $wpdb            WordPress database abstraction object.
 * @global array  $wp_queries
 * @global string $charset_collate
 */
global $wpdb, $wp_queries, $charset_collate;

/**
 * The database character collate.
 */
$charset_collate = $wpdb->get_charset_collate();

/**
 * Retrieve the SQL for creating database tables.
 *
 * @since 3.3.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param string $scope   Optional. The tables for which to retrieve SQL. Can be all, global, ms_global, or blog tables. Defaults to all.
 * @param int    $blog_id Optional. The site ID for which to retrieve SQL. Default is the current site ID.
 * @return string The SQL needed to create the requested tables.
 */
function wp_get_db_schema( $scope = 'all', $blog_id = null ) {
	global $wpdb;

	$charset_collate = $wpdb->get_charset_collate();

	if ( $blog_id && (int) $blog_id !== $wpdb->blogid ) {
		$old_blog_id = $wpdb->set_blog_id( $blog_id );
	}

	// Engage multisite if in the middle of turning it on from network.php.
	$is_multisite = is_multisite() || ( defined( 'WP_INSTALLING_NETWORK' ) && WP_INSTALLING_NETWORK );

	/*
	 * Indexes have a maximum size of 767 bytes. Historically, we haven't need to be concerned about that.
	 * As of 4.2, however, we moved to utf8mb4, which uses 4 bytes per character. This means that an index which
	 * used to have room for floor(767/3) = 255 characters, now only has room for floor(767/4) = 191 characters.
	 */
	$max_index_length = 191;

	// Blog-specific tables.
	$blog_tables = "CREATE TABLE $wpdb->termmeta (
	meta_id bigint(20) unsigned NOT NULL auto_increment,
	term_id bigint(20) unsigned NOT NULL default '0',
	meta_key varchar(255) default NULL,
	meta_value longtext,
	PRIMARY KEY  (meta_id),
	KEY term_id (term_id),
	KEY meta_key (meta_key($max_index_length))
) $charset_collate;
CREATE TABLE $wpdb->terms (
 term_id bigint(20) unsigned NOT NULL auto_increment,
 name varchar(200) NOT NULL default '',
 slug varchar(200) NOT NULL default '',
 term_group bigint(10) NOT NULL default 0,
 PRIMARY KEY  (term_id),
 KEY slug (slug($max_index_length)),
 KEY name (name($max_index_length))
) $charset_collate;
CREATE TABLE $wpdb->term_taxonomy (
 term_taxonomy_id bigint(20) unsigned NOT NULL auto_increment,
 term_id bigint(20) unsigned NOT NULL default 0,
 taxonomy varchar(32) NOT NULL default '',
 description longtext NOT NULL,
 parent bigint(20) unsigned NOT NULL default 0,
 count bigint(20) NOT NULL default 0,
 PRIMARY KEY  (term_taxonomy_id),
 UNIQUE KEY term_id_taxonomy (term_id,taxonomy),
 KEY taxonomy (taxonomy)
) $charset_collate;
CREATE TABLE $wpdb->term_relationships (
 object_id bigint(20) unsigned NOT NULL default 0,
 term_taxonomy_id bigint(20) unsigned NOT NULL default 0,
 term_order int(11) NOT NULL default 0,
 PRIMARY KEY  (object_id,term_taxonomy_id),
 KEY term_taxonomy_id (term_taxonomy_id)
) $charset_collate;
CREATE TABLE $wpdb->commentmeta (
	meta_id bigint(20) unsigned NOT NULL auto_increment,
	comment_id bigint(20) unsigned NOT NULL default '0',
	meta_key varchar(255) default NULL,
	meta_value longtext,
	PRIMARY KEY  (meta_id),
	KEY comment_id (comment_id),
	KEY meta_key (meta_key($max_index_length))
) $charset_collate;
CREATE TABLE $wpdb->comments (
	comment_ID bigint(20) unsigned NOT NULL auto_increment,
	comment_post_ID bigint(20) unsigned NOT NULL default '0',
	comment_author tinytext NOT NULL,
	comment_author_email varchar(100) NOT NULL default '',
	comment_author_url varchar(200) NOT NULL default '',
	comment_author_IP varchar(100) NOT NULL default '',
	comment_date datetime NOT NULL default '0000-00-00 00:00:00',
	comment_date_gmt datetime NOT NULL default '0000-00-00 00:00:00',
	comment_content text NOT NULL,
	comment_karma int(11) NOT NULL default '0',
	comment_approved varchar(20) NOT NULL default '1',
	comment_agent varchar(255) NOT NULL default '',
	comment_type varchar(20) NOT NULL default 'comment',
	comment_parent bigint(20) unsigned NOT NULL default '0',
	user_id bigint(20) unsigned NOT NULL default '0',
	PRIMARY KEY  (comment_ID),
	KEY comment_post_ID (comment_post_ID),
	KEY comment_approved_date_gmt (comment_approved,comment_date_gmt),
	KEY comment_date_gmt (comment_date_gmt),
	KEY comment_parent (comment_parent),
	KEY comment_author_email (comment_author_email(10))
) $charset_collate;
CREATE TABLE $wpdb->links (
	link_id bigint(20) unsigned NOT NULL auto_increment,
	link_url varchar(255) NOT NULL default '',
	link_name varchar(255) NOT NULL default '',
	link_image varchar(255) NOT NULL default '',
	link_target varchar(25) NOT NULL default '',
	link_description varchar(255) NOT NULL default '',
	link_visible varchar(20) NOT NULL default 'Y',
	link_owner bigint(20) unsigned NOT NULL default '1',
	link_rating int(11) NOT NULL default '0',
	link_updated datetime NOT NULL default '0000-00-00 00:00:00',
	link_rel varchar(255) NOT NULL default '',
	link_notes mediumtext NOT NULL,
	link_rss varchar(255) NOT NULL default '',
	PRIMARY KEY  (link_id),
	KEY link_visible (link_visible)
) $charset_collate;
CREATE TABLE $wpdb->options (
	option_id bigint(20) unsigned NOT NULL auto_increment,
	option_name varchar(191) NOT NULL default '',
	option_value longtext NOT NULL,
	autoload varchar(20) NOT NULL default 'yes',
	PRIMARY KEY  (option_id),
	UNIQUE KEY option_name (option_name),
	KEY autoload (autoload)
) $charset_collate;
CREATE TABLE $wpdb->postmeta (
	meta_id bigint(20) unsigned NOT NULL auto_increment,
	post_id bigint(20) unsigned NOT NULL default '0',
	meta_key varchar(255) default NULL,
	meta_value longtext,
	PRIMARY KEY  (meta_id),
	KEY post_id (post_id),
	KEY meta_key (meta_key($max_index_length))
) $charset_collate;
CREATE TABLE $wpdb->posts (
	ID bigint(20) unsigned NOT NULL auto_increment,
	post_author bigint(20) unsigned NOT NULL default '0',
	post_date datetime NOT NULL default '0000-00-00 00:00:00',
	post_date_gmt datetime NOT NULL default '0000-00-00 00:00:00',
	post_content longtext NOT NULL,
	post_title text NOT NULL,
	post_excerpt text NOT NULL,
	post_status varchar(20) NOT NULL default 'publish',
	comment_status varchar(20) NOT NULL default 'open',
	ping_status varchar(20) NOT NULL default 'open',
	post_password varchar(255) NOT NULL default '',
	post_name varchar(200) NOT NULL default '',
	to_ping text NOT NULL,
	pinged text NOT NULL,
	post_modified datetime NOT NULL default '0000-00-00 00:00:00',
	post_modified_gmt datetime NOT NULL default '0000-00-00 00:00:00',
	post_content_filtered longtext NOT NULL,
	post_parent bigint(20) unsigned NOT NULL default '0',
	guid varchar(255) NOT NULL default '',
	menu_order int(11) NOT NULL default '0',
	post_type varchar(20) NOT NULL default 'post',
	post_mime_type varchar(100) NOT NULL default '',
	comment_count bigint(20) NOT NULL default '0',
	PRIMARY KEY  (ID),
	KEY post_name (post_name($max_index_length)),
	KEY type_status_date (post_type,post_status,post_date,ID),
	KEY post_parent (post_parent),
	KEY post_author (post_author),
	KEY type_status_author (post_type,post_status,post_author)
) $charset_collate;\n";

	// Single site users table. The multisite flavor of the users table is handled below.
	$users_single_table = "CREATE TABLE $wpdb->users (
	ID bigint(20) unsigned NOT NULL auto_increment,
	user_login varchar(60) NOT NULL default '',
	user_pass varchar(255) NOT NULL default '',
	user_nicename varchar(50) NOT NULL default '',
	user_email varchar(100) NOT NULL default '',
	user_url varchar(100) NOT NULL default '',
	user_registered datetime NOT NULL default '0000-00-00 00:00:00',
	user_activation_key varchar(255) NOT NULL default '',
	user_status int(11) NOT NULL default '0',
	display_name varchar(250) NOT NULL default '',
	PRIMARY KEY  (ID),
	KEY user_login_key (user_login),
	KEY user_nicename (user_nicename),
	KEY user_email (user_email)
) $charset_collate;\n";

	// Multisite users table.
	$users_multi_table = "CREATE TABLE $wpdb->users (
	ID bigint(20) unsigned NOT NULL auto_increment,
	user_login varchar(60) NOT NULL default '',
	user_pass varchar(255) NOT NULL default '',
	user_nicename varchar(50) NOT NULL default '',
	user_email varchar(100) NOT NULL default '',
	user_url varchar(100) NOT NULL default '',
	user_registered datetime NOT NULL default '0000-00-00 00:00:00',
	user_activation_key varchar(255) NOT NULL default '',
	user_status int(11) NOT NULL default '0',
	display_name varchar(250) NOT NULL default '',
	spam tinyint(2) NOT NULL default '0',
	deleted tinyint(2) NOT NULL default '0',
	PRIMARY KEY  (ID),
	KEY user_login_key (user_login),
	KEY user_nicename (user_nicename),
	KEY user_email (user_email)
) $charset_collate;\n";

	// Usermeta.
	$usermeta_table = "CREATE TABLE $wpdb->usermeta (
	umeta_id bigint(20) unsigned NOT NULL auto_increment,
	user_id bigint(20) unsigned NOT NULL default '0',
	meta_key varchar(255) default NULL,
	meta_value longtext,
	PRIMARY KEY  (umeta_id),
	KEY user_id (user_id),
	KEY meta_key (meta_key($max_index_length))
) $charset_collate;\n";

	// Global tables.
	if ( $is_multisite ) {
		$global_tables = $users_multi_table . $usermeta_table;
	} else {
		$global_tables = $users_single_table . $usermeta_table;
	}

	// Multisite global tables.
	$ms_global_tables = "CREATE TABLE $wpdb->blogs (
	blog_id bigint(20) unsigned NOT NULL auto_increment,
	site_id bigint(20) unsigned NOT NULL default '0',
	domain varchar(200) NOT NULL default '',
	path varchar(100) NOT NULL default '',
	registered datetime NOT NULL default '0000-00-00 00:00:00',
	last_updated datetime NOT NULL default '0000-00-00 00:00:00',
	public tinyint(2) NOT NULL default '1',
	archived tinyint(2) NOT NULL default '0',
	mature tinyint(2) NOT NULL default '0',
	spam tinyint(2) NOT NULL default '0',
	deleted tinyint(2) NOT NULL default '0',
	lang_id int(11) NOT NULL default '0',
	PRIMARY KEY  (blog_id),
	KEY domain (domain(50),path(5)),
	KEY lang_id (lang_id)
) $charset_collate;
CREATE TABLE $wpdb->blogmeta (
	meta_id bigint(20) unsigned NOT NULL auto_increment,
	blog_id bigint(20) unsigned NOT NULL default '0',
	meta_key varchar(255) default NULL,
	meta_value longtext,
	PRIMARY KEY  (meta_id),
	KEY meta_key (meta_key($max_index_length)),
	KEY blog_id (blog_id)
) $charset_collate;
CREATE TABLE $wpdb->registration_log (
	ID bigint(20) unsigned NOT NULL auto_increment,
	email varchar(255) NOT NULL default '',
	IP varchar(30) NOT NULL default '',
	blog_id bigint(20) unsigned NOT NULL default '0',
	date_registered datetime NOT NULL default '0000-00-00 00:00:00',
	PRIMARY KEY  (ID),
	KEY IP (IP)
) $charset_collate;
CREATE TABLE $wpdb->site (
	id bigint(20) unsigned NOT NULL auto_increment,
	domain varchar(200) NOT NULL default '',
	path varchar(100) NOT NULL default '',
	PRIMARY KEY  (id),
	KEY domain (domain(140),path(51))
) $charset_collate;
CREATE TABLE $wpdb->sitemeta (
	meta_id bigint(20) unsigned NOT NULL auto_increment,
	site_id bigint(20) unsigned NOT NULL default '0',
	meta_key varchar(255) default NULL,
	meta_value longtext,
	PRIMARY KEY  (meta_id),
	KEY meta_key (meta_key($max_index_length)),
	KEY site_id (site_id)
) $charset_collate;
CREATE TABLE $wpdb->signups (
	signup_id bigint(20) unsigned NOT NULL auto_increment,
	domain varchar(200) NOT NULL default '',
	path varchar(100) NOT NULL default '',
	title longtext NOT NULL,
	user_login varchar(60) NOT NULL default '',
	user_email varchar(100) NOT NULL default '',
	registered datetime NOT NULL default '0000-00-00 00:00:00',
	activated datetime NOT NULL default '0000-00-00 00:00:00',
	active tinyint(1) NOT NULL default '0',
	activation_key varchar(50) NOT NULL default '',
	meta longtext,
	PRIMARY KEY  (signup_id),
	KEY activation_key (activation_key),
	KEY user_email (user_email),
	KEY user_login_email (user_login,user_email),
	KEY domain_path (domain(140),path(51))
) $charset_collate;";

	switch ( $scope ) {
		case 'blog':
			$queries = $blog_tables;
			break;
		case 'global':
			$queries = $global_tables;
			if ( $is_multisite ) {
				$queries .= $ms_global_tables;
			}
			break;
		case 'ms_global':
			$queries = $ms_global_tables;
			break;
		case 'all':
		default:
			$queries = $global_tables . $blog_tables;
			if ( $is_multisite ) {
				$queries .= $ms_global_tables;
			}
			break;
	}

	if ( isset( $old_blog_id ) ) {
		$wpdb->set_blog_id( $old_blog_id );
	}

	return $queries;
}

// Populate for back compat.
$wp_queries = wp_get_db_schema( 'all' );

/**
 * Create WordPress options and set the default values.
 *
 * @since 1.5.0
 * @since 5.1.0 The $options parameter has been added.
 *
 * @global wpdb $wpdb                  WordPress database abstraction object.
 * @global int  $wp_db_version         WordPress database version.
 * @global int  $wp_current_db_version The old (current) database version.
 *
 * @param array $options Optional. Custom option $key => $value pairs to use. Default empty array.
 */
function populate_options( array $options = array() ) {
	global $wpdb, $wp_db_version, $wp_current_db_version;

	$guessurl = wp_guess_url();
	/**
	 * Fires before creating WordPress options and populating their default values.
	 *
	 * @since 2.6.0
	 */
	do_action( 'populate_options' );

	// If WP_DEFAULT_THEME doesn't exist, fall back to the latest core default theme.
	$stylesheet = WP_DEFAULT_THEME;
	$template   = WP_DEFAULT_THEME;
	$theme      = wp_get_theme( WP_DEFAULT_THEME );
	if ( ! $theme->exists() ) {
		$theme = WP_Theme::get_core_default_theme();
	}

	// If we can't find a core default theme, WP_DEFAULT_THEME is the best we can do.
	if ( $theme ) {
		$stylesheet = $theme->get_stylesheet();
		$template   = $theme->get_template();
	}

	$timezone_string = '';
	$gmt_offset      = 0;
	/*
	 * translators: default GMT offset or timezone string. Must be either a valid offset (-12 to 14)
	 * or a valid timezone string (America/New_York). See https://www.php.net/manual/en/timezones.php
	 * for all timezone strings currently supported by PHP.
	 *
	 * Important: When a previous timezone string, like `Europe/Kiev`, has been superseded by an
	 * updated one, like `Europe/Kyiv`, as a rule of thumb, the **old** timezone name should be used
	 * in the "translation" to allow for the default timezone setting to be PHP cross-version compatible,
	 * as old timezone names will be recognized in new PHP versions, while new timezone names cannot
	 * be recognized in old PHP versions.
	 *
	 * To verify which timezone strings are available in the _oldest_ PHP version supported, you can
	 * use https://3v4l.org/6YQAt#v5.6.20 and replace the "BR" (Brazil) in the code line with the
	 * country code for which you want to look up the supported timezone names.
	 */
	$offset_or_tz = _x( '0', 'default GMT offset or timezone string' );
	if ( is_numeric( $offset_or_tz ) ) {
		$gmt_offset = $offset_or_tz;
	} elseif ( $offset_or_tz && in_array( $offset_or_tz, timezone_identifiers_list( DateTimeZone::ALL_WITH_BC ), true ) ) {
		$timezone_string = $offset_or_tz;
	}

	$defaults = array(
		'siteurl'                         => $guessurl,
		'home'                            => $guessurl,
		'blogname'                        => __( 'My Site' ),
		'blogdescription'                 => '',
		'users_can_register'              => 0,
		'admin_email'                     => 'you@example.com',
		/* translators: Default start of the week. 0 = Sunday, 1 = Monday. */
		'start_of_week'                   => _x( '1', 'start of week' ),
		'use_balanceTags'                 => 0,
		'use_smilies'                     => 1,
		'require_name_email'              => 1,
		'comments_notify'                 => 1,
		'posts_per_rss'                   => 10,
		'rss_use_excerpt'                 => 0,
		'mailserver_url'                  => 'mail.example.com',
		'mailserver_login'                => 'login@example.com',
		'mailserver_pass'                 => '',
		'mailserver_port'                 => 110,
		'default_category'                => 1,
		'default_comment_status'          => 'open',
		'default_ping_status'             => 'open',
		'default_pingback_flag'           => 1,
		'posts_per_page'                  => 10,
		/* translators: Default date format, see https://www.php.net/manual/datetime.format.php */
		'date_format'                     => __( 'F j, Y' ),
		/* translators: Default time format, see https://www.php.net/manual/datetime.format.php */
		'time_format'                     => __( 'g:i a' ),
		/* translators: Links last updated date format, see https://www.php.net/manual/datetime.format.php */
		'links_updated_date_format'       => __( 'F j, Y g:i a' ),
		'comment_moderation'              => 0,
		'moderation_notify'               => 1,
		'permalink_structure'             => '',
		'rewrite_rules'                   => '',
		'hack_file'                       => 0,
		'blog_charset'                    => 'UTF-8',
		'moderation_keys'                 => '',
		'active_plugins'                  => array(),
		'category_base'                   => '',
		'ping_sites'                      => 'https://rpc.pingomatic.com/',
		'comment_max_links'               => 2,
		'gmt_offset'                      => $gmt_offset,

		// 1.5.0
		'default_email_category'          => 1,
		'recently_edited'                 => '',
		'template'                        => $template,
		'stylesheet'                      => $stylesheet,
		'comment_registration'            => 0,
		'html_type'                       => 'text/html',

		// 1.5.1
		'use_trackback'                   => 0,

		// 2.0.0
		'default_role'                    => 'subscriber',
		'db_version'                      => $wp_db_version,

		// 2.0.1
		'uploads_use_yearmonth_folders'   => 1,
		'upload_path'                     => '',

		// 2.1.0
		'blog_public'                     => '1',
		'default_link_category'           => 2,
		'show_on_front'                   => 'posts',

		// 2.2.0
		'tag_base'                        => '',

		// 2.5.0
		'show_avatars'                    => '1',
		'avatar_rating'                   => 'G',
		'upload_url_path'                 => '',
		'thumbnail_size_w'                => 150,
		'thumbnail_size_h'                => 150,
		'thumbnail_crop'                  => 1,
		'medium_size_w'                   => 300,
		'medium_size_h'                   => 300,

		// 2.6.0
		'avatar_default'                  => 'mystery',

		// 2.7.0
		'large_size_w'                    => 1024,
		'large_size_h'                    => 1024,
		'image_default_link_type'         => 'none',
		'image_default_size'              => '',
		'image_default_align'             => '',
		'close_comments_for_old_posts'    => 0,
		'close_comments_days_old'         => 14,
		'thread_comments'                 => 1,
		'thread_comments_depth'           => 5,
		'page_comments'                   => 0,
		'comments_per_page'               => 50,
		'default_comments_page'           => 'newest',
		'comment_order'                   => 'asc',
		'sticky_posts'                    => array(),
		'widget_categories'               => array(),
		'widget_text'                     => array(),
		'widget_rss'                      => array(),
		'uninstall_plugins'               => array(),

		// 2.8.0
		'timezone_string'                 => $timezone_string,

		// 3.0.0
		'page_for_posts'                  => 0,
		'page_on_front'                   => 0,

		// 3.1.0
		'default_post_format'             => 0,

		// 3.5.0
		'link_manager_enabled'            => 0,

		// 4.3.0
		'finished_splitting_shared_terms' => 1,
		'site_icon'                       => 0,

		// 4.4.0
		'medium_large_size_w'             => 768,
		'medium_large_size_h'             => 0,

		// 4.9.6
		'wp_page_for_privacy_policy'      => 0,

		// 4.9.8
		'show_comments_cookies_opt_in'    => 1,

		// 5.3.0
		'admin_email_lifespan'            => ( time() + 6 * MONTH_IN_SECONDS ),

		// 5.5.0
		'disallowed_keys'                 => '',
		'comment_previously_approved'     => 1,
		'auto_plugin_theme_update_emails' => array(),

		// 5.6.0
		'auto_update_core_dev'            => 'enabled',
		'auto_update_core_minor'          => 'enabled',
		/*
		 * Default to enabled for new installs.
		 * See https://core.trac.wordpress.org/ticket/51742.
		 */
		'auto_update_core_major'          => 'enabled',

		// 5.8.0
		'wp_force_deactivated_plugins'    => array(),

		// 6.4.0
		'wp_attachment_pages_enabled'     => 0,

		// 6.9.0
		'wp_notes_notify'                 => 1,
	);

	// 3.3.0
	if ( ! is_multisite() ) {
		$defaults['initial_db_version'] = ! empty( $wp_current_db_version ) && $wp_current_db_version < $wp_db_version
			? $wp_current_db_version : $wp_db_version;
	}

	// 3.0.0 multisite.
	if ( is_multisite() ) {
		$defaults['permalink_structure'] = '/%year%/%monthnum%/%day%/%postname%/';
	}

	$options = wp_parse_args( $options, $defaults );

	// Set autoload to no for these options.
	$fat_options = array(
		'moderation_keys',
		'recently_edited',
		'disallowed_keys',
		'uninstall_plugins',
		'auto_plugin_theme_update_emails',
	);

	$keys             = "'" . implode( "', '", array_keys( $options ) ) . "'";
	$existing_options = $wpdb->get_col( "SELECT option_name FROM $wpdb->options WHERE option_name in ( $keys )" ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared

	$insert = '';

	foreach ( $options as $option => $value ) {
		if ( in_array( $option, $existing_options, true ) ) {
			continue;
		}

		if ( in_array( $option, $fat_options, true ) ) {
			$autoload = 'off';
		} else {
			$autoload = 'on';
		}

		if ( ! empty( $insert ) ) {
			$insert .= ', ';
		}

		$value = maybe_serialize( sanitize_option( $option, $value ) );

		$insert .= $wpdb->prepare( '(%s, %s, %s)', $option, $value, $autoload );
	}

	if ( ! empty( $insert ) ) {
		$wpdb->query( "INSERT INTO $wpdb->options (option_name, option_value, autoload) VALUES " . $insert ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
	}

	// In case it is set, but blank, update "home".
	if ( ! __get_option( 'home' ) ) {
		update_option( 'home', $guessurl );
	}

	// Delete unused options.
	$unusedoptions = array(
		'blodotgsping_url',
		'bodyterminator',
		'emailtestonly',
		'phoneemail_separator',
		'smilies_directory',
		'subjectprefix',
		'use_bbcode',
		'use_blodotgsping',
		'use_phoneemail',
		'use_quicktags',
		'use_weblogsping',
		'weblogs_cache_file',
		'use_preview',
		'use_htmltrans',
		'smilies_directory',
		'fileupload_allowedusers',
		'use_phoneemail',
		'default_post_status',
		'default_post_category',
		'archive_mode',
		'time_difference',
		'links_minadminlevel',
		'links_use_adminlevels',
		'links_rating_type',
		'links_rating_char',
		'links_rating_ignore_zero',
		'links_rating_single_image',
		'links_rating_image0',
		'links_rating_image1',
		'links_rating_image2',
		'links_rating_image3',
		'links_rating_image4',
		'links_rating_image5',
		'links_rating_image6',
		'links_rating_image7',
		'links_rating_image8',
		'links_rating_image9',
		'links_recently_updated_time',
		'links_recently_updated_prepend',
		'links_recently_updated_append',
		'weblogs_cacheminutes',
		'comment_allowed_tags',
		'search_engine_friendly_urls',
		'default_geourl_lat',
		'default_geourl_lon',
		'use_default_geourl',
		'weblogs_xml_url',
		'new_users_can_blog',
		'_wpnonce',
		'_wp_http_referer',
		'Update',
		'action',
		'rich_editing',
		'autosave_interval',
		'deactivated_plugins',
		'can_compress_scripts',
		'page_uris',
		'update_core',
		'update_plugins',
		'update_themes',
		'doing_cron',
		'random_seed',
		'rss_excerpt_length',
		'secret',
		'use_linksupdate',
		'default_comment_status_page',
		'wporg_popular_tags',
		'what_to_show',
		'rss_language',
		'language',
		'enable_xmlrpc',
		'enable_app',
		'embed_autourls',
		'default_post_edit_rows',
		'gzipcompression',
		'advanced_edit',
	);
	foreach ( $unusedoptions as $option ) {
		delete_option( $option );
	}

	// Delete obsolete magpie stuff.
	$wpdb->query( "DELETE FROM $wpdb->options WHERE option_name REGEXP '^rss_[0-9a-f]{32}(_ts)?$'" );

	// Clear expired transients.
	delete_expired_transients( true );
}

/**
 * Execute WordPress role creation for the various WordPress versions.
 *
 * @since 2.0.0
 */
function populate_roles() {
	$wp_roles = wp_roles();

	// Disable role updates to the database while populating roles.
	$original_use_db  = $wp_roles->use_db;
	$wp_roles->use_db = false;

	// Populate roles
	populate_roles_160();
	populate_roles_210();
	populate_roles_230();
	populate_roles_250();
	populate_roles_260();
	populate_roles_270();
	populate_roles_280();
	populate_roles_300();

	// Save the updated roles to the database.
	if ( $original_use_db ) {
		update_option( $wp_roles->role_key, $wp_roles->roles, true );
	}

	// Restore original value for writing to database.
	$wp_roles->use_db = $original_use_db;
}

/**
 * Create the roles for WordPress 2.0
 *
 * @since 2.0.0
 */
function populate_roles_160() {
	// Add roles.
	add_role( 'administrator', 'Administrator' );
	add_role( 'editor', 'Editor' );
	add_role( 'author', 'Author' );
	add_role( 'contributor', 'Contributor' );
	add_role( 'subscriber', 'Subscriber' );

	// Add caps for Administrator role.
	$role = get_role( 'administrator' );
	$role->add_cap( 'switch_themes' );
	$role->add_cap( 'edit_themes' );
	$role->add_cap( 'activate_plugins' );
	$role->add_cap( 'edit_plugins' );
	$role->add_cap( 'edit_users' );
	$role->add_cap( 'edit_files' );
	$role->add_cap( 'manage_options' );
	$role->add_cap( 'moderate_comments' );
	$role->add_cap( 'manage_categories' );
	$role->add_cap( 'manage_links' );
	$role->add_cap( 'upload_files' );
	$role->add_cap( 'import' );
	$role->add_cap( 'unfiltered_html' );
	$role->add_cap( 'edit_posts' );
	$role->add_cap( 'edit_others_posts' );
	$role->add_cap( 'edit_published_posts' );
	$role->add_cap( 'publish_posts' );
	$role->add_cap( 'edit_pages' );
	$role->add_cap( 'read' );
	$role->add_cap( 'level_10' );
	$role->add_cap( 'level_9' );
	$role->add_cap( 'level_8' );
	$role->add_cap( 'level_7' );
	$role->add_cap( 'level_6' );
	$role->add_cap( 'level_5' );
	$role->add_cap( 'level_4' );
	$role->add_cap( 'level_3' );
	$role->add_cap( 'level_2' );
	$role->add_cap( 'level_1' );
	$role->add_cap( 'level_0' );

	// Add caps for Editor role.
	$role = get_role( 'editor' );
	$role->add_cap( 'moderate_comments' );
	$role->add_cap( 'manage_categories' );
	$role->add_cap( 'manage_links' );
	$role->add_cap( 'upload_files' );
	$role->add_cap( 'unfiltered_html' );
	$role->add_cap( 'edit_posts' );
	$role->add_cap( 'edit_others_posts' );
	$role->add_cap( 'edit_published_posts' );
	$role->add_cap( 'publish_posts' );
	$role->add_cap( 'edit_pages' );
	$role->add_cap( 'read' );
	$role->add_cap( 'level_7' );
	$role->add_cap( 'level_6' );
	$role->add_cap( 'level_5' );
	$role->add_cap( 'level_4' );
	$role->add_cap( 'level_3' );
	$role->add_cap( 'level_2' );
	$role->add_cap( 'level_1' );
	$role->add_cap( 'level_0' );

	// Add caps for Author role.
	$role = get_role( 'author' );
	$role->add_cap( 'upload_files' );
	$role->add_cap( 'edit_posts' );
	$role->add_cap( 'edit_published_posts' );
	$role->add_cap( 'publish_posts' );
	$role->add_cap( 'read' );
	$role->add_cap( 'level_2' );
	$role->add_cap( 'level_1' );
	$role->add_cap( 'level_0' );

	// Add caps for Contributor role.
	$role = get_role( 'contributor' );
	$role->add_cap( 'edit_posts' );
	$role->add_cap( 'read' );
	$role->add_cap( 'level_1' );
	$role->add_cap( 'level_0' );

	// Add caps for Subscriber role.
	$role = get_role( 'subscriber' );
	$role->add_cap( 'read' );
	$role->add_cap( 'level_0' );
}

/**
 * Create and modify WordPress roles for WordPress 2.1.
 *
 * @since 2.1.0
 */
function populate_roles_210() {
	$roles = array( 'administrator', 'editor' );
	foreach ( $roles as $role ) {
		$role = get_role( $role );
		if ( empty( $role ) ) {
			continue;
		}

		$role->add_cap( 'edit_others_pages' );
		$role->add_cap( 'edit_published_pages' );
		$role->add_cap( 'publish_pages' );
		$role->add_cap( 'delete_pages' );
		$role->add_cap( 'delete_others_pages' );
		$role->add_cap( 'delete_published_pages' );
		$role->add_cap( 'delete_posts' );
		$role->add_cap( 'delete_others_posts' );
		$role->add_cap( 'delete_published_posts' );
		$role->add_cap( 'delete_private_posts' );
		$role->add_cap( 'edit_private_posts' );
		$role->add_cap( 'read_private_posts' );
		$role->add_cap( 'delete_private_pages' );
		$role->add_cap( 'edit_private_pages' );
		$role->add_cap( 'read_private_pages' );
	}

	$role = get_role( 'administrator' );
	if ( ! empty( $role ) ) {
		$role->add_cap( 'delete_users' );
		$role->add_cap( 'create_users' );
	}

	$role = get_role( 'author' );
	if ( ! empty( $role ) ) {
		$role->add_cap( 'delete_posts' );
		$role->add_cap( 'delete_published_posts' );
	}

	$role = get_role( 'contributor' );
	if ( ! empty( $role ) ) {
		$role->add_cap( 'delete_posts' );
	}
}

/**
 * Create and modify WordPress roles for WordPress 2.3.
 *
 * @since 2.3.0
 */
function populate_roles_230() {
	$role = get_role( 'administrator' );

	if ( ! empty( $role ) ) {
		$role->add_cap( 'unfiltered_upload' );
	}
}

/**
 * Create and modify WordPress roles for WordPress 2.5.
 *
 * @since 2.5.0
 */
function populate_roles_250() {
	$role = get_role( 'administrator' );

	if ( ! empty( $role ) ) {
		$role->add_cap( 'edit_dashboard' );
	}
}

/**
 * Create and modify WordPress roles for WordPress 2.6.
 *
 * @since 2.6.0
 */
function populate_roles_260() {
	$role = get_role( 'administrator' );

	if ( ! empty( $role ) ) {
		$role->add_cap( 'update_plugins' );
		$role->add_cap( 'delete_plugins' );
	}
}

/**
 * Create and modify WordPress roles for WordPress 2.7.
 *
 * @since 2.7.0
 */
function populate_roles_270() {
	$role = get_role( 'administrator' );

	if ( ! empty( $role ) ) {
		$role->add_cap( 'install_plugins' );
		$role->add_cap( 'update_themes' );
	}
}

/**
 * Create and modify WordPress roles for WordPress 2.8.
 *
 * @since 2.8.0
 */
function populate_roles_280() {
	$role = get_role( 'administrator' );

	if ( ! empty( $role ) ) {
		$role->add_cap( 'install_themes' );
	}
}

/**
 * Create and modify WordPress roles for WordPress 3.0.
 *
 * @since 3.0.0
 */
function populate_roles_300() {
	$role = get_role( 'administrator' );

	if ( ! empty( $role ) ) {
		$role->add_cap( 'update_core' );
		$role->add_cap( 'list_users' );
		$role->add_cap( 'remove_users' );
		$role->add_cap( 'promote_users' );
		$role->add_cap( 'edit_theme_options' );
		$role->add_cap( 'delete_themes' );
		$role->add_cap( 'export' );
	}
}

if ( ! function_exists( 'install_network' ) ) :
	/**
	 * Install Network.
	 *
	 * @since 3.0.0
	 */
	function install_network() {
		if ( ! defined( 'WP_INSTALLING_NETWORK' ) ) {
			define( 'WP_INSTALLING_NETWORK', true );
		}

		dbDelta( wp_get_db_schema( 'global' ) );
	}
endif;

/**
 * Populate network settings.
 *
 * @since 3.0.0
 *
 * @global wpdb       $wpdb         WordPress database abstraction object.
 * @global object     $current_site
 * @global WP_Rewrite $wp_rewrite   WordPress rewrite component.
 *
 * @param int    $network_id        ID of network to populate.
 * @param string $domain            The domain name for the network. Example: "example.com".
 * @param string $email             Email address for the network administrator.
 * @param string $site_name         The name of the network.
 * @param string $path              Optional. The path to append to the network's domain name. Default '/'.
 * @param bool   $subdomain_install Optional. Whether the network is a subdomain installation or a subdirectory installation.
 *                                  Default false, meaning the network is a subdirectory installation.
 * @return true|WP_Error True on success, or WP_Error on warning (with the installation otherwise successful,
 *                       so the error code must be checked) or failure.
 */
function populate_network( $network_id = 1, $domain = '', $email = '', $site_name = '', $path = '/', $subdomain_install = false ) {
	global $wpdb, $current_site, $wp_rewrite;

	$network_id = (int) $network_id;

	/**
	 * Fires before a network is populated.
	 *
	 * @since 6.9.0
	 *
	 * @param int    $network_id        ID of network to populate.
	 * @param string $domain            The domain name for the network.
	 * @param string $email             Email address for the network administrator.
	 * @param string $site_name         The name of the network.
	 * @param string $path              The path to append to the network's domain name.
	 * @param bool   $subdomain_install Whether the network is a subdomain installation or a subdirectory installation.
	 */
	do_action( 'before_populate_network', $network_id, $domain, $email, $site_name, $path, $subdomain_install );

	$errors = new WP_Error();
	if ( '' === $domain ) {
		$errors->add( 'empty_domain', __( 'You must provide a domain name.' ) );
	}
	if ( '' === $site_name ) {
		$errors->add( 'empty_sitename', __( 'You must provide a name for your network of sites.' ) );
	}

	// Check for network collision.
	$network_exists = false;
	if ( is_multisite() ) {
		if ( get_network( $network_id ) ) {
			$errors->add( 'siteid_exists', __( 'The network already exists.' ) );
		}
	} else {
		if ( $network_id === (int) $wpdb->get_var(
			$wpdb->prepare( "SELECT id FROM $wpdb->site WHERE id = %d", $network_id )
		) ) {
			$errors->add( 'siteid_exists', __( 'The network already exists.' ) );
		}
	}

	if ( ! is_email( $email ) ) {
		$errors->add( 'invalid_email', __( 'You must provide a valid email address.' ) );
	}

	if ( $errors->has_errors() ) {
		return $errors;
	}

	if ( 1 === $network_id ) {
		$wpdb->insert(
			$wpdb->site,
			array(
				'domain' => $domain,
				'path'   => $path,
			)
		);
		$network_id = $wpdb->insert_id;
	} else {
		$wpdb->insert(
			$wpdb->site,
			array(
				'domain' => $domain,
				'path'   => $path,
				'id'     => $network_id,
			)
		);
	}

	populate_network_meta(
		$network_id,
		array(
			'admin_email'       => $email,
			'site_name'         => $site_name,
			'subdomain_install' => $subdomain_install,
		)
	);

	// Remove the cron event since Recovery Mode is not used in Multisite.
	if ( wp_next_scheduled( 'recovery_mode_clean_expired_keys' ) ) {
		wp_clear_scheduled_hook( 'recovery_mode_clean_expired_keys' );
	}

	/*
	 * When upgrading from single to multisite, assume the current site will
	 * become the main site of the network. When using populate_network()
	 * to create another network in an existing multisite environment, skip
	 * these steps since the main site of the new network has not yet been
	 * created.
	 */
	if ( ! is_multisite() ) {
		$current_site            = new stdClass();
		$current_site->domain    = $domain;
		$current_site->path      = $path;
		$current_site->site_name = ucfirst( $domain );
		$wpdb->insert(
			$wpdb->blogs,
			array(
				'site_id'    => $network_id,
				'blog_id'    => 1,
				'domain'     => $domain,
				'path'       => $path,
				'registered' => current_time( 'mysql' ),
			)
		);
		$current_site->blog_id = $wpdb->insert_id;

		$site_user_id = (int) $wpdb->get_var(
			$wpdb->prepare(
				"SELECT meta_value
				FROM $wpdb->sitemeta
				WHERE meta_key = %s AND site_id = %d",
				'admin_user_id',
				$network_id
			)
		);

		update_user_meta( $site_user_id, 'source_domain', $domain );
		update_user_meta( $site_user_id, 'primary_blog', $current_site->blog_id );

		// Unable to use update_network_option() while populating the network.
		$wpdb->insert(
			$wpdb->sitemeta,
			array(
				'site_id'    => $network_id,
				'meta_key'   => 'main_site',
				'meta_value' => $current_site->blog_id,
			)
		);

		if ( $subdomain_install ) {
			$wp_rewrite->set_permalink_structure( '/%year%/%monthnum%/%day%/%postname%/' );
		} else {
			$wp_rewrite->set_permalink_structure( '/blog/%year%/%monthnum%/%day%/%postname%/' );
		}

		flush_rewrite_rules();

		/**
		 * Fires after a network is created when converting a single site to multisite.
		 *
		 * @since 6.9.0
		 *
		 * @param int    $network_id        ID of network created.
		 * @param string $domain            The domain name for the network.
		 * @param string $email             Email address for the network administrator.
		 * @param string $site_name         The name of the network.
		 * @param string $path              The path to append to the network's domain name.
		 * @param bool   $subdomain_install Whether the network is a subdomain installation or a subdirectory installation.
		 */
		do_action( 'after_upgrade_to_multisite', $network_id, $domain, $email, $site_name, $path, $subdomain_install );

		if ( ! $subdomain_install ) {
			return true;
		}

		$vhost_ok = false;
		$errstr   = '';
		$hostname = substr( md5( time() ), 0, 6 ) . '.' . $domain; // Very random hostname!
		$page     = wp_remote_get(
			'http://' . $hostname,
			array(
				'timeout'     => 5,
				'httpversion' => '1.1',
			)
		);
		if ( is_wp_error( $page ) ) {
			$errstr = $page->get_error_message();
		} elseif ( 200 === wp_remote_retrieve_response_code( $page ) ) {
				$vhost_ok = true;
		}

		if ( ! $vhost_ok ) {
			$msg = '<p><strong>' . __( 'Warning! Wildcard DNS may not be configured correctly!' ) . '</strong></p>';

			$msg .= '<p>' . sprintf(
				/* translators: %s: Host name. */
				__( 'The installer attempted to contact a random hostname (%s) on your domain.' ),
				'<code>' . $hostname . '</code>'
			);
			if ( ! empty( $errstr ) ) {
				/* translators: %s: Error message. */
				$msg .= ' ' . sprintf( __( 'This resulted in an error message: %s' ), '<code>' . $errstr . '</code>' );
			}
			$msg .= '</p>';

			$msg .= '<p>' . sprintf(
				/* translators: %s: Asterisk symbol (*). */
				__( 'To use a subdomain configuration, you must have a wildcard entry in your DNS. This usually means adding a %s hostname record pointing at your web server in your DNS configuration tool.' ),
				'<code>*</code>'
			) . '</p>';

			$msg .= '<p>' . __( 'You can still use your site but any subdomain you create may not be accessible. If you know your DNS is correct, ignore this message.' ) . '</p>';

			return new WP_Error( 'no_wildcard_dns', $msg );
		}
	}

	/**
	 * Fires after a network is fully populated.
	 *
	 * @since 6.9.0
	 *
	 * @param int    $network_id        ID of network created.
	 * @param string $domain            The domain name for the network.
	 * @param string $email             Email address for the network administrator.
	 * @param string $site_name         The name of the network.
	 * @param string $path              The path to append to the network's domain name.
	 * @param bool   $subdomain_install Whether the network is a subdomain installation or a subdirectory installation.
	 */
	do_action( 'after_populate_network', $network_id, $domain, $email, $site_name, $path, $subdomain_install );

	return true;
}

/**
 * Creates WordPress network meta and sets the default values.
 *
 * @since 5.1.0
 *
 * @global wpdb $wpdb          WordPress database abstraction object.
 * @global int  $wp_db_version WordPress database version.
 *
 * @param int   $network_id Network ID to populate meta for.
 * @param array $meta       Optional. Custom meta $key => $value pairs to use. Default empty array.
 */
function populate_network_meta( $network_id, array $meta = array() ) {
	global $wpdb, $wp_db_version;

	$network_id = (int) $network_id;

	$email             = ! empty( $meta['admin_email'] ) ? $meta['admin_email'] : '';
	$subdomain_install = isset( $meta['subdomain_install'] ) ? (int) $meta['subdomain_install'] : 0;

	// If a user with the provided email does not exist, default to the current user as the new network admin.
	$site_user = ! empty( $email ) ? get_user_by( 'email', $email ) : false;
	if ( false === $site_user ) {
		$site_user = wp_get_current_user();
	}

	if ( empty( $email ) ) {
		$email = $site_user->user_email;
	}

	$template       = get_option( 'template' );
	$stylesheet     = get_option( 'stylesheet' );
	$allowed_themes = array( $stylesheet => true );

	if ( $template !== $stylesheet ) {
		$allowed_themes[ $template ] = true;
	}

	if ( WP_DEFAULT_THEME !== $stylesheet && WP_DEFAULT_THEME !== $template ) {
		$allowed_themes[ WP_DEFAULT_THEME ] = true;
	}

	// If WP_DEFAULT_THEME doesn't exist, also include the latest core default theme.
	if ( ! wp_get_theme( WP_DEFAULT_THEME )->exists() ) {
		$core_default = WP_Theme::get_core_default_theme();
		if ( $core_default ) {
			$allowed_themes[ $core_default->get_stylesheet() ] = true;
		}
	}

	if ( function_exists( 'clean_network_cache' ) ) {
		clean_network_cache( $network_id );
	} else {
		wp_cache_delete( $network_id, 'networks' );
	}

	if ( ! is_multisite() ) {
		$site_admins = array( $site_user->user_login );
		$users       = get_users(
			array(
				'fields' => array( 'user_login' ),
				'role'   => 'administrator',
			)
		);
		if ( $users ) {
			foreach ( $users as $user ) {
				$site_admins[] = $user->user_login;
			}

			$site_admins = array_unique( $site_admins );
		}
	} else {
		$site_admins = get_site_option( 'site_admins' );
	}

	/* translators: Do not translate USERNAME, SITE_NAME, BLOG_URL, PASSWORD: those are placeholders. */
	$welcome_email = __(
		'Howdy USERNAME,

Your new SITE_NAME site has been successfully set up at:
BLOG_URL

You can log in to the administrator account with the following information:

Username: USERNAME
Password: PASSWORD
Log in here: BLOG_URLwp-login.php

We hope you enjoy your new site. Thanks!

--The Team @ SITE_NAME'
	);

	$allowed_file_types = array();
	$all_mime_types     = get_allowed_mime_types();

	foreach ( $all_mime_types as $ext => $mime ) {
		array_push( $allowed_file_types, ...explode( '|', $ext ) );
	}
	$upload_filetypes = array_unique( $allowed_file_types );

	$sitemeta = array(
		'site_name'                   => __( 'My Network' ),
		'admin_email'                 => $email,
		'admin_user_id'               => $site_user->ID,
		'registration'                => 'none',
		'upload_filetypes'            => implode( ' ', $upload_filetypes ),
		'blog_upload_space'           => 100,
		'fileupload_maxk'             => 1500,
		'site_admins'                 => $site_admins,
		'allowedthemes'               => $allowed_themes,
		'illegal_names'               => array( 'www', 'web', 'root', 'admin', 'main', 'invite', 'administrator', 'files' ),
		'wpmu_upgrade_site'           => $wp_db_version,
		'welcome_email'               => $welcome_email,
		/* translators: %s: Site link. */
		'first_post'                  => __( 'Welcome to %s. This is your first post. Edit or delete it, then start writing!' ),
		// @todo - Network admins should have a method of editing the network siteurl (used for cookie hash).
		'siteurl'                     => get_option( 'siteurl' ) . '/',
		'add_new_users'               => '0',
		'upload_space_check_disabled' => is_multisite() ? get_site_option( 'upload_space_check_disabled' ) : '1',
		'subdomain_install'           => $subdomain_install,
		'ms_files_rewriting'          => is_multisite() ? get_site_option( 'ms_files_rewriting' ) : '0',
		'user_count'                  => get_site_option( 'user_count' ),
		'initial_db_version'          => get_option( 'initial_db_version' ),
		'active_sitewide_plugins'     => array(),
		'WPLANG'                      => get_locale(),
	);
	if ( ! $subdomain_install ) {
		$sitemeta['illegal_names'][] = 'blog';
	}

	$sitemeta = wp_parse_args( $meta, $sitemeta );

	/**
	 * Filters meta for a network on creation.
	 *
	 * @since 3.7.0
	 *
	 * @param array $sitemeta   Associative array of network meta keys and values to be inserted.
	 * @param int   $network_id ID of network to populate.
	 */
	$sitemeta = apply_filters( 'populate_network_meta', $sitemeta, $network_id );

	$insert = '';
	foreach ( $sitemeta as $meta_key => $meta_value ) {
		if ( is_array( $meta_value ) ) {
			$meta_value = serialize( $meta_value );
		}
		if ( ! empty( $insert ) ) {
			$insert .= ', ';
		}
		$insert .= $wpdb->prepare( '( %d, %s, %s)', $network_id, $meta_key, $meta_value );
	}
	$wpdb->query( "INSERT INTO $wpdb->sitemeta ( site_id, meta_key, meta_value ) VALUES " . $insert ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
}

/**
 * Creates WordPress site meta and sets the default values.
 *
 * @since 5.1.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int   $site_id Site ID to populate meta for.
 * @param array $meta    Optional. Custom meta $key => $value pairs to use. Default empty array.
 */
function populate_site_meta( $site_id, array $meta = array() ) {
	global $wpdb;

	$site_id = (int) $site_id;

	if ( ! is_site_meta_supported() ) {
		return;
	}

	if ( empty( $meta ) ) {
		return;
	}

	/**
	 * Filters meta for a site on creation.
	 *
	 * @since 5.2.0
	 *
	 * @param array $meta    Associative array of site meta keys and values to be inserted.
	 * @param int   $site_id ID of site to populate.
	 */
	$site_meta = apply_filters( 'populate_site_meta', $meta, $site_id );

	$insert = '';
	foreach ( $site_meta as $meta_key => $meta_value ) {
		if ( is_array( $meta_value ) ) {
			$meta_value = serialize( $meta_value );
		}
		if ( ! empty( $insert ) ) {
			$insert .= ', ';
		}
		$insert .= $wpdb->prepare( '( %d, %s, %s)', $site_id, $meta_key, $meta_value );
	}

	$wpdb->query( "INSERT INTO $wpdb->blogmeta ( blog_id, meta_key, meta_value ) VALUES " . $insert ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared

	wp_cache_delete( $site_id, 'blog_meta' );
	wp_cache_set_sites_last_changed();
}
class-ftp.php000064400000065352151212616050007163 0ustar00<?php
/**
 * PemFTP - An Ftp implementation in pure PHP
 *
 * @package PemFTP
 * @since 2.5.0
 *
 * @version 1.0
 * @copyright Alexey Dotsenko
 * @author Alexey Dotsenko
 * @link https://www.phpclasses.org/package/1743-PHP-FTP-client-in-pure-PHP.html
 * @license LGPL https://opensource.org/licenses/lgpl-license.html
 */

/**
 * Defines the newline characters, if not defined already.
 *
 * This can be redefined.
 *
 * @since 2.5.0
 * @var string
 */
if ( ! defined( 'CRLF' ) ) {
	define( 'CRLF', "\r\n" );
}

/**
 * Sets whatever to autodetect ASCII mode.
 *
 * This can be redefined.
 *
 * @since 2.5.0
 * @var int
 */
if ( ! defined( 'FTP_AUTOASCII' ) ) {
	define( 'FTP_AUTOASCII', -1 );
}

/**
 *
 * This can be redefined.
 * @since 2.5.0
 * @var int
 */
if ( ! defined( 'FTP_BINARY' ) ) {
	define( 'FTP_BINARY', 1 );
}

/**
 *
 * This can be redefined.
 * @since 2.5.0
 * @var int
 */
if ( ! defined( 'FTP_ASCII' ) ) {
	define( 'FTP_ASCII', 0 );
}

/**
 * Whether to force FTP.
 *
 * This can be redefined.
 *
 * @since 2.5.0
 * @var bool
 */
if ( ! defined( 'FTP_FORCE' ) ) {
	define( 'FTP_FORCE', true );
}

/**
 * @since 2.5.0
 * @var string
 */
define('FTP_OS_Unix','u');

/**
 * @since 2.5.0
 * @var string
 */
define('FTP_OS_Windows','w');

/**
 * @since 2.5.0
 * @var string
 */
define('FTP_OS_Mac','m');

/**
 * PemFTP base class
 *
 */
class ftp_base {
	/* Public variables */
	var $LocalEcho;
	var $Verbose;
	var $OS_local;
	var $OS_remote;

	/* Private variables */
	var $_lastaction;
	var $_errors;
	var $_type;
	var $_umask;
	var $_timeout;
	var $_passive;
	var $_host;
	var $_fullhost;
	var $_port;
	var $_datahost;
	var $_dataport;
	var $_ftp_control_sock;
	var $_ftp_data_sock;
	var $_ftp_temp_sock;
	var $_ftp_buff_size;
	var $_login;
	var $_password;
	var $_connected;
	var $_ready;
	var $_code;
	var $_message;
	var $_can_restore;
	var $_port_available;
	var $_curtype;
	var $_features;

	var $_error_array;
	var $AuthorizedTransferMode;
	var $OS_FullName;
	var $_eol_code;
	var $AutoAsciiExt;

	/* Constructor */
	function __construct($port_mode=FALSE, $verb=FALSE, $le=FALSE) {
		$this->LocalEcho=$le;
		$this->Verbose=$verb;
		$this->_lastaction=NULL;
		$this->_error_array=array();
		$this->_eol_code=array(FTP_OS_Unix=>"\n", FTP_OS_Mac=>"\r", FTP_OS_Windows=>"\r\n");
		$this->AuthorizedTransferMode=array(FTP_AUTOASCII, FTP_ASCII, FTP_BINARY);
		$this->OS_FullName=array(FTP_OS_Unix => 'UNIX', FTP_OS_Windows => 'WINDOWS', FTP_OS_Mac => 'MACOS');
		$this->AutoAsciiExt=array("ASP","BAT","C","CPP","CSS","CSV","JS","H","HTM","HTML","SHTML","INI","LOG","PHP3","PHTML","PL","PERL","SH","SQL","TXT");
		$this->_port_available=($port_mode==TRUE);
		$this->SendMSG("Staring FTP client class".($this->_port_available?"":" without PORT mode support"));
		$this->_connected=FALSE;
		$this->_ready=FALSE;
		$this->_can_restore=FALSE;
		$this->_code=0;
		$this->_message="";
		$this->_ftp_buff_size=4096;
		$this->_curtype=NULL;
		$this->SetUmask(0022);
		$this->SetType(FTP_AUTOASCII);
		$this->SetTimeout(30);
		$this->Passive(!$this->_port_available);
		$this->_login="anonymous";
		$this->_password="anon@ftp.com";
		$this->_features=array();
	    $this->OS_local=FTP_OS_Unix;
		$this->OS_remote=FTP_OS_Unix;
		$this->features=array();
		if(strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') $this->OS_local=FTP_OS_Windows;
		elseif(strtoupper(substr(PHP_OS, 0, 3)) === 'MAC') $this->OS_local=FTP_OS_Mac;
	}

	function ftp_base($port_mode=FALSE) {
		$this->__construct($port_mode);
	}

// <!-- --------------------------------------------------------------------------------------- -->
// <!--       Public functions                                                                  -->
// <!-- --------------------------------------------------------------------------------------- -->

	function parselisting($line) {
		$is_windows = ($this->OS_remote == FTP_OS_Windows);
		if ($is_windows && preg_match("/([0-9]{2})-([0-9]{2})-([0-9]{2}) +([0-9]{2}):([0-9]{2})(AM|PM) +([0-9]+|<DIR>) +(.+)/",$line,$lucifer)) {
			$b = array();
			if ($lucifer[3]<70) { $lucifer[3]+=2000; } else { $lucifer[3]+=1900; } // 4digit year fix
			$b['isdir'] = ($lucifer[7]=="<DIR>");
			if ( $b['isdir'] )
				$b['type'] = 'd';
			else
				$b['type'] = 'f';
			$b['size'] = $lucifer[7];
			$b['month'] = $lucifer[1];
			$b['day'] = $lucifer[2];
			$b['year'] = $lucifer[3];
			$b['hour'] = $lucifer[4];
			$b['minute'] = $lucifer[5];
			$b['time'] = @mktime($lucifer[4]+(strcasecmp($lucifer[6],"PM")==0?12:0),$lucifer[5],0,$lucifer[1],$lucifer[2],$lucifer[3]);
			$b['am/pm'] = $lucifer[6];
			$b['name'] = $lucifer[8];
		} else if (!$is_windows && $lucifer=preg_split("/[ ]/",$line,9,PREG_SPLIT_NO_EMPTY)) {
			//echo $line."\n";
			$lcount=count($lucifer);
			if ($lcount<8) return '';
			$b = array();
			$b['isdir'] = $lucifer[0][0] === "d";
			$b['islink'] = $lucifer[0][0] === "l";
			if ( $b['isdir'] )
				$b['type'] = 'd';
			elseif ( $b['islink'] )
				$b['type'] = 'l';
			else
				$b['type'] = 'f';
			$b['perms'] = $lucifer[0];
			$b['number'] = $lucifer[1];
			$b['owner'] = $lucifer[2];
			$b['group'] = $lucifer[3];
			$b['size'] = $lucifer[4];
			if ($lcount==8) {
				sscanf($lucifer[5],"%d-%d-%d",$b['year'],$b['month'],$b['day']);
				sscanf($lucifer[6],"%d:%d",$b['hour'],$b['minute']);
				$b['time'] = @mktime($b['hour'],$b['minute'],0,$b['month'],$b['day'],$b['year']);
				$b['name'] = $lucifer[7];
			} else {
				$b['month'] = $lucifer[5];
				$b['day'] = $lucifer[6];
				if (preg_match("/([0-9]{2}):([0-9]{2})/",$lucifer[7],$l2)) {
					$b['year'] = gmdate("Y");
					$b['hour'] = $l2[1];
					$b['minute'] = $l2[2];
				} else {
					$b['year'] = $lucifer[7];
					$b['hour'] = 0;
					$b['minute'] = 0;
				}
				$b['time'] = strtotime(sprintf("%d %s %d %02d:%02d",$b['day'],$b['month'],$b['year'],$b['hour'],$b['minute']));
				$b['name'] = $lucifer[8];
			}
		}

		return $b;
	}

	function SendMSG($message = "", $crlf=true) {
		if ($this->Verbose) {
			echo $message.($crlf?CRLF:"");
			flush();
		}
		return TRUE;
	}

	function SetType($mode=FTP_AUTOASCII) {
		if(!in_array($mode, $this->AuthorizedTransferMode)) {
			$this->SendMSG("Wrong type");
			return FALSE;
		}
		$this->_type=$mode;
		$this->SendMSG("Transfer type: ".($this->_type==FTP_BINARY?"binary":($this->_type==FTP_ASCII?"ASCII":"auto ASCII") ) );
		return TRUE;
	}

	function _settype($mode=FTP_ASCII) {
		if($this->_ready) {
			if($mode==FTP_BINARY) {
				if($this->_curtype!=FTP_BINARY) {
					if(!$this->_exec("TYPE I", "SetType")) return FALSE;
					$this->_curtype=FTP_BINARY;
				}
			} elseif($this->_curtype!=FTP_ASCII) {
				if(!$this->_exec("TYPE A", "SetType")) return FALSE;
				$this->_curtype=FTP_ASCII;
			}
		} else return FALSE;
		return TRUE;
	}

	function Passive($pasv=NULL) {
		if(is_null($pasv)) $this->_passive=!$this->_passive;
		else $this->_passive=$pasv;
		if(!$this->_port_available and !$this->_passive) {
			$this->SendMSG("Only passive connections available!");
			$this->_passive=TRUE;
			return FALSE;
		}
		$this->SendMSG("Passive mode ".($this->_passive?"on":"off"));
		return TRUE;
	}

	function SetServer($host, $port=21, $reconnect=true) {
		if(!is_long($port)) {
	        $this->verbose=true;
    	    $this->SendMSG("Incorrect port syntax");
			return FALSE;
		} else {
			$ip=@gethostbyname($host);
	        $dns=@gethostbyaddr($host);
	        if(!$ip) $ip=$host;
	        if(!$dns) $dns=$host;
	        // Validate the IPAddress PHP4 returns -1 for invalid, PHP5 false
	        // -1 === "255.255.255.255" which is the broadcast address which is also going to be invalid
	        $ipaslong = ip2long($ip);
			if ( ($ipaslong == false) || ($ipaslong === -1) ) {
				$this->SendMSG("Wrong host name/address \"".$host."\"");
				return FALSE;
			}
	        $this->_host=$ip;
	        $this->_fullhost=$dns;
	        $this->_port=$port;
	        $this->_dataport=$port-1;
		}
		$this->SendMSG("Host \"".$this->_fullhost."(".$this->_host."):".$this->_port."\"");
		if($reconnect){
			if($this->_connected) {
				$this->SendMSG("Reconnecting");
				if(!$this->quit(FTP_FORCE)) return FALSE;
				if(!$this->connect()) return FALSE;
			}
		}
		return TRUE;
	}

	function SetUmask($umask=0022) {
		$this->_umask=$umask;
		umask($this->_umask);
		$this->SendMSG("UMASK 0".decoct($this->_umask));
		return TRUE;
	}

	function SetTimeout($timeout=30) {
		$this->_timeout=$timeout;
		$this->SendMSG("Timeout ".$this->_timeout);
		if($this->_connected)
			if(!$this->_settimeout($this->_ftp_control_sock)) return FALSE;
		return TRUE;
	}

	function connect($server=NULL) {
		if(!empty($server)) {
			if(!$this->SetServer($server)) return false;
		}
		if($this->_ready) return true;
	    $this->SendMsg('Local OS : '.$this->OS_FullName[$this->OS_local]);
		if(!($this->_ftp_control_sock = $this->_connect($this->_host, $this->_port))) {
			$this->SendMSG("Error : Cannot connect to remote host \"".$this->_fullhost." :".$this->_port."\"");
			return FALSE;
		}
		$this->SendMSG("Connected to remote host \"".$this->_fullhost.":".$this->_port."\". Waiting for greeting.");
		do {
			if(!$this->_readmsg()) return FALSE;
			if(!$this->_checkCode()) return FALSE;
			$this->_lastaction=time();
		} while($this->_code<200);
		$this->_ready=true;
		$syst=$this->systype();
		if(!$syst) $this->SendMSG("Cannot detect remote OS");
		else {
			if(preg_match("/win|dos|novell/i", $syst[0])) $this->OS_remote=FTP_OS_Windows;
			elseif(preg_match("/os/i", $syst[0])) $this->OS_remote=FTP_OS_Mac;
			elseif(preg_match("/(li|u)nix/i", $syst[0])) $this->OS_remote=FTP_OS_Unix;
			else $this->OS_remote=FTP_OS_Mac;
			$this->SendMSG("Remote OS: ".$this->OS_FullName[$this->OS_remote]);
		}
		if(!$this->features()) $this->SendMSG("Cannot get features list. All supported - disabled");
		else $this->SendMSG("Supported features: ".implode(", ", array_keys($this->_features)));
		return TRUE;
	}

	function quit($force=false) {
		if($this->_ready) {
			if(!$this->_exec("QUIT") and !$force) return FALSE;
			if(!$this->_checkCode() and !$force) return FALSE;
			$this->_ready=false;
			$this->SendMSG("Session finished");
		}
		$this->_quit();
		return TRUE;
	}

	function login($user=NULL, $pass=NULL) {
		if(!is_null($user)) $this->_login=$user;
		else $this->_login="anonymous";
		if(!is_null($pass)) $this->_password=$pass;
		else $this->_password="anon@anon.com";
		if(!$this->_exec("USER ".$this->_login, "login")) return FALSE;
		if(!$this->_checkCode()) return FALSE;
		if($this->_code!=230) {
			if(!$this->_exec((($this->_code==331)?"PASS ":"ACCT ").$this->_password, "login")) return FALSE;
			if(!$this->_checkCode()) return FALSE;
		}
		$this->SendMSG("Authentication succeeded");
		if(empty($this->_features)) {
			if(!$this->features()) $this->SendMSG("Cannot get features list. All supported - disabled");
			else $this->SendMSG("Supported features: ".implode(", ", array_keys($this->_features)));
		}
		return TRUE;
	}

	function pwd() {
		if(!$this->_exec("PWD", "pwd")) return FALSE;
		if(!$this->_checkCode()) return FALSE;
		return preg_replace("/^[0-9]{3} \"(.+)\".*$/s", "\\1", $this->_message);
	}

	function cdup() {
		if(!$this->_exec("CDUP", "cdup")) return FALSE;
		if(!$this->_checkCode()) return FALSE;
		return true;
	}

	function chdir($pathname) {
		if(!$this->_exec("CWD ".$pathname, "chdir")) return FALSE;
		if(!$this->_checkCode()) return FALSE;
		return TRUE;
	}

	function rmdir($pathname) {
		if(!$this->_exec("RMD ".$pathname, "rmdir")) return FALSE;
		if(!$this->_checkCode()) return FALSE;
		return TRUE;
	}

	function mkdir($pathname) {
		if(!$this->_exec("MKD ".$pathname, "mkdir")) return FALSE;
		if(!$this->_checkCode()) return FALSE;
		return TRUE;
	}

	function rename($from, $to) {
		if(!$this->_exec("RNFR ".$from, "rename")) return FALSE;
		if(!$this->_checkCode()) return FALSE;
		if($this->_code==350) {
			if(!$this->_exec("RNTO ".$to, "rename")) return FALSE;
			if(!$this->_checkCode()) return FALSE;
		} else return FALSE;
		return TRUE;
	}

	function filesize($pathname) {
		if(!isset($this->_features["SIZE"])) {
			$this->PushError("filesize", "not supported by server");
			return FALSE;
		}
		if(!$this->_exec("SIZE ".$pathname, "filesize")) return FALSE;
		if(!$this->_checkCode()) return FALSE;
		return preg_replace("/^[0-9]{3} ([0-9]+).*$/s", "\\1", $this->_message);
	}

	function abort() {
		if(!$this->_exec("ABOR", "abort")) return FALSE;
		if(!$this->_checkCode()) {
			if($this->_code!=426) return FALSE;
			if(!$this->_readmsg("abort")) return FALSE;
			if(!$this->_checkCode()) return FALSE;
		}
		return true;
	}

	function mdtm($pathname) {
		if(!isset($this->_features["MDTM"])) {
			$this->PushError("mdtm", "not supported by server");
			return FALSE;
		}
		if(!$this->_exec("MDTM ".$pathname, "mdtm")) return FALSE;
		if(!$this->_checkCode()) return FALSE;
		$mdtm = preg_replace("/^[0-9]{3} ([0-9]+).*$/s", "\\1", $this->_message);
		$date = sscanf($mdtm, "%4d%2d%2d%2d%2d%2d");
		$timestamp = mktime($date[3], $date[4], $date[5], $date[1], $date[2], $date[0]);
		return $timestamp;
	}

	function systype() {
		if(!$this->_exec("SYST", "systype")) return FALSE;
		if(!$this->_checkCode()) return FALSE;
		$DATA = explode(" ", $this->_message);
		return array($DATA[1], $DATA[3]);
	}

	function delete($pathname) {
		if(!$this->_exec("DELE ".$pathname, "delete")) return FALSE;
		if(!$this->_checkCode()) return FALSE;
		return TRUE;
	}

	function site($command, $fnction="site") {
		if(!$this->_exec("SITE ".$command, $fnction)) return FALSE;
		if(!$this->_checkCode()) return FALSE;
		return TRUE;
	}

	function chmod($pathname, $mode) {
		if(!$this->site( sprintf('CHMOD %o %s', $mode, $pathname), "chmod")) return FALSE;
		return TRUE;
	}

	function restore($from) {
		if(!isset($this->_features["REST"])) {
			$this->PushError("restore", "not supported by server");
			return FALSE;
		}
		if($this->_curtype!=FTP_BINARY) {
			$this->PushError("restore", "cannot restore in ASCII mode");
			return FALSE;
		}
		if(!$this->_exec("REST ".$from, "restore")) return FALSE;
		if(!$this->_checkCode()) return FALSE;
		return TRUE;
	}

	function features() {
		if(!$this->_exec("FEAT", "features")) return FALSE;
		if(!$this->_checkCode()) return FALSE;
		$f=preg_split("/[".CRLF."]+/", preg_replace("/[0-9]{3}[ -].*[".CRLF."]+/", "", $this->_message), -1, PREG_SPLIT_NO_EMPTY);
		$this->_features=array();
		foreach($f as $k=>$v) {
			$v=explode(" ", trim($v));
			$this->_features[array_shift($v)]=$v;
		}
		return true;
	}

	function rawlist($pathname="", $arg="") {
		return $this->_list(($arg?" ".$arg:"").($pathname?" ".$pathname:""), "LIST", "rawlist");
	}

	function nlist($pathname="", $arg="") {
		return $this->_list(($arg?" ".$arg:"").($pathname?" ".$pathname:""), "NLST", "nlist");
	}

	function is_exists($pathname) {
		return $this->file_exists($pathname);
	}

	function file_exists($pathname) {
		$exists=true;
		if(!$this->_exec("RNFR ".$pathname, "rename")) $exists=FALSE;
		else {
			if(!$this->_checkCode()) $exists=FALSE;
			$this->abort();
		}
		if($exists) $this->SendMSG("Remote file ".$pathname." exists");
		else $this->SendMSG("Remote file ".$pathname." does not exist");
		return $exists;
	}

	function fget($fp, $remotefile, $rest=0) {
		if($this->_can_restore and $rest!=0) fseek($fp, $rest);
		$pi=pathinfo($remotefile);
		if($this->_type==FTP_ASCII or ($this->_type==FTP_AUTOASCII and in_array(strtoupper($pi["extension"]), $this->AutoAsciiExt))) $mode=FTP_ASCII;
		else $mode=FTP_BINARY;
		if(!$this->_data_prepare($mode)) {
			return FALSE;
		}
		if($this->_can_restore and $rest!=0) $this->restore($rest);
		if(!$this->_exec("RETR ".$remotefile, "get")) {
			$this->_data_close();
			return FALSE;
		}
		if(!$this->_checkCode()) {
			$this->_data_close();
			return FALSE;
		}
		$out=$this->_data_read($mode, $fp);
		$this->_data_close();
		if(!$this->_readmsg()) return FALSE;
		if(!$this->_checkCode()) return FALSE;
		return $out;
	}

	function get($remotefile, $localfile=NULL, $rest=0) {
		if(is_null($localfile)) $localfile=$remotefile;
		if (@file_exists($localfile)) $this->SendMSG("Warning : local file will be overwritten");
		$fp = @fopen($localfile, "w");
		if (!$fp) {
			$this->PushError("get","cannot open local file", "Cannot create \"".$localfile."\"");
			return FALSE;
		}
		if($this->_can_restore and $rest!=0) fseek($fp, $rest);
		$pi=pathinfo($remotefile);
		if($this->_type==FTP_ASCII or ($this->_type==FTP_AUTOASCII and in_array(strtoupper($pi["extension"]), $this->AutoAsciiExt))) $mode=FTP_ASCII;
		else $mode=FTP_BINARY;
		if(!$this->_data_prepare($mode)) {
			fclose($fp);
			return FALSE;
		}
		if($this->_can_restore and $rest!=0) $this->restore($rest);
		if(!$this->_exec("RETR ".$remotefile, "get")) {
			$this->_data_close();
			fclose($fp);
			return FALSE;
		}
		if(!$this->_checkCode()) {
			$this->_data_close();
			fclose($fp);
			return FALSE;
		}
		$out=$this->_data_read($mode, $fp);
		fclose($fp);
		$this->_data_close();
		if(!$this->_readmsg()) return FALSE;
		if(!$this->_checkCode()) return FALSE;
		return $out;
	}

	function fput($remotefile, $fp, $rest=0) {
		if($this->_can_restore and $rest!=0) fseek($fp, $rest);
		$pi=pathinfo($remotefile);
		if($this->_type==FTP_ASCII or ($this->_type==FTP_AUTOASCII and in_array(strtoupper($pi["extension"]), $this->AutoAsciiExt))) $mode=FTP_ASCII;
		else $mode=FTP_BINARY;
		if(!$this->_data_prepare($mode)) {
			return FALSE;
		}
		if($this->_can_restore and $rest!=0) $this->restore($rest);
		if(!$this->_exec("STOR ".$remotefile, "put")) {
			$this->_data_close();
			return FALSE;
		}
		if(!$this->_checkCode()) {
			$this->_data_close();
			return FALSE;
		}
		$ret=$this->_data_write($mode, $fp);
		$this->_data_close();
		if(!$this->_readmsg()) return FALSE;
		if(!$this->_checkCode()) return FALSE;
		return $ret;
	}

	function put($localfile, $remotefile=NULL, $rest=0) {
		if(is_null($remotefile)) $remotefile=$localfile;
		if (!file_exists($localfile)) {
			$this->PushError("put","cannot open local file", "No such file or directory \"".$localfile."\"");
			return FALSE;
		}
		$fp = @fopen($localfile, "r");

		if (!$fp) {
			$this->PushError("put","cannot open local file", "Cannot read file \"".$localfile."\"");
			return FALSE;
		}
		if($this->_can_restore and $rest!=0) fseek($fp, $rest);
		$pi=pathinfo($localfile);
		if($this->_type==FTP_ASCII or ($this->_type==FTP_AUTOASCII and in_array(strtoupper($pi["extension"]), $this->AutoAsciiExt))) $mode=FTP_ASCII;
		else $mode=FTP_BINARY;
		if(!$this->_data_prepare($mode)) {
			fclose($fp);
			return FALSE;
		}
		if($this->_can_restore and $rest!=0) $this->restore($rest);
		if(!$this->_exec("STOR ".$remotefile, "put")) {
			$this->_data_close();
			fclose($fp);
			return FALSE;
		}
		if(!$this->_checkCode()) {
			$this->_data_close();
			fclose($fp);
			return FALSE;
		}
		$ret=$this->_data_write($mode, $fp);
		fclose($fp);
		$this->_data_close();
		if(!$this->_readmsg()) return FALSE;
		if(!$this->_checkCode()) return FALSE;
		return $ret;
	}

	function mput($local=".", $remote=NULL, $continious=false) {
		$local=realpath($local);
		if(!@file_exists($local)) {
			$this->PushError("mput","cannot open local folder", "Cannot stat folder \"".$local."\"");
			return FALSE;
		}
		if(!is_dir($local)) return $this->put($local, $remote);
		if(empty($remote)) $remote=".";
		elseif(!$this->file_exists($remote) and !$this->mkdir($remote)) return FALSE;
		if($handle = opendir($local)) {
			$list=array();
			while (false !== ($file = readdir($handle))) {
				if ($file != "." && $file != "..") $list[]=$file;
			}
			closedir($handle);
		} else {
			$this->PushError("mput","cannot open local folder", "Cannot read folder \"".$local."\"");
			return FALSE;
		}
		if(empty($list)) return TRUE;
		$ret=true;
		foreach($list as $el) {
			if(is_dir($local."/".$el)) $t=$this->mput($local."/".$el, $remote."/".$el);
			else $t=$this->put($local."/".$el, $remote."/".$el);
			if(!$t) {
				$ret=FALSE;
				if(!$continious) break;
			}
		}
		return $ret;

	}

	function mget($remote, $local=".", $continious=false) {
		$list=$this->rawlist($remote, "-lA");
		if($list===false) {
			$this->PushError("mget","cannot read remote folder list", "Cannot read remote folder \"".$remote."\" contents");
			return FALSE;
		}
		if(empty($list)) return true;
		if(!@file_exists($local)) {
			if(!@mkdir($local)) {
				$this->PushError("mget","cannot create local folder", "Cannot create folder \"".$local."\"");
				return FALSE;
			}
		}
		foreach($list as $k=>$v) {
			$list[$k]=$this->parselisting($v);
			if( ! $list[$k] or $list[$k]["name"]=="." or $list[$k]["name"]=="..") unset($list[$k]);
		}
		$ret=true;
		foreach($list as $el) {
			if($el["type"]=="d") {
				if(!$this->mget($remote."/".$el["name"], $local."/".$el["name"], $continious)) {
					$this->PushError("mget", "cannot copy folder", "Cannot copy remote folder \"".$remote."/".$el["name"]."\" to local \"".$local."/".$el["name"]."\"");
					$ret=false;
					if(!$continious) break;
				}
			} else {
				if(!$this->get($remote."/".$el["name"], $local."/".$el["name"])) {
					$this->PushError("mget", "cannot copy file", "Cannot copy remote file \"".$remote."/".$el["name"]."\" to local \"".$local."/".$el["name"]."\"");
					$ret=false;
					if(!$continious) break;
				}
			}
			@chmod($local."/".$el["name"], $el["perms"]);
			$t=strtotime($el["date"]);
			if($t!==-1 and $t!==false) @touch($local."/".$el["name"], $t);
		}
		return $ret;
	}

	function mdel($remote, $continious=false) {
		$list=$this->rawlist($remote, "-la");
		if($list===false) {
			$this->PushError("mdel","cannot read remote folder list", "Cannot read remote folder \"".$remote."\" contents");
			return false;
		}

		foreach($list as $k=>$v) {
			$list[$k]=$this->parselisting($v);
			if( ! $list[$k] or $list[$k]["name"]=="." or $list[$k]["name"]=="..") unset($list[$k]);
		}
		$ret=true;

		foreach($list as $el) {
			if ( empty($el) )
				continue;

			if($el["type"]=="d") {
				if(!$this->mdel($remote."/".$el["name"], $continious)) {
					$ret=false;
					if(!$continious) break;
				}
			} else {
				if (!$this->delete($remote."/".$el["name"])) {
					$this->PushError("mdel", "cannot delete file", "Cannot delete remote file \"".$remote."/".$el["name"]."\"");
					$ret=false;
					if(!$continious) break;
				}
			}
		}

		if(!$this->rmdir($remote)) {
			$this->PushError("mdel", "cannot delete folder", "Cannot delete remote folder \"".$remote."/".$el["name"]."\"");
			$ret=false;
		}
		return $ret;
	}

	function mmkdir($dir, $mode = 0777) {
		if(empty($dir)) return FALSE;
		if($this->is_exists($dir) or $dir == "/" ) return TRUE;
		if(!$this->mmkdir(dirname($dir), $mode)) return false;
		$r=$this->mkdir($dir, $mode);
		$this->chmod($dir,$mode);
		return $r;
	}

	function glob($pattern, $handle=NULL) {
		$path=$output=null;
		if(PHP_OS=='WIN32') $slash='\\';
		else $slash='/';
		$lastpos=strrpos($pattern,$slash);
		if(!($lastpos===false)) {
			$path=substr($pattern,0,-$lastpos-1);
			$pattern=substr($pattern,$lastpos);
		} else $path=getcwd();
		if(is_array($handle) and !empty($handle)) {
			foreach($handle as $dir) {
				if($this->glob_pattern_match($pattern,$dir))
				$output[]=$dir;
			}
		} else {
			$handle=@opendir($path);
			if($handle===false) return false;
			while($dir=readdir($handle)) {
				if($this->glob_pattern_match($pattern,$dir))
				$output[]=$dir;
			}
			closedir($handle);
		}
		if(is_array($output)) return $output;
		return false;
	}

	function glob_pattern_match($pattern,$subject) {
		$out=null;
		$chunks=explode(';',$pattern);
		foreach($chunks as $pattern) {
			$escape=array('$','^','.','{','}','(',')','[',']','|');
			while(str_contains($pattern,'**'))
				$pattern=str_replace('**','*',$pattern);
			foreach($escape as $probe)
				$pattern=str_replace($probe,"\\$probe",$pattern);
			$pattern=str_replace('?*','*',
				str_replace('*?','*',
					str_replace('*',".*",
						str_replace('?','.{1,1}',$pattern))));
			$out[]=$pattern;
		}
		if(count($out)==1) return($this->glob_regexp("^$out[0]$",$subject));
		else {
			foreach($out as $tester)
				// TODO: This should probably be glob_regexp(), but needs tests.
				if($this->my_regexp("^$tester$",$subject)) return true;
		}
		return false;
	}

	function glob_regexp($pattern,$subject) {
		$sensitive=(PHP_OS!='WIN32');
		return ($sensitive?
			preg_match( '/' . preg_quote( $pattern, '/' ) . '/', $subject ) :
			preg_match( '/' . preg_quote( $pattern, '/' ) . '/i', $subject )
		);
	}

	function dirlist($remote) {
		$list=$this->rawlist($remote, "-la");
		if($list===false) {
			$this->PushError("dirlist","cannot read remote folder list", "Cannot read remote folder \"".$remote."\" contents");
			return false;
		}

		$dirlist = array();
		foreach($list as $k=>$v) {
			$entry=$this->parselisting($v);
			if ( empty($entry) )
				continue;

			if($entry["name"]=="." or $entry["name"]=="..")
				continue;

			$dirlist[$entry['name']] = $entry;
		}

		return $dirlist;
	}
// <!-- --------------------------------------------------------------------------------------- -->
// <!--       Private functions                                                                 -->
// <!-- --------------------------------------------------------------------------------------- -->
	function _checkCode() {
		return ($this->_code<400 and $this->_code>0);
	}

	function _list($arg="", $cmd="LIST", $fnction="_list") {
		if(!$this->_data_prepare()) return false;
		if(!$this->_exec($cmd.$arg, $fnction)) {
			$this->_data_close();
			return FALSE;
		}
		if(!$this->_checkCode()) {
			$this->_data_close();
			return FALSE;
		}
		$out="";
		if($this->_code<200) {
			$out=$this->_data_read();
			$this->_data_close();
			if(!$this->_readmsg()) return FALSE;
			if(!$this->_checkCode()) return FALSE;
			if($out === FALSE ) return FALSE;
			$out=preg_split("/[".CRLF."]+/", $out, -1, PREG_SPLIT_NO_EMPTY);
//			$this->SendMSG(implode($this->_eol_code[$this->OS_local], $out));
		}
		return $out;
	}

// <!-- --------------------------------------------------------------------------------------- -->
// <!-- Partie : gestion des erreurs                                                            -->
// <!-- --------------------------------------------------------------------------------------- -->
// Gnre une erreur pour traitement externe  la classe
	function PushError($fctname,$msg,$desc=false){
		$error=array();
		$error['time']=time();
		$error['fctname']=$fctname;
		$error['msg']=$msg;
		$error['desc']=$desc;
		if($desc) $tmp=' ('.$desc.')'; else $tmp='';
		$this->SendMSG($fctname.': '.$msg.$tmp);
		return(array_push($this->_error_array,$error));
	}

// Rcupre une erreur externe
	function PopError(){
		if(count($this->_error_array)) return(array_pop($this->_error_array));
			else return(false);
	}
}

$mod_sockets = extension_loaded( 'sockets' );
if ( ! $mod_sockets && function_exists( 'dl' ) && is_callable( 'dl' ) ) {
	$prefix = ( PHP_SHLIB_SUFFIX == 'dll' ) ? 'php_' : '';
	@dl( $prefix . 'sockets.' . PHP_SHLIB_SUFFIX ); // phpcs:ignore PHPCompatibility.FunctionUse.RemovedFunctions.dlDeprecated
	$mod_sockets = extension_loaded( 'sockets' );
}

require_once __DIR__ . "/class-ftp-" . ( $mod_sockets ? "sockets" : "pure" ) . ".php";

if ( $mod_sockets ) {
	class ftp extends ftp_sockets {}
} else {
	class ftp extends ftp_pure {}
}
class-wp-filesystem-ftpext.php000064400000055327151212616050012513 0ustar00<?php
/**
 * WordPress FTP Filesystem.
 *
 * @package WordPress
 * @subpackage Filesystem
 */

/**
 * WordPress Filesystem Class for implementing FTP.
 *
 * @since 2.5.0
 *
 * @see WP_Filesystem_Base
 */
class WP_Filesystem_FTPext extends WP_Filesystem_Base {

	/**
	 * @since 2.5.0
	 * @var FTP\Connection|resource|false
	 */
	public $link;

	/**
	 * Constructor.
	 *
	 * @since 2.5.0
	 *
	 * @param array $opt
	 */
	public function __construct( $opt = '' ) {
		$this->method = 'ftpext';
		$this->errors = new WP_Error();

		// Check if possible to use ftp functions.
		if ( ! extension_loaded( 'ftp' ) ) {
			$this->errors->add( 'no_ftp_ext', __( 'The ftp PHP extension is not available' ) );
			return;
		}

		// This class uses the timeout on a per-connection basis, others use it on a per-action basis.
		if ( ! defined( 'FS_TIMEOUT' ) ) {
			define( 'FS_TIMEOUT', 4 * MINUTE_IN_SECONDS );
		}

		if ( empty( $opt['port'] ) ) {
			$this->options['port'] = 21;
		} else {
			$this->options['port'] = $opt['port'];
		}

		if ( empty( $opt['hostname'] ) ) {
			$this->errors->add( 'empty_hostname', __( 'FTP hostname is required' ) );
		} else {
			$this->options['hostname'] = $opt['hostname'];
		}

		// Check if the options provided are OK.
		if ( empty( $opt['username'] ) ) {
			$this->errors->add( 'empty_username', __( 'FTP username is required' ) );
		} else {
			$this->options['username'] = $opt['username'];
		}

		if ( empty( $opt['password'] ) ) {
			$this->errors->add( 'empty_password', __( 'FTP password is required' ) );
		} else {
			$this->options['password'] = $opt['password'];
		}

		$this->options['ssl'] = false;

		if ( isset( $opt['connection_type'] ) && 'ftps' === $opt['connection_type'] ) {
			$this->options['ssl'] = true;
		}
	}

	/**
	 * Connects filesystem.
	 *
	 * @since 2.5.0
	 *
	 * @return bool True on success, false on failure.
	 */
	public function connect() {
		if ( isset( $this->options['ssl'] ) && $this->options['ssl'] && function_exists( 'ftp_ssl_connect' ) ) {
			$this->link = @ftp_ssl_connect( $this->options['hostname'], $this->options['port'], FS_CONNECT_TIMEOUT );
		} else {
			$this->link = @ftp_connect( $this->options['hostname'], $this->options['port'], FS_CONNECT_TIMEOUT );
		}

		if ( ! $this->link ) {
			$this->errors->add(
				'connect',
				sprintf(
					/* translators: %s: hostname:port */
					__( 'Failed to connect to FTP Server %s' ),
					$this->options['hostname'] . ':' . $this->options['port']
				)
			);

			return false;
		}

		if ( ! @ftp_login( $this->link, $this->options['username'], $this->options['password'] ) ) {
			$this->errors->add(
				'auth',
				sprintf(
					/* translators: %s: Username. */
					__( 'Username/Password incorrect for %s' ),
					$this->options['username']
				)
			);

			return false;
		}

		// Set the connection to use Passive FTP.
		ftp_pasv( $this->link, true );

		if ( @ftp_get_option( $this->link, FTP_TIMEOUT_SEC ) < FS_TIMEOUT ) {
			@ftp_set_option( $this->link, FTP_TIMEOUT_SEC, FS_TIMEOUT );
		}

		return true;
	}

	/**
	 * Reads entire file into a string.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Name of the file to read.
	 * @return string|false Read data on success, false if no temporary file could be opened,
	 *                      or if the file couldn't be retrieved.
	 */
	public function get_contents( $file ) {
		$tempfile   = wp_tempnam( $file );
		$temphandle = fopen( $tempfile, 'w+' );

		if ( ! $temphandle ) {
			unlink( $tempfile );
			return false;
		}

		if ( ! ftp_fget( $this->link, $temphandle, $file, FTP_BINARY ) ) {
			fclose( $temphandle );
			unlink( $tempfile );
			return false;
		}

		fseek( $temphandle, 0 ); // Skip back to the start of the file being written to.
		$contents = '';

		while ( ! feof( $temphandle ) ) {
			$contents .= fread( $temphandle, 8 * KB_IN_BYTES );
		}

		fclose( $temphandle );
		unlink( $tempfile );

		return $contents;
	}

	/**
	 * Reads entire file into an array.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to the file.
	 * @return array|false File contents in an array on success, false on failure.
	 */
	public function get_contents_array( $file ) {
		return explode( "\n", $this->get_contents( $file ) );
	}

	/**
	 * Writes a string to a file.
	 *
	 * @since 2.5.0
	 *
	 * @param string    $file     Remote path to the file where to write the data.
	 * @param string    $contents The data to write.
	 * @param int|false $mode     Optional. The file permissions as octal number, usually 0644.
	 *                            Default false.
	 * @return bool True on success, false on failure.
	 */
	public function put_contents( $file, $contents, $mode = false ) {
		$tempfile   = wp_tempnam( $file );
		$temphandle = fopen( $tempfile, 'wb+' );

		if ( ! $temphandle ) {
			unlink( $tempfile );
			return false;
		}

		mbstring_binary_safe_encoding();

		$data_length   = strlen( $contents );
		$bytes_written = fwrite( $temphandle, $contents );

		reset_mbstring_encoding();

		if ( $data_length !== $bytes_written ) {
			fclose( $temphandle );
			unlink( $tempfile );
			return false;
		}

		fseek( $temphandle, 0 ); // Skip back to the start of the file being written to.

		$ret = ftp_fput( $this->link, $file, $temphandle, FTP_BINARY );

		fclose( $temphandle );
		unlink( $tempfile );

		$this->chmod( $file, $mode );

		return $ret;
	}

	/**
	 * Gets the current working directory.
	 *
	 * @since 2.5.0
	 *
	 * @return string|false The current working directory on success, false on failure.
	 */
	public function cwd() {
		$cwd = ftp_pwd( $this->link );

		if ( $cwd ) {
			$cwd = trailingslashit( $cwd );
		}

		return $cwd;
	}

	/**
	 * Changes current directory.
	 *
	 * @since 2.5.0
	 *
	 * @param string $dir The new current directory.
	 * @return bool True on success, false on failure.
	 */
	public function chdir( $dir ) {
		return @ftp_chdir( $this->link, $dir );
	}

	/**
	 * Changes filesystem permissions.
	 *
	 * @since 2.5.0
	 *
	 * @param string    $file      Path to the file.
	 * @param int|false $mode      Optional. The permissions as octal number, usually 0644 for files,
	 *                             0755 for directories. Default false.
	 * @param bool      $recursive Optional. If set to true, changes file permissions recursively.
	 *                             Default false.
	 * @return bool True on success, false on failure.
	 */
	public function chmod( $file, $mode = false, $recursive = false ) {
		if ( ! $mode ) {
			if ( $this->is_file( $file ) ) {
				$mode = FS_CHMOD_FILE;
			} elseif ( $this->is_dir( $file ) ) {
				$mode = FS_CHMOD_DIR;
			} else {
				return false;
			}
		}

		// chmod any sub-objects if recursive.
		if ( $recursive && $this->is_dir( $file ) ) {
			$filelist = $this->dirlist( $file );

			foreach ( (array) $filelist as $filename => $filemeta ) {
				$this->chmod( $file . '/' . $filename, $mode, $recursive );
			}
		}

		// chmod the file or directory.
		if ( ! function_exists( 'ftp_chmod' ) ) {
			return (bool) ftp_site( $this->link, sprintf( 'CHMOD %o %s', $mode, $file ) );
		}

		return (bool) ftp_chmod( $this->link, $mode, $file );
	}

	/**
	 * Gets the file owner.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to the file.
	 * @return string|false Username of the owner on success, false on failure.
	 */
	public function owner( $file ) {
		$dir = $this->dirlist( $file );

		return $dir[ $file ]['owner'];
	}

	/**
	 * Gets the permissions of the specified file or filepath in their octal format.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to the file.
	 * @return string Mode of the file (the last 3 digits).
	 */
	public function getchmod( $file ) {
		$dir = $this->dirlist( $file );

		return $dir[ $file ]['permsn'];
	}

	/**
	 * Gets the file's group.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to the file.
	 * @return string|false The group on success, false on failure.
	 */
	public function group( $file ) {
		$dir = $this->dirlist( $file );

		return $dir[ $file ]['group'];
	}

	/**
	 * Copies a file.
	 *
	 * @since 2.5.0
	 *
	 * @param string    $source      Path to the source file.
	 * @param string    $destination Path to the destination file.
	 * @param bool      $overwrite   Optional. Whether to overwrite the destination file if it exists.
	 *                               Default false.
	 * @param int|false $mode        Optional. The permissions as octal number, usually 0644 for files,
	 *                               0755 for dirs. Default false.
	 * @return bool True on success, false on failure.
	 */
	public function copy( $source, $destination, $overwrite = false, $mode = false ) {
		if ( ! $overwrite && $this->exists( $destination ) ) {
			return false;
		}

		$content = $this->get_contents( $source );

		if ( false === $content ) {
			return false;
		}

		return $this->put_contents( $destination, $content, $mode );
	}

	/**
	 * Moves a file or directory.
	 *
	 * After moving files or directories, OPcache will need to be invalidated.
	 *
	 * If moving a directory fails, `copy_dir()` can be used for a recursive copy.
	 *
	 * Use `move_dir()` for moving directories with OPcache invalidation and a
	 * fallback to `copy_dir()`.
	 *
	 * @since 2.5.0
	 *
	 * @param string $source      Path to the source file or directory.
	 * @param string $destination Path to the destination file or directory.
	 * @param bool   $overwrite   Optional. Whether to overwrite the destination if it exists.
	 *                            Default false.
	 * @return bool True on success, false on failure.
	 */
	public function move( $source, $destination, $overwrite = false ) {
		return ftp_rename( $this->link, $source, $destination );
	}

	/**
	 * Deletes a file or directory.
	 *
	 * @since 2.5.0
	 *
	 * @param string       $file      Path to the file or directory.
	 * @param bool         $recursive Optional. If set to true, deletes files and folders recursively.
	 *                                Default false.
	 * @param string|false $type      Type of resource. 'f' for file, 'd' for directory.
	 *                                Default false.
	 * @return bool True on success, false on failure.
	 */
	public function delete( $file, $recursive = false, $type = false ) {
		if ( empty( $file ) ) {
			return false;
		}

		if ( 'f' === $type || $this->is_file( $file ) ) {
			return ftp_delete( $this->link, $file );
		}

		if ( ! $recursive ) {
			return ftp_rmdir( $this->link, $file );
		}

		$filelist = $this->dirlist( trailingslashit( $file ) );

		if ( ! empty( $filelist ) ) {
			foreach ( $filelist as $delete_file ) {
				$this->delete( trailingslashit( $file ) . $delete_file['name'], $recursive, $delete_file['type'] );
			}
		}

		return ftp_rmdir( $this->link, $file );
	}

	/**
	 * Checks if a file or directory exists.
	 *
	 * @since 2.5.0
	 * @since 6.3.0 Returns false for an empty path.
	 *
	 * @param string $path Path to file or directory.
	 * @return bool Whether $path exists or not.
	 */
	public function exists( $path ) {
		/*
		 * Check for empty path. If ftp_nlist() receives an empty path,
		 * it checks the current working directory and may return true.
		 *
		 * See https://core.trac.wordpress.org/ticket/33058.
		 */
		if ( '' === $path ) {
			return false;
		}

		$list = ftp_nlist( $this->link, $path );

		if ( empty( $list ) && $this->is_dir( $path ) ) {
			return true; // File is an empty directory.
		}

		return ! empty( $list ); // Empty list = no file, so invert.
	}

	/**
	 * Checks if resource is a file.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file File path.
	 * @return bool Whether $file is a file.
	 */
	public function is_file( $file ) {
		return $this->exists( $file ) && ! $this->is_dir( $file );
	}

	/**
	 * Checks if resource is a directory.
	 *
	 * @since 2.5.0
	 *
	 * @param string $path Directory path.
	 * @return bool Whether $path is a directory.
	 */
	public function is_dir( $path ) {
		$cwd    = $this->cwd();
		$result = @ftp_chdir( $this->link, trailingslashit( $path ) );

		if ( $result && $path === $this->cwd() || $this->cwd() !== $cwd ) {
			@ftp_chdir( $this->link, $cwd );
			return true;
		}

		return false;
	}

	/**
	 * Checks if a file is readable.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to file.
	 * @return bool Whether $file is readable.
	 */
	public function is_readable( $file ) {
		return true;
	}

	/**
	 * Checks if a file or directory is writable.
	 *
	 * @since 2.5.0
	 *
	 * @param string $path Path to file or directory.
	 * @return bool Whether $path is writable.
	 */
	public function is_writable( $path ) {
		return true;
	}

	/**
	 * Gets the file's last access time.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to file.
	 * @return int|false Unix timestamp representing last access time, false on failure.
	 */
	public function atime( $file ) {
		return false;
	}

	/**
	 * Gets the file modification time.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to file.
	 * @return int|false Unix timestamp representing modification time, false on failure.
	 */
	public function mtime( $file ) {
		return ftp_mdtm( $this->link, $file );
	}

	/**
	 * Gets the file size (in bytes).
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to file.
	 * @return int|false Size of the file in bytes on success, false on failure.
	 */
	public function size( $file ) {
		$size = ftp_size( $this->link, $file );

		return ( $size > -1 ) ? $size : false;
	}

	/**
	 * Sets the access and modification times of a file.
	 *
	 * Note: If $file doesn't exist, it will be created.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file  Path to file.
	 * @param int    $time  Optional. Modified time to set for file.
	 *                      Default 0.
	 * @param int    $atime Optional. Access time to set for file.
	 *                      Default 0.
	 * @return bool True on success, false on failure.
	 */
	public function touch( $file, $time = 0, $atime = 0 ) {
		return false;
	}

	/**
	 * Creates a directory.
	 *
	 * @since 2.5.0
	 *
	 * @param string           $path  Path for new directory.
	 * @param int|false        $chmod Optional. The permissions as octal number (or false to skip chmod).
	 *                                Default false.
	 * @param string|int|false $chown Optional. A user name or number (or false to skip chown).
	 *                                Default false.
	 * @param string|int|false $chgrp Optional. A group name or number (or false to skip chgrp).
	 *                                Default false.
	 * @return bool True on success, false on failure.
	 */
	public function mkdir( $path, $chmod = false, $chown = false, $chgrp = false ) {
		$path = untrailingslashit( $path );

		if ( empty( $path ) ) {
			return false;
		}

		if ( ! ftp_mkdir( $this->link, $path ) ) {
			return false;
		}

		$this->chmod( $path, $chmod );

		return true;
	}

	/**
	 * Deletes a directory.
	 *
	 * @since 2.5.0
	 *
	 * @param string $path      Path to directory.
	 * @param bool   $recursive Optional. Whether to recursively remove files/directories.
	 *                          Default false.
	 * @return bool True on success, false on failure.
	 */
	public function rmdir( $path, $recursive = false ) {
		return $this->delete( $path, $recursive );
	}

	/**
	 * Parses an individual entry from the FTP LIST command output.
	 *
	 * @param string $line A line from the directory listing.
	 * @return array|string {
	 *     Array of file information. Empty string if the line could not be parsed.
	 *
	 *     @type string       $name        Name of the file or directory.
	 *     @type string       $perms       *nix representation of permissions.
	 *     @type string       $permsn      Octal representation of permissions.
	 *     @type string|false $number      File number as a string, or false if not available.
	 *     @type string|false $owner       Owner name or ID, or false if not available.
	 *     @type string|false $group       File permissions group, or false if not available.
	 *     @type string|false $size        Size of file in bytes as a string, or false if not available.
	 *     @type string|false $lastmodunix Last modified unix timestamp as a string, or false if not available.
	 *     @type string|false $lastmod     Last modified month (3 letters) and day (without leading 0), or
	 *                                     false if not available.
	 *     @type string|false $time        Last modified time, or false if not available.
	 *     @type string       $type        Type of resource. 'f' for file, 'd' for directory, 'l' for link.
	 *     @type array|false  $files       If a directory and `$recursive` is true, contains another array of files.
	 *                                     False if unable to list directory contents.
	 * }
	 */
	public function parselisting( $line ) {
		static $is_windows = null;

		if ( is_null( $is_windows ) ) {
			$is_windows = stripos( ftp_systype( $this->link ), 'win' ) !== false;
		}

		if ( $is_windows && preg_match( '/([0-9]{2})-([0-9]{2})-([0-9]{2}) +([0-9]{2}):([0-9]{2})(AM|PM) +([0-9]+|<DIR>) +(.+)/', $line, $lucifer ) ) {
			$b = array();

			if ( $lucifer[3] < 70 ) {
				$lucifer[3] += 2000;
			} else {
				$lucifer[3] += 1900; // 4-digit year fix.
			}

			$b['isdir'] = ( '<DIR>' === $lucifer[7] );

			if ( $b['isdir'] ) {
				$b['type'] = 'd';
			} else {
				$b['type'] = 'f';
			}

			$b['size']   = $lucifer[7];
			$b['month']  = $lucifer[1];
			$b['day']    = $lucifer[2];
			$b['year']   = $lucifer[3];
			$b['hour']   = $lucifer[4];
			$b['minute'] = $lucifer[5];
			$b['time']   = mktime( $lucifer[4] + ( strcasecmp( $lucifer[6], 'PM' ) === 0 ? 12 : 0 ), $lucifer[5], 0, $lucifer[1], $lucifer[2], $lucifer[3] );
			$b['am/pm']  = $lucifer[6];
			$b['name']   = $lucifer[8];
		} elseif ( ! $is_windows ) {
			$lucifer = preg_split( '/[ ]/', $line, 9, PREG_SPLIT_NO_EMPTY );

			if ( $lucifer ) {
				$lcount = count( $lucifer );

				if ( $lcount < 8 ) {
					return '';
				}

				$b           = array();
				$b['isdir']  = 'd' === $lucifer[0][0];
				$b['islink'] = 'l' === $lucifer[0][0];

				if ( $b['isdir'] ) {
					$b['type'] = 'd';
				} elseif ( $b['islink'] ) {
					$b['type'] = 'l';
				} else {
					$b['type'] = 'f';
				}

				$b['perms']  = $lucifer[0];
				$b['permsn'] = $this->getnumchmodfromh( $b['perms'] );
				$b['number'] = $lucifer[1];
				$b['owner']  = $lucifer[2];
				$b['group']  = $lucifer[3];
				$b['size']   = $lucifer[4];

				if ( 8 === $lcount ) {
					sscanf( $lucifer[5], '%d-%d-%d', $b['year'], $b['month'], $b['day'] );
					sscanf( $lucifer[6], '%d:%d', $b['hour'], $b['minute'] );

					$b['time'] = mktime( $b['hour'], $b['minute'], 0, $b['month'], $b['day'], $b['year'] );
					$b['name'] = $lucifer[7];
				} else {
					$b['month'] = $lucifer[5];
					$b['day']   = $lucifer[6];

					if ( preg_match( '/([0-9]{2}):([0-9]{2})/', $lucifer[7], $l2 ) ) {
						$b['year']   = gmdate( 'Y' );
						$b['hour']   = $l2[1];
						$b['minute'] = $l2[2];
					} else {
						$b['year']   = $lucifer[7];
						$b['hour']   = 0;
						$b['minute'] = 0;
					}

					$b['time'] = strtotime( sprintf( '%d %s %d %02d:%02d', $b['day'], $b['month'], $b['year'], $b['hour'], $b['minute'] ) );
					$b['name'] = $lucifer[8];
				}
			}
		}

		// Replace symlinks formatted as "source -> target" with just the source name.
		if ( isset( $b['islink'] ) && $b['islink'] ) {
			$b['name'] = preg_replace( '/(\s*->\s*.*)$/', '', $b['name'] );
		}

		return $b;
	}

	/**
	 * Gets details for files in a directory or a specific file.
	 *
	 * @since 2.5.0
	 *
	 * @param string $path           Path to directory or file.
	 * @param bool   $include_hidden Optional. Whether to include details of hidden ("." prefixed) files.
	 *                               Default true.
	 * @param bool   $recursive      Optional. Whether to recursively include file details in nested directories.
	 *                               Default false.
	 * @return array|false {
	 *     Array of arrays containing file information. False if unable to list directory contents.
	 *
	 *     @type array ...$0 {
	 *         Array of file information. Note that some elements may not be available on all filesystems.
	 *
	 *         @type string           $name        Name of the file or directory.
	 *         @type string           $perms       *nix representation of permissions.
	 *         @type string           $permsn      Octal representation of permissions.
	 *         @type int|string|false $number      File number. May be a numeric string. False if not available.
	 *         @type string|false     $owner       Owner name or ID, or false if not available.
	 *         @type string|false     $group       File permissions group, or false if not available.
	 *         @type int|string|false $size        Size of file in bytes. May be a numeric string.
	 *                                             False if not available.
	 *         @type int|string|false $lastmodunix Last modified unix timestamp. May be a numeric string.
	 *                                             False if not available.
	 *         @type string|false     $lastmod     Last modified month (3 letters) and day (without leading 0), or
	 *                                             false if not available.
	 *         @type string|false     $time        Last modified time, or false if not available.
	 *         @type string           $type        Type of resource. 'f' for file, 'd' for directory, 'l' for link.
	 *         @type array|false      $files       If a directory and `$recursive` is true, contains another array of
	 *                                             files. False if unable to list directory contents.
	 *     }
	 * }
	 */
	public function dirlist( $path = '.', $include_hidden = true, $recursive = false ) {
		if ( $this->is_file( $path ) ) {
			$limit_file = basename( $path );
			$path       = dirname( $path ) . '/';
		} else {
			$limit_file = false;
		}

		$pwd = ftp_pwd( $this->link );

		if ( ! @ftp_chdir( $this->link, $path ) ) { // Can't change to folder = folder doesn't exist.
			return false;
		}

		$list = ftp_rawlist( $this->link, '-a', false );

		@ftp_chdir( $this->link, $pwd );

		if ( empty( $list ) ) { // Empty array = non-existent folder (real folder will show . at least).
			return false;
		}

		$dirlist = array();

		foreach ( $list as $k => $v ) {
			$entry = $this->parselisting( $v );

			if ( empty( $entry ) ) {
				continue;
			}

			if ( '.' === $entry['name'] || '..' === $entry['name'] ) {
				continue;
			}

			if ( ! $include_hidden && '.' === $entry['name'][0] ) {
				continue;
			}

			if ( $limit_file && $entry['name'] !== $limit_file ) {
				continue;
			}

			$dirlist[ $entry['name'] ] = $entry;
		}

		$path = trailingslashit( $path );
		$ret  = array();

		foreach ( (array) $dirlist as $struc ) {
			if ( 'd' === $struc['type'] ) {
				if ( $recursive ) {
					$struc['files'] = $this->dirlist( $path . $struc['name'], $include_hidden, $recursive );
				} else {
					$struc['files'] = array();
				}
			}

			$ret[ $struc['name'] ] = $struc;
		}

		return $ret;
	}

	/**
	 * Destructor.
	 *
	 * @since 2.5.0
	 */
	public function __destruct() {
		if ( $this->link ) {
			ftp_close( $this->link );
		}
	}
}
class-wp-comments-list-table.php000064400000100550151212616050012667 0ustar00<?php
/**
 * List Table API: WP_Comments_List_Table class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 3.1.0
 */

/**
 * Core class used to implement displaying comments in a list table.
 *
 * @since 3.1.0
 *
 * @see WP_List_Table
 */
class WP_Comments_List_Table extends WP_List_Table {

	public $checkbox = true;

	public $pending_count = array();

	public $extra_items;

	private $user_can;

	/**
	 * Constructor.
	 *
	 * @since 3.1.0
	 *
	 * @see WP_List_Table::__construct() for more information on default arguments.
	 *
	 * @global int $post_id
	 *
	 * @param array $args An associative array of arguments.
	 */
	public function __construct( $args = array() ) {
		global $post_id;

		$post_id = isset( $_REQUEST['p'] ) ? absint( $_REQUEST['p'] ) : 0;

		if ( get_option( 'show_avatars' ) ) {
			add_filter( 'comment_author', array( $this, 'floated_admin_avatar' ), 10, 2 );
		}

		parent::__construct(
			array(
				'plural'   => 'comments',
				'singular' => 'comment',
				'ajax'     => true,
				'screen'   => isset( $args['screen'] ) ? $args['screen'] : null,
			)
		);
	}

	/**
	 * Adds avatars to comment author names.
	 *
	 * @since 3.1.0
	 *
	 * @param string $name       Comment author name.
	 * @param int    $comment_id Comment ID.
	 * @return string Avatar with the user name.
	 */
	public function floated_admin_avatar( $name, $comment_id ) {
		$comment = get_comment( $comment_id );
		$avatar  = get_avatar( $comment, 32, 'mystery' );
		return "$avatar $name";
	}

	/**
	 * @return bool
	 */
	public function ajax_user_can() {
		return current_user_can( 'edit_posts' );
	}

	/**
	 * @global string $mode           List table view mode.
	 * @global int    $post_id
	 * @global string $comment_status
	 * @global string $comment_type
	 * @global string $search
	 */
	public function prepare_items() {
		global $mode, $post_id, $comment_status, $comment_type, $search;

		if ( ! empty( $_REQUEST['mode'] ) ) {
			$mode = 'excerpt' === $_REQUEST['mode'] ? 'excerpt' : 'list';
			set_user_setting( 'posts_list_mode', $mode );
		} else {
			$mode = get_user_setting( 'posts_list_mode', 'list' );
		}

		$comment_status = isset( $_REQUEST['comment_status'] ) ? $_REQUEST['comment_status'] : 'all';

		if ( ! in_array( $comment_status, array( 'all', 'mine', 'moderated', 'approved', 'spam', 'trash' ), true ) ) {
			$comment_status = 'all';
		}

		$comment_type = '';

		if ( ! empty( $_REQUEST['comment_type'] ) && 'note' !== $_REQUEST['comment_type'] ) {
			$comment_type = $_REQUEST['comment_type'];
		}

		$search = ( isset( $_REQUEST['s'] ) ) ? $_REQUEST['s'] : '';

		$post_type = ( isset( $_REQUEST['post_type'] ) ) ? sanitize_key( $_REQUEST['post_type'] ) : '';

		$user_id = ( isset( $_REQUEST['user_id'] ) ) ? $_REQUEST['user_id'] : '';

		$orderby = ( isset( $_REQUEST['orderby'] ) ) ? $_REQUEST['orderby'] : '';
		$order   = ( isset( $_REQUEST['order'] ) ) ? $_REQUEST['order'] : '';

		$comments_per_page = $this->get_per_page( $comment_status );

		$doing_ajax = wp_doing_ajax();

		if ( isset( $_REQUEST['number'] ) ) {
			$number = (int) $_REQUEST['number'];
		} else {
			$number = $comments_per_page + min( 8, $comments_per_page ); // Grab a few extra.
		}

		$page = $this->get_pagenum();

		if ( isset( $_REQUEST['start'] ) ) {
			$start = $_REQUEST['start'];
		} else {
			$start = ( $page - 1 ) * $comments_per_page;
		}

		if ( $doing_ajax && isset( $_REQUEST['offset'] ) ) {
			$start += $_REQUEST['offset'];
		}

		$status_map = array(
			'mine'      => '',
			'moderated' => 'hold',
			'approved'  => 'approve',
			'all'       => '',
		);

		$args = array(
			'status'                    => isset( $status_map[ $comment_status ] ) ? $status_map[ $comment_status ] : $comment_status,
			'search'                    => $search,
			'user_id'                   => $user_id,
			'offset'                    => $start,
			'number'                    => $number,
			'post_id'                   => $post_id,
			'type'                      => $comment_type,
			'orderby'                   => $orderby,
			'order'                     => $order,
			'post_type'                 => $post_type,
			'update_comment_post_cache' => true,
		);

		/**
		 * Filters the arguments for the comment query in the comments list table.
		 *
		 * @since 5.1.0
		 *
		 * @param array $args An array of get_comments() arguments.
		 */
		$args = apply_filters( 'comments_list_table_query_args', $args );

		$_comments = get_comments( $args );

		if ( is_array( $_comments ) ) {
			$this->items       = array_slice( $_comments, 0, $comments_per_page );
			$this->extra_items = array_slice( $_comments, $comments_per_page );

			$_comment_post_ids = array_unique( wp_list_pluck( $_comments, 'comment_post_ID' ) );

			$this->pending_count = get_pending_comments_num( $_comment_post_ids );
		}

		$total_comments = get_comments(
			array_merge(
				$args,
				array(
					'count'   => true,
					'offset'  => 0,
					'number'  => 0,
					'orderby' => 'none',
				)
			)
		);

		$this->set_pagination_args(
			array(
				'total_items' => $total_comments,
				'per_page'    => $comments_per_page,
			)
		);
	}

	/**
	 * @param string $comment_status
	 * @return int
	 */
	public function get_per_page( $comment_status = 'all' ) {
		$comments_per_page = $this->get_items_per_page( 'edit_comments_per_page' );

		/**
		 * Filters the number of comments listed per page in the comments list table.
		 *
		 * @since 2.6.0
		 *
		 * @param int    $comments_per_page The number of comments to list per page.
		 * @param string $comment_status    The comment status name. Default 'All'.
		 */
		return apply_filters( 'comments_per_page', $comments_per_page, $comment_status );
	}

	/**
	 * @global string $comment_status
	 */
	public function no_items() {
		global $comment_status;

		if ( 'moderated' === $comment_status ) {
			_e( 'No comments awaiting moderation.' );
		} elseif ( 'trash' === $comment_status ) {
			_e( 'No comments found in Trash.' );
		} else {
			_e( 'No comments found.' );
		}
	}

	/**
	 * @global int $post_id
	 * @global string $comment_status
	 * @global string $comment_type
	 */
	protected function get_views() {
		global $post_id, $comment_status, $comment_type;

		$status_links = array();
		$num_comments = ( $post_id ) ? wp_count_comments( $post_id ) : wp_count_comments();

		$statuses = array(
			/* translators: %s: Number of comments. */
			'all'       => _nx_noop(
				'All <span class="count">(%s)</span>',
				'All <span class="count">(%s)</span>',
				'comments'
			), // Singular not used.

			/* translators: %s: Number of comments. */
			'mine'      => _nx_noop(
				'Mine <span class="count">(%s)</span>',
				'Mine <span class="count">(%s)</span>',
				'comments'
			),

			/* translators: %s: Number of comments. */
			'moderated' => _nx_noop(
				'Pending <span class="count">(%s)</span>',
				'Pending <span class="count">(%s)</span>',
				'comments'
			),

			/* translators: %s: Number of comments. */
			'approved'  => _nx_noop(
				'Approved <span class="count">(%s)</span>',
				'Approved <span class="count">(%s)</span>',
				'comments'
			),

			/* translators: %s: Number of comments. */
			'spam'      => _nx_noop(
				'Spam <span class="count">(%s)</span>',
				'Spam <span class="count">(%s)</span>',
				'comments'
			),

			/* translators: %s: Number of comments. */
			'trash'     => _nx_noop(
				'Trash <span class="count">(%s)</span>',
				'Trash <span class="count">(%s)</span>',
				'comments'
			),
		);

		if ( ! EMPTY_TRASH_DAYS ) {
			unset( $statuses['trash'] );
		}

		$link = admin_url( 'edit-comments.php' );

		if ( ! empty( $comment_type ) && 'all' !== $comment_type ) {
			$link = add_query_arg( 'comment_type', $comment_type, $link );
		}

		foreach ( $statuses as $status => $label ) {
			if ( 'mine' === $status ) {
				$current_user_id    = get_current_user_id();
				$num_comments->mine = get_comments(
					array(
						'post_id' => $post_id ? $post_id : 0,
						'user_id' => $current_user_id,
						'count'   => true,
						'orderby' => 'none',
					)
				);
				$link               = add_query_arg( 'user_id', $current_user_id, $link );
			} else {
				$link = remove_query_arg( 'user_id', $link );
			}

			if ( ! isset( $num_comments->$status ) ) {
				$num_comments->$status = 10;
			}

			$link = add_query_arg( 'comment_status', $status, $link );

			if ( $post_id ) {
				$link = add_query_arg( 'p', absint( $post_id ), $link );
			}

			/*
			// I toyed with this, but decided against it. Leaving it in here in case anyone thinks it is a good idea. ~ Mark
			if ( !empty( $_REQUEST['s'] ) )
				$link = add_query_arg( 's', esc_attr( wp_unslash( $_REQUEST['s'] ) ), $link );
			*/

			$status_links[ $status ] = array(
				'url'     => esc_url( $link ),
				'label'   => sprintf(
					translate_nooped_plural( $label, $num_comments->$status ),
					sprintf(
						'<span class="%s-count">%s</span>',
						( 'moderated' === $status ) ? 'pending' : $status,
						number_format_i18n( $num_comments->$status )
					)
				),
				'current' => $status === $comment_status,
			);
		}

		/**
		 * Filters the comment status links.
		 *
		 * @since 2.5.0
		 * @since 5.1.0 The 'Mine' link was added.
		 *
		 * @param string[] $status_links An associative array of fully-formed comment status links. Includes 'All', 'Mine',
		 *                              'Pending', 'Approved', 'Spam', and 'Trash'.
		 */
		return apply_filters( 'comment_status_links', $this->get_views_links( $status_links ) );
	}

	/**
	 * @global string $comment_status
	 *
	 * @return array
	 */
	protected function get_bulk_actions() {
		global $comment_status;

		if ( ! current_user_can( 'moderate_comments' ) ) {
			return array(); // Return an empty array if the user doesn't have permission
		}

		$actions = array();

		if ( in_array( $comment_status, array( 'all', 'approved' ), true ) ) {
			$actions['unapprove'] = __( 'Unapprove' );
		}

		if ( in_array( $comment_status, array( 'all', 'moderated' ), true ) ) {
			$actions['approve'] = __( 'Approve' );
		}

		if ( in_array( $comment_status, array( 'all', 'moderated', 'approved', 'trash' ), true ) ) {
			$actions['spam'] = _x( 'Mark as spam', 'comment' );
		}

		if ( 'trash' === $comment_status ) {
			$actions['untrash'] = __( 'Restore' );
		} elseif ( 'spam' === $comment_status ) {
			$actions['unspam'] = _x( 'Not spam', 'comment' );
		}

		if ( in_array( $comment_status, array( 'trash', 'spam' ), true ) || ! EMPTY_TRASH_DAYS ) {
			$actions['delete'] = __( 'Delete permanently' );
		} else {
			$actions['trash'] = __( 'Move to Trash' );
		}

		return $actions;
	}

	/**
	 * @global string $comment_status
	 * @global string $comment_type
	 *
	 * @param string $which
	 */
	protected function extra_tablenav( $which ) {
		global $comment_status, $comment_type;
		static $has_items;

		if ( ! isset( $has_items ) ) {
			$has_items = $this->has_items();
		}

		echo '<div class="alignleft actions">';

		if ( 'top' === $which ) {
			ob_start();

			$this->comment_type_dropdown( $comment_type );

			/**
			 * Fires just before the Filter submit button for comment types.
			 *
			 * @since 3.5.0
			 */
			do_action( 'restrict_manage_comments' );

			$output = ob_get_clean();

			if ( ! empty( $output ) && $this->has_items() ) {
				echo $output;
				submit_button( __( 'Filter' ), '', 'filter_action', false, array( 'id' => 'post-query-submit' ) );
			}
		}

		if ( ( 'spam' === $comment_status || 'trash' === $comment_status ) && $has_items
			&& current_user_can( 'moderate_comments' )
		) {
			wp_nonce_field( 'bulk-destroy', '_destroy_nonce' );
			$title = ( 'spam' === $comment_status ) ? esc_attr__( 'Empty Spam' ) : esc_attr__( 'Empty Trash' );
			submit_button( $title, 'apply', 'delete_all', false );
		}

		/**
		 * Fires after the Filter submit button for comment types.
		 *
		 * @since 2.5.0
		 * @since 5.6.0 The `$which` parameter was added.
		 *
		 * @param string $comment_status The comment status name. Default 'All'.
		 * @param string $which          The location of the extra table nav markup: Either 'top' or 'bottom'.
		 */
		do_action( 'manage_comments_nav', $comment_status, $which );

		echo '</div>';
	}

	/**
	 * @return string|false
	 */
	public function current_action() {
		if ( isset( $_REQUEST['delete_all'] ) || isset( $_REQUEST['delete_all2'] ) ) {
			return 'delete_all';
		}

		return parent::current_action();
	}

	/**
	 * @global int $post_id
	 *
	 * @return string[] Array of column titles keyed by their column name.
	 */
	public function get_columns() {
		global $post_id;

		$columns = array();

		if ( $this->checkbox ) {
			$columns['cb'] = '<input type="checkbox" />';
		}

		$columns['author']  = __( 'Author' );
		$columns['comment'] = _x( 'Comment', 'column name' );

		if ( ! $post_id ) {
			/* translators: Column name or table row header. */
			$columns['response'] = __( 'In response to' );
		}

		$columns['date'] = _x( 'Submitted on', 'column name' );

		return $columns;
	}

	/**
	 * Displays a comment type drop-down for filtering on the Comments list table.
	 *
	 * @since 5.5.0
	 * @since 5.6.0 Renamed from `comment_status_dropdown()` to `comment_type_dropdown()`.
	 *
	 * @param string $comment_type The current comment type slug.
	 */
	protected function comment_type_dropdown( $comment_type ) {
		/**
		 * Filters the comment types shown in the drop-down menu on the Comments list table.
		 *
		 * @since 2.7.0
		 *
		 * @param string[] $comment_types Array of comment type labels keyed by their name.
		 */
		$comment_types = apply_filters(
			'admin_comment_types_dropdown',
			array(
				'comment' => __( 'Comments' ),
				'pings'   => __( 'Pings' ),
			)
		);

		if ( $comment_types && is_array( $comment_types ) ) {
			printf(
				'<label class="screen-reader-text" for="filter-by-comment-type">%s</label>',
				/* translators: Hidden accessibility text. */
				__( 'Filter by comment type' )
			);

			echo '<select id="filter-by-comment-type" name="comment_type">';

			printf( "\t<option value=''>%s</option>", __( 'All comment types' ) );

			foreach ( $comment_types as $type => $label ) {
				if ( get_comments(
					array(
						'count'   => true,
						'orderby' => 'none',
						'type'    => $type,
					)
				) ) {
					printf(
						"\t<option value='%s'%s>%s</option>\n",
						esc_attr( $type ),
						selected( $comment_type, $type, false ),
						esc_html( $label )
					);
				}
			}

			echo '</select>';
		}
	}

	/**
	 * @return array
	 */
	protected function get_sortable_columns() {
		return array(
			'author'   => array( 'comment_author', false, __( 'Author' ), __( 'Table ordered by Comment Author.' ) ),
			'response' => array( 'comment_post_ID', false, _x( 'In Response To', 'column name' ), __( 'Table ordered by Post Replied To.' ) ),
			'date'     => 'comment_date',
		);
	}

	/**
	 * Gets the name of the default primary column.
	 *
	 * @since 4.3.0
	 *
	 * @return string Name of the default primary column, in this case, 'comment'.
	 */
	protected function get_default_primary_column_name() {
		return 'comment';
	}

	/**
	 * Displays the comments table.
	 *
	 * Overrides the parent display() method to render extra comments.
	 *
	 * @since 3.1.0
	 */
	public function display() {
		wp_nonce_field( 'fetch-list-' . get_class( $this ), '_ajax_fetch_list_nonce' );
		static $has_items;

		if ( ! isset( $has_items ) ) {
			$has_items = $this->has_items();

			if ( $has_items ) {
				$this->display_tablenav( 'top' );
			}
		}

		$this->screen->render_screen_reader_content( 'heading_list' );

		?>
<table class="wp-list-table <?php echo implode( ' ', $this->get_table_classes() ); ?>">
		<?php
		if ( ! isset( $_GET['orderby'] ) ) {
			// In the initial view, Comments are ordered by comment's date but there's no column for that.
			echo '<caption class="screen-reader-text">' .
			/* translators: Hidden accessibility text. */
			__( 'Ordered by Comment Date, descending.' ) .
			'</caption>';
		} else {
			$this->print_table_description();
		}
		?>
	<thead>
	<tr>
		<?php $this->print_column_headers(); ?>
	</tr>
	</thead>

	<tbody id="the-comment-list" data-wp-lists="list:comment">
		<?php $this->display_rows_or_placeholder(); ?>
	</tbody>

	<tbody id="the-extra-comment-list" data-wp-lists="list:comment" style="display: none;">
		<?php
			/*
			 * Back up the items to restore after printing the extra items markup.
			 * The extra items may be empty, which will prevent the table nav from displaying later.
			 */
			$items       = $this->items;
			$this->items = $this->extra_items;
			$this->display_rows_or_placeholder();
			$this->items = $items;
		?>
	</tbody>

	<tfoot>
	<tr>
		<?php $this->print_column_headers( false ); ?>
	</tr>
	</tfoot>

</table>
		<?php

		$this->display_tablenav( 'bottom' );
	}

	/**
	 * @global WP_Post    $post    Global post object.
	 * @global WP_Comment $comment Global comment object.
	 *
	 * @param WP_Comment $item
	 */
	public function single_row( $item ) {
		global $post, $comment;

		// Restores the more descriptive, specific name for use within this method.
		$comment = $item;

		if ( $comment->comment_post_ID > 0 ) {
			$post = get_post( $comment->comment_post_ID );
		}

		$edit_post_cap = $post ? 'edit_post' : 'edit_posts';

		if ( ! current_user_can( $edit_post_cap, $comment->comment_post_ID )
			&& ( post_password_required( $comment->comment_post_ID )
				|| ! current_user_can( 'read_post', $comment->comment_post_ID ) )
		) {
			// The user has no access to the post and thus cannot see the comments.
			return false;
		}

		$the_comment_class = wp_get_comment_status( $comment );

		if ( ! $the_comment_class ) {
			$the_comment_class = '';
		}

		$the_comment_class = implode( ' ', get_comment_class( $the_comment_class, $comment, $comment->comment_post_ID ) );

		$this->user_can = current_user_can( 'edit_comment', $comment->comment_ID );

		echo "<tr id='comment-$comment->comment_ID' class='$the_comment_class'>";
		$this->single_row_columns( $comment );
		echo "</tr>\n";

		unset( $GLOBALS['post'], $GLOBALS['comment'] );
	}

	/**
	 * Generates and displays row actions links.
	 *
	 * @since 4.3.0
	 * @since 5.9.0 Renamed `$comment` to `$item` to match parent class for PHP 8 named parameter support.
	 *
	 * @global string $comment_status Status for the current listed comments.
	 *
	 * @param WP_Comment $item        The comment object.
	 * @param string     $column_name Current column name.
	 * @param string     $primary     Primary column name.
	 * @return string Row actions output for comments. An empty string
	 *                if the current column is not the primary column,
	 *                or if the current user cannot edit the comment.
	 */
	protected function handle_row_actions( $item, $column_name, $primary ) {
		global $comment_status;

		if ( $primary !== $column_name ) {
			return '';
		}

		if ( ! $this->user_can ) {
			return '';
		}

		// Restores the more descriptive, specific name for use within this method.
		$comment = $item;

		$the_comment_status = wp_get_comment_status( $comment );

		$output = '';

		$approve_nonce = esc_html( '_wpnonce=' . wp_create_nonce( 'approve-comment_' . $comment->comment_ID ) );
		$del_nonce     = esc_html( '_wpnonce=' . wp_create_nonce( 'delete-comment_' . $comment->comment_ID ) );

		$action_string = 'comment.php?action=%s&c=' . $comment->comment_ID . '&%s';

		$approve_url   = sprintf( $action_string, 'approvecomment', $approve_nonce );
		$unapprove_url = sprintf( $action_string, 'unapprovecomment', $approve_nonce );
		$spam_url      = sprintf( $action_string, 'spamcomment', $del_nonce );
		$unspam_url    = sprintf( $action_string, 'unspamcomment', $del_nonce );
		$trash_url     = sprintf( $action_string, 'trashcomment', $del_nonce );
		$untrash_url   = sprintf( $action_string, 'untrashcomment', $del_nonce );
		$delete_url    = sprintf( $action_string, 'deletecomment', $del_nonce );

		// Preorder it: Approve | Reply | Quick Edit | Edit | Spam | Trash.
		$actions = array(
			'approve'   => '',
			'unapprove' => '',
			'reply'     => '',
			'quickedit' => '',
			'edit'      => '',
			'spam'      => '',
			'unspam'    => '',
			'trash'     => '',
			'untrash'   => '',
			'delete'    => '',
		);

		// Not looking at all comments.
		if ( $comment_status && 'all' !== $comment_status ) {
			if ( 'approved' === $the_comment_status ) {
				$actions['unapprove'] = sprintf(
					'<a href="%s" data-wp-lists="%s" class="vim-u vim-destructive aria-button-if-js" aria-label="%s">%s</a>',
					esc_url( $unapprove_url ),
					"delete:the-comment-list:comment-{$comment->comment_ID}:e7e7d3:action=dim-comment&amp;new=unapproved",
					esc_attr__( 'Unapprove this comment' ),
					__( 'Unapprove' )
				);
			} elseif ( 'unapproved' === $the_comment_status ) {
				$actions['approve'] = sprintf(
					'<a href="%s" data-wp-lists="%s" class="vim-a vim-destructive aria-button-if-js" aria-label="%s">%s</a>',
					esc_url( $approve_url ),
					"delete:the-comment-list:comment-{$comment->comment_ID}:e7e7d3:action=dim-comment&amp;new=approved",
					esc_attr__( 'Approve this comment' ),
					__( 'Approve' )
				);
			}
		} else {
			$actions['approve'] = sprintf(
				'<a href="%s" data-wp-lists="%s" class="vim-a aria-button-if-js" aria-label="%s">%s</a>',
				esc_url( $approve_url ),
				"dim:the-comment-list:comment-{$comment->comment_ID}:unapproved:e7e7d3:e7e7d3:new=approved",
				esc_attr__( 'Approve this comment' ),
				__( 'Approve' )
			);

			$actions['unapprove'] = sprintf(
				'<a href="%s" data-wp-lists="%s" class="vim-u aria-button-if-js" aria-label="%s">%s</a>',
				esc_url( $unapprove_url ),
				"dim:the-comment-list:comment-{$comment->comment_ID}:unapproved:e7e7d3:e7e7d3:new=unapproved",
				esc_attr__( 'Unapprove this comment' ),
				__( 'Unapprove' )
			);
		}

		if ( 'spam' !== $the_comment_status ) {
			$actions['spam'] = sprintf(
				'<a href="%s" data-wp-lists="%s" class="vim-s vim-destructive aria-button-if-js" aria-label="%s">%s</a>',
				esc_url( $spam_url ),
				"delete:the-comment-list:comment-{$comment->comment_ID}::spam=1",
				esc_attr__( 'Mark this comment as spam' ),
				/* translators: "Mark as spam" link. */
				_x( 'Spam', 'verb' )
			);
		} elseif ( 'spam' === $the_comment_status ) {
			$actions['unspam'] = sprintf(
				'<a href="%s" data-wp-lists="%s" class="vim-z vim-destructive aria-button-if-js" aria-label="%s">%s</a>',
				esc_url( $unspam_url ),
				"delete:the-comment-list:comment-{$comment->comment_ID}:66cc66:unspam=1",
				esc_attr__( 'Restore this comment from the spam' ),
				_x( 'Not Spam', 'comment' )
			);
		}

		if ( 'trash' === $the_comment_status ) {
			$actions['untrash'] = sprintf(
				'<a href="%s" data-wp-lists="%s" class="vim-z vim-destructive aria-button-if-js" aria-label="%s">%s</a>',
				esc_url( $untrash_url ),
				"delete:the-comment-list:comment-{$comment->comment_ID}:66cc66:untrash=1",
				esc_attr__( 'Restore this comment from the Trash' ),
				__( 'Restore' )
			);
		}

		if ( 'spam' === $the_comment_status || 'trash' === $the_comment_status || ! EMPTY_TRASH_DAYS ) {
			$actions['delete'] = sprintf(
				'<a href="%s" data-wp-lists="%s" class="delete vim-d vim-destructive aria-button-if-js" aria-label="%s">%s</a>',
				esc_url( $delete_url ),
				"delete:the-comment-list:comment-{$comment->comment_ID}::delete=1",
				esc_attr__( 'Delete this comment permanently' ),
				__( 'Delete Permanently' )
			);
		} else {
			$actions['trash'] = sprintf(
				'<a href="%s" data-wp-lists="%s" class="delete vim-d vim-destructive aria-button-if-js" aria-label="%s">%s</a>',
				esc_url( $trash_url ),
				"delete:the-comment-list:comment-{$comment->comment_ID}::trash=1",
				esc_attr__( 'Move this comment to the Trash' ),
				_x( 'Trash', 'verb' )
			);
		}

		if ( 'spam' !== $the_comment_status && 'trash' !== $the_comment_status ) {
			$actions['edit'] = sprintf(
				'<a href="%s" aria-label="%s">%s</a>',
				"comment.php?action=editcomment&amp;c={$comment->comment_ID}",
				esc_attr__( 'Edit this comment' ),
				__( 'Edit' )
			);

			$format = '<button type="button" data-comment-id="%d" data-post-id="%d" data-action="%s" class="%s button-link" aria-expanded="false" aria-label="%s">%s</button>';

			$actions['quickedit'] = sprintf(
				$format,
				$comment->comment_ID,
				$comment->comment_post_ID,
				'edit',
				'vim-q comment-inline',
				esc_attr__( 'Quick edit this comment inline' ),
				__( 'Quick&nbsp;Edit' )
			);

			$actions['reply'] = sprintf(
				$format,
				$comment->comment_ID,
				$comment->comment_post_ID,
				'replyto',
				'vim-r comment-inline',
				esc_attr__( 'Reply to this comment' ),
				__( 'Reply' )
			);
		}

		/**
		 * Filters the action links displayed for each comment in the Comments list table.
		 *
		 * @since 2.6.0
		 *
		 * @param string[]   $actions An array of comment actions. Default actions include:
		 *                            'Approve', 'Unapprove', 'Edit', 'Reply', 'Spam',
		 *                            'Delete', and 'Trash'.
		 * @param WP_Comment $comment The comment object.
		 */
		$actions = apply_filters( 'comment_row_actions', array_filter( $actions ), $comment );

		$always_visible = false;

		$mode = get_user_setting( 'posts_list_mode', 'list' );

		if ( 'excerpt' === $mode ) {
			$always_visible = true;
		}

		$output .= '<div class="' . ( $always_visible ? 'row-actions visible' : 'row-actions' ) . '">';

		$i = 0;

		foreach ( $actions as $action => $link ) {
			++$i;

			if ( ( ( 'approve' === $action || 'unapprove' === $action ) && 2 === $i )
				|| 1 === $i
			) {
				$separator = '';
			} else {
				$separator = ' | ';
			}

			// Reply and quickedit need a hide-if-no-js span when not added with Ajax.
			if ( ( 'reply' === $action || 'quickedit' === $action ) && ! wp_doing_ajax() ) {
				$action .= ' hide-if-no-js';
			} elseif ( ( 'untrash' === $action && 'trash' === $the_comment_status )
				|| ( 'unspam' === $action && 'spam' === $the_comment_status )
			) {
				if ( '1' === get_comment_meta( $comment->comment_ID, '_wp_trash_meta_status', true ) ) {
					$action .= ' approve';
				} else {
					$action .= ' unapprove';
				}
			}

			$output .= "<span class='$action'>{$separator}{$link}</span>";
		}

		$output .= '</div>';

		$output .= '<button type="button" class="toggle-row"><span class="screen-reader-text">' .
			/* translators: Hidden accessibility text. */
			__( 'Show more details' ) .
		'</span></button>';

		return $output;
	}

	/**
	 * @since 5.9.0 Renamed `$comment` to `$item` to match parent class for PHP 8 named parameter support.
	 *
	 * @param WP_Comment $item The comment object.
	 */
	public function column_cb( $item ) {
		// Restores the more descriptive, specific name for use within this method.
		$comment = $item;

		if ( $this->user_can ) {
			?>
		<input id="cb-select-<?php echo $comment->comment_ID; ?>" type="checkbox" name="delete_comments[]" value="<?php echo $comment->comment_ID; ?>" />
		<label for="cb-select-<?php echo $comment->comment_ID; ?>">
			<span class="screen-reader-text">
			<?php
			/* translators: Hidden accessibility text. */
			_e( 'Select comment' );
			?>
			</span>
		</label>
			<?php
		}
	}

	/**
	 * @param WP_Comment $comment The comment object.
	 */
	public function column_comment( $comment ) {
		echo '<div class="comment-author">';
			$this->column_author( $comment );
		echo '</div>';

		if ( $comment->comment_parent ) {
			$parent = get_comment( $comment->comment_parent );

			if ( $parent ) {
				$parent_link = esc_url( get_comment_link( $parent ) );
				$name        = get_comment_author( $parent );
				printf(
					/* translators: %s: Comment link. */
					__( 'In reply to %s.' ),
					'<a href="' . $parent_link . '">' . $name . '</a>'
				);
			}
		}

		comment_text( $comment );

		if ( $this->user_can ) {
			/** This filter is documented in wp-admin/includes/comment.php */
			$comment_content = apply_filters( 'comment_edit_pre', $comment->comment_content );
			?>
		<div id="inline-<?php echo $comment->comment_ID; ?>" class="hidden">
			<textarea class="comment" rows="1" cols="1"><?php echo esc_textarea( $comment_content ); ?></textarea>
			<div class="author-email"><?php echo esc_html( $comment->comment_author_email ); ?></div>
			<div class="author"><?php echo esc_html( $comment->comment_author ); ?></div>
			<div class="author-url"><?php echo esc_url( $comment->comment_author_url ); ?></div>
			<div class="comment_status"><?php echo $comment->comment_approved; ?></div>
		</div>
			<?php
		}
	}

	/**
	 * @global string $comment_status
	 *
	 * @param WP_Comment $comment The comment object.
	 */
	public function column_author( $comment ) {
		global $comment_status;

		$author_url = get_comment_author_url( $comment );

		$author_url_display = untrailingslashit( preg_replace( '|^http(s)?://(www\.)?|i', '', $author_url ) );

		if ( strlen( $author_url_display ) > 50 ) {
			$author_url_display = wp_html_excerpt( $author_url_display, 49, '&hellip;' );
		}

		echo '<strong>';
		comment_author( $comment );
		echo '</strong><br />';

		if ( ! empty( $author_url_display ) ) {
			// Print link to author URL, and disallow referrer information (without using target="_blank").
			printf(
				'<a href="%s" rel="noopener noreferrer">%s</a><br />',
				esc_url( $author_url ),
				esc_html( $author_url_display )
			);
		}

		if ( $this->user_can ) {
			if ( ! empty( $comment->comment_author_email ) ) {
				/** This filter is documented in wp-includes/comment-template.php */
				$email = apply_filters( 'comment_email', $comment->comment_author_email, $comment );

				if ( ! empty( $email ) && '@' !== $email ) {
					printf( '<a href="%1$s">%2$s</a><br />', esc_url( 'mailto:' . $email ), esc_html( $email ) );
				}
			}

			$author_ip = get_comment_author_IP( $comment );

			if ( $author_ip ) {
				$author_ip_url = add_query_arg(
					array(
						's'    => $author_ip,
						'mode' => 'detail',
					),
					admin_url( 'edit-comments.php' )
				);

				if ( 'spam' === $comment_status ) {
					$author_ip_url = add_query_arg( 'comment_status', 'spam', $author_ip_url );
				}

				printf( '<a href="%1$s">%2$s</a>', esc_url( $author_ip_url ), esc_html( $author_ip ) );
			}
		}
	}

	/**
	 * @param WP_Comment $comment The comment object.
	 */
	public function column_date( $comment ) {
		$submitted = sprintf(
			/* translators: 1: Comment date, 2: Comment time. */
			__( '%1$s at %2$s' ),
			/* translators: Comment date format. See https://www.php.net/manual/datetime.format.php */
			get_comment_date( __( 'Y/m/d' ), $comment ),
			/* translators: Comment time format. See https://www.php.net/manual/datetime.format.php */
			get_comment_date( __( 'g:i a' ), $comment )
		);

		echo '<div class="submitted-on">';

		if ( 'approved' === wp_get_comment_status( $comment ) && ! empty( $comment->comment_post_ID ) ) {
			printf(
				'<a href="%s">%s</a>',
				esc_url( get_comment_link( $comment ) ),
				$submitted
			);
		} else {
			echo $submitted;
		}

		echo '</div>';
	}

	/**
	 * @param WP_Comment $comment The comment object.
	 */
	public function column_response( $comment ) {
		$post = get_post();

		if ( ! $post ) {
			return;
		}

		if ( isset( $this->pending_count[ $post->ID ] ) ) {
			$pending_comments = $this->pending_count[ $post->ID ];
		} else {
			$_pending_count_temp              = get_pending_comments_num( array( $post->ID ) );
			$pending_comments                 = $_pending_count_temp[ $post->ID ];
			$this->pending_count[ $post->ID ] = $pending_comments;
		}

		if ( current_user_can( 'edit_post', $post->ID ) ) {
			$post_link  = "<a href='" . get_edit_post_link( $post->ID ) . "' class='comments-edit-item-link'>";
			$post_link .= esc_html( get_the_title( $post->ID ) ) . '</a>';
		} else {
			$post_link = esc_html( get_the_title( $post->ID ) );
		}

		echo '<div class="response-links">';

		if ( 'attachment' === $post->post_type ) {
			$thumb = wp_get_attachment_image( $post->ID, array( 80, 60 ), true );
			if ( $thumb ) {
				echo $thumb;
			}
		}

		echo $post_link;

		$post_type_object = get_post_type_object( $post->post_type );
		echo "<a href='" . get_permalink( $post->ID ) . "' class='comments-view-item-link'>" . $post_type_object->labels->view_item . '</a>';

		echo '<span class="post-com-count-wrapper post-com-count-', $post->ID, '">';
		$this->comments_bubble( $post->ID, $pending_comments );
		echo '</span> ';

		echo '</div>';
	}

	/**
	 * @since 5.9.0 Renamed `$comment` to `$item` to match parent class for PHP 8 named parameter support.
	 *
	 * @param WP_Comment $item        The comment object.
	 * @param string     $column_name The custom column's name.
	 */
	public function column_default( $item, $column_name ) {
		// Restores the more descriptive, specific name for use within this method.
		$comment = $item;

		/**
		 * Fires when the default column output is displayed for a single row.
		 *
		 * @since 2.8.0
		 *
		 * @param string $column_name The custom column's name.
		 * @param string $comment_id  The comment ID as a numeric string.
		 */
		do_action( 'manage_comments_custom_column', $column_name, $comment->comment_ID );
	}
}
class-wp-filesystem-direct.php000064400000043337151212616050012451 0ustar00<?php
/**
 * WordPress Direct Filesystem.
 *
 * @package WordPress
 * @subpackage Filesystem
 */

/**
 * WordPress Filesystem Class for direct PHP file and folder manipulation.
 *
 * @since 2.5.0
 *
 * @see WP_Filesystem_Base
 */
class WP_Filesystem_Direct extends WP_Filesystem_Base {

	/**
	 * Constructor.
	 *
	 * @since 2.5.0
	 *
	 * @param mixed $arg Not used.
	 */
	public function __construct( $arg ) {
		$this->method = 'direct';
		$this->errors = new WP_Error();
	}

	/**
	 * Reads entire file into a string.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Name of the file to read.
	 * @return string|false Read data on success, false on failure.
	 */
	public function get_contents( $file ) {
		return @file_get_contents( $file );
	}

	/**
	 * Reads entire file into an array.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to the file.
	 * @return array|false File contents in an array on success, false on failure.
	 */
	public function get_contents_array( $file ) {
		return @file( $file );
	}

	/**
	 * Writes a string to a file.
	 *
	 * @since 2.5.0
	 *
	 * @param string    $file     Remote path to the file where to write the data.
	 * @param string    $contents The data to write.
	 * @param int|false $mode     Optional. The file permissions as octal number, usually 0644.
	 *                            Default false.
	 * @return bool True on success, false on failure.
	 */
	public function put_contents( $file, $contents, $mode = false ) {
		$fp = @fopen( $file, 'wb' );

		if ( ! $fp ) {
			return false;
		}

		mbstring_binary_safe_encoding();

		$data_length = strlen( $contents );

		$bytes_written = fwrite( $fp, $contents );

		reset_mbstring_encoding();

		fclose( $fp );

		if ( $data_length !== $bytes_written ) {
			return false;
		}

		$this->chmod( $file, $mode );

		return true;
	}

	/**
	 * Gets the current working directory.
	 *
	 * @since 2.5.0
	 *
	 * @return string|false The current working directory on success, false on failure.
	 */
	public function cwd() {
		return getcwd();
	}

	/**
	 * Changes current directory.
	 *
	 * @since 2.5.0
	 *
	 * @param string $dir The new current directory.
	 * @return bool True on success, false on failure.
	 */
	public function chdir( $dir ) {
		return @chdir( $dir );
	}

	/**
	 * Changes the file group.
	 *
	 * @since 2.5.0
	 *
	 * @param string     $file      Path to the file.
	 * @param string|int $group     A group name or number.
	 * @param bool       $recursive Optional. If set to true, changes file group recursively.
	 *                              Default false.
	 * @return bool True on success, false on failure.
	 */
	public function chgrp( $file, $group, $recursive = false ) {
		if ( ! $this->exists( $file ) ) {
			return false;
		}

		if ( ! $recursive ) {
			return chgrp( $file, $group );
		}

		if ( ! $this->is_dir( $file ) ) {
			return chgrp( $file, $group );
		}

		// Is a directory, and we want recursive.
		$file     = trailingslashit( $file );
		$filelist = $this->dirlist( $file );

		foreach ( $filelist as $filename ) {
			$this->chgrp( $file . $filename, $group, $recursive );
		}

		return true;
	}

	/**
	 * Changes filesystem permissions.
	 *
	 * @since 2.5.0
	 *
	 * @param string    $file      Path to the file.
	 * @param int|false $mode      Optional. The permissions as octal number, usually 0644 for files,
	 *                             0755 for directories. Default false.
	 * @param bool      $recursive Optional. If set to true, changes file permissions recursively.
	 *                             Default false.
	 * @return bool True on success, false on failure.
	 */
	public function chmod( $file, $mode = false, $recursive = false ) {
		if ( ! $mode ) {
			if ( $this->is_file( $file ) ) {
				$mode = FS_CHMOD_FILE;
			} elseif ( $this->is_dir( $file ) ) {
				$mode = FS_CHMOD_DIR;
			} else {
				return false;
			}
		}

		if ( ! $recursive || ! $this->is_dir( $file ) ) {
			return chmod( $file, $mode );
		}

		// Is a directory, and we want recursive.
		$file     = trailingslashit( $file );
		$filelist = $this->dirlist( $file );

		foreach ( (array) $filelist as $filename => $filemeta ) {
			$this->chmod( $file . $filename, $mode, $recursive );
		}

		return true;
	}

	/**
	 * Changes the owner of a file or directory.
	 *
	 * @since 2.5.0
	 *
	 * @param string     $file      Path to the file or directory.
	 * @param string|int $owner     A user name or number.
	 * @param bool       $recursive Optional. If set to true, changes file owner recursively.
	 *                              Default false.
	 * @return bool True on success, false on failure.
	 */
	public function chown( $file, $owner, $recursive = false ) {
		if ( ! $this->exists( $file ) ) {
			return false;
		}

		if ( ! $recursive ) {
			return chown( $file, $owner );
		}

		if ( ! $this->is_dir( $file ) ) {
			return chown( $file, $owner );
		}

		// Is a directory, and we want recursive.
		$filelist = $this->dirlist( $file );

		foreach ( $filelist as $filename ) {
			$this->chown( $file . '/' . $filename, $owner, $recursive );
		}

		return true;
	}

	/**
	 * Gets the file owner.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to the file.
	 * @return string|false Username of the owner on success, false on failure.
	 */
	public function owner( $file ) {
		$owneruid = @fileowner( $file );

		if ( ! $owneruid ) {
			return false;
		}

		if ( ! function_exists( 'posix_getpwuid' ) ) {
			return $owneruid;
		}

		$ownerarray = posix_getpwuid( $owneruid );

		if ( ! $ownerarray ) {
			return false;
		}

		return $ownerarray['name'];
	}

	/**
	 * Gets the permissions of the specified file or filepath in their octal format.
	 *
	 * FIXME does not handle errors in fileperms()
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to the file.
	 * @return string Mode of the file (the last 3 digits).
	 */
	public function getchmod( $file ) {
		return substr( decoct( @fileperms( $file ) ), -3 );
	}

	/**
	 * Gets the file's group.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to the file.
	 * @return string|false The group on success, false on failure.
	 */
	public function group( $file ) {
		$gid = @filegroup( $file );

		if ( ! $gid ) {
			return false;
		}

		if ( ! function_exists( 'posix_getgrgid' ) ) {
			return $gid;
		}

		$grouparray = posix_getgrgid( $gid );

		if ( ! $grouparray ) {
			return false;
		}

		return $grouparray['name'];
	}

	/**
	 * Copies a file.
	 *
	 * @since 2.5.0
	 *
	 * @param string    $source      Path to the source file.
	 * @param string    $destination Path to the destination file.
	 * @param bool      $overwrite   Optional. Whether to overwrite the destination file if it exists.
	 *                               Default false.
	 * @param int|false $mode        Optional. The permissions as octal number, usually 0644 for files,
	 *                               0755 for dirs. Default false.
	 * @return bool True on success, false on failure.
	 */
	public function copy( $source, $destination, $overwrite = false, $mode = false ) {
		if ( ! $overwrite && $this->exists( $destination ) ) {
			return false;
		}

		$rtval = copy( $source, $destination );

		if ( $mode ) {
			$this->chmod( $destination, $mode );
		}

		return $rtval;
	}

	/**
	 * Moves a file or directory.
	 *
	 * After moving files or directories, OPcache will need to be invalidated.
	 *
	 * If moving a directory fails, `copy_dir()` can be used for a recursive copy.
	 *
	 * Use `move_dir()` for moving directories with OPcache invalidation and a
	 * fallback to `copy_dir()`.
	 *
	 * @since 2.5.0
	 *
	 * @param string $source      Path to the source file.
	 * @param string $destination Path to the destination file.
	 * @param bool   $overwrite   Optional. Whether to overwrite the destination file if it exists.
	 *                            Default false.
	 * @return bool True on success, false on failure.
	 */
	public function move( $source, $destination, $overwrite = false ) {
		if ( ! $overwrite && $this->exists( $destination ) ) {
			return false;
		}

		if ( $overwrite && $this->exists( $destination ) && ! $this->delete( $destination, true ) ) {
			// Can't overwrite if the destination couldn't be deleted.
			return false;
		}

		// Try using rename first. if that fails (for example, source is read only) try copy.
		if ( @rename( $source, $destination ) ) {
			return true;
		}

		// Backward compatibility: Only fall back to `::copy()` for single files.
		if ( $this->is_file( $source ) && $this->copy( $source, $destination, $overwrite ) && $this->exists( $destination ) ) {
			$this->delete( $source );

			return true;
		} else {
			return false;
		}
	}

	/**
	 * Deletes a file or directory.
	 *
	 * @since 2.5.0
	 *
	 * @param string       $file      Path to the file or directory.
	 * @param bool         $recursive Optional. If set to true, deletes files and folders recursively.
	 *                                Default false.
	 * @param string|false $type      Type of resource. 'f' for file, 'd' for directory.
	 *                                Default false.
	 * @return bool True on success, false on failure.
	 */
	public function delete( $file, $recursive = false, $type = false ) {
		if ( empty( $file ) ) {
			// Some filesystems report this as /, which can cause non-expected recursive deletion of all files in the filesystem.
			return false;
		}

		$file = str_replace( '\\', '/', $file ); // For Win32, occasional problems deleting files otherwise.

		if ( 'f' === $type || $this->is_file( $file ) ) {
			return @unlink( $file );
		}

		if ( ! $recursive && $this->is_dir( $file ) ) {
			return @rmdir( $file );
		}

		// At this point it's a folder, and we're in recursive mode.
		$file     = trailingslashit( $file );
		$filelist = $this->dirlist( $file, true );

		$retval = true;

		if ( is_array( $filelist ) ) {
			foreach ( $filelist as $filename => $fileinfo ) {
				if ( ! $this->delete( $file . $filename, $recursive, $fileinfo['type'] ) ) {
					$retval = false;
				}
			}
		}

		if ( file_exists( $file ) && ! @rmdir( $file ) ) {
			$retval = false;
		}

		return $retval;
	}

	/**
	 * Checks if a file or directory exists.
	 *
	 * @since 2.5.0
	 *
	 * @param string $path Path to file or directory.
	 * @return bool Whether $path exists or not.
	 */
	public function exists( $path ) {
		return @file_exists( $path );
	}

	/**
	 * Checks if resource is a file.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file File path.
	 * @return bool Whether $file is a file.
	 */
	public function is_file( $file ) {
		return @is_file( $file );
	}

	/**
	 * Checks if resource is a directory.
	 *
	 * @since 2.5.0
	 *
	 * @param string $path Directory path.
	 * @return bool Whether $path is a directory.
	 */
	public function is_dir( $path ) {
		return @is_dir( $path );
	}

	/**
	 * Checks if a file is readable.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to file.
	 * @return bool Whether $file is readable.
	 */
	public function is_readable( $file ) {
		return @is_readable( $file );
	}

	/**
	 * Checks if a file or directory is writable.
	 *
	 * @since 2.5.0
	 *
	 * @param string $path Path to file or directory.
	 * @return bool Whether $path is writable.
	 */
	public function is_writable( $path ) {
		return @is_writable( $path );
	}

	/**
	 * Gets the file's last access time.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to file.
	 * @return int|false Unix timestamp representing last access time, false on failure.
	 */
	public function atime( $file ) {
		return @fileatime( $file );
	}

	/**
	 * Gets the file modification time.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to file.
	 * @return int|false Unix timestamp representing modification time, false on failure.
	 */
	public function mtime( $file ) {
		return @filemtime( $file );
	}

	/**
	 * Gets the file size (in bytes).
	 *
	 * @since 2.5.0
	 *
	 * @param string $file Path to file.
	 * @return int|false Size of the file in bytes on success, false on failure.
	 */
	public function size( $file ) {
		return @filesize( $file );
	}

	/**
	 * Sets the access and modification times of a file.
	 *
	 * Note: If $file doesn't exist, it will be created.
	 *
	 * @since 2.5.0
	 *
	 * @param string $file  Path to file.
	 * @param int    $time  Optional. Modified time to set for file.
	 *                      Default 0.
	 * @param int    $atime Optional. Access time to set for file.
	 *                      Default 0.
	 * @return bool True on success, false on failure.
	 */
	public function touch( $file, $time = 0, $atime = 0 ) {
		if ( 0 === $time ) {
			$time = time();
		}

		if ( 0 === $atime ) {
			$atime = time();
		}

		return touch( $file, $time, $atime );
	}

	/**
	 * Creates a directory.
	 *
	 * @since 2.5.0
	 *
	 * @param string           $path  Path for new directory.
	 * @param int|false        $chmod Optional. The permissions as octal number (or false to skip chmod).
	 *                                Default false.
	 * @param string|int|false $chown Optional. A user name or number (or false to skip chown).
	 *                                Default false.
	 * @param string|int|false $chgrp Optional. A group name or number (or false to skip chgrp).
	 *                                Default false.
	 * @return bool True on success, false on failure.
	 */
	public function mkdir( $path, $chmod = false, $chown = false, $chgrp = false ) {
		// Safe mode fails with a trailing slash under certain PHP versions.
		$path = untrailingslashit( $path );

		if ( empty( $path ) ) {
			return false;
		}

		if ( ! $chmod ) {
			$chmod = FS_CHMOD_DIR;
		}

		if ( ! @mkdir( $path ) ) {
			return false;
		}

		$this->chmod( $path, $chmod );

		if ( $chown ) {
			$this->chown( $path, $chown );
		}

		if ( $chgrp ) {
			$this->chgrp( $path, $chgrp );
		}

		return true;
	}

	/**
	 * Deletes a directory.
	 *
	 * @since 2.5.0
	 *
	 * @param string $path      Path to directory.
	 * @param bool   $recursive Optional. Whether to recursively remove files/directories.
	 *                          Default false.
	 * @return bool True on success, false on failure.
	 */
	public function rmdir( $path, $recursive = false ) {
		return $this->delete( $path, $recursive );
	}

	/**
	 * Gets details for files in a directory or a specific file.
	 *
	 * @since 2.5.0
	 *
	 * @param string $path           Path to directory or file.
	 * @param bool   $include_hidden Optional. Whether to include details of hidden ("." prefixed) files.
	 *                               Default true.
	 * @param bool   $recursive      Optional. Whether to recursively include file details in nested directories.
	 *                               Default false.
	 * @return array|false {
	 *     Array of arrays containing file information. False if unable to list directory contents.
	 *
	 *     @type array ...$0 {
	 *         Array of file information. Note that some elements may not be available on all filesystems.
	 *
	 *         @type string           $name        Name of the file or directory.
	 *         @type string           $perms       *nix representation of permissions.
	 *         @type string           $permsn      Octal representation of permissions.
	 *         @type false            $number      File number. Always false in this context.
	 *         @type string|false     $owner       Owner name or ID, or false if not available.
	 *         @type string|false     $group       File permissions group, or false if not available.
	 *         @type int|string|false $size        Size of file in bytes. May be a numeric string.
	 *                                             False if not available.
	 *         @type int|string|false $lastmodunix Last modified unix timestamp. May be a numeric string.
	 *                                             False if not available.
	 *         @type string|false     $lastmod     Last modified month (3 letters) and day (without leading 0), or
	 *                                             false if not available.
	 *         @type string|false     $time        Last modified time, or false if not available.
	 *         @type string           $type        Type of resource. 'f' for file, 'd' for directory, 'l' for link.
	 *         @type array|false      $files       If a directory and `$recursive` is true, contains another array of
	 *                                             files. False if unable to list directory contents.
	 *     }
	 * }
	 */
	public function dirlist( $path, $include_hidden = true, $recursive = false ) {
		if ( $this->is_file( $path ) ) {
			$limit_file = basename( $path );
			$path       = dirname( $path );
		} else {
			$limit_file = false;
		}

		if ( ! $this->is_dir( $path ) || ! $this->is_readable( $path ) ) {
			return false;
		}

		$dir = dir( $path );

		if ( ! $dir ) {
			return false;
		}

		$path = trailingslashit( $path );
		$ret  = array();

		while ( false !== ( $entry = $dir->read() ) ) {
			$struc         = array();
			$struc['name'] = $entry;

			if ( '.' === $struc['name'] || '..' === $struc['name'] ) {
				continue;
			}

			if ( ! $include_hidden && '.' === $struc['name'][0] ) {
				continue;
			}

			if ( $limit_file && $struc['name'] !== $limit_file ) {
				continue;
			}

			$struc['perms']       = $this->gethchmod( $path . $entry );
			$struc['permsn']      = $this->getnumchmodfromh( $struc['perms'] );
			$struc['number']      = false;
			$struc['owner']       = $this->owner( $path . $entry );
			$struc['group']       = $this->group( $path . $entry );
			$struc['size']        = $this->size( $path . $entry );
			$struc['lastmodunix'] = $this->mtime( $path . $entry );
			$struc['lastmod']     = gmdate( 'M j', $struc['lastmodunix'] );
			$struc['time']        = gmdate( 'h:i:s', $struc['lastmodunix'] );
			$struc['type']        = $this->is_dir( $path . $entry ) ? 'd' : 'f';

			if ( 'd' === $struc['type'] ) {
				if ( $recursive ) {
					$struc['files'] = $this->dirlist( $path . $struc['name'], $include_hidden, $recursive );
				} else {
					$struc['files'] = array();
				}
			}

			$ret[ $struc['name'] ] = $struc;
		}

		$dir->close();
		unset( $dir );

		return $ret;
	}
}
options.php000064400000010302151212616050006743 0ustar00<?php
/**
 * WordPress Options Administration API.
 *
 * @package WordPress
 * @subpackage Administration
 * @since 4.4.0
 */

/**
 * Output JavaScript to toggle display of additional settings if avatars are disabled.
 *
 * @since 4.2.0
 */
function options_discussion_add_js() {
	?>
	<script>
	(function($){
		var parent = $( '#show_avatars' ),
			children = $( '.avatar-settings' );
		parent.on( 'change', function(){
			children.toggleClass( 'hide-if-js', ! this.checked );
		});
	})(jQuery);
	</script>
	<?php
}

/**
 * Display JavaScript on the page.
 *
 * @since 3.5.0
 */
function options_general_add_js() {
	?>
<script type="text/javascript">
	jQuery( function($) {
		var $siteName = $( '#wp-admin-bar-site-name' ).children( 'a' ).first(),
			$siteIconPreview = $('#site-icon-preview-site-title'),
			homeURL = ( <?php echo wp_json_encode( get_home_url(), JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ); ?> || '' ).replace( /^(https?:\/\/)?(www\.)?/, '' );

		$( '#blogname' ).on( 'input', function() {
			var title = $.trim( $( this ).val() ) || homeURL;

			// Truncate to 40 characters.
			if ( 40 < title.length ) {
				title = title.substring( 0, 40 ) + '\u2026';
			}

			$siteName.text( title );
			$siteIconPreview.text( title );
		});

		$( 'input[name="date_format"]' ).on( 'click', function() {
			if ( 'date_format_custom_radio' !== $(this).attr( 'id' ) )
				$( 'input[name="date_format_custom"]' ).val( $( this ).val() ).closest( 'fieldset' ).find( '.example' ).text( $( this ).parent( 'label' ).children( '.format-i18n' ).text() );
		});

		$( 'input[name="date_format_custom"]' ).on( 'click input', function() {
			$( '#date_format_custom_radio' ).prop( 'checked', true );
		});

		$( 'input[name="time_format"]' ).on( 'click', function() {
			if ( 'time_format_custom_radio' !== $(this).attr( 'id' ) )
				$( 'input[name="time_format_custom"]' ).val( $( this ).val() ).closest( 'fieldset' ).find( '.example' ).text( $( this ).parent( 'label' ).children( '.format-i18n' ).text() );
		});

		$( 'input[name="time_format_custom"]' ).on( 'click input', function() {
			$( '#time_format_custom_radio' ).prop( 'checked', true );
		});

		$( 'input[name="date_format_custom"], input[name="time_format_custom"]' ).on( 'input', function() {
			var format = $( this ),
				fieldset = format.closest( 'fieldset' ),
				example = fieldset.find( '.example' ),
				spinner = fieldset.find( '.spinner' );

			// Debounce the event callback while users are typing.
			clearTimeout( $.data( this, 'timer' ) );
			$( this ).data( 'timer', setTimeout( function() {
				// If custom date is not empty.
				if ( format.val() ) {
					spinner.addClass( 'is-active' );

					$.post( ajaxurl, {
						action: 'date_format_custom' === format.attr( 'name' ) ? 'date_format' : 'time_format',
						date 	: format.val()
					}, function( d ) { spinner.removeClass( 'is-active' ); example.text( d ); } );
				}
			}, 500 ) );
		} );

		var languageSelect = $( '#WPLANG' );
		$( 'form' ).on( 'submit', function() {
			/*
			 * Don't show a spinner for English and installed languages,
			 * as there is nothing to download.
			 */
			if ( ! languageSelect.find( 'option:selected' ).data( 'installed' ) ) {
				$( '#submit', this ).after( '<span class="spinner language-install-spinner is-active" />' );
			}
		});
	} );
</script>
	<?php
}

/**
 * Display JavaScript on the page.
 *
 * @since 3.5.0
 */
function options_reading_add_js() {
	?>
<script type="text/javascript">
	jQuery( function($) {
		var section = $('#front-static-pages'),
			staticPage = section.find('input:radio[value="page"]'),
			selects = section.find('select'),
			check_disabled = function(){
				selects.prop( 'disabled', ! staticPage.prop('checked') );
			};
		check_disabled();
		section.find( 'input:radio' ).on( 'change', check_disabled );
	} );
</script>
	<?php
}

/**
 * Render the site charset setting.
 *
 * @since 3.5.0
 */
function options_reading_blog_charset() {
	echo '<input name="blog_charset" type="text" id="blog_charset" value="' . esc_attr( get_option( 'blog_charset' ) ) . '" class="regular-text" />';
	echo '<p class="description">' . __( 'The <a href="https://wordpress.org/documentation/article/wordpress-glossary/#character-set">character encoding</a> of your site (UTF-8 is recommended)' ) . '</p>';
}
class-plugin-installer-skin.php000064400000027425151212616050012624 0ustar00<?php
/**
 * Upgrader API: Plugin_Installer_Skin class
 *
 * @package WordPress
 * @subpackage Upgrader
 * @since 4.6.0
 */

/**
 * Plugin Installer Skin for WordPress Plugin Installer.
 *
 * @since 2.8.0
 * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader-skins.php.
 *
 * @see WP_Upgrader_Skin
 */
class Plugin_Installer_Skin extends WP_Upgrader_Skin {
	public $api;
	public $type;
	public $url;
	public $overwrite;

	private $is_downgrading = false;

	/**
	 * Constructor.
	 *
	 * Sets up the plugin installer skin.
	 *
	 * @since 2.8.0
	 *
	 * @param array $args
	 */
	public function __construct( $args = array() ) {
		$defaults = array(
			'type'      => 'web',
			'url'       => '',
			'plugin'    => '',
			'nonce'     => '',
			'title'     => '',
			'overwrite' => '',
		);
		$args     = wp_parse_args( $args, $defaults );

		$this->type      = $args['type'];
		$this->url       = $args['url'];
		$this->api       = isset( $args['api'] ) ? $args['api'] : array();
		$this->overwrite = $args['overwrite'];

		parent::__construct( $args );
	}

	/**
	 * Performs an action before installing a plugin.
	 *
	 * @since 2.8.0
	 */
	public function before() {
		if ( ! empty( $this->api ) ) {
			$this->upgrader->strings['process_success'] = sprintf(
				$this->upgrader->strings['process_success_specific'],
				$this->api->name,
				$this->api->version
			);
		}
	}

	/**
	 * Hides the `process_failed` error when updating a plugin by uploading a zip file.
	 *
	 * @since 5.5.0
	 *
	 * @param WP_Error $wp_error WP_Error object.
	 * @return bool True if the error should be hidden, false otherwise.
	 */
	public function hide_process_failed( $wp_error ) {
		if (
			'upload' === $this->type &&
			'' === $this->overwrite &&
			$wp_error->get_error_code() === 'folder_exists'
		) {
			return true;
		}

		return false;
	}

	/**
	 * Performs an action following a plugin install.
	 *
	 * @since 2.8.0
	 */
	public function after() {
		// Check if the plugin can be overwritten and output the HTML.
		if ( $this->do_overwrite() ) {
			return;
		}

		$plugin_file = $this->upgrader->plugin_info();

		$install_actions = array();

		$from = isset( $_GET['from'] ) ? wp_unslash( $_GET['from'] ) : 'plugins';

		if ( 'import' === $from ) {
			$install_actions['activate_plugin'] = sprintf(
				'<a class="button button-primary" href="%s" target="_parent">%s</a>',
				wp_nonce_url( 'plugins.php?action=activate&amp;from=import&amp;plugin=' . urlencode( $plugin_file ), 'activate-plugin_' . $plugin_file ),
				__( 'Activate Plugin &amp; Run Importer' )
			);
		} elseif ( 'press-this' === $from ) {
			$install_actions['activate_plugin'] = sprintf(
				'<a class="button button-primary" href="%s" target="_parent">%s</a>',
				wp_nonce_url( 'plugins.php?action=activate&amp;from=press-this&amp;plugin=' . urlencode( $plugin_file ), 'activate-plugin_' . $plugin_file ),
				__( 'Activate Plugin &amp; Go to Press This' )
			);
		} else {
			$install_actions['activate_plugin'] = sprintf(
				'<a class="button button-primary" href="%s" target="_parent">%s</a>',
				wp_nonce_url( 'plugins.php?action=activate&amp;plugin=' . urlencode( $plugin_file ), 'activate-plugin_' . $plugin_file ),
				__( 'Activate Plugin' )
			);
		}

		if ( is_multisite() && current_user_can( 'manage_network_plugins' ) ) {
			$install_actions['network_activate'] = sprintf(
				'<a class="button button-primary" href="%s" target="_parent">%s</a>',
				wp_nonce_url( 'plugins.php?action=activate&amp;networkwide=1&amp;plugin=' . urlencode( $plugin_file ), 'activate-plugin_' . $plugin_file ),
				_x( 'Network Activate', 'plugin' )
			);
			unset( $install_actions['activate_plugin'] );
		}

		if ( 'import' === $from ) {
			$install_actions['importers_page'] = sprintf(
				'<a href="%s" target="_parent">%s</a>',
				admin_url( 'import.php' ),
				__( 'Go to Importers' )
			);
		} elseif ( 'web' === $this->type ) {
			$install_actions['plugins_page'] = sprintf(
				'<a href="%s" target="_parent">%s</a>',
				self_admin_url( 'plugin-install.php' ),
				__( 'Go to Plugin Installer' )
			);
		} elseif ( 'upload' === $this->type && 'plugins' === $from ) {
			$install_actions['plugins_page'] = sprintf(
				'<a href="%s">%s</a>',
				self_admin_url( 'plugin-install.php' ),
				__( 'Go to Plugin Installer' )
			);
		} else {
			$install_actions['plugins_page'] = sprintf(
				'<a href="%s" target="_parent">%s</a>',
				self_admin_url( 'plugins.php' ),
				__( 'Go to Plugins page' )
			);
		}

		if ( ! $this->result || is_wp_error( $this->result ) ) {
			unset( $install_actions['activate_plugin'], $install_actions['network_activate'] );
		} elseif ( ! current_user_can( 'activate_plugin', $plugin_file ) || is_plugin_active( $plugin_file ) ) {
			unset( $install_actions['activate_plugin'] );
		}

		/**
		 * Filters the list of action links available following a single plugin installation.
		 *
		 * @since 2.7.0
		 *
		 * @param string[] $install_actions Array of plugin action links.
		 * @param object   $api             Object containing WordPress.org API plugin data. Empty
		 *                                  for non-API installs, such as when a plugin is installed
		 *                                  via upload.
		 * @param string   $plugin_file     Path to the plugin file relative to the plugins directory.
		 */
		$install_actions = apply_filters( 'install_plugin_complete_actions', $install_actions, $this->api, $plugin_file );

		if ( ! empty( $install_actions ) ) {
			$this->feedback( implode( ' ', (array) $install_actions ) );
		}
	}

	/**
	 * Checks if the plugin can be overwritten and outputs the HTML for overwriting a plugin on upload.
	 *
	 * @since 5.5.0
	 *
	 * @return bool Whether the plugin can be overwritten and HTML was outputted.
	 */
	private function do_overwrite() {
		if ( 'upload' !== $this->type || ! is_wp_error( $this->result ) || 'folder_exists' !== $this->result->get_error_code() ) {
			return false;
		}

		$folder = $this->result->get_error_data( 'folder_exists' );
		$folder = ltrim( substr( $folder, strlen( WP_PLUGIN_DIR ) ), '/' );

		$current_plugin_data = false;
		$all_plugins         = get_plugins();

		foreach ( $all_plugins as $plugin => $plugin_data ) {
			if ( strrpos( $plugin, $folder ) !== 0 ) {
				continue;
			}

			$current_plugin_data = $plugin_data;
		}

		$new_plugin_data = $this->upgrader->new_plugin_data;

		if ( ! $current_plugin_data || ! $new_plugin_data ) {
			return false;
		}

		echo '<h2 class="update-from-upload-heading">' . esc_html__( 'This plugin is already installed.' ) . '</h2>';

		$this->is_downgrading = version_compare( $current_plugin_data['Version'], $new_plugin_data['Version'], '>' );

		$rows = array(
			'Name'        => __( 'Plugin name' ),
			'Version'     => __( 'Version' ),
			'Author'      => __( 'Author' ),
			'RequiresWP'  => __( 'Required WordPress version' ),
			'RequiresPHP' => __( 'Required PHP version' ),
		);

		$table  = '<table class="update-from-upload-comparison"><tbody>';
		$table .= '<tr><th></th><th>' . esc_html_x( 'Current', 'plugin' ) . '</th>';
		$table .= '<th>' . esc_html_x( 'Uploaded', 'plugin' ) . '</th></tr>';

		$is_same_plugin = true; // Let's consider only these rows.

		foreach ( $rows as $field => $label ) {
			$old_value = ! empty( $current_plugin_data[ $field ] ) ? (string) $current_plugin_data[ $field ] : '-';
			$new_value = ! empty( $new_plugin_data[ $field ] ) ? (string) $new_plugin_data[ $field ] : '-';

			$is_same_plugin = $is_same_plugin && ( $old_value === $new_value );

			$diff_field   = ( 'Version' !== $field && $new_value !== $old_value );
			$diff_version = ( 'Version' === $field && $this->is_downgrading );

			$table .= '<tr><td class="name-label">' . $label . '</td><td>' . wp_strip_all_tags( $old_value ) . '</td>';
			$table .= ( $diff_field || $diff_version ) ? '<td class="warning">' : '<td>';
			$table .= wp_strip_all_tags( $new_value ) . '</td></tr>';
		}

		$table .= '</tbody></table>';

		/**
		 * Filters the compare table output for overwriting a plugin package on upload.
		 *
		 * @since 5.5.0
		 *
		 * @param string $table               The output table with Name, Version, Author, RequiresWP, and RequiresPHP info.
		 * @param array  $current_plugin_data Array with current plugin data.
		 * @param array  $new_plugin_data     Array with uploaded plugin data.
		 */
		echo apply_filters( 'install_plugin_overwrite_comparison', $table, $current_plugin_data, $new_plugin_data );

		$install_actions = array();
		$can_update      = true;

		$blocked_message  = '<p>' . esc_html__( 'The plugin cannot be updated due to the following:' ) . '</p>';
		$blocked_message .= '<ul class="ul-disc">';

		$requires_php = isset( $new_plugin_data['RequiresPHP'] ) ? $new_plugin_data['RequiresPHP'] : null;
		$requires_wp  = isset( $new_plugin_data['RequiresWP'] ) ? $new_plugin_data['RequiresWP'] : null;

		if ( ! is_php_version_compatible( $requires_php ) ) {
			$error = sprintf(
				/* translators: 1: Current PHP version, 2: Version required by the uploaded plugin. */
				__( 'The PHP version on your server is %1$s, however the uploaded plugin requires %2$s.' ),
				PHP_VERSION,
				$requires_php
			);

			$blocked_message .= '<li>' . esc_html( $error ) . '</li>';
			$can_update       = false;
		}

		if ( ! is_wp_version_compatible( $requires_wp ) ) {
			$error = sprintf(
				/* translators: 1: Current WordPress version, 2: Version required by the uploaded plugin. */
				__( 'Your WordPress version is %1$s, however the uploaded plugin requires %2$s.' ),
				esc_html( wp_get_wp_version() ),
				$requires_wp
			);

			$blocked_message .= '<li>' . esc_html( $error ) . '</li>';
			$can_update       = false;
		}

		$blocked_message .= '</ul>';

		if ( $can_update ) {
			if ( $this->is_downgrading ) {
				$warning = sprintf(
					/* translators: %s: Documentation URL. */
					__( 'You are uploading an older version of a current plugin. You can continue to install the older version, but be sure to <a href="%s">back up your database and files</a> first.' ),
					__( 'https://developer.wordpress.org/advanced-administration/security/backup/' )
				);
			} else {
				$warning = sprintf(
					/* translators: %s: Documentation URL. */
					__( 'You are updating a plugin. Be sure to <a href="%s">back up your database and files</a> first.' ),
					__( 'https://developer.wordpress.org/advanced-administration/security/backup/' )
				);
			}

			echo '<p class="update-from-upload-notice">' . $warning . '</p>';

			$overwrite = $this->is_downgrading ? 'downgrade-plugin' : 'update-plugin';

			$install_actions['overwrite_plugin'] = sprintf(
				'<a class="button button-primary update-from-upload-overwrite" href="%s" target="_parent">%s</a>',
				wp_nonce_url( add_query_arg( 'overwrite', $overwrite, $this->url ), 'plugin-upload' ),
				_x( 'Replace current with uploaded', 'plugin' )
			);
		} else {
			echo $blocked_message;
		}

		$cancel_url = add_query_arg( 'action', 'upload-plugin-cancel-overwrite', $this->url );

		$install_actions['plugins_page'] = sprintf(
			'<a class="button" href="%s">%s</a>',
			wp_nonce_url( $cancel_url, 'plugin-upload-cancel-overwrite' ),
			__( 'Cancel and go back' )
		);

		/**
		 * Filters the list of action links available following a single plugin installation failure
		 * when overwriting is allowed.
		 *
		 * @since 5.5.0
		 *
		 * @param string[] $install_actions Array of plugin action links.
		 * @param object   $api             Object containing WordPress.org API plugin data.
		 * @param array    $new_plugin_data Array with uploaded plugin data.
		 */
		$install_actions = apply_filters( 'install_plugin_overwrite_actions', $install_actions, $this->api, $new_plugin_data );

		if ( ! empty( $install_actions ) ) {
			printf(
				'<p class="update-from-upload-expired hidden">%s</p>',
				__( 'The uploaded file has expired. Please go back and upload it again.' )
			);
			echo '<p class="update-from-upload-actions">' . implode( ' ', (array) $install_actions ) . '</p>';
		}

		return true;
	}
}
class-custom-image-header.php000064400000140207151212616050012203 0ustar00<?php
/**
 * The custom header image script.
 *
 * @package WordPress
 * @subpackage Administration
 */

/**
 * The custom header image class.
 *
 * @since 2.1.0
 */
#[AllowDynamicProperties]
class Custom_Image_Header {

	/**
	 * Callback for administration header.
	 *
	 * @since 2.1.0
	 * @var callable
	 */
	public $admin_header_callback;

	/**
	 * Callback for header div.
	 *
	 * @since 3.0.0
	 * @var callable
	 */
	public $admin_image_div_callback;

	/**
	 * Holds default headers.
	 *
	 * @since 3.0.0
	 * @var array
	 */
	public $default_headers = array();

	/**
	 * Used to trigger a success message when settings updated and set to true.
	 *
	 * @since 3.0.0
	 * @var bool
	 */
	private $updated;

	/**
	 * Constructor - Registers administration header callback.
	 *
	 * @since 2.1.0
	 *
	 * @param callable $admin_header_callback    Administration header callback.
	 * @param callable $admin_image_div_callback Optional. Custom image div output callback.
	 *                                           Default empty string.
	 */
	public function __construct( $admin_header_callback, $admin_image_div_callback = '' ) {
		$this->admin_header_callback    = $admin_header_callback;
		$this->admin_image_div_callback = $admin_image_div_callback;

		add_action( 'admin_menu', array( $this, 'init' ) );

		add_action( 'customize_save_after', array( $this, 'customize_set_last_used' ) );
		add_action( 'wp_ajax_custom-header-crop', array( $this, 'ajax_header_crop' ) );
		add_action( 'wp_ajax_custom-header-add', array( $this, 'ajax_header_add' ) );
		add_action( 'wp_ajax_custom-header-remove', array( $this, 'ajax_header_remove' ) );
	}

	/**
	 * Sets up the hooks for the Custom Header admin page.
	 *
	 * @since 2.1.0
	 */
	public function init() {
		$page = add_theme_page(
			_x( 'Header', 'custom image header' ),
			_x( 'Header', 'custom image header' ),
			'edit_theme_options',
			'custom-header',
			array( $this, 'admin_page' )
		);

		if ( ! $page ) {
			return;
		}

		add_action( "admin_print_scripts-{$page}", array( $this, 'js_includes' ) );
		add_action( "admin_print_styles-{$page}", array( $this, 'css_includes' ) );
		add_action( "admin_head-{$page}", array( $this, 'help' ) );
		add_action( "admin_head-{$page}", array( $this, 'take_action' ), 50 );
		add_action( "admin_head-{$page}", array( $this, 'js' ), 50 );

		if ( $this->admin_header_callback ) {
			add_action( "admin_head-{$page}", $this->admin_header_callback, 51 );
		}
	}

	/**
	 * Adds contextual help.
	 *
	 * @since 3.0.0
	 */
	public function help() {
		get_current_screen()->add_help_tab(
			array(
				'id'      => 'overview',
				'title'   => __( 'Overview' ),
				'content' =>
					'<p>' . __( 'This screen is used to customize the header section of your theme.' ) . '</p>' .
					'<p>' . __( 'You can choose from the theme&#8217;s default header images, or use one of your own. You can also customize how your Site Title and Tagline are displayed.' ) . '<p>',
			)
		);

		get_current_screen()->add_help_tab(
			array(
				'id'      => 'set-header-image',
				'title'   => __( 'Header Image' ),
				'content' =>
					'<p>' . __( 'You can set a custom image header for your site. Simply upload the image and crop it, and the new header will go live immediately. Alternatively, you can use an image that has already been uploaded to your Media Library by clicking the &#8220;Choose Image&#8221; button.' ) . '</p>' .
					'<p>' . __( 'Some themes come with additional header images bundled. If you see multiple images displayed, select the one you would like and click the &#8220;Save Changes&#8221; button.' ) . '</p>' .
					'<p>' . __( 'If your theme has more than one default header image, or you have uploaded more than one custom header image, you have the option of having WordPress display a randomly different image on each page of your site. Click the &#8220;Random&#8221; radio button next to the Uploaded Images or Default Images section to enable this feature.' ) . '</p>' .
					'<p>' . __( 'If you do not want a header image to be displayed on your site at all, click the &#8220;Remove Header Image&#8221; button at the bottom of the Header Image section of this page. If you want to re-enable the header image later, you just have to select one of the other image options and click &#8220;Save Changes&#8221;.' ) . '</p>',
			)
		);

		get_current_screen()->add_help_tab(
			array(
				'id'      => 'set-header-text',
				'title'   => __( 'Header Text' ),
				'content' =>
					'<p>' . sprintf(
						/* translators: %s: URL to General Settings screen. */
						__( 'For most themes, the header text is your Site Title and Tagline, as defined in the <a href="%s">General Settings</a> section.' ),
						admin_url( 'options-general.php' )
					) .
					'</p>' .
					'<p>' . __( 'In the Header Text section of this page, you can choose whether to display this text or hide it. You can also choose a color for the text by clicking the Select Color button and either typing in a legitimate HTML hex value, e.g. &#8220;#ff0000&#8221; for red, or by choosing a color using the color picker.' ) . '</p>' .
					'<p>' . __( 'Do not forget to click &#8220;Save Changes&#8221; when you are done!' ) . '</p>',
			)
		);

		get_current_screen()->set_help_sidebar(
			'<p><strong>' . __( 'For more information:' ) . '</strong></p>' .
			'<p>' . __( '<a href="https://codex.wordpress.org/Appearance_Header_Screen">Documentation on Custom Header</a>' ) . '</p>' .
			'<p>' . __( '<a href="https://wordpress.org/support/forums/">Support forums</a>' ) . '</p>'
		);
	}

	/**
	 * Gets the current step.
	 *
	 * @since 2.6.0
	 *
	 * @return int Current step.
	 */
	public function step() {
		if ( ! isset( $_GET['step'] ) ) {
			return 1;
		}

		$step = (int) $_GET['step'];
		if ( $step < 1 || 3 < $step ||
			( 2 === $step && ! wp_verify_nonce( $_REQUEST['_wpnonce-custom-header-upload'], 'custom-header-upload' ) ) ||
			( 3 === $step && ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'custom-header-crop-image' ) )
		) {
			return 1;
		}

		return $step;
	}

	/**
	 * Sets up the enqueue for the JavaScript files.
	 *
	 * @since 2.1.0
	 */
	public function js_includes() {
		$step = $this->step();

		if ( ( 1 === $step || 3 === $step ) ) {
			wp_enqueue_media();
			wp_enqueue_script( 'custom-header' );
			if ( current_theme_supports( 'custom-header', 'header-text' ) ) {
				wp_enqueue_script( 'wp-color-picker' );
			}
		} elseif ( 2 === $step ) {
			wp_enqueue_script( 'imgareaselect' );
		}
	}

	/**
	 * Sets up the enqueue for the CSS files.
	 *
	 * @since 2.7.0
	 */
	public function css_includes() {
		$step = $this->step();

		if ( ( 1 === $step || 3 === $step ) && current_theme_supports( 'custom-header', 'header-text' ) ) {
			wp_enqueue_style( 'wp-color-picker' );
		} elseif ( 2 === $step ) {
			wp_enqueue_style( 'imgareaselect' );
		}
	}

	/**
	 * Executes custom header modification.
	 *
	 * @since 2.6.0
	 */
	public function take_action() {
		if ( ! current_user_can( 'edit_theme_options' ) ) {
			return;
		}

		if ( empty( $_POST ) ) {
			return;
		}

		$this->updated = true;

		if ( isset( $_POST['resetheader'] ) ) {
			check_admin_referer( 'custom-header-options', '_wpnonce-custom-header-options' );

			$this->reset_header_image();

			return;
		}

		if ( isset( $_POST['removeheader'] ) ) {
			check_admin_referer( 'custom-header-options', '_wpnonce-custom-header-options' );

			$this->remove_header_image();

			return;
		}

		if ( isset( $_POST['text-color'] ) && ! isset( $_POST['display-header-text'] ) ) {
			check_admin_referer( 'custom-header-options', '_wpnonce-custom-header-options' );

			set_theme_mod( 'header_textcolor', 'blank' );
		} elseif ( isset( $_POST['text-color'] ) ) {
			check_admin_referer( 'custom-header-options', '_wpnonce-custom-header-options' );

			$_POST['text-color'] = str_replace( '#', '', $_POST['text-color'] );

			$color = preg_replace( '/[^0-9a-fA-F]/', '', $_POST['text-color'] );

			if ( strlen( $color ) === 6 || strlen( $color ) === 3 ) {
				set_theme_mod( 'header_textcolor', $color );
			} elseif ( ! $color ) {
				set_theme_mod( 'header_textcolor', 'blank' );
			}
		}

		if ( isset( $_POST['default-header'] ) ) {
			check_admin_referer( 'custom-header-options', '_wpnonce-custom-header-options' );

			$this->set_header_image( $_POST['default-header'] );

			return;
		}
	}

	/**
	 * Processes the default headers.
	 *
	 * @since 3.0.0
	 *
	 * @global array $_wp_default_headers
	 */
	public function process_default_headers() {
		global $_wp_default_headers;

		if ( ! isset( $_wp_default_headers ) ) {
			return;
		}

		if ( ! empty( $this->default_headers ) ) {
			return;
		}

		$this->default_headers    = $_wp_default_headers;
		$template_directory_uri   = get_template_directory_uri();
		$stylesheet_directory_uri = get_stylesheet_directory_uri();

		foreach ( array_keys( $this->default_headers ) as $header ) {
			$this->default_headers[ $header ]['url'] = sprintf(
				$this->default_headers[ $header ]['url'],
				$template_directory_uri,
				$stylesheet_directory_uri
			);

			$this->default_headers[ $header ]['thumbnail_url'] = sprintf(
				$this->default_headers[ $header ]['thumbnail_url'],
				$template_directory_uri,
				$stylesheet_directory_uri
			);
		}
	}

	/**
	 * Displays UI for selecting one of several default headers.
	 *
	 * Shows the random image option if this theme has multiple header images.
	 * Random image option is on by default if no header has been set.
	 *
	 * @since 3.0.0
	 *
	 * @param string $type The header type. One of 'default' (for the Uploaded Images control)
	 *                     or 'uploaded' (for the Uploaded Images control).
	 */
	public function show_header_selector( $type = 'default' ) {
		if ( 'default' === $type ) {
			$headers = $this->default_headers;
		} else {
			$headers = get_uploaded_header_images();
			$type    = 'uploaded';
		}

		if ( 1 < count( $headers ) ) {
			echo '<div class="random-header">';
			echo '<label><input name="default-header" type="radio" value="random-' . $type . '-image"' . checked( is_random_header_image( $type ), true, false ) . ' />';
			_e( '<strong>Random:</strong> Show a different image on each page.' );
			echo '</label>';
			echo '</div>';
		}

		echo '<div class="available-headers">';

		foreach ( $headers as $header_key => $header ) {
			$header_thumbnail = $header['thumbnail_url'];
			$header_url       = $header['url'];
			$header_alt_text  = empty( $header['alt_text'] ) ? '' : $header['alt_text'];

			echo '<div class="default-header">';
			echo '<label><input name="default-header" type="radio" value="' . esc_attr( $header_key ) . '" ' . checked( $header_url, get_theme_mod( 'header_image' ), false ) . ' />';
			$width = '';
			if ( ! empty( $header['attachment_id'] ) ) {
				$width = ' width="230"';
			}
			echo '<img src="' . esc_url( set_url_scheme( $header_thumbnail ) ) . '" alt="' . esc_attr( $header_alt_text ) . '"' . $width . ' /></label>';
			echo '</div>';
		}

		echo '<div class="clear"></div></div>';
	}

	/**
	 * Executes JavaScript depending on step.
	 *
	 * @since 2.1.0
	 */
	public function js() {
		$step = $this->step();

		if ( ( 1 === $step || 3 === $step ) && current_theme_supports( 'custom-header', 'header-text' ) ) {
			$this->js_1();
		} elseif ( 2 === $step ) {
			$this->js_2();
		}
	}

	/**
	 * Displays JavaScript based on Step 1 and 3.
	 *
	 * @since 2.6.0
	 */
	public function js_1() {
		$default_color = '';
		if ( current_theme_supports( 'custom-header', 'default-text-color' ) ) {
			$default_color = get_theme_support( 'custom-header', 'default-text-color' );
			if ( $default_color && ! str_contains( $default_color, '#' ) ) {
				$default_color = '#' . $default_color;
			}
		}
		?>
<script type="text/javascript">
(function($){
	var default_color = '<?php echo esc_js( $default_color ); ?>',
		header_text_fields;

	function pickColor(color) {
		$('#name').css('color', color);
		$('#desc').css('color', color);
		$('#text-color').val(color);
	}

	function toggle_text() {
		var checked = $('#display-header-text').prop('checked'),
			text_color;
		header_text_fields.toggle( checked );
		if ( ! checked )
			return;
		text_color = $('#text-color');
		if ( '' === text_color.val().replace('#', '') ) {
			text_color.val( default_color );
			pickColor( default_color );
		} else {
			pickColor( text_color.val() );
		}
	}

	$( function() {
		var text_color = $('#text-color');
		header_text_fields = $('.displaying-header-text');
		text_color.wpColorPicker({
			change: function( event, ui ) {
				pickColor( text_color.wpColorPicker('color') );
			},
			clear: function() {
				pickColor( '' );
			}
		});
		$('#display-header-text').click( toggle_text );
		<?php if ( ! display_header_text() ) : ?>
		toggle_text();
		<?php endif; ?>
	} );
})(jQuery);
</script>
		<?php
	}

	/**
	 * Displays JavaScript based on Step 2.
	 *
	 * @since 2.6.0
	 */
	public function js_2() {

		?>
<script type="text/javascript">
	function onEndCrop( coords ) {
		jQuery( '#x1' ).val(coords.x);
		jQuery( '#y1' ).val(coords.y);
		jQuery( '#width' ).val(coords.w);
		jQuery( '#height' ).val(coords.h);
	}

	jQuery( function() {
		var xinit = <?php echo absint( get_theme_support( 'custom-header', 'width' ) ); ?>;
		var yinit = <?php echo absint( get_theme_support( 'custom-header', 'height' ) ); ?>;
		var ratio = xinit / yinit;
		var ximg = jQuery('img#upload').width();
		var yimg = jQuery('img#upload').height();

		if ( yimg < yinit || ximg < xinit ) {
			if ( ximg / yimg > ratio ) {
				yinit = yimg;
				xinit = yinit * ratio;
			} else {
				xinit = ximg;
				yinit = xinit / ratio;
			}
		}

		jQuery('img#upload').imgAreaSelect({
			handles: true,
			keys: true,
			show: true,
			x1: 0,
			y1: 0,
			x2: xinit,
			y2: yinit,
			<?php
			if ( ! current_theme_supports( 'custom-header', 'flex-height' )
				&& ! current_theme_supports( 'custom-header', 'flex-width' )
			) {
				?>
			aspectRatio: xinit + ':' + yinit,
				<?php
			}
			if ( ! current_theme_supports( 'custom-header', 'flex-height' ) ) {
				?>
			maxHeight: <?php echo get_theme_support( 'custom-header', 'height' ); ?>,
				<?php
			}
			if ( ! current_theme_supports( 'custom-header', 'flex-width' ) ) {
				?>
			maxWidth: <?php echo get_theme_support( 'custom-header', 'width' ); ?>,
				<?php
			}
			?>
			onInit: function () {
				jQuery('#width').val(xinit);
				jQuery('#height').val(yinit);
			},
			onSelectChange: function(img, c) {
				jQuery('#x1').val(c.x1);
				jQuery('#y1').val(c.y1);
				jQuery('#width').val(c.width);
				jQuery('#height').val(c.height);
			}
		});
	} );
</script>
		<?php
	}

	/**
	 * Displays first step of custom header image page.
	 *
	 * @since 2.1.0
	 */
	public function step_1() {
		$this->process_default_headers();
		?>

<div class="wrap">
<h1><?php _e( 'Custom Header' ); ?></h1>

		<?php
		if ( current_user_can( 'customize' ) ) {
			$message = sprintf(
				/* translators: %s: URL to header image configuration in Customizer. */
				__( 'You can now manage and live-preview Custom Header in the <a href="%s">Customizer</a>.' ),
				admin_url( 'customize.php?autofocus[control]=header_image' )
			);
			wp_admin_notice(
				$message,
				array(
					'type'               => 'info',
					'additional_classes' => array( 'hide-if-no-customize' ),
				)
			);
		}

		if ( ! empty( $this->updated ) ) {
			$updated_message = sprintf(
				/* translators: %s: Home URL. */
				__( 'Header updated. <a href="%s">Visit your site</a> to see how it looks.' ),
				esc_url( home_url( '/' ) )
			);
			wp_admin_notice(
				$updated_message,
				array(
					'id'                 => 'message',
					'additional_classes' => array( 'updated' ),
				)
			);
		}
		?>

<h2><?php _e( 'Header Image' ); ?></h2>

<table class="form-table" role="presentation">
<tbody>

		<?php if ( get_custom_header() || display_header_text() ) : ?>
<tr>
<th scope="row"><?php _e( 'Preview' ); ?></th>
<td>
			<?php
			if ( $this->admin_image_div_callback ) {
				call_user_func( $this->admin_image_div_callback );
			} else {
				$custom_header = get_custom_header();
				$header_image  = get_header_image();

				if ( $header_image ) {
					$header_image_style = 'background-image:url(' . esc_url( $header_image ) . ');';
				} else {
					$header_image_style = '';
				}

				if ( $custom_header->width ) {
					$header_image_style .= 'max-width:' . $custom_header->width . 'px;';
				}
				if ( $custom_header->height ) {
					$header_image_style .= 'height:' . $custom_header->height . 'px;';
				}
				?>
	<div id="headimg" style="<?php echo $header_image_style; ?>">
				<?php
				if ( display_header_text() ) {
					$style = ' style="color:#' . get_header_textcolor() . ';"';
				} else {
					$style = ' style="display:none;"';
				}
				?>
		<h1><a id="name" class="displaying-header-text" <?php echo $style; ?> onclick="return false;" href="<?php bloginfo( 'url' ); ?>" tabindex="-1"><?php bloginfo( 'name' ); ?></a></h1>
		<div id="desc" class="displaying-header-text" <?php echo $style; ?>><?php bloginfo( 'description' ); ?></div>
	</div>
			<?php } ?>
</td>
</tr>
		<?php endif; ?>

		<?php if ( current_user_can( 'upload_files' ) && current_theme_supports( 'custom-header', 'uploads' ) ) : ?>
<tr>
<th scope="row"><?php _e( 'Select Image' ); ?></th>
<td>
	<p><?php _e( 'You can select an image to be shown at the top of your site by uploading from your computer or choosing from your media library. After selecting an image you will be able to crop it.' ); ?><br />
			<?php
			if ( ! current_theme_supports( 'custom-header', 'flex-height' )
				&& ! current_theme_supports( 'custom-header', 'flex-width' )
			) {
				printf(
					/* translators: 1: Image width in pixels, 2: Image height in pixels. */
					__( 'Images of exactly <strong>%1$d &times; %2$d pixels</strong> will be used as-is.' ) . '<br />',
					get_theme_support( 'custom-header', 'width' ),
					get_theme_support( 'custom-header', 'height' )
				);
			} elseif ( current_theme_supports( 'custom-header', 'flex-height' ) ) {
				if ( ! current_theme_supports( 'custom-header', 'flex-width' ) ) {
					printf(
						/* translators: %s: Size in pixels. */
						__( 'Images should be at least %s wide.' ) . ' ',
						sprintf(
							/* translators: %d: Custom header width. */
							'<strong>' . __( '%d pixels' ) . '</strong>',
							get_theme_support( 'custom-header', 'width' )
						)
					);
				}
			} elseif ( current_theme_supports( 'custom-header', 'flex-width' ) ) {
				if ( ! current_theme_supports( 'custom-header', 'flex-height' ) ) {
					printf(
						/* translators: %s: Size in pixels. */
						__( 'Images should be at least %s tall.' ) . ' ',
						sprintf(
							/* translators: %d: Custom header height. */
							'<strong>' . __( '%d pixels' ) . '</strong>',
							get_theme_support( 'custom-header', 'height' )
						)
					);
				}
			}

			if ( current_theme_supports( 'custom-header', 'flex-height' )
				|| current_theme_supports( 'custom-header', 'flex-width' )
			) {
				if ( current_theme_supports( 'custom-header', 'width' ) ) {
					printf(
						/* translators: %s: Size in pixels. */
						__( 'Suggested width is %s.' ) . ' ',
						sprintf(
							/* translators: %d: Custom header width. */
							'<strong>' . __( '%d pixels' ) . '</strong>',
							get_theme_support( 'custom-header', 'width' )
						)
					);
				}

				if ( current_theme_supports( 'custom-header', 'height' ) ) {
					printf(
						/* translators: %s: Size in pixels. */
						__( 'Suggested height is %s.' ) . ' ',
						sprintf(
							/* translators: %d: Custom header height. */
							'<strong>' . __( '%d pixels' ) . '</strong>',
							get_theme_support( 'custom-header', 'height' )
						)
					);
				}
			}
			?>
	</p>
	<form enctype="multipart/form-data" id="upload-form" class="wp-upload-form" method="post" action="<?php echo esc_url( add_query_arg( 'step', 2 ) ); ?>">
	<p>
		<label for="upload"><?php _e( 'Choose an image from your computer:' ); ?></label><br />
		<input type="file" id="upload" name="import" />
		<input type="hidden" name="action" value="save" />
			<?php wp_nonce_field( 'custom-header-upload', '_wpnonce-custom-header-upload' ); ?>
			<?php submit_button( _x( 'Upload', 'verb' ), '', 'submit', false ); ?>
	</p>
			<?php
			$modal_update_href = add_query_arg(
				array(
					'page'                          => 'custom-header',
					'step'                          => 2,
					'_wpnonce-custom-header-upload' => wp_create_nonce( 'custom-header-upload' ),
				),
				admin_url( 'themes.php' )
			);
			?>
	<p>
		<label for="choose-from-library-link"><?php _e( 'Or choose an image from your media library:' ); ?></label><br />
		<button id="choose-from-library-link" class="button"
			data-update-link="<?php echo esc_url( $modal_update_href ); ?>"
			data-choose="<?php esc_attr_e( 'Choose a Custom Header' ); ?>"
			data-update="<?php esc_attr_e( 'Set as header' ); ?>"><?php _e( 'Choose Image' ); ?></button>
	</p>
	</form>
</td>
</tr>
		<?php endif; ?>
</tbody>
</table>

<form method="post" action="<?php echo esc_url( add_query_arg( 'step', 1 ) ); ?>">
		<?php submit_button( null, 'screen-reader-text', 'save-header-options', false ); ?>
<table class="form-table" role="presentation">
<tbody>
		<?php if ( get_uploaded_header_images() ) : ?>
<tr>
<th scope="row"><?php _e( 'Uploaded Images' ); ?></th>
<td>
	<p><?php _e( 'You can choose one of your previously uploaded headers, or show a random one.' ); ?></p>
			<?php
			$this->show_header_selector( 'uploaded' );
			?>
</td>
</tr>
			<?php
	endif;
		if ( ! empty( $this->default_headers ) ) :
			?>
<tr>
<th scope="row"><?php _e( 'Default Images' ); ?></th>
<td>
			<?php if ( current_theme_supports( 'custom-header', 'uploads' ) ) : ?>
	<p><?php _e( 'If you do not want to upload your own image, you can use one of these cool headers, or show a random one.' ); ?></p>
	<?php else : ?>
	<p><?php _e( 'You can use one of these cool headers or show a random one on each page.' ); ?></p>
	<?php endif; ?>
			<?php
			$this->show_header_selector( 'default' );
			?>
</td>
</tr>
			<?php
	endif;
		if ( get_header_image() ) :
			?>
<tr>
<th scope="row"><?php _e( 'Remove Image' ); ?></th>
<td>
	<p><?php _e( 'This will remove the header image. You will not be able to restore any customizations.' ); ?></p>
			<?php submit_button( __( 'Remove Header Image' ), '', 'removeheader', false ); ?>
</td>
</tr>
			<?php
	endif;

		$default_image = sprintf(
			get_theme_support( 'custom-header', 'default-image' ),
			get_template_directory_uri(),
			get_stylesheet_directory_uri()
		);

		if ( $default_image && get_header_image() !== $default_image ) :
			?>
<tr>
<th scope="row"><?php _e( 'Reset Image' ); ?></th>
<td>
	<p><?php _e( 'This will restore the original header image. You will not be able to restore any customizations.' ); ?></p>
			<?php submit_button( __( 'Restore Original Header Image' ), '', 'resetheader', false ); ?>
</td>
</tr>
	<?php endif; ?>
</tbody>
</table>

		<?php if ( current_theme_supports( 'custom-header', 'header-text' ) ) : ?>

<h2><?php _e( 'Header Text' ); ?></h2>

<table class="form-table" role="presentation">
<tbody>
<tr>
<th scope="row"><?php _e( 'Header Text' ); ?></th>
<td>
	<p>
	<label><input type="checkbox" name="display-header-text" id="display-header-text"<?php checked( display_header_text() ); ?> /> <?php _e( 'Show header text with your image.' ); ?></label>
	</p>
</td>
</tr>

<tr class="displaying-header-text">
<th scope="row"><?php _e( 'Text Color' ); ?></th>
<td>
	<p>
			<?php
			$default_color = '';
			if ( current_theme_supports( 'custom-header', 'default-text-color' ) ) {
				$default_color = get_theme_support( 'custom-header', 'default-text-color' );
				if ( $default_color && ! str_contains( $default_color, '#' ) ) {
					$default_color = '#' . $default_color;
				}
			}

			$default_color_attr = $default_color ? ' data-default-color="' . esc_attr( $default_color ) . '"' : '';

			$header_textcolor = display_header_text() ? get_header_textcolor() : get_theme_support( 'custom-header', 'default-text-color' );
			if ( $header_textcolor && ! str_contains( $header_textcolor, '#' ) ) {
				$header_textcolor = '#' . $header_textcolor;
			}

			echo '<input type="text" name="text-color" id="text-color" value="' . esc_attr( $header_textcolor ) . '"' . $default_color_attr . ' />';
			if ( $default_color ) {
				/* translators: %s: Default text color. */
				echo ' <span class="description hide-if-js">' . sprintf( _x( 'Default: %s', 'color' ), esc_html( $default_color ) ) . '</span>';
			}
			?>
	</p>
</td>
</tr>
</tbody>
</table>
			<?php
endif;

		/**
		 * Fires just before the submit button in the custom header options form.
		 *
		 * @since 3.1.0
		 */
		do_action( 'custom_header_options' );

		wp_nonce_field( 'custom-header-options', '_wpnonce-custom-header-options' );
		?>

		<?php submit_button( null, 'primary', 'save-header-options' ); ?>
</form>
</div>

		<?php
	}

	/**
	 * Displays second step of custom header image page.
	 *
	 * @since 2.1.0
	 */
	public function step_2() {
		check_admin_referer( 'custom-header-upload', '_wpnonce-custom-header-upload' );

		if ( ! current_theme_supports( 'custom-header', 'uploads' ) ) {
			wp_die(
				'<h1>' . __( 'An error occurred while processing your header image.' ) . '</h1>' .
				'<p>' . __( 'The active theme does not support uploading a custom header image. Please ensure your theme supports custom headers and try again.' ) . '</p>',
				403
			);
		}

		if ( empty( $_POST ) && isset( $_GET['file'] ) ) {
			$attachment_id = absint( $_GET['file'] );
			$file          = get_attached_file( $attachment_id, true );
			$url           = wp_get_attachment_image_src( $attachment_id, 'full' );
			$url           = $url[0];
		} elseif ( isset( $_POST ) ) {
			$data          = $this->step_2_manage_upload();
			$attachment_id = $data['attachment_id'];
			$file          = $data['file'];
			$url           = $data['url'];
		}

		if ( file_exists( $file ) ) {
			list( $width, $height, $type, $attr ) = wp_getimagesize( $file );
		} else {
			$data   = wp_get_attachment_metadata( $attachment_id );
			$height = isset( $data['height'] ) ? (int) $data['height'] : 0;
			$width  = isset( $data['width'] ) ? (int) $data['width'] : 0;
			unset( $data );
		}

		$max_width = 0;

		// For flex, limit size of image displayed to 1500px unless theme says otherwise.
		if ( current_theme_supports( 'custom-header', 'flex-width' ) ) {
			$max_width = 1500;
		}

		if ( current_theme_supports( 'custom-header', 'max-width' ) ) {
			$max_width = max( $max_width, get_theme_support( 'custom-header', 'max-width' ) );
		}

		$max_width = max( $max_width, get_theme_support( 'custom-header', 'width' ) );

		// If flexible height isn't supported and the image is the exact right size.
		if ( ! current_theme_supports( 'custom-header', 'flex-height' )
			&& ! current_theme_supports( 'custom-header', 'flex-width' )
			&& (int) get_theme_support( 'custom-header', 'width' ) === $width
			&& (int) get_theme_support( 'custom-header', 'height' ) === $height
		) {
			// Add the metadata.
			if ( file_exists( $file ) ) {
				wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $file ) );
			}

			$this->set_header_image( compact( 'url', 'attachment_id', 'width', 'height' ) );

			/**
			 * Filters the attachment file path after the custom header or background image is set.
			 *
			 * Used for file replication.
			 *
			 * @since 2.1.0
			 *
			 * @param string $file          Path to the file.
			 * @param int    $attachment_id Attachment ID.
			 */
			$file = apply_filters( 'wp_create_file_in_uploads', $file, $attachment_id ); // For replication.

			return $this->finished();
		} elseif ( $width > $max_width ) {
			$oitar = $width / $max_width;

			$image = wp_crop_image(
				$attachment_id,
				0,
				0,
				$width,
				$height,
				$max_width,
				$height / $oitar,
				false,
				str_replace( wp_basename( $file ), 'midsize-' . wp_basename( $file ), $file )
			);

			if ( ! $image || is_wp_error( $image ) ) {
				wp_die( __( 'Image could not be processed. Please go back and try again.' ), __( 'Image Processing Error' ) );
			}

			/** This filter is documented in wp-admin/includes/class-custom-image-header.php */
			$image = apply_filters( 'wp_create_file_in_uploads', $image, $attachment_id ); // For replication.

			$url    = str_replace( wp_basename( $url ), wp_basename( $image ), $url );
			$width  = $width / $oitar;
			$height = $height / $oitar;
		} else {
			$oitar = 1;
		}
		?>

<div class="wrap">
<h1><?php _e( 'Crop Header Image' ); ?></h1>

<form method="post" action="<?php echo esc_url( add_query_arg( 'step', 3 ) ); ?>">
	<p class="hide-if-no-js"><?php _e( 'Choose the part of the image you want to use as your header.' ); ?></p>
	<p class="hide-if-js"><strong><?php _e( 'You need JavaScript to choose a part of the image.' ); ?></strong></p>

	<div id="crop_image" style="position: relative">
		<img src="<?php echo esc_url( $url ); ?>" id="upload" width="<?php echo esc_attr( $width ); ?>" height="<?php echo esc_attr( $height ); ?>" alt="" />
	</div>

	<input type="hidden" name="x1" id="x1" value="0" />
	<input type="hidden" name="y1" id="y1" value="0" />
	<input type="hidden" name="width" id="width" value="<?php echo esc_attr( $width ); ?>" />
	<input type="hidden" name="height" id="height" value="<?php echo esc_attr( $height ); ?>" />
	<input type="hidden" name="attachment_id" id="attachment_id" value="<?php echo esc_attr( $attachment_id ); ?>" />
	<input type="hidden" name="oitar" id="oitar" value="<?php echo esc_attr( $oitar ); ?>" />
		<?php if ( empty( $_POST ) && isset( $_GET['file'] ) ) { ?>
	<input type="hidden" name="create-new-attachment" value="true" />
	<?php } ?>
		<?php wp_nonce_field( 'custom-header-crop-image' ); ?>

	<p class="submit">
		<?php submit_button( __( 'Crop and Publish' ), 'primary', 'submit', false ); ?>
		<?php
		if ( 1 === $oitar
			&& ( current_theme_supports( 'custom-header', 'flex-height' )
				|| current_theme_supports( 'custom-header', 'flex-width' ) )
		) {
			submit_button( __( 'Skip Cropping, Publish Image as Is' ), '', 'skip-cropping', false );
		}
		?>
	</p>
</form>
</div>
		<?php
	}


	/**
	 * Uploads the file to be cropped in the second step.
	 *
	 * @since 3.4.0
	 */
	public function step_2_manage_upload() {
		$overrides = array( 'test_form' => false );

		$uploaded_file = $_FILES['import'];
		$wp_filetype   = wp_check_filetype_and_ext( $uploaded_file['tmp_name'], $uploaded_file['name'] );

		if ( ! wp_match_mime_types( 'image', $wp_filetype['type'] ) ) {
			wp_die( __( 'The uploaded file is not a valid image. Please try again.' ) );
		}

		$file = wp_handle_upload( $uploaded_file, $overrides );

		if ( isset( $file['error'] ) ) {
			wp_die( $file['error'], __( 'Image Upload Error' ) );
		}

		$url      = $file['url'];
		$type     = $file['type'];
		$file     = $file['file'];
		$filename = wp_basename( $file );

		// Construct the attachment array.
		$attachment = array(
			'post_title'     => $filename,
			'post_content'   => $url,
			'post_mime_type' => $type,
			'guid'           => $url,
			'context'        => 'custom-header',
		);

		// Save the data.
		$attachment_id = wp_insert_attachment( $attachment, $file );

		return compact( 'attachment_id', 'file', 'filename', 'url', 'type' );
	}

	/**
	 * Displays third step of custom header image page.
	 *
	 * @since 2.1.0
	 * @since 4.4.0 Switched to using wp_get_attachment_url() instead of the guid
	 *              for retrieving the header image URL.
	 */
	public function step_3() {
		check_admin_referer( 'custom-header-crop-image' );

		if ( ! current_theme_supports( 'custom-header', 'uploads' ) ) {
			wp_die(
				'<h1>' . __( 'An error occurred while processing your header image.' ) . '</h1>' .
				'<p>' . __( 'The active theme does not support uploading a custom header image. Please ensure your theme supports custom headers and try again.' ) . '</p>',
				403
			);
		}

		if ( ! empty( $_POST['skip-cropping'] )
			&& ! current_theme_supports( 'custom-header', 'flex-height' )
			&& ! current_theme_supports( 'custom-header', 'flex-width' )
		) {
			wp_die(
				'<h1>' . __( 'An error occurred while processing your header image.' ) . '</h1>' .
				'<p>' . __( 'The active theme does not support a flexible sized header image.' ) . '</p>',
				403
			);
		}

		if ( $_POST['oitar'] > 1 ) {
			$_POST['x1']     = $_POST['x1'] * $_POST['oitar'];
			$_POST['y1']     = $_POST['y1'] * $_POST['oitar'];
			$_POST['width']  = $_POST['width'] * $_POST['oitar'];
			$_POST['height'] = $_POST['height'] * $_POST['oitar'];
		}

		$attachment_id = absint( $_POST['attachment_id'] );
		$original      = get_attached_file( $attachment_id );

		$dimensions = $this->get_header_dimensions(
			array(
				'height' => $_POST['height'],
				'width'  => $_POST['width'],
			)
		);
		$height     = $dimensions['dst_height'];
		$width      = $dimensions['dst_width'];

		if ( empty( $_POST['skip-cropping'] ) ) {
			$cropped = wp_crop_image(
				$attachment_id,
				(int) $_POST['x1'],
				(int) $_POST['y1'],
				(int) $_POST['width'],
				(int) $_POST['height'],
				$width,
				$height
			);
		} elseif ( ! empty( $_POST['create-new-attachment'] ) ) {
			$cropped = _copy_image_file( $attachment_id );
		} else {
			$cropped = get_attached_file( $attachment_id );
		}

		if ( ! $cropped || is_wp_error( $cropped ) ) {
			wp_die( __( 'Image could not be processed. Please go back and try again.' ), __( 'Image Processing Error' ) );
		}

		/** This filter is documented in wp-admin/includes/class-custom-image-header.php */
		$cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication.

		$attachment = wp_copy_parent_attachment_properties( $cropped, $attachment_id, 'custom-header' );

		if ( ! empty( $_POST['create-new-attachment'] ) ) {
			unset( $attachment['ID'] );
		}

		// Update the attachment.
		$attachment_id = $this->insert_attachment( $attachment, $cropped );

		$url = wp_get_attachment_url( $attachment_id );
		$this->set_header_image( compact( 'url', 'attachment_id', 'width', 'height' ) );

		// Cleanup.
		$medium = str_replace( wp_basename( $original ), 'midsize-' . wp_basename( $original ), $original );
		if ( file_exists( $medium ) ) {
			wp_delete_file( $medium );
		}

		if ( empty( $_POST['create-new-attachment'] ) && empty( $_POST['skip-cropping'] ) ) {
			wp_delete_file( $original );
		}

		return $this->finished();
	}

	/**
	 * Displays last step of custom header image page.
	 *
	 * @since 2.1.0
	 */
	public function finished() {
		$this->updated = true;
		$this->step_1();
	}

	/**
	 * Displays the page based on the current step.
	 *
	 * @since 2.1.0
	 */
	public function admin_page() {
		if ( ! current_user_can( 'edit_theme_options' ) ) {
			wp_die( __( 'Sorry, you are not allowed to customize headers.' ) );
		}

		$step = $this->step();

		if ( 2 === $step ) {
			$this->step_2();
		} elseif ( 3 === $step ) {
			$this->step_3();
		} else {
			$this->step_1();
		}
	}

	/**
	 * Unused since 3.5.0.
	 *
	 * @since 3.4.0
	 *
	 * @param array $form_fields
	 * @return array $form_fields
	 */
	public function attachment_fields_to_edit( $form_fields ) {
		return $form_fields;
	}

	/**
	 * Unused since 3.5.0.
	 *
	 * @since 3.4.0
	 *
	 * @param array $tabs
	 * @return array $tabs
	 */
	public function filter_upload_tabs( $tabs ) {
		return $tabs;
	}

	/**
	 * Chooses a header image, selected from existing uploaded and default headers,
	 * or provides an array of uploaded header data (either new, or from media library).
	 *
	 * @since 3.4.0
	 *
	 * @param mixed $choice Which header image to select. Allows for values of 'random-default-image',
	 *                      for randomly cycling among the default images; 'random-uploaded-image',
	 *                      for randomly cycling among the uploaded images; the key of a default image
	 *                      registered for that theme; and the key of an image uploaded for that theme
	 *                      (the attachment ID of the image). Or an array of arguments: attachment_id,
	 *                      url, width, height. All are required.
	 */
	final public function set_header_image( $choice ) {
		if ( is_array( $choice ) || is_object( $choice ) ) {
			$choice = (array) $choice;

			if ( ! isset( $choice['attachment_id'] ) || ! isset( $choice['url'] ) ) {
				return;
			}

			$choice['url'] = sanitize_url( $choice['url'] );

			$header_image_data = (object) array(
				'attachment_id' => $choice['attachment_id'],
				'url'           => $choice['url'],
				'thumbnail_url' => $choice['url'],
				'height'        => $choice['height'],
				'width'         => $choice['width'],
			);

			update_post_meta( $choice['attachment_id'], '_wp_attachment_is_custom_header', get_stylesheet() );

			set_theme_mod( 'header_image', $choice['url'] );
			set_theme_mod( 'header_image_data', $header_image_data );

			return;
		}

		if ( in_array( $choice, array( 'remove-header', 'random-default-image', 'random-uploaded-image' ), true ) ) {
			set_theme_mod( 'header_image', $choice );
			remove_theme_mod( 'header_image_data' );

			return;
		}

		$uploaded = get_uploaded_header_images();

		if ( $uploaded && isset( $uploaded[ $choice ] ) ) {
			$header_image_data = $uploaded[ $choice ];
		} else {
			$this->process_default_headers();
			if ( isset( $this->default_headers[ $choice ] ) ) {
				$header_image_data = $this->default_headers[ $choice ];
			} else {
				return;
			}
		}

		set_theme_mod( 'header_image', sanitize_url( $header_image_data['url'] ) );
		set_theme_mod( 'header_image_data', $header_image_data );
	}

	/**
	 * Removes a header image.
	 *
	 * @since 3.4.0
	 */
	final public function remove_header_image() {
		$this->set_header_image( 'remove-header' );
	}

	/**
	 * Resets a header image to the default image for the theme.
	 *
	 * This method does not do anything if the theme does not have a default header image.
	 *
	 * @since 3.4.0
	 */
	final public function reset_header_image() {
		$this->process_default_headers();
		$default = get_theme_support( 'custom-header', 'default-image' );

		if ( ! $default ) {
			$this->remove_header_image();
			return;
		}

		$default = sprintf( $default, get_template_directory_uri(), get_stylesheet_directory_uri() );

		$default_data = array();
		foreach ( $this->default_headers as $header => $details ) {
			if ( $details['url'] === $default ) {
				$default_data = $details;
				break;
			}
		}

		set_theme_mod( 'header_image', $default );
		set_theme_mod( 'header_image_data', (object) $default_data );
	}

	/**
	 * Calculates width and height based on what the currently selected theme supports.
	 *
	 * @since 3.9.0
	 *
	 * @param array $dimensions
	 * @return array dst_height and dst_width of header image.
	 */
	final public function get_header_dimensions( $dimensions ) {
		$max_width       = 0;
		$width           = absint( $dimensions['width'] );
		$height          = absint( $dimensions['height'] );
		$theme_height    = get_theme_support( 'custom-header', 'height' );
		$theme_width     = get_theme_support( 'custom-header', 'width' );
		$has_flex_width  = current_theme_supports( 'custom-header', 'flex-width' );
		$has_flex_height = current_theme_supports( 'custom-header', 'flex-height' );
		$has_max_width   = current_theme_supports( 'custom-header', 'max-width' );
		$dst             = array(
			'dst_height' => null,
			'dst_width'  => null,
		);

		// For flex, limit size of image displayed to 1500px unless theme says otherwise.
		if ( $has_flex_width ) {
			$max_width = 1500;
		}

		if ( $has_max_width ) {
			$max_width = max( $max_width, get_theme_support( 'custom-header', 'max-width' ) );
		}
		$max_width = max( $max_width, $theme_width );

		if ( $has_flex_height && ( ! $has_flex_width || $width > $max_width ) ) {
			$dst['dst_height'] = absint( $height * ( $max_width / $width ) );
		} elseif ( $has_flex_height && $has_flex_width ) {
			$dst['dst_height'] = $height;
		} else {
			$dst['dst_height'] = $theme_height;
		}

		if ( $has_flex_width && ( ! $has_flex_height || $width > $max_width ) ) {
			$dst['dst_width'] = absint( $width * ( $max_width / $width ) );
		} elseif ( $has_flex_width && $has_flex_height ) {
			$dst['dst_width'] = $width;
		} else {
			$dst['dst_width'] = $theme_width;
		}

		return $dst;
	}

	/**
	 * Creates an attachment 'object'.
	 *
	 * @since 3.9.0
	 * @deprecated 6.5.0
	 *
	 * @param string $cropped              Cropped image URL.
	 * @param int    $parent_attachment_id Attachment ID of parent image.
	 * @return array An array with attachment object data.
	 */
	final public function create_attachment_object( $cropped, $parent_attachment_id ) {
		_deprecated_function( __METHOD__, '6.5.0', 'wp_copy_parent_attachment_properties()' );
		$parent     = get_post( $parent_attachment_id );
		$parent_url = wp_get_attachment_url( $parent->ID );
		$url        = str_replace( wp_basename( $parent_url ), wp_basename( $cropped ), $parent_url );

		$size       = wp_getimagesize( $cropped );
		$image_type = ( $size ) ? $size['mime'] : 'image/jpeg';

		$attachment = array(
			'ID'             => $parent_attachment_id,
			'post_title'     => wp_basename( $cropped ),
			'post_mime_type' => $image_type,
			'guid'           => $url,
			'context'        => 'custom-header',
			'post_parent'    => $parent_attachment_id,
		);

		return $attachment;
	}

	/**
	 * Inserts an attachment and its metadata.
	 *
	 * @since 3.9.0
	 *
	 * @param array  $attachment An array with attachment object data.
	 * @param string $cropped    File path to cropped image.
	 * @return int Attachment ID.
	 */
	final public function insert_attachment( $attachment, $cropped ) {
		$parent_id = isset( $attachment['post_parent'] ) ? $attachment['post_parent'] : null;
		unset( $attachment['post_parent'] );

		$attachment_id = wp_insert_attachment( $attachment, $cropped );
		$metadata      = wp_generate_attachment_metadata( $attachment_id, $cropped );

		// If this is a crop, save the original attachment ID as metadata.
		if ( $parent_id ) {
			$metadata['attachment_parent'] = $parent_id;
		}

		/**
		 * Filters the header image attachment metadata.
		 *
		 * @since 3.9.0
		 *
		 * @see wp_generate_attachment_metadata()
		 *
		 * @param array $metadata Attachment metadata.
		 */
		$metadata = apply_filters( 'wp_header_image_attachment_metadata', $metadata );

		wp_update_attachment_metadata( $attachment_id, $metadata );

		return $attachment_id;
	}

	/**
	 * Gets attachment uploaded by Media Manager, crops it, then saves it as a
	 * new object. Returns JSON-encoded object details.
	 *
	 * @since 3.9.0
	 */
	public function ajax_header_crop() {
		check_ajax_referer( 'image_editor-' . $_POST['id'], 'nonce' );

		if ( ! current_user_can( 'edit_theme_options' ) ) {
			wp_send_json_error();
		}

		if ( ! current_theme_supports( 'custom-header', 'uploads' ) ) {
			wp_send_json_error();
		}

		$crop_details = $_POST['cropDetails'];

		$dimensions = $this->get_header_dimensions(
			array(
				'height' => $crop_details['height'],
				'width'  => $crop_details['width'],
			)
		);

		$attachment_id = absint( $_POST['id'] );

		$cropped = wp_crop_image(
			$attachment_id,
			(int) $crop_details['x1'],
			(int) $crop_details['y1'],
			(int) $crop_details['width'],
			(int) $crop_details['height'],
			(int) $dimensions['dst_width'],
			(int) $dimensions['dst_height']
		);

		if ( ! $cropped || is_wp_error( $cropped ) ) {
			wp_send_json_error( array( 'message' => __( 'Image could not be processed. Please go back and try again.' ) ) );
		}

		/** This filter is documented in wp-admin/includes/class-custom-image-header.php */
		$cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication.

		$attachment = wp_copy_parent_attachment_properties( $cropped, $attachment_id, 'custom-header' );

		$previous = $this->get_previous_crop( $attachment );

		if ( $previous ) {
			$attachment['ID'] = $previous;
		} else {
			unset( $attachment['ID'] );
		}

		$new_attachment_id = $this->insert_attachment( $attachment, $cropped );

		$attachment['attachment_id'] = $new_attachment_id;
		$attachment['url']           = wp_get_attachment_url( $new_attachment_id );

		$attachment['width']  = $dimensions['dst_width'];
		$attachment['height'] = $dimensions['dst_height'];

		wp_send_json_success( $attachment );
	}

	/**
	 * Given an attachment ID for a header image, updates its "last used"
	 * timestamp to now.
	 *
	 * Triggered when the user tries adds a new header image from the
	 * Media Manager, even if s/he doesn't save that change.
	 *
	 * @since 3.9.0
	 */
	public function ajax_header_add() {
		check_ajax_referer( 'header-add', 'nonce' );

		if ( ! current_user_can( 'edit_theme_options' ) ) {
			wp_send_json_error();
		}

		$attachment_id = absint( $_POST['attachment_id'] );
		if ( $attachment_id < 1 ) {
			wp_send_json_error();
		}

		$key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
		update_post_meta( $attachment_id, $key, time() );
		update_post_meta( $attachment_id, '_wp_attachment_is_custom_header', get_stylesheet() );

		wp_send_json_success();
	}

	/**
	 * Given an attachment ID for a header image, unsets it as a user-uploaded
	 * header image for the active theme.
	 *
	 * Triggered when the user clicks the overlay "X" button next to each image
	 * choice in the Customizer's Header tool.
	 *
	 * @since 3.9.0
	 */
	public function ajax_header_remove() {
		check_ajax_referer( 'header-remove', 'nonce' );

		if ( ! current_user_can( 'edit_theme_options' ) ) {
			wp_send_json_error();
		}

		$attachment_id = absint( $_POST['attachment_id'] );
		if ( $attachment_id < 1 ) {
			wp_send_json_error();
		}

		$key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
		delete_post_meta( $attachment_id, $key );
		delete_post_meta( $attachment_id, '_wp_attachment_is_custom_header', get_stylesheet() );

		wp_send_json_success();
	}

	/**
	 * Updates the last-used postmeta on a header image attachment after saving a new header image via the Customizer.
	 *
	 * @since 3.9.0
	 *
	 * @param WP_Customize_Manager $wp_customize Customize manager.
	 */
	public function customize_set_last_used( $wp_customize ) {

		$header_image_data_setting = $wp_customize->get_setting( 'header_image_data' );

		if ( ! $header_image_data_setting ) {
			return;
		}

		$data = $header_image_data_setting->post_value();

		if ( ! isset( $data['attachment_id'] ) ) {
			return;
		}

		$attachment_id = $data['attachment_id'];
		$key           = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
		update_post_meta( $attachment_id, $key, time() );
	}

	/**
	 * Gets the details of default header images if defined.
	 *
	 * @since 3.9.0
	 *
	 * @return array Default header images.
	 */
	public function get_default_header_images() {
		$this->process_default_headers();

		// Get the default image if there is one.
		$default = get_theme_support( 'custom-header', 'default-image' );

		if ( ! $default ) { // If not, easy peasy.
			return $this->default_headers;
		}

		$default = sprintf( $default, get_template_directory_uri(), get_stylesheet_directory_uri() );

		$already_has_default = false;

		foreach ( $this->default_headers as $k => $header ) {
			if ( $header['url'] === $default ) {
				$already_has_default = true;
				break;
			}
		}

		if ( $already_has_default ) {
			return $this->default_headers;
		}

		// If the one true image isn't included in the default set, prepend it.
		$header_images            = array();
		$header_images['default'] = array(
			'url'           => $default,
			'thumbnail_url' => $default,
			'description'   => 'Default',
		);

		// The rest of the set comes after.
		return array_merge( $header_images, $this->default_headers );
	}

	/**
	 * Gets the previously uploaded header images.
	 *
	 * @since 3.9.0
	 *
	 * @return array Uploaded header images.
	 */
	public function get_uploaded_header_images() {
		$header_images = get_uploaded_header_images();
		$timestamp_key = '_wp_attachment_custom_header_last_used_' . get_stylesheet();
		$alt_text_key  = '_wp_attachment_image_alt';

		foreach ( $header_images as &$header_image ) {
			$header_meta               = get_post_meta( $header_image['attachment_id'] );
			$header_image['timestamp'] = isset( $header_meta[ $timestamp_key ] ) ? $header_meta[ $timestamp_key ] : '';
			$header_image['alt_text']  = isset( $header_meta[ $alt_text_key ] ) ? $header_meta[ $alt_text_key ] : '';
		}

		return $header_images;
	}

	/**
	 * Gets the ID of a previous crop from the same base image.
	 *
	 * @since 4.9.0
	 *
	 * @param array $attachment An array with a cropped attachment object data.
	 * @return int|false An attachment ID if one exists. False if none.
	 */
	public function get_previous_crop( $attachment ) {
		$header_images = $this->get_uploaded_header_images();

		// Bail early if there are no header images.
		if ( empty( $header_images ) ) {
			return false;
		}

		$previous = false;

		foreach ( $header_images as $image ) {
			if ( $image['attachment_parent'] === $attachment['post_parent'] ) {
				$previous = $image['attachment_id'];
				break;
			}
		}

		return $previous;
	}
}
user.php000064400000055754151212616050006252 0ustar00<?php
/**
 * WordPress user administration API.
 *
 * @package WordPress
 * @subpackage Administration
 */

/**
 * Creates a new user from the "Users" form using $_POST information.
 *
 * @since 2.0.0
 *
 * @return int|WP_Error WP_Error or User ID.
 */
function add_user() {
	return edit_user();
}

/**
 * Edit user settings based on contents of $_POST
 *
 * Used on user-edit.php and profile.php to manage and process user options, passwords etc.
 *
 * @since 2.0.0
 *
 * @param int $user_id Optional. User ID.
 * @return int|WP_Error User ID of the updated user or WP_Error on failure.
 */
function edit_user( $user_id = 0 ) {
	$wp_roles = wp_roles();
	$user     = new stdClass();
	$user_id  = (int) $user_id;
	if ( $user_id ) {
		$update           = true;
		$user->ID         = $user_id;
		$userdata         = get_userdata( $user_id );
		$user->user_login = wp_slash( $userdata->user_login );
	} else {
		$update = false;
	}

	if ( ! $update && isset( $_POST['user_login'] ) ) {
		$user->user_login = sanitize_user( wp_unslash( $_POST['user_login'] ), true );
	}

	$pass1 = '';
	$pass2 = '';
	if ( isset( $_POST['pass1'] ) ) {
		$pass1 = trim( $_POST['pass1'] );
	}
	if ( isset( $_POST['pass2'] ) ) {
		$pass2 = trim( $_POST['pass2'] );
	}

	if ( isset( $_POST['role'] ) && current_user_can( 'promote_users' ) && ( ! $user_id || current_user_can( 'promote_user', $user_id ) ) ) {
		$new_role = sanitize_text_field( $_POST['role'] );

		// If the new role isn't editable by the logged-in user die with error.
		$editable_roles = get_editable_roles();
		if ( ! empty( $new_role ) && empty( $editable_roles[ $new_role ] ) ) {
			wp_die( __( 'Sorry, you are not allowed to give users that role.' ), 403 );
		}

		$potential_role = isset( $wp_roles->role_objects[ $new_role ] ) ? $wp_roles->role_objects[ $new_role ] : false;

		/*
		 * Don't let anyone with 'promote_users' edit their own role to something without it.
		 * Multisite super admins can freely edit their roles, they possess all caps.
		 */
		if (
			( is_multisite() && current_user_can( 'manage_network_users' ) ) ||
			get_current_user_id() !== $user_id ||
			( $potential_role && $potential_role->has_cap( 'promote_users' ) )
		) {
			$user->role = $new_role;
		}
	}

	if ( isset( $_POST['email'] ) ) {
		$user->user_email = sanitize_text_field( wp_unslash( $_POST['email'] ) );
	}
	if ( isset( $_POST['url'] ) ) {
		if ( empty( $_POST['url'] ) || 'http://' === $_POST['url'] ) {
			$user->user_url = '';
		} else {
			$user->user_url = sanitize_url( $_POST['url'] );
			$protocols      = implode( '|', array_map( 'preg_quote', wp_allowed_protocols() ) );
			$user->user_url = preg_match( '/^(' . $protocols . '):/is', $user->user_url ) ? $user->user_url : 'http://' . $user->user_url;
		}
	}
	if ( isset( $_POST['first_name'] ) ) {
		$user->first_name = sanitize_text_field( $_POST['first_name'] );
	}
	if ( isset( $_POST['last_name'] ) ) {
		$user->last_name = sanitize_text_field( $_POST['last_name'] );
	}
	if ( isset( $_POST['nickname'] ) ) {
		$user->nickname = sanitize_text_field( $_POST['nickname'] );
	}
	if ( isset( $_POST['display_name'] ) ) {
		$user->display_name = sanitize_text_field( $_POST['display_name'] );
	}

	if ( isset( $_POST['description'] ) ) {
		$user->description = trim( $_POST['description'] );
	}

	foreach ( wp_get_user_contact_methods( $user ) as $method => $name ) {
		if ( isset( $_POST[ $method ] ) ) {
			$user->$method = sanitize_text_field( $_POST[ $method ] );
		}
	}

	if ( isset( $_POST['locale'] ) ) {
		$locale = sanitize_text_field( $_POST['locale'] );
		if ( 'site-default' === $locale ) {
			$locale = '';
		} elseif ( '' === $locale ) {
			$locale = 'en_US';
		} elseif ( ! in_array( $locale, get_available_languages(), true ) ) {
			if ( current_user_can( 'install_languages' ) && wp_can_install_language_pack() ) {
				if ( ! wp_download_language_pack( $locale ) ) {
					$locale = '';
				}
			} else {
				$locale = '';
			}
		}

		$user->locale = $locale;
	}

	if ( $update ) {
		$user->rich_editing         = isset( $_POST['rich_editing'] ) && 'false' === $_POST['rich_editing'] ? 'false' : 'true';
		$user->syntax_highlighting  = isset( $_POST['syntax_highlighting'] ) && 'false' === $_POST['syntax_highlighting'] ? 'false' : 'true';
		$user->admin_color          = isset( $_POST['admin_color'] ) ? sanitize_text_field( $_POST['admin_color'] ) : 'fresh';
		$user->show_admin_bar_front = isset( $_POST['admin_bar_front'] ) ? 'true' : 'false';
	}

	$user->comment_shortcuts = isset( $_POST['comment_shortcuts'] ) && 'true' === $_POST['comment_shortcuts'] ? 'true' : '';

	$user->use_ssl = 0;
	if ( ! empty( $_POST['use_ssl'] ) ) {
		$user->use_ssl = 1;
	}

	$errors = new WP_Error();

	/* checking that username has been typed */
	if ( '' === $user->user_login ) {
		$errors->add( 'user_login', __( '<strong>Error:</strong> Please enter a username.' ) );
	}

	/* checking that nickname has been typed */
	if ( $update && empty( $user->nickname ) ) {
		$errors->add( 'nickname', __( '<strong>Error:</strong> Please enter a nickname.' ) );
	}

	/**
	 * Fires before the password and confirm password fields are checked for congruity.
	 *
	 * @since 1.5.1
	 *
	 * @param string $user_login The username.
	 * @param string $pass1     The password (passed by reference).
	 * @param string $pass2     The confirmed password (passed by reference).
	 */
	do_action_ref_array( 'check_passwords', array( $user->user_login, &$pass1, &$pass2 ) );

	// Check for blank password when adding a user.
	if ( ! $update && empty( $pass1 ) ) {
		$errors->add( 'pass', __( '<strong>Error:</strong> Please enter a password.' ), array( 'form-field' => 'pass1' ) );
	}

	// Check for "\" in password.
	if ( str_contains( wp_unslash( $pass1 ), '\\' ) ) {
		$errors->add( 'pass', __( '<strong>Error:</strong> Passwords may not contain the character "\\".' ), array( 'form-field' => 'pass1' ) );
	}

	// Checking the password has been typed twice the same.
	if ( ( $update || ! empty( $pass1 ) ) && $pass1 !== $pass2 ) {
		$errors->add( 'pass', __( '<strong>Error:</strong> Passwords do not match. Please enter the same password in both password fields.' ), array( 'form-field' => 'pass1' ) );
	}

	if ( ! empty( $pass1 ) ) {
		$user->user_pass = $pass1;
	}

	if ( ! $update && isset( $_POST['user_login'] ) && ! validate_username( $_POST['user_login'] ) ) {
		$errors->add( 'user_login', __( '<strong>Error:</strong> This username is invalid because it uses illegal characters. Please enter a valid username.' ) );
	}

	if ( ! $update && username_exists( $user->user_login ) ) {
		$errors->add( 'user_login', __( '<strong>Error:</strong> This username is already registered. Please choose another one.' ) );
	}

	/** This filter is documented in wp-includes/user.php */
	$illegal_logins = (array) apply_filters( 'illegal_user_logins', array() );

	if ( in_array( strtolower( $user->user_login ), array_map( 'strtolower', $illegal_logins ), true ) ) {
		$errors->add( 'invalid_username', __( '<strong>Error:</strong> Sorry, that username is not allowed.' ) );
	}

	// Checking email address.
	if ( empty( $user->user_email ) ) {
		$errors->add( 'empty_email', __( '<strong>Error:</strong> Please enter an email address.' ), array( 'form-field' => 'email' ) );
	} elseif ( ! is_email( $user->user_email ) ) {
		$errors->add( 'invalid_email', __( '<strong>Error:</strong> The email address is not correct.' ), array( 'form-field' => 'email' ) );
	} else {
		$owner_id = email_exists( $user->user_email );
		if ( $owner_id && ( ! $update || ( $owner_id !== $user->ID ) ) ) {
			$errors->add( 'email_exists', __( '<strong>Error:</strong> This email is already registered. Please choose another one.' ), array( 'form-field' => 'email' ) );
		}
	}

	/**
	 * Fires before user profile update errors are returned.
	 *
	 * @since 2.8.0
	 *
	 * @param WP_Error $errors WP_Error object (passed by reference).
	 * @param bool     $update Whether this is a user update.
	 * @param stdClass $user   User object (passed by reference).
	 */
	do_action_ref_array( 'user_profile_update_errors', array( &$errors, $update, &$user ) );

	if ( $errors->has_errors() ) {
		return $errors;
	}

	if ( $update ) {
		$user_id = wp_update_user( $user );
	} else {
		$user_id = wp_insert_user( $user );
		$notify  = isset( $_POST['send_user_notification'] ) ? 'both' : 'admin';

		/**
		 * Fires after a new user has been created.
		 *
		 * @since 4.4.0
		 *
		 * @param int|WP_Error $user_id ID of the newly created user or WP_Error on failure.
		 * @param string       $notify  Type of notification that should happen. See
		 *                              wp_send_new_user_notifications() for more information.
		 */
		do_action( 'edit_user_created_user', $user_id, $notify );
	}
	return $user_id;
}

/**
 * Fetch a filtered list of user roles that the current user is
 * allowed to edit.
 *
 * Simple function whose main purpose is to allow filtering of the
 * list of roles in the $wp_roles object so that plugins can remove
 * inappropriate ones depending on the situation or user making edits.
 * Specifically because without filtering anyone with the edit_users
 * capability can edit others to be administrators, even if they are
 * only editors or authors. This filter allows admins to delegate
 * user management.
 *
 * @since 2.8.0
 *
 * @return array[] Array of arrays containing role information.
 */
function get_editable_roles() {
	$all_roles = wp_roles()->roles;

	/**
	 * Filters the list of editable roles.
	 *
	 * @since 2.8.0
	 *
	 * @param array[] $all_roles Array of arrays containing role information.
	 */
	$editable_roles = apply_filters( 'editable_roles', $all_roles );

	return $editable_roles;
}

/**
 * Retrieve user data and filter it.
 *
 * @since 2.0.5
 *
 * @param int $user_id User ID.
 * @return WP_User|false WP_User object on success, false on failure.
 */
function get_user_to_edit( $user_id ) {
	$user = get_userdata( $user_id );

	if ( $user ) {
		$user->filter = 'edit';
	}

	return $user;
}

/**
 * Retrieve the user's drafts.
 *
 * @since 2.0.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int $user_id User ID.
 * @return array
 */
function get_users_drafts( $user_id ) {
	global $wpdb;
	$query = $wpdb->prepare( "SELECT ID, post_title FROM $wpdb->posts WHERE post_type = 'post' AND post_status = 'draft' AND post_author = %d ORDER BY post_modified DESC", $user_id );

	/**
	 * Filters the SQL query string for the user's drafts query.
	 *
	 * @since 2.0.0
	 *
	 * @param string $query The user's drafts query string.
	 */
	$query = apply_filters( 'get_users_drafts', $query );
	return $wpdb->get_results( $query );
}

/**
 * Delete user and optionally reassign posts and links to another user.
 *
 * Note that on a Multisite installation the user only gets removed from the site
 * and does not get deleted from the database.
 *
 * If the `$reassign` parameter is not assigned to a user ID, then all posts will
 * be deleted of that user. The action {@see 'delete_user'} that is passed the user ID
 * being deleted will be run after the posts are either reassigned or deleted.
 * The user meta will also be deleted that are for that user ID.
 *
 * @since 2.0.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int $id       User ID.
 * @param int $reassign Optional. Reassign posts and links to new User ID.
 * @return bool True when finished.
 */
function wp_delete_user( $id, $reassign = null ) {
	global $wpdb;

	if ( ! is_numeric( $id ) ) {
		return false;
	}

	$id   = (int) $id;
	$user = new WP_User( $id );

	if ( ! $user->exists() ) {
		return false;
	}

	// Normalize $reassign to null or a user ID. 'novalue' was an older default.
	if ( 'novalue' === $reassign ) {
		$reassign = null;
	} elseif ( null !== $reassign ) {
		$reassign = (int) $reassign;
	}

	/**
	 * Fires immediately before a user is deleted from the site.
	 *
	 * Note that on a Multisite installation the user only gets removed from the site
	 * and does not get deleted from the database.
	 *
	 * @since 2.0.0
	 * @since 5.5.0 Added the `$user` parameter.
	 *
	 * @param int      $id       ID of the user to delete.
	 * @param int|null $reassign ID of the user to reassign posts and links to.
	 *                           Default null, for no reassignment.
	 * @param WP_User  $user     WP_User object of the user to delete.
	 */
	do_action( 'delete_user', $id, $reassign, $user );

	if ( null === $reassign ) {
		$post_types_to_delete = array();
		foreach ( get_post_types( array(), 'objects' ) as $post_type ) {
			if ( $post_type->delete_with_user ) {
				$post_types_to_delete[] = $post_type->name;
			} elseif ( null === $post_type->delete_with_user && post_type_supports( $post_type->name, 'author' ) ) {
				$post_types_to_delete[] = $post_type->name;
			}
		}

		/**
		 * Filters the list of post types to delete with a user.
		 *
		 * @since 3.4.0
		 *
		 * @param string[] $post_types_to_delete Array of post types to delete.
		 * @param int      $id                   User ID.
		 */
		$post_types_to_delete = apply_filters( 'post_types_to_delete_with_user', $post_types_to_delete, $id );
		$post_types_to_delete = implode( "', '", $post_types_to_delete );
		$post_ids             = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_author = %d AND post_type IN ('$post_types_to_delete')", $id ) );
		if ( $post_ids ) {
			foreach ( $post_ids as $post_id ) {
				wp_delete_post( $post_id );
			}
		}

		// Clean links.
		$link_ids = $wpdb->get_col( $wpdb->prepare( "SELECT link_id FROM $wpdb->links WHERE link_owner = %d", $id ) );

		if ( $link_ids ) {
			foreach ( $link_ids as $link_id ) {
				wp_delete_link( $link_id );
			}
		}
	} else {
		$post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_author = %d", $id ) );
		$wpdb->update( $wpdb->posts, array( 'post_author' => $reassign ), array( 'post_author' => $id ) );
		if ( ! empty( $post_ids ) ) {
			foreach ( $post_ids as $post_id ) {
				clean_post_cache( $post_id );
			}
		}
		$link_ids = $wpdb->get_col( $wpdb->prepare( "SELECT link_id FROM $wpdb->links WHERE link_owner = %d", $id ) );
		$wpdb->update( $wpdb->links, array( 'link_owner' => $reassign ), array( 'link_owner' => $id ) );
		if ( ! empty( $link_ids ) ) {
			foreach ( $link_ids as $link_id ) {
				clean_bookmark_cache( $link_id );
			}
		}
	}

	// FINALLY, delete user.
	if ( is_multisite() ) {
		remove_user_from_blog( $id, get_current_blog_id() );
	} else {
		$meta = $wpdb->get_col( $wpdb->prepare( "SELECT umeta_id FROM $wpdb->usermeta WHERE user_id = %d", $id ) );
		foreach ( $meta as $mid ) {
			delete_metadata_by_mid( 'user', $mid );
		}

		$wpdb->delete( $wpdb->users, array( 'ID' => $id ) );
	}

	clean_user_cache( $user );

	/**
	 * Fires immediately after a user is deleted from the site.
	 *
	 * Note that on a Multisite installation the user may not have been deleted from
	 * the database depending on whether `wp_delete_user()` or `wpmu_delete_user()`
	 * was called.
	 *
	 * @since 2.9.0
	 * @since 5.5.0 Added the `$user` parameter.
	 *
	 * @param int      $id       ID of the deleted user.
	 * @param int|null $reassign ID of the user to reassign posts and links to.
	 *                           Default null, for no reassignment.
	 * @param WP_User  $user     WP_User object of the deleted user.
	 */
	do_action( 'deleted_user', $id, $reassign, $user );

	return true;
}

/**
 * Remove all capabilities from user.
 *
 * @since 2.1.0
 *
 * @param int $id User ID.
 */
function wp_revoke_user( $id ) {
	$id = (int) $id;

	$user = new WP_User( $id );
	$user->remove_all_caps();
}

/**
 * @since 2.8.0
 *
 * @global int $user_ID
 *
 * @param false $errors Deprecated.
 */
function default_password_nag_handler( $errors = false ) {
	global $user_ID;
	// Short-circuit it.
	if ( ! get_user_option( 'default_password_nag' ) ) {
		return;
	}

	// get_user_setting() = JS-saved UI setting. Else no-js-fallback code.
	if ( 'hide' === get_user_setting( 'default_password_nag' )
		|| isset( $_GET['default_password_nag'] ) && '0' === $_GET['default_password_nag']
	) {
		delete_user_setting( 'default_password_nag' );
		update_user_meta( $user_ID, 'default_password_nag', false );
	}
}

/**
 * @since 2.8.0
 *
 * @param int     $user_ID
 * @param WP_User $old_data
 */
function default_password_nag_edit_user( $user_ID, $old_data ) {
	// Short-circuit it.
	if ( ! get_user_option( 'default_password_nag', $user_ID ) ) {
		return;
	}

	$new_data = get_userdata( $user_ID );

	// Remove the nag if the password has been changed.
	if ( $new_data->user_pass !== $old_data->user_pass ) {
		delete_user_setting( 'default_password_nag' );
		update_user_meta( $user_ID, 'default_password_nag', false );
	}
}

/**
 * @since 2.8.0
 *
 * @global string $pagenow The filename of the current screen.
 */
function default_password_nag() {
	global $pagenow;

	// Short-circuit it.
	if ( 'profile.php' === $pagenow || ! get_user_option( 'default_password_nag' ) ) {
		return;
	}

	$default_password_nag_message  = sprintf(
		'<p><strong>%1$s</strong> %2$s</p>',
		__( 'Notice:' ),
		__( 'You are using the auto-generated password for your account. Would you like to change it?' )
	);
	$default_password_nag_message .= sprintf(
		'<p><a href="%1$s">%2$s</a> | ',
		esc_url( get_edit_profile_url() . '#password' ),
		__( 'Yes, take me to my profile page' )
	);
	$default_password_nag_message .= sprintf(
		'<a href="%1$s" id="default-password-nag-no">%2$s</a></p>',
		'?default_password_nag=0',
		__( 'No thanks, do not remind me again' )
	);

	wp_admin_notice(
		$default_password_nag_message,
		array(
			'additional_classes' => array( 'error', 'default-password-nag' ),
			'paragraph_wrap'     => false,
		)
	);
}

/**
 * @since 3.5.0
 * @access private
 */
function delete_users_add_js() {
	?>
<script>
jQuery( function($) {
	var submit = $('#submit').prop('disabled', true);
	$('input[name="delete_option"]').one('change', function() {
		submit.prop('disabled', false);
	});
	$('#reassign_user').focus( function() {
		$('#delete_option1').prop('checked', true).trigger('change');
	});
} );
</script>
	<?php
}

/**
 * Optional SSL preference that can be turned on by hooking to the 'personal_options' action.
 *
 * See the {@see 'personal_options'} action.
 *
 * @since 2.7.0
 *
 * @param WP_User $user User data object.
 */
function use_ssl_preference( $user ) {
	?>
	<tr class="user-use-ssl-wrap">
		<th scope="row"><?php _e( 'Use https' ); ?></th>
		<td><label for="use_ssl"><input name="use_ssl" type="checkbox" id="use_ssl" value="1" <?php checked( '1', $user->use_ssl ); ?> /> <?php _e( 'Always use https when visiting the admin' ); ?></label></td>
	</tr>
	<?php
}

/**
 * @since MU (3.0.0)
 *
 * @param string $text
 * @return string
 */
function admin_created_user_email( $text ) {
	$roles = get_editable_roles();
	$role  = $roles[ $_REQUEST['role'] ];

	if ( '' !== get_bloginfo( 'name' ) ) {
		$site_title = wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES );
	} else {
		$site_title = parse_url( home_url(), PHP_URL_HOST );
	}

	return sprintf(
		/* translators: 1: Site title, 2: Site URL, 3: User role. */
		__(
			'Hi,
You\'ve been invited to join \'%1$s\' at
%2$s with the role of %3$s.
If you do not want to join this site please ignore
this email. This invitation will expire in a few days.

Please click the following link to activate your user account:
%%s'
		),
		$site_title,
		home_url(),
		wp_specialchars_decode( translate_user_role( $role['name'] ) )
	);
}

/**
 * Checks if the Authorize Application Password request is valid.
 *
 * @since 5.6.0
 * @since 6.2.0 Allow insecure HTTP connections for the local environment.
 * @since 6.3.2 Validates the success and reject URLs to prevent `javascript` pseudo protocol from being executed.
 *
 * @param array   $request {
 *     The array of request data. All arguments are optional and may be empty.
 *
 *     @type string $app_name    The suggested name of the application.
 *     @type string $app_id      A UUID provided by the application to uniquely identify it.
 *     @type string $success_url The URL the user will be redirected to after approving the application.
 *     @type string $reject_url  The URL the user will be redirected to after rejecting the application.
 * }
 * @param WP_User $user The user authorizing the application.
 * @return true|WP_Error True if the request is valid, a WP_Error object contains errors if not.
 */
function wp_is_authorize_application_password_request_valid( $request, $user ) {
	$error = new WP_Error();

	if ( isset( $request['success_url'] ) ) {
		$validated_success_url = wp_is_authorize_application_redirect_url_valid( $request['success_url'] );
		if ( is_wp_error( $validated_success_url ) ) {
			$error->add(
				$validated_success_url->get_error_code(),
				$validated_success_url->get_error_message()
			);
		}
	}

	if ( isset( $request['reject_url'] ) ) {
		$validated_reject_url = wp_is_authorize_application_redirect_url_valid( $request['reject_url'] );
		if ( is_wp_error( $validated_reject_url ) ) {
			$error->add(
				$validated_reject_url->get_error_code(),
				$validated_reject_url->get_error_message()
			);
		}
	}

	if ( ! empty( $request['app_id'] ) && ! wp_is_uuid( $request['app_id'] ) ) {
		$error->add(
			'invalid_app_id',
			__( 'The application ID must be a UUID.' )
		);
	}

	/**
	 * Fires before application password errors are returned.
	 *
	 * @since 5.6.0
	 *
	 * @param WP_Error $error   The error object.
	 * @param array    $request The array of request data.
	 * @param WP_User  $user    The user authorizing the application.
	 */
	do_action( 'wp_authorize_application_password_request_errors', $error, $request, $user );

	if ( $error->has_errors() ) {
		return $error;
	}

	return true;
}

/**
 * Validates the redirect URL protocol scheme. The protocol can be anything except `http` and `javascript`.
 *
 * @since 6.3.2
 *
 * @param string $url The redirect URL to be validated.
 * @return true|WP_Error True if the redirect URL is valid, a WP_Error object otherwise.
 */
function wp_is_authorize_application_redirect_url_valid( $url ) {
	$bad_protocols = array( 'javascript', 'data' );
	if ( empty( $url ) ) {
		return true;
	}

	// Based on https://www.rfc-editor.org/rfc/rfc2396#section-3.1
	$valid_scheme_regex = '/^[a-zA-Z][a-zA-Z0-9+.-]*:/';
	if ( ! preg_match( $valid_scheme_regex, $url ) ) {
		return new WP_Error(
			'invalid_redirect_url_format',
			__( 'Invalid URL format.' )
		);
	}

	/**
	 * Filters the list of invalid protocols used in applications redirect URLs.
	 *
	 * @since 6.3.2
	 *
	 * @param string[] $bad_protocols Array of invalid protocols.
	 * @param string   $url The redirect URL to be validated.
	 */
	$invalid_protocols = apply_filters( 'wp_authorize_application_redirect_url_invalid_protocols', $bad_protocols, $url );
	$invalid_protocols = array_map( 'strtolower', $invalid_protocols );

	$scheme   = wp_parse_url( $url, PHP_URL_SCHEME );
	$host     = wp_parse_url( $url, PHP_URL_HOST );
	$is_local = 'local' === wp_get_environment_type();

	// Validates if the proper URI format is applied to the URL.
	if ( empty( $host ) || empty( $scheme ) || in_array( strtolower( $scheme ), $invalid_protocols, true ) ) {
		return new WP_Error(
			'invalid_redirect_url_format',
			__( 'Invalid URL format.' )
		);
	}

	if ( 'http' === $scheme && ! $is_local ) {
		return new WP_Error(
			'invalid_redirect_scheme',
			__( 'The URL must be served over a secure connection.' )
		);
	}

	return true;
}
class-wp-community-events.php000064400000044371151212616050012342 0ustar00<?php
/**
 * Administration: Community Events class.
 *
 * @package WordPress
 * @subpackage Administration
 * @since 4.8.0
 */

/**
 * Class WP_Community_Events.
 *
 * A client for api.wordpress.org/events.
 *
 * @since 4.8.0
 */
#[AllowDynamicProperties]
class WP_Community_Events {
	/**
	 * ID for a WordPress user account.
	 *
	 * @since 4.8.0
	 *
	 * @var int
	 */
	protected $user_id = 0;

	/**
	 * Stores location data for the user.
	 *
	 * @since 4.8.0
	 *
	 * @var false|array
	 */
	protected $user_location = false;

	/**
	 * Constructor for WP_Community_Events.
	 *
	 * @since 4.8.0
	 *
	 * @param int        $user_id       WP user ID.
	 * @param false|array $user_location {
	 *     Stored location data for the user. false to pass no location.
	 *
	 *     @type string $description The name of the location
	 *     @type string $latitude    The latitude in decimal degrees notation, without the degree
	 *                               symbol. e.g.: 47.615200.
	 *     @type string $longitude   The longitude in decimal degrees notation, without the degree
	 *                               symbol. e.g.: -122.341100.
	 *     @type string $country     The ISO 3166-1 alpha-2 country code. e.g.: BR
	 * }
	 */
	public function __construct( $user_id, $user_location = false ) {
		$this->user_id       = absint( $user_id );
		$this->user_location = $user_location;
	}

	/**
	 * Gets data about events near a particular location.
	 *
	 * Cached events will be immediately returned if the `user_location` property
	 * is set for the current user, and cached events exist for that location.
	 *
	 * Otherwise, this method sends a request to the w.org Events API with location
	 * data. The API will send back a recognized location based on the data, along
	 * with nearby events.
	 *
	 * The browser's request for events is proxied with this method, rather
	 * than having the browser make the request directly to api.wordpress.org,
	 * because it allows results to be cached server-side and shared with other
	 * users and sites in the network. This makes the process more efficient,
	 * since increasing the number of visits that get cached data means users
	 * don't have to wait as often; if the user's browser made the request
	 * directly, it would also need to make a second request to WP in order to
	 * pass the data for caching. Having WP make the request also introduces
	 * the opportunity to anonymize the IP before sending it to w.org, which
	 * mitigates possible privacy concerns.
	 *
	 * @since 4.8.0
	 * @since 5.5.2 Response no longer contains formatted date field. They're added
	 *              in `wp.communityEvents.populateDynamicEventFields()` now.
	 *
	 * @param string $location_search Optional. City name to help determine the location.
	 *                                e.g., "Seattle". Default empty string.
	 * @param string $timezone        Optional. Timezone to help determine the location.
	 *                                Default empty string.
	 * @return array|WP_Error A WP_Error on failure; an array with location and events on
	 *                        success.
	 */
	public function get_events( $location_search = '', $timezone = '' ) {
		$cached_events = $this->get_cached_events();

		if ( ! $location_search && $cached_events ) {
			return $cached_events;
		}

		// Include an unmodified $wp_version.
		require ABSPATH . WPINC . '/version.php';

		$api_url                    = 'http://api.wordpress.org/events/1.0/';
		$request_args               = $this->get_request_args( $location_search, $timezone );
		$request_args['user-agent'] = 'WordPress/' . $wp_version . '; ' . home_url( '/' );

		if ( wp_http_supports( array( 'ssl' ) ) ) {
			$api_url = set_url_scheme( $api_url, 'https' );
		}

		$response       = wp_remote_get( $api_url, $request_args );
		$response_code  = wp_remote_retrieve_response_code( $response );
		$response_body  = json_decode( wp_remote_retrieve_body( $response ), true );
		$response_error = null;

		if ( is_wp_error( $response ) ) {
			$response_error = $response;
		} elseif ( 200 !== $response_code ) {
			$response_error = new WP_Error(
				'api-error',
				/* translators: %d: Numeric HTTP status code, e.g. 400, 403, 500, 504, etc. */
				sprintf( __( 'Invalid API response code (%d).' ), $response_code )
			);
		} elseif ( ! isset( $response_body['location'], $response_body['events'] ) ) {
			$response_error = new WP_Error(
				'api-invalid-response',
				isset( $response_body['error'] ) ? $response_body['error'] : __( 'Unknown API error.' )
			);
		}

		if ( is_wp_error( $response_error ) ) {
			return $response_error;
		} else {
			$expiration = false;

			if ( isset( $response_body['ttl'] ) ) {
				$expiration = $response_body['ttl'];
				unset( $response_body['ttl'] );
			}

			/*
			 * The IP in the response is usually the same as the one that was sent
			 * in the request, but in some cases it is different. In those cases,
			 * it's important to reset it back to the IP from the request.
			 *
			 * For example, if the IP sent in the request is private (e.g., 192.168.1.100),
			 * then the API will ignore that and use the corresponding public IP instead,
			 * and the public IP will get returned. If the public IP were saved, though,
			 * then get_cached_events() would always return `false`, because the transient
			 * would be generated based on the public IP when saving the cache, but generated
			 * based on the private IP when retrieving the cache.
			 */
			if ( ! empty( $response_body['location']['ip'] ) ) {
				$response_body['location']['ip'] = $request_args['body']['ip'];
			}

			/*
			 * The API doesn't return a description for latitude/longitude requests,
			 * but the description is already saved in the user location, so that
			 * one can be used instead.
			 */
			if ( $this->coordinates_match( $request_args['body'], $response_body['location'] ) && empty( $response_body['location']['description'] ) ) {
				$response_body['location']['description'] = $this->user_location['description'];
			}

			/*
			 * Store the raw response, because events will expire before the cache does.
			 * The response will need to be processed every page load.
			 */
			$this->cache_events( $response_body, $expiration );

			$response_body['events'] = $this->trim_events( $response_body['events'] );

			return $response_body;
		}
	}

	/**
	 * Builds an array of args to use in an HTTP request to the w.org Events API.
	 *
	 * @since 4.8.0
	 *
	 * @param string $search   Optional. City search string. Default empty string.
	 * @param string $timezone Optional. Timezone string. Default empty string.
	 * @return array The request args.
	 */
	protected function get_request_args( $search = '', $timezone = '' ) {
		$args = array(
			'number' => 5, // Get more than three in case some get trimmed out.
			'ip'     => self::get_unsafe_client_ip(),
		);

		/*
		 * Include the minimal set of necessary arguments, in order to increase the
		 * chances of a cache-hit on the API side.
		 */
		if ( empty( $search ) && isset( $this->user_location['latitude'], $this->user_location['longitude'] ) ) {
			$args['latitude']  = $this->user_location['latitude'];
			$args['longitude'] = $this->user_location['longitude'];
		} else {
			$args['locale'] = get_user_locale( $this->user_id );

			if ( $timezone ) {
				$args['timezone'] = $timezone;
			}

			if ( $search ) {
				$args['location'] = $search;
			}
		}

		// Wrap the args in an array compatible with the second parameter of `wp_remote_get()`.
		return array(
			'body' => $args,
		);
	}

	/**
	 * Determines the user's actual IP address and attempts to partially
	 * anonymize an IP address by converting it to a network ID.
	 *
	 * Geolocating the network ID usually returns a similar location as the
	 * actual IP, but provides some privacy for the user.
	 *
	 * $_SERVER['REMOTE_ADDR'] cannot be used in all cases, such as when the user
	 * is making their request through a proxy, or when the web server is behind
	 * a proxy. In those cases, $_SERVER['REMOTE_ADDR'] is set to the proxy address rather
	 * than the user's actual address.
	 *
	 * Modified from https://stackoverflow.com/a/2031935/450127, MIT license.
	 * Modified from https://github.com/geertw/php-ip-anonymizer, MIT license.
	 *
	 * SECURITY WARNING: This function is _NOT_ intended to be used in
	 * circumstances where the authenticity of the IP address matters. This does
	 * _NOT_ guarantee that the returned address is valid or accurate, and it can
	 * be easily spoofed.
	 *
	 * @since 4.8.0
	 *
	 * @return string|false The anonymized address on success; the given address
	 *                      or false on failure.
	 */
	public static function get_unsafe_client_ip() {
		$client_ip = false;

		// In order of preference, with the best ones for this purpose first.
		$address_headers = array(
			'HTTP_CLIENT_IP',
			'HTTP_X_FORWARDED_FOR',
			'HTTP_X_FORWARDED',
			'HTTP_X_CLUSTER_CLIENT_IP',
			'HTTP_FORWARDED_FOR',
			'HTTP_FORWARDED',
			'REMOTE_ADDR',
		);

		foreach ( $address_headers as $header ) {
			if ( array_key_exists( $header, $_SERVER ) ) {
				/*
				 * HTTP_X_FORWARDED_FOR can contain a chain of comma-separated
				 * addresses. The first one is the original client. It can't be
				 * trusted for authenticity, but we don't need to for this purpose.
				 */
				$address_chain = explode( ',', $_SERVER[ $header ] );
				$client_ip     = trim( $address_chain[0] );

				break;
			}
		}

		if ( ! $client_ip ) {
			return false;
		}

		$anon_ip = wp_privacy_anonymize_ip( $client_ip, true );

		if ( '0.0.0.0' === $anon_ip || '::' === $anon_ip ) {
			return false;
		}

		return $anon_ip;
	}

	/**
	 * Test if two pairs of latitude/longitude coordinates match each other.
	 *
	 * @since 4.8.0
	 *
	 * @param array $a The first pair, with indexes 'latitude' and 'longitude'.
	 * @param array $b The second pair, with indexes 'latitude' and 'longitude'.
	 * @return bool True if they match, false if they don't.
	 */
	protected function coordinates_match( $a, $b ) {
		if ( ! isset( $a['latitude'], $a['longitude'], $b['latitude'], $b['longitude'] ) ) {
			return false;
		}

		return $a['latitude'] === $b['latitude'] && $a['longitude'] === $b['longitude'];
	}

	/**
	 * Generates a transient key based on user location.
	 *
	 * This could be reduced to a one-liner in the calling functions, but it's
	 * intentionally a separate function because it's called from multiple
	 * functions, and having it abstracted keeps the logic consistent and DRY,
	 * which is less prone to errors.
	 *
	 * @since 4.8.0
	 *
	 * @param array $location Should contain 'latitude' and 'longitude' indexes.
	 * @return string|false Transient key on success, false on failure.
	 */
	protected function get_events_transient_key( $location ) {
		$key = false;

		if ( isset( $location['ip'] ) ) {
			$key = 'community-events-' . md5( $location['ip'] );
		} elseif ( isset( $location['latitude'], $location['longitude'] ) ) {
			$key = 'community-events-' . md5( $location['latitude'] . $location['longitude'] );
		}

		return $key;
	}

	/**
	 * Caches an array of events data from the Events API.
	 *
	 * @since 4.8.0
	 *
	 * @param array     $events     Response body from the API request.
	 * @param int|false $expiration Optional. Amount of time to cache the events. Defaults to false.
	 * @return bool true if events were cached; false if not.
	 */
	protected function cache_events( $events, $expiration = false ) {
		$set              = false;
		$transient_key    = $this->get_events_transient_key( $events['location'] );
		$cache_expiration = $expiration ? absint( $expiration ) : HOUR_IN_SECONDS * 12;

		if ( $transient_key ) {
			$set = set_site_transient( $transient_key, $events, $cache_expiration );
		}

		return $set;
	}

	/**
	 * Gets cached events.
	 *
	 * @since 4.8.0
	 * @since 5.5.2 Response no longer contains formatted date field. They're added
	 *              in `wp.communityEvents.populateDynamicEventFields()` now.
	 *
	 * @return array|false An array containing `location` and `events` items
	 *                     on success, false on failure.
	 */
	public function get_cached_events() {
		$transient_key = $this->get_events_transient_key( $this->user_location );
		if ( ! $transient_key ) {
			return false;
		}

		$cached_response = get_site_transient( $transient_key );
		if ( isset( $cached_response['events'] ) ) {
			$cached_response['events'] = $this->trim_events( $cached_response['events'] );
		}

		return $cached_response;
	}

	/**
	 * Adds formatted date and time items for each event in an API response.
	 *
	 * This has to be called after the data is pulled from the cache, because
	 * the cached events are shared by all users. If it was called before storing
	 * the cache, then all users would see the events in the localized data/time
	 * of the user who triggered the cache refresh, rather than their own.
	 *
	 * @since 4.8.0
	 * @deprecated 5.5.2 No longer used in core.
	 *
	 * @param array $response_body The response which contains the events.
	 * @return array The response with dates and times formatted.
	 */
	protected function format_event_data_time( $response_body ) {
		_deprecated_function( __METHOD__, '5.5.2' );

		if ( isset( $response_body['events'] ) ) {
			foreach ( $response_body['events'] as $key => $event ) {
				$timestamp = strtotime( $event['date'] );

				/*
				 * The `date_format` option is not used because it's important
				 * in this context to keep the day of the week in the formatted date,
				 * so that users can tell at a glance if the event is on a day they
				 * are available, without having to open the link.
				 */
				/* translators: Date format for upcoming events on the dashboard. Include the day of the week. See https://www.php.net/manual/datetime.format.php */
				$formatted_date = date_i18n( __( 'l, M j, Y' ), $timestamp );
				$formatted_time = date_i18n( get_option( 'time_format' ), $timestamp );

				if ( isset( $event['end_date'] ) ) {
					$end_timestamp      = strtotime( $event['end_date'] );
					$formatted_end_date = date_i18n( __( 'l, M j, Y' ), $end_timestamp );

					if ( 'meetup' !== $event['type'] && $formatted_end_date !== $formatted_date ) {
						/* translators: Upcoming events month format. See https://www.php.net/manual/datetime.format.php */
						$start_month = date_i18n( _x( 'F', 'upcoming events month format' ), $timestamp );
						$end_month   = date_i18n( _x( 'F', 'upcoming events month format' ), $end_timestamp );

						if ( $start_month === $end_month ) {
							$formatted_date = sprintf(
								/* translators: Date string for upcoming events. 1: Month, 2: Starting day, 3: Ending day, 4: Year. */
								__( '%1$s %2$d–%3$d, %4$d' ),
								$start_month,
								/* translators: Upcoming events day format. See https://www.php.net/manual/datetime.format.php */
								date_i18n( _x( 'j', 'upcoming events day format' ), $timestamp ),
								date_i18n( _x( 'j', 'upcoming events day format' ), $end_timestamp ),
								/* translators: Upcoming events year format. See https://www.php.net/manual/datetime.format.php */
								date_i18n( _x( 'Y', 'upcoming events year format' ), $timestamp )
							);
						} else {
							$formatted_date = sprintf(
								/* translators: Date string for upcoming events. 1: Starting month, 2: Starting day, 3: Ending month, 4: Ending day, 5: Year. */
								__( '%1$s %2$d – %3$s %4$d, %5$d' ),
								$start_month,
								date_i18n( _x( 'j', 'upcoming events day format' ), $timestamp ),
								$end_month,
								date_i18n( _x( 'j', 'upcoming events day format' ), $end_timestamp ),
								date_i18n( _x( 'Y', 'upcoming events year format' ), $timestamp )
							);
						}

						$formatted_date = wp_maybe_decline_date( $formatted_date, 'F j, Y' );
					}
				}

				$response_body['events'][ $key ]['formatted_date'] = $formatted_date;
				$response_body['events'][ $key ]['formatted_time'] = $formatted_time;
			}
		}

		return $response_body;
	}

	/**
	 * Prepares the event list for presentation.
	 *
	 * Discards expired events, and makes WordCamps "sticky." Attendees need more
	 * advanced notice about WordCamps than they do for meetups, so camps should
	 * appear in the list sooner. If a WordCamp is coming up, the API will "stick"
	 * it in the response, even if it wouldn't otherwise appear. When that happens,
	 * the event will be at the end of the list, and will need to be moved into a
	 * higher position, so that it doesn't get trimmed off.
	 *
	 * @since 4.8.0
	 * @since 4.9.7 Stick a WordCamp to the final list.
	 * @since 5.5.2 Accepts and returns only the events, rather than an entire HTTP response.
	 * @since 6.0.0 Decode HTML entities from the event title.
	 *
	 * @param array $events The events that will be prepared.
	 * @return array The response body with events trimmed.
	 */
	protected function trim_events( array $events ) {
		$future_events = array();

		foreach ( $events as $event ) {
			/*
			 * The API's `date` and `end_date` fields are in the _event's_ local timezone, but UTC is needed so
			 * it can be converted to the _user's_ local time.
			 */
			$end_time = (int) $event['end_unix_timestamp'];

			if ( time() < $end_time ) {
				// Decode HTML entities from the event title.
				$event['title'] = html_entity_decode( $event['title'], ENT_QUOTES, 'UTF-8' );

				array_push( $future_events, $event );
			}
		}

		$future_wordcamps = array_filter(
			$future_events,
			static function ( $wordcamp ) {
				return 'wordcamp' === $wordcamp['type'];
			}
		);

		$future_wordcamps    = array_values( $future_wordcamps ); // Remove gaps in indices.
		$trimmed_events      = array_slice( $future_events, 0, 3 );
		$trimmed_event_types = wp_list_pluck( $trimmed_events, 'type' );

		// Make sure the soonest upcoming WordCamp is pinned in the list.
		if ( $future_wordcamps && ! in_array( 'wordcamp', $trimmed_event_types, true ) ) {
			array_pop( $trimmed_events );
			array_push( $trimmed_events, $future_wordcamps[0] );
		}

		return $trimmed_events;
	}

	/**
	 * Logs responses to Events API requests.
	 *
	 * @since 4.8.0
	 * @deprecated 4.9.0 Use a plugin instead. See #41217 for an example.
	 *
	 * @param string $message A description of what occurred.
	 * @param array  $details Details that provide more context for the
	 *                        log entry.
	 */
	protected function maybe_log_events_response( $message, $details ) {
		_deprecated_function( __METHOD__, '4.9.0' );

		if ( ! WP_DEBUG_LOG ) {
			return;
		}

		error_log(
			sprintf(
				'%s: %s. Details: %s',
				__METHOD__,
				trim( $message, '.' ),
				wp_json_encode( $details )
			)
		);
	}
}
class-wp-internal-pointers.php000064400000011010151212616050012451 0ustar00<?php
/**
 * Administration API: WP_Internal_Pointers class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 4.4.0
 */

/**
 * Core class used to implement an internal admin pointers API.
 *
 * @since 3.3.0
 */
#[AllowDynamicProperties]
final class WP_Internal_Pointers {
	/**
	 * Initializes the new feature pointers.
	 *
	 * @since 3.3.0
	 *
	 * All pointers can be disabled using the following:
	 *     remove_action( 'admin_enqueue_scripts', array( 'WP_Internal_Pointers', 'enqueue_scripts' ) );
	 *
	 * Individual pointers (e.g. wp390_widgets) can be disabled using the following:
	 *
	 *    function yourprefix_remove_pointers() {
	 *        remove_action(
	 *            'admin_print_footer_scripts',
	 *            array( 'WP_Internal_Pointers', 'pointer_wp390_widgets' )
	 *        );
	 *    }
	 *    add_action( 'admin_enqueue_scripts', 'yourprefix_remove_pointers', 11 );
	 *
	 * @param string $hook_suffix The current admin page.
	 */
	public static function enqueue_scripts( $hook_suffix ) {
		/*
		 * Register feature pointers
		 *
		 * Format:
		 *     array(
		 *         hook_suffix => pointer callback
		 *     )
		 *
		 * Example:
		 *     array(
		 *         'themes.php' => 'wp390_widgets'
		 *     )
		 */
		$registered_pointers = array(
			// None currently.
		);

		// Check if screen related pointer is registered.
		if ( empty( $registered_pointers[ $hook_suffix ] ) ) {
			return;
		}

		$pointers = (array) $registered_pointers[ $hook_suffix ];

		/*
		 * Specify required capabilities for feature pointers
		 *
		 * Format:
		 *     array(
		 *         pointer callback => Array of required capabilities
		 *     )
		 *
		 * Example:
		 *     array(
		 *         'wp390_widgets' => array( 'edit_theme_options' )
		 *     )
		 */
		$caps_required = array(
			// None currently.
		);

		// Get dismissed pointers.
		$dismissed = explode( ',', (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true ) );

		$got_pointers = false;
		foreach ( array_diff( $pointers, $dismissed ) as $pointer ) {
			if ( isset( $caps_required[ $pointer ] ) ) {
				foreach ( $caps_required[ $pointer ] as $cap ) {
					if ( ! current_user_can( $cap ) ) {
						continue 2;
					}
				}
			}

			// Bind pointer print function.
			add_action( 'admin_print_footer_scripts', array( 'WP_Internal_Pointers', 'pointer_' . $pointer ) );
			$got_pointers = true;
		}

		if ( ! $got_pointers ) {
			return;
		}

		// Add pointers script and style to queue.
		wp_enqueue_style( 'wp-pointer' );
		wp_enqueue_script( 'wp-pointer' );
	}

	/**
	 * Prints the pointer JavaScript data.
	 *
	 * @since 3.3.0
	 *
	 * @param string $pointer_id The pointer ID.
	 * @param string $selector The HTML elements, on which the pointer should be attached.
	 * @param array  $args Arguments to be passed to the pointer JS (see wp-pointer.js).
	 */
	private static function print_js( $pointer_id, $selector, $args ) {
		if ( empty( $pointer_id ) || empty( $selector ) || empty( $args ) || empty( $args['content'] ) ) {
			return;
		}

		?>
		<script type="text/javascript">
		(function($){
			var options = <?php echo wp_json_encode( $args, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ); ?>, setup;

			if ( ! options )
				return;

			options = $.extend( options, {
				close: function() {
					$.post( ajaxurl, {
						pointer: '<?php echo $pointer_id; ?>',
						action: 'dismiss-wp-pointer'
					});
				}
			});

			setup = function() {
				$('<?php echo $selector; ?>').first().pointer( options ).pointer('open');
			};

			if ( options.position && options.position.defer_loading )
				$(window).bind( 'load.wp-pointers', setup );
			else
				$( function() {
					setup();
				} );

		})( jQuery );
		</script>
		<?php
	}

	public static function pointer_wp330_toolbar() {}
	public static function pointer_wp330_media_uploader() {}
	public static function pointer_wp330_saving_widgets() {}
	public static function pointer_wp340_customize_current_theme_link() {}
	public static function pointer_wp340_choose_image_from_library() {}
	public static function pointer_wp350_media() {}
	public static function pointer_wp360_revisions() {}
	public static function pointer_wp360_locks() {}
	public static function pointer_wp390_widgets() {}
	public static function pointer_wp410_dfw() {}
	public static function pointer_wp496_privacy() {}

	/**
	 * Prevents new users from seeing existing 'new feature' pointers.
	 *
	 * @since 3.3.0
	 *
	 * @param int $user_id User ID.
	 */
	public static function dismiss_pointers_for_new_users( $user_id ) {
		add_user_meta( $user_id, 'dismissed_wp_pointers', '' );
	}
}
class-wp-terms-list-table.php000064400000051360151212616050012200 0ustar00<?php
/**
 * List Table API: WP_Terms_List_Table class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 3.1.0
 */

/**
 * Core class used to implement displaying terms in a list table.
 *
 * @since 3.1.0
 *
 * @see WP_List_Table
 */
class WP_Terms_List_Table extends WP_List_Table {

	public $callback_args;

	private $level;

	/**
	 * Constructor.
	 *
	 * @since 3.1.0
	 *
	 * @see WP_List_Table::__construct() for more information on default arguments.
	 *
	 * @global string      $post_type Global post type.
	 * @global string      $taxonomy  Global taxonomy.
	 * @global string      $action
	 * @global WP_Taxonomy $tax       Global taxonomy object.
	 *
	 * @param array $args An associative array of arguments.
	 */
	public function __construct( $args = array() ) {
		global $post_type, $taxonomy, $action, $tax;

		parent::__construct(
			array(
				'plural'   => 'tags',
				'singular' => 'tag',
				'screen'   => isset( $args['screen'] ) ? $args['screen'] : null,
			)
		);

		$action    = $this->screen->action;
		$post_type = $this->screen->post_type;
		$taxonomy  = $this->screen->taxonomy;

		if ( empty( $taxonomy ) ) {
			$taxonomy = 'post_tag';
		}

		if ( ! taxonomy_exists( $taxonomy ) ) {
			wp_die( __( 'Invalid taxonomy.' ) );
		}

		$tax = get_taxonomy( $taxonomy );

		// @todo Still needed? Maybe just the show_ui part.
		if ( empty( $post_type ) || ! in_array( $post_type, get_post_types( array( 'show_ui' => true ) ), true ) ) {
			$post_type = 'post';
		}
	}

	/**
	 * @return bool
	 */
	public function ajax_user_can() {
		return current_user_can( get_taxonomy( $this->screen->taxonomy )->cap->manage_terms );
	}

	/**
	 */
	public function prepare_items() {
		$taxonomy = $this->screen->taxonomy;

		$tags_per_page = $this->get_items_per_page( "edit_{$taxonomy}_per_page" );

		if ( 'post_tag' === $taxonomy ) {
			/**
			 * Filters the number of terms displayed per page for the Tags list table.
			 *
			 * @since 2.8.0
			 *
			 * @param int $tags_per_page Number of tags to be displayed. Default 20.
			 */
			$tags_per_page = apply_filters( 'edit_tags_per_page', $tags_per_page );

			/**
			 * Filters the number of terms displayed per page for the Tags list table.
			 *
			 * @since 2.7.0
			 * @deprecated 2.8.0 Use {@see 'edit_tags_per_page'} instead.
			 *
			 * @param int $tags_per_page Number of tags to be displayed. Default 20.
			 */
			$tags_per_page = apply_filters_deprecated( 'tagsperpage', array( $tags_per_page ), '2.8.0', 'edit_tags_per_page' );
		} elseif ( 'category' === $taxonomy ) {
			/**
			 * Filters the number of terms displayed per page for the Categories list table.
			 *
			 * @since 2.8.0
			 *
			 * @param int $tags_per_page Number of categories to be displayed. Default 20.
			 */
			$tags_per_page = apply_filters( 'edit_categories_per_page', $tags_per_page );
		}

		$search = ! empty( $_REQUEST['s'] ) ? trim( wp_unslash( $_REQUEST['s'] ) ) : '';

		$args = array(
			'taxonomy'   => $taxonomy,
			'search'     => $search,
			'page'       => $this->get_pagenum(),
			'number'     => $tags_per_page,
			'hide_empty' => 0,
		);

		if ( ! empty( $_REQUEST['orderby'] ) ) {
			$args['orderby'] = trim( wp_unslash( $_REQUEST['orderby'] ) );
		}

		if ( ! empty( $_REQUEST['order'] ) ) {
			$args['order'] = trim( wp_unslash( $_REQUEST['order'] ) );
		}

		$args['offset'] = ( $args['page'] - 1 ) * $args['number'];

		// Save the values because 'number' and 'offset' can be subsequently overridden.
		$this->callback_args = $args;

		if ( is_taxonomy_hierarchical( $taxonomy ) && ! isset( $args['orderby'] ) ) {
			// We'll need the full set of terms then.
			$args['number'] = 0;
			$args['offset'] = $args['number'];
		}

		$this->items = get_terms( $args );

		$this->set_pagination_args(
			array(
				'total_items' => wp_count_terms(
					array(
						'taxonomy' => $taxonomy,
						'search'   => $search,
					)
				),
				'per_page'    => $tags_per_page,
			)
		);
	}

	/**
	 */
	public function no_items() {
		echo get_taxonomy( $this->screen->taxonomy )->labels->not_found;
	}

	/**
	 * @return array
	 */
	protected function get_bulk_actions() {
		$actions = array();

		if ( current_user_can( get_taxonomy( $this->screen->taxonomy )->cap->delete_terms ) ) {
			$actions['delete'] = __( 'Delete' );
		}

		return $actions;
	}

	/**
	 * @return string
	 */
	public function current_action() {
		if ( isset( $_REQUEST['action'] ) && isset( $_REQUEST['delete_tags'] ) && 'delete' === $_REQUEST['action'] ) {
			return 'bulk-delete';
		}

		return parent::current_action();
	}

	/**
	 * @return string[] Array of column titles keyed by their column name.
	 */
	public function get_columns() {
		$columns = array(
			'cb'          => '<input type="checkbox" />',
			'name'        => _x( 'Name', 'term name' ),
			'description' => __( 'Description' ),
			'slug'        => __( 'Slug' ),
		);

		if ( 'link_category' === $this->screen->taxonomy ) {
			$columns['links'] = __( 'Links' );
		} else {
			$columns['posts'] = _x( 'Count', 'Number/count of items' );
		}

		return $columns;
	}

	/**
	 * @return array
	 */
	protected function get_sortable_columns() {
		$taxonomy = $this->screen->taxonomy;

		if ( ! isset( $_GET['orderby'] ) && is_taxonomy_hierarchical( $taxonomy ) ) {
			$name_orderby_text = __( 'Table ordered hierarchically.' );
		} else {
			$name_orderby_text = __( 'Table ordered by Name.' );
		}

		return array(
			'name'        => array( 'name', false, _x( 'Name', 'term name' ), $name_orderby_text, 'asc' ),
			'description' => array( 'description', false, __( 'Description' ), __( 'Table ordered by Description.' ) ),
			'slug'        => array( 'slug', false, __( 'Slug' ), __( 'Table ordered by Slug.' ) ),
			'posts'       => array( 'count', false, _x( 'Count', 'Number/count of items' ), __( 'Table ordered by Posts Count.' ) ),
			'links'       => array( 'count', false, __( 'Links' ), __( 'Table ordered by Links.' ) ),
		);
	}

	/**
	 */
	public function display_rows_or_placeholder() {
		$taxonomy = $this->screen->taxonomy;

		$number = $this->callback_args['number'];
		$offset = $this->callback_args['offset'];

		// Convert it to table rows.
		$count = 0;

		if ( empty( $this->items ) || ! is_array( $this->items ) ) {
			echo '<tr class="no-items"><td class="colspanchange" colspan="' . $this->get_column_count() . '">';
			$this->no_items();
			echo '</td></tr>';
			return;
		}

		if ( is_taxonomy_hierarchical( $taxonomy ) && ! isset( $this->callback_args['orderby'] ) ) {
			if ( ! empty( $this->callback_args['search'] ) ) {// Ignore children on searches.
				$children = array();
			} else {
				$children = _get_term_hierarchy( $taxonomy );
			}

			/*
			 * Some funky recursion to get the job done (paging & parents mainly) is contained within.
			 * Skip it for non-hierarchical taxonomies for performance sake.
			 */
			$this->_rows( $taxonomy, $this->items, $children, $offset, $number, $count );
		} else {
			foreach ( $this->items as $term ) {
				$this->single_row( $term );
			}
		}
	}

	/**
	 * @param string $taxonomy
	 * @param array  $terms
	 * @param array  $children
	 * @param int    $start
	 * @param int    $per_page
	 * @param int    $count
	 * @param int    $parent_term
	 * @param int    $level
	 */
	private function _rows( $taxonomy, $terms, &$children, $start, $per_page, &$count, $parent_term = 0, $level = 0 ) {

		$end = $start + $per_page;

		foreach ( $terms as $key => $term ) {

			if ( $count >= $end ) {
				break;
			}

			if ( $term->parent !== $parent_term && empty( $_REQUEST['s'] ) ) {
				continue;
			}

			// If the page starts in a subtree, print the parents.
			if ( $count === $start && $term->parent > 0 && empty( $_REQUEST['s'] ) ) {
				$my_parents = array();
				$parent_ids = array();
				$p          = $term->parent;

				while ( $p ) {
					$my_parent    = get_term( $p, $taxonomy );
					$my_parents[] = $my_parent;
					$p            = $my_parent->parent;

					if ( in_array( $p, $parent_ids, true ) ) { // Prevent parent loops.
						break;
					}

					$parent_ids[] = $p;
				}

				unset( $parent_ids );

				$num_parents = count( $my_parents );

				while ( $my_parent = array_pop( $my_parents ) ) {
					echo "\t";
					$this->single_row( $my_parent, $level - $num_parents );
					--$num_parents;
				}
			}

			if ( $count >= $start ) {
				echo "\t";
				$this->single_row( $term, $level );
			}

			++$count;

			unset( $terms[ $key ] );

			if ( isset( $children[ $term->term_id ] ) && empty( $_REQUEST['s'] ) ) {
				$this->_rows( $taxonomy, $terms, $children, $start, $per_page, $count, $term->term_id, $level + 1 );
			}
		}
	}

	/**
	 * @global string $taxonomy Global taxonomy.
	 *
	 * @param WP_Term $tag   Term object.
	 * @param int     $level
	 */
	public function single_row( $tag, $level = 0 ) {
		global $taxonomy;
		$tag = sanitize_term( $tag, $taxonomy );

		$this->level = $level;

		if ( $tag->parent ) {
			$count = count( get_ancestors( $tag->term_id, $taxonomy, 'taxonomy' ) );
			$level = 'level-' . $count;
		} else {
			$level = 'level-0';
		}

		echo '<tr id="tag-' . $tag->term_id . '" class="' . $level . '">';
		$this->single_row_columns( $tag );
		echo '</tr>';
	}

	/**
	 * @since 5.9.0 Renamed `$tag` to `$item` to match parent class for PHP 8 named parameter support.
	 *
	 * @param WP_Term $item Term object.
	 * @return string
	 */
	public function column_cb( $item ) {
		// Restores the more descriptive, specific name for use within this method.
		$tag = $item;

		if ( current_user_can( 'delete_term', $tag->term_id ) ) {
			return sprintf(
				'<input type="checkbox" name="delete_tags[]" value="%1$s" id="cb-select-%1$s" />' .
				'<label for="cb-select-%1$s"><span class="screen-reader-text">%2$s</span></label>',
				$tag->term_id,
				/* translators: Hidden accessibility text. %s: Taxonomy term name. */
				sprintf( __( 'Select %s' ), $tag->name )
			);
		}

		return '&nbsp;';
	}

	/**
	 * @param WP_Term $tag Term object.
	 * @return string
	 */
	public function column_name( $tag ) {
		$taxonomy = $this->screen->taxonomy;

		$pad = str_repeat( '&#8212; ', max( 0, $this->level ) );

		/**
		 * Filters display of the term name in the terms list table.
		 *
		 * The default output may include padding due to the term's
		 * current level in the term hierarchy.
		 *
		 * @since 2.5.0
		 *
		 * @see WP_Terms_List_Table::column_name()
		 *
		 * @param string $pad_tag_name The term name, padded if not top-level.
		 * @param WP_Term $tag         Term object.
		 */
		$name = apply_filters( 'term_name', $pad . ' ' . $tag->name, $tag );

		$qe_data = get_term( $tag->term_id, $taxonomy, OBJECT, 'edit' );

		$uri = wp_doing_ajax() ? wp_get_referer() : $_SERVER['REQUEST_URI'];

		$edit_link = get_edit_term_link( $tag, $taxonomy, $this->screen->post_type );

		if ( $edit_link ) {
			$edit_link = add_query_arg(
				'wp_http_referer',
				urlencode( wp_unslash( $uri ) ),
				$edit_link
			);
			$name      = sprintf(
				'<a class="row-title" href="%s" aria-label="%s">%s</a>',
				esc_url( $edit_link ),
				/* translators: %s: Taxonomy term name. */
				esc_attr( sprintf( __( '&#8220;%s&#8221; (Edit)' ), $tag->name ) ),
				$name
			);
		}

		$output = sprintf(
			'<strong>%s</strong><br />',
			$name
		);

		/** This filter is documented in wp-admin/includes/class-wp-terms-list-table.php */
		$quick_edit_enabled = apply_filters( 'quick_edit_enabled_for_taxonomy', true, $taxonomy );

		if ( $quick_edit_enabled ) {
			$output .= '<div class="hidden" id="inline_' . $qe_data->term_id . '">';
			$output .= '<div class="name">' . $qe_data->name . '</div>';

			/** This filter is documented in wp-admin/edit-tag-form.php */
			$output .= '<div class="slug">' . apply_filters( 'editable_slug', $qe_data->slug, $qe_data ) . '</div>';
			$output .= '<div class="parent">' . $qe_data->parent . '</div></div>';
		}

		return $output;
	}

	/**
	 * Gets the name of the default primary column.
	 *
	 * @since 4.3.0
	 *
	 * @return string Name of the default primary column, in this case, 'name'.
	 */
	protected function get_default_primary_column_name() {
		return 'name';
	}

	/**
	 * Generates and displays row action links.
	 *
	 * @since 4.3.0
	 * @since 5.9.0 Renamed `$tag` to `$item` to match parent class for PHP 8 named parameter support.
	 *
	 * @param WP_Term $item        Tag being acted upon.
	 * @param string  $column_name Current column name.
	 * @param string  $primary     Primary column name.
	 * @return string Row actions output for terms, or an empty string
	 *                if the current column is not the primary column.
	 */
	protected function handle_row_actions( $item, $column_name, $primary ) {
		if ( $primary !== $column_name ) {
			return '';
		}

		// Restores the more descriptive, specific name for use within this method.
		$tag = $item;

		$taxonomy = $this->screen->taxonomy;
		$uri      = wp_doing_ajax() ? wp_get_referer() : $_SERVER['REQUEST_URI'];

		$actions = array();

		if ( current_user_can( 'edit_term', $tag->term_id ) ) {
			$actions['edit'] = sprintf(
				'<a href="%s" aria-label="%s">%s</a>',
				esc_url(
					add_query_arg(
						'wp_http_referer',
						urlencode( wp_unslash( $uri ) ),
						get_edit_term_link( $tag, $taxonomy, $this->screen->post_type )
					)
				),
				/* translators: %s: Taxonomy term name. */
				esc_attr( sprintf( __( 'Edit &#8220;%s&#8221;' ), $tag->name ) ),
				__( 'Edit' )
			);

			/**
			 * Filters whether Quick Edit should be enabled for the given taxonomy.
			 *
			 * @since 6.4.0
			 *
			 * @param bool   $enable   Whether to enable the Quick Edit functionality. Default true.
			 * @param string $taxonomy Taxonomy name.
			 */
			$quick_edit_enabled = apply_filters( 'quick_edit_enabled_for_taxonomy', true, $taxonomy );

			if ( $quick_edit_enabled ) {
				$actions['inline hide-if-no-js'] = sprintf(
					'<button type="button" class="button-link editinline" aria-label="%s" aria-expanded="false">%s</button>',
					/* translators: %s: Taxonomy term name. */
					esc_attr( sprintf( __( 'Quick edit &#8220;%s&#8221; inline' ), $tag->name ) ),
					__( 'Quick&nbsp;Edit' )
				);
			}
		}

		if ( current_user_can( 'delete_term', $tag->term_id ) ) {
			$actions['delete'] = sprintf(
				'<a href="%s" class="delete-tag aria-button-if-js" aria-label="%s">%s</a>',
				wp_nonce_url( "edit-tags.php?action=delete&amp;taxonomy=$taxonomy&amp;tag_ID=$tag->term_id", 'delete-tag_' . $tag->term_id ),
				/* translators: %s: Taxonomy term name. */
				esc_attr( sprintf( __( 'Delete &#8220;%s&#8221;' ), $tag->name ) ),
				__( 'Delete' )
			);
		}

		if ( is_term_publicly_viewable( $tag ) ) {
			$actions['view'] = sprintf(
				'<a href="%s" aria-label="%s">%s</a>',
				get_term_link( $tag ),
				/* translators: %s: Taxonomy term name. */
				esc_attr( sprintf( __( 'View &#8220;%s&#8221; archive' ), $tag->name ) ),
				__( 'View' )
			);
		}

		/**
		 * Filters the action links displayed for each term in the Tags list table.
		 *
		 * @since 2.8.0
		 * @since 3.0.0 Deprecated in favor of {@see '{$taxonomy}_row_actions'} filter.
		 * @since 5.4.2 Restored (un-deprecated).
		 *
		 * @param string[] $actions An array of action links to be displayed. Default
		 *                          'Edit', 'Quick Edit', 'Delete', and 'View'.
		 * @param WP_Term  $tag     Term object.
		 */
		$actions = apply_filters( 'tag_row_actions', $actions, $tag );

		/**
		 * Filters the action links displayed for each term in the terms list table.
		 *
		 * The dynamic portion of the hook name, `$taxonomy`, refers to the taxonomy slug.
		 *
		 * Possible hook names include:
		 *
		 *  - `category_row_actions`
		 *  - `post_tag_row_actions`
		 *
		 * @since 3.0.0
		 *
		 * @param string[] $actions An array of action links to be displayed. Default
		 *                          'Edit', 'Quick Edit', 'Delete', and 'View'.
		 * @param WP_Term  $tag     Term object.
		 */
		$actions = apply_filters( "{$taxonomy}_row_actions", $actions, $tag );

		return $this->row_actions( $actions );
	}

	/**
	 * @param WP_Term $tag Term object.
	 * @return string
	 */
	public function column_description( $tag ) {
		if ( $tag->description ) {
			return $tag->description;
		} else {
			return '<span aria-hidden="true">&#8212;</span><span class="screen-reader-text">' .
				/* translators: Hidden accessibility text. */
				__( 'No description' ) .
			'</span>';
		}
	}

	/**
	 * @param WP_Term $tag Term object.
	 * @return string
	 */
	public function column_slug( $tag ) {
		/** This filter is documented in wp-admin/edit-tag-form.php */
		return apply_filters( 'editable_slug', $tag->slug, $tag );
	}

	/**
	 * @param WP_Term $tag Term object.
	 * @return string
	 */
	public function column_posts( $tag ) {
		$count = number_format_i18n( $tag->count );

		$tax = get_taxonomy( $this->screen->taxonomy );

		$ptype_object = get_post_type_object( $this->screen->post_type );
		if ( ! $ptype_object->show_ui ) {
			return $count;
		}

		if ( $tax->query_var ) {
			$args = array( $tax->query_var => $tag->slug );
		} else {
			$args = array(
				'taxonomy' => $tax->name,
				'term'     => $tag->slug,
			);
		}

		if ( 'post' !== $this->screen->post_type ) {
			$args['post_type'] = $this->screen->post_type;
		}

		if ( 'attachment' === $this->screen->post_type ) {
			return "<a href='" . esc_url( add_query_arg( $args, 'upload.php' ) ) . "'>$count</a>";
		}

		return "<a href='" . esc_url( add_query_arg( $args, 'edit.php' ) ) . "'>$count</a>";
	}

	/**
	 * @param WP_Term $tag Term object.
	 * @return string
	 */
	public function column_links( $tag ) {
		$count = number_format_i18n( $tag->count );

		if ( $count ) {
			$count = "<a href='link-manager.php?cat_id=$tag->term_id'>$count</a>";
		}

		return $count;
	}

	/**
	 * @since 5.9.0 Renamed `$tag` to `$item` to match parent class for PHP 8 named parameter support.
	 *
	 * @param WP_Term $item        Term object.
	 * @param string  $column_name Name of the column.
	 * @return string
	 */
	public function column_default( $item, $column_name ) {
		// Restores the more descriptive, specific name for use within this method.
		$tag = $item;

		/**
		 * Filters the displayed columns in the terms list table.
		 *
		 * The dynamic portion of the hook name, `$this->screen->taxonomy`,
		 * refers to the slug of the current taxonomy.
		 *
		 * Possible hook names include:
		 *
		 *  - `manage_category_custom_column`
		 *  - `manage_post_tag_custom_column`
		 *
		 * @since 2.8.0
		 *
		 * @param string $string      Custom column output. Default empty.
		 * @param string $column_name Name of the column.
		 * @param int    $term_id     Term ID.
		 */
		return apply_filters( "manage_{$this->screen->taxonomy}_custom_column", '', $column_name, $tag->term_id );
	}

	/**
	 * Outputs the hidden row displayed when inline editing
	 *
	 * @since 3.1.0
	 */
	public function inline_edit() {
		$tax = get_taxonomy( $this->screen->taxonomy );

		if ( ! current_user_can( $tax->cap->edit_terms ) ) {
			return;
		}
		?>

		<form method="get">
		<table style="display: none"><tbody id="inlineedit">

			<tr id="inline-edit" class="inline-edit-row" style="display: none">
			<td colspan="<?php echo $this->get_column_count(); ?>" class="colspanchange">
			<div class="inline-edit-wrapper">

			<fieldset>
				<legend class="inline-edit-legend"><?php _e( 'Quick Edit' ); ?></legend>
				<div class="inline-edit-col">
				<label>
					<span class="title"><?php _ex( 'Name', 'term name' ); ?></span>
					<span class="input-text-wrap"><input type="text" name="name" class="ptitle" value="" /></span>
				</label>

				<label>
					<span class="title"><?php _e( 'Slug' ); ?></span>
					<span class="input-text-wrap"><input type="text" name="slug" class="ptitle" value="" /></span>
				</label>
				</div>
			</fieldset>

			<?php
			$core_columns = array(
				'cb'          => true,
				'description' => true,
				'name'        => true,
				'slug'        => true,
				'posts'       => true,
			);

			list( $columns ) = $this->get_column_info();

			foreach ( $columns as $column_name => $column_display_name ) {
				if ( isset( $core_columns[ $column_name ] ) ) {
					continue;
				}

				/** This action is documented in wp-admin/includes/class-wp-posts-list-table.php */
				do_action( 'quick_edit_custom_box', $column_name, 'edit-tags', $this->screen->taxonomy );
			}
			?>

			<div class="inline-edit-save submit">
				<button type="button" class="save button button-primary"><?php echo $tax->labels->update_item; ?></button>
				<button type="button" class="cancel button"><?php _e( 'Cancel' ); ?></button>
				<span class="spinner"></span>

				<?php wp_nonce_field( 'taxinlineeditnonce', '_inline_edit', false ); ?>
				<input type="hidden" name="taxonomy" value="<?php echo esc_attr( $this->screen->taxonomy ); ?>" />
				<input type="hidden" name="post_type" value="<?php echo esc_attr( $this->screen->post_type ); ?>" />

				<?php
				wp_admin_notice(
					'<p class="error"></p>',
					array(
						'type'               => 'error',
						'additional_classes' => array( 'notice-alt', 'inline', 'hidden' ),
						'paragraph_wrap'     => false,
					)
				);
				?>
			</div>
			</div>

			</td></tr>

		</tbody></table>
		</form>
		<?php
	}
}
class-wp-upgrader-skin.php000064400000015706151212616050011567 0ustar00<?php
/**
 * Upgrader API: WP_Upgrader_Skin class
 *
 * @package WordPress
 * @subpackage Upgrader
 * @since 4.6.0
 */

/**
 * Generic Skin for the WordPress Upgrader classes. This skin is designed to be extended for specific purposes.
 *
 * @since 2.8.0
 * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader-skins.php.
 */
#[AllowDynamicProperties]
class WP_Upgrader_Skin {

	/**
	 * Holds the upgrader data.
	 *
	 * @since 2.8.0
	 * @var WP_Upgrader
	 */
	public $upgrader;

	/**
	 * Whether header is done.
	 *
	 * @since 2.8.0
	 * @var bool
	 */
	public $done_header = false;

	/**
	 * Whether footer is done.
	 *
	 * @since 2.8.0
	 * @var bool
	 */
	public $done_footer = false;

	/**
	 * Holds the result of an upgrade.
	 *
	 * @since 2.8.0
	 * @var string|bool|WP_Error
	 */
	public $result = false;

	/**
	 * Holds the options of an upgrade.
	 *
	 * @since 2.8.0
	 * @var array
	 */
	public $options = array();

	/**
	 * Constructor.
	 *
	 * Sets up the generic skin for the WordPress Upgrader classes.
	 *
	 * @since 2.8.0
	 *
	 * @param array $args Optional. The WordPress upgrader skin arguments to
	 *                    override default options. Default empty array.
	 */
	public function __construct( $args = array() ) {
		$defaults      = array(
			'url'     => '',
			'nonce'   => '',
			'title'   => '',
			'context' => false,
		);
		$this->options = wp_parse_args( $args, $defaults );
	}

	/**
	 * Sets the relationship between the skin being used and the upgrader.
	 *
	 * @since 2.8.0
	 *
	 * @param WP_Upgrader $upgrader
	 */
	public function set_upgrader( &$upgrader ) {
		if ( is_object( $upgrader ) ) {
			$this->upgrader =& $upgrader;
		}
		$this->add_strings();
	}

	/**
	 * Sets up the strings used in the update process.
	 *
	 * @since 3.0.0
	 */
	public function add_strings() {
	}

	/**
	 * Sets the result of an upgrade.
	 *
	 * @since 2.8.0
	 *
	 * @param string|bool|WP_Error $result The result of an upgrade.
	 */
	public function set_result( $result ) {
		$this->result = $result;
	}

	/**
	 * Displays a form to the user to request for their FTP/SSH details in order
	 * to connect to the filesystem.
	 *
	 * @since 2.8.0
	 * @since 4.6.0 The `$context` parameter default changed from `false` to an empty string.
	 *
	 * @see request_filesystem_credentials()
	 *
	 * @param bool|WP_Error $error                        Optional. Whether the current request has failed to connect,
	 *                                                    or an error object. Default false.
	 * @param string        $context                      Optional. Full path to the directory that is tested
	 *                                                    for being writable. Default empty.
	 * @param bool          $allow_relaxed_file_ownership Optional. Whether to allow Group/World writable. Default false.
	 * @return bool True on success, false on failure.
	 */
	public function request_filesystem_credentials( $error = false, $context = '', $allow_relaxed_file_ownership = false ) {
		$url = $this->options['url'];
		if ( ! $context ) {
			$context = $this->options['context'];
		}
		if ( ! empty( $this->options['nonce'] ) ) {
			$url = wp_nonce_url( $url, $this->options['nonce'] );
		}

		$extra_fields = array();

		return request_filesystem_credentials( $url, '', $error, $context, $extra_fields, $allow_relaxed_file_ownership );
	}

	/**
	 * Displays the header before the update process.
	 *
	 * @since 2.8.0
	 */
	public function header() {
		if ( $this->done_header ) {
			return;
		}
		$this->done_header = true;
		echo '<div class="wrap">';
		echo '<h1>' . $this->options['title'] . '</h1>';
	}

	/**
	 * Displays the footer following the update process.
	 *
	 * @since 2.8.0
	 */
	public function footer() {
		if ( $this->done_footer ) {
			return;
		}
		$this->done_footer = true;
		echo '</div>';
	}

	/**
	 * Displays an error message about the update.
	 *
	 * @since 2.8.0
	 *
	 * @param string|WP_Error $errors Errors.
	 */
	public function error( $errors ) {
		if ( ! $this->done_header ) {
			$this->header();
		}
		if ( is_string( $errors ) ) {
			$this->feedback( $errors );
		} elseif ( is_wp_error( $errors ) && $errors->has_errors() ) {
			foreach ( $errors->get_error_messages() as $message ) {
				if ( $errors->get_error_data() && is_string( $errors->get_error_data() ) ) {
					$this->feedback( $message . ' ' . esc_html( strip_tags( $errors->get_error_data() ) ) );
				} else {
					$this->feedback( $message );
				}
			}
		}
	}

	/**
	 * Displays a message about the update.
	 *
	 * @since 2.8.0
	 * @since 5.9.0 Renamed `$string` (a PHP reserved keyword) to `$feedback` for PHP 8 named parameter support.
	 *
	 * @param string $feedback Message data.
	 * @param mixed  ...$args  Optional text replacements.
	 */
	public function feedback( $feedback, ...$args ) {
		if ( isset( $this->upgrader->strings[ $feedback ] ) ) {
			$feedback = $this->upgrader->strings[ $feedback ];
		}

		if ( str_contains( $feedback, '%' ) ) {
			if ( $args ) {
				$args     = array_map( 'strip_tags', $args );
				$args     = array_map( 'esc_html', $args );
				$feedback = vsprintf( $feedback, $args );
			}
		}
		if ( empty( $feedback ) ) {
			return;
		}
		show_message( $feedback );
	}

	/**
	 * Performs an action before an update.
	 *
	 * @since 2.8.0
	 */
	public function before() {}

	/**
	 * Performs an action following an update.
	 *
	 * @since 2.8.0
	 */
	public function after() {}

	/**
	 * Outputs JavaScript that calls function to decrement the update counts.
	 *
	 * @since 3.9.0
	 *
	 * @param string $type Type of update count to decrement. Likely values include 'plugin',
	 *                     'theme', 'translation', etc.
	 */
	protected function decrement_update_count( $type ) {
		if ( ! $this->result || is_wp_error( $this->result ) || 'up_to_date' === $this->result ) {
			return;
		}

		if ( defined( 'IFRAME_REQUEST' ) ) {
			echo '<script type="text/javascript">
					if ( window.postMessage && JSON ) {
						window.parent.postMessage(
							JSON.stringify( {
								action: "decrementUpdateCount",
								upgradeType: "' . $type . '"
							} ),
							window.location.protocol + "//" + window.location.hostname
								+ ( "" !== window.location.port ? ":" + window.location.port : "" )
						);
					}
				</script>';
		} else {
			echo '<script type="text/javascript">
					(function( wp ) {
						if ( wp && wp.updates && wp.updates.decrementCount ) {
							wp.updates.decrementCount( "' . $type . '" );
						}
					})( window.wp );
				</script>';
		}
	}

	/**
	 * Displays the header before the bulk update process.
	 *
	 * @since 3.0.0
	 */
	public function bulk_header() {}

	/**
	 * Displays the footer following the bulk update process.
	 *
	 * @since 3.0.0
	 */
	public function bulk_footer() {}

	/**
	 * Hides the `process_failed` error message when updating by uploading a zip file.
	 *
	 * @since 5.5.0
	 *
	 * @param WP_Error $wp_error WP_Error object.
	 * @return bool True if the error should be hidden, false otherwise.
	 */
	public function hide_process_failed( $wp_error ) {
		return false;
	}
}
class-bulk-upgrader-skin.php000064400000015141151212616050012067 0ustar00<?php
/**
 * Upgrader API: Bulk_Upgrader_Skin class
 *
 * @package WordPress
 * @subpackage Upgrader
 * @since 4.6.0
 */

/**
 * Generic Bulk Upgrader Skin for WordPress Upgrades.
 *
 * @since 3.0.0
 * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader-skins.php.
 *
 * @see WP_Upgrader_Skin
 */
class Bulk_Upgrader_Skin extends WP_Upgrader_Skin {

	/**
	 * Whether the bulk update process has started.
	 *
	 * @since 3.0.0
	 * @var bool
	 */
	public $in_loop = false;

	/**
	 * Stores an error message about the update.
	 *
	 * @since 3.0.0
	 * @var string|false
	 */
	public $error = false;

	/**
	 * Constructor.
	 *
	 * Sets up the generic skin for the Bulk Upgrader classes.
	 *
	 * @since 3.0.0
	 *
	 * @param array $args
	 */
	public function __construct( $args = array() ) {
		$defaults = array(
			'url'   => '',
			'nonce' => '',
		);
		$args     = wp_parse_args( $args, $defaults );

		parent::__construct( $args );
	}

	/**
	 * Sets up the strings used in the update process.
	 *
	 * @since 3.0.0
	 */
	public function add_strings() {
		$this->upgrader->strings['skin_upgrade_start'] = __( 'The update process is starting. This process may take a while on some hosts, so please be patient.' );
		/* translators: 1: Title of an update, 2: Error message. */
		$this->upgrader->strings['skin_update_failed_error'] = __( 'An error occurred while updating %1$s: %2$s' );
		/* translators: %s: Title of an update. */
		$this->upgrader->strings['skin_update_failed'] = __( 'The update of %s failed.' );
		/* translators: %s: Title of an update. */
		$this->upgrader->strings['skin_update_successful'] = __( '%s updated successfully.' );
		$this->upgrader->strings['skin_upgrade_end']       = __( 'All updates have been completed.' );
	}

	/**
	 * Displays a message about the update.
	 *
	 * @since 3.0.0
	 * @since 5.9.0 Renamed `$string` (a PHP reserved keyword) to `$feedback` for PHP 8 named parameter support.
	 *
	 * @param string $feedback Message data.
	 * @param mixed  ...$args  Optional text replacements.
	 */
	public function feedback( $feedback, ...$args ) {
		if ( isset( $this->upgrader->strings[ $feedback ] ) ) {
			$feedback = $this->upgrader->strings[ $feedback ];
		}

		if ( str_contains( $feedback, '%' ) ) {
			if ( $args ) {
				$args     = array_map( 'strip_tags', $args );
				$args     = array_map( 'esc_html', $args );
				$feedback = vsprintf( $feedback, $args );
			}
		}
		if ( empty( $feedback ) ) {
			return;
		}
		if ( $this->in_loop ) {
			echo "$feedback<br />\n";
		} else {
			echo "<p>$feedback</p>\n";
		}
	}

	/**
	 * Displays the header before the update process.
	 *
	 * @since 3.0.0
	 */
	public function header() {
		// Nothing. This will be displayed within an iframe.
	}

	/**
	 * Displays the footer following the update process.
	 *
	 * @since 3.0.0
	 */
	public function footer() {
		// Nothing. This will be displayed within an iframe.
	}

	/**
	 * Displays an error message about the update.
	 *
	 * @since 3.0.0
	 * @since 5.9.0 Renamed `$error` to `$errors` for PHP 8 named parameter support.
	 *
	 * @param string|WP_Error $errors Errors.
	 */
	public function error( $errors ) {
		if ( is_string( $errors ) && isset( $this->upgrader->strings[ $errors ] ) ) {
			$this->error = $this->upgrader->strings[ $errors ];
		}

		if ( is_wp_error( $errors ) ) {
			$messages = array();
			foreach ( $errors->get_error_messages() as $emessage ) {
				if ( $errors->get_error_data() && is_string( $errors->get_error_data() ) ) {
					$messages[] = $emessage . ' ' . esc_html( strip_tags( $errors->get_error_data() ) );
				} else {
					$messages[] = $emessage;
				}
			}
			$this->error = implode( ', ', $messages );
		}
		echo '<script type="text/javascript">jQuery(\'.waiting-' . esc_js( $this->upgrader->update_current ) . '\').hide();</script>';
	}

	/**
	 * Displays the header before the bulk update process.
	 *
	 * @since 3.0.0
	 */
	public function bulk_header() {
		$this->feedback( 'skin_upgrade_start' );
	}

	/**
	 * Displays the footer following the bulk update process.
	 *
	 * @since 3.0.0
	 */
	public function bulk_footer() {
		$this->feedback( 'skin_upgrade_end' );
	}

	/**
	 * Performs an action before a bulk update.
	 *
	 * @since 3.0.0
	 *
	 * @param string $title
	 */
	public function before( $title = '' ) {
		$this->in_loop = true;
		printf( '<h2>' . $this->upgrader->strings['skin_before_update_header'] . ' <span class="spinner waiting-' . $this->upgrader->update_current . '"></span></h2>', $title, $this->upgrader->update_current, $this->upgrader->update_count );
		echo '<script type="text/javascript">jQuery(\'.waiting-' . esc_js( $this->upgrader->update_current ) . '\').css("display", "inline-block");</script>';
		// This progress messages div gets moved via JavaScript when clicking on "More details.".
		echo '<div class="update-messages hide-if-js" id="progress-' . esc_attr( $this->upgrader->update_current ) . '"><p>';
		$this->flush_output();
	}

	/**
	 * Performs an action following a bulk update.
	 *
	 * @since 3.0.0
	 *
	 * @param string $title
	 */
	public function after( $title = '' ) {
		echo '</p></div>';
		if ( $this->error || ! $this->result ) {
			if ( $this->error ) {
				$after_error_message = sprintf( $this->upgrader->strings['skin_update_failed_error'], $title, '<strong>' . $this->error . '</strong>' );
			} else {
				$after_error_message = sprintf( $this->upgrader->strings['skin_update_failed'], $title );
			}
			wp_admin_notice(
				$after_error_message,
				array(
					'additional_classes' => array( 'error' ),
				)
			);

			echo '<script type="text/javascript">jQuery(\'#progress-' . esc_js( $this->upgrader->update_current ) . '\').show();</script>';
		}
		if ( $this->result && ! is_wp_error( $this->result ) ) {
			if ( ! $this->error ) {
				echo '<div class="updated js-update-details" data-update-details="progress-' . esc_attr( $this->upgrader->update_current ) . '">' .
					'<p>' . sprintf( $this->upgrader->strings['skin_update_successful'], $title ) .
					' <button type="button" class="hide-if-no-js button-link js-update-details-toggle" aria-expanded="false">' . __( 'More details.' ) . '<span class="dashicons dashicons-arrow-down" aria-hidden="true"></span></button>' .
					'</p></div>';
			}

			echo '<script type="text/javascript">jQuery(\'.waiting-' . esc_js( $this->upgrader->update_current ) . '\').hide();</script>';
		}

		$this->reset();
		$this->flush_output();
	}

	/**
	 * Resets the properties used in the update process.
	 *
	 * @since 3.0.0
	 */
	public function reset() {
		$this->in_loop = false;
		$this->error   = false;
	}

	/**
	 * Flushes all output buffers.
	 *
	 * @since 3.0.0
	 */
	public function flush_output() {
		wp_ob_end_flush_all();
		flush();
	}
}
bookmark.php000064400000026715151212616050007074 0ustar00<?php
/**
 * WordPress Bookmark Administration API
 *
 * @package WordPress
 * @subpackage Administration
 */

/**
 * Adds a link using values provided in $_POST.
 *
 * @since 2.0.0
 *
 * @return int|WP_Error Value 0 or WP_Error on failure. The link ID on success.
 */
function add_link() {
	return edit_link();
}

/**
 * Updates or inserts a link using values provided in $_POST.
 *
 * @since 2.0.0
 *
 * @param int $link_id Optional. ID of the link to edit. Default 0.
 * @return int|WP_Error Value 0 or WP_Error on failure. The link ID on success.
 */
function edit_link( $link_id = 0 ) {
	if ( ! current_user_can( 'manage_links' ) ) {
		wp_die(
			'<h1>' . __( 'You need a higher level of permission.' ) . '</h1>' .
			'<p>' . __( 'Sorry, you are not allowed to edit the links for this site.' ) . '</p>',
			403
		);
	}

	$_POST['link_url']   = esc_url( $_POST['link_url'] );
	$_POST['link_name']  = esc_html( $_POST['link_name'] );
	$_POST['link_image'] = esc_html( $_POST['link_image'] );
	$_POST['link_rss']   = esc_url( $_POST['link_rss'] );
	if ( ! isset( $_POST['link_visible'] ) || 'N' !== $_POST['link_visible'] ) {
		$_POST['link_visible'] = 'Y';
	}

	if ( ! empty( $link_id ) ) {
		$_POST['link_id'] = $link_id;
		return wp_update_link( $_POST );
	} else {
		return wp_insert_link( $_POST );
	}
}

/**
 * Retrieves the default link for editing.
 *
 * @since 2.0.0
 *
 * @return stdClass Default link object.
 */
function get_default_link_to_edit() {
	$link = new stdClass();
	if ( isset( $_GET['linkurl'] ) ) {
		$link->link_url = esc_url( wp_unslash( $_GET['linkurl'] ) );
	} else {
		$link->link_url = '';
	}

	if ( isset( $_GET['name'] ) ) {
		$link->link_name = esc_attr( wp_unslash( $_GET['name'] ) );
	} else {
		$link->link_name = '';
	}

	$link->link_visible = 'Y';

	return $link;
}

/**
 * Deletes a specified link from the database.
 *
 * @since 2.0.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int $link_id ID of the link to delete.
 * @return true Always true.
 */
function wp_delete_link( $link_id ) {
	global $wpdb;
	/**
	 * Fires before a link is deleted.
	 *
	 * @since 2.0.0
	 *
	 * @param int $link_id ID of the link to delete.
	 */
	do_action( 'delete_link', $link_id );

	wp_delete_object_term_relationships( $link_id, 'link_category' );

	$wpdb->delete( $wpdb->links, array( 'link_id' => $link_id ) );

	/**
	 * Fires after a link has been deleted.
	 *
	 * @since 2.2.0
	 *
	 * @param int $link_id ID of the deleted link.
	 */
	do_action( 'deleted_link', $link_id );

	clean_bookmark_cache( $link_id );

	return true;
}

/**
 * Retrieves the link category IDs associated with the link specified.
 *
 * @since 2.1.0
 *
 * @param int $link_id Link ID to look up.
 * @return int[] The IDs of the requested link's categories.
 */
function wp_get_link_cats( $link_id = 0 ) {
	$cats = wp_get_object_terms( $link_id, 'link_category', array( 'fields' => 'ids' ) );
	return array_unique( $cats );
}

/**
 * Retrieves link data based on its ID.
 *
 * @since 2.0.0
 *
 * @param int|stdClass $link Link ID or object to retrieve.
 * @return object Link object for editing.
 */
function get_link_to_edit( $link ) {
	return get_bookmark( $link, OBJECT, 'edit' );
}

/**
 * Inserts a link into the database, or updates an existing link.
 *
 * Runs all the necessary sanitizing, provides default values if arguments are missing,
 * and finally saves the link.
 *
 * @since 2.0.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param array $linkdata {
 *     Elements that make up the link to insert.
 *
 *     @type int    $link_id          Optional. The ID of the existing link if updating.
 *     @type string $link_url         The URL the link points to.
 *     @type string $link_name        The title of the link.
 *     @type string $link_image       Optional. A URL of an image.
 *     @type string $link_target      Optional. The target element for the anchor tag.
 *     @type string $link_description Optional. A short description of the link.
 *     @type string $link_visible     Optional. 'Y' means visible, anything else means not.
 *     @type int    $link_owner       Optional. A user ID.
 *     @type int    $link_rating      Optional. A rating for the link.
 *     @type string $link_rel         Optional. A relationship of the link to you.
 *     @type string $link_notes       Optional. An extended description of or notes on the link.
 *     @type string $link_rss         Optional. A URL of an associated RSS feed.
 *     @type int    $link_category    Optional. The term ID of the link category.
 *                                    If empty, uses default link category.
 * }
 * @param bool  $wp_error Optional. Whether to return a WP_Error object on failure. Default false.
 * @return int|WP_Error Value 0 or WP_Error on failure. The link ID on success.
 */
function wp_insert_link( $linkdata, $wp_error = false ) {
	global $wpdb;

	$defaults = array(
		'link_id'     => 0,
		'link_name'   => '',
		'link_url'    => '',
		'link_rating' => 0,
	);

	$parsed_args = wp_parse_args( $linkdata, $defaults );
	$parsed_args = wp_unslash( sanitize_bookmark( $parsed_args, 'db' ) );

	$link_id   = $parsed_args['link_id'];
	$link_name = $parsed_args['link_name'];
	$link_url  = $parsed_args['link_url'];

	$update = false;
	if ( ! empty( $link_id ) ) {
		$update = true;
	}

	if ( '' === trim( $link_name ) ) {
		if ( '' !== trim( $link_url ) ) {
			$link_name = $link_url;
		} else {
			return 0;
		}
	}

	if ( '' === trim( $link_url ) ) {
		return 0;
	}

	$link_rating      = ( ! empty( $parsed_args['link_rating'] ) ) ? $parsed_args['link_rating'] : 0;
	$link_image       = ( ! empty( $parsed_args['link_image'] ) ) ? $parsed_args['link_image'] : '';
	$link_target      = ( ! empty( $parsed_args['link_target'] ) ) ? $parsed_args['link_target'] : '';
	$link_visible     = ( ! empty( $parsed_args['link_visible'] ) ) ? $parsed_args['link_visible'] : 'Y';
	$link_owner       = ( ! empty( $parsed_args['link_owner'] ) ) ? $parsed_args['link_owner'] : get_current_user_id();
	$link_notes       = ( ! empty( $parsed_args['link_notes'] ) ) ? $parsed_args['link_notes'] : '';
	$link_description = ( ! empty( $parsed_args['link_description'] ) ) ? $parsed_args['link_description'] : '';
	$link_rss         = ( ! empty( $parsed_args['link_rss'] ) ) ? $parsed_args['link_rss'] : '';
	$link_rel         = ( ! empty( $parsed_args['link_rel'] ) ) ? $parsed_args['link_rel'] : '';
	$link_category    = ( ! empty( $parsed_args['link_category'] ) ) ? $parsed_args['link_category'] : array();
	$link_updated     = gmdate( 'Y-m-d H:i:s', current_time( 'timestamp', 0 ) );

	// Make sure we set a valid category.
	if ( ! is_array( $link_category ) || 0 === count( $link_category ) ) {
		$link_category = array( get_option( 'default_link_category' ) );
	}

	if ( $update ) {
		if ( false === $wpdb->update( $wpdb->links, compact( 'link_url', 'link_name', 'link_image', 'link_target', 'link_description', 'link_visible', 'link_owner', 'link_rating', 'link_rel', 'link_notes', 'link_rss', 'link_updated' ), compact( 'link_id' ) ) ) {
			if ( $wp_error ) {
				return new WP_Error( 'db_update_error', __( 'Could not update link in the database.' ), $wpdb->last_error );
			} else {
				return 0;
			}
		}
	} else {
		if ( false === $wpdb->insert( $wpdb->links, compact( 'link_url', 'link_name', 'link_image', 'link_target', 'link_description', 'link_visible', 'link_owner', 'link_rating', 'link_rel', 'link_notes', 'link_rss', 'link_updated' ) ) ) {
			if ( $wp_error ) {
				return new WP_Error( 'db_insert_error', __( 'Could not insert link into the database.' ), $wpdb->last_error );
			} else {
				return 0;
			}
		}
		$link_id = (int) $wpdb->insert_id;
	}

	wp_set_link_cats( $link_id, $link_category );

	if ( $update ) {
		/**
		 * Fires after a link was updated in the database.
		 *
		 * @since 2.0.0
		 *
		 * @param int $link_id ID of the link that was updated.
		 */
		do_action( 'edit_link', $link_id );
	} else {
		/**
		 * Fires after a link was added to the database.
		 *
		 * @since 2.0.0
		 *
		 * @param int $link_id ID of the link that was added.
		 */
		do_action( 'add_link', $link_id );
	}
	clean_bookmark_cache( $link_id );

	return $link_id;
}

/**
 * Updates link with the specified link categories.
 *
 * @since 2.1.0
 *
 * @param int   $link_id         ID of the link to update.
 * @param int[] $link_categories Array of link category IDs to add the link to.
 */
function wp_set_link_cats( $link_id = 0, $link_categories = array() ) {
	// If $link_categories isn't already an array, make it one:
	if ( ! is_array( $link_categories ) || 0 === count( $link_categories ) ) {
		$link_categories = array( get_option( 'default_link_category' ) );
	}

	$link_categories = array_map( 'intval', $link_categories );
	$link_categories = array_unique( $link_categories );

	wp_set_object_terms( $link_id, $link_categories, 'link_category' );

	clean_bookmark_cache( $link_id );
}

/**
 * Updates a link in the database.
 *
 * @since 2.0.0
 *
 * @param array $linkdata Link data to update. See wp_insert_link() for accepted arguments.
 * @return int|WP_Error Value 0 or WP_Error on failure. The updated link ID on success.
 */
function wp_update_link( $linkdata ) {
	$link_id = (int) $linkdata['link_id'];

	$link = get_bookmark( $link_id, ARRAY_A );

	// Escape data pulled from DB.
	$link = wp_slash( $link );

	// Passed link category list overwrites existing category list if not empty.
	if ( isset( $linkdata['link_category'] ) && is_array( $linkdata['link_category'] )
		&& count( $linkdata['link_category'] ) > 0
	) {
		$link_cats = $linkdata['link_category'];
	} else {
		$link_cats = $link['link_category'];
	}

	// Merge old and new fields with new fields overwriting old ones.
	$linkdata                  = array_merge( $link, $linkdata );
	$linkdata['link_category'] = $link_cats;

	return wp_insert_link( $linkdata );
}

/**
 * Outputs the 'disabled' message for the WordPress Link Manager.
 *
 * @since 3.5.0
 * @access private
 *
 * @global string $pagenow The filename of the current screen.
 */
function wp_link_manager_disabled_message() {
	global $pagenow;

	if ( ! in_array( $pagenow, array( 'link-manager.php', 'link-add.php', 'link.php' ), true ) ) {
		return;
	}

	add_filter( 'pre_option_link_manager_enabled', '__return_true', 100 );
	$really_can_manage_links = current_user_can( 'manage_links' );
	remove_filter( 'pre_option_link_manager_enabled', '__return_true', 100 );

	if ( $really_can_manage_links ) {
		$plugins = get_plugins();

		if ( empty( $plugins['link-manager/link-manager.php'] ) ) {
			if ( current_user_can( 'install_plugins' ) ) {
				$install_url = wp_nonce_url(
					self_admin_url( 'update.php?action=install-plugin&plugin=link-manager' ),
					'install-plugin_link-manager'
				);

				wp_die(
					sprintf(
						/* translators: %s: A link to install the Link Manager plugin. */
						__( 'If you are looking to use the link manager, please install the <a href="%s">Link Manager plugin</a>.' ),
						esc_url( $install_url )
					)
				);
			}
		} elseif ( is_plugin_inactive( 'link-manager/link-manager.php' ) ) {
			if ( current_user_can( 'activate_plugins' ) ) {
				$activate_url = wp_nonce_url(
					self_admin_url( 'plugins.php?action=activate&plugin=link-manager/link-manager.php' ),
					'activate-plugin_link-manager/link-manager.php'
				);

				wp_die(
					sprintf(
						/* translators: %s: A link to activate the Link Manager plugin. */
						__( 'Please activate the <a href="%s">Link Manager plugin</a> to use the link manager.' ),
						esc_url( $activate_url )
					)
				);
			}
		}
	}

	wp_die( __( 'Sorry, you are not allowed to edit the links for this site.' ) );
}
class-wp-filesystem-ssh2.php000064400000055416151212616050012057 0ustar00<?php
/**
 * WordPress Filesystem Class for implementing SSH2
 *
 * To use this class you must follow these steps for PHP 5.2.6+
 *
 * {@link http://kevin.vanzonneveld.net/techblog/article/make_ssh_connections_with_php/ - Installation Notes}
 *
 * Compile libssh2 (Note: Only 0.14 is officially working with PHP 5.2.6+ right now, But many users have found the latest versions work)
 *
 * cd /usr/src
 * wget https://www.libssh2.org/download/libssh2-0.14.tar.gz
 * tar -zxvf libssh2-0.14.tar.gz
 * cd libssh2-0.14/
 * ./configure
 * make all install
 *
 * Note: Do not leave the directory yet!
 *
 * Enter: pecl install -f ssh2
 *
 * Copy the ssh.so file it creates to your PHP Module Directory.
 * Open up your PHP.INI file and look for where extensions are placed.
 * Add in your PHP.ini file: extension=ssh2.so
 *
 * Restart Apache!
 * Check phpinfo() streams to confirm that: ssh2.shell, ssh2.exec, ssh2.tunnel, ssh2.scp, ssh2.sftp  exist.
 *
 * Note: As of WordPress 2.8, this utilizes the PHP5+ function `stream_get_contents()`.
 *
 * @since 2.7.0
 *
 * @package WordPress
 * @subpackage Filesystem
 */
class WP_Filesystem_SSH2 extends WP_Filesystem_Base {

	/**
	 * @since 2.7.0
	 * @var resource
	 */
	public $link = false;

	/**
	 * @since 2.7.0
	 * @var resource
	 */
	public $sftp_link;

	/**
	 * @since 2.7.0
	 * @var bool
	 */
	public $keys = false;

	/**
	 * Constructor.
	 *
	 * @since 2.7.0
	 *
	 * @param array $opt
	 */
	public function __construct( $opt = '' ) {
		$this->method = 'ssh2';
		$this->errors = new WP_Error();

		// Check if possible to use ssh2 functions.
		if ( ! extension_loaded( 'ssh2' ) ) {
			$this->errors->add( 'no_ssh2_ext', __( 'The ssh2 PHP extension is not available' ) );
			return;
		}

		// Set defaults:
		if ( empty( $opt['port'] ) ) {
			$this->options['port'] = 22;
		} else {
			$this->options['port'] = $opt['port'];
		}

		if ( empty( $opt['hostname'] ) ) {
			$this->errors->add( 'empty_hostname', __( 'SSH2 hostname is required' ) );
		} else {
			$this->options['hostname'] = $opt['hostname'];
		}

		// Check if the options provided are OK.
		if ( ! empty( $opt['public_key'] ) && ! empty( $opt['private_key'] ) ) {
			$this->options['public_key']  = $opt['public_key'];
			$this->options['private_key'] = $opt['private_key'];

			$this->options['hostkey'] = array( 'hostkey' => 'ssh-rsa,ssh-ed25519' );

			$this->keys = true;
		} elseif ( empty( $opt['username'] ) ) {
			$this->errors->add( 'empty_username', __( 'SSH2 username is required' ) );
		}

		if ( ! empty( $opt['username'] ) ) {
			$this->options['username'] = $opt['username'];
		}

		if ( empty( $opt['password'] ) ) {
			// Password can be blank if we are using keys.
			if ( ! $this->keys ) {
				$this->errors->add( 'empty_password', __( 'SSH2 password is required' ) );
			} else {
				$this->options['password'] = null;
			}
		} else {
			$this->options['password'] = $opt['password'];
		}
	}

	/**
	 * Connects filesystem.
	 *
	 * @since 2.7.0
	 *
	 * @return bool True on success, false on failure.
	 */
	public function connect() {
		if ( ! $this->keys ) {
			$this->link = @ssh2_connect( $this->options['hostname'], $this->options['port'] );
		} else {
			$this->link = @ssh2_connect( $this->options['hostname'], $this->options['port'], $this->options['hostkey'] );
		}

		if ( ! $this->link ) {
			$this->errors->add(
				'connect',
				sprintf(
					/* translators: %s: hostname:port */
					__( 'Failed to connect to SSH2 Server %s' ),
					$this->options['hostname'] . ':' . $this->options['port']
				)
			);

			return false;
		}

		if ( ! $this->keys ) {
			if ( ! @ssh2_auth_password( $this->link, $this->options['username'], $this->options['password'] ) ) {
				$this->errors->add(
					'auth',
					sprintf(
						/* translators: %s: Username. */
						__( 'Username/Password incorrect for %s' ),
						$this->options['username']
					)
				);

				return false;
			}
		} else {
			if ( ! @ssh2_auth_pubkey_file( $this->link, $this->options['username'], $this->options['public_key'], $this->options['private_key'], $this->options['password'] ) ) {
				$this->errors->add(
					'auth',
					sprintf(
						/* translators: %s: Username. */
						__( 'Public and Private keys incorrect for %s' ),
						$this->options['username']
					)
				);

				return false;
			}
		}

		$this->sftp_link = ssh2_sftp( $this->link );

		if ( ! $this->sftp_link ) {
			$this->errors->add(
				'connect',
				sprintf(
					/* translators: %s: hostname:port */
					__( 'Failed to initialize a SFTP subsystem session with the SSH2 Server %s' ),
					$this->options['hostname'] . ':' . $this->options['port']
				)
			);

			return false;
		}

		return true;
	}

	/**
	 * Gets the ssh2.sftp PHP stream wrapper path to open for the given file.
	 *
	 * This method also works around a PHP bug where the root directory (/) cannot
	 * be opened by PHP functions, causing a false failure. In order to work around
	 * this, the path is converted to /./ which is semantically the same as /
	 * See https://bugs.php.net/bug.php?id=64169 for more details.
	 *
	 * @since 4.4.0
	 *
	 * @param string $path The File/Directory path on the remote server to return
	 * @return string The ssh2.sftp:// wrapped path to use.
	 */
	public function sftp_path( $path ) {
		if ( '/' === $path ) {
			$path = '/./';
		}

		return 'ssh2.sftp://' . $this->sftp_link . '/' . ltrim( $path, '/' );
	}

	/**
	 * @since 2.7.0
	 *
	 * @param string $command
	 * @param bool   $returnbool
	 * @return bool|string True on success, false on failure. String if the command was executed, `$returnbool`
	 *                     is false (default), and data from the resulting stream was retrieved.
	 */
	public function run_command( $command, $returnbool = false ) {
		if ( ! $this->link ) {
			return false;
		}

		$stream = ssh2_exec( $this->link, $command );

		if ( ! $stream ) {
			$this->errors->add(
				'command',
				sprintf(
					/* translators: %s: Command. */
					__( 'Unable to perform command: %s' ),
					$command
				)
			);
		} else {
			stream_set_blocking( $stream, true );
			stream_set_timeout( $stream, FS_TIMEOUT );
			$data = stream_get_contents( $stream );
			fclose( $stream );

			if ( $returnbool ) {
				return ( false === $data ) ? false : '' !== trim( $data );
			} else {
				return $data;
			}
		}

		return false;
	}

	/**
	 * Reads entire file into a string.
	 *
	 * @since 2.7.0
	 *
	 * @param string $file Name of the file to read.
	 * @return string|false Read data on success, false if no temporary file could be opened,
	 *                      or if the file couldn't be retrieved.
	 */
	public function get_contents( $file ) {
		return file_get_contents( $this->sftp_path( $file ) );
	}

	/**
	 * Reads entire file into an array.
	 *
	 * @since 2.7.0
	 *
	 * @param string $file Path to the file.
	 * @return array|false File contents in an array on success, false on failure.
	 */
	public function get_contents_array( $file ) {
		return file( $this->sftp_path( $file ) );
	}

	/**
	 * Writes a string to a file.
	 *
	 * @since 2.7.0
	 *
	 * @param string    $file     Remote path to the file where to write the data.
	 * @param string    $contents The data to write.
	 * @param int|false $mode     Optional. The file permissions as octal number, usually 0644.
	 *                            Default false.
	 * @return bool True on success, false on failure.
	 */
	public function put_contents( $file, $contents, $mode = false ) {
		$ret = file_put_contents( $this->sftp_path( $file ), $contents );

		if ( strlen( $contents ) !== $ret ) {
			return false;
		}

		$this->chmod( $file, $mode );

		return true;
	}

	/**
	 * Gets the current working directory.
	 *
	 * @since 2.7.0
	 *
	 * @return string|false The current working directory on success, false on failure.
	 */
	public function cwd() {
		$cwd = ssh2_sftp_realpath( $this->sftp_link, '.' );

		if ( $cwd ) {
			$cwd = trailingslashit( trim( $cwd ) );
		}

		return $cwd;
	}

	/**
	 * Changes current directory.
	 *
	 * @since 2.7.0
	 *
	 * @param string $dir The new current directory.
	 * @return bool True on success, false on failure.
	 */
	public function chdir( $dir ) {
		return $this->run_command( 'cd ' . $dir, true );
	}

	/**
	 * Changes the file group.
	 *
	 * @since 2.7.0
	 *
	 * @param string     $file      Path to the file.
	 * @param string|int $group     A group name or number.
	 * @param bool       $recursive Optional. If set to true, changes file group recursively.
	 *                              Default false.
	 * @return bool True on success, false on failure.
	 */
	public function chgrp( $file, $group, $recursive = false ) {
		if ( ! $this->exists( $file ) ) {
			return false;
		}

		if ( ! $recursive || ! $this->is_dir( $file ) ) {
			return $this->run_command( sprintf( 'chgrp %s %s', escapeshellarg( $group ), escapeshellarg( $file ) ), true );
		}

		return $this->run_command( sprintf( 'chgrp -R %s %s', escapeshellarg( $group ), escapeshellarg( $file ) ), true );
	}

	/**
	 * Changes filesystem permissions.
	 *
	 * @since 2.7.0
	 *
	 * @param string    $file      Path to the file.
	 * @param int|false $mode      Optional. The permissions as octal number, usually 0644 for files,
	 *                             0755 for directories. Default false.
	 * @param bool      $recursive Optional. If set to true, changes file permissions recursively.
	 *                             Default false.
	 * @return bool True on success, false on failure.
	 */
	public function chmod( $file, $mode = false, $recursive = false ) {
		if ( ! $this->exists( $file ) ) {
			return false;
		}

		if ( ! $mode ) {
			if ( $this->is_file( $file ) ) {
				$mode = FS_CHMOD_FILE;
			} elseif ( $this->is_dir( $file ) ) {
				$mode = FS_CHMOD_DIR;
			} else {
				return false;
			}
		}

		if ( ! $recursive || ! $this->is_dir( $file ) ) {
			return $this->run_command( sprintf( 'chmod %o %s', $mode, escapeshellarg( $file ) ), true );
		}

		return $this->run_command( sprintf( 'chmod -R %o %s', $mode, escapeshellarg( $file ) ), true );
	}

	/**
	 * Changes the owner of a file or directory.
	 *
	 * @since 2.7.0
	 *
	 * @param string     $file      Path to the file or directory.
	 * @param string|int $owner     A user name or number.
	 * @param bool       $recursive Optional. If set to true, changes file owner recursively.
	 *                              Default false.
	 * @return bool True on success, false on failure.
	 */
	public function chown( $file, $owner, $recursive = false ) {
		if ( ! $this->exists( $file ) ) {
			return false;
		}

		if ( ! $recursive || ! $this->is_dir( $file ) ) {
			return $this->run_command( sprintf( 'chown %s %s', escapeshellarg( $owner ), escapeshellarg( $file ) ), true );
		}

		return $this->run_command( sprintf( 'chown -R %s %s', escapeshellarg( $owner ), escapeshellarg( $file ) ), true );
	}

	/**
	 * Gets the file owner.
	 *
	 * @since 2.7.0
	 *
	 * @param string $file Path to the file.
	 * @return string|false Username of the owner on success, false on failure.
	 */
	public function owner( $file ) {
		$owneruid = @fileowner( $this->sftp_path( $file ) );

		if ( ! $owneruid ) {
			return false;
		}

		if ( ! function_exists( 'posix_getpwuid' ) ) {
			return $owneruid;
		}

		$ownerarray = posix_getpwuid( $owneruid );

		if ( ! $ownerarray ) {
			return false;
		}

		return $ownerarray['name'];
	}

	/**
	 * Gets the permissions of the specified file or filepath in their octal format.
	 *
	 * @since 2.7.0
	 *
	 * @param string $file Path to the file.
	 * @return string Mode of the file (the last 3 digits).
	 */
	public function getchmod( $file ) {
		return substr( decoct( @fileperms( $this->sftp_path( $file ) ) ), -3 );
	}

	/**
	 * Gets the file's group.
	 *
	 * @since 2.7.0
	 *
	 * @param string $file Path to the file.
	 * @return string|false The group on success, false on failure.
	 */
	public function group( $file ) {
		$gid = @filegroup( $this->sftp_path( $file ) );

		if ( ! $gid ) {
			return false;
		}

		if ( ! function_exists( 'posix_getgrgid' ) ) {
			return $gid;
		}

		$grouparray = posix_getgrgid( $gid );

		if ( ! $grouparray ) {
			return false;
		}

		return $grouparray['name'];
	}

	/**
	 * Copies a file.
	 *
	 * @since 2.7.0
	 *
	 * @param string    $source      Path to the source file.
	 * @param string    $destination Path to the destination file.
	 * @param bool      $overwrite   Optional. Whether to overwrite the destination file if it exists.
	 *                               Default false.
	 * @param int|false $mode        Optional. The permissions as octal number, usually 0644 for files,
	 *                               0755 for dirs. Default false.
	 * @return bool True on success, false on failure.
	 */
	public function copy( $source, $destination, $overwrite = false, $mode = false ) {
		if ( ! $overwrite && $this->exists( $destination ) ) {
			return false;
		}

		$content = $this->get_contents( $source );

		if ( false === $content ) {
			return false;
		}

		return $this->put_contents( $destination, $content, $mode );
	}

	/**
	 * Moves a file or directory.
	 *
	 * After moving files or directories, OPcache will need to be invalidated.
	 *
	 * If moving a directory fails, `copy_dir()` can be used for a recursive copy.
	 *
	 * Use `move_dir()` for moving directories with OPcache invalidation and a
	 * fallback to `copy_dir()`.
	 *
	 * @since 2.7.0
	 *
	 * @param string $source      Path to the source file or directory.
	 * @param string $destination Path to the destination file or directory.
	 * @param bool   $overwrite   Optional. Whether to overwrite the destination if it exists.
	 *                            Default false.
	 * @return bool True on success, false on failure.
	 */
	public function move( $source, $destination, $overwrite = false ) {
		if ( $this->exists( $destination ) ) {
			if ( $overwrite ) {
				// We need to remove the destination before we can rename the source.
				$this->delete( $destination, false, 'f' );
			} else {
				// If we're not overwriting, the rename will fail, so return early.
				return false;
			}
		}

		return ssh2_sftp_rename( $this->sftp_link, $source, $destination );
	}

	/**
	 * Deletes a file or directory.
	 *
	 * @since 2.7.0
	 *
	 * @param string       $file      Path to the file or directory.
	 * @param bool         $recursive Optional. If set to true, deletes files and folders recursively.
	 *                                Default false.
	 * @param string|false $type      Type of resource. 'f' for file, 'd' for directory.
	 *                                Default false.
	 * @return bool True on success, false on failure.
	 */
	public function delete( $file, $recursive = false, $type = false ) {
		if ( 'f' === $type || $this->is_file( $file ) ) {
			return ssh2_sftp_unlink( $this->sftp_link, $file );
		}

		if ( ! $recursive ) {
			return ssh2_sftp_rmdir( $this->sftp_link, $file );
		}

		$filelist = $this->dirlist( $file );

		if ( is_array( $filelist ) ) {
			foreach ( $filelist as $filename => $fileinfo ) {
				$this->delete( $file . '/' . $filename, $recursive, $fileinfo['type'] );
			}
		}

		return ssh2_sftp_rmdir( $this->sftp_link, $file );
	}

	/**
	 * Checks if a file or directory exists.
	 *
	 * @since 2.7.0
	 *
	 * @param string $path Path to file or directory.
	 * @return bool Whether $path exists or not.
	 */
	public function exists( $path ) {
		return file_exists( $this->sftp_path( $path ) );
	}

	/**
	 * Checks if resource is a file.
	 *
	 * @since 2.7.0
	 *
	 * @param string $file File path.
	 * @return bool Whether $file is a file.
	 */
	public function is_file( $file ) {
		return is_file( $this->sftp_path( $file ) );
	}

	/**
	 * Checks if resource is a directory.
	 *
	 * @since 2.7.0
	 *
	 * @param string $path Directory path.
	 * @return bool Whether $path is a directory.
	 */
	public function is_dir( $path ) {
		return is_dir( $this->sftp_path( $path ) );
	}

	/**
	 * Checks if a file is readable.
	 *
	 * @since 2.7.0
	 *
	 * @param string $file Path to file.
	 * @return bool Whether $file is readable.
	 */
	public function is_readable( $file ) {
		return is_readable( $this->sftp_path( $file ) );
	}

	/**
	 * Checks if a file or directory is writable.
	 *
	 * @since 2.7.0
	 *
	 * @param string $path Path to file or directory.
	 * @return bool Whether $path is writable.
	 */
	public function is_writable( $path ) {
		// PHP will base its writable checks on system_user === file_owner, not ssh_user === file_owner.
		return true;
	}

	/**
	 * Gets the file's last access time.
	 *
	 * @since 2.7.0
	 *
	 * @param string $file Path to file.
	 * @return int|false Unix timestamp representing last access time, false on failure.
	 */
	public function atime( $file ) {
		return fileatime( $this->sftp_path( $file ) );
	}

	/**
	 * Gets the file modification time.
	 *
	 * @since 2.7.0
	 *
	 * @param string $file Path to file.
	 * @return int|false Unix timestamp representing modification time, false on failure.
	 */
	public function mtime( $file ) {
		return filemtime( $this->sftp_path( $file ) );
	}

	/**
	 * Gets the file size (in bytes).
	 *
	 * @since 2.7.0
	 *
	 * @param string $file Path to file.
	 * @return int|false Size of the file in bytes on success, false on failure.
	 */
	public function size( $file ) {
		return filesize( $this->sftp_path( $file ) );
	}

	/**
	 * Sets the access and modification times of a file.
	 *
	 * Note: Not implemented.
	 *
	 * @since 2.7.0
	 *
	 * @param string $file  Path to file.
	 * @param int    $time  Optional. Modified time to set for file.
	 *                      Default 0.
	 * @param int    $atime Optional. Access time to set for file.
	 *                      Default 0.
	 */
	public function touch( $file, $time = 0, $atime = 0 ) {
		// Not implemented.
	}

	/**
	 * Creates a directory.
	 *
	 * @since 2.7.0
	 *
	 * @param string           $path  Path for new directory.
	 * @param int|false        $chmod Optional. The permissions as octal number (or false to skip chmod).
	 *                                Default false.
	 * @param string|int|false $chown Optional. A user name or number (or false to skip chown).
	 *                                Default false.
	 * @param string|int|false $chgrp Optional. A group name or number (or false to skip chgrp).
	 *                                Default false.
	 * @return bool True on success, false on failure.
	 */
	public function mkdir( $path, $chmod = false, $chown = false, $chgrp = false ) {
		$path = untrailingslashit( $path );

		if ( empty( $path ) ) {
			return false;
		}

		if ( ! $chmod ) {
			$chmod = FS_CHMOD_DIR;
		}

		if ( ! ssh2_sftp_mkdir( $this->sftp_link, $path, $chmod, true ) ) {
			return false;
		}

		// Set directory permissions.
		ssh2_sftp_chmod( $this->sftp_link, $path, $chmod );

		if ( $chown ) {
			$this->chown( $path, $chown );
		}

		if ( $chgrp ) {
			$this->chgrp( $path, $chgrp );
		}

		return true;
	}

	/**
	 * Deletes a directory.
	 *
	 * @since 2.7.0
	 *
	 * @param string $path      Path to directory.
	 * @param bool   $recursive Optional. Whether to recursively remove files/directories.
	 *                          Default false.
	 * @return bool True on success, false on failure.
	 */
	public function rmdir( $path, $recursive = false ) {
		return $this->delete( $path, $recursive );
	}

	/**
	 * Gets details for files in a directory or a specific file.
	 *
	 * @since 2.7.0
	 *
	 * @param string $path           Path to directory or file.
	 * @param bool   $include_hidden Optional. Whether to include details of hidden ("." prefixed) files.
	 *                               Default true.
	 * @param bool   $recursive      Optional. Whether to recursively include file details in nested directories.
	 *                               Default false.
	 * @return array|false {
	 *     Array of arrays containing file information. False if unable to list directory contents.
	 *
	 *     @type array ...$0 {
	 *         Array of file information. Note that some elements may not be available on all filesystems.
	 *
	 *         @type string           $name        Name of the file or directory.
	 *         @type string           $perms       *nix representation of permissions.
	 *         @type string           $permsn      Octal representation of permissions.
	 *         @type false            $number      File number. Always false in this context.
	 *         @type string|false     $owner       Owner name or ID, or false if not available.
	 *         @type string|false     $group       File permissions group, or false if not available.
	 *         @type int|string|false $size        Size of file in bytes. May be a numeric string.
	 *                                             False if not available.
	 *         @type int|string|false $lastmodunix Last modified unix timestamp. May be a numeric string.
	 *                                             False if not available.
	 *         @type string|false     $lastmod     Last modified month (3 letters) and day (without leading 0), or
	 *                                             false if not available.
	 *         @type string|false     $time        Last modified time, or false if not available.
	 *         @type string           $type        Type of resource. 'f' for file, 'd' for directory, 'l' for link.
	 *         @type array|false      $files       If a directory and `$recursive` is true, contains another array of
	 *                                             files. False if unable to list directory contents.
	 *     }
	 * }
	 */
	public function dirlist( $path, $include_hidden = true, $recursive = false ) {
		if ( $this->is_file( $path ) ) {
			$limit_file = basename( $path );
			$path       = dirname( $path );
		} else {
			$limit_file = false;
		}

		if ( ! $this->is_dir( $path ) || ! $this->is_readable( $path ) ) {
			return false;
		}

		$ret = array();
		$dir = dir( $this->sftp_path( $path ) );

		if ( ! $dir ) {
			return false;
		}

		$path = trailingslashit( $path );

		while ( false !== ( $entry = $dir->read() ) ) {
			$struc         = array();
			$struc['name'] = $entry;

			if ( '.' === $struc['name'] || '..' === $struc['name'] ) {
				continue; // Do not care about these folders.
			}

			if ( ! $include_hidden && '.' === $struc['name'][0] ) {
				continue;
			}

			if ( $limit_file && $struc['name'] !== $limit_file ) {
				continue;
			}

			$struc['perms']       = $this->gethchmod( $path . $entry );
			$struc['permsn']      = $this->getnumchmodfromh( $struc['perms'] );
			$struc['number']      = false;
			$struc['owner']       = $this->owner( $path . $entry );
			$struc['group']       = $this->group( $path . $entry );
			$struc['size']        = $this->size( $path . $entry );
			$struc['lastmodunix'] = $this->mtime( $path . $entry );
			$struc['lastmod']     = gmdate( 'M j', $struc['lastmodunix'] );
			$struc['time']        = gmdate( 'h:i:s', $struc['lastmodunix'] );
			$struc['type']        = $this->is_dir( $path . $entry ) ? 'd' : 'f';

			if ( 'd' === $struc['type'] ) {
				if ( $recursive ) {
					$struc['files'] = $this->dirlist( $path . $struc['name'], $include_hidden, $recursive );
				} else {
					$struc['files'] = array();
				}
			}

			$ret[ $struc['name'] ] = $struc;
		}

		$dir->close();
		unset( $dir );

		return $ret;
	}
}
media.php000064400000350474151212616050006350 0ustar00<?php
/**
 * WordPress Administration Media API.
 *
 * @package WordPress
 * @subpackage Administration
 */

/**
 * Defines the default media upload tabs.
 *
 * @since 2.5.0
 *
 * @return string[] Default tabs.
 */
function media_upload_tabs() {
	$_default_tabs = array(
		'type'     => __( 'From Computer' ), // Handler action suffix => tab text.
		'type_url' => __( 'From URL' ),
		'gallery'  => __( 'Gallery' ),
		'library'  => __( 'Media Library' ),
	);

	/**
	 * Filters the available tabs in the legacy (pre-3.5.0) media popup.
	 *
	 * @since 2.5.0
	 *
	 * @param string[] $_default_tabs An array of media tabs.
	 */
	return apply_filters( 'media_upload_tabs', $_default_tabs );
}

/**
 * Adds the gallery tab back to the tabs array if post has image attachments.
 *
 * @since 2.5.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param array $tabs
 * @return array $tabs with gallery if post has image attachment
 */
function update_gallery_tab( $tabs ) {
	global $wpdb;

	if ( ! isset( $_REQUEST['post_id'] ) ) {
		unset( $tabs['gallery'] );
		return $tabs;
	}

	$post_id = (int) $_REQUEST['post_id'];

	if ( $post_id ) {
		$attachments = (int) $wpdb->get_var( $wpdb->prepare( "SELECT count(*) FROM $wpdb->posts WHERE post_type = 'attachment' AND post_status != 'trash' AND post_parent = %d", $post_id ) );
	}

	if ( empty( $attachments ) ) {
		unset( $tabs['gallery'] );
		return $tabs;
	}

	/* translators: %s: Number of attachments. */
	$tabs['gallery'] = sprintf( __( 'Gallery (%s)' ), "<span id='attachments-count'>$attachments</span>" );

	return $tabs;
}

/**
 * Outputs the legacy media upload tabs UI.
 *
 * @since 2.5.0
 *
 * @global string $redir_tab
 */
function the_media_upload_tabs() {
	global $redir_tab;
	$tabs    = media_upload_tabs();
	$default = 'type';

	if ( ! empty( $tabs ) ) {
		echo "<ul id='sidemenu'>\n";

		if ( isset( $redir_tab ) && array_key_exists( $redir_tab, $tabs ) ) {
			$current = $redir_tab;
		} elseif ( isset( $_GET['tab'] ) && array_key_exists( $_GET['tab'], $tabs ) ) {
			$current = $_GET['tab'];
		} else {
			/** This filter is documented in wp-admin/media-upload.php */
			$current = apply_filters( 'media_upload_default_tab', $default );
		}

		foreach ( $tabs as $callback => $text ) {
			$class = '';

			if ( $current === $callback ) {
				$class = " class='current'";
			}

			$href = add_query_arg(
				array(
					'tab'            => $callback,
					's'              => false,
					'paged'          => false,
					'post_mime_type' => false,
					'm'              => false,
				)
			);
			$link = "<a href='" . esc_url( $href ) . "'$class>$text</a>";
			echo "\t<li id='" . esc_attr( "tab-$callback" ) . "'>$link</li>\n";
		}

		echo "</ul>\n";
	}
}

/**
 * Retrieves the image HTML to send to the editor.
 *
 * @since 2.5.0
 *
 * @param int          $id      Image attachment ID.
 * @param string       $caption Image caption.
 * @param string       $title   Image title attribute.
 * @param string       $align   Image CSS alignment property.
 * @param string       $url     Optional. Image src URL. Default empty.
 * @param bool|string  $rel     Optional. Value for rel attribute or whether to add a default value. Default false.
 * @param string|int[] $size    Optional. Image size. Accepts any registered image size name, or an array of
 *                              width and height values in pixels (in that order). Default 'medium'.
 * @param string       $alt     Optional. Image alt attribute. Default empty.
 * @return string The HTML output to insert into the editor.
 */
function get_image_send_to_editor( $id, $caption, $title, $align, $url = '', $rel = false, $size = 'medium', $alt = '' ) {

	$html = get_image_tag( $id, $alt, '', $align, $size );

	if ( $rel ) {
		if ( is_string( $rel ) ) {
			$rel = ' rel="' . esc_attr( $rel ) . '"';
		} else {
			$rel = ' rel="attachment wp-att-' . (int) $id . '"';
		}
	} else {
		$rel = '';
	}

	if ( $url ) {
		$html = '<a href="' . esc_url( $url ) . '"' . $rel . '>' . $html . '</a>';
	}

	/**
	 * Filters the image HTML markup to send to the editor when inserting an image.
	 *
	 * @since 2.5.0
	 * @since 5.6.0 The `$rel` parameter was added.
	 *
	 * @param string       $html    The image HTML markup to send.
	 * @param int          $id      The attachment ID.
	 * @param string       $caption The image caption.
	 * @param string       $title   The image title.
	 * @param string       $align   The image alignment.
	 * @param string       $url     The image source URL.
	 * @param string|int[] $size    Requested image size. Can be any registered image size name, or
	 *                              an array of width and height values in pixels (in that order).
	 * @param string       $alt     The image alternative, or alt, text.
	 * @param string       $rel     The image rel attribute.
	 */
	$html = apply_filters( 'image_send_to_editor', $html, $id, $caption, $title, $align, $url, $size, $alt, $rel );

	return $html;
}

/**
 * Adds image shortcode with caption to editor.
 *
 * @since 2.6.0
 *
 * @param string  $html    The image HTML markup to send.
 * @param int     $id      Image attachment ID.
 * @param string  $caption Image caption.
 * @param string  $title   Image title attribute (not used).
 * @param string  $align   Image CSS alignment property.
 * @param string  $url     Image source URL (not used).
 * @param string  $size    Image size (not used).
 * @param string  $alt     Image `alt` attribute (not used).
 * @return string The image HTML markup with caption shortcode.
 */
function image_add_caption( $html, $id, $caption, $title, $align, $url, $size, $alt = '' ) {

	/**
	 * Filters the caption text.
	 *
	 * Note: If the caption text is empty, the caption shortcode will not be appended
	 * to the image HTML when inserted into the editor.
	 *
	 * Passing an empty value also prevents the {@see 'image_add_caption_shortcode'}
	 * Filters from being evaluated at the end of image_add_caption().
	 *
	 * @since 4.1.0
	 *
	 * @param string $caption The original caption text.
	 * @param int    $id      The attachment ID.
	 */
	$caption = apply_filters( 'image_add_caption_text', $caption, $id );

	/**
	 * Filters whether to disable captions.
	 *
	 * Prevents image captions from being appended to image HTML when inserted into the editor.
	 *
	 * @since 2.6.0
	 *
	 * @param bool $bool Whether to disable appending captions. Returning true from the filter
	 *                   will disable captions. Default empty string.
	 */
	if ( empty( $caption ) || apply_filters( 'disable_captions', '' ) ) {
		return $html;
	}

	$id = ( 0 < (int) $id ) ? 'attachment_' . $id : '';

	if ( ! preg_match( '/width=["\']([0-9]+)/', $html, $matches ) ) {
		return $html;
	}

	$width = $matches[1];

	$caption = str_replace( array( "\r\n", "\r" ), "\n", $caption );
	$caption = preg_replace_callback( '/<[a-zA-Z0-9]+(?: [^<>]+>)*/', '_cleanup_image_add_caption', $caption );

	// Convert any remaining line breaks to <br />.
	$caption = preg_replace( '/[ \n\t]*\n[ \t]*/', '<br />', $caption );

	$html = preg_replace( '/(class=["\'][^\'"]*)align(none|left|right|center)\s?/', '$1', $html );
	if ( empty( $align ) ) {
		$align = 'none';
	}

	$shcode = '[caption id="' . $id . '" align="align' . $align . '" width="' . $width . '"]' . $html . ' ' . $caption . '[/caption]';

	/**
	 * Filters the image HTML markup including the caption shortcode.
	 *
	 * @since 2.6.0
	 *
	 * @param string $shcode The image HTML markup with caption shortcode.
	 * @param string $html   The image HTML markup.
	 */
	return apply_filters( 'image_add_caption_shortcode', $shcode, $html );
}

/**
 * Private preg_replace callback used in image_add_caption().
 *
 * @access private
 * @since 3.4.0
 *
 * @param array $matches Single regex match.
 * @return string Cleaned up HTML for caption.
 */
function _cleanup_image_add_caption( $matches ) {
	// Remove any line breaks from inside the tags.
	return preg_replace( '/[\r\n\t]+/', ' ', $matches[0] );
}

/**
 * Adds image HTML to editor.
 *
 * @since 2.5.0
 *
 * @param string $html
 */
function media_send_to_editor( $html ) {
	?>
	<script type="text/javascript">
	var win = window.dialogArguments || opener || parent || top;
	win.send_to_editor( <?php echo wp_json_encode( $html, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ); ?> );
	</script>
	<?php
	exit;
}

/**
 * Saves a file submitted from a POST request and create an attachment post for it.
 *
 * @since 2.5.0
 *
 * @param string $file_id   Index of the `$_FILES` array that the file was sent.
 * @param int    $post_id   The post ID of a post to attach the media item to. Required, but can
 *                          be set to 0, creating a media item that has no relationship to a post.
 * @param array  $post_data Optional. Overwrite some of the attachment.
 * @param array  $overrides Optional. Override the wp_handle_upload() behavior.
 * @return int|WP_Error ID of the attachment or a WP_Error object on failure.
 */
function media_handle_upload( $file_id, $post_id, $post_data = array(), $overrides = array( 'test_form' => false ) ) {
	$time = current_time( 'mysql' );
	$post = get_post( $post_id );

	if ( $post ) {
		// The post date doesn't usually matter for pages, so don't backdate this upload.
		if ( 'page' !== $post->post_type && substr( $post->post_date, 0, 4 ) > 0 ) {
			$time = $post->post_date;
		}
	}

	$file = wp_handle_upload( $_FILES[ $file_id ], $overrides, $time );

	if ( isset( $file['error'] ) ) {
		return new WP_Error( 'upload_error', $file['error'] );
	}

	$name = $_FILES[ $file_id ]['name'];
	$ext  = pathinfo( $name, PATHINFO_EXTENSION );
	$name = wp_basename( $name, ".$ext" );

	$url     = $file['url'];
	$type    = $file['type'];
	$file    = $file['file'];
	$title   = sanitize_text_field( $name );
	$content = '';
	$excerpt = '';

	if ( preg_match( '#^audio#', $type ) ) {
		$meta = wp_read_audio_metadata( $file );

		if ( ! empty( $meta['title'] ) ) {
			$title = $meta['title'];
		}

		if ( ! empty( $title ) ) {

			if ( ! empty( $meta['album'] ) && ! empty( $meta['artist'] ) ) {
				/* translators: 1: Audio track title, 2: Album title, 3: Artist name. */
				$content .= sprintf( __( '"%1$s" from %2$s by %3$s.' ), $title, $meta['album'], $meta['artist'] );
			} elseif ( ! empty( $meta['album'] ) ) {
				/* translators: 1: Audio track title, 2: Album title. */
				$content .= sprintf( __( '"%1$s" from %2$s.' ), $title, $meta['album'] );
			} elseif ( ! empty( $meta['artist'] ) ) {
				/* translators: 1: Audio track title, 2: Artist name. */
				$content .= sprintf( __( '"%1$s" by %2$s.' ), $title, $meta['artist'] );
			} else {
				/* translators: %s: Audio track title. */
				$content .= sprintf( __( '"%s".' ), $title );
			}
		} elseif ( ! empty( $meta['album'] ) ) {

			if ( ! empty( $meta['artist'] ) ) {
				/* translators: 1: Audio album title, 2: Artist name. */
				$content .= sprintf( __( '%1$s by %2$s.' ), $meta['album'], $meta['artist'] );
			} else {
				$content .= $meta['album'] . '.';
			}
		} elseif ( ! empty( $meta['artist'] ) ) {

			$content .= $meta['artist'] . '.';

		}

		if ( ! empty( $meta['year'] ) ) {
			/* translators: Audio file track information. %d: Year of audio track release. */
			$content .= ' ' . sprintf( __( 'Released: %d.' ), $meta['year'] );
		}

		if ( ! empty( $meta['track_number'] ) ) {
			$track_number = explode( '/', $meta['track_number'] );

			if ( is_numeric( $track_number[0] ) ) {
				if ( isset( $track_number[1] ) && is_numeric( $track_number[1] ) ) {
					$content .= ' ' . sprintf(
						/* translators: Audio file track information. 1: Audio track number, 2: Total audio tracks. */
						__( 'Track %1$s of %2$s.' ),
						number_format_i18n( $track_number[0] ),
						number_format_i18n( $track_number[1] )
					);
				} else {
					$content .= ' ' . sprintf(
						/* translators: Audio file track information. %s: Audio track number. */
						__( 'Track %s.' ),
						number_format_i18n( $track_number[0] )
					);
				}
			}
		}

		if ( ! empty( $meta['genre'] ) ) {
			/* translators: Audio file genre information. %s: Audio genre name. */
			$content .= ' ' . sprintf( __( 'Genre: %s.' ), $meta['genre'] );
		}

		// Use image exif/iptc data for title and caption defaults if possible.
	} elseif ( str_starts_with( $type, 'image/' ) ) {
		$image_meta = wp_read_image_metadata( $file );

		if ( $image_meta ) {
			if ( trim( $image_meta['title'] ) && ! is_numeric( sanitize_title( $image_meta['title'] ) ) ) {
				$title = $image_meta['title'];
			}

			if ( trim( $image_meta['caption'] ) ) {
				$excerpt = $image_meta['caption'];
			}
		}
	}

	// Construct the attachment array.
	$attachment = array_merge(
		array(
			'post_mime_type' => $type,
			'guid'           => $url,
			'post_parent'    => $post_id,
			'post_title'     => $title,
			'post_content'   => $content,
			'post_excerpt'   => $excerpt,
		),
		$post_data
	);

	// This should never be set as it would then overwrite an existing attachment.
	unset( $attachment['ID'] );

	// Save the data.
	$attachment_id = wp_insert_attachment( $attachment, $file, $post_id, true );

	if ( ! is_wp_error( $attachment_id ) ) {
		/*
		 * Set a custom header with the attachment_id.
		 * Used by the browser/client to resume creating image sub-sizes after a PHP fatal error.
		 */
		if ( ! headers_sent() ) {
			header( 'X-WP-Upload-Attachment-ID: ' . $attachment_id );
		}

		/*
		 * The image sub-sizes are created during wp_generate_attachment_metadata().
		 * This is generally slow and may cause timeouts or out of memory errors.
		 */
		wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $file ) );
	}

	return $attachment_id;
}

/**
 * Handles a side-loaded file in the same way as an uploaded file is handled by media_handle_upload().
 *
 * @since 2.6.0
 * @since 5.3.0 The `$post_id` parameter was made optional.
 *
 * @param string[] $file_array Array that represents a `$_FILES` upload array.
 * @param int      $post_id    Optional. The post ID the media is associated with.
 * @param string   $desc       Optional. Description of the side-loaded file. Default null.
 * @param array    $post_data  Optional. Post data to override. Default empty array.
 * @return int|WP_Error The ID of the attachment or a WP_Error on failure.
 */
function media_handle_sideload( $file_array, $post_id = 0, $desc = null, $post_data = array() ) {
	$overrides = array( 'test_form' => false );

	if ( isset( $post_data['post_date'] ) && substr( $post_data['post_date'], 0, 4 ) > 0 ) {
		$time = $post_data['post_date'];
	} else {
		$post = get_post( $post_id );
		if ( $post && substr( $post->post_date, 0, 4 ) > 0 ) {
			$time = $post->post_date;
		} else {
			$time = current_time( 'mysql' );
		}
	}

	$file = wp_handle_sideload( $file_array, $overrides, $time );

	if ( isset( $file['error'] ) ) {
		return new WP_Error( 'upload_error', $file['error'] );
	}

	$url     = $file['url'];
	$type    = $file['type'];
	$file    = $file['file'];
	$title   = preg_replace( '/\.[^.]+$/', '', wp_basename( $file ) );
	$content = '';

	// Use image exif/iptc data for title and caption defaults if possible.
	$image_meta = wp_read_image_metadata( $file );

	if ( $image_meta ) {
		if ( trim( $image_meta['title'] ) && ! is_numeric( sanitize_title( $image_meta['title'] ) ) ) {
			$title = $image_meta['title'];
		}

		if ( trim( $image_meta['caption'] ) ) {
			$content = $image_meta['caption'];
		}
	}

	if ( isset( $desc ) ) {
		$title = $desc;
	}

	// Construct the attachment array.
	$attachment = array_merge(
		array(
			'post_mime_type' => $type,
			'guid'           => $url,
			'post_parent'    => $post_id,
			'post_title'     => $title,
			'post_content'   => $content,
		),
		$post_data
	);

	// This should never be set as it would then overwrite an existing attachment.
	unset( $attachment['ID'] );

	// Save the attachment metadata.
	$attachment_id = wp_insert_attachment( $attachment, $file, $post_id, true );

	if ( ! is_wp_error( $attachment_id ) ) {
		wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $file ) );
	}

	return $attachment_id;
}

/**
 * Outputs the iframe to display the media upload page.
 *
 * @since 2.5.0
 * @since 5.3.0 Formalized the existing and already documented `...$args` parameter
 *              by adding it to the function signature.
 *
 * @global string $body_id
 *
 * @param callable $content_func Function that outputs the content.
 * @param mixed    ...$args      Optional additional parameters to pass to the callback function when it's called.
 */
function wp_iframe( $content_func, ...$args ) {
	global $body_id;

	_wp_admin_html_begin();
	?>
	<title><?php bloginfo( 'name' ); ?> &rsaquo; <?php _e( 'Uploads' ); ?> &#8212; <?php _e( 'WordPress' ); ?></title>
	<?php

	wp_enqueue_style( 'colors' );
	// Check callback name for 'media'.
	if (
		( is_array( $content_func ) && ! empty( $content_func[1] ) && str_starts_with( (string) $content_func[1], 'media' ) ) ||
		( ! is_array( $content_func ) && str_starts_with( $content_func, 'media' ) )
	) {
		wp_enqueue_style( 'deprecated-media' );
	}

	?>
	<script type="text/javascript">
	addLoadEvent = function(func){if(typeof jQuery!=='undefined')jQuery(function(){func();});else if(typeof wpOnload!=='function'){wpOnload=func;}else{var oldonload=wpOnload;wpOnload=function(){oldonload();func();}}};
	var ajaxurl = '<?php echo esc_js( admin_url( 'admin-ajax.php', 'relative' ) ); ?>', pagenow = 'media-upload-popup', adminpage = 'media-upload-popup',
	isRtl = <?php echo (int) is_rtl(); ?>;
	</script>
	<?php
	/** This action is documented in wp-admin/admin-header.php */
	do_action( 'admin_enqueue_scripts', 'media-upload-popup' );

	/**
	 * Fires when admin styles enqueued for the legacy (pre-3.5.0) media upload popup are printed.
	 *
	 * @since 2.9.0
	 */
	do_action( 'admin_print_styles-media-upload-popup' );  // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores

	/** This action is documented in wp-admin/admin-header.php */
	do_action( 'admin_print_styles' );

	/**
	 * Fires when admin scripts enqueued for the legacy (pre-3.5.0) media upload popup are printed.
	 *
	 * @since 2.9.0
	 */
	do_action( 'admin_print_scripts-media-upload-popup' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores

	/** This action is documented in wp-admin/admin-header.php */
	do_action( 'admin_print_scripts' );

	/**
	 * Fires when scripts enqueued for the admin header for the legacy (pre-3.5.0)
	 * media upload popup are printed.
	 *
	 * @since 2.9.0
	 */
	do_action( 'admin_head-media-upload-popup' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores

	/** This action is documented in wp-admin/admin-header.php */
	do_action( 'admin_head' );

	if ( is_string( $content_func ) ) {
		/**
		 * Fires in the admin header for each specific form tab in the legacy
		 * (pre-3.5.0) media upload popup.
		 *
		 * The dynamic portion of the hook name, `$content_func`, refers to the form
		 * callback for the media upload type.
		 *
		 * @since 2.5.0
		 */
		do_action( "admin_head_{$content_func}" );
	}

	$body_id_attr = '';

	if ( isset( $body_id ) ) {
		$body_id_attr = ' id="' . $body_id . '"';
	}

	?>
	</head>
	<body<?php echo $body_id_attr; ?> class="wp-core-ui no-js">
	<script type="text/javascript">
	document.body.className = document.body.className.replace('no-js', 'js');
	</script>
	<?php

	call_user_func_array( $content_func, $args );

	/** This action is documented in wp-admin/admin-footer.php */
	do_action( 'admin_print_footer_scripts' );

	?>
	<script type="text/javascript">if(typeof wpOnload==='function')wpOnload();</script>
	</body>
	</html>
	<?php
}

/**
 * Adds the media button to the editor.
 *
 * @since 2.5.0
 *
 * @global int $post_ID
 *
 * @param string $editor_id
 */
function media_buttons( $editor_id = 'content' ) {
	static $instance = 0;
	++$instance;

	$post = get_post();

	if ( ! $post && ! empty( $GLOBALS['post_ID'] ) ) {
		$post = $GLOBALS['post_ID'];
	}

	wp_enqueue_media( array( 'post' => $post ) );

	$img = '<span class="wp-media-buttons-icon" aria-hidden="true"></span> ';

	$id_attribute = 1 === $instance ? ' id="insert-media-button"' : '';

	printf(
		'<button type="button"%s class="button insert-media add_media" data-editor="%s" aria-haspopup="dialog" aria-controls="wp-media-modal">%s</button>',
		$id_attribute,
		esc_attr( $editor_id ),
		$img . __( 'Add Media' )
	);

	/**
	 * Filters the legacy (pre-3.5.0) media buttons.
	 *
	 * Use {@see 'media_buttons'} action instead.
	 *
	 * @since 2.5.0
	 * @deprecated 3.5.0 Use {@see 'media_buttons'} action instead.
	 *
	 * @param string $string Media buttons context. Default empty.
	 */
	$legacy_filter = apply_filters_deprecated( 'media_buttons_context', array( '' ), '3.5.0', 'media_buttons' );

	if ( $legacy_filter ) {
		// #WP22559. Close <a> if a plugin started by closing <a> to open their own <a> tag.
		if ( 0 === stripos( trim( $legacy_filter ), '</a>' ) ) {
			$legacy_filter .= '</a>';
		}
		echo $legacy_filter;
	}
}

/**
 * Retrieves the upload iframe source URL.
 *
 * @since 3.0.0
 *
 * @global int $post_ID
 *
 * @param string $type    Media type.
 * @param int    $post_id Post ID.
 * @param string $tab     Media upload tab.
 * @return string Upload iframe source URL.
 */
function get_upload_iframe_src( $type = null, $post_id = null, $tab = null ) {
	global $post_ID;

	if ( empty( $post_id ) ) {
		$post_id = $post_ID;
	}

	$upload_iframe_src = add_query_arg( 'post_id', (int) $post_id, admin_url( 'media-upload.php' ) );

	if ( $type && 'media' !== $type ) {
		$upload_iframe_src = add_query_arg( 'type', $type, $upload_iframe_src );
	}

	if ( ! empty( $tab ) ) {
		$upload_iframe_src = add_query_arg( 'tab', $tab, $upload_iframe_src );
	}

	/**
	 * Filters the upload iframe source URL for a specific media type.
	 *
	 * The dynamic portion of the hook name, `$type`, refers to the type
	 * of media uploaded.
	 *
	 * Possible hook names include:
	 *
	 *  - `image_upload_iframe_src`
	 *  - `media_upload_iframe_src`
	 *
	 * @since 3.0.0
	 *
	 * @param string $upload_iframe_src The upload iframe source URL.
	 */
	$upload_iframe_src = apply_filters( "{$type}_upload_iframe_src", $upload_iframe_src );

	return add_query_arg( 'TB_iframe', true, $upload_iframe_src );
}

/**
 * Handles form submissions for the legacy media uploader.
 *
 * @since 2.5.0
 *
 * @return null|array|void Array of error messages keyed by attachment ID, null or void on success.
 */
function media_upload_form_handler() {
	check_admin_referer( 'media-form' );

	$errors = null;

	if ( isset( $_POST['send'] ) ) {
		$keys    = array_keys( $_POST['send'] );
		$send_id = (int) reset( $keys );
	}

	if ( ! empty( $_POST['attachments'] ) ) {
		foreach ( $_POST['attachments'] as $attachment_id => $attachment ) {
			$post  = get_post( $attachment_id, ARRAY_A );
			$_post = $post;

			if ( ! current_user_can( 'edit_post', $attachment_id ) ) {
				continue;
			}

			if ( isset( $attachment['post_content'] ) ) {
				$post['post_content'] = $attachment['post_content'];
			}

			if ( isset( $attachment['post_title'] ) ) {
				$post['post_title'] = $attachment['post_title'];
			}

			if ( isset( $attachment['post_excerpt'] ) ) {
				$post['post_excerpt'] = $attachment['post_excerpt'];
			}

			if ( isset( $attachment['menu_order'] ) ) {
				$post['menu_order'] = $attachment['menu_order'];
			}

			if ( isset( $send_id ) && $attachment_id === $send_id ) {
				if ( isset( $attachment['post_parent'] ) ) {
					$post['post_parent'] = $attachment['post_parent'];
				}
			}

			/**
			 * Filters the attachment fields to be saved.
			 *
			 * @since 2.5.0
			 *
			 * @see wp_get_attachment_metadata()
			 *
			 * @param array $post       An array of post data.
			 * @param array $attachment An array of attachment metadata.
			 */
			$post = apply_filters( 'attachment_fields_to_save', $post, $attachment );

			if ( isset( $attachment['image_alt'] ) ) {
				$image_alt = wp_unslash( $attachment['image_alt'] );

				if ( get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ) !== $image_alt ) {
					$image_alt = wp_strip_all_tags( $image_alt, true );

					// update_post_meta() expects slashed.
					update_post_meta( $attachment_id, '_wp_attachment_image_alt', wp_slash( $image_alt ) );
				}
			}

			if ( isset( $post['errors'] ) ) {
				$errors[ $attachment_id ] = $post['errors'];
				unset( $post['errors'] );
			}

			if ( $post != $_post ) {
				wp_update_post( $post );
			}

			foreach ( get_attachment_taxonomies( $post ) as $t ) {
				if ( isset( $attachment[ $t ] ) ) {
					wp_set_object_terms( $attachment_id, array_map( 'trim', preg_split( '/,+/', $attachment[ $t ] ) ), $t, false );
				}
			}
		}
	}

	if ( isset( $_POST['insert-gallery'] ) || isset( $_POST['update-gallery'] ) ) {
		?>
		<script type="text/javascript">
		var win = window.dialogArguments || opener || parent || top;
		win.tb_remove();
		</script>
		<?php

		exit;
	}

	if ( isset( $send_id ) ) {
		$attachment = wp_unslash( $_POST['attachments'][ $send_id ] );
		$html       = isset( $attachment['post_title'] ) ? $attachment['post_title'] : '';

		if ( ! empty( $attachment['url'] ) ) {
			$rel = '';

			if ( str_contains( $attachment['url'], 'attachment_id' ) || get_attachment_link( $send_id ) === $attachment['url'] ) {
				$rel = " rel='attachment wp-att-" . esc_attr( $send_id ) . "'";
			}

			$html = "<a href='{$attachment['url']}'$rel>$html</a>";
		}

		/**
		 * Filters the HTML markup for a media item sent to the editor.
		 *
		 * @since 2.5.0
		 *
		 * @see wp_get_attachment_metadata()
		 *
		 * @param string $html       HTML markup for a media item sent to the editor.
		 * @param int    $send_id    The first key from the $_POST['send'] data.
		 * @param array  $attachment Array of attachment metadata.
		 */
		$html = apply_filters( 'media_send_to_editor', $html, $send_id, $attachment );

		return media_send_to_editor( $html );
	}

	return $errors;
}

/**
 * Handles the process of uploading media.
 *
 * @since 2.5.0
 *
 * @return null|string
 */
function wp_media_upload_handler() {
	$errors = array();
	$id     = 0;

	if ( isset( $_POST['html-upload'] ) && ! empty( $_FILES ) ) {
		check_admin_referer( 'media-form' );
		// Upload File button was clicked.
		$id = media_handle_upload( 'async-upload', $_REQUEST['post_id'] );
		unset( $_FILES );

		if ( is_wp_error( $id ) ) {
			$errors['upload_error'] = $id;
			$id                     = false;
		}
	}

	if ( ! empty( $_POST['insertonlybutton'] ) ) {
		$src = $_POST['src'];

		if ( ! empty( $src ) && ! strpos( $src, '://' ) ) {
			$src = "http://$src";
		}

		if ( isset( $_POST['media_type'] ) && 'image' !== $_POST['media_type'] ) {
			$title = esc_html( wp_unslash( $_POST['title'] ) );
			if ( empty( $title ) ) {
				$title = esc_html( wp_basename( $src ) );
			}

			if ( $title && $src ) {
				$html = "<a href='" . esc_url( $src ) . "'>$title</a>";
			}

			$type = 'file';
			$ext  = preg_replace( '/^.+?\.([^.]+)$/', '$1', $src );

			if ( $ext ) {
				$ext_type = wp_ext2type( $ext );
				if ( 'audio' === $ext_type || 'video' === $ext_type ) {
					$type = $ext_type;
				}
			}

			/**
			 * Filters the URL sent to the editor for a specific media type.
			 *
			 * The dynamic portion of the hook name, `$type`, refers to the type
			 * of media being sent.
			 *
			 * Possible hook names include:
			 *
			 *  - `audio_send_to_editor_url`
			 *  - `file_send_to_editor_url`
			 *  - `video_send_to_editor_url`
			 *
			 * @since 3.3.0
			 *
			 * @param string $html  HTML markup sent to the editor.
			 * @param string $src   Media source URL.
			 * @param string $title Media title.
			 */
			$html = apply_filters( "{$type}_send_to_editor_url", $html, sanitize_url( $src ), $title );
		} else {
			$align = '';
			$alt   = esc_attr( wp_unslash( $_POST['alt'] ) );

			if ( isset( $_POST['align'] ) ) {
				$align = esc_attr( wp_unslash( $_POST['align'] ) );
				$class = " class='align$align'";
			}

			if ( ! empty( $src ) ) {
				$html = "<img src='" . esc_url( $src ) . "' alt='$alt'$class />";
			}

			/**
			 * Filters the image URL sent to the editor.
			 *
			 * @since 2.8.0
			 *
			 * @param string $html  HTML markup sent to the editor for an image.
			 * @param string $src   Image source URL.
			 * @param string $alt   Image alternate, or alt, text.
			 * @param string $align The image alignment. Default 'alignnone'. Possible values include
			 *                      'alignleft', 'aligncenter', 'alignright', 'alignnone'.
			 */
			$html = apply_filters( 'image_send_to_editor_url', $html, sanitize_url( $src ), $alt, $align );
		}

		return media_send_to_editor( $html );
	}

	if ( isset( $_POST['save'] ) ) {
		$errors['upload_notice'] = __( 'Saved.' );
		wp_enqueue_script( 'admin-gallery' );

		return wp_iframe( 'media_upload_gallery_form', $errors );

	} elseif ( ! empty( $_POST ) ) {
		$return = media_upload_form_handler();

		if ( is_string( $return ) ) {
			return $return;
		}

		if ( is_array( $return ) ) {
			$errors = $return;
		}
	}

	if ( isset( $_GET['tab'] ) && 'type_url' === $_GET['tab'] ) {
		$type = 'image';

		if ( isset( $_GET['type'] ) && in_array( $_GET['type'], array( 'video', 'audio', 'file' ), true ) ) {
			$type = $_GET['type'];
		}

		return wp_iframe( 'media_upload_type_url_form', $type, $errors, $id );
	}

	return wp_iframe( 'media_upload_type_form', 'image', $errors, $id );
}

/**
 * Downloads an image from the specified URL, saves it as an attachment, and optionally attaches it to a post.
 *
 * @since 2.6.0
 * @since 4.2.0 Introduced the `$return_type` parameter.
 * @since 4.8.0 Introduced the 'id' option for the `$return_type` parameter.
 * @since 5.3.0 The `$post_id` parameter was made optional.
 * @since 5.4.0 The original URL of the attachment is stored in the `_source_url`
 *              post meta value.
 * @since 5.8.0 Added 'webp' to the default list of allowed file extensions.
 *
 * @param string $file        The URL of the image to download.
 * @param int    $post_id     Optional. The post ID the media is to be associated with.
 * @param string $desc        Optional. Description of the image.
 * @param string $return_type Optional. Accepts 'html' (image tag html) or 'src' (URL),
 *                            or 'id' (attachment ID). Default 'html'.
 * @return string|int|WP_Error Populated HTML img tag, attachment ID, or attachment source
 *                             on success, WP_Error object otherwise.
 */
function media_sideload_image( $file, $post_id = 0, $desc = null, $return_type = 'html' ) {
	if ( ! empty( $file ) ) {

		$allowed_extensions = array( 'jpg', 'jpeg', 'jpe', 'png', 'gif', 'webp' );

		/**
		 * Filters the list of allowed file extensions when sideloading an image from a URL.
		 *
		 * The default allowed extensions are:
		 *
		 *  - `jpg`
		 *  - `jpeg`
		 *  - `jpe`
		 *  - `png`
		 *  - `gif`
		 *  - `webp`
		 *
		 * @since 5.6.0
		 * @since 5.8.0 Added 'webp' to the default list of allowed file extensions.
		 *
		 * @param string[] $allowed_extensions Array of allowed file extensions.
		 * @param string   $file               The URL of the image to download.
		 */
		$allowed_extensions = apply_filters( 'image_sideload_extensions', $allowed_extensions, $file );
		$allowed_extensions = array_map( 'preg_quote', $allowed_extensions );

		// Set variables for storage, fix file filename for query strings.
		preg_match( '/[^\?]+\.(' . implode( '|', $allowed_extensions ) . ')\b/i', $file, $matches );

		if ( ! $matches ) {
			return new WP_Error( 'image_sideload_failed', __( 'Invalid image URL.' ) );
		}

		$file_array         = array();
		$file_array['name'] = wp_basename( $matches[0] );

		// Download file to temp location.
		$file_array['tmp_name'] = download_url( $file );

		// If error storing temporarily, return the error.
		if ( is_wp_error( $file_array['tmp_name'] ) ) {
			return $file_array['tmp_name'];
		}

		// Do the validation and storage stuff.
		$id = media_handle_sideload( $file_array, $post_id, $desc );

		// If error storing permanently, unlink.
		if ( is_wp_error( $id ) ) {
			@unlink( $file_array['tmp_name'] );
			return $id;
		}

		// Store the original attachment source in meta.
		add_post_meta( $id, '_source_url', $file );

		// If attachment ID was requested, return it.
		if ( 'id' === $return_type ) {
			return $id;
		}

		$src = wp_get_attachment_url( $id );
	}

	// Finally, check to make sure the file has been saved, then return the HTML.
	if ( ! empty( $src ) ) {
		if ( 'src' === $return_type ) {
			return $src;
		}

		$alt  = isset( $desc ) ? esc_attr( $desc ) : '';
		$html = "<img src='$src' alt='$alt' />";

		return $html;
	} else {
		return new WP_Error( 'image_sideload_failed' );
	}
}

/**
 * Retrieves the legacy media uploader form in an iframe.
 *
 * @since 2.5.0
 *
 * @return string|null
 */
function media_upload_gallery() {
	$errors = array();

	if ( ! empty( $_POST ) ) {
		$return = media_upload_form_handler();

		if ( is_string( $return ) ) {
			return $return;
		}

		if ( is_array( $return ) ) {
			$errors = $return;
		}
	}

	wp_enqueue_script( 'admin-gallery' );
	return wp_iframe( 'media_upload_gallery_form', $errors );
}

/**
 * Retrieves the legacy media library form in an iframe.
 *
 * @since 2.5.0
 *
 * @return string|null
 */
function media_upload_library() {
	$errors = array();

	if ( ! empty( $_POST ) ) {
		$return = media_upload_form_handler();

		if ( is_string( $return ) ) {
			return $return;
		}
		if ( is_array( $return ) ) {
			$errors = $return;
		}
	}

	return wp_iframe( 'media_upload_library_form', $errors );
}

/**
 * Retrieves HTML for the image alignment radio buttons with the specified one checked.
 *
 * @since 2.7.0
 *
 * @param WP_Post $post
 * @param string  $checked
 * @return string
 */
function image_align_input_fields( $post, $checked = '' ) {

	if ( empty( $checked ) ) {
		$checked = get_user_setting( 'align', 'none' );
	}

	$alignments = array(
		'none'   => __( 'None' ),
		'left'   => __( 'Left' ),
		'center' => __( 'Center' ),
		'right'  => __( 'Right' ),
	);

	if ( ! array_key_exists( (string) $checked, $alignments ) ) {
		$checked = 'none';
	}

	$output = array();

	foreach ( $alignments as $name => $label ) {
		$name     = esc_attr( $name );
		$output[] = "<input type='radio' name='attachments[{$post->ID}][align]' id='image-align-{$name}-{$post->ID}' value='$name'" .
			( $checked === $name ? " checked='checked'" : '' ) .
			" /><label for='image-align-{$name}-{$post->ID}' class='align image-align-{$name}-label'>$label</label>";
	}

	return implode( "\n", $output );
}

/**
 * Retrieves HTML for the size radio buttons with the specified one checked.
 *
 * @since 2.7.0
 *
 * @param WP_Post     $post
 * @param bool|string $check
 * @return array
 */
function image_size_input_fields( $post, $check = '' ) {
	/**
	 * Filters the names and labels of the default image sizes.
	 *
	 * @since 3.3.0
	 *
	 * @param string[] $size_names Array of image size labels keyed by their name. Default values
	 *                             include 'Thumbnail', 'Medium', 'Large', and 'Full Size'.
	 */
	$size_names = apply_filters(
		'image_size_names_choose',
		array(
			'thumbnail' => __( 'Thumbnail' ),
			'medium'    => __( 'Medium' ),
			'large'     => __( 'Large' ),
			'full'      => __( 'Full Size' ),
		)
	);

	if ( empty( $check ) ) {
		$check = get_user_setting( 'imgsize', 'medium' );
	}

	$output = array();

	foreach ( $size_names as $size => $label ) {
		$downsize = image_downsize( $post->ID, $size );
		$checked  = '';

		// Is this size selectable?
		$enabled = ( $downsize[3] || 'full' === $size );
		$css_id  = "image-size-{$size}-{$post->ID}";

		// If this size is the default but that's not available, don't select it.
		if ( $size === $check ) {
			if ( $enabled ) {
				$checked = " checked='checked'";
			} else {
				$check = '';
			}
		} elseif ( ! $check && $enabled && 'thumbnail' !== $size ) {
			/*
			 * If $check is not enabled, default to the first available size
			 * that's bigger than a thumbnail.
			 */
			$check   = $size;
			$checked = " checked='checked'";
		}

		$html = "<div class='image-size-item'><input type='radio' " . disabled( $enabled, false, false ) . "name='attachments[$post->ID][image-size]' id='{$css_id}' value='{$size}'$checked />";

		$html .= "<label for='{$css_id}'>$label</label>";

		// Only show the dimensions if that choice is available.
		if ( $enabled ) {
			$html .= " <label for='{$css_id}' class='help'>" . sprintf( '(%d&nbsp;&times;&nbsp;%d)', $downsize[1], $downsize[2] ) . '</label>';
		}
		$html .= '</div>';

		$output[] = $html;
	}

	return array(
		'label' => __( 'Size' ),
		'input' => 'html',
		'html'  => implode( "\n", $output ),
	);
}

/**
 * Retrieves HTML for the Link URL buttons with the default link type as specified.
 *
 * @since 2.7.0
 *
 * @param WP_Post $post
 * @param string  $url_type
 * @return string
 */
function image_link_input_fields( $post, $url_type = '' ) {

	$file = wp_get_attachment_url( $post->ID );
	$link = get_attachment_link( $post->ID );

	if ( empty( $url_type ) ) {
		$url_type = get_user_setting( 'urlbutton', 'post' );
	}

	$url = '';

	if ( 'file' === $url_type ) {
		$url = $file;
	} elseif ( 'post' === $url_type ) {
		$url = $link;
	}

	return "
	<input type='text' class='text urlfield' name='attachments[$post->ID][url]' value='" . esc_attr( $url ) . "' /><br />
	<button type='button' class='button urlnone' data-link-url=''>" . __( 'None' ) . "</button>
	<button type='button' class='button urlfile' data-link-url='" . esc_url( $file ) . "'>" . __( 'File URL' ) . "</button>
	<button type='button' class='button urlpost' data-link-url='" . esc_url( $link ) . "'>" . __( 'Attachment Post URL' ) . '</button>
';
}

/**
 * Outputs a textarea element for inputting an attachment caption.
 *
 * @since 3.4.0
 *
 * @param WP_Post $edit_post Attachment WP_Post object.
 * @return string HTML markup for the textarea element.
 */
function wp_caption_input_textarea( $edit_post ) {
	// Post data is already escaped.
	$name = "attachments[{$edit_post->ID}][post_excerpt]";

	return '<textarea name="' . $name . '" id="' . $name . '">' . $edit_post->post_excerpt . '</textarea>';
}

/**
 * Retrieves the image attachment fields to edit form fields.
 *
 * @since 2.5.0
 *
 * @param array  $form_fields
 * @param object $post
 * @return array
 */
function image_attachment_fields_to_edit( $form_fields, $post ) {
	return $form_fields;
}

/**
 * Retrieves the single non-image attachment fields to edit form fields.
 *
 * @since 2.5.0
 *
 * @param array   $form_fields An array of attachment form fields.
 * @param WP_Post $post        The WP_Post attachment object.
 * @return array Filtered attachment form fields.
 */
function media_single_attachment_fields_to_edit( $form_fields, $post ) {
	unset( $form_fields['url'], $form_fields['align'], $form_fields['image-size'] );
	return $form_fields;
}

/**
 * Retrieves the post non-image attachment fields to edit form fields.
 *
 * @since 2.8.0
 *
 * @param array   $form_fields An array of attachment form fields.
 * @param WP_Post $post        The WP_Post attachment object.
 * @return array Filtered attachment form fields.
 */
function media_post_single_attachment_fields_to_edit( $form_fields, $post ) {
	unset( $form_fields['image_url'] );
	return $form_fields;
}

/**
 * Retrieves the media element HTML to send to the editor.
 *
 * @since 2.5.0
 *
 * @param string  $html
 * @param int     $attachment_id
 * @param array   $attachment
 * @return string
 */
function image_media_send_to_editor( $html, $attachment_id, $attachment ) {
	$post = get_post( $attachment_id );

	if ( str_starts_with( $post->post_mime_type, 'image' ) ) {
		$url   = $attachment['url'];
		$align = ! empty( $attachment['align'] ) ? $attachment['align'] : 'none';
		$size  = ! empty( $attachment['image-size'] ) ? $attachment['image-size'] : 'medium';
		$alt   = ! empty( $attachment['image_alt'] ) ? $attachment['image_alt'] : '';
		$rel   = ( str_contains( $url, 'attachment_id' ) || get_attachment_link( $attachment_id ) === $url );

		return get_image_send_to_editor( $attachment_id, $attachment['post_excerpt'], $attachment['post_title'], $align, $url, $rel, $size, $alt );
	}

	return $html;
}

/**
 * Retrieves the attachment fields to edit form fields.
 *
 * @since 2.5.0
 *
 * @param WP_Post $post
 * @param array   $errors
 * @return array
 */
function get_attachment_fields_to_edit( $post, $errors = null ) {
	if ( is_int( $post ) ) {
		$post = get_post( $post );
	}

	if ( is_array( $post ) ) {
		$post = new WP_Post( (object) $post );
	}

	$image_url = wp_get_attachment_url( $post->ID );

	$edit_post = sanitize_post( $post, 'edit' );

	$form_fields = array(
		'post_title'   => array(
			'label' => __( 'Title' ),
			'value' => $edit_post->post_title,
		),
		'image_alt'    => array(),
		'post_excerpt' => array(
			'label' => __( 'Caption' ),
			'input' => 'html',
			'html'  => wp_caption_input_textarea( $edit_post ),
		),
		'post_content' => array(
			'label' => __( 'Description' ),
			'value' => $edit_post->post_content,
			'input' => 'textarea',
		),
		'url'          => array(
			'label' => __( 'Link URL' ),
			'input' => 'html',
			'html'  => image_link_input_fields( $post, get_option( 'image_default_link_type' ) ),
			'helps' => __( 'Enter a link URL or click above for presets.' ),
		),
		'menu_order'   => array(
			'label' => __( 'Order' ),
			'value' => $edit_post->menu_order,
		),
		'image_url'    => array(
			'label' => __( 'File URL' ),
			'input' => 'html',
			'html'  => "<input type='text' class='text urlfield' readonly='readonly' name='attachments[$post->ID][url]' value='" . esc_attr( $image_url ) . "' /><br />",
			'value' => wp_get_attachment_url( $post->ID ),
			'helps' => __( 'Location of the uploaded file.' ),
		),
	);

	foreach ( get_attachment_taxonomies( $post ) as $taxonomy ) {
		$t = (array) get_taxonomy( $taxonomy );

		if ( ! $t['public'] || ! $t['show_ui'] ) {
			continue;
		}

		if ( empty( $t['label'] ) ) {
			$t['label'] = $taxonomy;
		}

		if ( empty( $t['args'] ) ) {
			$t['args'] = array();
		}

		$terms = get_object_term_cache( $post->ID, $taxonomy );

		if ( false === $terms ) {
			$terms = wp_get_object_terms( $post->ID, $taxonomy, $t['args'] );
		}

		$values = array();

		foreach ( $terms as $term ) {
			$values[] = $term->slug;
		}

		$t['value'] = implode( ', ', $values );

		$form_fields[ $taxonomy ] = $t;
	}

	/*
	 * Merge default fields with their errors, so any key passed with the error
	 * (e.g. 'error', 'helps', 'value') will replace the default.
	 * The recursive merge is easily traversed with array casting:
	 * foreach ( (array) $things as $thing )
	 */
	$form_fields = array_merge_recursive( $form_fields, (array) $errors );

	// This was formerly in image_attachment_fields_to_edit().
	if ( str_starts_with( $post->post_mime_type, 'image' ) ) {
		$alt = get_post_meta( $post->ID, '_wp_attachment_image_alt', true );

		if ( empty( $alt ) ) {
			$alt = '';
		}

		$form_fields['post_title']['required'] = true;

		$form_fields['image_alt'] = array(
			'value' => $alt,
			'label' => __( 'Alternative Text' ),
			'helps' => __( 'Alt text for the image, e.g. &#8220;The Mona Lisa&#8221;' ),
		);

		$form_fields['align'] = array(
			'label' => __( 'Alignment' ),
			'input' => 'html',
			'html'  => image_align_input_fields( $post, get_option( 'image_default_align' ) ),
		);

		$form_fields['image-size'] = image_size_input_fields( $post, get_option( 'image_default_size', 'medium' ) );

	} else {
		unset( $form_fields['image_alt'] );
	}

	/**
	 * Filters the attachment fields to edit.
	 *
	 * @since 2.5.0
	 *
	 * @param array   $form_fields An array of attachment form fields.
	 * @param WP_Post $post        The WP_Post attachment object.
	 */
	$form_fields = apply_filters( 'attachment_fields_to_edit', $form_fields, $post );

	return $form_fields;
}

/**
 * Retrieves HTML for media items of post gallery.
 *
 * The HTML markup retrieved will be created for the progress of SWF Upload
 * component. Will also create link for showing and hiding the form to modify
 * the image attachment.
 *
 * @since 2.5.0
 *
 * @global WP_Query $wp_the_query WordPress Query object.
 *
 * @param int   $post_id Post ID.
 * @param array $errors  Errors for attachment, if any.
 * @return string HTML content for media items of post gallery.
 */
function get_media_items( $post_id, $errors ) {
	$attachments = array();

	if ( $post_id ) {
		$post = get_post( $post_id );

		if ( $post && 'attachment' === $post->post_type ) {
			$attachments = array( $post->ID => $post );
		} else {
			$attachments = get_children(
				array(
					'post_parent' => $post_id,
					'post_type'   => 'attachment',
					'orderby'     => 'menu_order ASC, ID',
					'order'       => 'DESC',
				)
			);
		}
	} else {
		if ( is_array( $GLOBALS['wp_the_query']->posts ) ) {
			foreach ( $GLOBALS['wp_the_query']->posts as $attachment ) {
				$attachments[ $attachment->ID ] = $attachment;
			}
		}
	}

	$output = '';
	foreach ( (array) $attachments as $id => $attachment ) {
		if ( 'trash' === $attachment->post_status ) {
			continue;
		}

		$item = get_media_item( $id, array( 'errors' => isset( $errors[ $id ] ) ? $errors[ $id ] : null ) );

		if ( $item ) {
			$output .= "\n<div id='media-item-$id' class='media-item child-of-$attachment->post_parent preloaded'><div class='progress hidden'><div class='bar'></div></div><div id='media-upload-error-$id' class='hidden'></div><div class='filename hidden'></div>$item\n</div>";
		}
	}

	return $output;
}

/**
 * Retrieves HTML form for modifying the image attachment.
 *
 * @since 2.5.0
 *
 * @global string $redir_tab
 *
 * @param int          $attachment_id Attachment ID for modification.
 * @param string|array $args          Optional. Override defaults.
 * @return string HTML form for attachment.
 */
function get_media_item( $attachment_id, $args = null ) {
	global $redir_tab;

	$thumb_url     = false;
	$attachment_id = (int) $attachment_id;

	if ( $attachment_id ) {
		$thumb_url = wp_get_attachment_image_src( $attachment_id, 'thumbnail', true );

		if ( $thumb_url ) {
			$thumb_url = $thumb_url[0];
		}
	}

	$post            = get_post( $attachment_id );
	$current_post_id = ! empty( $_GET['post_id'] ) ? (int) $_GET['post_id'] : 0;

	$default_args = array(
		'errors'     => null,
		'send'       => $current_post_id ? post_type_supports( get_post_type( $current_post_id ), 'editor' ) : true,
		'delete'     => true,
		'toggle'     => true,
		'show_title' => true,
	);

	$parsed_args = wp_parse_args( $args, $default_args );

	/**
	 * Filters the arguments used to retrieve an image for the edit image form.
	 *
	 * @since 3.1.0
	 *
	 * @see get_media_item
	 *
	 * @param array $parsed_args An array of arguments.
	 */
	$parsed_args = apply_filters( 'get_media_item_args', $parsed_args );

	$toggle_on  = __( 'Show' );
	$toggle_off = __( 'Hide' );

	$file     = get_attached_file( $post->ID );
	$filename = esc_html( wp_basename( $file ) );
	$title    = esc_attr( $post->post_title );

	$post_mime_types = get_post_mime_types();
	$keys            = array_keys( wp_match_mime_types( array_keys( $post_mime_types ), $post->post_mime_type ) );
	$type            = reset( $keys );
	$type_html       = "<input type='hidden' id='type-of-$attachment_id' value='" . esc_attr( $type ) . "' />";

	$form_fields = get_attachment_fields_to_edit( $post, $parsed_args['errors'] );

	if ( $parsed_args['toggle'] ) {
		$class        = empty( $parsed_args['errors'] ) ? 'startclosed' : 'startopen';
		$toggle_links = "
		<a class='toggle describe-toggle-on' href='#'>$toggle_on</a>
		<a class='toggle describe-toggle-off' href='#'>$toggle_off</a>";
	} else {
		$class        = '';
		$toggle_links = '';
	}

	$display_title = ( ! empty( $title ) ) ? $title : $filename; // $title shouldn't ever be empty, but just in case.
	$display_title = $parsed_args['show_title'] ? "<div class='filename new'><span class='title'>" . wp_html_excerpt( $display_title, 60, '&hellip;' ) . '</span></div>' : '';

	$gallery = ( ( isset( $_REQUEST['tab'] ) && 'gallery' === $_REQUEST['tab'] ) || ( isset( $redir_tab ) && 'gallery' === $redir_tab ) );
	$order   = '';

	foreach ( $form_fields as $key => $val ) {
		if ( 'menu_order' === $key ) {
			if ( $gallery ) {
				$order = "<div class='menu_order'> <input class='menu_order_input' type='text' id='attachments[$attachment_id][menu_order]' name='attachments[$attachment_id][menu_order]' value='" . esc_attr( $val['value'] ) . "' /></div>";
			} else {
				$order = "<input type='hidden' name='attachments[$attachment_id][menu_order]' value='" . esc_attr( $val['value'] ) . "' />";
			}

			unset( $form_fields['menu_order'] );
			break;
		}
	}

	$media_dims = '';
	$meta       = wp_get_attachment_metadata( $post->ID );

	if ( isset( $meta['width'], $meta['height'] ) ) {
		/* translators: 1: A number of pixels wide, 2: A number of pixels tall. */
		$media_dims .= "<span id='media-dims-$post->ID'>" . sprintf( __( '%1$s by %2$s pixels' ), $meta['width'], $meta['height'] ) . '</span>';
	}

	/**
	 * Filters the media metadata.
	 *
	 * @since 2.5.0
	 *
	 * @param string  $media_dims The HTML markup containing the media dimensions.
	 * @param WP_Post $post       The WP_Post attachment object.
	 */
	$media_dims = apply_filters( 'media_meta', $media_dims, $post );

	$image_edit_button = '';

	if ( wp_attachment_is_image( $post->ID ) && wp_image_editor_supports( array( 'mime_type' => $post->post_mime_type ) ) ) {
		$nonce             = wp_create_nonce( "image_editor-$post->ID" );
		$image_edit_button = "<input type='button' id='imgedit-open-btn-$post->ID' onclick='imageEdit.open( $post->ID, \"$nonce\" )' class='button' value='" . esc_attr__( 'Edit Image' ) . "' /> <span class='spinner'></span>";
	}

	$attachment_url = get_permalink( $attachment_id );

	$item = "
		$type_html
		$toggle_links
		$order
		$display_title
		<table class='slidetoggle describe $class'>
			<thead class='media-item-info' id='media-head-$post->ID'>
			<tr>
			<td class='A1B1' id='thumbnail-head-$post->ID'>
			<p><a href='$attachment_url' target='_blank'><img class='thumbnail' src='$thumb_url' alt='' /></a></p>
			<p>$image_edit_button</p>
			</td>
			<td>
			<p><strong>" . __( 'File name:' ) . "</strong> $filename</p>
			<p><strong>" . __( 'File type:' ) . "</strong> $post->post_mime_type</p>
			<p><strong>" . __( 'Upload date:' ) . '</strong> ' . mysql2date( __( 'F j, Y' ), $post->post_date ) . '</p>';

	if ( ! empty( $media_dims ) ) {
		$item .= '<p><strong>' . __( 'Dimensions:' ) . "</strong> $media_dims</p>\n";
	}

	$item .= "</td></tr>\n";

	$item .= "
		</thead>
		<tbody>
		<tr><td colspan='2' class='imgedit-response' id='imgedit-response-$post->ID'></td></tr>\n
		<tr><td style='display:none' colspan='2' class='image-editor' id='image-editor-$post->ID'></td></tr>\n
		<tr><td colspan='2'><p class='media-types media-types-required-info'>" .
			wp_required_field_message() .
		"</p></td></tr>\n";

	$defaults = array(
		'input'      => 'text',
		'required'   => false,
		'value'      => '',
		'extra_rows' => array(),
	);

	if ( $parsed_args['send'] ) {
		$parsed_args['send'] = get_submit_button( __( 'Insert into Post' ), '', "send[$attachment_id]", false );
	}

	$delete = empty( $parsed_args['delete'] ) ? '' : $parsed_args['delete'];
	if ( $delete && current_user_can( 'delete_post', $attachment_id ) ) {
		if ( ! EMPTY_TRASH_DAYS ) {
			$delete = "<a href='" . wp_nonce_url( "post.php?action=delete&amp;post=$attachment_id", 'delete-post_' . $attachment_id ) . "' id='del[$attachment_id]' class='delete-permanently'>" . __( 'Delete Permanently' ) . '</a>';
		} elseif ( ! MEDIA_TRASH ) {
			$delete = "<a href='#' class='del-link' onclick=\"document.getElementById('del_attachment_$attachment_id').style.display='block';return false;\">" . __( 'Delete' ) . "</a>
				<div id='del_attachment_$attachment_id' class='del-attachment' style='display:none;'>" .
				/* translators: %s: File name. */
				'<p>' . sprintf( __( 'You are about to delete %s.' ), '<strong>' . $filename . '</strong>' ) . "</p>
				<a href='" . wp_nonce_url( "post.php?action=delete&amp;post=$attachment_id", 'delete-post_' . $attachment_id ) . "' id='del[$attachment_id]' class='button'>" . __( 'Continue' ) . "</a>
				<a href='#' class='button' onclick=\"this.parentNode.style.display='none';return false;\">" . __( 'Cancel' ) . '</a>
				</div>';
		} else {
			$delete = "<a href='" . wp_nonce_url( "post.php?action=trash&amp;post=$attachment_id", 'trash-post_' . $attachment_id ) . "' id='del[$attachment_id]' class='delete'>" . __( 'Move to Trash' ) . "</a>
			<a href='" . wp_nonce_url( "post.php?action=untrash&amp;post=$attachment_id", 'untrash-post_' . $attachment_id ) . "' id='undo[$attachment_id]' class='undo hidden'>" . __( 'Undo' ) . '</a>';
		}
	} else {
		$delete = '';
	}

	$thumbnail       = '';
	$calling_post_id = 0;

	if ( isset( $_GET['post_id'] ) ) {
		$calling_post_id = absint( $_GET['post_id'] );
	} elseif ( isset( $_POST ) && count( $_POST ) ) {// Like for async-upload where $_GET['post_id'] isn't set.
		$calling_post_id = $post->post_parent;
	}

	if ( 'image' === $type && $calling_post_id
		&& current_theme_supports( 'post-thumbnails', get_post_type( $calling_post_id ) )
		&& post_type_supports( get_post_type( $calling_post_id ), 'thumbnail' )
		&& get_post_thumbnail_id( $calling_post_id ) !== $attachment_id
	) {

		$calling_post             = get_post( $calling_post_id );
		$calling_post_type_object = get_post_type_object( $calling_post->post_type );

		$ajax_nonce = wp_create_nonce( "set_post_thumbnail-$calling_post_id" );
		$thumbnail  = "<a class='wp-post-thumbnail' id='wp-post-thumbnail-" . $attachment_id . "' href='#' onclick='WPSetAsThumbnail(\"$attachment_id\", \"$ajax_nonce\");return false;'>" . esc_html( $calling_post_type_object->labels->use_featured_image ) . '</a>';
	}

	if ( ( $parsed_args['send'] || $thumbnail || $delete ) && ! isset( $form_fields['buttons'] ) ) {
		$form_fields['buttons'] = array( 'tr' => "\t\t<tr class='submit'><td></td><td class='savesend'>" . $parsed_args['send'] . " $thumbnail $delete</td></tr>\n" );
	}

	$hidden_fields = array();

	foreach ( $form_fields as $id => $field ) {
		if ( '_' === $id[0] ) {
			continue;
		}

		if ( ! empty( $field['tr'] ) ) {
			$item .= $field['tr'];
			continue;
		}

		$field = array_merge( $defaults, $field );
		$name  = "attachments[$attachment_id][$id]";

		if ( 'hidden' === $field['input'] ) {
			$hidden_fields[ $name ] = $field['value'];
			continue;
		}

		$required      = $field['required'] ? ' ' . wp_required_field_indicator() : '';
		$required_attr = $field['required'] ? ' required' : '';
		$class         = $id;
		$class        .= $field['required'] ? ' form-required' : '';

		$item .= "\t\t<tr class='$class'>\n\t\t\t<th scope='row' class='label'><label for='$name'><span class='alignleft'>{$field['label']}{$required}</span><br class='clear' /></label></th>\n\t\t\t<td class='field'>";

		if ( ! empty( $field[ $field['input'] ] ) ) {
			$item .= $field[ $field['input'] ];
		} elseif ( 'textarea' === $field['input'] ) {
			if ( 'post_content' === $id && user_can_richedit() ) {
				// Sanitize_post() skips the post_content when user_can_richedit.
				$field['value'] = htmlspecialchars( $field['value'], ENT_QUOTES );
			}
			// Post_excerpt is already escaped by sanitize_post() in get_attachment_fields_to_edit().
			$item .= "<textarea id='$name' name='$name'{$required_attr}>" . $field['value'] . '</textarea>';
		} else {
			$item .= "<input type='text' class='text' id='$name' name='$name' value='" . esc_attr( $field['value'] ) . "'{$required_attr} />";
		}

		if ( ! empty( $field['helps'] ) ) {
			$item .= "<p class='help'>" . implode( "</p>\n<p class='help'>", array_unique( (array) $field['helps'] ) ) . '</p>';
		}
		$item .= "</td>\n\t\t</tr>\n";

		$extra_rows = array();

		if ( ! empty( $field['errors'] ) ) {
			foreach ( array_unique( (array) $field['errors'] ) as $error ) {
				$extra_rows['error'][] = $error;
			}
		}

		if ( ! empty( $field['extra_rows'] ) ) {
			foreach ( $field['extra_rows'] as $class => $rows ) {
				foreach ( (array) $rows as $html ) {
					$extra_rows[ $class ][] = $html;
				}
			}
		}

		foreach ( $extra_rows as $class => $rows ) {
			foreach ( $rows as $html ) {
				$item .= "\t\t<tr><td></td><td class='$class'>$html</td></tr>\n";
			}
		}
	}

	if ( ! empty( $form_fields['_final'] ) ) {
		$item .= "\t\t<tr class='final'><td colspan='2'>{$form_fields['_final']}</td></tr>\n";
	}

	$item .= "\t</tbody>\n";
	$item .= "\t</table>\n";

	foreach ( $hidden_fields as $name => $value ) {
		$item .= "\t<input type='hidden' name='$name' id='$name' value='" . esc_attr( $value ) . "' />\n";
	}

	if ( $post->post_parent < 1 && isset( $_REQUEST['post_id'] ) ) {
		$parent      = (int) $_REQUEST['post_id'];
		$parent_name = "attachments[$attachment_id][post_parent]";
		$item       .= "\t<input type='hidden' name='$parent_name' id='$parent_name' value='$parent' />\n";
	}

	return $item;
}

/**
 * @since 3.5.0
 *
 * @param int   $attachment_id
 * @param array $args
 * @return array
 */
function get_compat_media_markup( $attachment_id, $args = null ) {
	$post = get_post( $attachment_id );

	$default_args = array(
		'errors'   => null,
		'in_modal' => false,
	);

	$user_can_edit = current_user_can( 'edit_post', $attachment_id );

	$args = wp_parse_args( $args, $default_args );

	/** This filter is documented in wp-admin/includes/media.php */
	$args = apply_filters( 'get_media_item_args', $args );

	$form_fields = array();

	if ( $args['in_modal'] ) {
		foreach ( get_attachment_taxonomies( $post ) as $taxonomy ) {
			$t = (array) get_taxonomy( $taxonomy );

			if ( ! $t['public'] || ! $t['show_ui'] ) {
				continue;
			}

			if ( empty( $t['label'] ) ) {
				$t['label'] = $taxonomy;
			}

			if ( empty( $t['args'] ) ) {
				$t['args'] = array();
			}

			$terms = get_object_term_cache( $post->ID, $taxonomy );

			if ( false === $terms ) {
				$terms = wp_get_object_terms( $post->ID, $taxonomy, $t['args'] );
			}

			$values = array();

			foreach ( $terms as $term ) {
				$values[] = $term->slug;
			}

			$t['value']    = implode( ', ', $values );
			$t['taxonomy'] = true;

			$form_fields[ $taxonomy ] = $t;
		}
	}

	/*
	 * Merge default fields with their errors, so any key passed with the error
	 * (e.g. 'error', 'helps', 'value') will replace the default.
	 * The recursive merge is easily traversed with array casting:
	 * foreach ( (array) $things as $thing )
	 */
	$form_fields = array_merge_recursive( $form_fields, (array) $args['errors'] );

	/** This filter is documented in wp-admin/includes/media.php */
	$form_fields = apply_filters( 'attachment_fields_to_edit', $form_fields, $post );

	unset(
		$form_fields['image-size'],
		$form_fields['align'],
		$form_fields['image_alt'],
		$form_fields['post_title'],
		$form_fields['post_excerpt'],
		$form_fields['post_content'],
		$form_fields['url'],
		$form_fields['menu_order'],
		$form_fields['image_url']
	);

	/** This filter is documented in wp-admin/includes/media.php */
	$media_meta = apply_filters( 'media_meta', '', $post );

	$defaults = array(
		'input'         => 'text',
		'required'      => false,
		'value'         => '',
		'extra_rows'    => array(),
		'show_in_edit'  => true,
		'show_in_modal' => true,
	);

	$hidden_fields = array();

	$item = '';

	foreach ( $form_fields as $id => $field ) {
		if ( '_' === $id[0] ) {
			continue;
		}

		$name    = "attachments[$attachment_id][$id]";
		$id_attr = "attachments-$attachment_id-$id";

		if ( ! empty( $field['tr'] ) ) {
			$item .= $field['tr'];
			continue;
		}

		$field = array_merge( $defaults, $field );

		if ( ( ! $field['show_in_edit'] && ! $args['in_modal'] ) || ( ! $field['show_in_modal'] && $args['in_modal'] ) ) {
			continue;
		}

		if ( 'hidden' === $field['input'] ) {
			$hidden_fields[ $name ] = $field['value'];
			continue;
		}

		$readonly      = ! $user_can_edit && ! empty( $field['taxonomy'] ) ? " readonly='readonly' " : '';
		$required      = $field['required'] ? ' ' . wp_required_field_indicator() : '';
		$required_attr = $field['required'] ? ' required' : '';
		$class         = 'compat-field-' . $id;
		$class        .= $field['required'] ? ' form-required' : '';

		$item .= "\t\t<tr class='$class'>";
		$item .= "\t\t\t<th scope='row' class='label'><label for='$id_attr'><span class='alignleft'>{$field['label']}</span>$required<br class='clear' /></label>";
		$item .= "</th>\n\t\t\t<td class='field'>";

		if ( ! empty( $field[ $field['input'] ] ) ) {
			$item .= $field[ $field['input'] ];
		} elseif ( 'textarea' === $field['input'] ) {
			if ( 'post_content' === $id && user_can_richedit() ) {
				// sanitize_post() skips the post_content when user_can_richedit.
				$field['value'] = htmlspecialchars( $field['value'], ENT_QUOTES );
			}
			$item .= "<textarea id='$id_attr' name='$name'{$required_attr}>" . $field['value'] . '</textarea>';
		} else {
			$item .= "<input type='text' class='text' id='$id_attr' name='$name' value='" . esc_attr( $field['value'] ) . "' $readonly{$required_attr} />";
		}

		if ( ! empty( $field['helps'] ) ) {
			$item .= "<p class='help'>" . implode( "</p>\n<p class='help'>", array_unique( (array) $field['helps'] ) ) . '</p>';
		}

		$item .= "</td>\n\t\t</tr>\n";

		$extra_rows = array();

		if ( ! empty( $field['errors'] ) ) {
			foreach ( array_unique( (array) $field['errors'] ) as $error ) {
				$extra_rows['error'][] = $error;
			}
		}

		if ( ! empty( $field['extra_rows'] ) ) {
			foreach ( $field['extra_rows'] as $class => $rows ) {
				foreach ( (array) $rows as $html ) {
					$extra_rows[ $class ][] = $html;
				}
			}
		}

		foreach ( $extra_rows as $class => $rows ) {
			foreach ( $rows as $html ) {
				$item .= "\t\t<tr><td></td><td class='$class'>$html</td></tr>\n";
			}
		}
	}

	if ( ! empty( $form_fields['_final'] ) ) {
		$item .= "\t\t<tr class='final'><td colspan='2'>{$form_fields['_final']}</td></tr>\n";
	}

	if ( $item ) {
		$item = '<p class="media-types media-types-required-info">' .
			wp_required_field_message() .
			'</p>' .
			'<table class="compat-attachment-fields">' . $item . '</table>';
	}

	foreach ( $hidden_fields as $hidden_field => $value ) {
		$item .= '<input type="hidden" name="' . esc_attr( $hidden_field ) . '" value="' . esc_attr( $value ) . '" />' . "\n";
	}

	if ( $item ) {
		$item = '<input type="hidden" name="attachments[' . $attachment_id . '][menu_order]" value="' . esc_attr( $post->menu_order ) . '" />' . $item;
	}

	return array(
		'item' => $item,
		'meta' => $media_meta,
	);
}

/**
 * Outputs the legacy media upload header.
 *
 * @since 2.5.0
 */
function media_upload_header() {
	$post_id = isset( $_REQUEST['post_id'] ) ? (int) $_REQUEST['post_id'] : 0;

	echo '<script type="text/javascript">post_id = ' . $post_id . ';</script>';

	if ( empty( $_GET['chromeless'] ) ) {
		echo '<div id="media-upload-header">';
		the_media_upload_tabs();
		echo '</div>';
	}
}

/**
 * Outputs the legacy media upload form.
 *
 * @since 2.5.0
 *
 * @global string $type
 * @global string $tab
 *
 * @param array $errors
 */
function media_upload_form( $errors = null ) {
	global $type, $tab;

	if ( ! _device_can_upload() ) {
		echo '<p>' . sprintf(
			/* translators: %s: https://apps.wordpress.org/ */
			__( 'The web browser on your device cannot be used to upload files. You may be able to use the <a href="%s">native app for your device</a> instead.' ),
			'https://apps.wordpress.org/'
		) . '</p>';
		return;
	}

	$upload_action_url = admin_url( 'async-upload.php' );
	$post_id           = isset( $_REQUEST['post_id'] ) ? (int) $_REQUEST['post_id'] : 0;
	$_type             = isset( $type ) ? $type : '';
	$_tab              = isset( $tab ) ? $tab : '';

	$max_upload_size = wp_max_upload_size();
	if ( ! $max_upload_size ) {
		$max_upload_size = 0;
	}

	?>
	<div id="media-upload-notice">
	<?php

	if ( isset( $errors['upload_notice'] ) ) {
		echo $errors['upload_notice'];
	}

	?>
	</div>
	<div id="media-upload-error">
	<?php

	if ( isset( $errors['upload_error'] ) && is_wp_error( $errors['upload_error'] ) ) {
		echo $errors['upload_error']->get_error_message();
	}

	?>
	</div>
	<?php

	if ( is_multisite() && ! is_upload_space_available() ) {
		/**
		 * Fires when an upload will exceed the defined upload space quota for a network site.
		 *
		 * @since 3.5.0
		 */
		do_action( 'upload_ui_over_quota' );
		return;
	}

	/**
	 * Fires just before the legacy (pre-3.5.0) upload interface is loaded.
	 *
	 * @since 2.6.0
	 */
	do_action( 'pre-upload-ui' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores

	$post_params = array(
		'post_id'  => $post_id,
		'_wpnonce' => wp_create_nonce( 'media-form' ),
		'type'     => $_type,
		'tab'      => $_tab,
		'short'    => '1',
	);

	/**
	 * Filters the media upload post parameters.
	 *
	 * @since 3.1.0 As 'swfupload_post_params'
	 * @since 3.3.0
	 *
	 * @param array $post_params An array of media upload parameters used by Plupload.
	 */
	$post_params = apply_filters( 'upload_post_params', $post_params );

	/*
	* Since 4.9 the `runtimes` setting is hardcoded in our version of Plupload to `html5,html4`,
	* and the `flash_swf_url` and `silverlight_xap_url` are not used.
	*/
	$plupload_init = array(
		'browse_button'    => 'plupload-browse-button',
		'container'        => 'plupload-upload-ui',
		'drop_element'     => 'drag-drop-area',
		'file_data_name'   => 'async-upload',
		'url'              => $upload_action_url,
		'filters'          => array( 'max_file_size' => $max_upload_size . 'b' ),
		'multipart_params' => $post_params,
	);

	/*
	 * Currently only iOS Safari supports multiple files uploading,
	 * but iOS 7.x has a bug that prevents uploading of videos when enabled.
	 * See #29602.
	 */
	if (
		wp_is_mobile() &&
		str_contains( $_SERVER['HTTP_USER_AGENT'], 'OS 7_' ) &&
		str_contains( $_SERVER['HTTP_USER_AGENT'], 'like Mac OS X' )
	) {
		$plupload_init['multi_selection'] = false;
	}

	/** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php */
	$prevent_unsupported_uploads = apply_filters( 'wp_prevent_unsupported_mime_type_uploads', true, null );

	if ( $prevent_unsupported_uploads ) {
		// Check if WebP images can be edited.
		if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/webp' ) ) ) {
			$plupload_init['webp_upload_error'] = true;
		}

		// Check if AVIF images can be edited.
		if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/avif' ) ) ) {
			$plupload_init['avif_upload_error'] = true;
		}
	}

	/**
	 * Filters the default Plupload settings.
	 *
	 * @since 3.3.0
	 *
	 * @param array $plupload_init An array of default settings used by Plupload.
	 */
	$plupload_init = apply_filters( 'plupload_init', $plupload_init );

	?>
	<script type="text/javascript">
	<?php
	// Verify size is an int. If not return default value.
	$large_size_h = absint( get_option( 'large_size_h' ) );

	if ( ! $large_size_h ) {
		$large_size_h = 1024;
	}

	$large_size_w = absint( get_option( 'large_size_w' ) );

	if ( ! $large_size_w ) {
		$large_size_w = 1024;
	}

	?>
	var resize_height = <?php echo $large_size_h; ?>, resize_width = <?php echo $large_size_w; ?>,
	wpUploaderInit = <?php echo wp_json_encode( $plupload_init, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ); ?>;
	</script>

	<div id="plupload-upload-ui" class="hide-if-no-js">
	<?php
	/**
	 * Fires before the upload interface loads.
	 *
	 * @since 2.6.0 As 'pre-flash-upload-ui'
	 * @since 3.3.0
	 */
	do_action( 'pre-plupload-upload-ui' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores

	?>
	<div id="drag-drop-area">
		<div class="drag-drop-inside">
		<p class="drag-drop-info"><?php _e( 'Drop files to upload' ); ?></p>
		<p><?php _ex( 'or', 'Uploader: Drop files here - or - Select Files' ); ?></p>
		<p class="drag-drop-buttons"><input id="plupload-browse-button" type="button" value="<?php esc_attr_e( 'Select Files' ); ?>" class="button" /></p>
		</div>
	</div>
	<?php
	/**
	 * Fires after the upload interface loads.
	 *
	 * @since 2.6.0 As 'post-flash-upload-ui'
	 * @since 3.3.0
	 */
	do_action( 'post-plupload-upload-ui' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
	?>
	</div>

	<div id="html-upload-ui" class="hide-if-js">
	<?php
	/**
	 * Fires before the upload button in the media upload interface.
	 *
	 * @since 2.6.0
	 */
	do_action( 'pre-html-upload-ui' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores

	?>
	<p id="async-upload-wrap">
		<label class="screen-reader-text" for="async-upload">
			<?php
			/* translators: Hidden accessibility text. */
			_ex( 'Upload', 'verb' );
			?>
		</label>
		<input type="file" name="async-upload" id="async-upload" />
		<?php submit_button( _x( 'Upload', 'verb' ), 'primary', 'html-upload', false ); ?>
		<a href="#" onclick="try{top.tb_remove();}catch(e){}; return false;"><?php _e( 'Cancel' ); ?></a>
	</p>
	<div class="clear"></div>
	<?php
	/**
	 * Fires after the upload button in the media upload interface.
	 *
	 * @since 2.6.0
	 */
	do_action( 'post-html-upload-ui' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores

	?>
	</div>

<p class="max-upload-size">
	<?php
	/* translators: %s: Maximum allowed file size. */
	printf( __( 'Maximum upload file size: %s.' ), esc_html( size_format( $max_upload_size ) ) );
	?>
</p>
	<?php

	/**
	 * Fires on the post upload UI screen.
	 *
	 * Legacy (pre-3.5.0) media workflow hook.
	 *
	 * @since 2.6.0
	 */
	do_action( 'post-upload-ui' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
}

/**
 * Outputs the legacy media upload form for a given media type.
 *
 * @since 2.5.0
 *
 * @param string       $type
 * @param array        $errors
 * @param int|WP_Error $id
 */
function media_upload_type_form( $type = 'file', $errors = null, $id = null ) {

	media_upload_header();

	$post_id = isset( $_REQUEST['post_id'] ) ? (int) $_REQUEST['post_id'] : 0;

	$form_action_url = admin_url( "media-upload.php?type=$type&tab=type&post_id=$post_id" );

	/**
	 * Filters the media upload form action URL.
	 *
	 * @since 2.6.0
	 *
	 * @param string $form_action_url The media upload form action URL.
	 * @param string $type            The type of media. Default 'file'.
	 */
	$form_action_url = apply_filters( 'media_upload_form_url', $form_action_url, $type );
	$form_class      = 'media-upload-form type-form validate';

	if ( get_user_setting( 'uploader' ) ) {
		$form_class .= ' html-uploader';
	}

	?>
	<form enctype="multipart/form-data" method="post" action="<?php echo esc_url( $form_action_url ); ?>" class="<?php echo $form_class; ?>" id="<?php echo $type; ?>-form">
		<?php submit_button( '', 'hidden', 'save', false ); ?>
	<input type="hidden" name="post_id" id="post_id" value="<?php echo (int) $post_id; ?>" />
		<?php wp_nonce_field( 'media-form' ); ?>

	<h3 class="media-title"><?php _e( 'Add media files from your computer' ); ?></h3>

	<?php media_upload_form( $errors ); ?>

	<script type="text/javascript">
	jQuery(function($){
		var preloaded = $(".media-item.preloaded");
		if ( preloaded.length > 0 ) {
			preloaded.each(function(){prepareMediaItem({id:this.id.replace(/[^0-9]/g, '')},'');});
		}
		updateMediaForm();
	});
	</script>
	<div id="media-items">
	<?php

	if ( $id ) {
		if ( ! is_wp_error( $id ) ) {
			add_filter( 'attachment_fields_to_edit', 'media_post_single_attachment_fields_to_edit', 10, 2 );
			echo get_media_items( $id, $errors );
		} else {
			echo '<div id="media-upload-error">' . esc_html( $id->get_error_message() ) . '</div></div>';
			exit;
		}
	}

	?>
	</div>

	<p class="savebutton ml-submit">
		<?php submit_button( __( 'Save all changes' ), '', 'save', false ); ?>
	</p>
	</form>
	<?php
}

/**
 * Outputs the legacy media upload form for external media.
 *
 * @since 2.7.0
 *
 * @param string  $type
 * @param object  $errors
 * @param int     $id
 */
function media_upload_type_url_form( $type = null, $errors = null, $id = null ) {
	if ( null === $type ) {
		$type = 'image';
	}

	media_upload_header();

	$post_id = isset( $_REQUEST['post_id'] ) ? (int) $_REQUEST['post_id'] : 0;

	$form_action_url = admin_url( "media-upload.php?type=$type&tab=type&post_id=$post_id" );
	/** This filter is documented in wp-admin/includes/media.php */
	$form_action_url = apply_filters( 'media_upload_form_url', $form_action_url, $type );
	$form_class      = 'media-upload-form type-form validate';

	if ( get_user_setting( 'uploader' ) ) {
		$form_class .= ' html-uploader';
	}

	?>
	<form enctype="multipart/form-data" method="post" action="<?php echo esc_url( $form_action_url ); ?>" class="<?php echo $form_class; ?>" id="<?php echo $type; ?>-form">
	<input type="hidden" name="post_id" id="post_id" value="<?php echo (int) $post_id; ?>" />
		<?php wp_nonce_field( 'media-form' ); ?>

	<h3 class="media-title"><?php _e( 'Insert media from another website' ); ?></h3>

	<script type="text/javascript">
	var addExtImage = {

	width : '',
	height : '',
	align : 'alignnone',

	insert : function() {
		var t = this, html, f = document.forms[0], cls, title = '', alt = '', caption = '';

		if ( '' === f.src.value || '' === t.width )
			return false;

		if ( f.alt.value )
			alt = f.alt.value.replace(/'/g, '&#039;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');

		<?php
		/** This filter is documented in wp-admin/includes/media.php */
		if ( ! apply_filters( 'disable_captions', '' ) ) {
			?>
			if ( f.caption.value ) {
				caption = f.caption.value.replace(/\r\n|\r/g, '\n');
				caption = caption.replace(/<[a-zA-Z0-9]+( [^<>]+)?>/g, function(a){
					return a.replace(/[\r\n\t]+/, ' ');
				});

				caption = caption.replace(/\s*\n\s*/g, '<br />');
			}
			<?php
		}

		?>
		cls = caption ? '' : ' class="'+t.align+'"';

		html = '<img alt="'+alt+'" src="'+f.src.value+'"'+cls+' width="'+t.width+'" height="'+t.height+'" />';

		if ( f.url.value ) {
			url = f.url.value.replace(/'/g, '&#039;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
			html = '<a href="'+url+'">'+html+'</a>';
		}

		if ( caption )
			html = '[caption id="" align="'+t.align+'" width="'+t.width+'"]'+html+caption+'[/caption]';

		var win = window.dialogArguments || opener || parent || top;
		win.send_to_editor(html);
		return false;
	},

	resetImageData : function() {
		var t = addExtImage;

		t.width = t.height = '';
		document.getElementById('go_button').style.color = '#bbb';
		if ( ! document.forms[0].src.value )
			document.getElementById('status_img').innerHTML = '';
		else document.getElementById('status_img').innerHTML = '<img src="<?php echo esc_url( admin_url( 'images/no.png' ) ); ?>" alt="" />';
	},

	updateImageData : function() {
		var t = addExtImage;

		t.width = t.preloadImg.width;
		t.height = t.preloadImg.height;
		document.getElementById('go_button').style.color = '#333';
		document.getElementById('status_img').innerHTML = '<img src="<?php echo esc_url( admin_url( 'images/yes.png' ) ); ?>" alt="" />';
	},

	getImageData : function() {
		if ( jQuery('table.describe').hasClass('not-image') )
			return;

		var t = addExtImage, src = document.forms[0].src.value;

		if ( ! src ) {
			t.resetImageData();
			return false;
		}

		document.getElementById('status_img').innerHTML = '<img src="<?php echo esc_url( admin_url( 'images/spinner-2x.gif' ) ); ?>" alt="" width="16" height="16" />';
		t.preloadImg = new Image();
		t.preloadImg.onload = t.updateImageData;
		t.preloadImg.onerror = t.resetImageData;
		t.preloadImg.src = src;
	}
	};

	jQuery( function($) {
		$('.media-types input').click( function() {
			$('table.describe').toggleClass('not-image', $('#not-image').prop('checked') );
		});
	} );
	</script>

	<div id="media-items">
	<div class="media-item media-blank">
	<?php
	/**
	 * Filters the insert media from URL form HTML.
	 *
	 * @since 3.3.0
	 *
	 * @param string $form_html The insert from URL form HTML.
	 */
	echo apply_filters( 'type_url_form_media', wp_media_insert_url_form( $type ) );

	?>
	</div>
	</div>
	</form>
	<?php
}

/**
 * Adds gallery form to upload iframe.
 *
 * @since 2.5.0
 *
 * @global string $redir_tab
 * @global string $type
 * @global string $tab
 *
 * @param array $errors
 */
function media_upload_gallery_form( $errors ) {
	global $redir_tab, $type;

	$redir_tab = 'gallery';
	media_upload_header();

	$post_id         = (int) $_REQUEST['post_id'];
	$form_action_url = admin_url( "media-upload.php?type=$type&tab=gallery&post_id=$post_id" );
	/** This filter is documented in wp-admin/includes/media.php */
	$form_action_url = apply_filters( 'media_upload_form_url', $form_action_url, $type );
	$form_class      = 'media-upload-form validate';

	if ( get_user_setting( 'uploader' ) ) {
		$form_class .= ' html-uploader';
	}

	?>
	<script type="text/javascript">
	jQuery(function($){
		var preloaded = $(".media-item.preloaded");
		if ( preloaded.length > 0 ) {
			preloaded.each(function(){prepareMediaItem({id:this.id.replace(/[^0-9]/g, '')},'');});
			updateMediaForm();
		}
	});
	</script>
	<div id="sort-buttons" class="hide-if-no-js">
	<span>
		<?php _e( 'All Tabs:' ); ?>
	<a href="#" id="showall"><?php _e( 'Show' ); ?></a>
	<a href="#" id="hideall" style="display:none;"><?php _e( 'Hide' ); ?></a>
	</span>
		<?php _e( 'Sort Order:' ); ?>
	<a href="#" id="asc"><?php _e( 'Ascending' ); ?></a> |
	<a href="#" id="desc"><?php _e( 'Descending' ); ?></a> |
	<a href="#" id="clear"><?php _ex( 'Clear', 'verb' ); ?></a>
	</div>
	<form enctype="multipart/form-data" method="post" action="<?php echo esc_url( $form_action_url ); ?>" class="<?php echo $form_class; ?>" id="gallery-form">
		<?php wp_nonce_field( 'media-form' ); ?>
	<table class="widefat">
	<thead><tr>
	<th><?php _e( 'Media' ); ?></th>
	<th class="order-head"><?php _e( 'Order' ); ?></th>
	<th class="actions-head"><?php _e( 'Actions' ); ?></th>
	</tr></thead>
	</table>
	<div id="media-items">
		<?php add_filter( 'attachment_fields_to_edit', 'media_post_single_attachment_fields_to_edit', 10, 2 ); ?>
		<?php echo get_media_items( $post_id, $errors ); ?>
	</div>

	<p class="ml-submit">
		<?php
		submit_button(
			__( 'Save all changes' ),
			'savebutton',
			'save',
			false,
			array(
				'id'    => 'save-all',
				'style' => 'display: none;',
			)
		);
		?>
	<input type="hidden" name="post_id" id="post_id" value="<?php echo (int) $post_id; ?>" />
	<input type="hidden" name="type" value="<?php echo esc_attr( $GLOBALS['type'] ); ?>" />
	<input type="hidden" name="tab" value="<?php echo esc_attr( $GLOBALS['tab'] ); ?>" />
	</p>

	<div id="gallery-settings" style="display:none;">
	<div class="title"><?php _e( 'Gallery Settings' ); ?></div>
	<table id="basic" class="describe"><tbody>
		<tr>
		<th scope="row" class="label">
			<label>
			<span class="alignleft"><?php _e( 'Link thumbnails to:' ); ?></span>
			</label>
		</th>
		<td class="field">
			<input type="radio" name="linkto" id="linkto-file" value="file" />
			<label for="linkto-file" class="radio"><?php _e( 'Image File' ); ?></label>

			<input type="radio" checked="checked" name="linkto" id="linkto-post" value="post" />
			<label for="linkto-post" class="radio"><?php _e( 'Attachment Page' ); ?></label>
		</td>
		</tr>

		<tr>
		<th scope="row" class="label">
			<label>
			<span class="alignleft"><?php _e( 'Order images by:' ); ?></span>
			</label>
		</th>
		<td class="field">
			<select id="orderby" name="orderby">
				<option value="menu_order" selected="selected"><?php _e( 'Menu order' ); ?></option>
				<option value="title"><?php _e( 'Title' ); ?></option>
				<option value="post_date"><?php _e( 'Date/Time' ); ?></option>
				<option value="rand"><?php _e( 'Random' ); ?></option>
			</select>
		</td>
		</tr>

		<tr>
		<th scope="row" class="label">
			<label>
			<span class="alignleft"><?php _e( 'Order:' ); ?></span>
			</label>
		</th>
		<td class="field">
			<input type="radio" checked="checked" name="order" id="order-asc" value="asc" />
			<label for="order-asc" class="radio"><?php _e( 'Ascending' ); ?></label>

			<input type="radio" name="order" id="order-desc" value="desc" />
			<label for="order-desc" class="radio"><?php _e( 'Descending' ); ?></label>
		</td>
		</tr>

		<tr>
		<th scope="row" class="label">
			<label>
			<span class="alignleft"><?php _e( 'Gallery columns:' ); ?></span>
			</label>
		</th>
		<td class="field">
			<select id="columns" name="columns">
				<option value="1">1</option>
				<option value="2">2</option>
				<option value="3" selected="selected">3</option>
				<option value="4">4</option>
				<option value="5">5</option>
				<option value="6">6</option>
				<option value="7">7</option>
				<option value="8">8</option>
				<option value="9">9</option>
			</select>
		</td>
		</tr>
	</tbody></table>

	<p class="ml-submit">
	<input type="button" class="button" style="display:none;" onMouseDown="wpgallery.update();" name="insert-gallery" id="insert-gallery" value="<?php esc_attr_e( 'Insert gallery' ); ?>" />
	<input type="button" class="button" style="display:none;" onMouseDown="wpgallery.update();" name="update-gallery" id="update-gallery" value="<?php esc_attr_e( 'Update gallery settings' ); ?>" />
	</p>
	</div>
	</form>
	<?php
}

/**
 * Outputs the legacy media upload form for the media library.
 *
 * @since 2.5.0
 *
 * @global wpdb      $wpdb            WordPress database abstraction object.
 * @global WP_Query  $wp_query        WordPress Query object.
 * @global WP_Locale $wp_locale       WordPress date and time locale object.
 * @global string    $type
 * @global string    $tab
 * @global array     $post_mime_types
 *
 * @param array $errors
 */
function media_upload_library_form( $errors ) {
	global $wpdb, $wp_query, $wp_locale, $type, $tab, $post_mime_types;

	media_upload_header();

	$post_id = isset( $_REQUEST['post_id'] ) ? (int) $_REQUEST['post_id'] : 0;

	$form_action_url = admin_url( "media-upload.php?type=$type&tab=library&post_id=$post_id" );
	/** This filter is documented in wp-admin/includes/media.php */
	$form_action_url = apply_filters( 'media_upload_form_url', $form_action_url, $type );
	$form_class      = 'media-upload-form validate';

	if ( get_user_setting( 'uploader' ) ) {
		$form_class .= ' html-uploader';
	}

	$q                   = $_GET;
	$q['posts_per_page'] = 10;
	$q['paged']          = isset( $q['paged'] ) ? (int) $q['paged'] : 0;
	if ( $q['paged'] < 1 ) {
		$q['paged'] = 1;
	}
	$q['offset'] = ( $q['paged'] - 1 ) * 10;
	if ( $q['offset'] < 1 ) {
		$q['offset'] = 0;
	}

	list($post_mime_types, $avail_post_mime_types) = wp_edit_attachments_query( $q );

	?>
	<form id="filter" method="get">
	<input type="hidden" name="type" value="<?php echo esc_attr( $type ); ?>" />
	<input type="hidden" name="tab" value="<?php echo esc_attr( $tab ); ?>" />
	<input type="hidden" name="post_id" value="<?php echo (int) $post_id; ?>" />
	<input type="hidden" name="post_mime_type" value="<?php echo isset( $_GET['post_mime_type'] ) ? esc_attr( $_GET['post_mime_type'] ) : ''; ?>" />
	<input type="hidden" name="context" value="<?php echo isset( $_GET['context'] ) ? esc_attr( $_GET['context'] ) : ''; ?>" />

	<p id="media-search" class="search-box">
		<label class="screen-reader-text" for="media-search-input">
			<?php
			/* translators: Hidden accessibility text. */
			_e( 'Search Media:' );
			?>
		</label>
		<input type="search" id="media-search-input" name="s" value="<?php the_search_query(); ?>" />
		<?php submit_button( __( 'Search Media' ), '', '', false ); ?>
	</p>

	<ul class="subsubsub">
		<?php
		$type_links = array();
		$_num_posts = (array) wp_count_attachments();
		$matches    = wp_match_mime_types( array_keys( $post_mime_types ), array_keys( $_num_posts ) );
		foreach ( $matches as $_type => $reals ) {
			foreach ( $reals as $real ) {
				if ( isset( $num_posts[ $_type ] ) ) {
					$num_posts[ $_type ] += $_num_posts[ $real ];
				} else {
					$num_posts[ $_type ] = $_num_posts[ $real ];
				}
			}
		}
		// If available type specified by media button clicked, filter by that type.
		if ( empty( $_GET['post_mime_type'] ) && ! empty( $num_posts[ $type ] ) ) {
			$_GET['post_mime_type']                        = $type;
			list($post_mime_types, $avail_post_mime_types) = wp_edit_attachments_query();
		}
		if ( empty( $_GET['post_mime_type'] ) || 'all' === $_GET['post_mime_type'] ) {
			$class = ' class="current"';
		} else {
			$class = '';
		}
		$type_links[] = '<li><a href="' . esc_url(
			add_query_arg(
				array(
					'post_mime_type' => 'all',
					'paged'          => false,
					'm'              => false,
				)
			)
		) . '"' . $class . '>' . __( 'All Types' ) . '</a>';
		foreach ( $post_mime_types as $mime_type => $label ) {
			$class = '';

			if ( ! wp_match_mime_types( $mime_type, $avail_post_mime_types ) ) {
				continue;
			}

			if ( isset( $_GET['post_mime_type'] ) && wp_match_mime_types( $mime_type, $_GET['post_mime_type'] ) ) {
				$class = ' class="current"';
			}

			$type_links[] = '<li><a href="' . esc_url(
				add_query_arg(
					array(
						'post_mime_type' => $mime_type,
						'paged'          => false,
					)
				)
			) . '"' . $class . '>' . sprintf( translate_nooped_plural( $label[2], $num_posts[ $mime_type ] ), '<span id="' . $mime_type . '-counter">' . number_format_i18n( $num_posts[ $mime_type ] ) . '</span>' ) . '</a>';
		}
		/**
		 * Filters the media upload mime type list items.
		 *
		 * Returned values should begin with an `<li>` tag.
		 *
		 * @since 3.1.0
		 *
		 * @param string[] $type_links An array of list items containing mime type link HTML.
		 */
		echo implode( ' | </li>', apply_filters( 'media_upload_mime_type_links', $type_links ) ) . '</li>';
		unset( $type_links );
		?>
	</ul>

	<div class="tablenav">

		<?php
		$page_links = paginate_links(
			array(
				'base'      => add_query_arg( 'paged', '%#%' ),
				'format'    => '',
				'prev_text' => __( '&laquo;' ),
				'next_text' => __( '&raquo;' ),
				'total'     => (int) ceil( $wp_query->found_posts / 10 ),
				'current'   => $q['paged'],
			)
		);

		if ( $page_links ) {
			echo "<div class='tablenav-pages'>$page_links</div>";
		}
		?>

	<div class="alignleft actions">
		<?php
		$months = $wpdb->get_results(
			"SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month
			FROM $wpdb->posts
			WHERE post_type = 'attachment'
			ORDER BY post_date DESC"
		);

		$month_count    = count( $months );
		$selected_month = isset( $_GET['m'] ) ? (int) $_GET['m'] : 0;

		if ( $month_count && ( 1 !== $month_count || 0 !== (int) $months[0]->month ) ) {
			?>
			<select name='m'>
				<option<?php selected( $selected_month, 0 ); ?> value='0'><?php _e( 'All dates' ); ?></option>
			<?php
			foreach ( $months as $arc_row ) {
				if ( 0 === (int) $arc_row->year ) {
					continue;
				}

				$month = zeroise( $arc_row->month, 2 );
				$year  = $arc_row->year;

				printf(
					"<option %s value='%s'>%s</option>\n",
					selected( $selected_month, $year . $month, false ),
					esc_attr( $year . $month ),
					/* translators: 1: Month name, 2: 4-digit year. */
					esc_html( sprintf( __( '%1$s %2$d' ), $wp_locale->get_month( $month ), $year ) )
				);
			}
			?>
			</select>
		<?php } ?>

		<?php submit_button( __( 'Filter &#187;' ), '', 'post-query-submit', false ); ?>

	</div>

	<br class="clear" />
	</div>
	</form>

	<form enctype="multipart/form-data" method="post" action="<?php echo esc_url( $form_action_url ); ?>" class="<?php echo $form_class; ?>" id="library-form">
	<?php wp_nonce_field( 'media-form' ); ?>

	<script type="text/javascript">
	jQuery(function($){
		var preloaded = $(".media-item.preloaded");
		if ( preloaded.length > 0 ) {
			preloaded.each(function(){prepareMediaItem({id:this.id.replace(/[^0-9]/g, '')},'');});
			updateMediaForm();
		}
	});
	</script>

	<div id="media-items">
		<?php add_filter( 'attachment_fields_to_edit', 'media_post_single_attachment_fields_to_edit', 10, 2 ); ?>
		<?php echo get_media_items( null, $errors ); ?>
	</div>
	<p class="ml-submit">
		<?php submit_button( __( 'Save all changes' ), 'savebutton', 'save', false ); ?>
	<input type="hidden" name="post_id" id="post_id" value="<?php echo (int) $post_id; ?>" />
	</p>
	</form>
	<?php
}

/**
 * Creates the form for external url.
 *
 * @since 2.7.0
 *
 * @param string $default_view
 * @return string HTML content of the form.
 */
function wp_media_insert_url_form( $default_view = 'image' ) {
	/** This filter is documented in wp-admin/includes/media.php */
	if ( ! apply_filters( 'disable_captions', '' ) ) {
		$caption = '
		<tr class="image-only">
			<th scope="row" class="label">
				<label for="caption"><span class="alignleft">' . __( 'Image Caption' ) . '</span></label>
			</th>
			<td class="field"><textarea id="caption" name="caption"></textarea></td>
		</tr>';
	} else {
		$caption = '';
	}

	$default_align = get_option( 'image_default_align' );

	if ( empty( $default_align ) ) {
		$default_align = 'none';
	}

	if ( 'image' === $default_view ) {
		$view        = 'image-only';
		$table_class = '';
	} else {
		$view        = 'not-image';
		$table_class = $view;
	}

	return '
	<p class="media-types"><label><input type="radio" name="media_type" value="image" id="image-only"' . checked( 'image-only', $view, false ) . ' /> ' . __( 'Image' ) . '</label> &nbsp; &nbsp; <label><input type="radio" name="media_type" value="generic" id="not-image"' . checked( 'not-image', $view, false ) . ' /> ' . __( 'Audio, Video, or Other File' ) . '</label></p>
	<p class="media-types media-types-required-info">' .
		wp_required_field_message() .
	'</p>
	<table class="describe ' . $table_class . '"><tbody>
		<tr>
			<th scope="row" class="label" style="width:130px;">
				<label for="src"><span class="alignleft">' . __( 'URL' ) . '</span> ' . wp_required_field_indicator() . '</label>
				<span class="alignright" id="status_img"></span>
			</th>
			<td class="field"><input id="src" name="src" value="" type="text" required onblur="addExtImage.getImageData()" /></td>
		</tr>

		<tr>
			<th scope="row" class="label">
				<label for="title"><span class="alignleft">' . __( 'Title' ) . '</span> ' . wp_required_field_indicator() . '</label>
			</th>
			<td class="field"><input id="title" name="title" value="" type="text" required /></td>
		</tr>

		<tr class="not-image"><td></td><td><p class="help">' . __( 'Link text, e.g. &#8220;Ransom Demands (PDF)&#8221;' ) . '</p></td></tr>

		<tr class="image-only">
			<th scope="row" class="label">
				<label for="alt"><span class="alignleft">' . __( 'Alternative Text' ) . '</span> ' . wp_required_field_indicator() . '</label>
			</th>
			<td class="field"><input id="alt" name="alt" value="" type="text" required />
			<p class="help">' . __( 'Alt text for the image, e.g. &#8220;The Mona Lisa&#8221;' ) . '</p></td>
		</tr>
		' . $caption . '
		<tr class="align image-only">
			<th scope="row" class="label"><p><label for="align">' . __( 'Alignment' ) . '</label></p></th>
			<td class="field">
				<input name="align" id="align-none" value="none" onclick="addExtImage.align=\'align\'+this.value" type="radio"' . ( 'none' === $default_align ? ' checked="checked"' : '' ) . ' />
				<label for="align-none" class="align image-align-none-label">' . __( 'None' ) . '</label>
				<input name="align" id="align-left" value="left" onclick="addExtImage.align=\'align\'+this.value" type="radio"' . ( 'left' === $default_align ? ' checked="checked"' : '' ) . ' />
				<label for="align-left" class="align image-align-left-label">' . __( 'Left' ) . '</label>
				<input name="align" id="align-center" value="center" onclick="addExtImage.align=\'align\'+this.value" type="radio"' . ( 'center' === $default_align ? ' checked="checked"' : '' ) . ' />
				<label for="align-center" class="align image-align-center-label">' . __( 'Center' ) . '</label>
				<input name="align" id="align-right" value="right" onclick="addExtImage.align=\'align\'+this.value" type="radio"' . ( 'right' === $default_align ? ' checked="checked"' : '' ) . ' />
				<label for="align-right" class="align image-align-right-label">' . __( 'Right' ) . '</label>
			</td>
		</tr>

		<tr class="image-only">
			<th scope="row" class="label">
				<label for="url"><span class="alignleft">' . __( 'Link Image To:' ) . '</span></label>
			</th>
			<td class="field"><input id="url" name="url" value="" type="text" /><br />

			<button type="button" class="button" value="" onclick="document.forms[0].url.value=null">' . __( 'None' ) . '</button>
			<button type="button" class="button" value="" onclick="document.forms[0].url.value=document.forms[0].src.value">' . __( 'Link to image' ) . '</button>
			<p class="help">' . __( 'Enter a link URL or click above for presets.' ) . '</p></td>
		</tr>
		<tr class="image-only">
			<td></td>
			<td>
				<input type="button" class="button" id="go_button" style="color:#bbb;" onclick="addExtImage.insert()" value="' . esc_attr__( 'Insert into Post' ) . '" />
			</td>
		</tr>
		<tr class="not-image">
			<td></td>
			<td>
				' . get_submit_button( __( 'Insert into Post' ), '', 'insertonlybutton', false ) . '
			</td>
		</tr>
	</tbody></table>';
}

/**
 * Displays the multi-file uploader message.
 *
 * @since 2.6.0
 */
function media_upload_flash_bypass() {
	?>
	<p class="upload-flash-bypass">
	<?php
		printf(
			/* translators: %s: HTML attributes for button. */
			__( 'You are using the multi-file uploader. Problems? Try the <button %s>browser uploader</button> instead.' ),
			'type="button" class="button-link"'
		);
	?>
	</p>
	<?php
}

/**
 * Displays the browser's built-in uploader message.
 *
 * @since 2.6.0
 */
function media_upload_html_bypass() {
	?>
	<p class="upload-html-bypass hide-if-no-js">
	<?php
		printf(
			/* translators: %s: HTML attributes for button. */
			__( 'You are using the browser&#8217;s built-in file uploader. The WordPress uploader includes multiple file selection and drag and drop capability. <button %s>Switch to the multi-file uploader</button>.' ),
			'type="button" class="button-link"'
		);
	?>
	</p>
	<?php
}

/**
 * Used to display a "After a file has been uploaded..." help message.
 *
 * @since 3.3.0
 */
function media_upload_text_after() {}

/**
 * Displays the checkbox to scale images.
 *
 * @since 3.3.0
 */
function media_upload_max_image_resize() {
	$checked = get_user_setting( 'upload_resize' ) ? ' checked="true"' : '';
	$a       = '';
	$end     = '';

	if ( current_user_can( 'manage_options' ) ) {
		$a   = '<a href="' . esc_url( admin_url( 'options-media.php' ) ) . '" target="_blank">';
		$end = '</a>';
	}

	?>
	<p class="hide-if-no-js"><label>
	<input name="image_resize" type="checkbox" id="image_resize" value="true"<?php echo $checked; ?> />
	<?php
	/* translators: 1: Link start tag, 2: Link end tag, 3: Width, 4: Height. */
	printf( __( 'Scale images to match the large size selected in %1$simage options%2$s (%3$d &times; %4$d).' ), $a, $end, (int) get_option( 'large_size_w', '1024' ), (int) get_option( 'large_size_h', '1024' ) );

	?>
	</label></p>
	<?php
}

/**
 * Displays the out of storage quota message in Multisite.
 *
 * @since 3.5.0
 */
function multisite_over_quota_message() {
	echo '<p>' . sprintf(
		/* translators: %s: Allowed space allocation. */
		__( 'Sorry, you have used your space allocation of %s. Please delete some files to upload more files.' ),
		size_format( get_space_allowed() * MB_IN_BYTES )
	) . '</p>';
}

/**
 * Displays the image and editor in the post editor
 *
 * @since 3.5.0
 *
 * @param WP_Post $post A post object.
 */
function edit_form_image_editor( $post ) {
	$open = isset( $_GET['image-editor'] );

	if ( $open ) {
		require_once ABSPATH . 'wp-admin/includes/image-edit.php';
	}

	$thumb_url     = false;
	$attachment_id = (int) $post->ID;

	if ( $attachment_id ) {
		$thumb_url = wp_get_attachment_image_src( $attachment_id, array( 900, 450 ), true );
	}

	$alt_text = get_post_meta( $post->ID, '_wp_attachment_image_alt', true );

	$att_url = wp_get_attachment_url( $post->ID );
	?>
	<div class="wp_attachment_holder wp-clearfix">
	<?php

	if ( wp_attachment_is_image( $post->ID ) ) :
		$image_edit_button = '';
		if ( wp_image_editor_supports( array( 'mime_type' => $post->post_mime_type ) ) ) {
			$nonce             = wp_create_nonce( "image_editor-$post->ID" );
			$image_edit_button = "<input type='button' id='imgedit-open-btn-$post->ID' onclick='imageEdit.open( $post->ID, \"$nonce\" )' class='button' value='" . esc_attr__( 'Edit Image' ) . "' /> <span class='spinner'></span>";
		}

		$open_style     = '';
		$not_open_style = '';

		if ( $open ) {
			$open_style = ' style="display:none"';
		} else {
			$not_open_style = ' style="display:none"';
		}

		?>
		<div class="imgedit-response" id="imgedit-response-<?php echo $attachment_id; ?>"></div>

		<div<?php echo $open_style; ?> class="wp_attachment_image wp-clearfix" id="media-head-<?php echo $attachment_id; ?>">
			<p id="thumbnail-head-<?php echo $attachment_id; ?>"><img class="thumbnail" src="<?php echo set_url_scheme( $thumb_url[0] ); ?>" style="max-width:100%" alt="" /></p>
			<p><?php echo $image_edit_button; ?></p>
		</div>
		<div<?php echo $not_open_style; ?> class="image-editor" id="image-editor-<?php echo $attachment_id; ?>">
		<?php

		if ( $open ) {
			wp_image_editor( $attachment_id );
		}

		?>
		</div>
		<?php
	elseif ( $attachment_id && wp_attachment_is( 'audio', $post ) ) :

		wp_maybe_generate_attachment_metadata( $post );

		echo wp_audio_shortcode( array( 'src' => $att_url ) );

	elseif ( $attachment_id && wp_attachment_is( 'video', $post ) ) :

		wp_maybe_generate_attachment_metadata( $post );

		$meta = wp_get_attachment_metadata( $attachment_id );
		$w    = ! empty( $meta['width'] ) ? min( $meta['width'], 640 ) : 0;
		$h    = ! empty( $meta['height'] ) ? $meta['height'] : 0;

		if ( $h && $w < $meta['width'] ) {
			$h = round( ( $meta['height'] * $w ) / $meta['width'] );
		}

		$attr = array( 'src' => $att_url );

		if ( ! empty( $w ) && ! empty( $h ) ) {
			$attr['width']  = $w;
			$attr['height'] = $h;
		}

		$thumb_id = get_post_thumbnail_id( $attachment_id );

		if ( ! empty( $thumb_id ) ) {
			$attr['poster'] = wp_get_attachment_url( $thumb_id );
		}

		echo wp_video_shortcode( $attr );

	elseif ( isset( $thumb_url[0] ) ) :
		?>
		<div class="wp_attachment_image wp-clearfix" id="media-head-<?php echo $attachment_id; ?>">
			<p id="thumbnail-head-<?php echo $attachment_id; ?>">
				<img class="thumbnail" src="<?php echo set_url_scheme( $thumb_url[0] ); ?>" style="max-width:100%" alt="" />
			</p>
		</div>
		<?php

	else :

		/**
		 * Fires when an attachment type can't be rendered in the edit form.
		 *
		 * @since 4.6.0
		 *
		 * @param WP_Post $post A post object.
		 */
		do_action( 'wp_edit_form_attachment_display', $post );

	endif;

	?>
	</div>
	<div class="wp_attachment_details edit-form-section">
	<?php if ( str_starts_with( $post->post_mime_type, 'image' ) ) : ?>
		<p class="attachment-alt-text">
			<label for="attachment_alt"><strong><?php _e( 'Alternative Text' ); ?></strong></label><br />
			<textarea class="widefat" name="_wp_attachment_image_alt" id="attachment_alt" aria-describedby="alt-text-description"><?php echo esc_attr( $alt_text ); ?></textarea>
		</p>
		<p class="attachment-alt-text-description" id="alt-text-description">
		<?php

		printf(
			/* translators: 1: Link to tutorial, 2: Additional link attributes, 3: Accessibility text. */
			__( '<a href="%1$s" %2$s>Learn how to describe the purpose of the image%3$s</a>. Leave empty if the image is purely decorative.' ),
			/* translators: Localized tutorial, if one exists. W3C Web Accessibility Initiative link has list of existing translations. */
			esc_url( __( 'https://www.w3.org/WAI/tutorials/images/decision-tree/' ) ),
			'target="_blank"',
			sprintf(
				'<span class="screen-reader-text"> %s</span>',
				/* translators: Hidden accessibility text. */
				__( '(opens in a new tab)' )
			)
		);

		?>
		</p>
	<?php endif; ?>

		<p>
			<label for="attachment_caption"><strong><?php _e( 'Caption' ); ?></strong></label><br />
			<textarea class="widefat" name="excerpt" id="attachment_caption"><?php echo $post->post_excerpt; ?></textarea>
		</p>

	<?php

	$quicktags_settings = array( 'buttons' => 'strong,em,link,block,del,ins,img,ul,ol,li,code,close' );
	$editor_args        = array(
		'textarea_name' => 'content',
		'textarea_rows' => 5,
		'media_buttons' => false,
		/**
		 * Filters the TinyMCE argument for the media description field on the attachment details screen.
		 *
		 * @since 6.6.0
		 *
		 * @param bool $tinymce Whether to activate TinyMCE in media description field. Default false.
		 */
		'tinymce'       => apply_filters( 'activate_tinymce_for_media_description', false ),
		'quicktags'     => $quicktags_settings,
	);

	?>

	<label for="attachment_content" class="attachment-content-description"><strong><?php _e( 'Description' ); ?></strong>
	<?php

	if ( preg_match( '#^(audio|video)/#', $post->post_mime_type ) ) {
		echo ': ' . __( 'Displayed on attachment pages.' );
	}

	?>
	</label>
	<?php wp_editor( format_to_edit( $post->post_content ), 'attachment_content', $editor_args ); ?>

	</div>
	<?php

	$extras = get_compat_media_markup( $post->ID );
	echo $extras['item'];
	echo '<input type="hidden" id="image-edit-context" value="edit-attachment" />' . "\n";
}

/**
 * Displays non-editable attachment metadata in the publish meta box.
 *
 * @since 3.5.0
 */
function attachment_submitbox_metadata() {
	$post          = get_post();
	$attachment_id = $post->ID;

	$file     = get_attached_file( $attachment_id );
	$filename = esc_html( wp_basename( $file ) );

	$media_dims = '';
	$meta       = wp_get_attachment_metadata( $attachment_id );

	if ( isset( $meta['width'], $meta['height'] ) ) {
		/* translators: 1: A number of pixels wide, 2: A number of pixels tall. */
		$media_dims .= "<span id='media-dims-$attachment_id'>" . sprintf( __( '%1$s by %2$s pixels' ), $meta['width'], $meta['height'] ) . '</span>';
	}
	/** This filter is documented in wp-admin/includes/media.php */
	$media_dims = apply_filters( 'media_meta', $media_dims, $post );

	$att_url = wp_get_attachment_url( $attachment_id );

	$author = new WP_User( $post->post_author );

	$uploaded_by_name = __( '(no author)' );
	$uploaded_by_link = '';

	if ( $author->exists() ) {
		$uploaded_by_name = $author->display_name ? $author->display_name : $author->nickname;
		$uploaded_by_link = get_edit_user_link( $author->ID );
	}
	?>
	<div class="misc-pub-section misc-pub-uploadedby word-wrap-break-word">
		<?php if ( $uploaded_by_link ) { ?>
			<?php _e( 'Uploaded by:' ); ?> <a href="<?php echo $uploaded_by_link; ?>"><strong><?php echo $uploaded_by_name; ?></strong></a>
		<?php } else { ?>
			<?php _e( 'Uploaded by:' ); ?> <strong><?php echo $uploaded_by_name; ?></strong>
		<?php } ?>
	</div>

	<?php
	if ( $post->post_parent ) {
		$post_parent = get_post( $post->post_parent );
		if ( $post_parent ) {
			$uploaded_to_title = $post_parent->post_title ? $post_parent->post_title : __( '(no title)' );
			$uploaded_to_link  = get_edit_post_link( $post->post_parent, 'raw' );
			?>
			<div class="misc-pub-section misc-pub-uploadedto">
				<?php if ( $uploaded_to_link ) { ?>
					<?php _e( 'Uploaded to:' ); ?> <a href="<?php echo $uploaded_to_link; ?>"><strong><?php echo $uploaded_to_title; ?></strong></a>
				<?php } else { ?>
					<?php _e( 'Uploaded to:' ); ?> <strong><?php echo $uploaded_to_title; ?></strong>
				<?php } ?>
			</div>
			<?php
		}
	}
	?>

	<div class="misc-pub-section misc-pub-attachment">
		<label for="attachment_url"><?php _e( 'File URL:' ); ?></label>
		<input type="text" class="widefat urlfield" readonly="readonly" name="attachment_url" id="attachment_url" value="<?php echo esc_attr( $att_url ); ?>" />
		<span class="copy-to-clipboard-container">
			<button type="button" class="button copy-attachment-url edit-media" data-clipboard-target="#attachment_url"><?php _e( 'Copy URL to clipboard' ); ?></button>
			<span class="success hidden" aria-hidden="true"><?php _e( 'Copied!' ); ?></span>
		</span>
	</div>
	<div class="misc-pub-section misc-pub-download">
		<a href="<?php echo esc_attr( $att_url ); ?>" download><?php _e( 'Download file' ); ?></a>
	</div>
	<div class="misc-pub-section misc-pub-filename">
		<?php _e( 'File name:' ); ?> <strong><?php echo $filename; ?></strong>
	</div>
	<div class="misc-pub-section misc-pub-filetype">
		<?php _e( 'File type:' ); ?>
		<strong>
		<?php

		if ( preg_match( '/^.*?\.(\w+)$/', get_attached_file( $post->ID ), $matches ) ) {
			echo esc_html( strtoupper( $matches[1] ) );
			list( $mime_type ) = explode( '/', $post->post_mime_type );
			if ( 'image' !== $mime_type && ! empty( $meta['mime_type'] ) ) {
				if ( "$mime_type/" . strtolower( $matches[1] ) !== $meta['mime_type'] ) {
					echo ' (' . $meta['mime_type'] . ')';
				}
			}
		} else {
			echo strtoupper( str_replace( 'image/', '', $post->post_mime_type ) );
		}

		?>
		</strong>
	</div>

	<?php

	$file_size = false;

	if ( isset( $meta['filesize'] ) ) {
		$file_size = $meta['filesize'];
	} elseif ( file_exists( $file ) ) {
		$file_size = wp_filesize( $file );
	}

	if ( ! empty( $file_size ) ) {
		?>
		<div class="misc-pub-section misc-pub-filesize">
			<?php _e( 'File size:' ); ?> <strong><?php echo size_format( $file_size ); ?></strong>
		</div>
		<?php
	}

	if ( preg_match( '#^(audio|video)/#', $post->post_mime_type ) ) {
		$fields = array(
			'length_formatted' => __( 'Length:' ),
			'bitrate'          => __( 'Bitrate:' ),
		);

		/**
		 * Filters the audio and video metadata fields to be shown in the publish meta box.
		 *
		 * The key for each item in the array should correspond to an attachment
		 * metadata key, and the value should be the desired label.
		 *
		 * @since 3.7.0
		 * @since 4.9.0 Added the `$post` parameter.
		 *
		 * @param array   $fields An array of the attachment metadata keys and labels.
		 * @param WP_Post $post   WP_Post object for the current attachment.
		 */
		$fields = apply_filters( 'media_submitbox_misc_sections', $fields, $post );

		foreach ( $fields as $key => $label ) {
			if ( empty( $meta[ $key ] ) ) {
				continue;
			}

			?>
			<div class="misc-pub-section misc-pub-mime-meta misc-pub-<?php echo sanitize_html_class( $key ); ?>">
				<?php echo $label; ?>
				<strong>
				<?php

				switch ( $key ) {
					case 'bitrate':
						echo round( $meta['bitrate'] / 1000 ) . 'kb/s';
						if ( ! empty( $meta['bitrate_mode'] ) ) {
							echo ' ' . strtoupper( esc_html( $meta['bitrate_mode'] ) );
						}
						break;
					case 'length_formatted':
						echo human_readable_duration( $meta['length_formatted'] );
						break;
					default:
						echo esc_html( $meta[ $key ] );
						break;
				}

				?>
				</strong>
			</div>
			<?php
		}

		$fields = array(
			'dataformat' => __( 'Audio Format:' ),
			'codec'      => __( 'Audio Codec:' ),
		);

		/**
		 * Filters the audio attachment metadata fields to be shown in the publish meta box.
		 *
		 * The key for each item in the array should correspond to an attachment
		 * metadata key, and the value should be the desired label.
		 *
		 * @since 3.7.0
		 * @since 4.9.0 Added the `$post` parameter.
		 *
		 * @param array   $fields An array of the attachment metadata keys and labels.
		 * @param WP_Post $post   WP_Post object for the current attachment.
		 */
		$audio_fields = apply_filters( 'audio_submitbox_misc_sections', $fields, $post );

		foreach ( $audio_fields as $key => $label ) {
			if ( empty( $meta['audio'][ $key ] ) ) {
				continue;
			}

			?>
			<div class="misc-pub-section misc-pub-audio misc-pub-<?php echo sanitize_html_class( $key ); ?>">
				<?php echo $label; ?> <strong><?php echo esc_html( $meta['audio'][ $key ] ); ?></strong>
			</div>
			<?php
		}
	}

	if ( $media_dims ) {
		?>
		<div class="misc-pub-section misc-pub-dimensions">
			<?php _e( 'Dimensions:' ); ?> <strong><?php echo $media_dims; ?></strong>
		</div>
		<?php
	}

	if ( ! empty( $meta['original_image'] ) ) {
		?>
		<div class="misc-pub-section misc-pub-original-image word-wrap-break-word">
			<?php _e( 'Original image:' ); ?>
			<a href="<?php echo esc_url( wp_get_original_image_url( $attachment_id ) ); ?>">
				<strong><?php echo esc_html( wp_basename( wp_get_original_image_path( $attachment_id ) ) ); ?></strong>
			</a>
		</div>
		<?php
	}
}

/**
 * Parses ID3v2, ID3v1, and getID3 comments to extract usable data.
 *
 * @since 3.6.0
 *
 * @param array $metadata An existing array with data.
 * @param array $data Data supplied by ID3 tags.
 */
function wp_add_id3_tag_data( &$metadata, $data ) {
	foreach ( array( 'id3v2', 'id3v1' ) as $version ) {
		if ( ! empty( $data[ $version ]['comments'] ) ) {
			foreach ( $data[ $version ]['comments'] as $key => $list ) {
				if ( 'length' !== $key && ! empty( $list ) ) {
					$metadata[ $key ] = is_array( $list ) ? wp_kses_post_deep( reset( $list ) ) : wp_kses_post( $list );
					// Fix bug in byte stream analysis.
					if ( 'terms_of_use' === $key && str_starts_with( $metadata[ $key ], 'yright notice.' ) ) {
						$metadata[ $key ] = 'Cop' . $metadata[ $key ];
					}
				}
			}
			break;
		}
	}

	if ( ! empty( $data['id3v2']['APIC'] ) ) {
		$image = reset( $data['id3v2']['APIC'] );
		if ( ! empty( $image['data'] ) ) {
			$metadata['image'] = array(
				'data'   => $image['data'],
				'mime'   => $image['image_mime'],
				'width'  => $image['image_width'],
				'height' => $image['image_height'],
			);
		}
	} elseif ( ! empty( $data['comments']['picture'] ) ) {
		$image = reset( $data['comments']['picture'] );
		if ( ! empty( $image['data'] ) ) {
			$metadata['image'] = array(
				'data' => $image['data'],
				'mime' => $image['image_mime'],
			);
		}
	}
}

/**
 * Retrieves metadata from a video file's ID3 tags.
 *
 * @since 3.6.0
 *
 * @param string $file Path to file.
 * @return array|false Returns array of metadata, if found.
 */
function wp_read_video_metadata( $file ) {
	if ( ! file_exists( $file ) ) {
		return false;
	}

	$metadata = array();

	if ( ! defined( 'GETID3_TEMP_DIR' ) ) {
		define( 'GETID3_TEMP_DIR', get_temp_dir() );
	}

	if ( ! class_exists( 'getID3', false ) ) {
		require ABSPATH . WPINC . '/ID3/getid3.php';
	}

	$id3 = new getID3();
	// Required to get the `created_timestamp` value.
	$id3->options_audiovideo_quicktime_ReturnAtomData = true; // phpcs:ignore WordPress.NamingConventions.ValidVariableName

	$data = $id3->analyze( $file );

	if ( isset( $data['video']['lossless'] ) ) {
		$metadata['lossless'] = $data['video']['lossless'];
	}

	if ( ! empty( $data['video']['bitrate'] ) ) {
		$metadata['bitrate'] = (int) $data['video']['bitrate'];
	}

	if ( ! empty( $data['video']['bitrate_mode'] ) ) {
		$metadata['bitrate_mode'] = $data['video']['bitrate_mode'];
	}

	if ( ! empty( $data['filesize'] ) ) {
		$metadata['filesize'] = (int) $data['filesize'];
	}

	if ( ! empty( $data['mime_type'] ) ) {
		$metadata['mime_type'] = $data['mime_type'];
	}

	if ( ! empty( $data['playtime_seconds'] ) ) {
		$metadata['length'] = (int) round( $data['playtime_seconds'] );
	}

	if ( ! empty( $data['playtime_string'] ) ) {
		$metadata['length_formatted'] = $data['playtime_string'];
	}

	if ( ! empty( $data['video']['resolution_x'] ) ) {
		$metadata['width'] = (int) $data['video']['resolution_x'];
	}

	if ( ! empty( $data['video']['resolution_y'] ) ) {
		$metadata['height'] = (int) $data['video']['resolution_y'];
	}

	if ( ! empty( $data['fileformat'] ) ) {
		$metadata['fileformat'] = $data['fileformat'];
	}

	if ( ! empty( $data['video']['dataformat'] ) ) {
		$metadata['dataformat'] = $data['video']['dataformat'];
	}

	if ( ! empty( $data['video']['encoder'] ) ) {
		$metadata['encoder'] = $data['video']['encoder'];
	}

	if ( ! empty( $data['video']['codec'] ) ) {
		$metadata['codec'] = $data['video']['codec'];
	}

	if ( ! empty( $data['audio'] ) ) {
		unset( $data['audio']['streams'] );
		$metadata['audio'] = $data['audio'];
	}

	if ( empty( $metadata['created_timestamp'] ) ) {
		$created_timestamp = wp_get_media_creation_timestamp( $data );

		if ( false !== $created_timestamp ) {
			$metadata['created_timestamp'] = $created_timestamp;
		}
	}

	wp_add_id3_tag_data( $metadata, $data );

	$file_format = isset( $metadata['fileformat'] ) ? $metadata['fileformat'] : null;

	/**
	 * Filters the array of metadata retrieved from a video.
	 *
	 * In core, usually this selection is what is stored.
	 * More complete data can be parsed from the `$data` parameter.
	 *
	 * @since 4.9.0
	 *
	 * @param array       $metadata    Filtered video metadata.
	 * @param string      $file        Path to video file.
	 * @param string|null $file_format File format of video, as analyzed by getID3.
	 *                                 Null if unknown.
	 * @param array       $data        Raw metadata from getID3.
	 */
	return apply_filters( 'wp_read_video_metadata', $metadata, $file, $file_format, $data );
}

/**
 * Retrieves metadata from an audio file's ID3 tags.
 *
 * @since 3.6.0
 *
 * @param string $file Path to file.
 * @return array|false Returns array of metadata, if found.
 */
function wp_read_audio_metadata( $file ) {
	if ( ! file_exists( $file ) ) {
		return false;
	}

	$metadata = array();

	if ( ! defined( 'GETID3_TEMP_DIR' ) ) {
		define( 'GETID3_TEMP_DIR', get_temp_dir() );
	}

	if ( ! class_exists( 'getID3', false ) ) {
		require ABSPATH . WPINC . '/ID3/getid3.php';
	}

	$id3 = new getID3();
	// Required to get the `created_timestamp` value.
	$id3->options_audiovideo_quicktime_ReturnAtomData = true; // phpcs:ignore WordPress.NamingConventions.ValidVariableName

	$data = $id3->analyze( $file );

	if ( ! empty( $data['audio'] ) ) {
		unset( $data['audio']['streams'] );
		$metadata = $data['audio'];
	}

	if ( ! empty( $data['fileformat'] ) ) {
		$metadata['fileformat'] = $data['fileformat'];
	}

	if ( ! empty( $data['filesize'] ) ) {
		$metadata['filesize'] = (int) $data['filesize'];
	}

	if ( ! empty( $data['mime_type'] ) ) {
		$metadata['mime_type'] = $data['mime_type'];
	}

	if ( ! empty( $data['playtime_seconds'] ) ) {
		$metadata['length'] = (int) round( $data['playtime_seconds'] );
	}

	if ( ! empty( $data['playtime_string'] ) ) {
		$metadata['length_formatted'] = $data['playtime_string'];
	}

	if ( empty( $metadata['created_timestamp'] ) ) {
		$created_timestamp = wp_get_media_creation_timestamp( $data );

		if ( false !== $created_timestamp ) {
			$metadata['created_timestamp'] = $created_timestamp;
		}
	}

	wp_add_id3_tag_data( $metadata, $data );

	$file_format = isset( $metadata['fileformat'] ) ? $metadata['fileformat'] : null;

	/**
	 * Filters the array of metadata retrieved from an audio file.
	 *
	 * In core, usually this selection is what is stored.
	 * More complete data can be parsed from the `$data` parameter.
	 *
	 * @since 6.1.0
	 *
	 * @param array       $metadata    Filtered audio metadata.
	 * @param string      $file        Path to audio file.
	 * @param string|null $file_format File format of audio, as analyzed by getID3.
	 *                                 Null if unknown.
	 * @param array       $data        Raw metadata from getID3.
	 */
	return apply_filters( 'wp_read_audio_metadata', $metadata, $file, $file_format, $data );
}

/**
 * Parses creation date from media metadata.
 *
 * The getID3 library doesn't have a standard method for getting creation dates,
 * so the location of this data can vary based on the MIME type.
 *
 * @since 4.9.0
 *
 * @link https://github.com/JamesHeinrich/getID3/blob/master/structure.txt
 *
 * @param array $metadata The metadata returned by getID3::analyze().
 * @return int|false A UNIX timestamp for the media's creation date if available
 *                   or a boolean FALSE if a timestamp could not be determined.
 */
function wp_get_media_creation_timestamp( $metadata ) {
	$creation_date = false;

	if ( empty( $metadata['fileformat'] ) ) {
		return $creation_date;
	}

	switch ( $metadata['fileformat'] ) {
		case 'asf':
			if ( isset( $metadata['asf']['file_properties_object']['creation_date_unix'] ) ) {
				$creation_date = (int) $metadata['asf']['file_properties_object']['creation_date_unix'];
			}
			break;

		case 'matroska':
		case 'webm':
			if ( isset( $metadata['matroska']['comments']['creation_time'][0] ) ) {
				$creation_date = strtotime( $metadata['matroska']['comments']['creation_time'][0] );
			} elseif ( isset( $metadata['matroska']['info'][0]['DateUTC_unix'] ) ) {
				$creation_date = (int) $metadata['matroska']['info'][0]['DateUTC_unix'];
			}
			break;

		case 'quicktime':
		case 'mp4':
			if ( isset( $metadata['quicktime']['moov']['subatoms'][0]['creation_time_unix'] ) ) {
				$creation_date = (int) $metadata['quicktime']['moov']['subatoms'][0]['creation_time_unix'];
			}
			break;
	}

	return $creation_date;
}

/**
 * Encapsulates the logic for Attach/Detach actions.
 *
 * @since 4.2.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param int    $parent_id Attachment parent ID.
 * @param string $action    Optional. Attach/detach action. Accepts 'attach' or 'detach'.
 *                          Default 'attach'.
 */
function wp_media_attach_action( $parent_id, $action = 'attach' ) {
	global $wpdb;

	if ( ! $parent_id ) {
		return;
	}

	if ( ! current_user_can( 'edit_post', $parent_id ) ) {
		wp_die( __( 'Sorry, you are not allowed to edit this post.' ) );
	}

	$ids = array();

	foreach ( (array) $_REQUEST['media'] as $attachment_id ) {
		$attachment_id = (int) $attachment_id;

		if ( ! current_user_can( 'edit_post', $attachment_id ) ) {
			continue;
		}

		$ids[] = $attachment_id;
	}

	if ( ! empty( $ids ) ) {
		$ids_string = implode( ',', $ids );

		if ( 'attach' === $action ) {
			$result = $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->posts SET post_parent = %d WHERE post_type = 'attachment' AND ID IN ( $ids_string )", $parent_id ) );
		} else {
			$result = $wpdb->query( "UPDATE $wpdb->posts SET post_parent = 0 WHERE post_type = 'attachment' AND ID IN ( $ids_string )" );
		}
	}

	if ( isset( $result ) ) {
		foreach ( $ids as $attachment_id ) {
			/**
			 * Fires when media is attached or detached from a post.
			 *
			 * @since 5.5.0
			 *
			 * @param string $action        Attach/detach action. Accepts 'attach' or 'detach'.
			 * @param int    $attachment_id The attachment ID.
			 * @param int    $parent_id     Attachment parent ID.
			 */
			do_action( 'wp_media_attach_action', $action, $attachment_id, $parent_id );

			clean_attachment_cache( $attachment_id );
		}

		$location = 'upload.php';
		$referer  = wp_get_referer();

		if ( $referer ) {
			if ( str_contains( $referer, 'upload.php' ) ) {
				$location = remove_query_arg( array( 'attached', 'detach' ), $referer );
			}
		}

		$key      = 'attach' === $action ? 'attached' : 'detach';
		$location = add_query_arg( array( $key => $result ), $location );

		wp_redirect( $location );
		exit;
	}
}
ms-deprecated.php000064400000007272151212616050010001 0ustar00<?php
/**
 * Multisite: Deprecated admin functions from past versions and WordPress MU
 *
 * These functions should not be used and will be removed in a later version.
 * It is suggested to use for the alternatives instead when available.
 *
 * @package WordPress
 * @subpackage Deprecated
 * @since 3.0.0
 */

/**
 * Outputs the WPMU menu.
 *
 * @deprecated 3.0.0
 */
function wpmu_menu() {
	_deprecated_function( __FUNCTION__, '3.0.0' );
	// Deprecated. See #11763.
}

/**
 * Determines if the available space defined by the admin has been exceeded by the user.
 *
 * @deprecated 3.0.0 Use is_upload_space_available()
 * @see is_upload_space_available()
 */
function wpmu_checkAvailableSpace() {
	_deprecated_function( __FUNCTION__, '3.0.0', 'is_upload_space_available()' );

	if ( ! is_upload_space_available() ) {
		wp_die( sprintf(
			/* translators: %s: Allowed space allocation. */
			__( 'Sorry, you have used your space allocation of %s. Please delete some files to upload more files.' ),
			size_format( get_space_allowed() * MB_IN_BYTES )
		) );
	}
}

/**
 * WPMU options.
 *
 * @deprecated 3.0.0
 */
function mu_options( $options ) {
	_deprecated_function( __FUNCTION__, '3.0.0' );
	return $options;
}

/**
 * Deprecated functionality for activating a network-only plugin.
 *
 * @deprecated 3.0.0 Use activate_plugin()
 * @see activate_plugin()
 */
function activate_sitewide_plugin() {
	_deprecated_function( __FUNCTION__, '3.0.0', 'activate_plugin()' );
	return false;
}

/**
 * Deprecated functionality for deactivating a network-only plugin.
 *
 * @deprecated 3.0.0 Use deactivate_plugin()
 * @see deactivate_plugin()
 */
function deactivate_sitewide_plugin( $plugin = false ) {
	_deprecated_function( __FUNCTION__, '3.0.0', 'deactivate_plugin()' );
}

/**
 * Deprecated functionality for determining if the current plugin is network-only.
 *
 * @deprecated 3.0.0 Use is_network_only_plugin()
 * @see is_network_only_plugin()
 */
function is_wpmu_sitewide_plugin( $file ) {
	_deprecated_function( __FUNCTION__, '3.0.0', 'is_network_only_plugin()' );
	return is_network_only_plugin( $file );
}

/**
 * Deprecated functionality for getting themes network-enabled themes.
 *
 * @deprecated 3.4.0 Use WP_Theme::get_allowed_on_network()
 * @see WP_Theme::get_allowed_on_network()
 */
function get_site_allowed_themes() {
	_deprecated_function( __FUNCTION__, '3.4.0', 'WP_Theme::get_allowed_on_network()' );
	return array_map( 'intval', WP_Theme::get_allowed_on_network() );
}

/**
 * Deprecated functionality for getting themes allowed on a specific site.
 *
 * @deprecated 3.4.0 Use WP_Theme::get_allowed_on_site()
 * @see WP_Theme::get_allowed_on_site()
 */
function wpmu_get_blog_allowedthemes( $blog_id = 0 ) {
	_deprecated_function( __FUNCTION__, '3.4.0', 'WP_Theme::get_allowed_on_site()' );
	return array_map( 'intval', WP_Theme::get_allowed_on_site( $blog_id ) );
}

/**
 * Deprecated functionality for determining whether a file is deprecated.
 *
 * @deprecated 3.5.0
 */
function ms_deprecated_blogs_file() {}

if ( ! function_exists( 'install_global_terms' ) ) :
	/**
	 * Install global terms.
	 *
	 * @since 3.0.0
	 * @since 6.1.0 This function no longer does anything.
	 * @deprecated 6.1.0
	 */
	function install_global_terms() {
		_deprecated_function( __FUNCTION__, '6.1.0' );
	}
endif;

/**
 * Synchronizes category and post tag slugs when global terms are enabled.
 *
 * @since 3.0.0
 * @since 6.1.0 This function no longer does anything.
 * @deprecated 6.1.0
 *
 * @param WP_Term|array $term     The term.
 * @param string        $taxonomy The taxonomy for `$term`.
 * @return WP_Term|array Always returns `$term`.
 */
function sync_category_tag_slugs( $term, $taxonomy ) {
	_deprecated_function( __FUNCTION__, '6.1.0' );

	return $term;
}
class-wp-ajax-upgrader-skin.php000064400000010141151212616050012474 0ustar00<?php
/**
 * Upgrader API: WP_Ajax_Upgrader_Skin class
 *
 * @package WordPress
 * @subpackage Upgrader
 * @since 4.6.0
 */

/**
 * Upgrader Skin for Ajax WordPress upgrades.
 *
 * This skin is designed to be used for Ajax updates.
 *
 * @since 4.6.0
 *
 * @see Automatic_Upgrader_Skin
 */
class WP_Ajax_Upgrader_Skin extends Automatic_Upgrader_Skin {

	/**
	 * Plugin info.
	 *
	 * The Plugin_Upgrader::bulk_upgrade() method will fill this in
	 * with info retrieved from the get_plugin_data() function.
	 *
	 * @var array Plugin data. Values will be empty if not supplied by the plugin.
	 */
	public $plugin_info = array();

	/**
	 * Theme info.
	 *
	 * The Theme_Upgrader::bulk_upgrade() method will fill this in
	 * with info retrieved from the Theme_Upgrader::theme_info() method,
	 * which in turn calls the wp_get_theme() function.
	 *
	 * @var WP_Theme|false The theme's info object, or false.
	 */
	public $theme_info = false;

	/**
	 * Holds the WP_Error object.
	 *
	 * @since 4.6.0
	 *
	 * @var null|WP_Error
	 */
	protected $errors = null;

	/**
	 * Constructor.
	 *
	 * Sets up the WordPress Ajax upgrader skin.
	 *
	 * @since 4.6.0
	 *
	 * @see WP_Upgrader_Skin::__construct()
	 *
	 * @param array $args Optional. The WordPress Ajax upgrader skin arguments to
	 *                    override default options. See WP_Upgrader_Skin::__construct().
	 *                    Default empty array.
	 */
	public function __construct( $args = array() ) {
		parent::__construct( $args );

		$this->errors = new WP_Error();
	}

	/**
	 * Retrieves the list of errors.
	 *
	 * @since 4.6.0
	 *
	 * @return WP_Error Errors during an upgrade.
	 */
	public function get_errors() {
		return $this->errors;
	}

	/**
	 * Retrieves a string for error messages.
	 *
	 * @since 4.6.0
	 *
	 * @return string Error messages during an upgrade.
	 */
	public function get_error_messages() {
		$messages = array();

		foreach ( $this->errors->get_error_codes() as $error_code ) {
			$error_data = $this->errors->get_error_data( $error_code );

			if ( $error_data && is_string( $error_data ) ) {
				$messages[] = $this->errors->get_error_message( $error_code ) . ' ' . esc_html( strip_tags( $error_data ) );
			} else {
				$messages[] = $this->errors->get_error_message( $error_code );
			}
		}

		return implode( ', ', $messages );
	}

	/**
	 * Stores an error message about the upgrade.
	 *
	 * @since 4.6.0
	 * @since 5.3.0 Formalized the existing `...$args` parameter by adding it
	 *              to the function signature.
	 *
	 * @param string|WP_Error $errors  Errors.
	 * @param mixed           ...$args Optional text replacements.
	 */
	public function error( $errors, ...$args ) {
		if ( is_string( $errors ) ) {
			$string = $errors;
			if ( ! empty( $this->upgrader->strings[ $string ] ) ) {
				$string = $this->upgrader->strings[ $string ];
			}

			if ( str_contains( $string, '%' ) ) {
				if ( ! empty( $args ) ) {
					$string = vsprintf( $string, $args );
				}
			}

			// Count existing errors to generate a unique error code.
			$errors_count = count( $this->errors->get_error_codes() );
			$this->errors->add( 'unknown_upgrade_error_' . ( $errors_count + 1 ), $string );
		} elseif ( is_wp_error( $errors ) ) {
			foreach ( $errors->get_error_codes() as $error_code ) {
				$this->errors->add( $error_code, $errors->get_error_message( $error_code ), $errors->get_error_data( $error_code ) );
			}
		}

		parent::error( $errors, ...$args );
	}

	/**
	 * Stores a message about the upgrade.
	 *
	 * @since 4.6.0
	 * @since 5.3.0 Formalized the existing `...$args` parameter by adding it
	 *              to the function signature.
	 * @since 5.9.0 Renamed `$data` to `$feedback` for PHP 8 named parameter support.
	 *
	 * @param string|array|WP_Error $feedback Message data.
	 * @param mixed                 ...$args  Optional text replacements.
	 */
	public function feedback( $feedback, ...$args ) {
		if ( is_wp_error( $feedback ) ) {
			foreach ( $feedback->get_error_codes() as $error_code ) {
				$this->errors->add( $error_code, $feedback->get_error_message( $error_code ), $feedback->get_error_data( $error_code ) );
			}
		}

		parent::feedback( $feedback, ...$args );
	}
}
class-wp-application-passwords-list-table.php000064400000015445151212616050015400 0ustar00<?php
/**
 * List Table API: WP_Application_Passwords_List_Table class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 5.6.0
 */

/**
 * Class for displaying the list of application password items.
 *
 * @since 5.6.0
 *
 * @see WP_List_Table
 */
class WP_Application_Passwords_List_Table extends WP_List_Table {

	/**
	 * Gets the list of columns.
	 *
	 * @since 5.6.0
	 *
	 * @return string[] Array of column titles keyed by their column name.
	 */
	public function get_columns() {
		return array(
			'name'      => __( 'Name' ),
			'created'   => __( 'Created' ),
			'last_used' => __( 'Last Used' ),
			'last_ip'   => __( 'Last IP' ),
			'revoke'    => __( 'Revoke' ),
		);
	}

	/**
	 * Prepares the list of items for displaying.
	 *
	 * @since 5.6.0
	 *
	 * @global int $user_id User ID.
	 */
	public function prepare_items() {
		global $user_id;
		$this->items = array_reverse( WP_Application_Passwords::get_user_application_passwords( $user_id ) );
	}

	/**
	 * Handles the name column output.
	 *
	 * @since 5.6.0
	 *
	 * @param array $item The current application password item.
	 */
	public function column_name( $item ) {
		echo esc_html( $item['name'] );
	}

	/**
	 * Handles the created column output.
	 *
	 * @since 5.6.0
	 *
	 * @param array $item The current application password item.
	 */
	public function column_created( $item ) {
		if ( empty( $item['created'] ) ) {
			echo '&mdash;';
		} else {
			echo date_i18n( __( 'F j, Y' ), $item['created'] );
		}
	}

	/**
	 * Handles the last used column output.
	 *
	 * @since 5.6.0
	 *
	 * @param array $item The current application password item.
	 */
	public function column_last_used( $item ) {
		if ( empty( $item['last_used'] ) ) {
			echo '&mdash;';
		} else {
			echo date_i18n( __( 'F j, Y' ), $item['last_used'] );
		}
	}

	/**
	 * Handles the last ip column output.
	 *
	 * @since 5.6.0
	 *
	 * @param array $item The current application password item.
	 */
	public function column_last_ip( $item ) {
		if ( empty( $item['last_ip'] ) ) {
			echo '&mdash;';
		} else {
			echo $item['last_ip'];
		}
	}

	/**
	 * Handles the revoke column output.
	 *
	 * @since 5.6.0
	 *
	 * @param array $item The current application password item.
	 */
	public function column_revoke( $item ) {
		$name = 'revoke-application-password-' . $item['uuid'];
		printf(
			'<button type="button" name="%1$s" id="%1$s" class="button delete" aria-label="%2$s">%3$s</button>',
			esc_attr( $name ),
			/* translators: %s: the application password's given name. */
			esc_attr( sprintf( __( 'Revoke "%s"' ), $item['name'] ) ),
			__( 'Revoke' )
		);
	}

	/**
	 * Generates content for a single row of the table
	 *
	 * @since 5.6.0
	 *
	 * @param array  $item        The current item.
	 * @param string $column_name The current column name.
	 */
	protected function column_default( $item, $column_name ) {
		/**
		 * Fires for each custom column in the Application Passwords list table.
		 *
		 * Custom columns are registered using the {@see 'manage_application-passwords-user_columns'} filter.
		 *
		 * @since 5.6.0
		 *
		 * @param string $column_name Name of the custom column.
		 * @param array  $item        The application password item.
		 */
		do_action( "manage_{$this->screen->id}_custom_column", $column_name, $item );
	}

	/**
	 * Generates custom table navigation to prevent conflicting nonces.
	 *
	 * @since 5.6.0
	 *
	 * @param string $which The location of the bulk actions: Either 'top' or 'bottom'.
	 */
	protected function display_tablenav( $which ) {
		?>
		<div class="tablenav <?php echo esc_attr( $which ); ?>">
			<?php if ( 'bottom' === $which ) : ?>
				<div class="alignright">
					<button type="button" name="revoke-all-application-passwords" id="revoke-all-application-passwords" class="button delete"><?php _e( 'Revoke all application passwords' ); ?></button>
				</div>
			<?php endif; ?>
			<div class="alignleft actions bulkactions">
				<?php $this->bulk_actions( $which ); ?>
			</div>
			<?php
			$this->extra_tablenav( $which );
			$this->pagination( $which );
			?>
			<br class="clear" />
		</div>
		<?php
	}

	/**
	 * Generates content for a single row of the table.
	 *
	 * @since 5.6.0
	 *
	 * @param array $item The current item.
	 */
	public function single_row( $item ) {
		echo '<tr data-uuid="' . esc_attr( $item['uuid'] ) . '">';
		$this->single_row_columns( $item );
		echo '</tr>';
	}

	/**
	 * Gets the name of the default primary column.
	 *
	 * @since 5.6.0
	 *
	 * @return string Name of the default primary column, in this case, 'name'.
	 */
	protected function get_default_primary_column_name() {
		return 'name';
	}

	/**
	 * Prints the JavaScript template for the new row item.
	 *
	 * @since 5.6.0
	 */
	public function print_js_template_row() {
		list( $columns, $hidden, , $primary ) = $this->get_column_info();

		echo '<tr data-uuid="{{ data.uuid }}">';

		foreach ( $columns as $column_name => $display_name ) {
			$is_primary = $primary === $column_name;
			$classes    = "{$column_name} column-{$column_name}";

			if ( $is_primary ) {
				$classes .= ' has-row-actions column-primary';
			}

			if ( in_array( $column_name, $hidden, true ) ) {
				$classes .= ' hidden';
			}

			printf( '<td class="%s" data-colname="%s">', esc_attr( $classes ), esc_attr( wp_strip_all_tags( $display_name ) ) );

			switch ( $column_name ) {
				case 'name':
					echo '{{ data.name }}';
					break;
				case 'created':
					// JSON encoding automatically doubles backslashes to ensure they don't get lost when printing the inline JS.
					echo '<# print( wp.date.dateI18n( ' . wp_json_encode( __( 'F j, Y' ) ) . ', data.created ) ) #>';
					break;
				case 'last_used':
					echo '<# print( data.last_used !== null ? wp.date.dateI18n( ' . wp_json_encode( __( 'F j, Y' ) ) . ", data.last_used ) : '—' ) #>";
					break;
				case 'last_ip':
					echo "{{ data.last_ip || '—' }}";
					break;
				case 'revoke':
					printf(
						'<button type="button" class="button delete" aria-label="%1$s">%2$s</button>',
						/* translators: %s: the application password's given name. */
						esc_attr( sprintf( __( 'Revoke "%s"' ), '{{ data.name }}' ) ),
						esc_html__( 'Revoke' )
					);
					break;
				default:
					/**
					 * Fires in the JavaScript row template for each custom column in the Application Passwords list table.
					 *
					 * Custom columns are registered using the {@see 'manage_application-passwords-user_columns'} filter.
					 *
					 * @since 5.6.0
					 *
					 * @param string $column_name Name of the custom column.
					 */
					do_action( "manage_{$this->screen->id}_custom_column_js_template", $column_name );
					break;
			}

			if ( $is_primary ) {
				echo '<button type="button" class="toggle-row"><span class="screen-reader-text">' .
					/* translators: Hidden accessibility text. */
					__( 'Show more details' ) .
				'</span></button>';
			}

			echo '</td>';
		}

		echo '</tr>';
	}
}
credits.php000064400000013356151212616050006721 0ustar00<?php
/**
 * WordPress Credits Administration API.
 *
 * @package WordPress
 * @subpackage Administration
 * @since 4.4.0
 */

/**
 * Retrieves the contributor credits.
 *
 * @since 3.2.0
 * @since 5.6.0 Added the `$version` and `$locale` parameters.
 *
 * @param string $version WordPress version. Defaults to the current version.
 * @param string $locale  WordPress locale. Defaults to the current user's locale.
 * @return array|false A list of all of the contributors, or false on error.
 */
function wp_credits( $version = '', $locale = '' ) {
	if ( ! $version ) {
		$version = wp_get_wp_version();
	}

	if ( ! $locale ) {
		$locale = get_user_locale();
	}

	$results = get_site_transient( 'wordpress_credits_' . $locale );

	if ( ! is_array( $results )
		|| str_contains( $version, '-' )
		|| ( isset( $results['data']['version'] ) && ! str_starts_with( $version, $results['data']['version'] ) )
	) {
		$url     = "http://api.wordpress.org/core/credits/1.1/?version={$version}&locale={$locale}";
		$options = array( 'user-agent' => 'WordPress/' . $version . '; ' . home_url( '/' ) );

		if ( wp_http_supports( array( 'ssl' ) ) ) {
			$url = set_url_scheme( $url, 'https' );
		}

		$response = wp_remote_get( $url, $options );

		if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
			return false;
		}

		$results = json_decode( wp_remote_retrieve_body( $response ), true );

		if ( ! is_array( $results ) ) {
			return false;
		}

		set_site_transient( 'wordpress_credits_' . $locale, $results, DAY_IN_SECONDS );
	}

	return $results;
}

/**
 * Retrieves the link to a contributor's WordPress.org profile page.
 *
 * @access private
 * @since 3.2.0
 *
 * @param string $display_name  The contributor's display name (passed by reference).
 * @param string $username      The contributor's username.
 * @param string $profiles      URL to the contributor's WordPress.org profile page.
 */
function _wp_credits_add_profile_link( &$display_name, $username, $profiles ) {
	$display_name = '<a href="' . esc_url( sprintf( $profiles, $username ) ) . '">' . esc_html( $display_name ) . '</a>';
}

/**
 * Retrieves the link to an external library used in WordPress.
 *
 * @access private
 * @since 3.2.0
 *
 * @param string $data External library data (passed by reference).
 */
function _wp_credits_build_object_link( &$data ) {
	$data = '<a href="' . esc_url( $data[1] ) . '">' . esc_html( $data[0] ) . '</a>';
}

/**
 * Displays the title for a given group of contributors.
 *
 * @since 5.3.0
 *
 * @param array $group_data The current contributor group.
 */
function wp_credits_section_title( $group_data = array() ) {
	if ( ! count( $group_data ) ) {
		return;
	}

	if ( $group_data['name'] ) {
		if ( 'Translators' === $group_data['name'] ) {
			// Considered a special slug in the API response. (Also, will never be returned for en_US.)
			$title = _x( 'Translators', 'Translate this to be the equivalent of English Translators in your language for the credits page Translators section' );
		} elseif ( isset( $group_data['placeholders'] ) ) {
			// phpcs:ignore WordPress.WP.I18n.LowLevelTranslationFunction,WordPress.WP.I18n.NonSingularStringLiteralText
			$title = vsprintf( translate( $group_data['name'] ), $group_data['placeholders'] );
		} else {
			// phpcs:ignore WordPress.WP.I18n.LowLevelTranslationFunction,WordPress.WP.I18n.NonSingularStringLiteralText
			$title = translate( $group_data['name'] );
		}

		echo '<h2 class="wp-people-group-title">' . esc_html( $title ) . "</h2>\n";
	}
}

/**
 * Displays a list of contributors for a given group.
 *
 * @since 5.3.0
 *
 * @param array  $credits The credits groups returned from the API.
 * @param string $slug    The current group to display.
 */
function wp_credits_section_list( $credits = array(), $slug = '' ) {
	$group_data   = isset( $credits['groups'][ $slug ] ) ? $credits['groups'][ $slug ] : array();
	$credits_data = $credits['data'];
	if ( ! count( $group_data ) ) {
		return;
	}

	if ( ! empty( $group_data['shuffle'] ) ) {
		shuffle( $group_data['data'] ); // We were going to sort by ability to pronounce "hierarchical," but that wouldn't be fair to Matt.
	}

	switch ( $group_data['type'] ) {
		case 'list':
			array_walk( $group_data['data'], '_wp_credits_add_profile_link', $credits_data['profiles'] );
			echo '<p class="wp-credits-list">' . wp_sprintf( '%l.', $group_data['data'] ) . "</p>\n\n";
			break;
		case 'libraries':
			array_walk( $group_data['data'], '_wp_credits_build_object_link' );
			echo '<p class="wp-credits-list">' . wp_sprintf( '%l.', $group_data['data'] ) . "</p>\n\n";
			break;
		default:
			$compact = 'compact' === $group_data['type'];
			$classes = 'wp-people-group ' . ( $compact ? 'compact' : '' );
			echo '<ul class="' . $classes . '" id="wp-people-group-' . $slug . '">' . "\n";
			foreach ( $group_data['data'] as $person_data ) {
				echo '<li class="wp-person" id="wp-person-' . esc_attr( $person_data[2] ) . '">' . "\n\t";
				echo '<a href="' . esc_url( sprintf( $credits_data['profiles'], $person_data[2] ) ) . '" class="web">';
				$size   = $compact ? 80 : 160;
				$data   = get_avatar_data( $person_data[1] . '@sha256.gravatar.com', array( 'size' => $size ) );
				$data2x = get_avatar_data( $person_data[1] . '@sha256.gravatar.com', array( 'size' => $size * 2 ) );
				echo '<span class="wp-person-avatar"><img src="' . esc_url( $data['url'] ) . '" srcset="' . esc_url( $data2x['url'] ) . ' 2x" class="gravatar" alt="" /></span>' . "\n";
				echo esc_html( $person_data[0] ) . "</a>\n\t";
				if ( ! $compact && ! empty( $person_data[3] ) ) {
					// phpcs:ignore WordPress.WP.I18n.LowLevelTranslationFunction,WordPress.WP.I18n.NonSingularStringLiteralText
					echo '<span class="title">' . translate( $person_data[3] ) . "</span>\n";
				}
				echo "</li>\n";
			}
			echo "</ul>\n";
			break;
	}
}
class-wp-privacy-data-export-requests-list-table.php000064400000012673151212616050016626 0ustar00<?php
/**
 * List Table API: WP_Privacy_Data_Export_Requests_List_Table class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 4.9.6
 */

if ( ! class_exists( 'WP_Privacy_Requests_Table' ) ) {
	require_once ABSPATH . 'wp-admin/includes/class-wp-privacy-requests-table.php';
}

/**
 * WP_Privacy_Data_Export_Requests_Table class.
 *
 * @since 4.9.6
 */
class WP_Privacy_Data_Export_Requests_List_Table extends WP_Privacy_Requests_Table {
	/**
	 * Action name for the requests this table will work with.
	 *
	 * @since 4.9.6
	 *
	 * @var string $request_type Name of action.
	 */
	protected $request_type = 'export_personal_data';

	/**
	 * Post type for the requests.
	 *
	 * @since 4.9.6
	 *
	 * @var string $post_type The post type.
	 */
	protected $post_type = 'user_request';

	/**
	 * Actions column.
	 *
	 * @since 4.9.6
	 *
	 * @param WP_User_Request $item Item being shown.
	 * @return string Email column markup.
	 */
	public function column_email( $item ) {
		/** This filter is documented in wp-admin/includes/ajax-actions.php */
		$exporters       = apply_filters( 'wp_privacy_personal_data_exporters', array() );
		$exporters_count = count( $exporters );
		$status          = $item->status;
		$request_id      = $item->ID;
		$nonce           = wp_create_nonce( 'wp-privacy-export-personal-data-' . $request_id );

		$download_data_markup = '<span class="export-personal-data" ' .
			'data-exporters-count="' . esc_attr( $exporters_count ) . '" ' .
			'data-request-id="' . esc_attr( $request_id ) . '" ' .
			'data-nonce="' . esc_attr( $nonce ) .
			'">';

		$download_data_markup .= '<span class="export-personal-data-idle"><button type="button" class="button-link export-personal-data-handle">' . __( 'Download personal data' ) . '</button></span>' .
			'<span class="export-personal-data-processing hidden">' . __( 'Downloading data...' ) . ' <span class="export-progress"></span></span>' .
			'<span class="export-personal-data-success hidden"><button type="button" class="button-link export-personal-data-handle">' . __( 'Download personal data again' ) . '</button></span>' .
			'<span class="export-personal-data-failed hidden">' . __( 'Download failed.' ) . ' <button type="button" class="button-link export-personal-data-handle">' . __( 'Retry' ) . '</button></span>';

		$download_data_markup .= '</span>';

		$row_actions['download-data'] = $download_data_markup;

		if ( 'request-completed' !== $status ) {
			$complete_request_markup  = '<span>';
			$complete_request_markup .= sprintf(
				'<a href="%s" class="complete-request" aria-label="%s">%s</a>',
				esc_url(
					wp_nonce_url(
						add_query_arg(
							array(
								'action'     => 'complete',
								'request_id' => array( $request_id ),
							),
							admin_url( 'export-personal-data.php' )
						),
						'bulk-privacy_requests'
					)
				),
				esc_attr(
					sprintf(
						/* translators: %s: Request email. */
						__( 'Mark export request for &#8220;%s&#8221; as completed.' ),
						$item->email
					)
				),
				__( 'Complete request' )
			);
			$complete_request_markup .= '</span>';
		}

		if ( ! empty( $complete_request_markup ) ) {
			$row_actions['complete-request'] = $complete_request_markup;
		}

		return sprintf( '<a href="%1$s">%2$s</a> %3$s', esc_url( 'mailto:' . $item->email ), $item->email, $this->row_actions( $row_actions ) );
	}

	/**
	 * Displays the next steps column.
	 *
	 * @since 4.9.6
	 *
	 * @param WP_User_Request $item Item being shown.
	 */
	public function column_next_steps( $item ) {
		$status = $item->status;

		switch ( $status ) {
			case 'request-pending':
				esc_html_e( 'Waiting for confirmation' );
				break;
			case 'request-confirmed':
				/** This filter is documented in wp-admin/includes/ajax-actions.php */
				$exporters       = apply_filters( 'wp_privacy_personal_data_exporters', array() );
				$exporters_count = count( $exporters );
				$request_id      = $item->ID;
				$nonce           = wp_create_nonce( 'wp-privacy-export-personal-data-' . $request_id );

				echo '<div class="export-personal-data" ' .
					'data-send-as-email="1" ' .
					'data-exporters-count="' . esc_attr( $exporters_count ) . '" ' .
					'data-request-id="' . esc_attr( $request_id ) . '" ' .
					'data-nonce="' . esc_attr( $nonce ) .
					'">';

				?>
				<span class="export-personal-data-idle"><button type="button" class="button-link export-personal-data-handle"><?php _e( 'Send export link' ); ?></button></span>
				<span class="export-personal-data-processing hidden"><?php _e( 'Sending email...' ); ?> <span class="export-progress"></span></span>
				<span class="export-personal-data-success success-message hidden"><?php _e( 'Email sent.' ); ?></span>
				<span class="export-personal-data-failed hidden"><?php _e( 'Email could not be sent.' ); ?> <button type="button" class="button-link export-personal-data-handle"><?php _e( 'Retry' ); ?></button></span>
				<?php

				echo '</div>';
				break;
			case 'request-failed':
				echo '<button type="submit" class="button-link" name="privacy_action_email_retry[' . $item->ID . ']" id="privacy_action_email_retry[' . $item->ID . ']">' . __( 'Retry' ) . '</button>';
				break;
			case 'request-completed':
				echo '<a href="' . esc_url(
					wp_nonce_url(
						add_query_arg(
							array(
								'action'     => 'delete',
								'request_id' => array( $item->ID ),
							),
							admin_url( 'export-personal-data.php' )
						),
						'bulk-privacy_requests'
					)
				) . '">' . esc_html__( 'Remove request' ) . '</a>';
				break;
		}
	}
}
dashboard.php000064400000210271151212616050007206 0ustar00<?php
/**
 * WordPress Dashboard Widget Administration Screen API
 *
 * @package WordPress
 * @subpackage Administration
 */

/**
 * Registers dashboard widgets.
 *
 * Handles POST data, sets up filters.
 *
 * @since 2.5.0
 *
 * @global array $wp_registered_widgets
 * @global array $wp_registered_widget_controls
 * @global callable[] $wp_dashboard_control_callbacks
 */
function wp_dashboard_setup() {
	global $wp_registered_widgets, $wp_registered_widget_controls, $wp_dashboard_control_callbacks;

	$screen = get_current_screen();

	/* Register Widgets and Controls */
	$wp_dashboard_control_callbacks = array();

	// Browser version
	$check_browser = wp_check_browser_version();

	if ( $check_browser && $check_browser['upgrade'] ) {
		add_filter( 'postbox_classes_dashboard_dashboard_browser_nag', 'dashboard_browser_nag_class' );

		if ( $check_browser['insecure'] ) {
			wp_add_dashboard_widget( 'dashboard_browser_nag', __( 'You are using an insecure browser!' ), 'wp_dashboard_browser_nag' );
		} else {
			wp_add_dashboard_widget( 'dashboard_browser_nag', __( 'Your browser is out of date!' ), 'wp_dashboard_browser_nag' );
		}
	}

	// PHP Version.
	$check_php = wp_check_php_version();

	if ( $check_php && current_user_can( 'update_php' ) ) {
		// If "not acceptable" the widget will be shown.
		if ( isset( $check_php['is_acceptable'] ) && ! $check_php['is_acceptable'] ) {
			add_filter( 'postbox_classes_dashboard_dashboard_php_nag', 'dashboard_php_nag_class' );

			if ( $check_php['is_lower_than_future_minimum'] ) {
				wp_add_dashboard_widget( 'dashboard_php_nag', __( 'PHP Update Required' ), 'wp_dashboard_php_nag' );
			} else {
				wp_add_dashboard_widget( 'dashboard_php_nag', __( 'PHP Update Recommended' ), 'wp_dashboard_php_nag' );
			}
		}
	}

	// Site Health.
	if ( current_user_can( 'view_site_health_checks' ) && ! is_network_admin() ) {
		if ( ! class_exists( 'WP_Site_Health' ) ) {
			require_once ABSPATH . 'wp-admin/includes/class-wp-site-health.php';
		}

		WP_Site_Health::get_instance();

		wp_enqueue_style( 'site-health' );
		wp_enqueue_script( 'site-health' );

		wp_add_dashboard_widget( 'dashboard_site_health', __( 'Site Health Status' ), 'wp_dashboard_site_health' );
	}

	// Right Now.
	if ( is_blog_admin() && current_user_can( 'edit_posts' ) ) {
		wp_add_dashboard_widget( 'dashboard_right_now', __( 'At a Glance' ), 'wp_dashboard_right_now' );
	}

	if ( is_network_admin() ) {
		wp_add_dashboard_widget( 'network_dashboard_right_now', __( 'Right Now' ), 'wp_network_dashboard_right_now' );
	}

	// Activity Widget.
	if ( is_blog_admin() ) {
		wp_add_dashboard_widget( 'dashboard_activity', __( 'Activity' ), 'wp_dashboard_site_activity' );
	}

	// QuickPress Widget.
	if ( is_blog_admin() && current_user_can( get_post_type_object( 'post' )->cap->create_posts ) ) {
		$quick_draft_title = sprintf( '<span class="hide-if-no-js">%1$s</span> <span class="hide-if-js">%2$s</span>', __( 'Quick Draft' ), __( 'Your Recent Drafts' ) );
		wp_add_dashboard_widget( 'dashboard_quick_press', $quick_draft_title, 'wp_dashboard_quick_press' );
	}

	// WordPress Events and News.
	wp_add_dashboard_widget( 'dashboard_primary', __( 'WordPress Events and News' ), 'wp_dashboard_events_news' );

	if ( is_network_admin() ) {

		/**
		 * Fires after core widgets for the Network Admin dashboard have been registered.
		 *
		 * @since 3.1.0
		 */
		do_action( 'wp_network_dashboard_setup' );

		/**
		 * Filters the list of widgets to load for the Network Admin dashboard.
		 *
		 * @since 3.1.0
		 *
		 * @param string[] $dashboard_widgets An array of dashboard widget IDs.
		 */
		$dashboard_widgets = apply_filters( 'wp_network_dashboard_widgets', array() );
	} elseif ( is_user_admin() ) {

		/**
		 * Fires after core widgets for the User Admin dashboard have been registered.
		 *
		 * @since 3.1.0
		 */
		do_action( 'wp_user_dashboard_setup' );

		/**
		 * Filters the list of widgets to load for the User Admin dashboard.
		 *
		 * @since 3.1.0
		 *
		 * @param string[] $dashboard_widgets An array of dashboard widget IDs.
		 */
		$dashboard_widgets = apply_filters( 'wp_user_dashboard_widgets', array() );
	} else {

		/**
		 * Fires after core widgets for the admin dashboard have been registered.
		 *
		 * @since 2.5.0
		 */
		do_action( 'wp_dashboard_setup' );

		/**
		 * Filters the list of widgets to load for the admin dashboard.
		 *
		 * @since 2.5.0
		 *
		 * @param string[] $dashboard_widgets An array of dashboard widget IDs.
		 */
		$dashboard_widgets = apply_filters( 'wp_dashboard_widgets', array() );
	}

	foreach ( $dashboard_widgets as $widget_id ) {
		$name = empty( $wp_registered_widgets[ $widget_id ]['all_link'] ) ? $wp_registered_widgets[ $widget_id ]['name'] : $wp_registered_widgets[ $widget_id ]['name'] . " <a href='{$wp_registered_widgets[$widget_id]['all_link']}' class='edit-box open-box'>" . __( 'View all' ) . '</a>';
		wp_add_dashboard_widget( $widget_id, $name, $wp_registered_widgets[ $widget_id ]['callback'], $wp_registered_widget_controls[ $widget_id ]['callback'] );
	}

	if ( 'POST' === $_SERVER['REQUEST_METHOD'] && isset( $_POST['widget_id'] ) ) {
		check_admin_referer( 'edit-dashboard-widget_' . $_POST['widget_id'], 'dashboard-widget-nonce' );
		ob_start(); // Hack - but the same hack wp-admin/widgets.php uses.
		wp_dashboard_trigger_widget_control( $_POST['widget_id'] );
		ob_end_clean();
		wp_redirect( remove_query_arg( 'edit' ) );
		exit;
	}

	/** This action is documented in wp-admin/includes/meta-boxes.php */
	do_action( 'do_meta_boxes', $screen->id, 'normal', '' );

	/** This action is documented in wp-admin/includes/meta-boxes.php */
	do_action( 'do_meta_boxes', $screen->id, 'side', '' );
}

/**
 * Adds a new dashboard widget.
 *
 * @since 2.7.0
 * @since 5.6.0 The `$context` and `$priority` parameters were added.
 *
 * @global callable[] $wp_dashboard_control_callbacks
 *
 * @param string   $widget_id        Widget ID  (used in the 'id' attribute for the widget).
 * @param string   $widget_name      Title of the widget.
 * @param callable $callback         Function that fills the widget with the desired content.
 *                                   The function should echo its output.
 * @param callable $control_callback Optional. Function that outputs controls for the widget. Default null.
 * @param array    $callback_args    Optional. Data that should be set as the $args property of the widget array
 *                                   (which is the second parameter passed to your callback). Default null.
 * @param string   $context          Optional. The context within the screen where the box should display.
 *                                   Accepts 'normal', 'side', 'column3', or 'column4'. Default 'normal'.
 * @param string   $priority         Optional. The priority within the context where the box should show.
 *                                   Accepts 'high', 'core', 'default', or 'low'. Default 'core'.
 */
function wp_add_dashboard_widget( $widget_id, $widget_name, $callback, $control_callback = null, $callback_args = null, $context = 'normal', $priority = 'core' ) {
	global $wp_dashboard_control_callbacks;

	$screen = get_current_screen();

	$private_callback_args = array( '__widget_basename' => $widget_name );

	if ( is_null( $callback_args ) ) {
		$callback_args = $private_callback_args;
	} elseif ( is_array( $callback_args ) ) {
		$callback_args = array_merge( $callback_args, $private_callback_args );
	}

	if ( $control_callback && is_callable( $control_callback ) && current_user_can( 'edit_dashboard' ) ) {
		$wp_dashboard_control_callbacks[ $widget_id ] = $control_callback;

		if ( isset( $_GET['edit'] ) && $widget_id === $_GET['edit'] ) {
			list($url)    = explode( '#', add_query_arg( 'edit', false ), 2 );
			$widget_name .= ' <span class="postbox-title-action"><a href="' . esc_url( $url ) . '">' . __( 'Cancel' ) . '</a></span>';
			$callback     = '_wp_dashboard_control_callback';
		} else {
			list($url)    = explode( '#', add_query_arg( 'edit', $widget_id ), 2 );
			$widget_name .= ' <span class="postbox-title-action"><a href="' . esc_url( "$url#$widget_id" ) . '" class="edit-box open-box">' . __( 'Configure' ) . '</a></span>';
		}
	}

	$side_widgets = array( 'dashboard_quick_press', 'dashboard_primary' );

	if ( in_array( $widget_id, $side_widgets, true ) ) {
		$context = 'side';
	}

	$high_priority_widgets = array( 'dashboard_browser_nag', 'dashboard_php_nag' );

	if ( in_array( $widget_id, $high_priority_widgets, true ) ) {
		$priority = 'high';
	}

	if ( empty( $context ) ) {
		$context = 'normal';
	}

	if ( empty( $priority ) ) {
		$priority = 'core';
	}

	add_meta_box( $widget_id, $widget_name, $callback, $screen, $context, $priority, $callback_args );
}

/**
 * Outputs controls for the current dashboard widget.
 *
 * @access private
 * @since 2.7.0
 *
 * @param mixed $dashboard
 * @param array $meta_box
 */
function _wp_dashboard_control_callback( $dashboard, $meta_box ) {
	echo '<form method="post" class="dashboard-widget-control-form wp-clearfix">';
	wp_dashboard_trigger_widget_control( $meta_box['id'] );
	wp_nonce_field( 'edit-dashboard-widget_' . $meta_box['id'], 'dashboard-widget-nonce' );
	echo '<input type="hidden" name="widget_id" value="' . esc_attr( $meta_box['id'] ) . '" />';
	submit_button( __( 'Save Changes' ) );
	echo '</form>';
}

/**
 * Displays the dashboard.
 *
 * @since 2.5.0
 */
function wp_dashboard() {
	$screen      = get_current_screen();
	$columns     = absint( $screen->get_columns() );
	$columns_css = '';

	if ( $columns ) {
		$columns_css = " columns-$columns";
	}
	?>
<div id="dashboard-widgets" class="metabox-holder<?php echo $columns_css; ?>">
	<div id="postbox-container-1" class="postbox-container">
	<?php do_meta_boxes( $screen->id, 'normal', '' ); ?>
	</div>
	<div id="postbox-container-2" class="postbox-container">
	<?php do_meta_boxes( $screen->id, 'side', '' ); ?>
	</div>
	<div id="postbox-container-3" class="postbox-container">
	<?php do_meta_boxes( $screen->id, 'column3', '' ); ?>
	</div>
	<div id="postbox-container-4" class="postbox-container">
	<?php do_meta_boxes( $screen->id, 'column4', '' ); ?>
	</div>
</div>

	<?php
	wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
	wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false );
}

//
// Dashboard Widgets.
//

/**
 * Dashboard widget that displays some basic stats about the site.
 *
 * Formerly 'Right Now'. A streamlined 'At a Glance' as of 3.8.
 *
 * @since 2.7.0
 */
function wp_dashboard_right_now() {
	?>
	<div class="main">
	<ul>
	<?php
	// Posts and Pages.
	foreach ( array( 'post', 'page' ) as $post_type ) {
		$num_posts = wp_count_posts( $post_type );

		if ( $num_posts && $num_posts->publish ) {
			if ( 'post' === $post_type ) {
				/* translators: %s: Number of posts. */
				$text = _n( '%s Post', '%s Posts', $num_posts->publish );
			} else {
				/* translators: %s: Number of pages. */
				$text = _n( '%s Page', '%s Pages', $num_posts->publish );
			}

			$text             = sprintf( $text, number_format_i18n( $num_posts->publish ) );
			$post_type_object = get_post_type_object( $post_type );

			if ( $post_type_object && current_user_can( $post_type_object->cap->edit_posts ) ) {
				printf( '<li class="%1$s-count"><a href="edit.php?post_type=%1$s">%2$s</a></li>', $post_type, $text );
			} else {
				printf( '<li class="%1$s-count"><span>%2$s</span></li>', $post_type, $text );
			}
		}
	}

	// Comments.
	$num_comm = wp_count_comments();

	if ( $num_comm && ( $num_comm->approved || $num_comm->moderated ) ) {
		/* translators: %s: Number of comments. */
		$text = sprintf( _n( '%s Comment', '%s Comments', $num_comm->approved ), number_format_i18n( $num_comm->approved ) );
		?>
		<li class="comment-count">
			<a href="edit-comments.php"><?php echo $text; ?></a>
		</li>
		<?php
		$moderated_comments_count_i18n = number_format_i18n( $num_comm->moderated );
		/* translators: %s: Number of comments. */
		$text = sprintf( _n( '%s Comment in moderation', '%s Comments in moderation', $num_comm->moderated ), $moderated_comments_count_i18n );
		?>
		<li class="comment-mod-count<?php echo ! $num_comm->moderated ? ' hidden' : ''; ?>">
			<a href="edit-comments.php?comment_status=moderated" class="comments-in-moderation-text"><?php echo $text; ?></a>
		</li>
		<?php
	}

	/**
	 * Filters the array of extra elements to list in the 'At a Glance'
	 * dashboard widget.
	 *
	 * Prior to 3.8.0, the widget was named 'Right Now'. Each element
	 * is wrapped in list-item tags on output.
	 *
	 * @since 3.8.0
	 *
	 * @param string[] $items Array of extra 'At a Glance' widget items.
	 */
	$elements = apply_filters( 'dashboard_glance_items', array() );

	if ( $elements ) {
		echo '<li>' . implode( "</li>\n<li>", $elements ) . "</li>\n";
	}

	?>
	</ul>
	<?php
	update_right_now_message();

	// Check if search engines are asked not to index this site.
	if ( ! is_network_admin() && ! is_user_admin()
		&& current_user_can( 'manage_options' ) && ! get_option( 'blog_public' )
	) {

		/**
		 * Filters the link title attribute for the 'Search engines discouraged'
		 * message displayed in the 'At a Glance' dashboard widget.
		 *
		 * Prior to 3.8.0, the widget was named 'Right Now'.
		 *
		 * @since 3.0.0
		 * @since 4.5.0 The default for `$title` was updated to an empty string.
		 *
		 * @param string $title Default attribute text.
		 */
		$title = apply_filters( 'privacy_on_link_title', '' );

		/**
		 * Filters the link label for the 'Search engines discouraged' message
		 * displayed in the 'At a Glance' dashboard widget.
		 *
		 * Prior to 3.8.0, the widget was named 'Right Now'.
		 *
		 * @since 3.0.0
		 *
		 * @param string $content Default text.
		 */
		$content = apply_filters( 'privacy_on_link_text', __( 'Search engines discouraged' ) );

		$title_attr = '' === $title ? '' : " title='$title'";

		echo "<p class='search-engines-info'><a href='options-reading.php'$title_attr>$content</a></p>";
	}
	?>
	</div>
	<?php
	/*
	 * activity_box_end has a core action, but only prints content when multisite.
	 * Using an output buffer is the only way to really check if anything's displayed here.
	 */
	ob_start();

	/**
	 * Fires at the end of the 'At a Glance' dashboard widget.
	 *
	 * Prior to 3.8.0, the widget was named 'Right Now'.
	 *
	 * @since 2.5.0
	 */
	do_action( 'rightnow_end' );

	/**
	 * Fires at the end of the 'At a Glance' dashboard widget.
	 *
	 * Prior to 3.8.0, the widget was named 'Right Now'.
	 *
	 * @since 2.0.0
	 */
	do_action( 'activity_box_end' );

	$actions = ob_get_clean();

	if ( ! empty( $actions ) ) :
		?>
	<div class="sub">
		<?php echo $actions; ?>
	</div>
		<?php
	endif;
}

/**
 * @since 3.1.0
 */
function wp_network_dashboard_right_now() {
	$actions = array();

	if ( current_user_can( 'create_sites' ) ) {
		$actions['create-site'] = '<a href="' . network_admin_url( 'site-new.php' ) . '">' . __( 'Create a New Site' ) . '</a>';
	}
	if ( current_user_can( 'create_users' ) ) {
		$actions['create-user'] = '<a href="' . network_admin_url( 'user-new.php' ) . '">' . __( 'Create a New User' ) . '</a>';
	}

	$c_users = get_user_count();
	$c_blogs = get_blog_count();

	/* translators: %s: Number of users on the network. */
	$user_text = sprintf( _n( '%s user', '%s users', $c_users ), number_format_i18n( $c_users ) );
	/* translators: %s: Number of sites on the network. */
	$blog_text = sprintf( _n( '%s site', '%s sites', $c_blogs ), number_format_i18n( $c_blogs ) );

	/* translators: 1: Text indicating the number of sites on the network, 2: Text indicating the number of users on the network. */
	$sentence = sprintf( __( 'You have %1$s and %2$s.' ), $blog_text, $user_text );

	if ( $actions ) {
		echo '<ul class="subsubsub">';
		foreach ( $actions as $class => $action ) {
			$actions[ $class ] = "\t<li class='$class'>$action";
		}
		echo implode( " |</li>\n", $actions ) . "</li>\n";
		echo '</ul>';
	}
	?>
	<br class="clear" />

	<p class="youhave"><?php echo $sentence; ?></p>


	<?php
		/**
		 * Fires in the Network Admin 'Right Now' dashboard widget
		 * just before the user and site search form fields.
		 *
		 * @since MU (3.0.0)
		 */
		do_action( 'wpmuadminresult' );
	?>

	<form action="<?php echo esc_url( network_admin_url( 'users.php' ) ); ?>" method="get">
		<p>
			<label class="screen-reader-text" for="search-users">
				<?php
				/* translators: Hidden accessibility text. */
				_e( 'Search Users' );
				?>
			</label>
			<input type="search" name="s" value="" size="30" autocomplete="off" id="search-users" />
			<?php submit_button( __( 'Search Users' ), '', false, false, array( 'id' => 'submit_users' ) ); ?>
		</p>
	</form>

	<form action="<?php echo esc_url( network_admin_url( 'sites.php' ) ); ?>" method="get">
		<p>
			<label class="screen-reader-text" for="search-sites">
				<?php
				/* translators: Hidden accessibility text. */
				_e( 'Search Sites' );
				?>
			</label>
			<input type="search" name="s" value="" size="30" autocomplete="off" id="search-sites" />
			<?php submit_button( __( 'Search Sites' ), '', false, false, array( 'id' => 'submit_sites' ) ); ?>
		</p>
	</form>
	<?php
	/**
	 * Fires at the end of the 'Right Now' widget in the Network Admin dashboard.
	 *
	 * @since MU (3.0.0)
	 */
	do_action( 'mu_rightnow_end' );

	/**
	 * Fires at the end of the 'Right Now' widget in the Network Admin dashboard.
	 *
	 * @since MU (3.0.0)
	 */
	do_action( 'mu_activity_box_end' );
}

/**
 * Displays the Quick Draft widget.
 *
 * @since 3.8.0
 *
 * @global int $post_ID
 *
 * @param string|false $error_msg Optional. Error message. Default false.
 */
function wp_dashboard_quick_press( $error_msg = false ) {
	global $post_ID;

	if ( ! current_user_can( 'edit_posts' ) ) {
		return;
	}

	// Check if a new auto-draft (= no new post_ID) is needed or if the old can be used.
	$last_post_id = (int) get_user_option( 'dashboard_quick_press_last_post_id' ); // Get the last post_ID.

	if ( $last_post_id ) {
		$post = get_post( $last_post_id );

		if ( empty( $post ) || 'auto-draft' !== $post->post_status ) { // auto-draft doesn't exist anymore.
			$post = get_default_post_to_edit( 'post', true );
			update_user_option( get_current_user_id(), 'dashboard_quick_press_last_post_id', (int) $post->ID ); // Save post_ID.
		} else {
			$post->post_title = ''; // Remove the auto draft title.
		}
	} else {
		$post    = get_default_post_to_edit( 'post', true );
		$user_id = get_current_user_id();

		// Don't create an option if this is a super admin who does not belong to this site.
		if ( in_array( get_current_blog_id(), array_keys( get_blogs_of_user( $user_id ) ), true ) ) {
			update_user_option( $user_id, 'dashboard_quick_press_last_post_id', (int) $post->ID ); // Save post_ID.
		}
	}

	$post_ID = (int) $post->ID;
	?>

	<form name="post" action="<?php echo esc_url( admin_url( 'post.php' ) ); ?>" method="post" id="quick-press" class="initial-form hide-if-no-js">

		<?php
		if ( $error_msg ) {
			wp_admin_notice(
				$error_msg,
				array(
					'additional_classes' => array( 'error' ),
				)
			);
		}
		?>

		<div class="input-text-wrap" id="title-wrap">
			<label for="title">
				<?php
				/** This filter is documented in wp-admin/edit-form-advanced.php */
				echo apply_filters( 'enter_title_here', __( 'Title' ), $post );
				?>
			</label>
			<input type="text" name="post_title" id="title" autocomplete="off" />
		</div>

		<div class="textarea-wrap" id="description-wrap">
			<label for="content"><?php _e( 'Content' ); ?></label>
			<textarea name="content" id="content" placeholder="<?php esc_attr_e( 'What&#8217;s on your mind?' ); ?>" class="mceEditor" rows="3" cols="15" autocomplete="off"></textarea>
		</div>

		<p class="submit">
			<input type="hidden" name="action" id="quickpost-action" value="post-quickdraft-save" />
			<input type="hidden" name="post_ID" value="<?php echo $post_ID; ?>" />
			<input type="hidden" name="post_type" value="post" />
			<?php wp_nonce_field( 'add-post' ); ?>
			<?php submit_button( __( 'Save Draft' ), 'primary', 'save', false, array( 'id' => 'save-post' ) ); ?>
			<br class="clear" />
		</p>

	</form>
	<?php
	wp_dashboard_recent_drafts();
}

/**
 * Show recent drafts of the user on the dashboard.
 *
 * @since 2.7.0
 *
 * @param WP_Post[]|false $drafts Optional. Array of posts to display. Default false.
 */
function wp_dashboard_recent_drafts( $drafts = false ) {
	if ( ! $drafts ) {
		$query_args = array(
			'post_type'      => 'post',
			'post_status'    => 'draft',
			'author'         => get_current_user_id(),
			'posts_per_page' => 4,
			'orderby'        => 'modified',
			'order'          => 'DESC',
		);

		/**
		 * Filters the post query arguments for the 'Recent Drafts' dashboard widget.
		 *
		 * @since 4.4.0
		 *
		 * @param array $query_args The query arguments for the 'Recent Drafts' dashboard widget.
		 */
		$query_args = apply_filters( 'dashboard_recent_drafts_query_args', $query_args );

		$drafts = get_posts( $query_args );
		if ( ! $drafts ) {
			return;
		}
	}

	echo '<div class="drafts">';

	if ( count( $drafts ) > 3 ) {
		printf(
			'<p class="view-all"><a href="%s">%s</a></p>' . "\n",
			esc_url( admin_url( 'edit.php?post_status=draft' ) ),
			__( 'View all drafts' )
		);
	}

	echo '<h2 class="hide-if-no-js">' . __( 'Your Recent Drafts' ) . "</h2>\n";
	echo '<ul>';

	/* translators: Maximum number of words used in a preview of a draft on the dashboard. */
	$draft_length = (int) _x( '10', 'draft_length' );

	$drafts = array_slice( $drafts, 0, 3 );
	foreach ( $drafts as $draft ) {
		$url   = get_edit_post_link( $draft->ID );
		$title = _draft_or_post_title( $draft->ID );

		echo "<li>\n";
		printf(
			'<div class="draft-title"><a href="%s" aria-label="%s">%s</a><time datetime="%s">%s</time></div>',
			esc_url( $url ),
			/* translators: %s: Post title. */
			esc_attr( sprintf( __( 'Edit &#8220;%s&#8221;' ), $title ) ),
			esc_html( $title ),
			get_the_time( 'c', $draft ),
			get_the_time( __( 'F j, Y' ), $draft )
		);

		$the_content = wp_trim_words( $draft->post_content, $draft_length );

		if ( $the_content ) {
			echo '<p>' . $the_content . '</p>';
		}
		echo "</li>\n";
	}

	echo "</ul>\n";
	echo '</div>';
}

/**
 * Outputs a row for the Recent Comments widget.
 *
 * @access private
 * @since 2.7.0
 *
 * @global WP_Comment $comment Global comment object.
 *
 * @param WP_Comment $comment   The current comment.
 * @param bool       $show_date Optional. Whether to display the date.
 */
function _wp_dashboard_recent_comments_row( &$comment, $show_date = true ) {
	$GLOBALS['comment'] = clone $comment;

	if ( $comment->comment_post_ID > 0 ) {
		$comment_post_title = _draft_or_post_title( $comment->comment_post_ID );
		$comment_post_url   = get_the_permalink( $comment->comment_post_ID );
		$comment_post_link  = '<a href="' . esc_url( $comment_post_url ) . '">' . $comment_post_title . '</a>';
	} else {
		$comment_post_link = '';
	}

	$actions_string = '';
	if ( current_user_can( 'edit_comment', $comment->comment_ID ) ) {
		// Pre-order it: Approve | Reply | Edit | Spam | Trash.
		$actions = array(
			'approve'   => '',
			'unapprove' => '',
			'reply'     => '',
			'edit'      => '',
			'spam'      => '',
			'trash'     => '',
			'delete'    => '',
			'view'      => '',
		);

		$approve_nonce = esc_html( '_wpnonce=' . wp_create_nonce( 'approve-comment_' . $comment->comment_ID ) );
		$del_nonce     = esc_html( '_wpnonce=' . wp_create_nonce( 'delete-comment_' . $comment->comment_ID ) );

		$action_string = 'comment.php?action=%s&p=' . $comment->comment_post_ID . '&c=' . $comment->comment_ID . '&%s';

		$approve_url   = sprintf( $action_string, 'approvecomment', $approve_nonce );
		$unapprove_url = sprintf( $action_string, 'unapprovecomment', $approve_nonce );
		$spam_url      = sprintf( $action_string, 'spamcomment', $del_nonce );
		$trash_url     = sprintf( $action_string, 'trashcomment', $del_nonce );
		$delete_url    = sprintf( $action_string, 'deletecomment', $del_nonce );

		$actions['approve'] = sprintf(
			'<a href="%s" data-wp-lists="%s" class="vim-a aria-button-if-js" aria-label="%s">%s</a>',
			esc_url( $approve_url ),
			"dim:the-comment-list:comment-{$comment->comment_ID}:unapproved:e7e7d3:e7e7d3:new=approved",
			esc_attr__( 'Approve this comment' ),
			__( 'Approve' )
		);

		$actions['unapprove'] = sprintf(
			'<a href="%s" data-wp-lists="%s" class="vim-u aria-button-if-js" aria-label="%s">%s</a>',
			esc_url( $unapprove_url ),
			"dim:the-comment-list:comment-{$comment->comment_ID}:unapproved:e7e7d3:e7e7d3:new=unapproved",
			esc_attr__( 'Unapprove this comment' ),
			__( 'Unapprove' )
		);

		$actions['edit'] = sprintf(
			'<a href="%s" aria-label="%s">%s</a>',
			"comment.php?action=editcomment&amp;c={$comment->comment_ID}",
			esc_attr__( 'Edit this comment' ),
			__( 'Edit' )
		);

		$actions['reply'] = sprintf(
			'<button type="button" onclick="window.commentReply && commentReply.open(\'%s\',\'%s\');" class="vim-r button-link hide-if-no-js" aria-label="%s">%s</button>',
			$comment->comment_ID,
			$comment->comment_post_ID,
			esc_attr__( 'Reply to this comment' ),
			__( 'Reply' )
		);

		$actions['spam'] = sprintf(
			'<a href="%s" data-wp-lists="%s" class="vim-s vim-destructive aria-button-if-js" aria-label="%s">%s</a>',
			esc_url( $spam_url ),
			"delete:the-comment-list:comment-{$comment->comment_ID}::spam=1",
			esc_attr__( 'Mark this comment as spam' ),
			/* translators: "Mark as spam" link. */
			_x( 'Spam', 'verb' )
		);

		if ( ! EMPTY_TRASH_DAYS ) {
			$actions['delete'] = sprintf(
				'<a href="%s" data-wp-lists="%s" class="delete vim-d vim-destructive aria-button-if-js" aria-label="%s">%s</a>',
				esc_url( $delete_url ),
				"delete:the-comment-list:comment-{$comment->comment_ID}::trash=1",
				esc_attr__( 'Delete this comment permanently' ),
				__( 'Delete Permanently' )
			);
		} else {
			$actions['trash'] = sprintf(
				'<a href="%s" data-wp-lists="%s" class="delete vim-d vim-destructive aria-button-if-js" aria-label="%s">%s</a>',
				esc_url( $trash_url ),
				"delete:the-comment-list:comment-{$comment->comment_ID}::trash=1",
				esc_attr__( 'Move this comment to the Trash' ),
				_x( 'Trash', 'verb' )
			);
		}

		$actions['view'] = sprintf(
			'<a class="comment-link" href="%s" aria-label="%s">%s</a>',
			esc_url( get_comment_link( $comment ) ),
			esc_attr__( 'View this comment' ),
			__( 'View' )
		);

		/** This filter is documented in wp-admin/includes/class-wp-comments-list-table.php */
		$actions = apply_filters( 'comment_row_actions', array_filter( $actions ), $comment );

		$i = 0;

		foreach ( $actions as $action => $link ) {
			++$i;

			if ( ( ( 'approve' === $action || 'unapprove' === $action ) && 2 === $i )
				|| 1 === $i
			) {
				$separator = '';
			} else {
				$separator = ' | ';
			}

			// Reply and quickedit need a hide-if-no-js span.
			if ( 'reply' === $action || 'quickedit' === $action ) {
				$action .= ' hide-if-no-js';
			}

			if ( 'view' === $action && '1' !== $comment->comment_approved ) {
				$action .= ' hidden';
			}

			$actions_string .= "<span class='$action'>{$separator}{$link}</span>";
		}
	}
	?>

		<li id="comment-<?php echo $comment->comment_ID; ?>" <?php comment_class( array( 'comment-item', wp_get_comment_status( $comment ) ), $comment ); ?>>

			<?php
			$comment_row_class = '';

			if ( get_option( 'show_avatars' ) ) {
				echo get_avatar( $comment, 50, 'mystery' );
				$comment_row_class .= ' has-avatar';
			}
			?>

			<?php if ( ! $comment->comment_type || 'comment' === $comment->comment_type ) : ?>

			<div class="dashboard-comment-wrap has-row-actions <?php echo $comment_row_class; ?>">
			<p class="comment-meta">
				<?php
				// Comments might not have a post they relate to, e.g. programmatically created ones.
				if ( $comment_post_link ) {
					printf(
						/* translators: 1: Comment author, 2: Post link, 3: Notification if the comment is pending. */
						__( 'From %1$s on %2$s %3$s' ),
						'<cite class="comment-author">' . get_comment_author_link( $comment ) . '</cite>',
						$comment_post_link,
						'<span class="approve">' . __( '[Pending]' ) . '</span>'
					);
				} else {
					printf(
						/* translators: 1: Comment author, 2: Notification if the comment is pending. */
						__( 'From %1$s %2$s' ),
						'<cite class="comment-author">' . get_comment_author_link( $comment ) . '</cite>',
						'<span class="approve">' . __( '[Pending]' ) . '</span>'
					);
				}
				?>
			</p>

				<?php
			else :
				switch ( $comment->comment_type ) {
					case 'pingback':
						$type = __( 'Pingback' );
						break;
					case 'trackback':
						$type = __( 'Trackback' );
						break;
					default:
						$type = ucwords( $comment->comment_type );
				}
				$type = esc_html( $type );
				?>
			<div class="dashboard-comment-wrap has-row-actions">
			<p class="comment-meta">
				<?php
				// Pingbacks, Trackbacks or custom comment types might not have a post they relate to, e.g. programmatically created ones.
				if ( $comment_post_link ) {
					printf(
						/* translators: 1: Type of comment, 2: Post link, 3: Notification if the comment is pending. */
						_x( '%1$s on %2$s %3$s', 'dashboard' ),
						"<strong>$type</strong>",
						$comment_post_link,
						'<span class="approve">' . __( '[Pending]' ) . '</span>'
					);
				} else {
					printf(
						/* translators: 1: Type of comment, 2: Notification if the comment is pending. */
						_x( '%1$s %2$s', 'dashboard' ),
						"<strong>$type</strong>",
						'<span class="approve">' . __( '[Pending]' ) . '</span>'
					);
				}
				?>
			</p>
			<p class="comment-author"><?php comment_author_link( $comment ); ?></p>

			<?php endif; // comment_type ?>
			<blockquote><p><?php comment_excerpt( $comment ); ?></p></blockquote>
			<?php if ( $actions_string ) : ?>
			<p class="row-actions"><?php echo $actions_string; ?></p>
			<?php endif; ?>
			</div>
		</li>
	<?php
	$GLOBALS['comment'] = null;
}

/**
 * Outputs the Activity widget.
 *
 * Callback function for {@see 'dashboard_activity'}.
 *
 * @since 3.8.0
 */
function wp_dashboard_site_activity() {

	echo '<div id="activity-widget">';

	$future_posts = wp_dashboard_recent_posts(
		array(
			'max'    => 5,
			'status' => 'future',
			'order'  => 'ASC',
			'title'  => __( 'Publishing Soon' ),
			'id'     => 'future-posts',
		)
	);
	$recent_posts = wp_dashboard_recent_posts(
		array(
			'max'    => 5,
			'status' => 'publish',
			'order'  => 'DESC',
			'title'  => __( 'Recently Published' ),
			'id'     => 'published-posts',
		)
	);

	$recent_comments = wp_dashboard_recent_comments();

	if ( ! $future_posts && ! $recent_posts && ! $recent_comments ) {
		echo '<div class="no-activity">';
		echo '<p>' . __( 'No activity yet!' ) . '</p>';
		echo '</div>';
	}

	echo '</div>';
}

/**
 * Generates Publishing Soon and Recently Published sections.
 *
 * @since 3.8.0
 *
 * @param array $args {
 *     An array of query and display arguments.
 *
 *     @type int    $max     Number of posts to display.
 *     @type string $status  Post status.
 *     @type string $order   Designates ascending ('ASC') or descending ('DESC') order.
 *     @type string $title   Section title.
 *     @type string $id      The container id.
 * }
 * @return bool False if no posts were found. True otherwise.
 */
function wp_dashboard_recent_posts( $args ) {
	$query_args = array(
		'post_type'      => 'post',
		'post_status'    => $args['status'],
		'orderby'        => 'date',
		'order'          => $args['order'],
		'posts_per_page' => (int) $args['max'],
		'no_found_rows'  => true,
		'cache_results'  => true,
		'perm'           => ( 'future' === $args['status'] ) ? 'editable' : 'readable',
	);

	/**
	 * Filters the query arguments used for the Recent Posts widget.
	 *
	 * @since 4.2.0
	 *
	 * @param array $query_args The arguments passed to WP_Query to produce the list of posts.
	 */
	$query_args = apply_filters( 'dashboard_recent_posts_query_args', $query_args );

	$posts = new WP_Query( $query_args );

	if ( $posts->have_posts() ) {

		echo '<div id="' . $args['id'] . '" class="activity-block">';

		echo '<h3>' . $args['title'] . '</h3>';

		echo '<ul>';

		$today    = current_time( 'Y-m-d' );
		$tomorrow = current_datetime()->modify( '+1 day' )->format( 'Y-m-d' );
		$year     = current_time( 'Y' );

		while ( $posts->have_posts() ) {
			$posts->the_post();

			$time = get_the_time( 'U' );

			if ( gmdate( 'Y-m-d', $time ) === $today ) {
				$relative = __( 'Today' );
			} elseif ( gmdate( 'Y-m-d', $time ) === $tomorrow ) {
				$relative = __( 'Tomorrow' );
			} elseif ( gmdate( 'Y', $time ) !== $year ) {
				/* translators: Date and time format for recent posts on the dashboard, from a different calendar year, see https://www.php.net/manual/datetime.format.php */
				$relative = date_i18n( __( 'M jS Y' ), $time );
			} else {
				/* translators: Date and time format for recent posts on the dashboard, see https://www.php.net/manual/datetime.format.php */
				$relative = date_i18n( __( 'M jS' ), $time );
			}

			// Use the post edit link for those who can edit, the permalink otherwise.
			$recent_post_link = current_user_can( 'edit_post', get_the_ID() ) ? get_edit_post_link() : get_permalink();

			$draft_or_post_title = _draft_or_post_title();
			printf(
				'<li><span>%1$s</span> <a href="%2$s" aria-label="%3$s">%4$s</a></li>',
				/* translators: 1: Relative date, 2: Time. */
				sprintf( _x( '%1$s, %2$s', 'dashboard' ), $relative, get_the_time() ),
				$recent_post_link,
				/* translators: %s: Post title. */
				esc_attr( sprintf( __( 'Edit &#8220;%s&#8221;' ), $draft_or_post_title ) ),
				$draft_or_post_title
			);
		}

		echo '</ul>';
		echo '</div>';

	} else {
		return false;
	}

	wp_reset_postdata();

	return true;
}

/**
 * Show Comments section.
 *
 * @since 3.8.0
 *
 * @param int $total_items Optional. Number of comments to query. Default 5.
 * @return bool False if no comments were found. True otherwise.
 */
function wp_dashboard_recent_comments( $total_items = 5 ) {
	// Select all comment types and filter out spam later for better query performance.
	$comments = array();

	$comments_query = array(
		'number' => $total_items * 5,
		'offset' => 0,
	);

	if ( ! current_user_can( 'edit_posts' ) ) {
		$comments_query['status'] = 'approve';
	}

	$comments_count = 0;
	do {
		$possible = get_comments( $comments_query );

		if ( empty( $possible ) || ! is_array( $possible ) ) {
			break;
		}

		foreach ( $possible as $comment ) {
			if ( ! current_user_can( 'edit_post', $comment->comment_post_ID )
				&& ( post_password_required( $comment->comment_post_ID )
					|| ! current_user_can( 'read_post', $comment->comment_post_ID ) )
			) {
				// The user has no access to the post and thus cannot see the comments.
				continue;
			}

			$comments[]     = $comment;
			$comments_count = count( $comments );

			if ( $comments_count === $total_items ) {
				break 2;
			}
		}

		$comments_query['offset'] += $comments_query['number'];
		$comments_query['number']  = $total_items * 10;
	} while ( $comments_count < $total_items );

	if ( $comments ) {
		echo '<div id="latest-comments" class="activity-block table-view-list">';
		echo '<h3>' . __( 'Recent Comments' ) . '</h3>';

		echo '<ul id="the-comment-list" data-wp-lists="list:comment">';
		foreach ( $comments as $comment ) {
			_wp_dashboard_recent_comments_row( $comment );
		}
		echo '</ul>';

		if ( current_user_can( 'edit_posts' ) ) {
			echo '<h3 class="screen-reader-text">' .
				/* translators: Hidden accessibility text. */
				__( 'View more comments' ) .
			'</h3>';
			_get_list_table( 'WP_Comments_List_Table' )->views();
		}

		wp_comment_reply( -1, false, 'dashboard', false );
		wp_comment_trashnotice();

		echo '</div>';
	} else {
		return false;
	}
	return true;
}

/**
 * Display generic dashboard RSS widget feed.
 *
 * @since 2.5.0
 *
 * @param string $widget_id
 */
function wp_dashboard_rss_output( $widget_id ) {
	$widgets = get_option( 'dashboard_widget_options' );
	echo '<div class="rss-widget">';
	wp_widget_rss_output( $widgets[ $widget_id ] );
	echo '</div>';
}

/**
 * Checks to see if all of the feed url in $check_urls are cached.
 *
 * If $check_urls is empty, look for the rss feed url found in the dashboard
 * widget options of $widget_id. If cached, call $callback, a function that
 * echoes out output for this widget. If not cache, echo a "Loading..." stub
 * which is later replaced by Ajax call (see top of /wp-admin/index.php)
 *
 * @since 2.5.0
 * @since 5.3.0 Formalized the existing and already documented `...$args` parameter
 *              by adding it to the function signature.
 *
 * @param string   $widget_id  The widget ID.
 * @param callable $callback   The callback function used to display each feed.
 * @param array    $check_urls RSS feeds.
 * @param mixed    ...$args    Optional additional parameters to pass to the callback function.
 * @return bool True on success, false on failure.
 */
function wp_dashboard_cached_rss_widget( $widget_id, $callback, $check_urls = array(), ...$args ) {
	$doing_ajax = wp_doing_ajax();
	$loading    = '<p class="widget-loading hide-if-no-js">' . __( 'Loading&hellip;' ) . '</p>';
	$loading   .= wp_get_admin_notice(
		__( 'This widget requires JavaScript.' ),
		array(
			'type'               => 'error',
			'additional_classes' => array( 'inline', 'hide-if-js' ),
		)
	);

	if ( empty( $check_urls ) ) {
		$widgets = get_option( 'dashboard_widget_options' );

		if ( empty( $widgets[ $widget_id ]['url'] ) && ! $doing_ajax ) {
			echo $loading;
			return false;
		}

		$check_urls = array( $widgets[ $widget_id ]['url'] );
	}

	$locale    = get_user_locale();
	$cache_key = 'dash_v2_' . md5( $widget_id . '_' . $locale );
	$output    = get_transient( $cache_key );

	if ( false !== $output ) {
		echo $output;
		return true;
	}

	if ( ! $doing_ajax ) {
		echo $loading;
		return false;
	}

	if ( $callback && is_callable( $callback ) ) {
		array_unshift( $args, $widget_id, $check_urls );
		ob_start();
		call_user_func_array( $callback, $args );
		// Default lifetime in cache of 12 hours (same as the feeds).
		set_transient( $cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS );
	}

	return true;
}

//
// Dashboard Widgets Controls.
//

/**
 * Calls widget control callback.
 *
 * @since 2.5.0
 *
 * @global callable[] $wp_dashboard_control_callbacks
 *
 * @param int|false $widget_control_id Optional. Registered widget ID. Default false.
 */
function wp_dashboard_trigger_widget_control( $widget_control_id = false ) {
	global $wp_dashboard_control_callbacks;

	if ( is_scalar( $widget_control_id ) && $widget_control_id
		&& isset( $wp_dashboard_control_callbacks[ $widget_control_id ] )
		&& is_callable( $wp_dashboard_control_callbacks[ $widget_control_id ] )
	) {
		call_user_func(
			$wp_dashboard_control_callbacks[ $widget_control_id ],
			'',
			array(
				'id'       => $widget_control_id,
				'callback' => $wp_dashboard_control_callbacks[ $widget_control_id ],
			)
		);
	}
}

/**
 * Sets up the RSS dashboard widget control and $args to be used as input to wp_widget_rss_form().
 *
 * Handles POST data from RSS-type widgets.
 *
 * @since 2.5.0
 *
 * @param string $widget_id
 * @param array  $form_inputs
 */
function wp_dashboard_rss_control( $widget_id, $form_inputs = array() ) {
	$widget_options = get_option( 'dashboard_widget_options' );

	if ( ! $widget_options ) {
		$widget_options = array();
	}

	if ( ! isset( $widget_options[ $widget_id ] ) ) {
		$widget_options[ $widget_id ] = array();
	}

	$number = 1; // Hack to use wp_widget_rss_form().

	$widget_options[ $widget_id ]['number'] = $number;

	if ( 'POST' === $_SERVER['REQUEST_METHOD'] && isset( $_POST['widget-rss'][ $number ] ) ) {
		$_POST['widget-rss'][ $number ]         = wp_unslash( $_POST['widget-rss'][ $number ] );
		$widget_options[ $widget_id ]           = wp_widget_rss_process( $_POST['widget-rss'][ $number ] );
		$widget_options[ $widget_id ]['number'] = $number;

		// Title is optional. If black, fill it if possible.
		if ( ! $widget_options[ $widget_id ]['title'] && isset( $_POST['widget-rss'][ $number ]['title'] ) ) {
			$rss = fetch_feed( $widget_options[ $widget_id ]['url'] );
			if ( is_wp_error( $rss ) ) {
				$widget_options[ $widget_id ]['title'] = htmlentities( __( 'Unknown Feed' ) );
			} else {
				$widget_options[ $widget_id ]['title'] = htmlentities( strip_tags( $rss->get_title() ) );
				$rss->__destruct();
				unset( $rss );
			}
		}

		update_option( 'dashboard_widget_options', $widget_options, false );

		$locale    = get_user_locale();
		$cache_key = 'dash_v2_' . md5( $widget_id . '_' . $locale );
		delete_transient( $cache_key );
	}

	wp_widget_rss_form( $widget_options[ $widget_id ], $form_inputs );
}


/**
 * Renders the Events and News dashboard widget.
 *
 * @since 4.8.0
 */
function wp_dashboard_events_news() {
	wp_print_community_events_markup();

	?>

	<div class="wordpress-news hide-if-no-js">
		<?php wp_dashboard_primary(); ?>
	</div>

	<p class="community-events-footer">
		<?php
			printf(
				'<a href="%1$s" target="_blank">%2$s <span class="screen-reader-text"> %3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a>',
				'https://make.wordpress.org/community/meetups-landing-page',
				__( 'Meetups' ),
				/* translators: Hidden accessibility text. */
				__( '(opens in a new tab)' )
			);
		?>

		|

		<?php
			printf(
				'<a href="%1$s" target="_blank">%2$s <span class="screen-reader-text"> %3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a>',
				'https://central.wordcamp.org/schedule/',
				__( 'WordCamps' ),
				/* translators: Hidden accessibility text. */
				__( '(opens in a new tab)' )
			);
		?>

		|

		<?php
			printf(
				'<a href="%1$s" target="_blank">%2$s <span class="screen-reader-text"> %3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a>',
				/* translators: If a Rosetta site exists (e.g. https://es.wordpress.org/news/), then use that. Otherwise, leave untranslated. */
				esc_url( _x( 'https://wordpress.org/news/', 'Events and News dashboard widget' ) ),
				__( 'News' ),
				/* translators: Hidden accessibility text. */
				__( '(opens in a new tab)' )
			);
		?>
	</p>

	<?php
}

/**
 * Prints the markup for the Community Events section of the Events and News Dashboard widget.
 *
 * @since 4.8.0
 */
function wp_print_community_events_markup() {
	$community_events_notice  = '<p class="hide-if-js">' . ( 'This widget requires JavaScript.' ) . '</p>';
	$community_events_notice .= '<p class="community-events-error-occurred" aria-hidden="true">' . __( 'An error occurred. Please try again.' ) . '</p>';
	$community_events_notice .= '<p class="community-events-could-not-locate" aria-hidden="true"></p>';

	wp_admin_notice(
		$community_events_notice,
		array(
			'type'               => 'error',
			'additional_classes' => array( 'community-events-errors', 'inline', 'hide-if-js' ),
			'paragraph_wrap'     => false,
		)
	);

	/*
	 * Hide the main element when the page first loads, because the content
	 * won't be ready until wp.communityEvents.renderEventsTemplate() has run.
	 */
	?>
	<div id="community-events" class="community-events" aria-hidden="true">
		<div class="activity-block">
			<p>
				<span id="community-events-location-message"></span>

				<button class="button-link community-events-toggle-location" aria-expanded="false">
					<span class="dashicons dashicons-location" aria-hidden="true"></span>
					<span class="community-events-location-edit"><?php _e( 'Select location' ); ?></span>
				</button>
			</p>

			<form class="community-events-form" aria-hidden="true" action="<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>" method="post">
				<label for="community-events-location">
					<?php _e( 'City:' ); ?>
				</label>
				<?php
				/* translators: Replace with a city related to your locale.
				 * Test that it matches the expected location and has upcoming
				 * events before including it. If no cities related to your
				 * locale have events, then use a city related to your locale
				 * that would be recognizable to most users. Use only the city
				 * name itself, without any region or country. Use the endonym
				 * (native locale name) instead of the English name if possible.
				 */
				?>
				<input id="community-events-location" class="regular-text" type="text" name="community-events-location" placeholder="<?php esc_attr_e( 'Cincinnati' ); ?>" />

				<?php submit_button( __( 'Submit' ), 'secondary', 'community-events-submit', false ); ?>

				<button class="community-events-cancel button-link" type="button" aria-expanded="false">
					<?php _e( 'Cancel' ); ?>
				</button>

				<span class="spinner"></span>
			</form>
		</div>

		<ul class="community-events-results activity-block last"></ul>
	</div>

	<?php
}

/**
 * Renders the events templates for the Event and News widget.
 *
 * @since 4.8.0
 */
function wp_print_community_events_templates() {
	?>

	<script id="tmpl-community-events-attend-event-near" type="text/template">
		<?php
		printf(
			/* translators: %s: The name of a city. */
			__( 'Attend an upcoming event near %s.' ),
			'<strong>{{ data.location.description }}</strong>'
		);
		?>
	</script>

	<script id="tmpl-community-events-could-not-locate" type="text/template">
		<?php
		printf(
			/* translators: %s is the name of the city we couldn't locate.
			 * Replace the examples with cities in your locale, but test
			 * that they match the expected location before including them.
			 * Use endonyms (native locale names) whenever possible.
			 */
			__( '%s could not be located. Please try another nearby city. For example: Kansas City; Springfield; Portland.' ),
			'<em>{{data.unknownCity}}</em>'
		);
		?>
	</script>

	<script id="tmpl-community-events-event-list" type="text/template">
		<# _.each( data.events, function( event ) { #>
			<li class="event event-{{ event.type }} wp-clearfix">
				<div class="event-info">
					<div class="dashicons event-icon" aria-hidden="true"></div>
					<div class="event-info-inner">
						<a class="event-title" href="{{ event.url }}">{{ event.title }}</a>
						<# if ( event.type ) {
							const titleCaseEventType = event.type.replace(
								/\w\S*/g,
								function ( type ) { return type.charAt(0).toUpperCase() + type.substr(1).toLowerCase(); }
							);
						#>
							{{ 'wordcamp' === event.type ? 'WordCamp' : titleCaseEventType }}
							<span class="ce-separator" aria-hidden="true"></span>
						<# } #>
						<span class="event-city">{{ event.location.location }}</span>
					</div>
				</div>

				<div class="event-date-time">
					<span class="event-date">{{ event.user_formatted_date }}</span>
					<# if ( 'meetup' === event.type ) { #>
						<span class="event-time">
							{{ event.user_formatted_time }} {{ event.timeZoneAbbreviation }}
						</span>
					<# } #>
				</div>
			</li>
		<# } ) #>

		<# if ( data.events.length <= 2 ) { #>
			<li class="event-none">
				<?php
				printf(
					/* translators: %s: Localized meetup organization documentation URL. */
					__( 'Want more events? <a href="%s">Help organize the next one</a>!' ),
					__( 'https://make.wordpress.org/community/organize-event-landing-page/' )
				);
				?>
			</li>
		<# } #>

	</script>

	<script id="tmpl-community-events-no-upcoming-events" type="text/template">
		<li class="event-none">
			<# if ( data.location.description ) { #>
				<?php
				printf(
					/* translators: 1: The city the user searched for, 2: Meetup organization documentation URL. */
					__( 'There are no events scheduled near %1$s at the moment. Would you like to <a href="%2$s">organize a WordPress event</a>?' ),
					'{{ data.location.description }}',
					__( 'https://make.wordpress.org/community/handbook/meetup-organizer/welcome/' )
				);
				?>

			<# } else { #>
				<?php
				printf(
					/* translators: %s: Meetup organization documentation URL. */
					__( 'There are no events scheduled near you at the moment. Would you like to <a href="%s">organize a WordPress event</a>?' ),
					__( 'https://make.wordpress.org/community/handbook/meetup-organizer/welcome/' )
				);
				?>
			<# } #>
		</li>
	</script>
	<?php
}

/**
 * 'WordPress Events and News' dashboard widget.
 *
 * @since 2.7.0
 * @since 4.8.0 Removed popular plugins feed.
 */
function wp_dashboard_primary() {
	$feeds = array(
		'news'   => array(

			/**
			 * Filters the primary link URL for the 'WordPress Events and News' dashboard widget.
			 *
			 * @since 2.5.0
			 *
			 * @param string $link The widget's primary link URL.
			 */
			'link'         => apply_filters( 'dashboard_primary_link', __( 'https://wordpress.org/news/' ) ),

			/**
			 * Filters the primary feed URL for the 'WordPress Events and News' dashboard widget.
			 *
			 * @since 2.3.0
			 *
			 * @param string $url The widget's primary feed URL.
			 */
			'url'          => apply_filters( 'dashboard_primary_feed', __( 'https://wordpress.org/news/feed/' ) ),

			/**
			 * Filters the primary link title for the 'WordPress Events and News' dashboard widget.
			 *
			 * @since 2.3.0
			 *
			 * @param string $title Title attribute for the widget's primary link.
			 */
			'title'        => apply_filters( 'dashboard_primary_title', __( 'WordPress Blog' ) ),
			'items'        => 2,
			'show_summary' => 0,
			'show_author'  => 0,
			'show_date'    => 0,
		),
		'planet' => array(

			/**
			 * Filters the secondary link URL for the 'WordPress Events and News' dashboard widget.
			 *
			 * @since 2.3.0
			 *
			 * @param string $link The widget's secondary link URL.
			 */
			'link'         => apply_filters(
				'dashboard_secondary_link',
				/* translators: Link to the Planet website of the locale. */
				__( 'https://planet.wordpress.org/' )
			),

			/**
			 * Filters the secondary feed URL for the 'WordPress Events and News' dashboard widget.
			 *
			 * @since 2.3.0
			 *
			 * @param string $url The widget's secondary feed URL.
			 */
			'url'          => apply_filters(
				'dashboard_secondary_feed',
				/* translators: Link to the Planet feed of the locale. */
				__( 'https://planet.wordpress.org/feed/' )
			),

			/**
			 * Filters the secondary link title for the 'WordPress Events and News' dashboard widget.
			 *
			 * @since 2.3.0
			 *
			 * @param string $title Title attribute for the widget's secondary link.
			 */
			'title'        => apply_filters( 'dashboard_secondary_title', __( 'Other WordPress News' ) ),

			/**
			 * Filters the number of secondary link items for the 'WordPress Events and News' dashboard widget.
			 *
			 * @since 4.4.0
			 *
			 * @param string $items How many items to show in the secondary feed.
			 */
			'items'        => apply_filters( 'dashboard_secondary_items', 3 ),
			'show_summary' => 0,
			'show_author'  => 0,
			'show_date'    => 0,
		),
	);

	wp_dashboard_cached_rss_widget( 'dashboard_primary', 'wp_dashboard_primary_output', $feeds );
}

/**
 * Displays the WordPress events and news feeds.
 *
 * @since 3.8.0
 * @since 4.8.0 Removed popular plugins feed.
 *
 * @param string $widget_id Widget ID.
 * @param array  $feeds     Array of RSS feeds.
 */
function wp_dashboard_primary_output( $widget_id, $feeds ) {
	foreach ( $feeds as $type => $args ) {
		$args['type'] = $type;
		echo '<div class="rss-widget">';
			wp_widget_rss_output( $args['url'], $args );
		echo '</div>';
	}
}

/**
 * Displays file upload quota on dashboard.
 *
 * Runs on the {@see 'activity_box_end'} hook in wp_dashboard_right_now().
 *
 * @since 3.0.0
 *
 * @return true|void True if not multisite, user can't upload files, or the space check option is disabled.
 */
function wp_dashboard_quota() {
	if ( ! is_multisite() || ! current_user_can( 'upload_files' )
		|| get_site_option( 'upload_space_check_disabled' )
	) {
		return true;
	}

	$quota = get_space_allowed();
	$used  = get_space_used();

	if ( $used > $quota ) {
		$percentused = '100';
	} else {
		$percentused = ( $used / $quota ) * 100;
	}

	$used_class  = ( $percentused >= 70 ) ? ' warning' : '';
	$used        = round( $used, 2 );
	$percentused = number_format( $percentused );

	?>
	<h3 class="mu-storage"><?php _e( 'Storage Space' ); ?></h3>
	<div class="mu-storage">
	<ul>
		<li class="storage-count">
			<?php
			$text = sprintf(
				/* translators: %s: Number of megabytes. */
				__( '%s MB Space Allowed' ),
				number_format_i18n( $quota )
			);
			printf(
				'<a href="%1$s">%2$s<span class="screen-reader-text"> (%3$s)</span></a>',
				esc_url( admin_url( 'upload.php' ) ),
				$text,
				/* translators: Hidden accessibility text. */
				__( 'Manage Uploads' )
			);
			?>
		</li><li class="storage-count <?php echo $used_class; ?>">
			<?php
			$text = sprintf(
				/* translators: 1: Number of megabytes, 2: Percentage. */
				__( '%1$s MB (%2$s%%) Space Used' ),
				number_format_i18n( $used, 2 ),
				$percentused
			);
			printf(
				'<a href="%1$s" class="musublink">%2$s<span class="screen-reader-text"> (%3$s)</span></a>',
				esc_url( admin_url( 'upload.php' ) ),
				$text,
				/* translators: Hidden accessibility text. */
				__( 'Manage Uploads' )
			);
			?>
		</li>
	</ul>
	</div>
	<?php
}

/**
 * Displays the browser update nag.
 *
 * @since 3.2.0
 * @since 5.8.0 Added a special message for Internet Explorer users.
 *
 * @global bool $is_IE
 */
function wp_dashboard_browser_nag() {
	global $is_IE;

	$notice   = '';
	$response = wp_check_browser_version();

	if ( $response ) {
		if ( $is_IE ) {
			$msg = __( 'Internet Explorer does not give you the best WordPress experience. Switch to Microsoft Edge, or another more modern browser to get the most from your site.' );
		} elseif ( $response['insecure'] ) {
			$msg = sprintf(
				/* translators: %s: Browser name and link. */
				__( "It looks like you're using an insecure version of %s. Using an outdated browser makes your computer unsafe. For the best WordPress experience, please update your browser." ),
				sprintf( '<a href="%s">%s</a>', esc_url( $response['update_url'] ), esc_html( $response['name'] ) )
			);
		} else {
			$msg = sprintf(
				/* translators: %s: Browser name and link. */
				__( "It looks like you're using an old version of %s. For the best WordPress experience, please update your browser." ),
				sprintf( '<a href="%s">%s</a>', esc_url( $response['update_url'] ), esc_html( $response['name'] ) )
			);
		}

		$browser_nag_class = '';
		if ( ! empty( $response['img_src'] ) ) {
			$img_src = ( is_ssl() && ! empty( $response['img_src_ssl'] ) ) ? $response['img_src_ssl'] : $response['img_src'];

			$notice           .= '<div class="alignright browser-icon"><img src="' . esc_url( $img_src ) . '" alt="" /></div>';
			$browser_nag_class = ' has-browser-icon';
		}
		$notice .= "<p class='browser-update-nag{$browser_nag_class}'>{$msg}</p>";

		$browsehappy = 'https://browsehappy.com/';
		$locale      = get_user_locale();
		if ( 'en_US' !== $locale ) {
			$browsehappy = add_query_arg( 'locale', $locale, $browsehappy );
		}

		if ( $is_IE ) {
			$msg_browsehappy = sprintf(
				/* translators: %s: Browse Happy URL. */
				__( 'Learn how to <a href="%s" class="update-browser-link">browse happy</a>' ),
				esc_url( $browsehappy )
			);
		} else {
			$msg_browsehappy = sprintf(
				/* translators: 1: Browser update URL, 2: Browser name, 3: Browse Happy URL. */
				__( '<a href="%1$s" class="update-browser-link">Update %2$s</a> or learn how to <a href="%3$s" class="browse-happy-link">browse happy</a>' ),
				esc_attr( $response['update_url'] ),
				esc_html( $response['name'] ),
				esc_url( $browsehappy )
			);
		}

		$notice .= '<p>' . $msg_browsehappy . '</p>';
		$notice .= '<p class="hide-if-no-js"><a href="" class="dismiss" aria-label="' . esc_attr__( 'Dismiss the browser warning panel' ) . '">' . __( 'Dismiss' ) . '</a></p>';
		$notice .= '<div class="clear"></div>';
	}

	/**
	 * Filters the notice output for the 'Browse Happy' nag meta box.
	 *
	 * @since 3.2.0
	 *
	 * @param string      $notice   The notice content.
	 * @param array|false $response An array containing web browser information, or
	 *                              false on failure. See wp_check_browser_version().
	 */
	echo apply_filters( 'browse-happy-notice', $notice, $response ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
}

/**
 * Adds an additional class to the browser nag if the current version is insecure.
 *
 * @since 3.2.0
 *
 * @param string[] $classes Array of meta box classes.
 * @return string[] Modified array of meta box classes.
 */
function dashboard_browser_nag_class( $classes ) {
	$response = wp_check_browser_version();

	if ( $response && $response['insecure'] ) {
		$classes[] = 'browser-insecure';
	}

	return $classes;
}

/**
 * Checks if the user needs a browser update.
 *
 * @since 3.2.0
 *
 * @return array|false Array of browser data on success, false on failure.
 */
function wp_check_browser_version() {
	if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
		return false;
	}

	$key = md5( $_SERVER['HTTP_USER_AGENT'] );

	$response = get_site_transient( 'browser_' . $key );

	if ( false === $response ) {
		$url     = 'http://api.wordpress.org/core/browse-happy/1.1/';
		$options = array(
			'body'       => array( 'useragent' => $_SERVER['HTTP_USER_AGENT'] ),
			'user-agent' => 'WordPress/' . wp_get_wp_version() . '; ' . home_url( '/' ),
		);

		if ( wp_http_supports( array( 'ssl' ) ) ) {
			$url = set_url_scheme( $url, 'https' );
		}

		$response = wp_remote_post( $url, $options );

		if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
			return false;
		}

		/**
		 * Response should be an array with:
		 *  'platform' - string - A user-friendly platform name, if it can be determined
		 *  'name' - string - A user-friendly browser name
		 *  'version' - string - The version of the browser the user is using
		 *  'current_version' - string - The most recent version of the browser
		 *  'upgrade' - boolean - Whether the browser needs an upgrade
		 *  'insecure' - boolean - Whether the browser is deemed insecure
		 *  'update_url' - string - The url to visit to upgrade
		 *  'img_src' - string - An image representing the browser
		 *  'img_src_ssl' - string - An image (over SSL) representing the browser
		 */
		$response = json_decode( wp_remote_retrieve_body( $response ), true );

		if ( ! is_array( $response ) ) {
			return false;
		}

		set_site_transient( 'browser_' . $key, $response, WEEK_IN_SECONDS );
	}

	return $response;
}

/**
 * Displays the PHP update nag.
 *
 * @since 5.1.0
 */
function wp_dashboard_php_nag() {
	$response = wp_check_php_version();

	if ( ! $response ) {
		return;
	}

	if ( isset( $response['is_secure'] ) && ! $response['is_secure'] ) {
		// The `is_secure` array key name doesn't actually imply this is a secure version of PHP. It only means it receives security updates.

		if ( $response['is_lower_than_future_minimum'] ) {
			$message = sprintf(
				/* translators: %s: The server PHP version. */
				__( 'Your site is running on an outdated version of PHP (%s), which does not receive security updates and soon will not be supported by WordPress. Ensure that PHP is updated on your server as soon as possible. Otherwise you will not be able to upgrade WordPress.' ),
				PHP_VERSION
			);
		} else {
			$message = sprintf(
				/* translators: %s: The server PHP version. */
				__( 'Your site is running on an outdated version of PHP (%s), which does not receive security updates. It should be updated.' ),
				PHP_VERSION
			);
		}
	} elseif ( $response['is_lower_than_future_minimum'] ) {
		$message = sprintf(
			/* translators: %s: The server PHP version. */
			__( 'Your site is running on an outdated version of PHP (%s), which soon will not be supported by WordPress. Ensure that PHP is updated on your server as soon as possible. Otherwise you will not be able to upgrade WordPress.' ),
			PHP_VERSION
		);
	} else {
		$message = sprintf(
			/* translators: %s: The server PHP version. */
			__( 'Your site is running on an outdated version of PHP (%s), which should be updated.' ),
			PHP_VERSION
		);
	}
	?>
	<p class="bigger-bolder-text"><?php echo $message; ?></p>

	<p><?php _e( 'What is PHP and how does it affect my site?' ); ?></p>
	<p>
		<?php _e( 'PHP is one of the programming languages used to build WordPress. Newer versions of PHP receive regular security updates and may increase your site&#8217;s performance.' ); ?>
		<?php
		if ( ! empty( $response['recommended_version'] ) ) {
			printf(
				/* translators: %s: The minimum recommended PHP version. */
				__( 'The minimum recommended version of PHP is %s.' ),
				$response['recommended_version']
			);
		}
		?>
	</p>

	<p class="button-container">
		<?php
		printf(
			'<a class="button button-primary" href="%1$s" target="_blank">%2$s<span class="screen-reader-text"> %3$s</span><span aria-hidden="true" class="dashicons dashicons-external"></span></a>',
			esc_url( wp_get_update_php_url() ),
			__( 'Learn more about updating PHP' ),
			/* translators: Hidden accessibility text. */
			__( '(opens in a new tab)' )
		);
		?>
	</p>
	<?php

	wp_update_php_annotation();
	wp_direct_php_update_button();
}

/**
 * Adds an additional class to the PHP nag if the current version is insecure.
 *
 * @since 5.1.0
 *
 * @param string[] $classes Array of meta box classes.
 * @return string[] Modified array of meta box classes.
 */
function dashboard_php_nag_class( $classes ) {
	$response = wp_check_php_version();

	if ( ! $response ) {
		return $classes;
	}

	if ( isset( $response['is_secure'] ) && ! $response['is_secure'] ) {
		$classes[] = 'php-no-security-updates';
	} elseif ( $response['is_lower_than_future_minimum'] ) {
		$classes[] = 'php-version-lower-than-future-minimum';
	}

	return $classes;
}

/**
 * Displays the Site Health Status widget.
 *
 * @since 5.4.0
 */
function wp_dashboard_site_health() {
	$get_issues = get_transient( 'health-check-site-status-result' );

	$issue_counts = array();

	if ( false !== $get_issues ) {
		$issue_counts = json_decode( $get_issues, true );
	}

	if ( ! is_array( $issue_counts ) || ! $issue_counts ) {
		$issue_counts = array(
			'good'        => 0,
			'recommended' => 0,
			'critical'    => 0,
		);
	}

	$issues_total = $issue_counts['recommended'] + $issue_counts['critical'];
	?>
	<div class="health-check-widget">
		<div class="health-check-widget-title-section site-health-progress-wrapper loading hide-if-no-js">
			<div class="site-health-progress">
				<svg aria-hidden="true" focusable="false" width="100%" height="100%" viewBox="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg">
					<circle r="90" cx="100" cy="100" fill="transparent" stroke-dasharray="565.48" stroke-dashoffset="0"></circle>
					<circle id="bar" r="90" cx="100" cy="100" fill="transparent" stroke-dasharray="565.48" stroke-dashoffset="0"></circle>
				</svg>
			</div>
			<div class="site-health-progress-label">
				<?php if ( false === $get_issues ) : ?>
					<?php _e( 'No information yet&hellip;' ); ?>
				<?php else : ?>
					<?php _e( 'Results are still loading&hellip;' ); ?>
				<?php endif; ?>
			</div>
		</div>

		<div class="site-health-details">
			<?php if ( false === $get_issues ) : ?>
				<p>
					<?php
					printf(
						/* translators: %s: URL to Site Health screen. */
						__( 'Site health checks will automatically run periodically to gather information about your site. You can also <a href="%s">visit the Site Health screen</a> to gather information about your site now.' ),
						esc_url( admin_url( 'site-health.php' ) )
					);
					?>
				</p>
			<?php else : ?>
				<p>
					<?php if ( $issues_total <= 0 ) : ?>
						<?php _e( 'Great job! Your site currently passes all site health checks.' ); ?>
					<?php elseif ( 1 === (int) $issue_counts['critical'] ) : ?>
						<?php _e( 'Your site has a critical issue that should be addressed as soon as possible to improve its performance and security.' ); ?>
					<?php elseif ( $issue_counts['critical'] > 1 ) : ?>
						<?php _e( 'Your site has critical issues that should be addressed as soon as possible to improve its performance and security.' ); ?>
					<?php elseif ( 1 === (int) $issue_counts['recommended'] ) : ?>
						<?php _e( 'Your site&#8217;s health is looking good, but there is still one thing you can do to improve its performance and security.' ); ?>
					<?php else : ?>
						<?php _e( 'Your site&#8217;s health is looking good, but there are still some things you can do to improve its performance and security.' ); ?>
					<?php endif; ?>
				</p>
			<?php endif; ?>

			<?php if ( $issues_total > 0 && false !== $get_issues ) : ?>
				<p>
					<?php
					printf(
						/* translators: 1: Number of issues. 2: URL to Site Health screen. */
						_n(
							'Take a look at the <strong>%1$d item</strong> on the <a href="%2$s">Site Health screen</a>.',
							'Take a look at the <strong>%1$d items</strong> on the <a href="%2$s">Site Health screen</a>.',
							$issues_total
						),
						$issues_total,
						esc_url( admin_url( 'site-health.php' ) )
					);
					?>
				</p>
			<?php endif; ?>
		</div>
	</div>

	<?php
}

/**
 * Outputs empty dashboard widget to be populated by JS later.
 *
 * Usable by plugins.
 *
 * @since 2.5.0
 */
function wp_dashboard_empty() {}

/**
 * Displays a welcome panel to introduce users to WordPress.
 *
 * @since 3.3.0
 * @since 5.9.0 Send users to the Site Editor if the active theme is block-based.
 */
function wp_welcome_panel() {
	list( $display_version ) = explode( '-', wp_get_wp_version() );
	$can_customize           = current_user_can( 'customize' );
	$is_block_theme          = wp_is_block_theme();
	?>
	<div class="welcome-panel-content">
	<div class="welcome-panel-header">
		<div class="welcome-panel-header-image">
			<?php echo file_get_contents( dirname( __DIR__ ) . '/images/dashboard-background.svg' ); ?>
		</div>
		<h2><?php _e( 'Welcome to WordPress!' ); ?></h2>
		<p>
			<a href="<?php echo esc_url( admin_url( 'about.php' ) ); ?>">
			<?php
				/* translators: %s: Current WordPress version. */
				printf( __( 'Learn more about the %s version.' ), esc_html( $display_version ) );
			?>
			</a>
		</p>
	</div>
	<div class="welcome-panel-column-container">
		<div class="welcome-panel-column">
			<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false">
				<rect width="48" height="48" rx="4" fill="#1E1E1E"/>
				<path fill-rule="evenodd" clip-rule="evenodd" d="M32.0668 17.0854L28.8221 13.9454L18.2008 24.671L16.8983 29.0827L21.4257 27.8309L32.0668 17.0854ZM16 32.75H24V31.25H16V32.75Z" fill="white"/>
			</svg>
			<div class="welcome-panel-column-content">
				<h3><?php _e( 'Author rich content with blocks and patterns' ); ?></h3>
				<p><?php _e( 'Block patterns are pre-configured block layouts. Use them to get inspired or create new pages in a flash.' ); ?></p>
				<a href="<?php echo esc_url( admin_url( 'post-new.php?post_type=page' ) ); ?>"><?php _e( 'Add a new page' ); ?></a>
			</div>
		</div>
		<div class="welcome-panel-column">
			<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false">
				<rect width="48" height="48" rx="4" fill="#1E1E1E"/>
				<path fill-rule="evenodd" clip-rule="evenodd" d="M18 16h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H18a2 2 0 0 1-2-2V18a2 2 0 0 1 2-2zm12 1.5H18a.5.5 0 0 0-.5.5v3h13v-3a.5.5 0 0 0-.5-.5zm.5 5H22v8h8a.5.5 0 0 0 .5-.5v-7.5zm-10 0h-3V30a.5.5 0 0 0 .5.5h2.5v-8z" fill="#fff"/>
			</svg>
			<div class="welcome-panel-column-content">
			<?php if ( $is_block_theme ) : ?>
				<h3><?php _e( 'Customize your entire site with block themes' ); ?></h3>
				<p><?php _e( 'Design everything on your site &#8212; from the header down to the footer, all using blocks and patterns.' ); ?></p>
				<a href="<?php echo esc_url( admin_url( 'site-editor.php' ) ); ?>"><?php _e( 'Open site editor' ); ?></a>
			<?php else : ?>
				<h3><?php _e( 'Start Customizing' ); ?></h3>
				<p><?php _e( 'Configure your site&#8217;s logo, header, menus, and more in the Customizer.' ); ?></p>
				<?php if ( $can_customize ) : ?>
					<a class="load-customize hide-if-no-customize" href="<?php echo wp_customize_url(); ?>"><?php _e( 'Open the Customizer' ); ?></a>
				<?php endif; ?>
			<?php endif; ?>
			</div>
		</div>
		<div class="welcome-panel-column">
			<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false">
				<rect width="48" height="48" rx="4" fill="#1E1E1E"/>
				<path fill-rule="evenodd" clip-rule="evenodd" d="M31 24a7 7 0 0 1-7 7V17a7 7 0 0 1 7 7zm-7-8a8 8 0 1 1 0 16 8 8 0 0 1 0-16z" fill="#fff"/>
			</svg>
			<div class="welcome-panel-column-content">
			<?php if ( $is_block_theme ) : ?>
				<h3><?php _e( 'Switch up your site&#8217;s look & feel with Styles' ); ?></h3>
				<p><?php _e( 'Tweak your site, or give it a whole new look! Get creative &#8212; how about a new color palette or font?' ); ?></p>
				<a href="<?php echo esc_url( admin_url( '/site-editor.php?path=%2Fwp_global_styles' ) ); ?>"><?php _e( 'Edit styles' ); ?></a>
			<?php else : ?>
				<h3><?php _e( 'Discover a new way to build your site.' ); ?></h3>
				<p><?php _e( 'There is a new kind of WordPress theme, called a block theme, that lets you build the site you&#8217;ve always wanted &#8212; with blocks and styles.' ); ?></p>
				<a href="<?php echo esc_url( __( 'https://wordpress.org/documentation/article/block-themes/' ) ); ?>"><?php _e( 'Learn about block themes' ); ?></a>
			<?php endif; ?>
			</div>
		</div>
	</div>
	</div>
	<?php
}
taxonomy.php000064400000020347151212616060007141 0ustar00<?php
/**
 * WordPress Taxonomy Administration API.
 *
 * @package WordPress
 * @subpackage Administration
 */

//
// Category.
//

/**
 * Checks whether a category exists.
 *
 * @since 2.0.0
 *
 * @see term_exists()
 *
 * @param int|string $cat_name        Category name.
 * @param int        $category_parent Optional. ID of parent category.
 * @return string|null Returns the category ID as a numeric string if the pairing exists, null if not.
 */
function category_exists( $cat_name, $category_parent = null ) {
	$id = term_exists( $cat_name, 'category', $category_parent );
	if ( is_array( $id ) ) {
		$id = $id['term_id'];
	}
	return $id;
}

/**
 * Gets category object for given ID and 'edit' filter context.
 *
 * @since 2.0.0
 *
 * @param int $id
 * @return object
 */
function get_category_to_edit( $id ) {
	$category = get_term( $id, 'category', OBJECT, 'edit' );
	_make_cat_compat( $category );
	return $category;
}

/**
 * Adds a new category to the database if it does not already exist.
 *
 * @since 2.0.0
 *
 * @param int|string $cat_name        Category name.
 * @param int        $category_parent Optional. ID of parent category.
 * @return int|WP_Error
 */
function wp_create_category( $cat_name, $category_parent = 0 ) {
	$id = category_exists( $cat_name, $category_parent );
	if ( $id ) {
		return $id;
	}

	return wp_insert_category(
		array(
			'cat_name'        => $cat_name,
			'category_parent' => $category_parent,
		)
	);
}

/**
 * Creates categories for the given post.
 *
 * @since 2.0.0
 *
 * @param string[] $categories Array of category names to create.
 * @param int      $post_id    Optional. The post ID. Default empty.
 * @return int[] Array of IDs of categories assigned to the given post.
 */
function wp_create_categories( $categories, $post_id = 0 ) {
	$cat_ids = array();
	foreach ( $categories as $category ) {
		$id = category_exists( $category );
		if ( $id ) {
			$cat_ids[] = $id;
		} else {
			$id = wp_create_category( $category );
			if ( $id ) {
				$cat_ids[] = $id;
			}
		}
	}

	if ( $post_id ) {
		wp_set_post_categories( $post_id, $cat_ids );
	}

	return $cat_ids;
}

/**
 * Updates an existing Category or creates a new Category.
 *
 * @since 2.0.0
 * @since 2.5.0 $wp_error parameter was added.
 * @since 3.0.0 The 'taxonomy' argument was added.
 *
 * @param array $catarr {
 *     Array of arguments for inserting a new category.
 *
 *     @type int        $cat_ID               Category ID. A non-zero value updates an existing category.
 *                                            Default 0.
 *     @type string     $taxonomy             Taxonomy slug. Default 'category'.
 *     @type string     $cat_name             Category name. Default empty.
 *     @type string     $category_description Category description. Default empty.
 *     @type string     $category_nicename    Category nice (display) name. Default empty.
 *     @type int|string $category_parent      Category parent ID. Default empty.
 * }
 * @param bool  $wp_error Optional. Default false.
 * @return int|WP_Error The ID number of the new or updated Category on success. Zero or a WP_Error on failure,
 *                      depending on param `$wp_error`.
 */
function wp_insert_category( $catarr, $wp_error = false ) {
	$cat_defaults = array(
		'cat_ID'               => 0,
		'taxonomy'             => 'category',
		'cat_name'             => '',
		'category_description' => '',
		'category_nicename'    => '',
		'category_parent'      => '',
	);
	$catarr       = wp_parse_args( $catarr, $cat_defaults );

	if ( '' === trim( $catarr['cat_name'] ) ) {
		if ( ! $wp_error ) {
			return 0;
		} else {
			return new WP_Error( 'cat_name', __( 'You did not enter a category name.' ) );
		}
	}

	$catarr['cat_ID'] = (int) $catarr['cat_ID'];

	// Are we updating or creating?
	$update = ! empty( $catarr['cat_ID'] );

	$name        = $catarr['cat_name'];
	$description = $catarr['category_description'];
	$slug        = $catarr['category_nicename'];
	$parent      = (int) $catarr['category_parent'];
	if ( $parent < 0 ) {
		$parent = 0;
	}

	if ( empty( $parent )
		|| ! term_exists( $parent, $catarr['taxonomy'] )
		|| ( $catarr['cat_ID'] && term_is_ancestor_of( $catarr['cat_ID'], $parent, $catarr['taxonomy'] ) ) ) {
		$parent = 0;
	}

	$args = compact( 'name', 'slug', 'parent', 'description' );

	if ( $update ) {
		$catarr['cat_ID'] = wp_update_term( $catarr['cat_ID'], $catarr['taxonomy'], $args );
	} else {
		$catarr['cat_ID'] = wp_insert_term( $catarr['cat_name'], $catarr['taxonomy'], $args );
	}

	if ( is_wp_error( $catarr['cat_ID'] ) ) {
		if ( $wp_error ) {
			return $catarr['cat_ID'];
		} else {
			return 0;
		}
	}
	return $catarr['cat_ID']['term_id'];
}

/**
 * Aliases wp_insert_category() with minimal args.
 *
 * If you want to update only some fields of an existing category, call this
 * function with only the new values set inside $catarr.
 *
 * @since 2.0.0
 *
 * @param array $catarr The 'cat_ID' value is required. All other keys are optional.
 * @return int|false The ID number of the new or updated Category on success. Zero or FALSE on failure.
 */
function wp_update_category( $catarr ) {
	$cat_id = (int) $catarr['cat_ID'];

	if ( isset( $catarr['category_parent'] ) && ( $cat_id === (int) $catarr['category_parent'] ) ) {
		return false;
	}

	// First, get all of the original fields.
	$category = get_term( $cat_id, 'category', ARRAY_A );
	_make_cat_compat( $category );

	// Escape data pulled from DB.
	$category = wp_slash( $category );

	// Merge old and new fields with new fields overwriting old ones.
	$catarr = array_merge( $category, $catarr );

	return wp_insert_category( $catarr );
}

//
// Tags.
//

/**
 * Checks whether a post tag with a given name exists.
 *
 * @since 2.3.0
 *
 * @param int|string $tag_name
 * @return mixed Returns null if the term does not exist.
 *               Returns an array of the term ID and the term taxonomy ID if the pairing exists.
 *               Returns 0 if term ID 0 is passed to the function.
 */
function tag_exists( $tag_name ) {
	return term_exists( $tag_name, 'post_tag' );
}

/**
 * Adds a new tag to the database if it does not already exist.
 *
 * @since 2.3.0
 *
 * @param int|string $tag_name
 * @return array|WP_Error
 */
function wp_create_tag( $tag_name ) {
	return wp_create_term( $tag_name, 'post_tag' );
}

/**
 * Gets comma-separated list of tags available to edit.
 *
 * @since 2.3.0
 *
 * @param int    $post_id
 * @param string $taxonomy Optional. The taxonomy for which to retrieve terms. Default 'post_tag'.
 * @return string|false|WP_Error
 */
function get_tags_to_edit( $post_id, $taxonomy = 'post_tag' ) {
	return get_terms_to_edit( $post_id, $taxonomy );
}

/**
 * Gets comma-separated list of terms available to edit for the given post ID.
 *
 * @since 2.8.0
 *
 * @param int    $post_id
 * @param string $taxonomy Optional. The taxonomy for which to retrieve terms. Default 'post_tag'.
 * @return string|false|WP_Error
 */
function get_terms_to_edit( $post_id, $taxonomy = 'post_tag' ) {
	$post_id = (int) $post_id;
	if ( ! $post_id ) {
		return false;
	}

	$terms = get_object_term_cache( $post_id, $taxonomy );
	if ( false === $terms ) {
		$terms = wp_get_object_terms( $post_id, $taxonomy );
		wp_cache_add( $post_id, wp_list_pluck( $terms, 'term_id' ), $taxonomy . '_relationships' );
	}

	if ( ! $terms ) {
		return false;
	}
	if ( is_wp_error( $terms ) ) {
		return $terms;
	}
	$term_names = array();
	foreach ( $terms as $term ) {
		$term_names[] = $term->name;
	}

	$terms_to_edit = esc_attr( implode( ',', $term_names ) );

	/**
	 * Filters the comma-separated list of terms available to edit.
	 *
	 * @since 2.8.0
	 *
	 * @see get_terms_to_edit()
	 *
	 * @param string $terms_to_edit A comma-separated list of term names.
	 * @param string $taxonomy      The taxonomy name for which to retrieve terms.
	 */
	$terms_to_edit = apply_filters( 'terms_to_edit', $terms_to_edit, $taxonomy );

	return $terms_to_edit;
}

/**
 * Adds a new term to the database if it does not already exist.
 *
 * @since 2.8.0
 *
 * @param string $tag_name The term name.
 * @param string $taxonomy Optional. The taxonomy within which to create the term. Default 'post_tag'.
 * @return array|WP_Error
 */
function wp_create_term( $tag_name, $taxonomy = 'post_tag' ) {
	$id = term_exists( $tag_name, $taxonomy );
	if ( $id ) {
		return $id;
	}

	return wp_insert_term( $tag_name, $taxonomy );
}
class-automatic-upgrader-skin.php000064400000007117151212616060013125 0ustar00<?php
/**
 * Upgrader API: Automatic_Upgrader_Skin class
 *
 * @package WordPress
 * @subpackage Upgrader
 * @since 4.6.0
 */

/**
 * Upgrader Skin for Automatic WordPress Upgrades.
 *
 * This skin is designed to be used when no output is intended, all output
 * is captured and stored for the caller to process and log/email/discard.
 *
 * @since 3.7.0
 * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader-skins.php.
 *
 * @see Bulk_Upgrader_Skin
 */
class Automatic_Upgrader_Skin extends WP_Upgrader_Skin {
	protected $messages = array();

	/**
	 * Determines whether the upgrader needs FTP/SSH details in order to connect
	 * to the filesystem.
	 *
	 * @since 3.7.0
	 * @since 4.6.0 The `$context` parameter default changed from `false` to an empty string.
	 *
	 * @see request_filesystem_credentials()
	 *
	 * @param bool|WP_Error $error                        Optional. Whether the current request has failed to connect,
	 *                                                    or an error object. Default false.
	 * @param string        $context                      Optional. Full path to the directory that is tested
	 *                                                    for being writable. Default empty.
	 * @param bool          $allow_relaxed_file_ownership Optional. Whether to allow Group/World writable. Default false.
	 * @return bool True on success, false on failure.
	 */
	public function request_filesystem_credentials( $error = false, $context = '', $allow_relaxed_file_ownership = false ) {
		if ( $context ) {
			$this->options['context'] = $context;
		}
		/*
		 * TODO: Fix up request_filesystem_credentials(), or split it, to allow us to request a no-output version.
		 * This will output a credentials form in event of failure. We don't want that, so just hide with a buffer.
		 */
		ob_start();
		$result = parent::request_filesystem_credentials( $error, $context, $allow_relaxed_file_ownership );
		ob_end_clean();
		return $result;
	}

	/**
	 * Retrieves the upgrade messages.
	 *
	 * @since 3.7.0
	 *
	 * @return string[] Messages during an upgrade.
	 */
	public function get_upgrade_messages() {
		return $this->messages;
	}

	/**
	 * Stores a message about the upgrade.
	 *
	 * @since 3.7.0
	 * @since 5.9.0 Renamed `$data` to `$feedback` for PHP 8 named parameter support.
	 *
	 * @param string|array|WP_Error $feedback Message data.
	 * @param mixed                 ...$args  Optional text replacements.
	 */
	public function feedback( $feedback, ...$args ) {
		if ( is_wp_error( $feedback ) ) {
			$string = $feedback->get_error_message();
		} elseif ( is_array( $feedback ) ) {
			return;
		} else {
			$string = $feedback;
		}

		if ( ! empty( $this->upgrader->strings[ $string ] ) ) {
			$string = $this->upgrader->strings[ $string ];
		}

		if ( str_contains( $string, '%' ) ) {
			if ( ! empty( $args ) ) {
				$string = vsprintf( $string, $args );
			}
		}

		$string = trim( $string );

		// Only allow basic HTML in the messages, as it'll be used in emails/logs rather than direct browser output.
		$string = wp_kses(
			$string,
			array(
				'a'      => array(
					'href' => true,
				),
				'br'     => true,
				'em'     => true,
				'strong' => true,
			)
		);

		if ( empty( $string ) ) {
			return;
		}

		$this->messages[] = $string;
	}

	/**
	 * Creates a new output buffer.
	 *
	 * @since 3.7.0
	 */
	public function header() {
		ob_start();
	}

	/**
	 * Retrieves the buffered content, deletes the buffer, and processes the output.
	 *
	 * @since 3.7.0
	 */
	public function footer() {
		$output = ob_get_clean();
		if ( ! empty( $output ) ) {
			$this->feedback( $output );
		}
	}
}
class-wp-plugin-install-list-table.php000064400000061047151212616060014014 0ustar00<?php
/**
 * List Table API: WP_Plugin_Install_List_Table class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 3.1.0
 */

/**
 * Core class used to implement displaying plugins to install in a list table.
 *
 * @since 3.1.0
 *
 * @see WP_List_Table
 */
class WP_Plugin_Install_List_Table extends WP_List_Table {

	public $order   = 'ASC';
	public $orderby = null;
	public $groups  = array();

	private $error;

	/**
	 * @return bool
	 */
	public function ajax_user_can() {
		return current_user_can( 'install_plugins' );
	}

	/**
	 * Returns the list of known plugins.
	 *
	 * Uses the transient data from the updates API to determine the known
	 * installed plugins.
	 *
	 * @since 4.9.0
	 *
	 * @return array
	 */
	protected function get_installed_plugins() {
		$plugins = array();

		$plugin_info = get_site_transient( 'update_plugins' );
		if ( isset( $plugin_info->no_update ) ) {
			foreach ( $plugin_info->no_update as $plugin ) {
				if ( isset( $plugin->slug ) ) {
					$plugin->upgrade          = false;
					$plugins[ $plugin->slug ] = $plugin;
				}
			}
		}

		if ( isset( $plugin_info->response ) ) {
			foreach ( $plugin_info->response as $plugin ) {
				if ( isset( $plugin->slug ) ) {
					$plugin->upgrade          = true;
					$plugins[ $plugin->slug ] = $plugin;
				}
			}
		}

		return $plugins;
	}

	/**
	 * Returns a list of slugs of installed plugins, if known.
	 *
	 * Uses the transient data from the updates API to determine the slugs of
	 * known installed plugins. This might be better elsewhere, perhaps even
	 * within get_plugins().
	 *
	 * @since 4.0.0
	 *
	 * @return array
	 */
	protected function get_installed_plugin_slugs() {
		return array_keys( $this->get_installed_plugins() );
	}

	/**
	 * @global array  $tabs
	 * @global string $tab
	 * @global int    $paged
	 * @global string $type
	 * @global string $term
	 */
	public function prepare_items() {
		require_once ABSPATH . 'wp-admin/includes/plugin-install.php';

		global $tabs, $tab, $paged, $type, $term;

		$tab = ! empty( $_REQUEST['tab'] ) ? sanitize_text_field( $_REQUEST['tab'] ) : '';

		$paged = $this->get_pagenum();

		$per_page = 36;

		// These are the tabs which are shown on the page.
		$tabs = array();

		if ( 'search' === $tab ) {
			$tabs['search'] = __( 'Search Results' );
		}

		if ( 'beta' === $tab || str_contains( get_bloginfo( 'version' ), '-' ) ) {
			$tabs['beta'] = _x( 'Beta Testing', 'Plugin Installer' );
		}

		$tabs['featured']    = _x( 'Featured', 'Plugin Installer' );
		$tabs['popular']     = _x( 'Popular', 'Plugin Installer' );
		$tabs['recommended'] = _x( 'Recommended', 'Plugin Installer' );
		$tabs['favorites']   = _x( 'Favorites', 'Plugin Installer' );

		if ( current_user_can( 'upload_plugins' ) ) {
			/*
			 * No longer a real tab. Here for filter compatibility.
			 * Gets skipped in get_views().
			 */
			$tabs['upload'] = __( 'Upload Plugin' );
		}

		$nonmenu_tabs = array( 'plugin-information' ); // Valid actions to perform which do not have a Menu item.

		/**
		 * Filters the tabs shown on the Add Plugins screen.
		 *
		 * @since 2.7.0
		 *
		 * @param string[] $tabs The tabs shown on the Add Plugins screen. Defaults include
		 *                       'featured', 'popular', 'recommended', 'favorites', and 'upload'.
		 */
		$tabs = apply_filters( 'install_plugins_tabs', $tabs );

		/**
		 * Filters tabs not associated with a menu item on the Add Plugins screen.
		 *
		 * @since 2.7.0
		 *
		 * @param string[] $nonmenu_tabs The tabs that don't have a menu item on the Add Plugins screen.
		 */
		$nonmenu_tabs = apply_filters( 'install_plugins_nonmenu_tabs', $nonmenu_tabs );

		// If a non-valid menu tab has been selected, And it's not a non-menu action.
		if ( empty( $tab ) || ( ! isset( $tabs[ $tab ] ) && ! in_array( $tab, (array) $nonmenu_tabs, true ) ) ) {
			$tab = key( $tabs );
		}

		$installed_plugins = $this->get_installed_plugins();

		$args = array(
			'page'     => $paged,
			'per_page' => $per_page,
			// Send the locale to the API so it can provide context-sensitive results.
			'locale'   => get_user_locale(),
		);

		switch ( $tab ) {
			case 'search':
				$type = isset( $_REQUEST['type'] ) ? wp_unslash( $_REQUEST['type'] ) : 'term';
				$term = isset( $_REQUEST['s'] ) ? wp_unslash( $_REQUEST['s'] ) : '';

				switch ( $type ) {
					case 'tag':
						$args['tag'] = sanitize_title_with_dashes( $term );
						break;
					case 'term':
						$args['search'] = $term;
						break;
					case 'author':
						$args['author'] = $term;
						break;
				}

				break;

			case 'featured':
			case 'popular':
			case 'new':
			case 'beta':
				$args['browse'] = $tab;
				break;
			case 'recommended':
				$args['browse'] = $tab;
				// Include the list of installed plugins so we can get relevant results.
				$args['installed_plugins'] = array_keys( $installed_plugins );
				break;

			case 'favorites':
				$action = 'save_wporg_username_' . get_current_user_id();
				if ( isset( $_GET['_wpnonce'] ) && wp_verify_nonce( wp_unslash( $_GET['_wpnonce'] ), $action ) ) {
					$user = isset( $_GET['user'] ) ? wp_unslash( $_GET['user'] ) : get_user_option( 'wporg_favorites' );

					// If the save url parameter is passed with a falsey value, don't save the favorite user.
					if ( ! isset( $_GET['save'] ) || $_GET['save'] ) {
						update_user_meta( get_current_user_id(), 'wporg_favorites', $user );
					}
				} else {
					$user = get_user_option( 'wporg_favorites' );
				}
				if ( $user ) {
					$args['user'] = $user;
				} else {
					$args = false;
				}

				add_action( 'install_plugins_favorites', 'install_plugins_favorites_form', 9, 0 );
				break;

			default:
				$args = false;
				break;
		}

		/**
		 * Filters API request arguments for each Add Plugins screen tab.
		 *
		 * The dynamic portion of the hook name, `$tab`, refers to the plugin install tabs.
		 *
		 * Possible hook names include:
		 *
		 *  - `install_plugins_table_api_args_favorites`
		 *  - `install_plugins_table_api_args_featured`
		 *  - `install_plugins_table_api_args_popular`
		 *  - `install_plugins_table_api_args_recommended`
		 *  - `install_plugins_table_api_args_upload`
		 *  - `install_plugins_table_api_args_search`
		 *  - `install_plugins_table_api_args_beta`
		 *
		 * @since 3.7.0
		 *
		 * @param array|false $args Plugin install API arguments.
		 */
		$args = apply_filters( "install_plugins_table_api_args_{$tab}", $args );

		if ( ! $args ) {
			return;
		}

		$api = plugins_api( 'query_plugins', $args );

		if ( is_wp_error( $api ) ) {
			$this->error = $api;
			return;
		}

		$this->items = $api->plugins;

		if ( $this->orderby ) {
			uasort( $this->items, array( $this, 'order_callback' ) );
		}

		$this->set_pagination_args(
			array(
				'total_items' => $api->info['results'],
				'per_page'    => $args['per_page'],
			)
		);

		if ( isset( $api->info['groups'] ) ) {
			$this->groups = $api->info['groups'];
		}

		if ( $installed_plugins ) {
			$js_plugins = array_fill_keys(
				array( 'all', 'search', 'active', 'inactive', 'recently_activated', 'mustuse', 'dropins' ),
				array()
			);

			$js_plugins['all'] = array_values( wp_list_pluck( $installed_plugins, 'plugin' ) );
			$upgrade_plugins   = wp_filter_object_list( $installed_plugins, array( 'upgrade' => true ), 'and', 'plugin' );

			if ( $upgrade_plugins ) {
				$js_plugins['upgrade'] = array_values( $upgrade_plugins );
			}

			wp_localize_script(
				'updates',
				'_wpUpdatesItemCounts',
				array(
					'plugins' => $js_plugins,
					'totals'  => wp_get_update_data(),
				)
			);
		}
	}

	/**
	 */
	public function no_items() {
		if ( isset( $this->error ) ) {
			$error_message  = '<p>' . $this->error->get_error_message() . '</p>';
			$error_message .= '<p class="hide-if-no-js"><button class="button try-again">' . __( 'Try Again' ) . '</button></p>';
			wp_admin_notice(
				$error_message,
				array(
					'additional_classes' => array( 'inline', 'error' ),
					'paragraph_wrap'     => false,
				)
			);
			?>
		<?php } else { ?>
			<div class="no-plugin-results"><?php _e( 'No plugins found. Try a different search.' ); ?></div>
			<?php
		}
	}

	/**
	 * @global array $tabs
	 * @global string $tab
	 *
	 * @return array
	 */
	protected function get_views() {
		global $tabs, $tab;

		$display_tabs = array();
		foreach ( (array) $tabs as $action => $text ) {
			$display_tabs[ 'plugin-install-' . $action ] = array(
				'url'     => self_admin_url( 'plugin-install.php?tab=' . $action ),
				'label'   => $text,
				'current' => $action === $tab,
			);
		}
		// No longer a real tab.
		unset( $display_tabs['plugin-install-upload'] );

		return $this->get_views_links( $display_tabs );
	}

	/**
	 * Overrides parent views so we can use the filter bar display.
	 */
	public function views() {
		$views = $this->get_views();

		/** This filter is documented in wp-admin/includes/class-wp-list-table.php */
		$views = apply_filters( "views_{$this->screen->id}", $views );

		$this->screen->render_screen_reader_content( 'heading_views' );

		printf(
			/* translators: %s: https://wordpress.org/plugins/ */
			'<p>' . __( 'Plugins extend and expand the functionality of WordPress. You may install plugins from the <a href="%s">WordPress Plugin Directory</a> right on this page, or upload a plugin in .zip format by clicking the button above.' ) . '</p>',
			__( 'https://wordpress.org/plugins/' )
		);
		?>
<div class="wp-filter">
	<ul class="filter-links">
		<?php
		if ( ! empty( $views ) ) {
			foreach ( $views as $class => $view ) {
				$views[ $class ] = "\t<li class='$class'>$view";
			}
			echo implode( " </li>\n", $views ) . "</li>\n";
		}
		?>
	</ul>

		<?php install_search_form(); ?>
</div>
		<?php
	}

	/**
	 * Displays the plugin install table.
	 *
	 * Overrides the parent display() method to provide a different container.
	 *
	 * @since 4.0.0
	 */
	public function display() {
		$singular = $this->_args['singular'];

		$data_attr = '';

		if ( $singular ) {
			$data_attr = " data-wp-lists='list:$singular'";
		}

		$this->display_tablenav( 'top' );

		?>
<div class="wp-list-table <?php echo implode( ' ', $this->get_table_classes() ); ?>">
		<?php
		$this->screen->render_screen_reader_content( 'heading_list' );
		?>
	<div id="the-list"<?php echo $data_attr; ?>>
		<?php $this->display_rows_or_placeholder(); ?>
	</div>
</div>
		<?php
		$this->display_tablenav( 'bottom' );
	}

	/**
	 * @global string $tab
	 *
	 * @param string $which
	 */
	protected function display_tablenav( $which ) {
		if ( 'featured' === $GLOBALS['tab'] ) {
			return;
		}

		if ( 'top' === $which ) {
			wp_referer_field();
			?>
			<div class="tablenav top">
				<div class="alignleft actions">
					<?php
					/**
					 * Fires before the Plugin Install table header pagination is displayed.
					 *
					 * @since 2.7.0
					 */
					do_action( 'install_plugins_table_header' );
					?>
				</div>
				<?php $this->pagination( $which ); ?>
				<br class="clear" />
			</div>
		<?php } else { ?>
			<div class="tablenav bottom">
				<?php $this->pagination( $which ); ?>
				<br class="clear" />
			</div>
			<?php
		}
	}

	/**
	 * @return array
	 */
	protected function get_table_classes() {
		return array( 'widefat', $this->_args['plural'] );
	}

	/**
	 * @return string[] Array of column titles keyed by their column name.
	 */
	public function get_columns() {
		return array();
	}

	/**
	 * @param object $plugin_a
	 * @param object $plugin_b
	 * @return int
	 */
	private function order_callback( $plugin_a, $plugin_b ) {
		$orderby = $this->orderby;
		if ( ! isset( $plugin_a->$orderby, $plugin_b->$orderby ) ) {
			return 0;
		}

		$a = $plugin_a->$orderby;
		$b = $plugin_b->$orderby;

		if ( $a === $b ) {
			return 0;
		}

		if ( 'DESC' === $this->order ) {
			return ( $a < $b ) ? 1 : -1;
		} else {
			return ( $a < $b ) ? -1 : 1;
		}
	}

	/**
	 * Generates the list table rows.
	 *
	 * @since 3.1.0
	 */
	public function display_rows() {
		$plugins_allowedtags = array(
			'a'       => array(
				'href'   => array(),
				'title'  => array(),
				'target' => array(),
			),
			'abbr'    => array( 'title' => array() ),
			'acronym' => array( 'title' => array() ),
			'code'    => array(),
			'pre'     => array(),
			'em'      => array(),
			'strong'  => array(),
			'ul'      => array(),
			'ol'      => array(),
			'li'      => array(),
			'p'       => array(),
			'br'      => array(),
		);

		$plugins_group_titles = array(
			'Performance' => _x( 'Performance', 'Plugin installer group title' ),
			'Social'      => _x( 'Social', 'Plugin installer group title' ),
			'Tools'       => _x( 'Tools', 'Plugin installer group title' ),
		);

		$group = null;

		foreach ( (array) $this->items as $plugin ) {
			if ( is_object( $plugin ) ) {
				$plugin = (array) $plugin;
			}

			// Display the group heading if there is one.
			if ( isset( $plugin['group'] ) && $plugin['group'] !== $group ) {
				if ( isset( $this->groups[ $plugin['group'] ] ) ) {
					$group_name = $this->groups[ $plugin['group'] ];
					if ( isset( $plugins_group_titles[ $group_name ] ) ) {
						$group_name = $plugins_group_titles[ $group_name ];
					}
				} else {
					$group_name = $plugin['group'];
				}

				// Starting a new group, close off the divs of the last one.
				if ( ! empty( $group ) ) {
					echo '</div></div>';
				}

				echo '<div class="plugin-group"><h3>' . esc_html( $group_name ) . '</h3>';
				// Needs an extra wrapping div for nth-child selectors to work.
				echo '<div class="plugin-items">';

				$group = $plugin['group'];
			}

			$title = wp_kses( $plugin['name'], $plugins_allowedtags );

			// Remove any HTML from the description.
			$description = strip_tags( $plugin['short_description'] );

			/**
			 * Filters the plugin card description on the Add Plugins screen.
			 *
			 * @since 6.0.0
			 *
			 * @param string $description Plugin card description.
			 * @param array  $plugin      An array of plugin data. See {@see plugins_api()}
			 *                            for the list of possible values.
			 */
			$description = apply_filters( 'plugin_install_description', $description, $plugin );

			$version = wp_kses( $plugin['version'], $plugins_allowedtags );

			$name = strip_tags( $title . ' ' . $version );

			$author = wp_kses( $plugin['author'], $plugins_allowedtags );
			if ( ! empty( $author ) ) {
				/* translators: %s: Plugin author. */
				$author = ' <cite>' . sprintf( __( 'By %s' ), $author ) . '</cite>';
			}

			$requires_php = isset( $plugin['requires_php'] ) ? $plugin['requires_php'] : null;
			$requires_wp  = isset( $plugin['requires'] ) ? $plugin['requires'] : null;

			$compatible_php = is_php_version_compatible( $requires_php );
			$compatible_wp  = is_wp_version_compatible( $requires_wp );
			$tested_wp      = ( empty( $plugin['tested'] ) || version_compare( get_bloginfo( 'version' ), $plugin['tested'], '<=' ) );

			$action_links = array();

			$action_links[] = wp_get_plugin_action_button( $name, $plugin, $compatible_php, $compatible_wp );

			$details_link = self_admin_url(
				'plugin-install.php?tab=plugin-information&amp;plugin=' . $plugin['slug'] .
				'&amp;TB_iframe=true&amp;width=600&amp;height=550'
			);

			$action_links[] = sprintf(
				'<a href="%s" class="thickbox open-plugin-details-modal" aria-label="%s" data-title="%s">%s</a>',
				esc_url( $details_link ),
				/* translators: %s: Plugin name and version. */
				esc_attr( sprintf( __( 'More information about %s' ), $name ) ),
				esc_attr( $name ),
				__( 'More Details' )
			);

			if ( ! empty( $plugin['icons']['svg'] ) ) {
				$plugin_icon_url = $plugin['icons']['svg'];
			} elseif ( ! empty( $plugin['icons']['2x'] ) ) {
				$plugin_icon_url = $plugin['icons']['2x'];
			} elseif ( ! empty( $plugin['icons']['1x'] ) ) {
				$plugin_icon_url = $plugin['icons']['1x'];
			} else {
				$plugin_icon_url = $plugin['icons']['default'];
			}

			/**
			 * Filters the install action links for a plugin.
			 *
			 * @since 2.7.0
			 *
			 * @param string[] $action_links An array of plugin action links.
			 *                               Defaults are links to Details and Install Now.
			 * @param array    $plugin       An array of plugin data. See {@see plugins_api()}
			 *                               for the list of possible values.
			 */
			$action_links = apply_filters( 'plugin_install_action_links', $action_links, $plugin );

			$last_updated_timestamp = strtotime( $plugin['last_updated'] );
			?>
		<div class="plugin-card plugin-card-<?php echo sanitize_html_class( $plugin['slug'] ); ?>">
			<?php
			if ( ! $compatible_php || ! $compatible_wp ) {
				$incompatible_notice_message = '';
				if ( ! $compatible_php && ! $compatible_wp ) {
					$incompatible_notice_message .= __( 'This plugin does not work with your versions of WordPress and PHP.' );
					if ( current_user_can( 'update_core' ) && current_user_can( 'update_php' ) ) {
						$incompatible_notice_message .= sprintf(
							/* translators: 1: URL to WordPress Updates screen, 2: URL to Update PHP page. */
							' ' . __( '<a href="%1$s">Please update WordPress</a>, and then <a href="%2$s">learn more about updating PHP</a>.' ),
							self_admin_url( 'update-core.php' ),
							esc_url( wp_get_update_php_url() )
						);
						$incompatible_notice_message .= wp_update_php_annotation( '</p><p><em>', '</em>', false );
					} elseif ( current_user_can( 'update_core' ) ) {
						$incompatible_notice_message .= sprintf(
							/* translators: %s: URL to WordPress Updates screen. */
							' ' . __( '<a href="%s">Please update WordPress</a>.' ),
							self_admin_url( 'update-core.php' )
						);
					} elseif ( current_user_can( 'update_php' ) ) {
						$incompatible_notice_message .= sprintf(
							/* translators: %s: URL to Update PHP page. */
							' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
							esc_url( wp_get_update_php_url() )
						);
						$incompatible_notice_message .= wp_update_php_annotation( '</p><p><em>', '</em>', false );
					}
				} elseif ( ! $compatible_wp ) {
					$incompatible_notice_message .= __( 'This plugin does not work with your version of WordPress.' );
					if ( current_user_can( 'update_core' ) ) {
						$incompatible_notice_message .= sprintf(
							/* translators: %s: URL to WordPress Updates screen. */
							' ' . __( '<a href="%s">Please update WordPress</a>.' ),
							self_admin_url( 'update-core.php' )
						);
					}
				} elseif ( ! $compatible_php ) {
					$incompatible_notice_message .= __( 'This plugin does not work with your version of PHP.' );
					if ( current_user_can( 'update_php' ) ) {
						$incompatible_notice_message .= sprintf(
							/* translators: %s: URL to Update PHP page. */
							' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ),
							esc_url( wp_get_update_php_url() )
						);
						$incompatible_notice_message .= wp_update_php_annotation( '</p><p><em>', '</em>', false );
					}
				}

				wp_admin_notice(
					$incompatible_notice_message,
					array(
						'type'               => 'error',
						'additional_classes' => array( 'notice-alt', 'inline' ),
					)
				);
			}
			?>
			<div class="plugin-card-top">
				<div class="name column-name">
					<h3>
						<a href="<?php echo esc_url( $details_link ); ?>" class="thickbox open-plugin-details-modal">
						<?php echo $title; ?>
						<img src="<?php echo esc_url( $plugin_icon_url ); ?>" class="plugin-icon" alt="" />
						</a>
					</h3>
				</div>
				<div class="action-links">
					<?php
					if ( $action_links ) {
						echo '<ul class="plugin-action-buttons"><li>' . implode( '</li><li>', $action_links ) . '</li></ul>';
					}
					?>
				</div>
				<div class="desc column-description">
					<p><?php echo $description; ?></p>
					<p class="authors"><?php echo $author; ?></p>
				</div>
			</div>
			<?php
			$dependencies_notice = $this->get_dependencies_notice( $plugin );
			if ( ! empty( $dependencies_notice ) ) {
				echo $dependencies_notice;
			}
			?>
			<div class="plugin-card-bottom">
				<div class="vers column-rating">
					<?php
					wp_star_rating(
						array(
							'rating' => $plugin['rating'],
							'type'   => 'percent',
							'number' => $plugin['num_ratings'],
						)
					);
					?>
					<span class="num-ratings" aria-hidden="true">(<?php echo number_format_i18n( $plugin['num_ratings'] ); ?>)</span>
				</div>
				<div class="column-updated">
					<strong><?php _e( 'Last Updated:' ); ?></strong>
					<?php
						/* translators: %s: Human-readable time difference. */
						printf( __( '%s ago' ), human_time_diff( $last_updated_timestamp ) );
					?>
				</div>
				<div class="column-downloaded">
					<?php
					if ( $plugin['active_installs'] >= 1000000 ) {
						$active_installs_millions = floor( $plugin['active_installs'] / 1000000 );
						$active_installs_text     = sprintf(
							/* translators: %s: Number of millions. */
							_nx( '%s+ Million', '%s+ Million', $active_installs_millions, 'Active plugin installations' ),
							number_format_i18n( $active_installs_millions )
						);
					} elseif ( 0 === $plugin['active_installs'] ) {
						$active_installs_text = _x( 'Less Than 10', 'Active plugin installations' );
					} else {
						$active_installs_text = number_format_i18n( $plugin['active_installs'] ) . '+';
					}
					/* translators: %s: Number of installations. */
					printf( __( '%s Active Installations' ), $active_installs_text );
					?>
				</div>
				<div class="column-compatibility">
					<?php
					if ( ! $tested_wp ) {
						echo '<span class="compatibility-untested">' . __( 'Untested with your version of WordPress' ) . '</span>';
					} elseif ( ! $compatible_wp ) {
						echo '<span class="compatibility-incompatible">' . __( '<strong>Incompatible</strong> with your version of WordPress' ) . '</span>';
					} else {
						echo '<span class="compatibility-compatible">' . __( '<strong>Compatible</strong> with your version of WordPress' ) . '</span>';
					}
					?>
				</div>
			</div>
		</div>
			<?php
		}

		// Close off the group divs of the last one.
		if ( ! empty( $group ) ) {
			echo '</div></div>';
		}
	}

	/**
	 * Returns a notice containing a list of dependencies required by the plugin.
	 *
	 * @since 6.5.0
	 *
	 * @param array  $plugin_data An array of plugin data. See {@see plugins_api()}
	 *                            for the list of possible values.
	 * @return string A notice containing a list of dependencies required by the plugin,
	 *                or an empty string if none is required.
	 */
	protected function get_dependencies_notice( $plugin_data ) {
		if ( empty( $plugin_data['requires_plugins'] ) ) {
			return '';
		}

		$no_name_markup  = '<div class="plugin-dependency"><span class="plugin-dependency-name">%s</span></div>';
		$has_name_markup = '<div class="plugin-dependency"><span class="plugin-dependency-name">%s</span> %s</div>';

		$dependencies_list = '';
		foreach ( $plugin_data['requires_plugins'] as $dependency ) {
			$dependency_data = WP_Plugin_Dependencies::get_dependency_data( $dependency );

			if (
				false !== $dependency_data &&
				! empty( $dependency_data['name'] ) &&
				! empty( $dependency_data['slug'] ) &&
				! empty( $dependency_data['version'] )
			) {
				$more_details_link  = $this->get_more_details_link( $dependency_data['name'], $dependency_data['slug'] );
				$dependencies_list .= sprintf( $has_name_markup, esc_html( $dependency_data['name'] ), $more_details_link );
				continue;
			}

			$result = plugins_api( 'plugin_information', array( 'slug' => $dependency ) );

			if ( ! empty( $result->name ) ) {
				$more_details_link  = $this->get_more_details_link( $result->name, $result->slug );
				$dependencies_list .= sprintf( $has_name_markup, esc_html( $result->name ), $more_details_link );
				continue;
			}

			$dependencies_list .= sprintf( $no_name_markup, esc_html( $dependency ) );
		}

		$dependencies_notice = sprintf(
			'<div class="plugin-dependencies notice notice-alt notice-info inline"><p class="plugin-dependencies-explainer-text">%s</p> %s</div>',
			'<strong>' . __( 'Additional plugins are required' ) . '</strong>',
			$dependencies_list
		);

		return $dependencies_notice;
	}

	/**
	 * Creates a 'More details' link for the plugin.
	 *
	 * @since 6.5.0
	 *
	 * @param string $name The plugin's name.
	 * @param string $slug The plugin's slug.
	 * @return string The 'More details' link for the plugin.
	 */
	protected function get_more_details_link( $name, $slug ) {
		$url = add_query_arg(
			array(
				'tab'       => 'plugin-information',
				'plugin'    => $slug,
				'TB_iframe' => 'true',
				'width'     => '600',
				'height'    => '550',
			),
			network_admin_url( 'plugin-install.php' )
		);

		$more_details_link = sprintf(
			'<a href="%1$s" class="more-details-link thickbox open-plugin-details-modal" aria-label="%2$s" data-title="%3$s">%4$s</a>',
			esc_url( $url ),
			/* translators: %s: Plugin name. */
			sprintf( __( 'More information about %s' ), esc_html( $name ) ),
			esc_attr( $name ),
			__( 'More Details' )
		);

		return $more_details_link;
	}
}
import.php000064400000014731151212616060006575 0ustar00<?php
/**
 * WordPress Administration Importer API.
 *
 * @package WordPress
 * @subpackage Administration
 */

/**
 * Retrieves the list of importers.
 *
 * @since 2.0.0
 *
 * @global array $wp_importers
 * @return array
 */
function get_importers() {
	global $wp_importers;
	if ( is_array( $wp_importers ) ) {
		uasort( $wp_importers, '_usort_by_first_member' );
	}
	return $wp_importers;
}

/**
 * Sorts a multidimensional array by first member of each top level member.
 *
 * Used by uasort() as a callback, should not be used directly.
 *
 * @since 2.9.0
 * @access private
 *
 * @param array $a
 * @param array $b
 * @return int
 */
function _usort_by_first_member( $a, $b ) {
	return strnatcasecmp( $a[0], $b[0] );
}

/**
 * Registers importer for WordPress.
 *
 * @since 2.0.0
 *
 * @global array $wp_importers
 *
 * @param string   $id          Importer tag. Used to uniquely identify importer.
 * @param string   $name        Importer name and title.
 * @param string   $description Importer description.
 * @param callable $callback    Callback to run.
 * @return void|WP_Error Void on success. WP_Error when $callback is WP_Error.
 */
function register_importer( $id, $name, $description, $callback ) {
	global $wp_importers;
	if ( is_wp_error( $callback ) ) {
		return $callback;
	}
	$wp_importers[ $id ] = array( $name, $description, $callback );
}

/**
 * Cleanup importer.
 *
 * Removes attachment based on ID.
 *
 * @since 2.0.0
 *
 * @param string $id Importer ID.
 */
function wp_import_cleanup( $id ) {
	wp_delete_attachment( $id );
}

/**
 * Handles importer uploading and adds attachment.
 *
 * @since 2.0.0
 *
 * @return array Uploaded file's details on success, error message on failure.
 */
function wp_import_handle_upload() {
	if ( ! isset( $_FILES['import'] ) ) {
		return array(
			'error' => sprintf(
				/* translators: 1: php.ini, 2: post_max_size, 3: upload_max_filesize */
				__( 'File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your %1$s file or by %2$s being defined as smaller than %3$s in %1$s.' ),
				'php.ini',
				'post_max_size',
				'upload_max_filesize'
			),
		);
	}

	$overrides                 = array(
		'test_form' => false,
		'test_type' => false,
	);
	$_FILES['import']['name'] .= '.txt';
	$upload                    = wp_handle_upload( $_FILES['import'], $overrides );

	if ( isset( $upload['error'] ) ) {
		return $upload;
	}

	// Construct the attachment array.
	$attachment = array(
		'post_title'     => wp_basename( $upload['file'] ),
		'post_content'   => $upload['url'],
		'post_mime_type' => $upload['type'],
		'guid'           => $upload['url'],
		'context'        => 'import',
		'post_status'    => 'private',
	);

	// Save the data.
	$id = wp_insert_attachment( $attachment, $upload['file'] );

	/*
	 * Schedule a cleanup for one day from now in case of failed
	 * import or missing wp_import_cleanup() call.
	 */
	wp_schedule_single_event( time() + DAY_IN_SECONDS, 'importer_scheduled_cleanup', array( $id ) );

	return array(
		'file' => $upload['file'],
		'id'   => $id,
	);
}

/**
 * Returns a list from WordPress.org of popular importer plugins.
 *
 * @since 3.5.0
 *
 * @return array Importers with metadata for each.
 */
function wp_get_popular_importers() {
	$locale            = get_user_locale();
	$cache_key         = 'popular_importers_' . md5( $locale . wp_get_wp_version() );
	$popular_importers = get_site_transient( $cache_key );

	if ( ! $popular_importers ) {
		$url     = add_query_arg(
			array(
				'locale'  => $locale,
				'version' => wp_get_wp_version(),
			),
			'http://api.wordpress.org/core/importers/1.1/'
		);
		$options = array( 'user-agent' => 'WordPress/' . wp_get_wp_version() . '; ' . home_url( '/' ) );

		if ( wp_http_supports( array( 'ssl' ) ) ) {
			$url = set_url_scheme( $url, 'https' );
		}

		$response          = wp_remote_get( $url, $options );
		$popular_importers = json_decode( wp_remote_retrieve_body( $response ), true );

		if ( is_array( $popular_importers ) ) {
			set_site_transient( $cache_key, $popular_importers, 2 * DAY_IN_SECONDS );
		} else {
			$popular_importers = false;
		}
	}

	if ( is_array( $popular_importers ) ) {
		// If the data was received as translated, return it as-is.
		if ( $popular_importers['translated'] ) {
			return $popular_importers['importers'];
		}

		foreach ( $popular_importers['importers'] as &$importer ) {
			// phpcs:ignore WordPress.WP.I18n.LowLevelTranslationFunction,WordPress.WP.I18n.NonSingularStringLiteralText
			$importer['description'] = translate( $importer['description'] );
			if ( 'WordPress' !== $importer['name'] ) {
				// phpcs:ignore WordPress.WP.I18n.LowLevelTranslationFunction,WordPress.WP.I18n.NonSingularStringLiteralText
				$importer['name'] = translate( $importer['name'] );
			}
		}
		return $popular_importers['importers'];
	}

	return array(
		// slug => name, description, plugin slug, and register_importer() slug.
		'blogger'     => array(
			'name'        => __( 'Blogger' ),
			'description' => __( 'Import posts, comments, and users from a Blogger blog.' ),
			'plugin-slug' => 'blogger-importer',
			'importer-id' => 'blogger',
		),
		'wpcat2tag'   => array(
			'name'        => __( 'Categories and Tags Converter' ),
			'description' => __( 'Convert existing categories to tags or tags to categories, selectively.' ),
			'plugin-slug' => 'wpcat2tag-importer',
			'importer-id' => 'wp-cat2tag',
		),
		'livejournal' => array(
			'name'        => __( 'LiveJournal' ),
			'description' => __( 'Import posts from LiveJournal using their API.' ),
			'plugin-slug' => 'livejournal-importer',
			'importer-id' => 'livejournal',
		),
		'movabletype' => array(
			'name'        => __( 'Movable Type and TypePad' ),
			'description' => __( 'Import posts and comments from a Movable Type or TypePad blog.' ),
			'plugin-slug' => 'movabletype-importer',
			'importer-id' => 'mt',
		),
		'rss'         => array(
			'name'        => __( 'RSS' ),
			'description' => __( 'Import posts from an RSS feed.' ),
			'plugin-slug' => 'rss-importer',
			'importer-id' => 'rss',
		),
		'tumblr'      => array(
			'name'        => __( 'Tumblr' ),
			'description' => __( 'Import posts &amp; media from Tumblr using their API.' ),
			'plugin-slug' => 'tumblr-importer',
			'importer-id' => 'tumblr',
		),
		'wordpress'   => array(
			'name'        => 'WordPress',
			'description' => __( 'Import posts, pages, comments, custom fields, categories, and tags from a WordPress export file.' ),
			'plugin-slug' => 'wordpress-importer',
			'importer-id' => 'wordpress',
		),
	);
}
image.php000064400000123360151212616060006344 0ustar00<?php
/**
 * File contains all the administration image manipulation functions.
 *
 * @package WordPress
 * @subpackage Administration
 */

/**
 * Crops an image to a given size.
 *
 * @since 2.1.0
 *
 * @param string|int   $src      The source file or Attachment ID.
 * @param int          $src_x    The start x position to crop from.
 * @param int          $src_y    The start y position to crop from.
 * @param int          $src_w    The width to crop.
 * @param int          $src_h    The height to crop.
 * @param int          $dst_w    The destination width.
 * @param int          $dst_h    The destination height.
 * @param bool|false   $src_abs  Optional. If the source crop points are absolute.
 * @param string|false $dst_file Optional. The destination file to write to.
 * @return string|WP_Error New filepath on success, WP_Error on failure.
 */
function wp_crop_image( $src, $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs = false, $dst_file = false ) {
	$src_file = $src;
	if ( is_numeric( $src ) ) { // Handle int as attachment ID.
		$src_file = get_attached_file( $src );

		if ( ! file_exists( $src_file ) ) {
			/*
			 * If the file doesn't exist, attempt a URL fopen on the src link.
			 * This can occur with certain file replication plugins.
			 */
			$src = _load_image_to_edit_path( $src, 'full' );
		} else {
			$src = $src_file;
		}
	}

	$editor = wp_get_image_editor( $src );
	if ( is_wp_error( $editor ) ) {
		return $editor;
	}

	$src = $editor->crop( $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs );
	if ( is_wp_error( $src ) ) {
		return $src;
	}

	if ( ! $dst_file ) {
		$dst_file = str_replace( wp_basename( $src_file ), 'cropped-' . wp_basename( $src_file ), $src_file );
	}

	/*
	 * The directory containing the original file may no longer exist when
	 * using a replication plugin.
	 */
	wp_mkdir_p( dirname( $dst_file ) );

	$dst_file = dirname( $dst_file ) . '/' . wp_unique_filename( dirname( $dst_file ), wp_basename( $dst_file ) );

	$result = $editor->save( $dst_file );
	if ( is_wp_error( $result ) ) {
		return $result;
	}

	if ( ! empty( $result['path'] ) ) {
		return $result['path'];
	}

	return $dst_file;
}

/**
 * Compare the existing image sub-sizes (as saved in the attachment meta)
 * to the currently registered image sub-sizes, and return the difference.
 *
 * Registered sub-sizes that are larger than the image are skipped.
 *
 * @since 5.3.0
 *
 * @param int $attachment_id The image attachment post ID.
 * @return array[] Associative array of arrays of image sub-size information for
 *                 missing image sizes, keyed by image size name.
 */
function wp_get_missing_image_subsizes( $attachment_id ) {
	if ( ! wp_attachment_is_image( $attachment_id ) ) {
		return array();
	}

	$registered_sizes = wp_get_registered_image_subsizes();
	$image_meta       = wp_get_attachment_metadata( $attachment_id );

	// Meta error?
	if ( empty( $image_meta ) ) {
		return $registered_sizes;
	}

	// Use the originally uploaded image dimensions as full_width and full_height.
	if ( ! empty( $image_meta['original_image'] ) ) {
		$image_file = wp_get_original_image_path( $attachment_id );
		$imagesize  = wp_getimagesize( $image_file );
	}

	if ( ! empty( $imagesize ) ) {
		$full_width  = $imagesize[0];
		$full_height = $imagesize[1];
	} else {
		$full_width  = (int) $image_meta['width'];
		$full_height = (int) $image_meta['height'];
	}

	$possible_sizes = array();

	// Skip registered sizes that are too large for the uploaded image.
	foreach ( $registered_sizes as $size_name => $size_data ) {
		if ( image_resize_dimensions( $full_width, $full_height, $size_data['width'], $size_data['height'], $size_data['crop'] ) ) {
			$possible_sizes[ $size_name ] = $size_data;
		}
	}

	if ( empty( $image_meta['sizes'] ) ) {
		$image_meta['sizes'] = array();
	}

	/*
	 * Remove sizes that already exist. Only checks for matching "size names".
	 * It is possible that the dimensions for a particular size name have changed.
	 * For example the user has changed the values on the Settings -> Media screen.
	 * However we keep the old sub-sizes with the previous dimensions
	 * as the image may have been used in an older post.
	 */
	$missing_sizes = array_diff_key( $possible_sizes, $image_meta['sizes'] );

	/**
	 * Filters the array of missing image sub-sizes for an uploaded image.
	 *
	 * @since 5.3.0
	 *
	 * @param array[] $missing_sizes Associative array of arrays of image sub-size information for
	 *                               missing image sizes, keyed by image size name.
	 * @param array   $image_meta    The image meta data.
	 * @param int     $attachment_id The image attachment post ID.
	 */
	return apply_filters( 'wp_get_missing_image_subsizes', $missing_sizes, $image_meta, $attachment_id );
}

/**
 * If any of the currently registered image sub-sizes are missing,
 * create them and update the image meta data.
 *
 * @since 5.3.0
 *
 * @param int $attachment_id The image attachment post ID.
 * @return array|WP_Error The updated image meta data array or WP_Error object
 *                        if both the image meta and the attached file are missing.
 */
function wp_update_image_subsizes( $attachment_id ) {
	$image_meta = wp_get_attachment_metadata( $attachment_id );
	$image_file = wp_get_original_image_path( $attachment_id );

	if ( empty( $image_meta ) || ! is_array( $image_meta ) ) {
		/*
		 * Previously failed upload?
		 * If there is an uploaded file, make all sub-sizes and generate all of the attachment meta.
		 */
		if ( ! empty( $image_file ) ) {
			$image_meta = wp_create_image_subsizes( $image_file, $attachment_id );
		} else {
			return new WP_Error( 'invalid_attachment', __( 'The attached file cannot be found.' ) );
		}
	} else {
		$missing_sizes = wp_get_missing_image_subsizes( $attachment_id );

		if ( empty( $missing_sizes ) ) {
			return $image_meta;
		}

		// This also updates the image meta.
		$image_meta = _wp_make_subsizes( $missing_sizes, $image_file, $image_meta, $attachment_id );
	}

	/** This filter is documented in wp-admin/includes/image.php */
	$image_meta = apply_filters( 'wp_generate_attachment_metadata', $image_meta, $attachment_id, 'update' );

	// Save the updated metadata.
	wp_update_attachment_metadata( $attachment_id, $image_meta );

	return $image_meta;
}

/**
 * Updates the attached file and image meta data when the original image was edited.
 *
 * @since 5.3.0
 * @since 6.0.0 The `$filesize` value was added to the returned array.
 * @access private
 *
 * @param array  $saved_data    The data returned from WP_Image_Editor after successfully saving an image.
 * @param string $original_file Path to the original file.
 * @param array  $image_meta    The image meta data.
 * @param int    $attachment_id The attachment post ID.
 * @return array The updated image meta data.
 */
function _wp_image_meta_replace_original( $saved_data, $original_file, $image_meta, $attachment_id ) {
	$new_file = $saved_data['path'];

	// Update the attached file meta.
	update_attached_file( $attachment_id, $new_file );

	// Width and height of the new image.
	$image_meta['width']  = $saved_data['width'];
	$image_meta['height'] = $saved_data['height'];

	// Make the file path relative to the upload dir.
	$image_meta['file'] = _wp_relative_upload_path( $new_file );

	// Add image file size.
	$image_meta['filesize'] = wp_filesize( $new_file );

	// Store the original image file name in image_meta.
	$image_meta['original_image'] = wp_basename( $original_file );

	return $image_meta;
}

/**
 * Creates image sub-sizes, adds the new data to the image meta `sizes` array, and updates the image metadata.
 *
 * Intended for use after an image is uploaded. Saves/updates the image metadata after each
 * sub-size is created. If there was an error, it is added to the returned image metadata array.
 *
 * @since 5.3.0
 *
 * @param string $file          Full path to the image file.
 * @param int    $attachment_id Attachment ID to process.
 * @return array The image attachment meta data.
 */
function wp_create_image_subsizes( $file, $attachment_id ) {
	$imagesize = wp_getimagesize( $file );

	if ( empty( $imagesize ) ) {
		// File is not an image.
		return array();
	}

	// Default image meta.
	$image_meta = array(
		'width'    => $imagesize[0],
		'height'   => $imagesize[1],
		'file'     => _wp_relative_upload_path( $file ),
		'filesize' => wp_filesize( $file ),
		'sizes'    => array(),
	);

	// Fetch additional metadata from EXIF/IPTC.
	$exif_meta = wp_read_image_metadata( $file );

	if ( $exif_meta ) {
		$image_meta['image_meta'] = $exif_meta;
	}

	/**
	 * Filters the "BIG image" threshold value.
	 *
	 * If the original image width or height is above the threshold, it will be scaled down. The threshold is
	 * used as max width and max height. The scaled down image will be used as the largest available size, including
	 * the `_wp_attached_file` post meta value.
	 *
	 * Returning `false` from the filter callback will disable the scaling.
	 *
	 * @since 5.3.0
	 *
	 * @param int    $threshold     The threshold value in pixels. Default 2560.
	 * @param array  $imagesize     {
	 *     Indexed array of the image width and height in pixels.
	 *
	 *     @type int $0 The image width.
	 *     @type int $1 The image height.
	 * }
	 * @param string $file          Full path to the uploaded image file.
	 * @param int    $attachment_id Attachment post ID.
	 */
	$threshold = (int) apply_filters( 'big_image_size_threshold', 2560, $imagesize, $file, $attachment_id );

	/*
	 * If the original image's dimensions are over the threshold,
	 * scale the image and use it as the "full" size.
	 */
	$scale_down = false;
	$convert    = false;

	if ( $threshold && ( $image_meta['width'] > $threshold || $image_meta['height'] > $threshold ) ) {
		// The image will be converted if needed on saving.
		$scale_down = true;
	} else {
		// The image may need to be converted regardless of its dimensions.
		$output_format = wp_get_image_editor_output_format( $file, $imagesize['mime'] );

		if (
			is_array( $output_format ) &&
			array_key_exists( $imagesize['mime'], $output_format ) &&
			$output_format[ $imagesize['mime'] ] !== $imagesize['mime']
		) {
			$convert = true;
		}
	}

	if ( $scale_down || $convert ) {
		$editor = wp_get_image_editor( $file );

		if ( is_wp_error( $editor ) ) {
			// This image cannot be edited.
			return $image_meta;
		}

		if ( $scale_down ) {
			// Resize the image. This will also convet it if needed.
			$resized = $editor->resize( $threshold, $threshold );
		} elseif ( $convert ) {
			// The image will be converted (if possible) when saved.
			$resized = true;
		}

		$rotated = null;

		// If there is EXIF data, rotate according to EXIF Orientation.
		if ( ! is_wp_error( $resized ) && is_array( $exif_meta ) ) {
			$resized = $editor->maybe_exif_rotate();
			$rotated = $resized; // bool true or WP_Error
		}

		if ( ! is_wp_error( $resized ) ) {
			/*
			 * Append "-scaled" to the image file name. It will look like "my_image-scaled.jpg".
			 * This doesn't affect the sub-sizes names as they are generated from the original image (for best quality).
			 */
			if ( $scale_down ) {
				$saved = $editor->save( $editor->generate_filename( 'scaled' ) );
			} elseif ( $convert ) {
				// Pass an empty string to avoid adding a suffix to converted file names.
				$saved = $editor->save( $editor->generate_filename( '' ) );
			} else {
				$saved = $editor->save();
			}

			if ( ! is_wp_error( $saved ) ) {
				$image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id );

				// If the image was rotated update the stored EXIF data.
				if ( true === $rotated && ! empty( $image_meta['image_meta']['orientation'] ) ) {
					$image_meta['image_meta']['orientation'] = 1;
				}
			} else {
				// TODO: Log errors.
			}
		} else {
			// TODO: Log errors.
		}
	} elseif ( ! empty( $exif_meta['orientation'] ) && 1 !== (int) $exif_meta['orientation'] ) {
		// Rotate the whole original image if there is EXIF data and "orientation" is not 1.
		$editor = wp_get_image_editor( $file );

		if ( is_wp_error( $editor ) ) {
			// This image cannot be edited.
			return $image_meta;
		}

		// Rotate the image.
		$rotated = $editor->maybe_exif_rotate();

		if ( true === $rotated ) {
			// Append `-rotated` to the image file name.
			$saved = $editor->save( $editor->generate_filename( 'rotated' ) );

			if ( ! is_wp_error( $saved ) ) {
				$image_meta = _wp_image_meta_replace_original( $saved, $file, $image_meta, $attachment_id );

				// Update the stored EXIF data.
				if ( ! empty( $image_meta['image_meta']['orientation'] ) ) {
					$image_meta['image_meta']['orientation'] = 1;
				}
			} else {
				// TODO: Log errors.
			}
		}
	}

	/*
	 * Initial save of the new metadata.
	 * At this point the file was uploaded and moved to the uploads directory
	 * but the image sub-sizes haven't been created yet and the `sizes` array is empty.
	 */
	wp_update_attachment_metadata( $attachment_id, $image_meta );

	$new_sizes = wp_get_registered_image_subsizes();

	/**
	 * Filters the image sizes automatically generated when uploading an image.
	 *
	 * @since 2.9.0
	 * @since 4.4.0 Added the `$image_meta` argument.
	 * @since 5.3.0 Added the `$attachment_id` argument.
	 *
	 * @param array $new_sizes     Associative array of image sizes to be created.
	 * @param array $image_meta    The image meta data: width, height, file, sizes, etc.
	 * @param int   $attachment_id The attachment post ID for the image.
	 */
	$new_sizes = apply_filters( 'intermediate_image_sizes_advanced', $new_sizes, $image_meta, $attachment_id );

	return _wp_make_subsizes( $new_sizes, $file, $image_meta, $attachment_id );
}

/**
 * Low-level function to create image sub-sizes.
 *
 * Updates the image meta after each sub-size is created.
 * Errors are stored in the returned image metadata array.
 *
 * @since 5.3.0
 * @access private
 *
 * @param array  $new_sizes     Array defining what sizes to create.
 * @param string $file          Full path to the image file.
 * @param array  $image_meta    The attachment meta data array.
 * @param int    $attachment_id Attachment ID to process.
 * @return array The attachment meta data with updated `sizes` array. Includes an array of errors encountered while resizing.
 */
function _wp_make_subsizes( $new_sizes, $file, $image_meta, $attachment_id ) {
	if ( empty( $image_meta ) || ! is_array( $image_meta ) ) {
		// Not an image attachment.
		return array();
	}

	// Check if any of the new sizes already exist.
	if ( isset( $image_meta['sizes'] ) && is_array( $image_meta['sizes'] ) ) {
		foreach ( $image_meta['sizes'] as $size_name => $size_meta ) {
			/*
			 * Only checks "size name" so we don't override existing images even if the dimensions
			 * don't match the currently defined size with the same name.
			 * To change the behavior, unset changed/mismatched sizes in the `sizes` array in image meta.
			 */
			if ( array_key_exists( $size_name, $new_sizes ) ) {
				unset( $new_sizes[ $size_name ] );
			}
		}
	} else {
		$image_meta['sizes'] = array();
	}

	if ( empty( $new_sizes ) ) {
		// Nothing to do...
		return $image_meta;
	}

	/*
	 * Sort the image sub-sizes in order of priority when creating them.
	 * This ensures there is an appropriate sub-size the user can access immediately
	 * even when there was an error and not all sub-sizes were created.
	 */
	$priority = array(
		'medium'       => null,
		'large'        => null,
		'thumbnail'    => null,
		'medium_large' => null,
	);

	$new_sizes = array_filter( array_merge( $priority, $new_sizes ) );

	$editor = wp_get_image_editor( $file );

	if ( is_wp_error( $editor ) ) {
		// The image cannot be edited.
		return $image_meta;
	}

	// If stored EXIF data exists, rotate the source image before creating sub-sizes.
	if ( ! empty( $image_meta['image_meta'] ) ) {
		$rotated = $editor->maybe_exif_rotate();

		if ( is_wp_error( $rotated ) ) {
			// TODO: Log errors.
		}
	}

	if ( method_exists( $editor, 'make_subsize' ) ) {
		foreach ( $new_sizes as $new_size_name => $new_size_data ) {
			$new_size_meta = $editor->make_subsize( $new_size_data );

			if ( is_wp_error( $new_size_meta ) ) {
				// TODO: Log errors.
			} else {
				// Save the size meta value.
				$image_meta['sizes'][ $new_size_name ] = $new_size_meta;
				wp_update_attachment_metadata( $attachment_id, $image_meta );
			}
		}
	} else {
		// Fall back to `$editor->multi_resize()`.
		$created_sizes = $editor->multi_resize( $new_sizes );

		if ( ! empty( $created_sizes ) ) {
			$image_meta['sizes'] = array_merge( $image_meta['sizes'], $created_sizes );
			wp_update_attachment_metadata( $attachment_id, $image_meta );
		}
	}

	return $image_meta;
}

/**
 * Copy parent attachment properties to newly cropped image.
 *
 * @since 6.5.0
 *
 * @param string $cropped              Path to the cropped image file.
 * @param int    $parent_attachment_id Parent file Attachment ID.
 * @param string $context              Control calling the function.
 * @return array Properties of attachment.
 */
function wp_copy_parent_attachment_properties( $cropped, $parent_attachment_id, $context = '' ) {
	$parent          = get_post( $parent_attachment_id );
	$parent_url      = wp_get_attachment_url( $parent->ID );
	$parent_basename = wp_basename( $parent_url );
	$url             = str_replace( wp_basename( $parent_url ), wp_basename( $cropped ), $parent_url );

	$size       = wp_getimagesize( $cropped );
	$image_type = $size ? $size['mime'] : 'image/jpeg';

	$sanitized_post_title = sanitize_file_name( $parent->post_title );
	$use_original_title   = (
		( '' !== trim( $parent->post_title ) ) &&
		/*
		 * Check if the original image has a title other than the "filename" default,
		 * meaning the image had a title when originally uploaded or its title was edited.
		 */
		( $parent_basename !== $sanitized_post_title ) &&
		( pathinfo( $parent_basename, PATHINFO_FILENAME ) !== $sanitized_post_title )
	);
	$use_original_description = ( '' !== trim( $parent->post_content ) );

	$attachment = array(
		'post_title'     => $use_original_title ? $parent->post_title : wp_basename( $cropped ),
		'post_content'   => $use_original_description ? $parent->post_content : $url,
		'post_mime_type' => $image_type,
		'guid'           => $url,
		'context'        => $context,
	);

	// Copy the image caption attribute (post_excerpt field) from the original image.
	if ( '' !== trim( $parent->post_excerpt ) ) {
		$attachment['post_excerpt'] = $parent->post_excerpt;
	}

	// Copy the image alt text attribute from the original image.
	if ( '' !== trim( $parent->_wp_attachment_image_alt ) ) {
		$attachment['meta_input'] = array(
			'_wp_attachment_image_alt' => wp_slash( $parent->_wp_attachment_image_alt ),
		);
	}

	$attachment['post_parent'] = $parent_attachment_id;

	return $attachment;
}

/**
 * Generates attachment meta data and create image sub-sizes for images.
 *
 * @since 2.1.0
 * @since 6.0.0 The `$filesize` value was added to the returned array.
 * @since 6.7.0 The 'image/heic' mime type is supported.
 *
 * @param int    $attachment_id Attachment ID to process.
 * @param string $file          Filepath of the attached image.
 * @return array Metadata for attachment.
 */
function wp_generate_attachment_metadata( $attachment_id, $file ) {
	$attachment = get_post( $attachment_id );

	$metadata  = array();
	$support   = false;
	$mime_type = get_post_mime_type( $attachment );

	if ( 'image/heic' === $mime_type || ( preg_match( '!^image/!', $mime_type ) && file_is_displayable_image( $file ) ) ) {
		// Make thumbnails and other intermediate sizes.
		$metadata = wp_create_image_subsizes( $file, $attachment_id );
	} elseif ( wp_attachment_is( 'video', $attachment ) ) {
		$metadata = wp_read_video_metadata( $file );
		$support  = current_theme_supports( 'post-thumbnails', 'attachment:video' ) || post_type_supports( 'attachment:video', 'thumbnail' );
	} elseif ( wp_attachment_is( 'audio', $attachment ) ) {
		$metadata = wp_read_audio_metadata( $file );
		$support  = current_theme_supports( 'post-thumbnails', 'attachment:audio' ) || post_type_supports( 'attachment:audio', 'thumbnail' );
	}

	/*
	 * wp_read_video_metadata() and wp_read_audio_metadata() return `false`
	 * if the attachment does not exist in the local filesystem,
	 * so make sure to convert the value to an array.
	 */
	if ( ! is_array( $metadata ) ) {
		$metadata = array();
	}

	if ( $support && ! empty( $metadata['image']['data'] ) ) {
		// Check for existing cover.
		$hash   = md5( $metadata['image']['data'] );
		$posts  = get_posts(
			array(
				'fields'         => 'ids',
				'post_type'      => 'attachment',
				'post_mime_type' => $metadata['image']['mime'],
				'post_status'    => 'inherit',
				'posts_per_page' => 1,
				'meta_key'       => '_cover_hash',
				'meta_value'     => $hash,
			)
		);
		$exists = reset( $posts );

		if ( ! empty( $exists ) ) {
			update_post_meta( $attachment_id, '_thumbnail_id', $exists );
		} else {
			$ext = '.jpg';
			switch ( $metadata['image']['mime'] ) {
				case 'image/gif':
					$ext = '.gif';
					break;
				case 'image/png':
					$ext = '.png';
					break;
				case 'image/webp':
					$ext = '.webp';
					break;
			}
			$basename = str_replace( '.', '-', wp_basename( $file ) ) . '-image' . $ext;
			$uploaded = wp_upload_bits( $basename, '', $metadata['image']['data'] );
			if ( false === $uploaded['error'] ) {
				$image_attachment = array(
					'post_mime_type' => $metadata['image']['mime'],
					'post_type'      => 'attachment',
					'post_content'   => '',
				);
				/**
				 * Filters the parameters for the attachment thumbnail creation.
				 *
				 * @since 3.9.0
				 *
				 * @param array $image_attachment An array of parameters to create the thumbnail.
				 * @param array $metadata         Current attachment metadata.
				 * @param array $uploaded         {
				 *     Information about the newly-uploaded file.
				 *
				 *     @type string $file  Filename of the newly-uploaded file.
				 *     @type string $url   URL of the uploaded file.
				 *     @type string $type  File type.
				 * }
				 */
				$image_attachment = apply_filters( 'attachment_thumbnail_args', $image_attachment, $metadata, $uploaded );

				$sub_attachment_id = wp_insert_attachment( $image_attachment, $uploaded['file'] );
				add_post_meta( $sub_attachment_id, '_cover_hash', $hash );
				$attach_data = wp_generate_attachment_metadata( $sub_attachment_id, $uploaded['file'] );
				wp_update_attachment_metadata( $sub_attachment_id, $attach_data );
				update_post_meta( $attachment_id, '_thumbnail_id', $sub_attachment_id );
			}
		}
	} elseif ( 'application/pdf' === $mime_type ) {
		// Try to create image thumbnails for PDFs.

		$fallback_sizes = array(
			'thumbnail',
			'medium',
			'large',
		);

		/**
		 * Filters the image sizes generated for non-image mime types.
		 *
		 * @since 4.7.0
		 *
		 * @param string[] $fallback_sizes An array of image size names.
		 * @param array    $metadata       Current attachment metadata.
		 */
		$fallback_sizes = apply_filters( 'fallback_intermediate_image_sizes', $fallback_sizes, $metadata );

		$registered_sizes = wp_get_registered_image_subsizes();
		$merged_sizes     = array_intersect_key( $registered_sizes, array_flip( $fallback_sizes ) );

		// Force thumbnails to be soft crops.
		if ( isset( $merged_sizes['thumbnail'] ) && is_array( $merged_sizes['thumbnail'] ) ) {
			$merged_sizes['thumbnail']['crop'] = false;
		}

		// Only load PDFs in an image editor if we're processing sizes.
		if ( ! empty( $merged_sizes ) ) {
			$editor = wp_get_image_editor( $file );

			if ( ! is_wp_error( $editor ) ) { // No support for this type of file.
				/*
				 * PDFs may have the same file filename as JPEGs.
				 * Ensure the PDF preview image does not overwrite any JPEG images that already exist.
				 */
				$dirname      = dirname( $file ) . '/';
				$ext          = '.' . pathinfo( $file, PATHINFO_EXTENSION );
				$preview_file = $dirname . wp_unique_filename( $dirname, wp_basename( $file, $ext ) . '-pdf.jpg' );

				$uploaded = $editor->save( $preview_file, 'image/jpeg' );
				unset( $editor );

				// Resize based on the full size image, rather than the source.
				if ( ! is_wp_error( $uploaded ) ) {
					$image_file = $uploaded['path'];
					unset( $uploaded['path'] );

					$metadata['sizes'] = array(
						'full' => $uploaded,
					);

					// Save the meta data before any image post-processing errors could happen.
					wp_update_attachment_metadata( $attachment_id, $metadata );

					// Create sub-sizes saving the image meta after each.
					$metadata = _wp_make_subsizes( $merged_sizes, $image_file, $metadata, $attachment_id );
				}
			}
		}
	}

	// Remove the blob of binary data from the array.
	unset( $metadata['image']['data'] );

	// Capture file size for cases where it has not been captured yet, such as PDFs.
	if ( ! isset( $metadata['filesize'] ) && file_exists( $file ) ) {
		$metadata['filesize'] = wp_filesize( $file );
	}

	/**
	 * Filters the generated attachment meta data.
	 *
	 * @since 2.1.0
	 * @since 5.3.0 The `$context` parameter was added.
	 *
	 * @param array  $metadata      An array of attachment meta data.
	 * @param int    $attachment_id Current attachment ID.
	 * @param string $context       Additional context. Can be 'create' when metadata was initially created for new attachment
	 *                              or 'update' when the metadata was updated.
	 */
	return apply_filters( 'wp_generate_attachment_metadata', $metadata, $attachment_id, 'create' );
}

/**
 * Converts a fraction string to a decimal.
 *
 * @since 2.5.0
 *
 * @param string $str Fraction string.
 * @return int|float Returns calculated fraction or integer 0 on invalid input.
 */
function wp_exif_frac2dec( $str ) {
	if ( ! is_scalar( $str ) || is_bool( $str ) ) {
		return 0;
	}

	if ( ! is_string( $str ) ) {
		return $str; // This can only be an integer or float, so this is fine.
	}

	// Fractions passed as a string must contain a single `/`.
	if ( substr_count( $str, '/' ) !== 1 ) {
		if ( is_numeric( $str ) ) {
			return (float) $str;
		}

		return 0;
	}

	list( $numerator, $denominator ) = explode( '/', $str );

	// Both the numerator and the denominator must be numbers.
	if ( ! is_numeric( $numerator ) || ! is_numeric( $denominator ) ) {
		return 0;
	}

	// The denominator must not be zero.
	if ( 0 == $denominator ) { // phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual -- Deliberate loose comparison.
		return 0;
	}

	return $numerator / $denominator;
}

/**
 * Converts the exif date format to a unix timestamp.
 *
 * @since 2.5.0
 *
 * @param string $str A date string expected to be in Exif format (Y:m:d H:i:s).
 * @return int|false The unix timestamp, or false on failure.
 */
function wp_exif_date2ts( $str ) {
	list( $date, $time ) = explode( ' ', trim( $str ) );
	list( $y, $m, $d )   = explode( ':', $date );

	return strtotime( "{$y}-{$m}-{$d} {$time}" );
}

/**
 * Gets extended image metadata, exif or iptc as available.
 *
 * Retrieves the EXIF metadata aperture, credit, camera, caption, copyright, iso
 * created_timestamp, focal_length, shutter_speed, and title.
 *
 * The IPTC metadata that is retrieved is APP13, credit, byline, created date
 * and time, caption, copyright, and title. Also includes FNumber, Model,
 * DateTimeDigitized, FocalLength, ISOSpeedRatings, and ExposureTime.
 *
 * @todo Try other exif libraries if available.
 * @since 2.5.0
 *
 * @param string $file
 * @return array|false Image metadata array on success, false on failure.
 */
function wp_read_image_metadata( $file ) {
	if ( ! file_exists( $file ) ) {
		return false;
	}

	$image_size = wp_getimagesize( $file );

	if ( false === $image_size ) {
		return false;
	}

	list( , , $image_type ) = $image_size;

	/*
	 * EXIF contains a bunch of data we'll probably never need formatted in ways
	 * that are difficult to use. We'll normalize it and just extract the fields
	 * that are likely to be useful. Fractions and numbers are converted to
	 * floats, dates to unix timestamps, and everything else to strings.
	 */
	$meta = array(
		'aperture'          => 0,
		'credit'            => '',
		'camera'            => '',
		'caption'           => '',
		'created_timestamp' => 0,
		'copyright'         => '',
		'focal_length'      => 0,
		'iso'               => 0,
		'shutter_speed'     => 0,
		'title'             => '',
		'orientation'       => 0,
		'keywords'          => array(),
	);

	$iptc = array();
	$info = array();
	/*
	 * Read IPTC first, since it might contain data not available in exif such
	 * as caption, description etc.
	 */
	if ( is_callable( 'iptcparse' ) ) {
		wp_getimagesize( $file, $info );

		if ( ! empty( $info['APP13'] ) ) {
			// Don't silence errors when in debug mode, unless running unit tests.
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG
				&& ! defined( 'WP_RUN_CORE_TESTS' )
			) {
				$iptc = iptcparse( $info['APP13'] );
			} else {
				// Silencing notice and warning is intentional. See https://core.trac.wordpress.org/ticket/42480
				$iptc = @iptcparse( $info['APP13'] );
			}

			if ( ! is_array( $iptc ) ) {
				$iptc = array();
			}

			// Headline, "A brief synopsis of the caption".
			if ( ! empty( $iptc['2#105'][0] ) ) {
				$meta['title'] = trim( $iptc['2#105'][0] );
				/*
				* Title, "Many use the Title field to store the filename of the image,
				* though the field may be used in many ways".
				*/
			} elseif ( ! empty( $iptc['2#005'][0] ) ) {
				$meta['title'] = trim( $iptc['2#005'][0] );
			}

			if ( ! empty( $iptc['2#120'][0] ) ) { // Description / legacy caption.
				$caption = trim( $iptc['2#120'][0] );

				mbstring_binary_safe_encoding();
				$caption_length = strlen( $caption );
				reset_mbstring_encoding();

				if ( empty( $meta['title'] ) && $caption_length < 80 ) {
					// Assume the title is stored in 2:120 if it's short.
					$meta['title'] = $caption;
				}

				$meta['caption'] = $caption;
			}

			if ( ! empty( $iptc['2#110'][0] ) ) { // Credit.
				$meta['credit'] = trim( $iptc['2#110'][0] );
			} elseif ( ! empty( $iptc['2#080'][0] ) ) { // Creator / legacy byline.
				$meta['credit'] = trim( $iptc['2#080'][0] );
			}

			if ( ! empty( $iptc['2#055'][0] ) && ! empty( $iptc['2#060'][0] ) ) { // Created date and time.
				$meta['created_timestamp'] = strtotime( $iptc['2#055'][0] . ' ' . $iptc['2#060'][0] );
			}

			if ( ! empty( $iptc['2#116'][0] ) ) { // Copyright.
				$meta['copyright'] = trim( $iptc['2#116'][0] );
			}

			if ( ! empty( $iptc['2#025'][0] ) ) { // Keywords array.
				$meta['keywords'] = array_values( $iptc['2#025'] );
			}
		}
	}

	$exif = array();

	/**
	 * Filters the image types to check for exif data.
	 *
	 * @since 2.5.0
	 *
	 * @param int[] $image_types Array of image types to check for exif data. Each value
	 *                           is usually one of the `IMAGETYPE_*` constants.
	 */
	$exif_image_types = apply_filters( 'wp_read_image_metadata_types', array( IMAGETYPE_JPEG, IMAGETYPE_TIFF_II, IMAGETYPE_TIFF_MM ) );

	if ( is_callable( 'exif_read_data' ) && in_array( $image_type, $exif_image_types, true ) ) {
		// Don't silence errors when in debug mode, unless running unit tests.
		if ( defined( 'WP_DEBUG' ) && WP_DEBUG
			&& ! defined( 'WP_RUN_CORE_TESTS' )
		) {
			$exif = exif_read_data( $file );
		} else {
			// Silencing notice and warning is intentional. See https://core.trac.wordpress.org/ticket/42480
			$exif = @exif_read_data( $file );
		}

		if ( ! is_array( $exif ) ) {
			$exif = array();
		}

		$exif_description = '';
		$exif_usercomment = '';
		if ( ! empty( $exif['ImageDescription'] ) ) {
			$exif_description = trim( $exif['ImageDescription'] );
		}

		if ( ! empty( $exif['COMPUTED']['UserComment'] ) ) {
			$exif_usercomment = trim( $exif['COMPUTED']['UserComment'] );
		}

		if ( $exif_description ) {
			mbstring_binary_safe_encoding();
			$description_length = strlen( $exif_description );
			reset_mbstring_encoding();
			if ( empty( $meta['title'] ) && $description_length < 80 ) {
				// Assume the title is stored in ImageDescription.
				$meta['title'] = $exif_description;
			}

			// If both user comments and description are present.
			if ( empty( $meta['caption'] ) && $exif_usercomment ) {
				if ( ! empty( $meta['title'] ) && $exif_description === $meta['title'] ) {
					$caption = $exif_usercomment;
				} else {
					if ( $exif_description === $exif_usercomment ) {
						$caption = $exif_description;
					} else {
						$caption = trim( $exif_description . ' ' . $exif_usercomment );
					}
				}
				$meta['caption'] = $caption;
			}

			if ( empty( $meta['caption'] ) && $exif_usercomment ) {
				$meta['caption'] = $exif_usercomment;
			}

			if ( empty( $meta['caption'] ) ) {
				$meta['caption'] = $exif_description;
			}
		} elseif ( empty( $meta['caption'] ) && $exif_usercomment ) {
			$meta['caption']    = $exif_usercomment;
			$description_length = strlen( $exif_usercomment );
			if ( empty( $meta['title'] ) && $description_length < 80 ) {
				$meta['title'] = trim( $exif_usercomment );
			}
		} elseif ( empty( $meta['caption'] ) && ! empty( $exif['Comments'] ) ) {
			$meta['caption'] = trim( $exif['Comments'] );
		}

		if ( empty( $meta['credit'] ) ) {
			if ( ! empty( $exif['Artist'] ) ) {
				$meta['credit'] = trim( $exif['Artist'] );
			} elseif ( ! empty( $exif['Author'] ) ) {
				$meta['credit'] = trim( $exif['Author'] );
			}
		}

		if ( empty( $meta['copyright'] ) && ! empty( $exif['Copyright'] ) ) {
			$meta['copyright'] = trim( $exif['Copyright'] );
		}
		if ( ! empty( $exif['FNumber'] ) && is_scalar( $exif['FNumber'] ) ) {
			$meta['aperture'] = round( wp_exif_frac2dec( $exif['FNumber'] ), 2 );
		}
		if ( ! empty( $exif['Model'] ) ) {
			$meta['camera'] = trim( $exif['Model'] );
		}
		if ( empty( $meta['created_timestamp'] ) && ! empty( $exif['DateTimeDigitized'] ) ) {
			$meta['created_timestamp'] = wp_exif_date2ts( $exif['DateTimeDigitized'] );
		}
		if ( ! empty( $exif['FocalLength'] ) ) {
			$meta['focal_length'] = (string) $exif['FocalLength'];
			if ( is_scalar( $exif['FocalLength'] ) ) {
				$meta['focal_length'] = (string) wp_exif_frac2dec( $exif['FocalLength'] );
			}
		}
		if ( ! empty( $exif['ISOSpeedRatings'] ) ) {
			$meta['iso'] = is_array( $exif['ISOSpeedRatings'] ) ? reset( $exif['ISOSpeedRatings'] ) : $exif['ISOSpeedRatings'];
			$meta['iso'] = trim( $meta['iso'] );
		}
		if ( ! empty( $exif['ExposureTime'] ) ) {
			$meta['shutter_speed'] = (string) $exif['ExposureTime'];
			if ( is_scalar( $exif['ExposureTime'] ) ) {
				$meta['shutter_speed'] = (string) wp_exif_frac2dec( $exif['ExposureTime'] );
			}
		}
		if ( ! empty( $exif['Orientation'] ) ) {
			$meta['orientation'] = $exif['Orientation'];
		}
	}

	foreach ( array( 'title', 'caption', 'credit', 'copyright', 'camera', 'iso' ) as $key ) {
		if ( $meta[ $key ] && ! wp_is_valid_utf8( $meta[ $key ] ) ) {
			$meta[ $key ] = utf8_encode( $meta[ $key ] );
		}
	}

	foreach ( $meta['keywords'] as $key => $keyword ) {
		if ( ! wp_is_valid_utf8( $keyword ) ) {
			$meta['keywords'][ $key ] = utf8_encode( $keyword );
		}
	}

	$meta = wp_kses_post_deep( $meta );

	/**
	 * Filters the array of meta data read from an image's exif data.
	 *
	 * @since 2.5.0
	 * @since 4.4.0 The `$iptc` parameter was added.
	 * @since 5.0.0 The `$exif` parameter was added.
	 *
	 * @param array  $meta       Image meta data.
	 * @param string $file       Path to image file.
	 * @param int    $image_type Type of image, one of the `IMAGETYPE_XXX` constants.
	 * @param array  $iptc       IPTC data.
	 * @param array  $exif       EXIF data.
	 */
	return apply_filters( 'wp_read_image_metadata', $meta, $file, $image_type, $iptc, $exif );
}

/**
 * Validates that file is an image.
 *
 * @since 2.5.0
 *
 * @param string $path File path to test if valid image.
 * @return bool True if valid image, false if not valid image.
 */
function file_is_valid_image( $path ) {
	$size = wp_getimagesize( $path );
	return ! empty( $size );
}

/**
 * Validates that file is suitable for displaying within a web page.
 *
 * @since 2.5.0
 *
 * @param string $path File path to test.
 * @return bool True if suitable, false if not suitable.
 */
function file_is_displayable_image( $path ) {
	$displayable_image_types = array( IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG, IMAGETYPE_BMP, IMAGETYPE_ICO, IMAGETYPE_WEBP, IMAGETYPE_AVIF );

	$info = wp_getimagesize( $path );
	if ( empty( $info ) ) {
		$result = false;
	} elseif ( ! in_array( $info[2], $displayable_image_types, true ) ) {
		$result = false;
	} else {
		$result = true;
	}

	/**
	 * Filters whether the current image is displayable in the browser.
	 *
	 * @since 2.5.0
	 *
	 * @param bool   $result Whether the image can be displayed. Default true.
	 * @param string $path   Path to the image.
	 */
	return apply_filters( 'file_is_displayable_image', $result, $path );
}

/**
 * Loads an image resource for editing.
 *
 * @since 2.9.0
 *
 * @param int          $attachment_id Attachment ID.
 * @param string       $mime_type     Image mime type.
 * @param string|int[] $size          Optional. Image size. Accepts any registered image size name, or an array
 *                                    of width and height values in pixels (in that order). Default 'full'.
 * @return resource|GdImage|false The resulting image resource or GdImage instance on success,
 *                                false on failure.
 */
function load_image_to_edit( $attachment_id, $mime_type, $size = 'full' ) {
	$filepath = _load_image_to_edit_path( $attachment_id, $size );
	if ( empty( $filepath ) ) {
		return false;
	}

	switch ( $mime_type ) {
		case 'image/jpeg':
			$image = imagecreatefromjpeg( $filepath );
			break;
		case 'image/png':
			$image = imagecreatefrompng( $filepath );
			break;
		case 'image/gif':
			$image = imagecreatefromgif( $filepath );
			break;
		case 'image/webp':
			$image = false;
			if ( function_exists( 'imagecreatefromwebp' ) ) {
				$image = imagecreatefromwebp( $filepath );
			}
			break;
		default:
			$image = false;
			break;
	}

	if ( is_gd_image( $image ) ) {
		/**
		 * Filters the current image being loaded for editing.
		 *
		 * @since 2.9.0
		 *
		 * @param resource|GdImage $image         Current image.
		 * @param int              $attachment_id Attachment ID.
		 * @param string|int[]     $size          Requested image size. Can be any registered image size name, or
		 *                                        an array of width and height values in pixels (in that order).
		 */
		$image = apply_filters( 'load_image_to_edit', $image, $attachment_id, $size );

		if ( function_exists( 'imagealphablending' ) && function_exists( 'imagesavealpha' ) ) {
			imagealphablending( $image, false );
			imagesavealpha( $image, true );
		}
	}

	return $image;
}

/**
 * Retrieves the path or URL of an attachment's attached file.
 *
 * If the attached file is not present on the local filesystem (usually due to replication plugins),
 * then the URL of the file is returned if `allow_url_fopen` is supported.
 *
 * @since 3.4.0
 * @access private
 *
 * @param int          $attachment_id Attachment ID.
 * @param string|int[] $size          Optional. Image size. Accepts any registered image size name, or an array
 *                                    of width and height values in pixels (in that order). Default 'full'.
 * @return string|false File path or URL on success, false on failure.
 */
function _load_image_to_edit_path( $attachment_id, $size = 'full' ) {
	$filepath = get_attached_file( $attachment_id );

	if ( $filepath && file_exists( $filepath ) ) {
		if ( 'full' !== $size ) {
			$data = image_get_intermediate_size( $attachment_id, $size );

			if ( $data ) {
				$filepath = path_join( dirname( $filepath ), $data['file'] );

				/**
				 * Filters the path to an attachment's file when editing the image.
				 *
				 * The filter is evaluated for all image sizes except 'full'.
				 *
				 * @since 3.1.0
				 *
				 * @param string       $path          Path to the current image.
				 * @param int          $attachment_id Attachment ID.
				 * @param string|int[] $size          Requested image size. Can be any registered image size name, or
				 *                                    an array of width and height values in pixels (in that order).
				 */
				$filepath = apply_filters( 'load_image_to_edit_filesystempath', $filepath, $attachment_id, $size );
			}
		}
	} elseif ( function_exists( 'fopen' ) && ini_get( 'allow_url_fopen' ) ) {
		/**
		 * Filters the path to an attachment's URL when editing the image.
		 *
		 * The filter is only evaluated if the file isn't stored locally and `allow_url_fopen` is enabled on the server.
		 *
		 * @since 3.1.0
		 *
		 * @param string|false $image_url     Current image URL.
		 * @param int          $attachment_id Attachment ID.
		 * @param string|int[] $size          Requested image size. Can be any registered image size name, or
		 *                                    an array of width and height values in pixels (in that order).
		 */
		$filepath = apply_filters( 'load_image_to_edit_attachmenturl', wp_get_attachment_url( $attachment_id ), $attachment_id, $size );
	}

	/**
	 * Filters the returned path or URL of the current image.
	 *
	 * @since 2.9.0
	 *
	 * @param string|false $filepath      File path or URL to current image, or false.
	 * @param int          $attachment_id Attachment ID.
	 * @param string|int[] $size          Requested image size. Can be any registered image size name, or
	 *                                    an array of width and height values in pixels (in that order).
	 */
	return apply_filters( 'load_image_to_edit_path', $filepath, $attachment_id, $size );
}

/**
 * Copies an existing image file.
 *
 * @since 3.4.0
 * @access private
 *
 * @param int $attachment_id Attachment ID.
 * @return string|false New file path on success, false on failure.
 */
function _copy_image_file( $attachment_id ) {
	$dst_file = get_attached_file( $attachment_id );
	$src_file = $dst_file;

	if ( ! file_exists( $src_file ) ) {
		$src_file = _load_image_to_edit_path( $attachment_id );
	}

	if ( $src_file ) {
		$dst_file = str_replace( wp_basename( $dst_file ), 'copy-' . wp_basename( $dst_file ), $dst_file );
		$dst_file = dirname( $dst_file ) . '/' . wp_unique_filename( dirname( $dst_file ), wp_basename( $dst_file ) );

		/*
		 * The directory containing the original file may no longer
		 * exist when using a replication plugin.
		 */
		wp_mkdir_p( dirname( $dst_file ) );

		if ( ! copy( $src_file, $dst_file ) ) {
			$dst_file = false;
		}
	} else {
		$dst_file = false;
	}

	return $dst_file;
}
admin.php000064400000007054151212616060006353 0ustar00<?php
/**
 * Core Administration API
 *
 * @package WordPress
 * @subpackage Administration
 * @since 2.3.0
 */

if ( ! defined( 'WP_ADMIN' ) ) {
	/*
	 * This file is being included from a file other than wp-admin/admin.php, so
	 * some setup was skipped. Make sure the admin message catalog is loaded since
	 * load_default_textdomain() will not have done so in this context.
	 */
	$admin_locale = get_locale();
	load_textdomain( 'default', WP_LANG_DIR . '/admin-' . $admin_locale . '.mo', $admin_locale );
	unset( $admin_locale );
}

/** WordPress Administration Hooks */
require_once ABSPATH . 'wp-admin/includes/admin-filters.php';

/** WordPress Bookmark Administration API */
require_once ABSPATH . 'wp-admin/includes/bookmark.php';

/** WordPress Comment Administration API */
require_once ABSPATH . 'wp-admin/includes/comment.php';

/** WordPress Administration File API */
require_once ABSPATH . 'wp-admin/includes/file.php';

/** WordPress Image Administration API */
require_once ABSPATH . 'wp-admin/includes/image.php';

/** WordPress Media Administration API */
require_once ABSPATH . 'wp-admin/includes/media.php';

/** WordPress Import Administration API */
require_once ABSPATH . 'wp-admin/includes/import.php';

/** WordPress Misc Administration API */
require_once ABSPATH . 'wp-admin/includes/misc.php';

/** WordPress Misc Administration API */
require_once ABSPATH . 'wp-admin/includes/class-wp-privacy-policy-content.php';

/** WordPress Options Administration API */
require_once ABSPATH . 'wp-admin/includes/options.php';

/** WordPress Plugin Administration API */
require_once ABSPATH . 'wp-admin/includes/plugin.php';

/** WordPress Post Administration API */
require_once ABSPATH . 'wp-admin/includes/post.php';

/** WordPress Administration Screen API */
require_once ABSPATH . 'wp-admin/includes/class-wp-screen.php';
require_once ABSPATH . 'wp-admin/includes/screen.php';

/** WordPress Taxonomy Administration API */
require_once ABSPATH . 'wp-admin/includes/taxonomy.php';

/** WordPress Template Administration API */
require_once ABSPATH . 'wp-admin/includes/template.php';

/** WordPress List Table Administration API and base class */
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table-compat.php';
require_once ABSPATH . 'wp-admin/includes/list-table.php';

/** WordPress Theme Administration API */
require_once ABSPATH . 'wp-admin/includes/theme.php';

/** WordPress Privacy Functions */
require_once ABSPATH . 'wp-admin/includes/privacy-tools.php';

/** WordPress Privacy List Table classes. */
// Previously in wp-admin/includes/user.php. Need to be loaded for backward compatibility.
require_once ABSPATH . 'wp-admin/includes/class-wp-privacy-requests-table.php';
require_once ABSPATH . 'wp-admin/includes/class-wp-privacy-data-export-requests-list-table.php';
require_once ABSPATH . 'wp-admin/includes/class-wp-privacy-data-removal-requests-list-table.php';

/** WordPress User Administration API */
require_once ABSPATH . 'wp-admin/includes/user.php';

/** WordPress Site Icon API */
require_once ABSPATH . 'wp-admin/includes/class-wp-site-icon.php';

/** WordPress Update Administration API */
require_once ABSPATH . 'wp-admin/includes/update.php';

/** WordPress Deprecated Administration API */
require_once ABSPATH . 'wp-admin/includes/deprecated.php';

/** WordPress Multisite support API */
if ( is_multisite() ) {
	require_once ABSPATH . 'wp-admin/includes/ms-admin-filters.php';
	require_once ABSPATH . 'wp-admin/includes/ms.php';
	require_once ABSPATH . 'wp-admin/includes/ms-deprecated.php';
}
class-wp-privacy-data-removal-requests-list-table.php000064400000013123151212616060016742 0ustar00<?php
/**
 * List Table API: WP_Privacy_Data_Removal_Requests_List_Table class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 4.9.6
 */

if ( ! class_exists( 'WP_Privacy_Requests_Table' ) ) {
	require_once ABSPATH . 'wp-admin/includes/class-wp-privacy-requests-table.php';
}

/**
 * WP_Privacy_Data_Removal_Requests_List_Table class.
 *
 * @since 4.9.6
 */
class WP_Privacy_Data_Removal_Requests_List_Table extends WP_Privacy_Requests_Table {
	/**
	 * Action name for the requests this table will work with.
	 *
	 * @since 4.9.6
	 *
	 * @var string $request_type Name of action.
	 */
	protected $request_type = 'remove_personal_data';

	/**
	 * Post type for the requests.
	 *
	 * @since 4.9.6
	 *
	 * @var string $post_type The post type.
	 */
	protected $post_type = 'user_request';

	/**
	 * Outputs the Actions column.
	 *
	 * @since 4.9.6
	 *
	 * @param WP_User_Request $item Item being shown.
	 * @return string Email column markup.
	 */
	public function column_email( $item ) {
		$row_actions = array();

		// Allow the administrator to "force remove" the personal data even if confirmation has not yet been received.
		$status      = $item->status;
		$request_id  = $item->ID;
		$row_actions = array();
		if ( 'request-confirmed' !== $status ) {
			/** This filter is documented in wp-admin/includes/ajax-actions.php */
			$erasers       = apply_filters( 'wp_privacy_personal_data_erasers', array() );
			$erasers_count = count( $erasers );
			$nonce         = wp_create_nonce( 'wp-privacy-erase-personal-data-' . $request_id );

			$remove_data_markup = '<span class="remove-personal-data force-remove-personal-data" ' .
				'data-erasers-count="' . esc_attr( $erasers_count ) . '" ' .
				'data-request-id="' . esc_attr( $request_id ) . '" ' .
				'data-nonce="' . esc_attr( $nonce ) .
				'">';

			$remove_data_markup .= '<span class="remove-personal-data-idle"><button type="button" class="button-link remove-personal-data-handle">' . __( 'Force erase personal data' ) . '</button></span>' .
				'<span class="remove-personal-data-processing hidden">' . __( 'Erasing data...' ) . ' <span class="erasure-progress"></span></span>' .
				'<span class="remove-personal-data-success hidden">' . __( 'Erasure completed.' ) . '</span>' .
				'<span class="remove-personal-data-failed hidden">' . __( 'Force erasure has failed.' ) . ' <button type="button" class="button-link remove-personal-data-handle">' . __( 'Retry' ) . '</button></span>';

			$remove_data_markup .= '</span>';

			$row_actions['remove-data'] = $remove_data_markup;
		}

		if ( 'request-completed' !== $status ) {
			$complete_request_markup  = '<span>';
			$complete_request_markup .= sprintf(
				'<a href="%s" class="complete-request" aria-label="%s">%s</a>',
				esc_url(
					wp_nonce_url(
						add_query_arg(
							array(
								'action'     => 'complete',
								'request_id' => array( $request_id ),
							),
							admin_url( 'erase-personal-data.php' )
						),
						'bulk-privacy_requests'
					)
				),
				esc_attr(
					sprintf(
						/* translators: %s: Request email. */
						__( 'Mark export request for &#8220;%s&#8221; as completed.' ),
						$item->email
					)
				),
				__( 'Complete request' )
			);
			$complete_request_markup .= '</span>';
		}

		if ( ! empty( $complete_request_markup ) ) {
			$row_actions['complete-request'] = $complete_request_markup;
		}

		return sprintf( '<a href="%1$s">%2$s</a> %3$s', esc_url( 'mailto:' . $item->email ), $item->email, $this->row_actions( $row_actions ) );
	}

	/**
	 * Outputs the Next steps column.
	 *
	 * @since 4.9.6
	 *
	 * @param WP_User_Request $item Item being shown.
	 */
	public function column_next_steps( $item ) {
		$status = $item->status;

		switch ( $status ) {
			case 'request-pending':
				esc_html_e( 'Waiting for confirmation' );
				break;
			case 'request-confirmed':
				/** This filter is documented in wp-admin/includes/ajax-actions.php */
				$erasers       = apply_filters( 'wp_privacy_personal_data_erasers', array() );
				$erasers_count = count( $erasers );
				$request_id    = $item->ID;
				$nonce         = wp_create_nonce( 'wp-privacy-erase-personal-data-' . $request_id );

				echo '<div class="remove-personal-data" ' .
					'data-force-erase="1" ' .
					'data-erasers-count="' . esc_attr( $erasers_count ) . '" ' .
					'data-request-id="' . esc_attr( $request_id ) . '" ' .
					'data-nonce="' . esc_attr( $nonce ) .
					'">';

				?>
				<span class="remove-personal-data-idle"><button type="button" class="button-link remove-personal-data-handle"><?php _e( 'Erase personal data' ); ?></button></span>
				<span class="remove-personal-data-processing hidden"><?php _e( 'Erasing data...' ); ?> <span class="erasure-progress"></span></span>
				<span class="remove-personal-data-success success-message hidden" ><?php _e( 'Erasure completed.' ); ?></span>
				<span class="remove-personal-data-failed hidden"><?php _e( 'Data erasure has failed.' ); ?> <button type="button" class="button-link remove-personal-data-handle"><?php _e( 'Retry' ); ?></button></span>
				<?php

				echo '</div>';

				break;
			case 'request-failed':
				echo '<button type="submit" class="button-link" name="privacy_action_email_retry[' . $item->ID . ']" id="privacy_action_email_retry[' . $item->ID . ']">' . __( 'Retry' ) . '</button>';
				break;
			case 'request-completed':
				echo '<a href="' . esc_url(
					wp_nonce_url(
						add_query_arg(
							array(
								'action'     => 'delete',
								'request_id' => array( $item->ID ),
							),
							admin_url( 'erase-personal-data.php' )
						),
						'bulk-privacy_requests'
					)
				) . '">' . esc_html__( 'Remove request' ) . '</a>';
				break;
		}
	}
}
class-wp-list-table.php000064400000147414151212616060011057 0ustar00<?php
/**
 * Administration API: WP_List_Table class
 *
 * @package WordPress
 * @subpackage List_Table
 * @since 3.1.0
 */

/**
 * Base class for displaying a list of items in an ajaxified HTML table.
 *
 * @since 3.1.0
 */
#[AllowDynamicProperties]
class WP_List_Table {

	/**
	 * The current list of items.
	 *
	 * @since 3.1.0
	 * @var array
	 */
	public $items;

	/**
	 * Various information about the current table.
	 *
	 * @since 3.1.0
	 * @var array
	 */
	protected $_args;

	/**
	 * Various information needed for displaying the pagination.
	 *
	 * @since 3.1.0
	 * @var array
	 */
	protected $_pagination_args = array();

	/**
	 * The current screen.
	 *
	 * @since 3.1.0
	 * @var WP_Screen
	 */
	protected $screen;

	/**
	 * Cached bulk actions.
	 *
	 * @since 3.1.0
	 * @var array
	 */
	private $_actions;

	/**
	 * Cached pagination output.
	 *
	 * @since 3.1.0
	 * @var string
	 */
	private $_pagination;

	/**
	 * The view switcher modes.
	 *
	 * @since 4.1.0
	 * @var array
	 */
	protected $modes = array();

	/**
	 * Stores the value returned by ::get_column_info().
	 *
	 * @since 4.1.0
	 * @var array|null
	 */
	protected $_column_headers;

	/**
	 * {@internal Missing Summary}
	 *
	 * @var array
	 */
	protected $compat_fields = array( '_args', '_pagination_args', 'screen', '_actions', '_pagination' );

	/**
	 * {@internal Missing Summary}
	 *
	 * @var array
	 */
	protected $compat_methods = array(
		'set_pagination_args',
		'get_views',
		'get_bulk_actions',
		'bulk_actions',
		'row_actions',
		'months_dropdown',
		'view_switcher',
		'comments_bubble',
		'get_items_per_page',
		'pagination',
		'get_sortable_columns',
		'get_column_info',
		'get_table_classes',
		'display_tablenav',
		'extra_tablenav',
		'single_row_columns',
	);

	/**
	 * Constructor.
	 *
	 * The child class should call this constructor from its own constructor to override
	 * the default $args.
	 *
	 * @since 3.1.0
	 *
	 * @param array|string $args {
	 *     Array or string of arguments.
	 *
	 *     @type string $plural   Plural value used for labels and the objects being listed.
	 *                            This affects things such as CSS class-names and nonces used
	 *                            in the list table, e.g. 'posts'. Default empty.
	 *     @type string $singular Singular label for an object being listed, e.g. 'post'.
	 *                            Default empty
	 *     @type bool   $ajax     Whether the list table supports Ajax. This includes loading
	 *                            and sorting data, for example. If true, the class will call
	 *                            the _js_vars() method in the footer to provide variables
	 *                            to any scripts handling Ajax events. Default false.
	 *     @type string $screen   String containing the hook name used to determine the current
	 *                            screen. If left null, the current screen will be automatically set.
	 *                            Default null.
	 * }
	 */
	public function __construct( $args = array() ) {
		$args = wp_parse_args(
			$args,
			array(
				'plural'   => '',
				'singular' => '',
				'ajax'     => false,
				'screen'   => null,
			)
		);

		$this->screen = convert_to_screen( $args['screen'] );

		add_filter( "manage_{$this->screen->id}_columns", array( $this, 'get_columns' ), 0 );

		if ( ! $args['plural'] ) {
			$args['plural'] = $this->screen->base;
		}

		$args['plural']   = sanitize_key( $args['plural'] );
		$args['singular'] = sanitize_key( $args['singular'] );

		$this->_args = $args;

		if ( $args['ajax'] ) {
			// wp_enqueue_script( 'list-table' );
			add_action( 'admin_footer', array( $this, '_js_vars' ) );
		}

		if ( empty( $this->modes ) ) {
			$this->modes = array(
				'list'    => __( 'Compact view' ),
				'excerpt' => __( 'Extended view' ),
			);
		}
	}

	/**
	 * Makes private properties readable for backward compatibility.
	 *
	 * @since 4.0.0
	 * @since 6.4.0 Getting a dynamic property is deprecated.
	 *
	 * @param string $name Property to get.
	 * @return mixed Property.
	 */
	public function __get( $name ) {
		if ( in_array( $name, $this->compat_fields, true ) ) {
			return $this->$name;
		}

		wp_trigger_error(
			__METHOD__,
			"The property `{$name}` is not declared. Getting a dynamic property is " .
			'deprecated since version 6.4.0! Instead, declare the property on the class.',
			E_USER_DEPRECATED
		);
		return null;
	}

	/**
	 * Makes private properties settable for backward compatibility.
	 *
	 * @since 4.0.0
	 * @since 6.4.0 Setting a dynamic property is deprecated.
	 *
	 * @param string $name  Property to check if set.
	 * @param mixed  $value Property value.
	 */
	public function __set( $name, $value ) {
		if ( in_array( $name, $this->compat_fields, true ) ) {
			$this->$name = $value;
			return;
		}

		wp_trigger_error(
			__METHOD__,
			"The property `{$name}` is not declared. Setting a dynamic property is " .
			'deprecated since version 6.4.0! Instead, declare the property on the class.',
			E_USER_DEPRECATED
		);
	}

	/**
	 * Makes private properties checkable for backward compatibility.
	 *
	 * @since 4.0.0
	 * @since 6.4.0 Checking a dynamic property is deprecated.
	 *
	 * @param string $name Property to check if set.
	 * @return bool Whether the property is a back-compat property and it is set.
	 */
	public function __isset( $name ) {
		if ( in_array( $name, $this->compat_fields, true ) ) {
			return isset( $this->$name );
		}

		wp_trigger_error(
			__METHOD__,
			"The property `{$name}` is not declared. Checking `isset()` on a dynamic property " .
			'is deprecated since version 6.4.0! Instead, declare the property on the class.',
			E_USER_DEPRECATED
		);
		return false;
	}

	/**
	 * Makes private properties un-settable for backward compatibility.
	 *
	 * @since 4.0.0
	 * @since 6.4.0 Unsetting a dynamic property is deprecated.
	 *
	 * @param string $name Property to unset.
	 */
	public function __unset( $name ) {
		if ( in_array( $name, $this->compat_fields, true ) ) {
			unset( $this->$name );
			return;
		}

		wp_trigger_error(
			__METHOD__,
			"A property `{$name}` is not declared. Unsetting a dynamic property is " .
			'deprecated since version 6.4.0! Instead, declare the property on the class.',
			E_USER_DEPRECATED
		);
	}

	/**
	 * Makes private/protected methods readable for backward compatibility.
	 *
	 * @since 4.0.0
	 *
	 * @param string $name      Method to call.
	 * @param array  $arguments Arguments to pass when calling.
	 * @return mixed|bool Return value of the callback, false otherwise.
	 */
	public function __call( $name, $arguments ) {
		if ( in_array( $name, $this->compat_methods, true ) ) {
			return $this->$name( ...$arguments );
		}
		return false;
	}

	/**
	 * Checks the current user's permissions
	 *
	 * @since 3.1.0
	 * @abstract
	 */
	public function ajax_user_can() {
		die( 'function WP_List_Table::ajax_user_can() must be overridden in a subclass.' );
	}

	/**
	 * Prepares the list of items for displaying.
	 *
	 * @uses WP_List_Table::set_pagination_args()
	 *
	 * @since 3.1.0
	 * @abstract
	 */
	public function prepare_items() {
		die( 'function WP_List_Table::prepare_items() must be overridden in a subclass.' );
	}

	/**
	 * Sets all the necessary pagination arguments.
	 *
	 * @since 3.1.0
	 *
	 * @param array|string $args Array or string of arguments with information about the pagination.
	 */
	protected function set_pagination_args( $args ) {
		$args = wp_parse_args(
			$args,
			array(
				'total_items' => 0,
				'total_pages' => 0,
				'per_page'    => 0,
			)
		);

		if ( ! $args['total_pages'] && $args['per_page'] > 0 ) {
			$args['total_pages'] = (int) ceil( $args['total_items'] / $args['per_page'] );
		}

		// Redirect if page number is invalid and headers are not already sent.
		if ( ! headers_sent() && ! wp_doing_ajax() && $args['total_pages'] > 0 && $this->get_pagenum() > $args['total_pages'] ) {
			wp_redirect( add_query_arg( 'paged', $args['total_pages'] ) );
			exit;
		}

		$this->_pagination_args = $args;
	}

	/**
	 * Access the pagination args.
	 *
	 * @since 3.1.0
	 *
	 * @param string $key Pagination argument to retrieve. Common values include 'total_items',
	 *                    'total_pages', 'per_page', or 'infinite_scroll'.
	 * @return int Number of items that correspond to the given pagination argument.
	 */
	public function get_pagination_arg( $key ) {
		if ( 'page' === $key ) {
			return $this->get_pagenum();
		}

		if ( isset( $this->_pagination_args[ $key ] ) ) {
			return $this->_pagination_args[ $key ];
		}

		return 0;
	}

	/**
	 * Determines whether the table has items to display or not
	 *
	 * @since 3.1.0
	 *
	 * @return bool
	 */
	public function has_items() {
		return ! empty( $this->items );
	}

	/**
	 * Message to be displayed when there are no items
	 *
	 * @since 3.1.0
	 */
	public function no_items() {
		_e( 'No items found.' );
	}

	/**
	 * Displays the search box.
	 *
	 * @since 3.1.0
	 *
	 * @param string $text     The 'submit' button label.
	 * @param string $input_id ID attribute value for the search input field.
	 */
	public function search_box( $text, $input_id ) {
		if ( empty( $_REQUEST['s'] ) && ! $this->has_items() ) {
			return;
		}

		$input_id = $input_id . '-search-input';

		if ( ! empty( $_REQUEST['orderby'] ) ) {
			if ( is_array( $_REQUEST['orderby'] ) ) {
				foreach ( $_REQUEST['orderby'] as $key => $value ) {
					echo '<input type="hidden" name="orderby[' . esc_attr( $key ) . ']" value="' . esc_attr( $value ) . '" />';
				}
			} else {
				echo '<input type="hidden" name="orderby" value="' . esc_attr( $_REQUEST['orderby'] ) . '" />';
			}
		}
		if ( ! empty( $_REQUEST['order'] ) ) {
			echo '<input type="hidden" name="order" value="' . esc_attr( $_REQUEST['order'] ) . '" />';
		}
		if ( ! empty( $_REQUEST['post_mime_type'] ) ) {
			echo '<input type="hidden" name="post_mime_type" value="' . esc_attr( $_REQUEST['post_mime_type'] ) . '" />';
		}
		if ( ! empty( $_REQUEST['detached'] ) ) {
			echo '<input type="hidden" name="detached" value="' . esc_attr( $_REQUEST['detached'] ) . '" />';
		}
		?>
<p class="search-box">
	<label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>"><?php echo $text; ?>:</label>
	<input type="search" id="<?php echo esc_attr( $input_id ); ?>" name="s" value="<?php _admin_search_query(); ?>" />
		<?php submit_button( $text, '', '', false, array( 'id' => 'search-submit' ) ); ?>
</p>
		<?php
	}

	/**
	 * Generates views links.
	 *
	 * @since 6.1.0
	 *
	 * @param array $link_data {
	 *     An array of link data.
	 *
	 *     @type string $url     The link URL.
	 *     @type string $label   The link label.
	 *     @type bool   $current Optional. Whether this is the currently selected view.
	 * }
	 * @return string[] An array of link markup. Keys match the `$link_data` input array.
	 */
	protected function get_views_links( $link_data = array() ) {
		if ( ! is_array( $link_data ) ) {
			_doing_it_wrong(
				__METHOD__,
				sprintf(
					/* translators: %s: The $link_data argument. */
					__( 'The %s argument must be an array.' ),
					'<code>$link_data</code>'
				),
				'6.1.0'
			);

			return array( '' );
		}

		$views_links = array();

		foreach ( $link_data as $view => $link ) {
			if ( empty( $link['url'] ) || ! is_string( $link['url'] ) || '' === trim( $link['url'] ) ) {
				_doing_it_wrong(
					__METHOD__,
					sprintf(
						/* translators: %1$s: The argument name. %2$s: The view name. */
						__( 'The %1$s argument must be a non-empty string for %2$s.' ),
						'<code>url</code>',
						'<code>' . esc_html( $view ) . '</code>'
					),
					'6.1.0'
				);

				continue;
			}

			if ( empty( $link['label'] ) || ! is_string( $link['label'] ) || '' === trim( $link['label'] ) ) {
				_doing_it_wrong(
					__METHOD__,
					sprintf(
						/* translators: %1$s: The argument name. %2$s: The view name. */
						__( 'The %1$s argument must be a non-empty string for %2$s.' ),
						'<code>label</code>',
						'<code>' . esc_html( $view ) . '</code>'
					),
					'6.1.0'
				);

				continue;
			}

			$views_links[ $view ] = sprintf(
				'<a href="%s"%s>%s</a>',
				esc_url( $link['url'] ),
				isset( $link['current'] ) && true === $link['current'] ? ' class="current" aria-current="page"' : '',
				$link['label']
			);
		}

		return $views_links;
	}

	/**
	 * Gets the list of views available on this table.
	 *
	 * The format is an associative array:
	 * - `'id' => 'link'`
	 *
	 * @since 3.1.0
	 *
	 * @return array
	 */
	protected function get_views() {
		return array();
	}

	/**
	 * Displays the list of views available on this table.
	 *
	 * @since 3.1.0
	 */
	public function views() {
		$views = $this->get_views();
		/**
		 * Filters the list of available list table views.
		 *
		 * The dynamic portion of the hook name, `$this->screen->id`, refers
		 * to the ID of the current screen.
		 *
		 * @since 3.1.0
		 *
		 * @param string[] $views An array of available list table views.
		 */
		$views = apply_filters( "views_{$this->screen->id}", $views );

		if ( empty( $views ) ) {
			return;
		}

		$this->screen->render_screen_reader_content( 'heading_views' );

		echo "<ul class='subsubsub'>\n";
		foreach ( $views as $class => $view ) {
			$views[ $class ] = "\t<li class='$class'>$view";
		}
		echo implode( " |</li>\n", $views ) . "</li>\n";
		echo '</ul>';
	}

	/**
	 * Retrieves the list of bulk actions available for this table.
	 *
	 * The format is an associative array where each element represents either a top level option value and label, or
	 * an array representing an optgroup and its options.
	 *
	 * For a standard option, the array element key is the field value and the array element value is the field label.
	 *
	 * For an optgroup, the array element key is the label and the array element value is an associative array of
	 * options as above.
	 *
	 * Example:
	 *
	 *     [
	 *         'edit'         => 'Edit',
	 *         'delete'       => 'Delete',
	 *         'Change State' => [
	 *             'feature' => 'Featured',
	 *             'sale'    => 'On Sale',
	 *         ]
	 *     ]
	 *
	 * @since 3.1.0
	 * @since 5.6.0 A bulk action can now contain an array of options in order to create an optgroup.
	 *
	 * @return array
	 */
	protected function get_bulk_actions() {
		return array();
	}

	/**
	 * Displays the bulk actions dropdown.
	 *
	 * @since 3.1.0
	 *
	 * @param string $which The location of the bulk actions: Either 'top' or 'bottom'.
	 *                      This is designated as optional for backward compatibility.
	 */
	protected function bulk_actions( $which = '' ) {
		if ( is_null( $this->_actions ) ) {
			$this->_actions = $this->get_bulk_actions();

			/**
			 * Filters the items in the bulk actions menu of the list table.
			 *
			 * The dynamic portion of the hook name, `$this->screen->id`, refers
			 * to the ID of the current screen.
			 *
			 * @since 3.1.0
			 * @since 5.6.0 A bulk action can now contain an array of options in order to create an optgroup.
			 *
			 * @param array $actions An array of the available bulk actions.
			 */
			$this->_actions = apply_filters( "bulk_actions-{$this->screen->id}", $this->_actions ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores

			$two = '';
		} else {
			$two = '2';
		}

		if ( empty( $this->_actions ) ) {
			return;
		}

		echo '<label for="bulk-action-selector-' . esc_attr( $which ) . '" class="screen-reader-text">' .
			/* translators: Hidden accessibility text. */
			__( 'Select bulk action' ) .
		'</label>';
		echo '<select name="action' . $two . '" id="bulk-action-selector-' . esc_attr( $which ) . "\">\n";
		echo '<option value="-1">' . __( 'Bulk actions' ) . "</option>\n";

		foreach ( $this->_actions as $key => $value ) {
			if ( is_array( $value ) ) {
				echo "\t" . '<optgroup label="' . esc_attr( $key ) . '">' . "\n";

				foreach ( $value as $name => $title ) {
					$class = ( 'edit' === $name ) ? ' class="hide-if-no-js"' : '';

					echo "\t\t" . '<option value="' . esc_attr( $name ) . '"' . $class . '>' . $title . "</option>\n";
				}
				echo "\t" . "</optgroup>\n";
			} else {
				$class = ( 'edit' === $key ) ? ' class="hide-if-no-js"' : '';

				echo "\t" . '<option value="' . esc_attr( $key ) . '"' . $class . '>' . $value . "</option>\n";
			}
		}

		echo "</select>\n";

		submit_button( __( 'Apply' ), 'action', 'bulk_action', false, array( 'id' => "doaction$two" ) );
		echo "\n";
	}

	/**
	 * Gets the current action selected from the bulk actions dropdown.
	 *
	 * @since 3.1.0
	 *
	 * @return string|false The action name. False if no action was selected.
	 */
	public function current_action() {
		if ( isset( $_REQUEST['filter_action'] ) && ! empty( $_REQUEST['filter_action'] ) ) {
			return false;
		}

		if ( isset( $_REQUEST['action'] ) && '-1' !== $_REQUEST['action'] ) {
			return $_REQUEST['action'];
		}

		return false;
	}

	/**
	 * Generates the required HTML for a list of row action links.
	 *
	 * @since 3.1.0
	 *
	 * @param string[] $actions        An array of action links.
	 * @param bool     $always_visible Whether the actions should be always visible.
	 * @return string The HTML for the row actions.
	 */
	protected function row_actions( $actions, $always_visible = false ) {
		$action_count = count( $actions );

		if ( ! $action_count ) {
			return '';
		}

		$mode = get_user_setting( 'posts_list_mode', 'list' );

		if ( 'excerpt' === $mode ) {
			$always_visible = true;
		}

		$output = '<div class="' . ( $always_visible ? 'row-actions visible' : 'row-actions' ) . '">';

		$i = 0;

		foreach ( $actions as $action => $link ) {
			++$i;

			$separator = ( $i < $action_count ) ? ' | ' : '';

			$output .= "<span class='$action'>{$link}{$separator}</span>";
		}

		$output .= '</div>';

		$output .= '<button type="button" class="toggle-row"><span class="screen-reader-text">' .
			/* translators: Hidden accessibility text. */
			__( 'Show more details' ) .
		'</span></button>';

		return $output;
	}

	/**
	 * Displays a dropdown for filtering items in the list table by month.
	 *
	 * @since 3.1.0
	 *
	 * @global wpdb      $wpdb      WordPress database abstraction object.
	 * @global WP_Locale $wp_locale WordPress date and time locale object.
	 *
	 * @param string $post_type The post type.
	 */
	protected function months_dropdown( $post_type ) {
		global $wpdb, $wp_locale;

		/**
		 * Filters whether to remove the 'Months' drop-down from the post list table.
		 *
		 * @since 4.2.0
		 *
		 * @param bool   $disable   Whether to disable the drop-down. Default false.
		 * @param string $post_type The post type.
		 */
		if ( apply_filters( 'disable_months_dropdown', false, $post_type ) ) {
			return;
		}

		/**
		 * Filters whether to short-circuit performing the months dropdown query.
		 *
		 * @since 5.7.0
		 *
		 * @param object[]|false $months   'Months' drop-down results. Default false.
		 * @param string         $post_type The post type.
		 */
		$months = apply_filters( 'pre_months_dropdown_query', false, $post_type );

		if ( ! is_array( $months ) ) {
			$extra_checks = "AND post_status != 'auto-draft'";
			if ( ! isset( $_GET['post_status'] ) || 'trash' !== $_GET['post_status'] ) {
				$extra_checks .= " AND post_status != 'trash'";
			} elseif ( isset( $_GET['post_status'] ) ) {
				$extra_checks = $wpdb->prepare( ' AND post_status = %s', $_GET['post_status'] );
			}

			$months = $wpdb->get_results(
				$wpdb->prepare(
					"SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month
					FROM $wpdb->posts
					WHERE post_type = %s
					$extra_checks
					ORDER BY post_date DESC",
					$post_type
				)
			);
		}

		/**
		 * Filters the 'Months' drop-down results.
		 *
		 * @since 3.7.0
		 *
		 * @param object[] $months    Array of the months drop-down query results.
		 * @param string   $post_type The post type.
		 */
		$months = apply_filters( 'months_dropdown_results', $months, $post_type );

		$month_count = count( $months );

		if ( ! $month_count || ( 1 === $month_count && 0 === (int) $months[0]->month ) ) {
			return;
		}

		$selected_month = isset( $_GET['m'] ) ? (int) $_GET['m'] : 0;
		?>
		<label for="filter-by-date" class="screen-reader-text"><?php echo get_post_type_object( $post_type )->labels->filter_by_date; ?></label>
		<select name="m" id="filter-by-date">
			<option<?php selected( $selected_month, 0 ); ?> value="0"><?php _e( 'All dates' ); ?></option>
		<?php
		foreach ( $months as $arc_row ) {
			if ( 0 === (int) $arc_row->year ) {
				continue;
			}

			$month = zeroise( $arc_row->month, 2 );
			$year  = $arc_row->year;

			printf(
				"<option %s value='%s'>%s</option>\n",
				selected( $selected_month, $year . $month, false ),
				esc_attr( $year . $month ),
				/* translators: 1: Month name, 2: 4-digit year. */
				esc_html( sprintf( __( '%1$s %2$d' ), $wp_locale->get_month( $month ), $year ) )
			);
		}
		?>
		</select>
		<?php
	}

	/**
	 * Displays a view switcher.
	 *
	 * @since 3.1.0
	 *
	 * @param string $current_mode
	 */
	protected function view_switcher( $current_mode ) {
		?>
		<input type="hidden" name="mode" value="<?php echo esc_attr( $current_mode ); ?>" />
		<div class="view-switch">
		<?php
		foreach ( $this->modes as $mode => $title ) {
			$classes      = array( 'view-' . $mode );
			$aria_current = '';

			if ( $current_mode === $mode ) {
				$classes[]    = 'current';
				$aria_current = ' aria-current="page"';
			}

			printf(
				"<a href='%s' class='%s' id='view-switch-$mode'$aria_current>" .
					"<span class='screen-reader-text'>%s</span>" .
				"</a>\n",
				esc_url( remove_query_arg( 'attachment-filter', add_query_arg( 'mode', $mode ) ) ),
				implode( ' ', $classes ),
				$title
			);
		}
		?>
		</div>
		<?php
	}

	/**
	 * Displays a comment count bubble.
	 *
	 * @since 3.1.0
	 *
	 * @param int $post_id          The post ID.
	 * @param int $pending_comments Number of pending comments.
	 */
	protected function comments_bubble( $post_id, $pending_comments ) {
		$post_object   = get_post( $post_id );
		$edit_post_cap = $post_object ? 'edit_post' : 'edit_posts';

		if ( ! current_user_can( $edit_post_cap, $post_id )
			&& ( post_password_required( $post_id )
				|| ! current_user_can( 'read_post', $post_id ) )
		) {
			// The user has no access to the post and thus cannot see the comments.
			return false;
		}

		$approved_comments = get_comments_number();

		$approved_comments_number = number_format_i18n( $approved_comments );
		$pending_comments_number  = number_format_i18n( $pending_comments );

		$approved_only_phrase = sprintf(
			/* translators: %s: Number of comments. */
			_n( '%s comment', '%s comments', $approved_comments ),
			$approved_comments_number
		);

		$approved_phrase = sprintf(
			/* translators: %s: Number of comments. */
			_n( '%s approved comment', '%s approved comments', $approved_comments ),
			$approved_comments_number
		);

		$pending_phrase = sprintf(
			/* translators: %s: Number of comments. */
			_n( '%s pending comment', '%s pending comments', $pending_comments ),
			$pending_comments_number
		);

		if ( ! $approved_comments && ! $pending_comments ) {
			// No comments at all.
			printf(
				'<span aria-hidden="true">&#8212;</span>' .
				'<span class="screen-reader-text">%s</span>',
				__( 'No comments' )
			);
		} elseif ( $approved_comments && 'trash' === get_post_status( $post_id ) ) {
			// Don't link the comment bubble for a trashed post.
			printf(
				'<span class="post-com-count post-com-count-approved">' .
					'<span class="comment-count-approved" aria-hidden="true">%s</span>' .
					'<span class="screen-reader-text">%s</span>' .
				'</span>',
				$approved_comments_number,
				$pending_comments ? $approved_phrase : $approved_only_phrase
			);
		} elseif ( $approved_comments ) {
			// Link the comment bubble to approved comments.
			printf(
				'<a href="%s" class="post-com-count post-com-count-approved">' .
					'<span class="comment-count-approved" aria-hidden="true">%s</span>' .
					'<span class="screen-reader-text">%s</span>' .
				'</a>',
				esc_url(
					add_query_arg(
						array(
							'p'              => $post_id,
							'comment_status' => 'approved',
						),
						admin_url( 'edit-comments.php' )
					)
				),
				$approved_comments_number,
				$pending_comments ? $approved_phrase : $approved_only_phrase
			);
		} else {
			// Don't link the comment bubble when there are no approved comments.
			printf(
				'<span class="post-com-count post-com-count-no-comments">' .
					'<span class="comment-count comment-count-no-comments" aria-hidden="true">%s</span>' .
					'<span class="screen-reader-text">%s</span>' .
				'</span>',
				$approved_comments_number,
				$pending_comments ?
				/* translators: Hidden accessibility text. */
				__( 'No approved comments' ) :
				/* translators: Hidden accessibility text. */
				__( 'No comments' )
			);
		}

		if ( $pending_comments ) {
			printf(
				'<a href="%s" class="post-com-count post-com-count-pending">' .
					'<span class="comment-count-pending" aria-hidden="true">%s</span>' .
					'<span class="screen-reader-text">%s</span>' .
				'</a>',
				esc_url(
					add_query_arg(
						array(
							'p'              => $post_id,
							'comment_status' => 'moderated',
						),
						admin_url( 'edit-comments.php' )
					)
				),
				$pending_comments_number,
				$pending_phrase
			);
		} else {
			printf(
				'<span class="post-com-count post-com-count-pending post-com-count-no-pending">' .
					'<span class="comment-count comment-count-no-pending" aria-hidden="true">%s</span>' .
					'<span class="screen-reader-text">%s</span>' .
				'</span>',
				$pending_comments_number,
				$approved_comments ?
				/* translators: Hidden accessibility text. */
				__( 'No pending comments' ) :
				/* translators: Hidden accessibility text. */
				__( 'No comments' )
			);
		}
	}

	/**
	 * Gets the current page number.
	 *
	 * @since 3.1.0
	 *
	 * @return int
	 */
	public function get_pagenum() {
		$pagenum = isset( $_REQUEST['paged'] ) ? absint( $_REQUEST['paged'] ) : 0;

		if ( isset( $this->_pagination_args['total_pages'] ) && $pagenum > $this->_pagination_args['total_pages'] ) {
			$pagenum = $this->_pagination_args['total_pages'];
		}

		return max( 1, $pagenum );
	}

	/**
	 * Gets the number of items to display on a single page.
	 *
	 * @since 3.1.0
	 *
	 * @param string $option        User option name.
	 * @param int    $default_value Optional. The number of items to display. Default 20.
	 * @return int
	 */
	protected function get_items_per_page( $option, $default_value = 20 ) {
		$per_page = (int) get_user_option( $option );
		if ( empty( $per_page ) || $per_page < 1 ) {
			$per_page = $default_value;
		}

		/**
		 * Filters the number of items to be displayed on each page of the list table.
		 *
		 * The dynamic hook name, `$option`, refers to the `per_page` option depending
		 * on the type of list table in use. Possible filter names include:
		 *
		 *  - `edit_comments_per_page`
		 *  - `sites_network_per_page`
		 *  - `site_themes_network_per_page`
		 *  - `themes_network_per_page`
		 *  - `users_network_per_page`
		 *  - `edit_post_per_page`
		 *  - `edit_page_per_page`
		 *  - `edit_{$post_type}_per_page`
		 *  - `edit_post_tag_per_page`
		 *  - `edit_category_per_page`
		 *  - `edit_{$taxonomy}_per_page`
		 *  - `site_users_network_per_page`
		 *  - `users_per_page`
		 *
		 * @since 2.9.0
		 *
		 * @param int $per_page Number of items to be displayed. Default 20.
		 */
		return (int) apply_filters( "{$option}", $per_page );
	}

	/**
	 * Displays the pagination.
	 *
	 * @since 3.1.0
	 *
	 * @param string $which The location of the pagination: Either 'top' or 'bottom'.
	 */
	protected function pagination( $which ) {
		if ( empty( $this->_pagination_args['total_items'] ) ) {
			return;
		}

		$total_items     = $this->_pagination_args['total_items'];
		$total_pages     = $this->_pagination_args['total_pages'];
		$infinite_scroll = false;
		if ( isset( $this->_pagination_args['infinite_scroll'] ) ) {
			$infinite_scroll = $this->_pagination_args['infinite_scroll'];
		}

		if ( 'top' === $which && $total_pages > 1 ) {
			$this->screen->render_screen_reader_content( 'heading_pagination' );
		}

		$output = '<span class="displaying-num">' . sprintf(
			/* translators: %s: Number of items. */
			_n( '%s item', '%s items', $total_items ),
			number_format_i18n( $total_items )
		) . '</span>';

		$current              = $this->get_pagenum();
		$removable_query_args = wp_removable_query_args();

		$current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );

		$current_url = remove_query_arg( $removable_query_args, $current_url );

		$page_links = array();

		$total_pages_before = '<span class="paging-input">';
		$total_pages_after  = '</span></span>';

		$disable_first = false;
		$disable_last  = false;
		$disable_prev  = false;
		$disable_next  = false;

		if ( 1 === $current ) {
			$disable_first = true;
			$disable_prev  = true;
		}
		if ( $total_pages === $current ) {
			$disable_last = true;
			$disable_next = true;
		}

		if ( $disable_first ) {
			$page_links[] = '<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&laquo;</span>';
		} else {
			$page_links[] = sprintf(
				"<a class='first-page button' href='%s'>" .
					"<span class='screen-reader-text'>%s</span>" .
					"<span aria-hidden='true'>%s</span>" .
				'</a>',
				esc_url( remove_query_arg( 'paged', $current_url ) ),
				/* translators: Hidden accessibility text. */
				__( 'First page' ),
				'&laquo;'
			);
		}

		if ( $disable_prev ) {
			$page_links[] = '<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&lsaquo;</span>';
		} else {
			$page_links[] = sprintf(
				"<a class='prev-page button' href='%s'>" .
					"<span class='screen-reader-text'>%s</span>" .
					"<span aria-hidden='true'>%s</span>" .
				'</a>',
				esc_url( add_query_arg( 'paged', max( 1, $current - 1 ), $current_url ) ),
				/* translators: Hidden accessibility text. */
				__( 'Previous page' ),
				'&lsaquo;'
			);
		}

		if ( 'bottom' === $which ) {
			$html_current_page  = $current;
			$total_pages_before = sprintf(
				'<span class="screen-reader-text">%s</span>' .
				'<span id="table-paging" class="paging-input">' .
				'<span class="tablenav-paging-text">',
				/* translators: Hidden accessibility text. */
				__( 'Current Page' )
			);
		} else {
			$html_current_page = sprintf(
				'<label for="current-page-selector" class="screen-reader-text">%s</label>' .
				"<input class='current-page' id='current-page-selector' type='text'
					name='paged' value='%s' size='%d' aria-describedby='table-paging' />" .
				"<span class='tablenav-paging-text'>",
				/* translators: Hidden accessibility text. */
				__( 'Current Page' ),
				$current,
				strlen( $total_pages )
			);
		}

		$html_total_pages = sprintf( "<span class='total-pages'>%s</span>", number_format_i18n( $total_pages ) );

		$page_links[] = $total_pages_before . sprintf(
			/* translators: 1: Current page, 2: Total pages. */
			_x( '%1$s of %2$s', 'paging' ),
			$html_current_page,
			$html_total_pages
		) . $total_pages_after;

		if ( $disable_next ) {
			$page_links[] = '<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&rsaquo;</span>';
		} else {
			$page_links[] = sprintf(
				"<a class='next-page button' href='%s'>" .
					"<span class='screen-reader-text'>%s</span>" .
					"<span aria-hidden='true'>%s</span>" .
				'</a>',
				esc_url( add_query_arg( 'paged', min( $total_pages, $current + 1 ), $current_url ) ),
				/* translators: Hidden accessibility text. */
				__( 'Next page' ),
				'&rsaquo;'
			);
		}

		if ( $disable_last ) {
			$page_links[] = '<span class="tablenav-pages-navspan button disabled" aria-hidden="true">&raquo;</span>';
		} else {
			$page_links[] = sprintf(
				"<a class='last-page button' href='%s'>" .
					"<span class='screen-reader-text'>%s</span>" .
					"<span aria-hidden='true'>%s</span>" .
				'</a>',
				esc_url( add_query_arg( 'paged', $total_pages, $current_url ) ),
				/* translators: Hidden accessibility text. */
				__( 'Last page' ),
				'&raquo;'
			);
		}

		$pagination_links_class = 'pagination-links';
		if ( ! empty( $infinite_scroll ) ) {
			$pagination_links_class .= ' hide-if-js';
		}
		$output .= "\n<span class='$pagination_links_class'>" . implode( "\n", $page_links ) . '</span>';

		if ( $total_pages ) {
			$page_class = $total_pages < 2 ? ' one-page' : '';
		} else {
			$page_class = ' no-pages';
		}
		$this->_pagination = "<div class='tablenav-pages{$page_class}'>$output</div>";

		echo $this->_pagination;
	}

	/**
	 * Gets a list of columns.
	 *
	 * The format is:
	 * - `'internal-name' => 'Title'`
	 *
	 * @since 3.1.0
	 * @abstract
	 *
	 * @return array
	 */
	public function get_columns() {
		die( 'function WP_List_Table::get_columns() must be overridden in a subclass.' );
	}

	/**
	 * Gets a list of sortable columns.
	 *
	 * The format is:
	 * - `'internal-name' => 'orderby'`
	 * - `'internal-name' => array( 'orderby', bool, 'abbr', 'orderby-text', 'initially-sorted-column-order' )` -
	 * - `'internal-name' => array( 'orderby', 'asc' )` - The second element sets the initial sorting order.
	 * - `'internal-name' => array( 'orderby', true )`  - The second element makes the initial order descending.
	 *
	 * In the second format, passing true as second parameter will make the initial
	 * sorting order be descending. Following parameters add a short column name to
	 * be used as 'abbr' attribute, a translatable string for the current sorting,
	 * and the initial order for the initial sorted column, 'asc' or 'desc' (default: false).
	 *
	 * @since 3.1.0
	 * @since 6.3.0 Added 'abbr', 'orderby-text' and 'initially-sorted-column-order'.
	 *
	 * @return array
	 */
	protected function get_sortable_columns() {
		return array();
	}

	/**
	 * Gets the name of the default primary column.
	 *
	 * @since 4.3.0
	 *
	 * @return string Name of the default primary column, in this case, an empty string.
	 */
	protected function get_default_primary_column_name() {
		$columns = $this->get_columns();
		$column  = '';

		if ( empty( $columns ) ) {
			return $column;
		}

		/*
		 * We need a primary defined so responsive views show something,
		 * so let's fall back to the first non-checkbox column.
		 */
		foreach ( $columns as $col => $column_name ) {
			if ( 'cb' === $col ) {
				continue;
			}

			$column = $col;
			break;
		}

		return $column;
	}

	/**
	 * Gets the name of the primary column.
	 *
	 * Public wrapper for WP_List_Table::get_default_primary_column_name().
	 *
	 * @since 4.4.0
	 *
	 * @return string Name of the default primary column.
	 */
	public function get_primary_column() {
		return $this->get_primary_column_name();
	}

	/**
	 * Gets the name of the primary column.
	 *
	 * @since 4.3.0
	 *
	 * @return string The name of the primary column.
	 */
	protected function get_primary_column_name() {
		$columns = get_column_headers( $this->screen );
		$default = $this->get_default_primary_column_name();

		/*
		 * If the primary column doesn't exist,
		 * fall back to the first non-checkbox column.
		 */
		if ( ! isset( $columns[ $default ] ) ) {
			$default = self::get_default_primary_column_name();
		}

		/**
		 * Filters the name of the primary column for the current list table.
		 *
		 * @since 4.3.0
		 *
		 * @param string $default Column name default for the specific list table, e.g. 'name'.
		 * @param string $context Screen ID for specific list table, e.g. 'plugins'.
		 */
		$column = apply_filters( 'list_table_primary_column', $default, $this->screen->id );

		if ( empty( $column ) || ! isset( $columns[ $column ] ) ) {
			$column = $default;
		}

		return $column;
	}

	/**
	 * Gets a list of all, hidden, and sortable columns, with filter applied.
	 *
	 * @since 3.1.0
	 *
	 * @return array
	 */
	protected function get_column_info() {
		// $_column_headers is already set / cached.
		if (
			isset( $this->_column_headers ) &&
			is_array( $this->_column_headers )
		) {
			/*
			 * Backward compatibility for `$_column_headers` format prior to WordPress 4.3.
			 *
			 * In WordPress 4.3 the primary column name was added as a fourth item in the
			 * column headers property. This ensures the primary column name is included
			 * in plugins setting the property directly in the three item format.
			 */
			if ( 4 === count( $this->_column_headers ) ) {
				return $this->_column_headers;
			}

			$column_headers = array( array(), array(), array(), $this->get_primary_column_name() );
			foreach ( $this->_column_headers as $key => $value ) {
				$column_headers[ $key ] = $value;
			}

			$this->_column_headers = $column_headers;

			return $this->_column_headers;
		}

		$columns = get_column_headers( $this->screen );
		$hidden  = get_hidden_columns( $this->screen );

		$sortable_columns = $this->get_sortable_columns();
		/**
		 * Filters the list table sortable columns for a specific screen.
		 *
		 * The dynamic portion of the hook name, `$this->screen->id`, refers
		 * to the ID of the current screen.
		 *
		 * @since 3.1.0
		 *
		 * @param array $sortable_columns An array of sortable columns.
		 */
		$_sortable = apply_filters( "manage_{$this->screen->id}_sortable_columns", $sortable_columns );

		$sortable = array();
		foreach ( $_sortable as $id => $data ) {
			if ( empty( $data ) ) {
				continue;
			}

			$data = (array) $data;
			// Descending initial sorting.
			if ( ! isset( $data[1] ) ) {
				$data[1] = false;
			}
			// Current sorting translatable string.
			if ( ! isset( $data[2] ) ) {
				$data[2] = '';
			}
			// Initial view sorted column and asc/desc order, default: false.
			if ( ! isset( $data[3] ) ) {
				$data[3] = false;
			}
			// Initial order for the initial sorted column, default: false.
			if ( ! isset( $data[4] ) ) {
				$data[4] = false;
			}

			$sortable[ $id ] = $data;
		}

		$primary               = $this->get_primary_column_name();
		$this->_column_headers = array( $columns, $hidden, $sortable, $primary );

		return $this->_column_headers;
	}

	/**
	 * Returns the number of visible columns.
	 *
	 * @since 3.1.0
	 *
	 * @return int
	 */
	public function get_column_count() {
		list ( $columns, $hidden ) = $this->get_column_info();
		$hidden                    = array_intersect( array_keys( $columns ), array_filter( $hidden ) );
		return count( $columns ) - count( $hidden );
	}

	/**
	 * Prints column headers, accounting for hidden and sortable columns.
	 *
	 * @since 3.1.0
	 *
	 * @param bool $with_id Whether to set the ID attribute or not
	 */
	public function print_column_headers( $with_id = true ) {
		list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();

		$current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
		$current_url = remove_query_arg( 'paged', $current_url );

		// When users click on a column header to sort by other columns.
		if ( isset( $_GET['orderby'] ) ) {
			$current_orderby = $_GET['orderby'];
			// In the initial view there's no orderby parameter.
		} else {
			$current_orderby = '';
		}

		// Not in the initial view and descending order.
		if ( isset( $_GET['order'] ) && 'desc' === $_GET['order'] ) {
			$current_order = 'desc';
		} else {
			// The initial view is not always 'asc', we'll take care of this below.
			$current_order = 'asc';
		}

		if ( ! empty( $columns['cb'] ) ) {
			static $cb_counter = 1;
			$columns['cb']     = '<input id="cb-select-all-' . $cb_counter . '" type="checkbox" />
			<label for="cb-select-all-' . $cb_counter . '">' .
				'<span class="screen-reader-text">' .
					/* translators: Hidden accessibility text. */
					__( 'Select All' ) .
				'</span>' .
				'</label>';
			++$cb_counter;
		}

		foreach ( $columns as $column_key => $column_display_name ) {
			$class          = array( 'manage-column', "column-$column_key" );
			$aria_sort_attr = '';
			$abbr_attr      = '';
			$order_text     = '';

			if ( in_array( $column_key, $hidden, true ) ) {
				$class[] = 'hidden';
			}

			if ( 'cb' === $column_key ) {
				$class[] = 'check-column';
			} elseif ( in_array( $column_key, array( 'posts', 'comments', 'links' ), true ) ) {
				$class[] = 'num';
			}

			if ( $column_key === $primary ) {
				$class[] = 'column-primary';
			}

			if ( isset( $sortable[ $column_key ] ) ) {
				$orderby       = isset( $sortable[ $column_key ][0] ) ? $sortable[ $column_key ][0] : '';
				$desc_first    = isset( $sortable[ $column_key ][1] ) ? $sortable[ $column_key ][1] : false;
				$abbr          = isset( $sortable[ $column_key ][2] ) ? $sortable[ $column_key ][2] : '';
				$orderby_text  = isset( $sortable[ $column_key ][3] ) ? $sortable[ $column_key ][3] : '';
				$initial_order = isset( $sortable[ $column_key ][4] ) ? $sortable[ $column_key ][4] : '';

				/*
				 * We're in the initial view and there's no $_GET['orderby'] then check if the
				 * initial sorting information is set in the sortable columns and use that.
				 */
				if ( '' === $current_orderby && $initial_order ) {
					// Use the initially sorted column $orderby as current orderby.
					$current_orderby = $orderby;
					// Use the initially sorted column asc/desc order as initial order.
					$current_order = $initial_order;
				}

				/*
				 * True in the initial view when an initial orderby is set via get_sortable_columns()
				 * and true in the sorted views when the actual $_GET['orderby'] is equal to $orderby.
				 */
				if ( $current_orderby === $orderby ) {
					// The sorted column. The `aria-sort` attribute must be set only on the sorted column.
					if ( 'asc' === $current_order ) {
						$order          = 'desc';
						$aria_sort_attr = ' aria-sort="ascending"';
					} else {
						$order          = 'asc';
						$aria_sort_attr = ' aria-sort="descending"';
					}

					$class[] = 'sorted';
					$class[] = $current_order;
				} else {
					// The other sortable columns.
					$order = strtolower( $desc_first );

					if ( ! in_array( $order, array( 'desc', 'asc' ), true ) ) {
						$order = $desc_first ? 'desc' : 'asc';
					}

					$class[] = 'sortable';
					$class[] = 'desc' === $order ? 'asc' : 'desc';

					/* translators: Hidden accessibility text. */
					$asc_text = __( 'Sort ascending.' );
					/* translators: Hidden accessibility text. */
					$desc_text  = __( 'Sort descending.' );
					$order_text = 'asc' === $order ? $asc_text : $desc_text;
				}

				if ( '' !== $order_text ) {
					$order_text = ' <span class="screen-reader-text">' . $order_text . '</span>';
				}

				// Print an 'abbr' attribute if a value is provided via get_sortable_columns().
				$abbr_attr = $abbr ? ' abbr="' . esc_attr( $abbr ) . '"' : '';

				$column_display_name = sprintf(
					'<a href="%1$s">' .
						'<span>%2$s</span>' .
						'<span class="sorting-indicators">' .
							'<span class="sorting-indicator asc" aria-hidden="true"></span>' .
							'<span class="sorting-indicator desc" aria-hidden="true"></span>' .
						'</span>' .
						'%3$s' .
					'</a>',
					esc_url( add_query_arg( compact( 'orderby', 'order' ), $current_url ) ),
					$column_display_name,
					$order_text
				);
			}

			$tag        = ( 'cb' === $column_key ) ? 'td' : 'th';
			$scope      = ( 'th' === $tag ) ? 'scope="col"' : '';
			$id         = $with_id ? "id='$column_key'" : '';
			$class_attr = "class='" . implode( ' ', $class ) . "'";

			echo "<$tag $scope $id $class_attr $aria_sort_attr $abbr_attr>$column_display_name</$tag>";
		}
	}

	/**
	 * Print a table description with information about current sorting and order.
	 *
	 * For the table initial view, information about initial orderby and order
	 * should be provided via get_sortable_columns().
	 *
	 * @since 6.3.0
	 */
	public function print_table_description() {
		list( $columns, $hidden, $sortable ) = $this->get_column_info();

		if ( empty( $sortable ) ) {
			return;
		}

		// When users click on a column header to sort by other columns.
		if ( isset( $_GET['orderby'] ) ) {
			$current_orderby = $_GET['orderby'];
			// In the initial view there's no orderby parameter.
		} else {
			$current_orderby = '';
		}

		// Not in the initial view and descending order.
		if ( isset( $_GET['order'] ) && 'desc' === $_GET['order'] ) {
			$current_order = 'desc';
		} else {
			// The initial view is not always 'asc', we'll take care of this below.
			$current_order = 'asc';
		}

		foreach ( array_keys( $columns ) as $column_key ) {

			if ( isset( $sortable[ $column_key ] ) ) {
				$orderby       = isset( $sortable[ $column_key ][0] ) ? $sortable[ $column_key ][0] : '';
				$desc_first    = isset( $sortable[ $column_key ][1] ) ? $sortable[ $column_key ][1] : false;
				$abbr          = isset( $sortable[ $column_key ][2] ) ? $sortable[ $column_key ][2] : '';
				$orderby_text  = isset( $sortable[ $column_key ][3] ) ? $sortable[ $column_key ][3] : '';
				$initial_order = isset( $sortable[ $column_key ][4] ) ? $sortable[ $column_key ][4] : '';

				if ( ! is_string( $orderby_text ) || '' === $orderby_text ) {
					return;
				}
				/*
				 * We're in the initial view and there's no $_GET['orderby'] then check if the
				 * initial sorting information is set in the sortable columns and use that.
				 */
				if ( '' === $current_orderby && $initial_order ) {
					// Use the initially sorted column $orderby as current orderby.
					$current_orderby = $orderby;
					// Use the initially sorted column asc/desc order as initial order.
					$current_order = $initial_order;
				}

				/*
				 * True in the initial view when an initial orderby is set via get_sortable_columns()
				 * and true in the sorted views when the actual $_GET['orderby'] is equal to $orderby.
				 */
				if ( $current_orderby === $orderby ) {
					/* translators: Hidden accessibility text. */
					$asc_text = __( 'Ascending.' );
					/* translators: Hidden accessibility text. */
					$desc_text  = __( 'Descending.' );
					$order_text = 'asc' === $current_order ? $asc_text : $desc_text;
					echo '<caption class="screen-reader-text">' . $orderby_text . ' ' . $order_text . '</caption>';

					return;
				}
			}
		}
	}

	/**
	 * Displays the table.
	 *
	 * @since 3.1.0
	 */
	public function display() {
		$singular = $this->_args['singular'];

		$this->display_tablenav( 'top' );

		$this->screen->render_screen_reader_content( 'heading_list' );
		?>
<table class="wp-list-table <?php echo implode( ' ', $this->get_table_classes() ); ?>">
		<?php $this->print_table_description(); ?>
	<thead>
	<tr>
		<?php $this->print_column_headers(); ?>
	</tr>
	</thead>

	<tbody id="the-list"
		<?php
		if ( $singular ) {
			echo " data-wp-lists='list:$singular'";
		}
		?>
		>
		<?php $this->display_rows_or_placeholder(); ?>
	</tbody>

	<tfoot>
	<tr>
		<?php $this->print_column_headers( false ); ?>
	</tr>
	</tfoot>

</table>
		<?php
		$this->display_tablenav( 'bottom' );
	}

	/**
	 * Gets a list of CSS classes for the WP_List_Table table tag.
	 *
	 * @since 3.1.0
	 *
	 * @return string[] Array of CSS classes for the table tag.
	 */
	protected function get_table_classes() {
		$mode = get_user_setting( 'posts_list_mode', 'list' );

		$mode_class = esc_attr( 'table-view-' . $mode );

		return array( 'widefat', 'fixed', 'striped', $mode_class, $this->_args['plural'] );
	}

	/**
	 * Generates the table navigation above or below the table
	 *
	 * @since 3.1.0
	 * @param string $which The location of the navigation: Either 'top' or 'bottom'.
	 */
	protected function display_tablenav( $which ) {
		if ( 'bottom' === $which && ! $this->has_items() ) {
			return;
		}
		if ( 'top' === $which ) {
			wp_nonce_field( 'bulk-' . $this->_args['plural'] );
		}
		?>
	<div class="tablenav <?php echo esc_attr( $which ); ?>">

		<?php if ( $this->has_items() ) : ?>
		<div class="alignleft actions bulkactions">
			<?php $this->bulk_actions( $which ); ?>
		</div>
			<?php
		endif;
		$this->extra_tablenav( $which );
		$this->pagination( $which );
		?>

		<br class="clear" />
	</div>
		<?php
	}

	/**
	 * Displays extra controls between bulk actions and pagination.
	 *
	 * @since 3.1.0
	 *
	 * @param string $which
	 */
	protected function extra_tablenav( $which ) {}

	/**
	 * Generates the tbody element for the list table.
	 *
	 * @since 3.1.0
	 */
	public function display_rows_or_placeholder() {
		if ( $this->has_items() ) {
			$this->display_rows();
		} else {
			echo '<tr class="no-items"><td class="colspanchange" colspan="' . $this->get_column_count() . '">';
			$this->no_items();
			echo '</td></tr>';
		}
	}

	/**
	 * Generates the list table rows.
	 *
	 * @since 3.1.0
	 */
	public function display_rows() {
		foreach ( $this->items as $item ) {
			$this->single_row( $item );
		}
	}

	/**
	 * Generates content for a single row of the table.
	 *
	 * @since 3.1.0
	 *
	 * @param object|array $item The current item
	 */
	public function single_row( $item ) {
		echo '<tr>';
		$this->single_row_columns( $item );
		echo '</tr>';
	}

	/**
	 * @param object|array $item
	 * @param string $column_name
	 */
	protected function column_default( $item, $column_name ) {}

	/**
	 * @param object|array $item
	 */
	protected function column_cb( $item ) {}

	/**
	 * Generates the columns for a single row of the table.
	 *
	 * @since 3.1.0
	 *
	 * @param object|array $item The current item.
	 */
	protected function single_row_columns( $item ) {
		list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();

		foreach ( $columns as $column_name => $column_display_name ) {
			$classes = "$column_name column-$column_name";
			if ( $primary === $column_name ) {
				$classes .= ' has-row-actions column-primary';
			}

			if ( in_array( $column_name, $hidden, true ) ) {
				$classes .= ' hidden';
			}

			/*
			 * Comments column uses HTML in the display name with screen reader text.
			 * Strip tags to get closer to a user-friendly string.
			 */
			$data = 'data-colname="' . esc_attr( wp_strip_all_tags( $column_display_name ) ) . '"';

			$attributes = "class='$classes' $data";

			if ( 'cb' === $column_name ) {
				echo '<th scope="row" class="check-column">';
				echo $this->column_cb( $item );
				echo '</th>';
			} elseif ( method_exists( $this, '_column_' . $column_name ) ) {
				echo call_user_func(
					array( $this, '_column_' . $column_name ),
					$item,
					$classes,
					$data,
					$primary
				);
			} elseif ( method_exists( $this, 'column_' . $column_name ) ) {
				echo "<td $attributes>";
				echo call_user_func( array( $this, 'column_' . $column_name ), $item );
				echo $this->handle_row_actions( $item, $column_name, $primary );
				echo '</td>';
			} else {
				echo "<td $attributes>";
				echo $this->column_default( $item, $column_name );
				echo $this->handle_row_actions( $item, $column_name, $primary );
				echo '</td>';
			}
		}
	}

	/**
	 * Generates and display row actions links for the list table.
	 *
	 * @since 4.3.0
	 *
	 * @param object|array $item        The item being acted upon.
	 * @param string       $column_name Current column name.
	 * @param string       $primary     Primary column name.
	 * @return string The row actions HTML, or an empty string
	 *                if the current column is not the primary column.
	 */
	protected function handle_row_actions( $item, $column_name, $primary ) {
		return $column_name === $primary ? '<button type="button" class="toggle-row"><span class="screen-reader-text">' .
			/* translators: Hidden accessibility text. */
			__( 'Show more details' ) .
		'</span></button>' : '';
	}

	/**
	 * Handles an incoming ajax request (called from admin-ajax.php)
	 *
	 * @since 3.1.0
	 */
	public function ajax_response() {
		$this->prepare_items();

		ob_start();
		if ( ! empty( $_REQUEST['no_placeholder'] ) ) {
			$this->display_rows();
		} else {
			$this->display_rows_or_placeholder();
		}

		$rows = ob_get_clean();

		$response = array( 'rows' => $rows );

		if ( isset( $this->_pagination_args['total_items'] ) ) {
			$response['total_items_i18n'] = sprintf(
				/* translators: Number of items. */
				_n( '%s item', '%s items', $this->_pagination_args['total_items'] ),
				number_format_i18n( $this->_pagination_args['total_items'] )
			);
		}
		if ( isset( $this->_pagination_args['total_pages'] ) ) {
			$response['total_pages']      = $this->_pagination_args['total_pages'];
			$response['total_pages_i18n'] = number_format_i18n( $this->_pagination_args['total_pages'] );
		}

		die( wp_json_encode( $response ) );
	}

	/**
	 * Sends required variables to JavaScript land.
	 *
	 * @since 3.1.0
	 */
	public function _js_vars() {
		$args = array(
			'class'  => get_class( $this ),
			'screen' => array(
				'id'   => $this->screen->id,
				'base' => $this->screen->base,
			),
		);

		printf( "<script type='text/javascript'>list_args = %s;</script>\n", wp_json_encode( $args, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) );
	}
}
class-wp-screen.php000064400000110744151212616060010272 0ustar00<?php
/**
 * Screen API: WP_Screen class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 4.4.0
 */

/**
 * Core class used to implement an admin screen API.
 *
 * @since 3.3.0
 */
#[AllowDynamicProperties]
final class WP_Screen {
	/**
	 * Any action associated with the screen.
	 *
	 * 'add' for *-add.php and *-new.php screens. Empty otherwise.
	 *
	 * @since 3.3.0
	 * @var string
	 */
	public $action;

	/**
	 * The base type of the screen.
	 *
	 * This is typically the same as `$id` but with any post types and taxonomies stripped.
	 * For example, for an `$id` of 'edit-post' the base is 'edit'.
	 *
	 * @since 3.3.0
	 * @var string
	 */
	public $base;

	/**
	 * The number of columns to display. Access with get_columns().
	 *
	 * @since 3.4.0
	 * @var int
	 */
	private $columns = 0;

	/**
	 * The unique ID of the screen.
	 *
	 * @since 3.3.0
	 * @var string
	 */
	public $id;

	/**
	 * Which admin the screen is in. network | user | site | false
	 *
	 * @since 3.5.0
	 * @var string
	 */
	protected $in_admin;

	/**
	 * Whether the screen is in the network admin.
	 *
	 * Deprecated. Use in_admin() instead.
	 *
	 * @since 3.3.0
	 * @deprecated 3.5.0
	 * @var bool
	 */
	public $is_network;

	/**
	 * Whether the screen is in the user admin.
	 *
	 * Deprecated. Use in_admin() instead.
	 *
	 * @since 3.3.0
	 * @deprecated 3.5.0
	 * @var bool
	 */
	public $is_user;

	/**
	 * The base menu parent.
	 *
	 * This is derived from `$parent_file` by removing the query string and any .php extension.
	 * `$parent_file` values of 'edit.php?post_type=page' and 'edit.php?post_type=post'
	 * have a `$parent_base` of 'edit'.
	 *
	 * @since 3.3.0
	 * @var string|null
	 */
	public $parent_base;

	/**
	 * The parent_file for the screen per the admin menu system.
	 *
	 * Some `$parent_file` values are 'edit.php?post_type=page', 'edit.php', and 'options-general.php'.
	 *
	 * @since 3.3.0
	 * @var string|null
	 */
	public $parent_file;

	/**
	 * The post type associated with the screen, if any.
	 *
	 * The 'edit.php?post_type=page' screen has a post type of 'page'.
	 * The 'edit-tags.php?taxonomy=$taxonomy&post_type=page' screen has a post type of 'page'.
	 *
	 * @since 3.3.0
	 * @var string
	 */
	public $post_type;

	/**
	 * The taxonomy associated with the screen, if any.
	 *
	 * The 'edit-tags.php?taxonomy=category' screen has a taxonomy of 'category'.
	 *
	 * @since 3.3.0
	 * @var string
	 */
	public $taxonomy;

	/**
	 * The help tab data associated with the screen, if any.
	 *
	 * @since 3.3.0
	 * @var array
	 */
	private $_help_tabs = array();

	/**
	 * The help sidebar data associated with screen, if any.
	 *
	 * @since 3.3.0
	 * @var string
	 */
	private $_help_sidebar = '';

	/**
	 * The accessible hidden headings and text associated with the screen, if any.
	 *
	 * @since 4.4.0
	 * @var string[]
	 */
	private $_screen_reader_content = array();

	/**
	 * Stores old string-based help.
	 *
	 * @var array
	 */
	private static $_old_compat_help = array();

	/**
	 * The screen options associated with screen, if any.
	 *
	 * @since 3.3.0
	 * @var array
	 */
	private $_options = array();

	/**
	 * The screen object registry.
	 *
	 * @since 3.3.0
	 *
	 * @var array
	 */
	private static $_registry = array();

	/**
	 * Stores the result of the public show_screen_options function.
	 *
	 * @since 3.3.0
	 * @var bool
	 */
	private $_show_screen_options;

	/**
	 * Stores the 'screen_settings' section of screen options.
	 *
	 * @since 3.3.0
	 * @var string
	 */
	private $_screen_settings;

	/**
	 * Whether the screen is using the block editor.
	 *
	 * @since 5.0.0
	 * @var bool
	 */
	public $is_block_editor = false;

	/**
	 * Fetches a screen object.
	 *
	 * @since 3.3.0
	 *
	 * @global string $hook_suffix
	 *
	 * @param string|WP_Screen $hook_name Optional. The hook name (also known as the hook suffix) used to determine the screen.
	 *                                    Defaults to the current $hook_suffix global.
	 * @return WP_Screen Screen object.
	 */
	public static function get( $hook_name = '' ) {
		if ( $hook_name instanceof WP_Screen ) {
			return $hook_name;
		}

		$id              = '';
		$post_type       = null;
		$taxonomy        = null;
		$in_admin        = false;
		$action          = '';
		$is_block_editor = false;

		if ( $hook_name ) {
			$id = $hook_name;
		} elseif ( ! empty( $GLOBALS['hook_suffix'] ) ) {
			$id = $GLOBALS['hook_suffix'];
		}

		// For those pesky meta boxes.
		if ( $hook_name && post_type_exists( $hook_name ) ) {
			$post_type = $id;
			$id        = 'post'; // Changes later. Ends up being $base.
		} else {
			if ( str_ends_with( $id, '.php' ) ) {
				$id = substr( $id, 0, -4 );
			}

			if ( in_array( $id, array( 'post-new', 'link-add', 'media-new', 'user-new' ), true ) ) {
				$id     = substr( $id, 0, -4 );
				$action = 'add';
			}
		}

		if ( ! $post_type && $hook_name ) {
			if ( str_ends_with( $id, '-network' ) ) {
				$id       = substr( $id, 0, -8 );
				$in_admin = 'network';
			} elseif ( str_ends_with( $id, '-user' ) ) {
				$id       = substr( $id, 0, -5 );
				$in_admin = 'user';
			}

			$id = sanitize_key( $id );
			if ( 'edit-comments' !== $id && 'edit-tags' !== $id && str_starts_with( $id, 'edit-' ) ) {
				$maybe = substr( $id, 5 );
				if ( taxonomy_exists( $maybe ) ) {
					$id       = 'edit-tags';
					$taxonomy = $maybe;
				} elseif ( post_type_exists( $maybe ) ) {
					$id        = 'edit';
					$post_type = $maybe;
				}
			}

			if ( ! $in_admin ) {
				$in_admin = 'site';
			}
		} else {
			if ( defined( 'WP_NETWORK_ADMIN' ) && WP_NETWORK_ADMIN ) {
				$in_admin = 'network';
			} elseif ( defined( 'WP_USER_ADMIN' ) && WP_USER_ADMIN ) {
				$in_admin = 'user';
			} else {
				$in_admin = 'site';
			}
		}

		if ( 'index' === $id ) {
			$id = 'dashboard';
		} elseif ( 'front' === $id ) {
			$in_admin = false;
		}

		$base = $id;

		// If this is the current screen, see if we can be more accurate for post types and taxonomies.
		if ( ! $hook_name ) {
			if ( isset( $_REQUEST['post_type'] ) ) {
				$post_type = post_type_exists( $_REQUEST['post_type'] ) ? $_REQUEST['post_type'] : false;
			}
			if ( isset( $_REQUEST['taxonomy'] ) ) {
				$taxonomy = taxonomy_exists( $_REQUEST['taxonomy'] ) ? $_REQUEST['taxonomy'] : false;
			}

			switch ( $base ) {
				case 'post':
					if ( isset( $_GET['post'] ) && isset( $_POST['post_ID'] ) && (int) $_GET['post'] !== (int) $_POST['post_ID'] ) {
						wp_die( __( 'A post ID mismatch has been detected.' ), __( 'Sorry, you are not allowed to edit this item.' ), 400 );
					} elseif ( isset( $_GET['post'] ) ) {
						$post_id = (int) $_GET['post'];
					} elseif ( isset( $_POST['post_ID'] ) ) {
						$post_id = (int) $_POST['post_ID'];
					} else {
						$post_id = 0;
					}

					if ( $post_id ) {
						$post = get_post( $post_id );
						if ( $post ) {
							$post_type = $post->post_type;

							/** This filter is documented in wp-admin/post.php */
							$replace_editor = apply_filters( 'replace_editor', false, $post );

							if ( ! $replace_editor ) {
								$is_block_editor = use_block_editor_for_post( $post );
							}
						}
					}
					break;
				case 'edit-tags':
				case 'term':
					if ( null === $post_type && is_object_in_taxonomy( 'post', $taxonomy ? $taxonomy : 'post_tag' ) ) {
						$post_type = 'post';
					}
					break;
				case 'upload':
					$post_type = 'attachment';
					break;
			}
		}

		switch ( $base ) {
			case 'post':
				if ( null === $post_type ) {
					$post_type = 'post';
				}

				// When creating a new post, use the default block editor support value for the post type.
				if ( empty( $post_id ) ) {
					$is_block_editor = use_block_editor_for_post_type( $post_type );
				}

				$id = $post_type;
				break;
			case 'edit':
				if ( null === $post_type ) {
					$post_type = 'post';
				}
				$id .= '-' . $post_type;
				break;
			case 'edit-tags':
			case 'term':
				if ( null === $taxonomy ) {
					$taxonomy = 'post_tag';
				}
				// The edit-tags ID does not contain the post type. Look for it in the request.
				if ( null === $post_type ) {
					$post_type = 'post';
					if ( isset( $_REQUEST['post_type'] ) && post_type_exists( $_REQUEST['post_type'] ) ) {
						$post_type = $_REQUEST['post_type'];
					}
				}

				$id = 'edit-' . $taxonomy;
				break;
		}

		if ( 'network' === $in_admin ) {
			$id   .= '-network';
			$base .= '-network';
		} elseif ( 'user' === $in_admin ) {
			$id   .= '-user';
			$base .= '-user';
		}

		if ( isset( self::$_registry[ $id ] ) ) {
			$screen = self::$_registry[ $id ];
			if ( get_current_screen() === $screen ) {
				return $screen;
			}
		} else {
			$screen     = new self();
			$screen->id = $id;
		}

		$screen->base            = $base;
		$screen->action          = $action;
		$screen->post_type       = (string) $post_type;
		$screen->taxonomy        = (string) $taxonomy;
		$screen->is_user         = ( 'user' === $in_admin );
		$screen->is_network      = ( 'network' === $in_admin );
		$screen->in_admin        = $in_admin;
		$screen->is_block_editor = $is_block_editor;

		self::$_registry[ $id ] = $screen;

		return $screen;
	}

	/**
	 * Makes the screen object the current screen.
	 *
	 * @see set_current_screen()
	 * @since 3.3.0
	 *
	 * @global WP_Screen $current_screen WordPress current screen object.
	 * @global string    $typenow        The post type of the current screen.
	 * @global string    $taxnow         The taxonomy of the current screen.
	 */
	public function set_current_screen() {
		global $current_screen, $taxnow, $typenow;

		$current_screen = $this;
		$typenow        = $this->post_type;
		$taxnow         = $this->taxonomy;

		/**
		 * Fires after the current screen has been set.
		 *
		 * @since 3.0.0
		 *
		 * @param WP_Screen $current_screen Current WP_Screen object.
		 */
		do_action( 'current_screen', $current_screen );
	}

	/**
	 * Constructor
	 *
	 * @since 3.3.0
	 */
	private function __construct() {}

	/**
	 * Indicates whether the screen is in a particular admin.
	 *
	 * @since 3.5.0
	 *
	 * @param string $admin The admin to check against (network | user | site).
	 *                      If empty any of the three admins will result in true.
	 * @return bool True if the screen is in the indicated admin, false otherwise.
	 */
	public function in_admin( $admin = null ) {
		if ( empty( $admin ) ) {
			return (bool) $this->in_admin;
		}

		return ( $admin === $this->in_admin );
	}

	/**
	 * Sets or returns whether the block editor is loading on the current screen.
	 *
	 * @since 5.0.0
	 *
	 * @param bool $set Optional. Sets whether the block editor is loading on the current screen or not.
	 * @return bool True if the block editor is being loaded, false otherwise.
	 */
	public function is_block_editor( $set = null ) {
		if ( null !== $set ) {
			$this->is_block_editor = (bool) $set;
		}

		return $this->is_block_editor;
	}

	/**
	 * Sets the old string-based contextual help for the screen for backward compatibility.
	 *
	 * @since 3.3.0
	 *
	 * @param WP_Screen $screen A screen object.
	 * @param string    $help   Help text.
	 */
	public static function add_old_compat_help( $screen, $help ) {
		self::$_old_compat_help[ $screen->id ] = $help;
	}

	/**
	 * Sets the parent information for the screen.
	 *
	 * This is called in admin-header.php after the menu parent for the screen has been determined.
	 *
	 * @since 3.3.0
	 *
	 * @param string $parent_file The parent file of the screen. Typically the $parent_file global.
	 */
	public function set_parentage( $parent_file ) {
		$this->parent_file         = $parent_file;
		list( $this->parent_base ) = explode( '?', $parent_file );
		$this->parent_base         = str_replace( '.php', '', $this->parent_base );
	}

	/**
	 * Adds an option for the screen.
	 *
	 * Call this in template files after admin.php is loaded and before admin-header.php is loaded
	 * to add screen options.
	 *
	 * @since 3.3.0
	 *
	 * @param string $option Option ID.
	 * @param mixed  $args   Option-dependent arguments.
	 */
	public function add_option( $option, $args = array() ) {
		$this->_options[ $option ] = $args;
	}

	/**
	 * Removes an option from the screen.
	 *
	 * @since 3.8.0
	 *
	 * @param string $option Option ID.
	 */
	public function remove_option( $option ) {
		unset( $this->_options[ $option ] );
	}

	/**
	 * Removes all options from the screen.
	 *
	 * @since 3.8.0
	 */
	public function remove_options() {
		$this->_options = array();
	}

	/**
	 * Gets the options registered for the screen.
	 *
	 * @since 3.8.0
	 *
	 * @return array Options with arguments.
	 */
	public function get_options() {
		return $this->_options;
	}

	/**
	 * Gets the arguments for an option for the screen.
	 *
	 * @since 3.3.0
	 *
	 * @param string       $option Option name.
	 * @param string|false $key    Optional. Specific array key for when the option is an array.
	 *                             Default false.
	 * @return string The option value if set, null otherwise.
	 */
	public function get_option( $option, $key = false ) {
		if ( ! isset( $this->_options[ $option ] ) ) {
			return null;
		}
		if ( $key ) {
			if ( isset( $this->_options[ $option ][ $key ] ) ) {
				return $this->_options[ $option ][ $key ];
			}
			return null;
		}
		return $this->_options[ $option ];
	}

	/**
	 * Gets the help tabs registered for the screen.
	 *
	 * @since 3.4.0
	 * @since 4.4.0 Help tabs are ordered by their priority.
	 *
	 * @return array Help tabs with arguments.
	 */
	public function get_help_tabs() {
		$help_tabs = $this->_help_tabs;

		$priorities = array();
		foreach ( $help_tabs as $help_tab ) {
			if ( isset( $priorities[ $help_tab['priority'] ] ) ) {
				$priorities[ $help_tab['priority'] ][] = $help_tab;
			} else {
				$priorities[ $help_tab['priority'] ] = array( $help_tab );
			}
		}

		ksort( $priorities );

		$sorted = array();
		foreach ( $priorities as $list ) {
			foreach ( $list as $tab ) {
				$sorted[ $tab['id'] ] = $tab;
			}
		}

		return $sorted;
	}

	/**
	 * Gets the arguments for a help tab.
	 *
	 * @since 3.4.0
	 *
	 * @param string $id Help Tab ID.
	 * @return array Help tab arguments.
	 */
	public function get_help_tab( $id ) {
		if ( ! isset( $this->_help_tabs[ $id ] ) ) {
			return null;
		}
		return $this->_help_tabs[ $id ];
	}

	/**
	 * Adds a help tab to the contextual help for the screen.
	 *
	 * Call this on the `load-$pagenow` hook for the relevant screen,
	 * or fetch the `$current_screen` object, or use get_current_screen()
	 * and then call the method from the object.
	 *
	 * You may need to filter `$current_screen` using an if or switch statement
	 * to prevent new help tabs from being added to ALL admin screens.
	 *
	 * @since 3.3.0
	 * @since 4.4.0 The `$priority` argument was added.
	 *
	 * @param array $args {
	 *     Array of arguments used to display the help tab.
	 *
	 *     @type string   $title    Title for the tab. Default false.
	 *     @type string   $id       Tab ID. Must be HTML-safe and should be unique for this menu.
	 *                              It is NOT allowed to contain any empty spaces. Default false.
	 *     @type string   $content  Optional. Help tab content in plain text or HTML. Default empty string.
	 *     @type callable $callback Optional. A callback to generate the tab content. Default false.
	 *     @type int      $priority Optional. The priority of the tab, used for ordering. Default 10.
	 * }
	 */
	public function add_help_tab( $args ) {
		$defaults = array(
			'title'    => false,
			'id'       => false,
			'content'  => '',
			'callback' => false,
			'priority' => 10,
		);
		$args     = wp_parse_args( $args, $defaults );

		$args['id'] = sanitize_html_class( $args['id'] );

		// Ensure we have an ID and title.
		if ( ! $args['id'] || ! $args['title'] ) {
			return;
		}

		// Allows for overriding an existing tab with that ID.
		$this->_help_tabs[ $args['id'] ] = $args;
	}

	/**
	 * Removes a help tab from the contextual help for the screen.
	 *
	 * @since 3.3.0
	 *
	 * @param string $id The help tab ID.
	 */
	public function remove_help_tab( $id ) {
		unset( $this->_help_tabs[ $id ] );
	}

	/**
	 * Removes all help tabs from the contextual help for the screen.
	 *
	 * @since 3.3.0
	 */
	public function remove_help_tabs() {
		$this->_help_tabs = array();
	}

	/**
	 * Gets the content from a contextual help sidebar.
	 *
	 * @since 3.4.0
	 *
	 * @return string Contents of the help sidebar.
	 */
	public function get_help_sidebar() {
		return $this->_help_sidebar;
	}

	/**
	 * Adds a sidebar to the contextual help for the screen.
	 *
	 * Call this in template files after admin.php is loaded and before admin-header.php is loaded
	 * to add a sidebar to the contextual help.
	 *
	 * @since 3.3.0
	 *
	 * @param string $content Sidebar content in plain text or HTML.
	 */
	public function set_help_sidebar( $content ) {
		$this->_help_sidebar = $content;
	}

	/**
	 * Gets the number of layout columns the user has selected.
	 *
	 * The layout_columns option controls the max number and default number of
	 * columns. This method returns the number of columns within that range selected
	 * by the user via Screen Options. If no selection has been made, the default
	 * provisioned in layout_columns is returned. If the screen does not support
	 * selecting the number of layout columns, 0 is returned.
	 *
	 * @since 3.4.0
	 *
	 * @return int Number of columns to display.
	 */
	public function get_columns() {
		return $this->columns;
	}

	/**
	 * Gets the accessible hidden headings and text used in the screen.
	 *
	 * @since 4.4.0
	 *
	 * @see set_screen_reader_content() For more information on the array format.
	 *
	 * @return string[] An associative array of screen reader text strings.
	 */
	public function get_screen_reader_content() {
		return $this->_screen_reader_content;
	}

	/**
	 * Gets a screen reader text string.
	 *
	 * @since 4.4.0
	 *
	 * @param string $key Screen reader text array named key.
	 * @return string Screen reader text string.
	 */
	public function get_screen_reader_text( $key ) {
		if ( ! isset( $this->_screen_reader_content[ $key ] ) ) {
			return null;
		}
		return $this->_screen_reader_content[ $key ];
	}

	/**
	 * Adds accessible hidden headings and text for the screen.
	 *
	 * @since 4.4.0
	 *
	 * @param array $content {
	 *     An associative array of screen reader text strings.
	 *
	 *     @type string $heading_views      Screen reader text for the filter links heading.
	 *                                      Default 'Filter items list'.
	 *     @type string $heading_pagination Screen reader text for the pagination heading.
	 *                                      Default 'Items list navigation'.
	 *     @type string $heading_list       Screen reader text for the items list heading.
	 *                                      Default 'Items list'.
	 * }
	 */
	public function set_screen_reader_content( $content = array() ) {
		$defaults = array(
			'heading_views'      => __( 'Filter items list' ),
			'heading_pagination' => __( 'Items list navigation' ),
			'heading_list'       => __( 'Items list' ),
		);
		$content  = wp_parse_args( $content, $defaults );

		$this->_screen_reader_content = $content;
	}

	/**
	 * Removes all the accessible hidden headings and text for the screen.
	 *
	 * @since 4.4.0
	 */
	public function remove_screen_reader_content() {
		$this->_screen_reader_content = array();
	}

	/**
	 * Renders the screen's help section.
	 *
	 * This will trigger the deprecated filters for backward compatibility.
	 *
	 * @since 3.3.0
	 *
	 * @global string $screen_layout_columns
	 */
	public function render_screen_meta() {

		/**
		 * Filters the legacy contextual help list.
		 *
		 * @since 2.7.0
		 * @deprecated 3.3.0 Use {@see get_current_screen()->add_help_tab()} or
		 *                   {@see get_current_screen()->remove_help_tab()} instead.
		 *
		 * @param array     $old_compat_help Old contextual help.
		 * @param WP_Screen $screen          Current WP_Screen instance.
		 */
		self::$_old_compat_help = apply_filters_deprecated(
			'contextual_help_list',
			array( self::$_old_compat_help, $this ),
			'3.3.0',
			'get_current_screen()->add_help_tab(), get_current_screen()->remove_help_tab()'
		);

		$old_help = isset( self::$_old_compat_help[ $this->id ] ) ? self::$_old_compat_help[ $this->id ] : '';

		/**
		 * Filters the legacy contextual help text.
		 *
		 * @since 2.7.0
		 * @deprecated 3.3.0 Use {@see get_current_screen()->add_help_tab()} or
		 *                   {@see get_current_screen()->remove_help_tab()} instead.
		 *
		 * @param string    $old_help  Help text that appears on the screen.
		 * @param string    $screen_id Screen ID.
		 * @param WP_Screen $screen    Current WP_Screen instance.
		 */
		$old_help = apply_filters_deprecated(
			'contextual_help',
			array( $old_help, $this->id, $this ),
			'3.3.0',
			'get_current_screen()->add_help_tab(), get_current_screen()->remove_help_tab()'
		);

		// Default help only if there is no old-style block of text and no new-style help tabs.
		if ( empty( $old_help ) && ! $this->get_help_tabs() ) {

			/**
			 * Filters the default legacy contextual help text.
			 *
			 * @since 2.8.0
			 * @deprecated 3.3.0 Use {@see get_current_screen()->add_help_tab()} or
			 *                   {@see get_current_screen()->remove_help_tab()} instead.
			 *
			 * @param string $old_help_default Default contextual help text.
			 */
			$default_help = apply_filters_deprecated(
				'default_contextual_help',
				array( '' ),
				'3.3.0',
				'get_current_screen()->add_help_tab(), get_current_screen()->remove_help_tab()'
			);
			if ( $default_help ) {
				$old_help = '<p>' . $default_help . '</p>';
			}
		}

		if ( $old_help ) {
			$this->add_help_tab(
				array(
					'id'      => 'old-contextual-help',
					'title'   => __( 'Overview' ),
					'content' => $old_help,
				)
			);
		}

		$help_sidebar = $this->get_help_sidebar();

		$help_class = 'hidden';
		if ( ! $help_sidebar ) {
			$help_class .= ' no-sidebar';
		}

		// Time to render!
		?>
		<div id="screen-meta" class="metabox-prefs">

			<div id="contextual-help-wrap" class="<?php echo esc_attr( $help_class ); ?>" tabindex="-1" aria-label="<?php esc_attr_e( 'Contextual Help Tab' ); ?>">
				<div id="contextual-help-back"></div>
				<div id="contextual-help-columns">
					<div class="contextual-help-tabs">
						<ul>
						<?php
						$class = ' class="active"';
						foreach ( $this->get_help_tabs() as $tab ) :
							$link_id  = "tab-link-{$tab['id']}";
							$panel_id = "tab-panel-{$tab['id']}";
							?>

							<li id="<?php echo esc_attr( $link_id ); ?>"<?php echo $class; ?>>
								<a href="<?php echo esc_url( "#$panel_id" ); ?>" aria-controls="<?php echo esc_attr( $panel_id ); ?>">
									<?php echo esc_html( $tab['title'] ); ?>
								</a>
							</li>
							<?php
							$class = '';
						endforeach;
						?>
						</ul>
					</div>

					<?php if ( $help_sidebar ) : ?>
					<div class="contextual-help-sidebar">
						<?php echo $help_sidebar; ?>
					</div>
					<?php endif; ?>

					<div class="contextual-help-tabs-wrap">
						<?php
						$classes = 'help-tab-content active';
						foreach ( $this->get_help_tabs() as $tab ) :
							$panel_id = "tab-panel-{$tab['id']}";
							?>

							<div id="<?php echo esc_attr( $panel_id ); ?>" class="<?php echo $classes; ?>">
								<?php
								// Print tab content.
								echo $tab['content'];

								// If it exists, fire tab callback.
								if ( ! empty( $tab['callback'] ) ) {
									call_user_func_array( $tab['callback'], array( $this, $tab ) );
								}
								?>
							</div>
							<?php
							$classes = 'help-tab-content';
						endforeach;
						?>
					</div>
				</div>
			</div>
		<?php
		// Setup layout columns.

		/**
		 * Filters the array of screen layout columns.
		 *
		 * This hook provides back-compat for plugins using the back-compat
		 * Filters instead of add_screen_option().
		 *
		 * @since 2.8.0
		 *
		 * @param array     $empty_columns Empty array.
		 * @param string    $screen_id     Screen ID.
		 * @param WP_Screen $screen        Current WP_Screen instance.
		 */
		$columns = apply_filters( 'screen_layout_columns', array(), $this->id, $this );

		if ( ! empty( $columns ) && isset( $columns[ $this->id ] ) ) {
			$this->add_option( 'layout_columns', array( 'max' => $columns[ $this->id ] ) );
		}

		if ( $this->get_option( 'layout_columns' ) ) {
			$this->columns = (int) get_user_option( "screen_layout_$this->id" );

			if ( ! $this->columns && $this->get_option( 'layout_columns', 'default' ) ) {
				$this->columns = $this->get_option( 'layout_columns', 'default' );
			}
		}
		$GLOBALS['screen_layout_columns'] = $this->columns; // Set the global for back-compat.

		// Add screen options.
		if ( $this->show_screen_options() ) {
			$this->render_screen_options();
		}
		?>
		</div>
		<?php
		if ( ! $this->get_help_tabs() && ! $this->show_screen_options() ) {
			return;
		}
		?>
		<div id="screen-meta-links">
		<?php if ( $this->show_screen_options() ) : ?>
			<div id="screen-options-link-wrap" class="hide-if-no-js screen-meta-toggle">
			<button type="button" id="show-settings-link" class="button show-settings" aria-controls="screen-options-wrap" aria-expanded="false"><?php _e( 'Screen Options' ); ?></button>
			</div>
			<?php
		endif;
		if ( $this->get_help_tabs() ) :
			?>
			<div id="contextual-help-link-wrap" class="hide-if-no-js screen-meta-toggle">
			<button type="button" id="contextual-help-link" class="button show-settings" aria-controls="contextual-help-wrap" aria-expanded="false"><?php _e( 'Help' ); ?></button>
			</div>
		<?php endif; ?>
		</div>
		<?php
	}

	/**
	 * @since 3.3.0
	 *
	 * @global array $wp_meta_boxes Global meta box state.
	 *
	 * @return bool
	 */
	public function show_screen_options() {
		global $wp_meta_boxes;

		if ( is_bool( $this->_show_screen_options ) ) {
			return $this->_show_screen_options;
		}

		$columns = get_column_headers( $this );

		$show_screen = ! empty( $wp_meta_boxes[ $this->id ] ) || $columns || $this->get_option( 'per_page' );

		$this->_screen_settings = '';

		if ( 'post' === $this->base ) {
			$expand                 = '<fieldset class="editor-expand hidden"><legend>' . __( 'Additional settings' ) . '</legend><label for="editor-expand-toggle">';
			$expand                .= '<input type="checkbox" id="editor-expand-toggle"' . checked( get_user_setting( 'editor_expand', 'on' ), 'on', false ) . ' />';
			$expand                .= __( 'Enable full-height editor and distraction-free functionality.' ) . '</label></fieldset>';
			$this->_screen_settings = $expand;
		}

		/**
		 * Filters the screen settings text displayed in the Screen Options tab.
		 *
		 * @since 3.0.0
		 *
		 * @param string    $screen_settings Screen settings.
		 * @param WP_Screen $screen          WP_Screen object.
		 */
		$this->_screen_settings = apply_filters( 'screen_settings', $this->_screen_settings, $this );

		if ( $this->_screen_settings || $this->_options ) {
			$show_screen = true;
		}

		/**
		 * Filters whether to show the Screen Options tab.
		 *
		 * @since 3.2.0
		 *
		 * @param bool      $show_screen Whether to show Screen Options tab.
		 *                               Default true.
		 * @param WP_Screen $screen      Current WP_Screen instance.
		 */
		$this->_show_screen_options = apply_filters( 'screen_options_show_screen', $show_screen, $this );
		return $this->_show_screen_options;
	}

	/**
	 * Renders the screen options tab.
	 *
	 * @since 3.3.0
	 *
	 * @param array $options {
	 *     Options for the tab.
	 *
	 *     @type bool $wrap Whether the screen-options-wrap div will be included. Defaults to true.
	 * }
	 */
	public function render_screen_options( $options = array() ) {
		$options = wp_parse_args(
			$options,
			array(
				'wrap' => true,
			)
		);

		$wrapper_start = '';
		$wrapper_end   = '';
		$form_start    = '';
		$form_end      = '';

		// Output optional wrapper.
		if ( $options['wrap'] ) {
			$wrapper_start = '<div id="screen-options-wrap" class="hidden" tabindex="-1" aria-label="' . esc_attr__( 'Screen Options Tab' ) . '">';
			$wrapper_end   = '</div>';
		}

		// Don't output the form and nonce for the widgets accessibility mode links.
		if ( 'widgets' !== $this->base ) {
			$form_start = "\n<form id='adv-settings' method='post'>\n";
			$form_end   = "\n" . wp_nonce_field( 'screen-options-nonce', 'screenoptionnonce', false, false ) . "\n</form>\n";
		}

		echo $wrapper_start . $form_start;

		$this->render_meta_boxes_preferences();
		$this->render_list_table_columns_preferences();
		$this->render_screen_layout();
		$this->render_per_page_options();
		$this->render_view_mode();
		echo $this->_screen_settings;

		/**
		 * Filters whether to show the Screen Options submit button.
		 *
		 * @since 4.4.0
		 *
		 * @param bool      $show_button Whether to show Screen Options submit button.
		 *                               Default false.
		 * @param WP_Screen $screen      Current WP_Screen instance.
		 */
		$show_button = apply_filters( 'screen_options_show_submit', false, $this );

		if ( $show_button ) {
			submit_button( __( 'Apply' ), 'primary', 'screen-options-apply', true );
		}

		echo $form_end . $wrapper_end;
	}

	/**
	 * Renders the meta boxes preferences.
	 *
	 * @since 4.4.0
	 *
	 * @global array $wp_meta_boxes Global meta box state.
	 */
	public function render_meta_boxes_preferences() {
		global $wp_meta_boxes;

		if ( ! isset( $wp_meta_boxes[ $this->id ] ) ) {
			return;
		}
		?>
		<fieldset class="metabox-prefs">
		<legend><?php _e( 'Screen elements' ); ?></legend>
		<p>
			<?php _e( 'Some screen elements can be shown or hidden by using the checkboxes.' ); ?>
			<?php _e( 'Expand or collapse the elements by clicking on their headings, and arrange them by dragging their headings or by clicking on the up and down arrows.' ); ?>
		</p>
		<div class="metabox-prefs-container">
		<?php

		meta_box_prefs( $this );

		if ( 'dashboard' === $this->id && has_action( 'welcome_panel' ) && current_user_can( 'edit_theme_options' ) ) {
			if ( isset( $_GET['welcome'] ) ) {
				$welcome_checked = empty( $_GET['welcome'] ) ? 0 : 1;
				update_user_meta( get_current_user_id(), 'show_welcome_panel', $welcome_checked );
			} else {
				$welcome_checked = (int) get_user_meta( get_current_user_id(), 'show_welcome_panel', true );
				if ( 2 === $welcome_checked && wp_get_current_user()->user_email !== get_option( 'admin_email' ) ) {
					$welcome_checked = false;
				}
			}
			echo '<label for="wp_welcome_panel-hide">';
			echo '<input type="checkbox" id="wp_welcome_panel-hide"' . checked( (bool) $welcome_checked, true, false ) . ' />';
			echo _x( 'Welcome', 'Welcome panel' ) . "</label>\n";
		}
		?>
		</div>
		</fieldset>
		<?php
	}

	/**
	 * Renders the list table columns preferences.
	 *
	 * @since 4.4.0
	 */
	public function render_list_table_columns_preferences() {

		$columns = get_column_headers( $this );
		$hidden  = get_hidden_columns( $this );

		if ( ! $columns ) {
			return;
		}

		$legend = ! empty( $columns['_title'] ) ? $columns['_title'] : __( 'Columns' );
		?>
		<fieldset class="metabox-prefs">
		<legend><?php echo $legend; ?></legend>
		<?php
		$special = array( '_title', 'cb', 'comment', 'media', 'name', 'title', 'username', 'blogname' );

		foreach ( $columns as $column => $title ) {
			// Can't hide these for they are special.
			if ( in_array( $column, $special, true ) ) {
				continue;
			}

			if ( empty( $title ) ) {
				continue;
			}

			/*
			 * The Comments column uses HTML in the display name with some screen
			 * reader text. Make sure to strip tags from the Comments column
			 * title and any other custom column title plugins might add.
			 */
			$title = wp_strip_all_tags( $title );

			$id = "$column-hide";
			echo '<label>';
			echo '<input class="hide-column-tog" name="' . $id . '" type="checkbox" id="' . $id . '" value="' . $column . '"' . checked( ! in_array( $column, $hidden, true ), true, false ) . ' />';
			echo "$title</label>\n";
		}
		?>
		</fieldset>
		<?php
	}

	/**
	 * Renders the option for number of columns on the page.
	 *
	 * @since 3.3.0
	 */
	public function render_screen_layout() {
		if ( ! $this->get_option( 'layout_columns' ) ) {
			return;
		}

		$screen_layout_columns = $this->get_columns();
		$num                   = $this->get_option( 'layout_columns', 'max' );

		?>
		<fieldset class='columns-prefs'>
		<legend class="screen-layout"><?php _e( 'Layout' ); ?></legend>
		<?php for ( $i = 1; $i <= $num; ++$i ) : ?>
			<label class="columns-prefs-<?php echo $i; ?>">
			<input type='radio' name='screen_columns' value='<?php echo esc_attr( $i ); ?>' <?php checked( $screen_layout_columns, $i ); ?> />
			<?php
				printf(
					/* translators: %s: Number of columns on the page. */
					_n( '%s column', '%s columns', $i ),
					number_format_i18n( $i )
				);
			?>
			</label>
		<?php endfor; ?>
		</fieldset>
		<?php
	}

	/**
	 * Renders the items per page option.
	 *
	 * @since 3.3.0
	 */
	public function render_per_page_options() {
		if ( null === $this->get_option( 'per_page' ) ) {
			return;
		}

		$per_page_label = $this->get_option( 'per_page', 'label' );
		if ( null === $per_page_label ) {
			$per_page_label = __( 'Number of items per page:' );
		}

		$option = $this->get_option( 'per_page', 'option' );
		if ( ! $option ) {
			$option = str_replace( '-', '_', "{$this->id}_per_page" );
		}

		$per_page = (int) get_user_option( $option );
		if ( empty( $per_page ) || $per_page < 1 ) {
			$per_page = $this->get_option( 'per_page', 'default' );
			if ( ! $per_page ) {
				$per_page = 20;
			}
		}

		if ( 'edit_comments_per_page' === $option ) {
			$comment_status = isset( $_REQUEST['comment_status'] ) ? $_REQUEST['comment_status'] : 'all';

			/** This filter is documented in wp-admin/includes/class-wp-comments-list-table.php */
			$per_page = apply_filters( 'comments_per_page', $per_page, $comment_status );
		} elseif ( 'categories_per_page' === $option ) {
			/** This filter is documented in wp-admin/includes/class-wp-terms-list-table.php */
			$per_page = apply_filters( 'edit_categories_per_page', $per_page );
		} else {
			/** This filter is documented in wp-admin/includes/class-wp-list-table.php */
			$per_page = apply_filters( "{$option}", $per_page );
		}

		// Back compat.
		if ( isset( $this->post_type ) ) {
			/** This filter is documented in wp-admin/includes/post.php */
			$per_page = apply_filters( 'edit_posts_per_page', $per_page, $this->post_type );
		}

		// This needs a submit button.
		add_filter( 'screen_options_show_submit', '__return_true' );

		?>
		<fieldset class="screen-options">
		<legend><?php _e( 'Pagination' ); ?></legend>
			<?php if ( $per_page_label ) : ?>
				<label for="<?php echo esc_attr( $option ); ?>"><?php echo $per_page_label; ?></label>
				<input type="number" step="1" min="1" max="999" class="screen-per-page" name="wp_screen_options[value]"
					id="<?php echo esc_attr( $option ); ?>"
					value="<?php echo esc_attr( $per_page ); ?>" />
			<?php endif; ?>
				<input type="hidden" name="wp_screen_options[option]" value="<?php echo esc_attr( $option ); ?>" />
		</fieldset>
		<?php
	}

	/**
	 * Renders the list table view mode preferences.
	 *
	 * @since 4.4.0
	 *
	 * @global string $mode List table view mode.
	 */
	public function render_view_mode() {
		global $mode;

		$screen = get_current_screen();

		// Currently only enabled for posts and comments lists.
		if ( 'edit' !== $screen->base && 'edit-comments' !== $screen->base ) {
			return;
		}

		$view_mode_post_types = get_post_types( array( 'show_ui' => true ) );

		/**
		 * Filters the post types that have different view mode options.
		 *
		 * @since 4.4.0
		 *
		 * @param string[] $view_mode_post_types Array of post types that can change view modes.
		 *                                       Default post types with show_ui on.
		 */
		$view_mode_post_types = apply_filters( 'view_mode_post_types', $view_mode_post_types );

		if ( 'edit' === $screen->base && ! in_array( $this->post_type, $view_mode_post_types, true ) ) {
			return;
		}

		if ( ! isset( $mode ) ) {
			$mode = get_user_setting( 'posts_list_mode', 'list' );
		}

		// This needs a submit button.
		add_filter( 'screen_options_show_submit', '__return_true' );
		?>
		<fieldset class="metabox-prefs view-mode">
			<legend><?php _e( 'View mode' ); ?></legend>
			<label for="list-view-mode">
				<input id="list-view-mode" type="radio" name="mode" value="list" <?php checked( 'list', $mode ); ?> />
				<?php _e( 'Compact view' ); ?>
			</label>
			<label for="excerpt-view-mode">
				<input id="excerpt-view-mode" type="radio" name="mode" value="excerpt" <?php checked( 'excerpt', $mode ); ?> />
				<?php _e( 'Extended view' ); ?>
			</label>
		</fieldset>
		<?php
	}

	/**
	 * Renders screen reader text.
	 *
	 * @since 4.4.0
	 *
	 * @param string $key The screen reader text array named key.
	 * @param string $tag Optional. The HTML tag to wrap the screen reader text. Default h2.
	 */
	public function render_screen_reader_content( $key = '', $tag = 'h2' ) {

		if ( ! isset( $this->_screen_reader_content[ $key ] ) ) {
			return;
		}
		echo "<$tag class='screen-reader-text'>" . $this->_screen_reader_content[ $key ] . "</$tag>";
	}
}
class-file-upload-upgrader.php000064400000010103151212616060012363 0ustar00<?php
/**
 * Upgrade API: File_Upload_Upgrader class
 *
 * @package WordPress
 * @subpackage Upgrader
 * @since 4.6.0
 */

/**
 * Core class used for handling file uploads.
 *
 * This class handles the upload process and passes it as if it's a local file
 * to the Upgrade/Installer functions.
 *
 * @since 2.8.0
 * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader.php.
 */
#[AllowDynamicProperties]
class File_Upload_Upgrader {

	/**
	 * The full path to the file package.
	 *
	 * @since 2.8.0
	 * @var string $package
	 */
	public $package;

	/**
	 * The name of the file.
	 *
	 * @since 2.8.0
	 * @var string $filename
	 */
	public $filename;

	/**
	 * The ID of the attachment post for this file.
	 *
	 * @since 3.3.0
	 * @var int $id
	 */
	public $id = 0;

	/**
	 * Construct the upgrader for a form.
	 *
	 * @since 2.8.0
	 *
	 * @param string $form      The name of the form the file was uploaded from.
	 * @param string $urlholder The name of the `GET` parameter that holds the filename.
	 */
	public function __construct( $form, $urlholder ) {

		if ( empty( $_FILES[ $form ]['name'] ) && empty( $_GET[ $urlholder ] ) ) {
			wp_die( __( 'Please select a file' ) );
		}

		// Handle a newly uploaded file. Else, assume it's already been uploaded.
		if ( ! empty( $_FILES ) ) {
			$overrides = array(
				'test_form' => false,
				'test_type' => false,
			);
			$file      = wp_handle_upload( $_FILES[ $form ], $overrides );

			if ( isset( $file['error'] ) ) {
				wp_die( $file['error'] );
			}

			if ( 'pluginzip' === $form || 'themezip' === $form ) {
				if ( ! wp_zip_file_is_valid( $file['file'] ) ) {
					wp_delete_file( $file['file'] );

					if ( 'pluginzip' === $form ) {
						$plugins_page = sprintf(
							'<a href="%s">%s</a>',
							self_admin_url( 'plugin-install.php' ),
							__( 'Return to the Plugin Installer' )
						);
						wp_die( __( 'Incompatible Archive.' ) . '<br />' . $plugins_page );
					}

					if ( 'themezip' === $form ) {
						$themes_page = sprintf(
							'<a href="%s" target="_parent">%s</a>',
							self_admin_url( 'theme-install.php' ),
							__( 'Return to the Theme Installer' )
						);
						wp_die( __( 'Incompatible Archive.' ) . '<br />' . $themes_page );
					}
				}
			}

			$this->filename = $_FILES[ $form ]['name'];
			$this->package  = $file['file'];

			// Construct the attachment array.
			$attachment = array(
				'post_title'     => $this->filename,
				'post_content'   => $file['url'],
				'post_mime_type' => $file['type'],
				'guid'           => $file['url'],
				'context'        => 'upgrader',
				'post_status'    => 'private',
			);

			// Save the data.
			$this->id = wp_insert_attachment( $attachment, $file['file'] );

			// Schedule a cleanup for 2 hours from now in case of failed installation.
			wp_schedule_single_event( time() + 2 * HOUR_IN_SECONDS, 'upgrader_scheduled_cleanup', array( $this->id ) );

		} elseif ( is_numeric( $_GET[ $urlholder ] ) ) {
			// Numeric Package = previously uploaded file, see above.
			$this->id   = (int) $_GET[ $urlholder ];
			$attachment = get_post( $this->id );
			if ( empty( $attachment ) ) {
				wp_die( __( 'Please select a file' ) );
			}

			$this->filename = $attachment->post_title;
			$this->package  = get_attached_file( $attachment->ID );
		} else {
			// Else, It's set to something, Back compat for plugins using the old (pre-3.3) File_Uploader handler.
			$uploads = wp_upload_dir();
			if ( ! ( $uploads && false === $uploads['error'] ) ) {
				wp_die( $uploads['error'] );
			}

			$this->filename = sanitize_file_name( $_GET[ $urlholder ] );
			$this->package  = $uploads['basedir'] . '/' . $this->filename;

			if ( ! str_starts_with( realpath( $this->package ), realpath( $uploads['basedir'] ) ) ) {
				wp_die( __( 'Please select a file' ) );
			}
		}
	}

	/**
	 * Deletes the attachment/uploaded file.
	 *
	 * @since 3.2.2
	 *
	 * @return bool Whether the cleanup was successful.
	 */
	public function cleanup() {
		if ( $this->id ) {
			wp_delete_attachment( $this->id );

		} elseif ( file_exists( $this->package ) ) {
			return @unlink( $this->package );
		}

		return true;
	}
}
privacy-tools.php000064400000101261151212616060010071 0ustar00<?php
/**
 * WordPress Administration Privacy Tools API.
 *
 * @package WordPress
 * @subpackage Administration
 */

/**
 * Resend an existing request and return the result.
 *
 * @since 4.9.6
 * @access private
 *
 * @param int $request_id Request ID.
 * @return true|WP_Error Returns true if sending the email was successful, or a WP_Error object.
 */
function _wp_privacy_resend_request( $request_id ) {
	$request_id = absint( $request_id );
	$request    = get_post( $request_id );

	if ( ! $request || 'user_request' !== $request->post_type ) {
		return new WP_Error( 'privacy_request_error', __( 'Invalid personal data request.' ) );
	}

	$result = wp_send_user_request( $request_id );

	if ( is_wp_error( $result ) ) {
		return $result;
	} elseif ( ! $result ) {
		return new WP_Error( 'privacy_request_error', __( 'Unable to initiate confirmation for personal data request.' ) );
	}

	return true;
}

/**
 * Marks a request as completed by the admin and logs the current timestamp.
 *
 * @since 4.9.6
 * @access private
 *
 * @param int $request_id Request ID.
 * @return int|WP_Error Request ID on success, or a WP_Error on failure.
 */
function _wp_privacy_completed_request( $request_id ) {
	// Get the request.
	$request_id = absint( $request_id );
	$request    = wp_get_user_request( $request_id );

	if ( ! $request ) {
		return new WP_Error( 'privacy_request_error', __( 'Invalid personal data request.' ) );
	}

	update_post_meta( $request_id, '_wp_user_request_completed_timestamp', time() );

	$result = wp_update_post(
		array(
			'ID'          => $request_id,
			'post_status' => 'request-completed',
		)
	);

	return $result;
}

/**
 * Handle list table actions.
 *
 * @since 4.9.6
 * @access private
 */
function _wp_personal_data_handle_actions() {
	if ( isset( $_POST['privacy_action_email_retry'] ) ) {
		check_admin_referer( 'bulk-privacy_requests' );

		$request_id = absint( current( array_keys( (array) wp_unslash( $_POST['privacy_action_email_retry'] ) ) ) );
		$result     = _wp_privacy_resend_request( $request_id );

		if ( is_wp_error( $result ) ) {
			add_settings_error(
				'privacy_action_email_retry',
				'privacy_action_email_retry',
				$result->get_error_message(),
				'error'
			);
		} else {
			add_settings_error(
				'privacy_action_email_retry',
				'privacy_action_email_retry',
				__( 'Confirmation request sent again successfully.' ),
				'success'
			);
		}
	} elseif ( isset( $_POST['action'] ) ) {
		$action = ! empty( $_POST['action'] ) ? sanitize_key( wp_unslash( $_POST['action'] ) ) : '';

		switch ( $action ) {
			case 'add_export_personal_data_request':
			case 'add_remove_personal_data_request':
				check_admin_referer( 'personal-data-request' );

				if ( ! isset( $_POST['type_of_action'], $_POST['username_or_email_for_privacy_request'] ) ) {
					add_settings_error(
						'action_type',
						'action_type',
						__( 'Invalid personal data action.' ),
						'error'
					);
				}
				$action_type               = sanitize_text_field( wp_unslash( $_POST['type_of_action'] ) );
				$username_or_email_address = sanitize_text_field( wp_unslash( $_POST['username_or_email_for_privacy_request'] ) );
				$email_address             = '';
				$status                    = 'pending';

				if ( ! isset( $_POST['send_confirmation_email'] ) ) {
					$status = 'confirmed';
				}

				if ( ! in_array( $action_type, _wp_privacy_action_request_types(), true ) ) {
					add_settings_error(
						'action_type',
						'action_type',
						__( 'Invalid personal data action.' ),
						'error'
					);
				}

				if ( ! is_email( $username_or_email_address ) ) {
					$user = get_user_by( 'login', $username_or_email_address );
					if ( ! $user instanceof WP_User ) {
						add_settings_error(
							'username_or_email_for_privacy_request',
							'username_or_email_for_privacy_request',
							__( 'Unable to add this request. A valid email address or username must be supplied.' ),
							'error'
						);
					} else {
						$email_address = $user->user_email;
					}
				} else {
					$email_address = $username_or_email_address;
				}

				if ( empty( $email_address ) ) {
					break;
				}

				$request_id = wp_create_user_request( $email_address, $action_type, array(), $status );
				$message    = '';

				if ( is_wp_error( $request_id ) ) {
					$message = $request_id->get_error_message();
				} elseif ( ! $request_id ) {
					$message = __( 'Unable to initiate confirmation request.' );
				}

				if ( $message ) {
					add_settings_error(
						'username_or_email_for_privacy_request',
						'username_or_email_for_privacy_request',
						$message,
						'error'
					);
					break;
				}

				if ( 'pending' === $status ) {
					wp_send_user_request( $request_id );

					$message = __( 'Confirmation request initiated successfully.' );
				} elseif ( 'confirmed' === $status ) {
					$message = __( 'Request added successfully.' );
				}

				if ( $message ) {
					add_settings_error(
						'username_or_email_for_privacy_request',
						'username_or_email_for_privacy_request',
						$message,
						'success'
					);
					break;
				}
		}
	}
}

/**
 * Cleans up failed and expired requests before displaying the list table.
 *
 * @since 4.9.6
 * @access private
 */
function _wp_personal_data_cleanup_requests() {
	/** This filter is documented in wp-includes/user.php */
	$expires = (int) apply_filters( 'user_request_key_expiration', DAY_IN_SECONDS );

	$requests_query = new WP_Query(
		array(
			'post_type'      => 'user_request',
			'posts_per_page' => -1,
			'post_status'    => 'request-pending',
			'fields'         => 'ids',
			'date_query'     => array(
				array(
					'column' => 'post_modified_gmt',
					'before' => $expires . ' seconds ago',
				),
			),
		)
	);

	$request_ids = $requests_query->posts;

	foreach ( $request_ids as $request_id ) {
		wp_update_post(
			array(
				'ID'            => $request_id,
				'post_status'   => 'request-failed',
				'post_password' => '',
			)
		);
	}
}

/**
 * Generate a single group for the personal data export report.
 *
 * @since 4.9.6
 * @since 5.4.0 Added the `$group_id` and `$groups_count` parameters.
 *
 * @param array  $group_data {
 *     The group data to render.
 *
 *     @type string $group_label  The user-facing heading for the group, e.g. 'Comments'.
 *     @type array  $items        {
 *         An array of group items.
 *
 *         @type array  $group_item_data  {
 *             An array of name-value pairs for the item.
 *
 *             @type string $name   The user-facing name of an item name-value pair, e.g. 'IP Address'.
 *             @type string $value  The user-facing value of an item data pair, e.g. '50.60.70.0'.
 *         }
 *     }
 * }
 * @param string $group_id     The group identifier.
 * @param int    $groups_count The number of all groups
 * @return string The HTML for this group and its items.
 */
function wp_privacy_generate_personal_data_export_group_html( $group_data, $group_id = '', $groups_count = 1 ) {
	$group_id_attr = sanitize_title_with_dashes( $group_data['group_label'] . '-' . $group_id );

	$group_html  = '<h2 id="' . esc_attr( $group_id_attr ) . '">';
	$group_html .= esc_html( $group_data['group_label'] );

	$items_count = count( (array) $group_data['items'] );
	if ( $items_count > 1 ) {
		$group_html .= sprintf( ' <span class="count">(%d)</span>', $items_count );
	}

	$group_html .= '</h2>';

	if ( ! empty( $group_data['group_description'] ) ) {
		$group_html .= '<p>' . esc_html( $group_data['group_description'] ) . '</p>';
	}

	$group_html .= '<div>';

	foreach ( (array) $group_data['items'] as $group_item_id => $group_item_data ) {
		$group_html .= '<table>';
		$group_html .= '<tbody>';

		foreach ( (array) $group_item_data as $group_item_datum ) {
			$value = $group_item_datum['value'];
			// If it looks like a link, make it a link.
			if ( ! str_contains( $value, ' ' ) && ( str_starts_with( $value, 'http://' ) || str_starts_with( $value, 'https://' ) ) ) {
				$value = '<a href="' . esc_url( $value ) . '">' . esc_html( $value ) . '</a>';
			}

			$group_html .= '<tr>';
			$group_html .= '<th>' . esc_html( $group_item_datum['name'] ) . '</th>';
			$group_html .= '<td>' . wp_kses( $value, 'personal_data_export' ) . '</td>';
			$group_html .= '</tr>';
		}

		$group_html .= '</tbody>';
		$group_html .= '</table>';
	}

	if ( $groups_count > 1 ) {
		$group_html .= '<div class="return-to-top">';
		$group_html .= '<a href="#top"><span aria-hidden="true">&uarr; </span> ' . esc_html__( 'Go to top' ) . '</a>';
		$group_html .= '</div>';
	}

	$group_html .= '</div>';

	return $group_html;
}

/**
 * Generate the personal data export file.
 *
 * @since 4.9.6
 *
 * @param int $request_id The export request ID.
 */
function wp_privacy_generate_personal_data_export_file( $request_id ) {
	if ( ! class_exists( 'ZipArchive' ) ) {
		wp_send_json_error( __( 'Unable to generate personal data export file. ZipArchive not available.' ) );
	}

	// Get the request.
	$request = wp_get_user_request( $request_id );

	if ( ! $request || 'export_personal_data' !== $request->action_name ) {
		wp_send_json_error( __( 'Invalid request ID when generating personal data export file.' ) );
	}

	$email_address = $request->email;

	if ( ! is_email( $email_address ) ) {
		wp_send_json_error( __( 'Invalid email address when generating personal data export file.' ) );
	}

	// Create the exports folder if needed.
	$exports_dir = wp_privacy_exports_dir();
	$exports_url = wp_privacy_exports_url();

	if ( ! wp_mkdir_p( $exports_dir ) ) {
		wp_send_json_error( __( 'Unable to create personal data export folder.' ) );
	}

	// Protect export folder from browsing.
	$index_pathname = $exports_dir . 'index.php';
	if ( ! file_exists( $index_pathname ) ) {
		$file = fopen( $index_pathname, 'w' );
		if ( false === $file ) {
			wp_send_json_error( __( 'Unable to protect personal data export folder from browsing.' ) );
		}
		fwrite( $file, "<?php\n// Silence is golden.\n" );
		fclose( $file );
	}

	$obscura              = wp_generate_password( 32, false, false );
	$file_basename        = 'wp-personal-data-file-' . $obscura;
	$html_report_filename = wp_unique_filename( $exports_dir, $file_basename . '.html' );
	$html_report_pathname = wp_normalize_path( $exports_dir . $html_report_filename );
	$json_report_filename = $file_basename . '.json';
	$json_report_pathname = wp_normalize_path( $exports_dir . $json_report_filename );

	/*
	 * Gather general data needed.
	 */

	// Title.
	$title = sprintf(
		/* translators: %s: User's email address. */
		__( 'Personal Data Export for %s' ),
		$email_address
	);

	// First, build an "About" group on the fly for this report.
	$about_group = array(
		/* translators: Header for the About section in a personal data export. */
		'group_label'       => _x( 'About', 'personal data group label' ),
		/* translators: Description for the About section in a personal data export. */
		'group_description' => _x( 'Overview of export report.', 'personal data group description' ),
		'items'             => array(
			'about-1' => array(
				array(
					'name'  => _x( 'Report generated for', 'email address' ),
					'value' => $email_address,
				),
				array(
					'name'  => _x( 'For site', 'website name' ),
					'value' => get_bloginfo( 'name' ),
				),
				array(
					'name'  => _x( 'At URL', 'website URL' ),
					'value' => get_bloginfo( 'url' ),
				),
				array(
					'name'  => _x( 'On', 'date/time' ),
					'value' => current_time( 'mysql' ),
				),
			),
		),
	);

	// And now, all the Groups.
	$groups = get_post_meta( $request_id, '_export_data_grouped', true );
	if ( is_array( $groups ) ) {
		// Merge in the special "About" group.
		$groups       = array_merge( array( 'about' => $about_group ), $groups );
		$groups_count = count( $groups );
	} else {
		if ( false !== $groups ) {
			_doing_it_wrong(
				__FUNCTION__,
				/* translators: %s: Post meta key. */
				sprintf( __( 'The %s post meta must be an array.' ), '<code>_export_data_grouped</code>' ),
				'5.8.0'
			);
		}

		$groups       = null;
		$groups_count = 0;
	}

	// Convert the groups to JSON format.
	$groups_json = wp_json_encode( $groups );

	if ( false === $groups_json ) {
		$error_message = sprintf(
			/* translators: %s: Error message. */
			__( 'Unable to encode the personal data for export. Error: %s' ),
			json_last_error_msg()
		);

		wp_send_json_error( $error_message );
	}

	/*
	 * Handle the JSON export.
	 */
	$file = fopen( $json_report_pathname, 'w' );

	if ( false === $file ) {
		wp_send_json_error( __( 'Unable to open personal data export file (JSON report) for writing.' ) );
	}

	fwrite( $file, '{' );
	fwrite( $file, '"' . $title . '":' );
	fwrite( $file, $groups_json );
	fwrite( $file, '}' );
	fclose( $file );

	/*
	 * Handle the HTML export.
	 */
	$file = fopen( $html_report_pathname, 'w' );

	if ( false === $file ) {
		wp_send_json_error( __( 'Unable to open personal data export (HTML report) for writing.' ) );
	}

	fwrite( $file, "<!DOCTYPE html>\n" );
	fwrite( $file, "<html>\n" );
	fwrite( $file, "<head>\n" );
	fwrite( $file, "<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />\n" );
	fwrite( $file, "<style type='text/css'>" );
	fwrite( $file, 'body { color: black; font-family: Arial, sans-serif; font-size: 11pt; margin: 15px auto; width: 860px; }' );
	fwrite( $file, 'table { background: #f0f0f0; border: 1px solid #ddd; margin-bottom: 20px; width: 100%; }' );
	fwrite( $file, 'th { padding: 5px; text-align: left; width: 20%; }' );
	fwrite( $file, 'td { padding: 5px; }' );
	fwrite( $file, 'tr:nth-child(odd) { background-color: #fafafa; }' );
	fwrite( $file, '.return-to-top { text-align: right; }' );
	fwrite( $file, '</style>' );
	fwrite( $file, '<title>' );
	fwrite( $file, esc_html( $title ) );
	fwrite( $file, '</title>' );
	fwrite( $file, "</head>\n" );
	fwrite( $file, "<body>\n" );
	fwrite( $file, '<h1 id="top">' . esc_html__( 'Personal Data Export' ) . '</h1>' );

	// Create TOC.
	if ( $groups_count > 1 ) {
		fwrite( $file, '<div id="table_of_contents">' );
		fwrite( $file, '<h2>' . esc_html__( 'Table of Contents' ) . '</h2>' );
		fwrite( $file, '<ul>' );
		foreach ( (array) $groups as $group_id => $group_data ) {
			$group_label       = esc_html( $group_data['group_label'] );
			$group_id_attr     = sanitize_title_with_dashes( $group_data['group_label'] . '-' . $group_id );
			$group_items_count = count( (array) $group_data['items'] );
			if ( $group_items_count > 1 ) {
				$group_label .= sprintf( ' <span class="count">(%d)</span>', $group_items_count );
			}
			fwrite( $file, '<li>' );
			fwrite( $file, '<a href="#' . esc_attr( $group_id_attr ) . '">' . $group_label . '</a>' );
			fwrite( $file, '</li>' );
		}
		fwrite( $file, '</ul>' );
		fwrite( $file, '</div>' );
	}

	// Now, iterate over every group in $groups and have the formatter render it in HTML.
	foreach ( (array) $groups as $group_id => $group_data ) {
		fwrite( $file, wp_privacy_generate_personal_data_export_group_html( $group_data, $group_id, $groups_count ) );
	}

	fwrite( $file, "</body>\n" );
	fwrite( $file, "</html>\n" );
	fclose( $file );

	/*
	 * Now, generate the ZIP.
	 *
	 * If an archive has already been generated, then remove it and reuse the filename,
	 * to avoid breaking any URLs that may have been previously sent via email.
	 */
	$error = false;

	// This meta value is used from version 5.5.
	$archive_filename = get_post_meta( $request_id, '_export_file_name', true );

	// This one stored an absolute path and is used for backward compatibility.
	$archive_pathname = get_post_meta( $request_id, '_export_file_path', true );

	// If a filename meta exists, use it.
	if ( ! empty( $archive_filename ) ) {
		$archive_pathname = $exports_dir . $archive_filename;
	} elseif ( ! empty( $archive_pathname ) ) {
		// If a full path meta exists, use it and create the new meta value.
		$archive_filename = basename( $archive_pathname );

		update_post_meta( $request_id, '_export_file_name', $archive_filename );

		// Remove the back-compat meta values.
		delete_post_meta( $request_id, '_export_file_url' );
		delete_post_meta( $request_id, '_export_file_path' );
	} else {
		// If there's no filename or full path stored, create a new file.
		$archive_filename = $file_basename . '.zip';
		$archive_pathname = $exports_dir . $archive_filename;

		update_post_meta( $request_id, '_export_file_name', $archive_filename );
	}

	$archive_url = $exports_url . $archive_filename;

	if ( ! empty( $archive_pathname ) && file_exists( $archive_pathname ) ) {
		wp_delete_file( $archive_pathname );
	}

	$zip = new ZipArchive();
	if ( true === $zip->open( $archive_pathname, ZipArchive::CREATE ) ) {
		if ( ! $zip->addFile( $json_report_pathname, 'export.json' ) ) {
			$error = __( 'Unable to archive the personal data export file (JSON format).' );
		}

		if ( ! $zip->addFile( $html_report_pathname, 'index.html' ) ) {
			$error = __( 'Unable to archive the personal data export file (HTML format).' );
		}

		$zip->close();

		if ( ! $error ) {
			/**
			 * Fires right after all personal data has been written to the export file.
			 *
			 * @since 4.9.6
			 * @since 5.4.0 Added the `$json_report_pathname` parameter.
			 *
			 * @param string $archive_pathname     The full path to the export file on the filesystem.
			 * @param string $archive_url          The URL of the archive file.
			 * @param string $html_report_pathname The full path to the HTML personal data report on the filesystem.
			 * @param int    $request_id           The export request ID.
			 * @param string $json_report_pathname The full path to the JSON personal data report on the filesystem.
			 */
			do_action( 'wp_privacy_personal_data_export_file_created', $archive_pathname, $archive_url, $html_report_pathname, $request_id, $json_report_pathname );
		}
	} else {
		$error = __( 'Unable to open personal data export file (archive) for writing.' );
	}

	// Remove the JSON file.
	unlink( $json_report_pathname );

	// Remove the HTML file.
	unlink( $html_report_pathname );

	if ( $error ) {
		wp_send_json_error( $error );
	}
}

/**
 * Send an email to the user with a link to the personal data export file
 *
 * @since 4.9.6
 *
 * @param int $request_id The request ID for this personal data export.
 * @return true|WP_Error True on success or `WP_Error` on failure.
 */
function wp_privacy_send_personal_data_export_email( $request_id ) {
	// Get the request.
	$request = wp_get_user_request( $request_id );

	if ( ! $request || 'export_personal_data' !== $request->action_name ) {
		return new WP_Error( 'invalid_request', __( 'Invalid request ID when sending personal data export email.' ) );
	}

	// Localize message content for user; fallback to site default for visitors.
	if ( ! empty( $request->user_id ) ) {
		$switched_locale = switch_to_user_locale( $request->user_id );
	} else {
		$switched_locale = switch_to_locale( get_locale() );
	}

	/** This filter is documented in wp-includes/functions.php */
	$expiration      = apply_filters( 'wp_privacy_export_expiration', 3 * DAY_IN_SECONDS );
	$expiration_date = date_i18n( get_option( 'date_format' ), time() + $expiration );

	$exports_url      = wp_privacy_exports_url();
	$export_file_name = get_post_meta( $request_id, '_export_file_name', true );
	$export_file_url  = $exports_url . $export_file_name;

	$site_name = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
	$site_url  = home_url();

	/**
	 * Filters the recipient of the personal data export email notification.
	 * Should be used with great caution to avoid sending the data export link to the wrong email.
	 *
	 * @since 5.3.0
	 *
	 * @param string          $request_email The email address of the notification recipient.
	 * @param WP_User_Request $request       The request that is initiating the notification.
	 */
	$request_email = apply_filters( 'wp_privacy_personal_data_email_to', $request->email, $request );

	$email_data = array(
		'request'           => $request,
		'expiration'        => $expiration,
		'expiration_date'   => $expiration_date,
		'message_recipient' => $request_email,
		'export_file_url'   => $export_file_url,
		'sitename'          => $site_name,
		'siteurl'           => $site_url,
	);

	/* translators: Personal data export notification email subject. %s: Site title. */
	$subject = sprintf( __( '[%s] Personal Data Export' ), $site_name );

	/**
	 * Filters the subject of the email sent when an export request is completed.
	 *
	 * @since 5.3.0
	 *
	 * @param string $subject    The email subject.
	 * @param string $sitename   The name of the site.
	 * @param array  $email_data {
	 *     Data relating to the account action email.
	 *
	 *     @type WP_User_Request $request           User request object.
	 *     @type int             $expiration        The time in seconds until the export file expires.
	 *     @type string          $expiration_date   The localized date and time when the export file expires.
	 *     @type string          $message_recipient The address that the email will be sent to. Defaults
	 *                                              to the value of `$request->email`, but can be changed
	 *                                              by the `wp_privacy_personal_data_email_to` filter.
	 *     @type string          $export_file_url   The export file URL.
	 *     @type string          $sitename          The site name sending the mail.
	 *     @type string          $siteurl           The site URL sending the mail.
	 * }
	 */
	$subject = apply_filters( 'wp_privacy_personal_data_email_subject', $subject, $site_name, $email_data );

	/* translators: Do not translate EXPIRATION, LINK, SITENAME, SITEURL: those are placeholders. */
	$email_text = __(
		'Howdy,

Your request for an export of personal data has been completed. You may
download your personal data by clicking on the link below. For privacy
and security, we will automatically delete the file on ###EXPIRATION###,
so please download it before then.

###LINK###

Regards,
All at ###SITENAME###
###SITEURL###'
	);

	/**
	 * Filters the text of the email sent with a personal data export file.
	 *
	 * The following strings have a special meaning and will get replaced dynamically:
	 *
	 *  - `###EXPIRATION###` The date when the URL will be automatically deleted.
	 *  - `###LINK###`       URL of the personal data export file for the user.
	 *  - `###SITENAME###`   The name of the site.
	 *  - `###SITEURL###`    The URL to the site.
	 *
	 * @since 4.9.6
	 * @since 5.3.0 Introduced the `$email_data` array.
	 *
	 * @param string $email_text Text in the email.
	 * @param int    $request_id The request ID for this personal data export.
	 * @param array  $email_data {
	 *     Data relating to the account action email.
	 *
	 *     @type WP_User_Request $request           User request object.
	 *     @type int             $expiration        The time in seconds until the export file expires.
	 *     @type string          $expiration_date   The localized date and time when the export file expires.
	 *     @type string          $message_recipient The address that the email will be sent to. Defaults
	 *                                              to the value of `$request->email`, but can be changed
	 *                                              by the `wp_privacy_personal_data_email_to` filter.
	 *     @type string          $export_file_url   The export file URL.
	 *     @type string          $sitename          The site name sending the mail.
	 *     @type string          $siteurl           The site URL sending the mail.
	 */
	$content = apply_filters( 'wp_privacy_personal_data_email_content', $email_text, $request_id, $email_data );

	$content = str_replace( '###EXPIRATION###', $expiration_date, $content );
	$content = str_replace( '###LINK###', sanitize_url( $export_file_url ), $content );
	$content = str_replace( '###EMAIL###', $request_email, $content );
	$content = str_replace( '###SITENAME###', $site_name, $content );
	$content = str_replace( '###SITEURL###', sanitize_url( $site_url ), $content );

	$headers = '';

	/**
	 * Filters the headers of the email sent with a personal data export file.
	 *
	 * @since 5.4.0
	 *
	 * @param string|array $headers    The email headers.
	 * @param string       $subject    The email subject.
	 * @param string       $content    The email content.
	 * @param int          $request_id The request ID.
	 * @param array        $email_data {
	 *     Data relating to the account action email.
	 *
	 *     @type WP_User_Request $request           User request object.
	 *     @type int             $expiration        The time in seconds until the export file expires.
	 *     @type string          $expiration_date   The localized date and time when the export file expires.
	 *     @type string          $message_recipient The address that the email will be sent to. Defaults
	 *                                              to the value of `$request->email`, but can be changed
	 *                                              by the `wp_privacy_personal_data_email_to` filter.
	 *     @type string          $export_file_url   The export file URL.
	 *     @type string          $sitename          The site name sending the mail.
	 *     @type string          $siteurl           The site URL sending the mail.
	 * }
	 */
	$headers = apply_filters( 'wp_privacy_personal_data_email_headers', $headers, $subject, $content, $request_id, $email_data );

	$mail_success = wp_mail( $request_email, $subject, $content, $headers );

	if ( $switched_locale ) {
		restore_previous_locale();
	}

	if ( ! $mail_success ) {
		return new WP_Error( 'privacy_email_error', __( 'Unable to send personal data export email.' ) );
	}

	return true;
}

/**
 * Intercept personal data exporter page Ajax responses in order to assemble the personal data export file.
 *
 * @since 4.9.6
 *
 * @see 'wp_privacy_personal_data_export_page'
 *
 * @param array  $response        The response from the personal data exporter for the given page.
 * @param int    $exporter_index  The index of the personal data exporter. Begins at 1.
 * @param string $email_address   The email address of the user whose personal data this is.
 * @param int    $page            The page of personal data for this exporter. Begins at 1.
 * @param int    $request_id      The request ID for this personal data export.
 * @param bool   $send_as_email   Whether the final results of the export should be emailed to the user.
 * @param string $exporter_key    The slug (key) of the exporter.
 * @return array The filtered response.
 */
function wp_privacy_process_personal_data_export_page( $response, $exporter_index, $email_address, $page, $request_id, $send_as_email, $exporter_key ) {
	/* Do some simple checks on the shape of the response from the exporter.
	 * If the exporter response is malformed, don't attempt to consume it - let it
	 * pass through to generate a warning to the user by default Ajax processing.
	 */
	if ( ! is_array( $response ) ) {
		return $response;
	}

	if ( ! array_key_exists( 'done', $response ) ) {
		return $response;
	}

	if ( ! array_key_exists( 'data', $response ) ) {
		return $response;
	}

	if ( ! is_array( $response['data'] ) ) {
		return $response;
	}

	// Get the request.
	$request = wp_get_user_request( $request_id );

	if ( ! $request || 'export_personal_data' !== $request->action_name ) {
		wp_send_json_error( __( 'Invalid request ID when merging personal data to export.' ) );
	}

	$export_data = array();

	// First exporter, first page? Reset the report data accumulation array.
	if ( 1 === $exporter_index && 1 === $page ) {
		update_post_meta( $request_id, '_export_data_raw', $export_data );
	} else {
		$accumulated_data = get_post_meta( $request_id, '_export_data_raw', true );

		if ( $accumulated_data ) {
			$export_data = $accumulated_data;
		}
	}

	// Now, merge the data from the exporter response into the data we have accumulated already.
	$export_data = array_merge( $export_data, $response['data'] );
	update_post_meta( $request_id, '_export_data_raw', $export_data );

	// If we are not yet on the last page of the last exporter, return now.
	/** This filter is documented in wp-admin/includes/ajax-actions.php */
	$exporters        = apply_filters( 'wp_privacy_personal_data_exporters', array() );
	$is_last_exporter = count( $exporters ) === $exporter_index;
	$exporter_done    = $response['done'];
	if ( ! $is_last_exporter || ! $exporter_done ) {
		return $response;
	}

	// Last exporter, last page - let's prepare the export file.

	// First we need to re-organize the raw data hierarchically in groups and items.
	$groups = array();
	foreach ( (array) $export_data as $export_datum ) {
		$group_id    = $export_datum['group_id'];
		$group_label = $export_datum['group_label'];

		$group_description = '';
		if ( ! empty( $export_datum['group_description'] ) ) {
			$group_description = $export_datum['group_description'];
		}

		if ( ! array_key_exists( $group_id, $groups ) ) {
			$groups[ $group_id ] = array(
				'group_label'       => $group_label,
				'group_description' => $group_description,
				'items'             => array(),
			);
		}

		$item_id = $export_datum['item_id'];
		if ( ! array_key_exists( $item_id, $groups[ $group_id ]['items'] ) ) {
			$groups[ $group_id ]['items'][ $item_id ] = array();
		}

		$old_item_data                            = $groups[ $group_id ]['items'][ $item_id ];
		$merged_item_data                         = array_merge( $export_datum['data'], $old_item_data );
		$groups[ $group_id ]['items'][ $item_id ] = $merged_item_data;
	}

	// Then save the grouped data into the request.
	delete_post_meta( $request_id, '_export_data_raw' );
	update_post_meta( $request_id, '_export_data_grouped', $groups );

	/**
	 * Generate the export file from the collected, grouped personal data.
	 *
	 * @since 4.9.6
	 *
	 * @param int $request_id The export request ID.
	 */
	do_action( 'wp_privacy_personal_data_export_file', $request_id );

	// Clear the grouped data now that it is no longer needed.
	delete_post_meta( $request_id, '_export_data_grouped' );

	// If the destination is email, send it now.
	if ( $send_as_email ) {
		$mail_success = wp_privacy_send_personal_data_export_email( $request_id );
		if ( is_wp_error( $mail_success ) ) {
			wp_send_json_error( $mail_success->get_error_message() );
		}

		// Update the request to completed state when the export email is sent.
		_wp_privacy_completed_request( $request_id );
	} else {
		// Modify the response to include the URL of the export file so the browser can fetch it.
		$exports_url      = wp_privacy_exports_url();
		$export_file_name = get_post_meta( $request_id, '_export_file_name', true );
		$export_file_url  = $exports_url . $export_file_name;

		if ( ! empty( $export_file_url ) ) {
			$response['url'] = $export_file_url;
		}
	}

	return $response;
}

/**
 * Mark erasure requests as completed after processing is finished.
 *
 * This intercepts the Ajax responses to personal data eraser page requests, and
 * monitors the status of a request. Once all of the processing has finished, the
 * request is marked as completed.
 *
 * @since 4.9.6
 *
 * @see 'wp_privacy_personal_data_erasure_page'
 *
 * @param array  $response      The response from the personal data eraser for
 *                              the given page.
 * @param int    $eraser_index  The index of the personal data eraser. Begins
 *                              at 1.
 * @param string $email_address The email address of the user whose personal
 *                              data this is.
 * @param int    $page          The page of personal data for this eraser.
 *                              Begins at 1.
 * @param int    $request_id    The request ID for this personal data erasure.
 * @return array The filtered response.
 */
function wp_privacy_process_personal_data_erasure_page( $response, $eraser_index, $email_address, $page, $request_id ) {
	/*
	 * If the eraser response is malformed, don't attempt to consume it; let it
	 * pass through, so that the default Ajax processing will generate a warning
	 * to the user.
	 */
	if ( ! is_array( $response ) ) {
		return $response;
	}

	if ( ! array_key_exists( 'done', $response ) ) {
		return $response;
	}

	if ( ! array_key_exists( 'items_removed', $response ) ) {
		return $response;
	}

	if ( ! array_key_exists( 'items_retained', $response ) ) {
		return $response;
	}

	if ( ! array_key_exists( 'messages', $response ) ) {
		return $response;
	}

	// Get the request.
	$request = wp_get_user_request( $request_id );

	if ( ! $request || 'remove_personal_data' !== $request->action_name ) {
		wp_send_json_error( __( 'Invalid request ID when processing personal data to erase.' ) );
	}

	/** This filter is documented in wp-admin/includes/ajax-actions.php */
	$erasers        = apply_filters( 'wp_privacy_personal_data_erasers', array() );
	$is_last_eraser = count( $erasers ) === $eraser_index;
	$eraser_done    = $response['done'];

	if ( ! $is_last_eraser || ! $eraser_done ) {
		return $response;
	}

	_wp_privacy_completed_request( $request_id );

	/**
	 * Fires immediately after a personal data erasure request has been marked completed.
	 *
	 * @since 4.9.6
	 *
	 * @param int $request_id The privacy request post ID associated with this request.
	 */
	do_action( 'wp_privacy_personal_data_erased', $request_id );

	return $response;
}
class-language-pack-upgrader-skin.php000064400000005466151212616060013643 0ustar00<?php
/**
 * Upgrader API: Language_Pack_Upgrader_Skin class
 *
 * @package WordPress
 * @subpackage Upgrader
 * @since 4.6.0
 */

/**
 * Translation Upgrader Skin for WordPress Translation Upgrades.
 *
 * @since 3.7.0
 * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader-skins.php.
 *
 * @see WP_Upgrader_Skin
 */
class Language_Pack_Upgrader_Skin extends WP_Upgrader_Skin {
	public $language_update        = null;
	public $done_header            = false;
	public $done_footer            = false;
	public $display_footer_actions = true;

	/**
	 * Constructor.
	 *
	 * Sets up the language pack upgrader skin.
	 *
	 * @since 3.7.0
	 *
	 * @param array $args
	 */
	public function __construct( $args = array() ) {
		$defaults = array(
			'url'                => '',
			'nonce'              => '',
			'title'              => __( 'Update Translations' ),
			'skip_header_footer' => false,
		);
		$args     = wp_parse_args( $args, $defaults );
		if ( $args['skip_header_footer'] ) {
			$this->done_header            = true;
			$this->done_footer            = true;
			$this->display_footer_actions = false;
		}
		parent::__construct( $args );
	}

	/**
	 * Performs an action before a language pack update.
	 *
	 * @since 3.7.0
	 */
	public function before() {
		$name = $this->upgrader->get_name_for_update( $this->language_update );

		echo '<div class="update-messages lp-show-latest">';

		/* translators: 1: Project name (plugin, theme, or WordPress), 2: Language. */
		printf( '<h2>' . __( 'Updating translations for %1$s (%2$s)&#8230;' ) . '</h2>', $name, $this->language_update->language );
	}

	/**
	 * Displays an error message about the update.
	 *
	 * @since 3.7.0
	 * @since 5.9.0 Renamed `$error` to `$errors` for PHP 8 named parameter support.
	 *
	 * @param string|WP_Error $errors Errors.
	 */
	public function error( $errors ) {
		echo '<div class="lp-error">';
		parent::error( $errors );
		echo '</div>';
	}

	/**
	 * Performs an action following a language pack update.
	 *
	 * @since 3.7.0
	 */
	public function after() {
		echo '</div>';
	}

	/**
	 * Displays the footer following the bulk update process.
	 *
	 * @since 3.7.0
	 */
	public function bulk_footer() {
		$this->decrement_update_count( 'translation' );

		$update_actions = array(
			'updates_page' => sprintf(
				'<a href="%s" target="_parent">%s</a>',
				self_admin_url( 'update-core.php' ),
				__( 'Go to WordPress Updates page' )
			),
		);

		/**
		 * Filters the list of action links available following a translations update.
		 *
		 * @since 3.7.0
		 *
		 * @param string[] $update_actions Array of translations update links.
		 */
		$update_actions = apply_filters( 'update_translations_complete_actions', $update_actions );

		if ( $update_actions && $this->display_footer_actions ) {
			$this->feedback( implode( ' | ', $update_actions ) );
		}
	}
}
class-wp-privacy-requests-table.php000064400000034707151212616060013432 0ustar00<?php
/**
 * List Table API: WP_Privacy_Requests_Table class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 4.9.6
 */

abstract class WP_Privacy_Requests_Table extends WP_List_Table {

	/**
	 * Action name for the requests this table will work with. Classes
	 * which inherit from WP_Privacy_Requests_Table should define this.
	 *
	 * Example: 'export_personal_data'.
	 *
	 * @since 4.9.6
	 *
	 * @var string $request_type Name of action.
	 */
	protected $request_type = 'INVALID';

	/**
	 * Post type to be used.
	 *
	 * @since 4.9.6
	 *
	 * @var string $post_type The post type.
	 */
	protected $post_type = 'INVALID';

	/**
	 * Gets columns to show in the list table.
	 *
	 * @since 4.9.6
	 *
	 * @return string[] Array of column titles keyed by their column name.
	 */
	public function get_columns() {
		$columns = array(
			'cb'                => '<input type="checkbox" />',
			'email'             => __( 'Requester' ),
			'status'            => __( 'Status' ),
			'created_timestamp' => __( 'Requested' ),
			'next_steps'        => __( 'Next steps' ),
		);
		return $columns;
	}

	/**
	 * Normalizes the admin URL to the current page (by request_type).
	 *
	 * @since 5.3.0
	 *
	 * @return string URL to the current admin page.
	 */
	protected function get_admin_url() {
		$pagenow = str_replace( '_', '-', $this->request_type );

		if ( 'remove-personal-data' === $pagenow ) {
			$pagenow = 'erase-personal-data';
		}

		return admin_url( $pagenow . '.php' );
	}

	/**
	 * Gets a list of sortable columns.
	 *
	 * @since 4.9.6
	 *
	 * @return array Default sortable columns.
	 */
	protected function get_sortable_columns() {
		/*
		 * The initial sorting is by 'Requested' (post_date) and descending.
		 * With initial sorting, the first click on 'Requested' should be ascending.
		 * With 'Requester' sorting active, the next click on 'Requested' should be descending.
		 */
		$desc_first = isset( $_GET['orderby'] );

		return array(
			'email'             => 'requester',
			'created_timestamp' => array( 'requested', $desc_first ),
		);
	}

	/**
	 * Returns the default primary column.
	 *
	 * @since 4.9.6
	 *
	 * @return string Default primary column name.
	 */
	protected function get_default_primary_column_name() {
		return 'email';
	}

	/**
	 * Counts the number of requests for each status.
	 *
	 * @since 4.9.6
	 *
	 * @global wpdb $wpdb WordPress database abstraction object.
	 *
	 * @return object Number of posts for each status.
	 */
	protected function get_request_counts() {
		global $wpdb;

		$cache_key = $this->post_type . '-' . $this->request_type;
		$counts    = wp_cache_get( $cache_key, 'counts' );

		if ( false !== $counts ) {
			return $counts;
		}

		$results = (array) $wpdb->get_results(
			$wpdb->prepare(
				"SELECT post_status, COUNT( * ) AS num_posts
				FROM {$wpdb->posts}
				WHERE post_type = %s
				AND post_name = %s
				GROUP BY post_status",
				$this->post_type,
				$this->request_type
			),
			ARRAY_A
		);

		$counts = array_fill_keys( get_post_stati(), 0 );

		foreach ( $results as $row ) {
			$counts[ $row['post_status'] ] = $row['num_posts'];
		}

		$counts = (object) $counts;
		wp_cache_set( $cache_key, $counts, 'counts' );

		return $counts;
	}

	/**
	 * Gets an associative array ( id => link ) with the list of views available on this table.
	 *
	 * @since 4.9.6
	 *
	 * @return string[] An array of HTML links keyed by their view.
	 */
	protected function get_views() {
		$current_status = isset( $_REQUEST['filter-status'] ) ? sanitize_text_field( $_REQUEST['filter-status'] ) : '';
		$statuses       = _wp_privacy_statuses();
		$views          = array();
		$counts         = $this->get_request_counts();
		$total_requests = absint( array_sum( (array) $counts ) );

		// Normalized admin URL.
		$admin_url = $this->get_admin_url();

		$status_label = sprintf(
			/* translators: %s: Number of requests. */
			_nx(
				'All <span class="count">(%s)</span>',
				'All <span class="count">(%s)</span>',
				$total_requests,
				'requests'
			),
			number_format_i18n( $total_requests )
		);

		$views['all'] = array(
			'url'     => esc_url( $admin_url ),
			'label'   => $status_label,
			'current' => empty( $current_status ),
		);

		foreach ( $statuses as $status => $label ) {
			$post_status = get_post_status_object( $status );
			if ( ! $post_status ) {
				continue;
			}

			$total_status_requests = absint( $counts->{$status} );

			if ( ! $total_status_requests ) {
				continue;
			}

			$status_label = sprintf(
				translate_nooped_plural( $post_status->label_count, $total_status_requests ),
				number_format_i18n( $total_status_requests )
			);

			$status_link = add_query_arg( 'filter-status', $status, $admin_url );

			$views[ $status ] = array(
				'url'     => esc_url( $status_link ),
				'label'   => $status_label,
				'current' => $status === $current_status,
			);
		}

		return $this->get_views_links( $views );
	}

	/**
	 * Gets bulk actions.
	 *
	 * @since 4.9.6
	 *
	 * @return array Array of bulk action labels keyed by their action.
	 */
	protected function get_bulk_actions() {
		return array(
			'resend'   => __( 'Resend confirmation requests' ),
			'complete' => __( 'Mark requests as completed' ),
			'delete'   => __( 'Delete requests' ),
		);
	}

	/**
	 * Process bulk actions.
	 *
	 * @since 4.9.6
	 * @since 5.6.0 Added support for the `complete` action.
	 */
	public function process_bulk_action() {
		$action      = $this->current_action();
		$request_ids = isset( $_REQUEST['request_id'] ) ? wp_parse_id_list( wp_unslash( $_REQUEST['request_id'] ) ) : array();

		if ( empty( $request_ids ) ) {
			return;
		}

		$count    = 0;
		$failures = 0;

		check_admin_referer( 'bulk-privacy_requests' );

		switch ( $action ) {
			case 'resend':
				foreach ( $request_ids as $request_id ) {
					$resend = _wp_privacy_resend_request( $request_id );

					if ( $resend && ! is_wp_error( $resend ) ) {
						++$count;
					} else {
						++$failures;
					}
				}

				if ( $failures ) {
					add_settings_error(
						'bulk_action',
						'bulk_action',
						sprintf(
							/* translators: %d: Number of requests. */
							_n(
								'%d confirmation request failed to resend.',
								'%d confirmation requests failed to resend.',
								$failures
							),
							$failures
						),
						'error'
					);
				}

				if ( $count ) {
					add_settings_error(
						'bulk_action',
						'bulk_action',
						sprintf(
							/* translators: %d: Number of requests. */
							_n(
								'%d confirmation request re-sent successfully.',
								'%d confirmation requests re-sent successfully.',
								$count
							),
							$count
						),
						'success'
					);
				}

				break;

			case 'complete':
				foreach ( $request_ids as $request_id ) {
					$result = _wp_privacy_completed_request( $request_id );

					if ( $result && ! is_wp_error( $result ) ) {
						++$count;
					}
				}

				add_settings_error(
					'bulk_action',
					'bulk_action',
					sprintf(
						/* translators: %d: Number of requests. */
						_n(
							'%d request marked as complete.',
							'%d requests marked as complete.',
							$count
						),
						$count
					),
					'success'
				);
				break;

			case 'delete':
				foreach ( $request_ids as $request_id ) {
					if ( wp_delete_post( $request_id, true ) ) {
						++$count;
					} else {
						++$failures;
					}
				}

				if ( $failures ) {
					add_settings_error(
						'bulk_action',
						'bulk_action',
						sprintf(
							/* translators: %d: Number of requests. */
							_n(
								'%d request failed to delete.',
								'%d requests failed to delete.',
								$failures
							),
							$failures
						),
						'error'
					);
				}

				if ( $count ) {
					add_settings_error(
						'bulk_action',
						'bulk_action',
						sprintf(
							/* translators: %d: Number of requests. */
							_n(
								'%d request deleted successfully.',
								'%d requests deleted successfully.',
								$count
							),
							$count
						),
						'success'
					);
				}

				break;
		}
	}

	/**
	 * Prepares items to output.
	 *
	 * @since 4.9.6
	 * @since 5.1.0 Added support for column sorting.
	 */
	public function prepare_items() {
		$this->items    = array();
		$posts_per_page = $this->get_items_per_page( $this->request_type . '_requests_per_page' );
		$args           = array(
			'post_type'      => $this->post_type,
			'post_name__in'  => array( $this->request_type ),
			'posts_per_page' => $posts_per_page,
			'offset'         => isset( $_REQUEST['paged'] ) ? max( 0, absint( $_REQUEST['paged'] ) - 1 ) * $posts_per_page : 0,
			'post_status'    => 'any',
			's'              => isset( $_REQUEST['s'] ) ? sanitize_text_field( $_REQUEST['s'] ) : '',
		);

		$orderby_mapping = array(
			'requester' => 'post_title',
			'requested' => 'post_date',
		);

		if ( isset( $_REQUEST['orderby'] ) && isset( $orderby_mapping[ $_REQUEST['orderby'] ] ) ) {
			$args['orderby'] = $orderby_mapping[ $_REQUEST['orderby'] ];
		}

		if ( isset( $_REQUEST['order'] ) && in_array( strtoupper( $_REQUEST['order'] ), array( 'ASC', 'DESC' ), true ) ) {
			$args['order'] = strtoupper( $_REQUEST['order'] );
		}

		if ( ! empty( $_REQUEST['filter-status'] ) ) {
			$filter_status       = isset( $_REQUEST['filter-status'] ) ? sanitize_text_field( $_REQUEST['filter-status'] ) : '';
			$args['post_status'] = $filter_status;
		}

		$requests_query = new WP_Query( $args );
		$requests       = $requests_query->posts;

		foreach ( $requests as $request ) {
			$this->items[] = wp_get_user_request( $request->ID );
		}

		$this->items = array_filter( $this->items );

		$this->set_pagination_args(
			array(
				'total_items' => $requests_query->found_posts,
				'per_page'    => $posts_per_page,
			)
		);
	}

	/**
	 * Returns the markup for the Checkbox column.
	 *
	 * @since 4.9.6
	 *
	 * @param WP_User_Request $item Item being shown.
	 * @return string Checkbox column markup.
	 */
	public function column_cb( $item ) {
		return sprintf(
			'<input type="checkbox" name="request_id[]" id="requester_%1$s" value="%1$s" />' .
			'<label for="requester_%1$s"><span class="screen-reader-text">%2$s</span></label><span class="spinner"></span>',
			esc_attr( $item->ID ),
			/* translators: Hidden accessibility text. %s: Email address. */
			sprintf( __( 'Select %s' ), $item->email )
		);
	}

	/**
	 * Status column.
	 *
	 * @since 4.9.6
	 *
	 * @param WP_User_Request $item Item being shown.
	 * @return string|void Status column markup. Returns a string if no status is found,
	 *                     otherwise it displays the markup.
	 */
	public function column_status( $item ) {
		$status        = get_post_status( $item->ID );
		$status_object = get_post_status_object( $status );

		if ( ! $status_object || empty( $status_object->label ) ) {
			return '-';
		}

		$timestamp = false;

		switch ( $status ) {
			case 'request-confirmed':
				$timestamp = $item->confirmed_timestamp;
				break;
			case 'request-completed':
				$timestamp = $item->completed_timestamp;
				break;
		}

		echo '<span class="status-label status-' . esc_attr( $status ) . '">';
		echo esc_html( $status_object->label );

		if ( $timestamp ) {
			echo '<span class="status-date">' . $this->get_timestamp_as_date( $timestamp ) . '</span>';
		}

		echo '</span>';
	}

	/**
	 * Converts a timestamp for display.
	 *
	 * @since 4.9.6
	 *
	 * @param int $timestamp Event timestamp.
	 * @return string Human readable date.
	 */
	protected function get_timestamp_as_date( $timestamp ) {
		if ( empty( $timestamp ) ) {
			return '';
		}

		$time_diff = time() - $timestamp;

		if ( $time_diff >= 0 && $time_diff < DAY_IN_SECONDS ) {
			/* translators: %s: Human-readable time difference. */
			return sprintf( __( '%s ago' ), human_time_diff( $timestamp ) );
		}

		return sprintf(
			/* translators: 1: privacy request date format, 2: privacy request time format. */
			__( '%1$s at %2$s' ),
			/* translators: privacy request date format. See https://www.php.net/manual/en/datetime.format.php */
			date_i18n( __( 'Y/m/d' ), $timestamp ),
			/* translators: privacy request time format. See https://www.php.net/manual/en/datetime.format.php */
			date_i18n( __( 'g:i a' ), $timestamp )
		);
	}

	/**
	 * Handles the default column.
	 *
	 * @since 4.9.6
	 * @since 5.7.0 Added `manage_{$this->screen->id}_custom_column` action.
	 *
	 * @param WP_User_Request $item        Item being shown.
	 * @param string          $column_name Name of column being shown.
	 */
	public function column_default( $item, $column_name ) {
		/**
		 * Fires for each custom column of a specific request type in the Privacy Requests list table.
		 *
		 * Custom columns are registered using the {@see 'manage_export-personal-data_columns'}
		 * and the {@see 'manage_erase-personal-data_columns'} filters.
		 *
		 * The dynamic portion of the hook name, `$this->screen->id`, refers to the ID given to the list table
		 * according to which screen it's displayed on.
		 *
		 * Possible hook names include:
		 *
		 *  - `manage_export-personal-data_custom_column`
		 *  - `manage_erase-personal-data_custom_column`
		 *
		 * @since 5.7.0
		 *
		 * @param string          $column_name The name of the column to display.
		 * @param WP_User_Request $item        The item being shown.
		 */
		do_action( "manage_{$this->screen->id}_custom_column", $column_name, $item );
	}

	/**
	 * Returns the markup for the Created timestamp column. Overridden by children.
	 *
	 * @since 5.7.0
	 *
	 * @param WP_User_Request $item Item being shown.
	 * @return string Human readable date.
	 */
	public function column_created_timestamp( $item ) {
		return $this->get_timestamp_as_date( $item->created_timestamp );
	}

	/**
	 * Actions column. Overridden by children.
	 *
	 * @since 4.9.6
	 *
	 * @param WP_User_Request $item Item being shown.
	 * @return string Email column markup.
	 */
	public function column_email( $item ) {
		return sprintf( '<a href="%1$s">%2$s</a> %3$s', esc_url( 'mailto:' . $item->email ), $item->email, $this->row_actions( array() ) );
	}

	/**
	 * Returns the markup for the next steps column. Overridden by children.
	 *
	 * @since 4.9.6
	 *
	 * @param WP_User_Request $item Item being shown.
	 */
	public function column_next_steps( $item ) {}

	/**
	 * Generates content for a single row of the table,
	 *
	 * @since 4.9.6
	 *
	 * @param WP_User_Request $item The current item.
	 */
	public function single_row( $item ) {
		$status = $item->status;

		echo '<tr id="request-' . esc_attr( $item->ID ) . '" class="status-' . esc_attr( $status ) . '">';
		$this->single_row_columns( $item );
		echo '</tr>';
	}

	/**
	 * Embeds scripts used to perform actions. Overridden by children.
	 *
	 * @since 4.9.6
	 */
	public function embed_scripts() {}
}
class-core-upgrader.php000064400000035527151212616060011133 0ustar00<?php
/**
 * Upgrade API: Core_Upgrader class
 *
 * @package WordPress
 * @subpackage Upgrader
 * @since 4.6.0
 */

/**
 * Core class used for updating core.
 *
 * It allows for WordPress to upgrade itself in combination with
 * the wp-admin/includes/update-core.php file.
 *
 * Note: Newly introduced functions and methods cannot be used here.
 * All functions must be present in the previous version being upgraded from
 * as this file is used there too.
 *
 * @since 2.8.0
 * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader.php.
 *
 * @see WP_Upgrader
 */
class Core_Upgrader extends WP_Upgrader {

	/**
	 * Initializes the upgrade strings.
	 *
	 * @since 2.8.0
	 */
	public function upgrade_strings() {
		$this->strings['up_to_date'] = __( 'WordPress is at the latest version.' );
		$this->strings['locked']     = __( 'Another update is currently in progress.' );
		$this->strings['no_package'] = __( 'Update package not available.' );
		/* translators: %s: Package URL. */
		$this->strings['downloading_package']   = sprintf( __( 'Downloading update from %s&#8230;' ), '<span class="code pre">%s</span>' );
		$this->strings['unpack_package']        = __( 'Unpacking the update&#8230;' );
		$this->strings['copy_failed']           = __( 'Could not copy files.' );
		$this->strings['copy_failed_space']     = __( 'Could not copy files. You may have run out of disk space.' );
		$this->strings['start_rollback']        = __( 'Attempting to restore the previous version.' );
		$this->strings['rollback_was_required'] = __( 'Due to an error during updating, WordPress has been restored to your previous version.' );
	}

	/**
	 * Upgrades WordPress core.
	 *
	 * @since 2.8.0
	 *
	 * @global WP_Filesystem_Base $wp_filesystem                WordPress filesystem subclass.
	 * @global callable           $_wp_filesystem_direct_method
	 *
	 * @param object $current Response object for whether WordPress is current.
	 * @param array  $args {
	 *     Optional. Arguments for upgrading WordPress core. Default empty array.
	 *
	 *     @type bool $pre_check_md5    Whether to check the file checksums before
	 *                                  attempting the upgrade. Default true.
	 *     @type bool $attempt_rollback Whether to attempt to rollback the chances if
	 *                                  there is a problem. Default false.
	 *     @type bool $do_rollback      Whether to perform this "upgrade" as a rollback.
	 *                                  Default false.
	 * }
	 * @return string|false|WP_Error New WordPress version on success, false or WP_Error on failure.
	 */
	public function upgrade( $current, $args = array() ) {
		global $wp_filesystem;

		require ABSPATH . WPINC . '/version.php'; // $wp_version;

		$start_time = time();

		$defaults    = array(
			'pre_check_md5'                => true,
			'attempt_rollback'             => false,
			'do_rollback'                  => false,
			'allow_relaxed_file_ownership' => false,
		);
		$parsed_args = wp_parse_args( $args, $defaults );

		$this->init();
		$this->upgrade_strings();

		// Is an update available?
		if ( ! isset( $current->response ) || 'latest' === $current->response ) {
			return new WP_Error( 'up_to_date', $this->strings['up_to_date'] );
		}

		$res = $this->fs_connect( array( ABSPATH, WP_CONTENT_DIR ), $parsed_args['allow_relaxed_file_ownership'] );
		if ( ! $res || is_wp_error( $res ) ) {
			return $res;
		}

		$wp_dir = trailingslashit( $wp_filesystem->abspath() );

		$partial = true;
		if ( $parsed_args['do_rollback'] ) {
			$partial = false;
		} elseif ( $parsed_args['pre_check_md5'] && ! $this->check_files() ) {
			$partial = false;
		}

		/*
		 * If partial update is returned from the API, use that, unless we're doing
		 * a reinstallation. If we cross the new_bundled version number, then use
		 * the new_bundled zip. Don't though if the constant is set to skip bundled items.
		 * If the API returns a no_content zip, go with it. Finally, default to the full zip.
		 */
		if ( $parsed_args['do_rollback'] && $current->packages->rollback ) {
			$to_download = 'rollback';
		} elseif ( $current->packages->partial && 'reinstall' !== $current->response && $wp_version === $current->partial_version && $partial ) {
			$to_download = 'partial';
		} elseif ( $current->packages->new_bundled && version_compare( $wp_version, $current->new_bundled, '<' )
			&& ( ! defined( 'CORE_UPGRADE_SKIP_NEW_BUNDLED' ) || ! CORE_UPGRADE_SKIP_NEW_BUNDLED ) ) {
			$to_download = 'new_bundled';
		} elseif ( $current->packages->no_content ) {
			$to_download = 'no_content';
		} else {
			$to_download = 'full';
		}

		// Lock to prevent multiple Core Updates occurring.
		$lock = WP_Upgrader::create_lock( 'core_updater', 15 * MINUTE_IN_SECONDS );
		if ( ! $lock ) {
			return new WP_Error( 'locked', $this->strings['locked'] );
		}

		$download = $this->download_package( $current->packages->$to_download, false );

		/*
		 * Allow for signature soft-fail.
		 * WARNING: This may be removed in the future.
		 */
		if ( is_wp_error( $download ) && $download->get_error_data( 'softfail-filename' ) ) {
			// Output the failure error as a normal feedback, and not as an error:
			/** This filter is documented in wp-admin/includes/update-core.php */
			apply_filters( 'update_feedback', $download->get_error_message() );

			// Report this failure back to WordPress.org for debugging purposes.
			wp_version_check(
				array(
					'signature_failure_code' => $download->get_error_code(),
					'signature_failure_data' => $download->get_error_data(),
				)
			);

			// Pretend this error didn't happen.
			$download = $download->get_error_data( 'softfail-filename' );
		}

		if ( is_wp_error( $download ) ) {
			WP_Upgrader::release_lock( 'core_updater' );
			return $download;
		}

		$working_dir = $this->unpack_package( $download );
		if ( is_wp_error( $working_dir ) ) {
			WP_Upgrader::release_lock( 'core_updater' );
			return $working_dir;
		}

		// Copy update-core.php from the new version into place.
		if ( ! $wp_filesystem->copy( $working_dir . '/wordpress/wp-admin/includes/update-core.php', $wp_dir . 'wp-admin/includes/update-core.php', true ) ) {
			$wp_filesystem->delete( $working_dir, true );
			WP_Upgrader::release_lock( 'core_updater' );
			return new WP_Error( 'copy_failed_for_update_core_file', __( 'The update cannot be installed because some files could not be copied. This is usually due to inconsistent file permissions.' ), 'wp-admin/includes/update-core.php' );
		}
		$wp_filesystem->chmod( $wp_dir . 'wp-admin/includes/update-core.php', FS_CHMOD_FILE );

		wp_opcache_invalidate( ABSPATH . 'wp-admin/includes/update-core.php' );
		require_once ABSPATH . 'wp-admin/includes/update-core.php';

		if ( ! function_exists( 'update_core' ) ) {
			WP_Upgrader::release_lock( 'core_updater' );
			return new WP_Error( 'copy_failed_space', $this->strings['copy_failed_space'] );
		}

		$result = update_core( $working_dir, $wp_dir );

		// In the event of an issue, we may be able to roll back.
		if ( $parsed_args['attempt_rollback'] && $current->packages->rollback && ! $parsed_args['do_rollback'] ) {
			$try_rollback = false;
			if ( is_wp_error( $result ) ) {
				$error_code = $result->get_error_code();
				/*
				 * Not all errors are equal. These codes are critical: copy_failed__copy_dir,
				 * mkdir_failed__copy_dir, copy_failed__copy_dir_retry, and disk_full.
				 * do_rollback allows for update_core() to trigger a rollback if needed.
				 */
				if ( str_contains( $error_code, 'do_rollback' ) ) {
					$try_rollback = true;
				} elseif ( str_contains( $error_code, '__copy_dir' ) ) {
					$try_rollback = true;
				} elseif ( 'disk_full' === $error_code ) {
					$try_rollback = true;
				}
			}

			if ( $try_rollback ) {
				/** This filter is documented in wp-admin/includes/update-core.php */
				apply_filters( 'update_feedback', $result );

				/** This filter is documented in wp-admin/includes/update-core.php */
				apply_filters( 'update_feedback', $this->strings['start_rollback'] );

				$rollback_result = $this->upgrade( $current, array_merge( $parsed_args, array( 'do_rollback' => true ) ) );

				$original_result = $result;
				$result          = new WP_Error(
					'rollback_was_required',
					$this->strings['rollback_was_required'],
					(object) array(
						'update'   => $original_result,
						'rollback' => $rollback_result,
					)
				);
			}
		}

		/** This action is documented in wp-admin/includes/class-wp-upgrader.php */
		do_action(
			'upgrader_process_complete',
			$this,
			array(
				'action' => 'update',
				'type'   => 'core',
			)
		);

		// Clear the current updates.
		delete_site_transient( 'update_core' );

		if ( ! $parsed_args['do_rollback'] ) {
			$stats = array(
				'update_type'      => $current->response,
				'success'          => true,
				'fs_method'        => $wp_filesystem->method,
				'fs_method_forced' => defined( 'FS_METHOD' ) || has_filter( 'filesystem_method' ),
				'fs_method_direct' => ! empty( $GLOBALS['_wp_filesystem_direct_method'] ) ? $GLOBALS['_wp_filesystem_direct_method'] : '',
				'time_taken'       => time() - $start_time,
				'reported'         => $wp_version,
				'attempted'        => $current->version,
			);

			if ( is_wp_error( $result ) ) {
				$stats['success'] = false;
				// Did a rollback occur?
				if ( ! empty( $try_rollback ) ) {
					$stats['error_code'] = $original_result->get_error_code();
					$stats['error_data'] = $original_result->get_error_data();
					// Was the rollback successful? If not, collect its error too.
					$stats['rollback'] = ! is_wp_error( $rollback_result );
					if ( is_wp_error( $rollback_result ) ) {
						$stats['rollback_code'] = $rollback_result->get_error_code();
						$stats['rollback_data'] = $rollback_result->get_error_data();
					}
				} else {
					$stats['error_code'] = $result->get_error_code();
					$stats['error_data'] = $result->get_error_data();
				}
			}

			wp_version_check( $stats );
		}

		WP_Upgrader::release_lock( 'core_updater' );

		return $result;
	}

	/**
	 * Determines if this WordPress Core version should update to an offered version or not.
	 *
	 * @since 3.7.0
	 *
	 * @param string $offered_ver The offered version, of the format x.y.z.
	 * @return bool True if we should update to the offered version, otherwise false.
	 */
	public static function should_update_to_version( $offered_ver ) {
		require ABSPATH . WPINC . '/version.php'; // $wp_version; // x.y.z

		$current_branch = implode( '.', array_slice( preg_split( '/[.-]/', $wp_version ), 0, 2 ) ); // x.y
		$new_branch     = implode( '.', array_slice( preg_split( '/[.-]/', $offered_ver ), 0, 2 ) ); // x.y

		$current_is_development_version = (bool) strpos( $wp_version, '-' );

		// Defaults:
		$upgrade_dev   = get_site_option( 'auto_update_core_dev', 'enabled' ) === 'enabled';
		$upgrade_minor = get_site_option( 'auto_update_core_minor', 'enabled' ) === 'enabled';
		$upgrade_major = get_site_option( 'auto_update_core_major', 'unset' ) === 'enabled';

		// WP_AUTO_UPDATE_CORE = true (all), 'beta', 'rc', 'development', 'branch-development', 'minor', false.
		if ( defined( 'WP_AUTO_UPDATE_CORE' ) ) {
			if ( false === WP_AUTO_UPDATE_CORE ) {
				// Defaults to turned off, unless a filter allows it.
				$upgrade_dev   = false;
				$upgrade_minor = false;
				$upgrade_major = false;
			} elseif ( true === WP_AUTO_UPDATE_CORE
				|| in_array( WP_AUTO_UPDATE_CORE, array( 'beta', 'rc', 'development', 'branch-development' ), true )
			) {
				// ALL updates for core.
				$upgrade_dev   = true;
				$upgrade_minor = true;
				$upgrade_major = true;
			} elseif ( 'minor' === WP_AUTO_UPDATE_CORE ) {
				// Only minor updates for core.
				$upgrade_dev   = false;
				$upgrade_minor = true;
				$upgrade_major = false;
			}
		}

		// 1: If we're already on that version, not much point in updating?
		if ( $offered_ver === $wp_version ) {
			return false;
		}

		// 2: If we're running a newer version, that's a nope.
		if ( version_compare( $wp_version, $offered_ver, '>' ) ) {
			return false;
		}

		$failure_data = get_site_option( 'auto_core_update_failed' );
		if ( $failure_data ) {
			// If this was a critical update failure, cannot update.
			if ( ! empty( $failure_data['critical'] ) ) {
				return false;
			}

			// Don't claim we can update on update-core.php if we have a non-critical failure logged.
			if ( $wp_version === $failure_data['current'] && str_contains( $offered_ver, '.1.next.minor' ) ) {
				return false;
			}

			/*
			 * Cannot update if we're retrying the same A to B update that caused a non-critical failure.
			 * Some non-critical failures do allow retries, like download_failed.
			 * 3.7.1 => 3.7.2 resulted in files_not_writable, if we are still on 3.7.1 and still trying to update to 3.7.2.
			 */
			if ( empty( $failure_data['retry'] ) && $wp_version === $failure_data['current'] && $offered_ver === $failure_data['attempted'] ) {
				return false;
			}
		}

		// 3: 3.7-alpha-25000 -> 3.7-alpha-25678 -> 3.7-beta1 -> 3.7-beta2.
		if ( $current_is_development_version ) {

			/**
			 * Filters whether to enable automatic core updates for development versions.
			 *
			 * @since 3.7.0
			 *
			 * @param bool $upgrade_dev Whether to enable automatic updates for
			 *                          development versions.
			 */
			if ( ! apply_filters( 'allow_dev_auto_core_updates', $upgrade_dev ) ) {
				return false;
			}
			// Else fall through to minor + major branches below.
		}

		// 4: Minor in-branch updates (3.7.0 -> 3.7.1 -> 3.7.2 -> 3.7.4).
		if ( $current_branch === $new_branch ) {

			/**
			 * Filters whether to enable minor automatic core updates.
			 *
			 * @since 3.7.0
			 *
			 * @param bool $upgrade_minor Whether to enable minor automatic core updates.
			 */
			return apply_filters( 'allow_minor_auto_core_updates', $upgrade_minor );
		}

		// 5: Major version updates (3.7.0 -> 3.8.0 -> 3.9.1).
		if ( version_compare( $new_branch, $current_branch, '>' ) ) {

			/**
			 * Filters whether to enable major automatic core updates.
			 *
			 * @since 3.7.0
			 *
			 * @param bool $upgrade_major Whether to enable major automatic core updates.
			 */
			return apply_filters( 'allow_major_auto_core_updates', $upgrade_major );
		}

		// If we're not sure, we don't want it.
		return false;
	}

	/**
	 * Compares the disk file checksums against the expected checksums.
	 *
	 * @since 3.7.0
	 *
	 * @global string $wp_version       The WordPress version string.
	 * @global string $wp_local_package Locale code of the package.
	 *
	 * @return bool True if the checksums match, otherwise false.
	 */
	public function check_files() {
		global $wp_version, $wp_local_package;

		$checksums = get_core_checksums( $wp_version, isset( $wp_local_package ) ? $wp_local_package : 'en_US' );

		if ( ! is_array( $checksums ) ) {
			return false;
		}

		foreach ( $checksums as $file => $checksum ) {
			// Skip files which get updated.
			if ( str_starts_with( $file, 'wp-content' ) ) {
				continue;
			}
			if ( ! file_exists( ABSPATH . $file ) || md5_file( ABSPATH . $file ) !== $checksum ) {
				return false;
			}
		}

		return true;
	}
}
class-plugin-upgrader-skin.php000064400000006316151212616060012435 0ustar00<?php
/**
 * Upgrader API: Plugin_Upgrader_Skin class
 *
 * @package WordPress
 * @subpackage Upgrader
 * @since 4.6.0
 */

/**
 * Plugin Upgrader Skin for WordPress Plugin Upgrades.
 *
 * @since 2.8.0
 * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader-skins.php.
 *
 * @see WP_Upgrader_Skin
 */
class Plugin_Upgrader_Skin extends WP_Upgrader_Skin {

	/**
	 * Holds the plugin slug in the Plugin Directory.
	 *
	 * @since 2.8.0
	 *
	 * @var string
	 */
	public $plugin = '';

	/**
	 * Whether the plugin is active.
	 *
	 * @since 2.8.0
	 *
	 * @var bool
	 */
	public $plugin_active = false;

	/**
	 * Whether the plugin is active for the entire network.
	 *
	 * @since 2.8.0
	 *
	 * @var bool
	 */
	public $plugin_network_active = false;

	/**
	 * Constructor.
	 *
	 * Sets up the plugin upgrader skin.
	 *
	 * @since 2.8.0
	 *
	 * @param array $args Optional. The plugin upgrader skin arguments to
	 *                    override default options. Default empty array.
	 */
	public function __construct( $args = array() ) {
		$defaults = array(
			'url'    => '',
			'plugin' => '',
			'nonce'  => '',
			'title'  => __( 'Update Plugin' ),
		);
		$args     = wp_parse_args( $args, $defaults );

		$this->plugin = $args['plugin'];

		$this->plugin_active         = is_plugin_active( $this->plugin );
		$this->plugin_network_active = is_plugin_active_for_network( $this->plugin );

		parent::__construct( $args );
	}

	/**
	 * Performs an action following a single plugin update.
	 *
	 * @since 2.8.0
	 */
	public function after() {
		$this->plugin = $this->upgrader->plugin_info();
		if ( ! empty( $this->plugin ) && ! is_wp_error( $this->result ) && $this->plugin_active ) {
			// Currently used only when JS is off for a single plugin update?
			printf(
				'<iframe title="%s" style="border:0;overflow:hidden" width="100%%" height="170" src="%s"></iframe>',
				esc_attr__( 'Update progress' ),
				wp_nonce_url( 'update.php?action=activate-plugin&networkwide=' . $this->plugin_network_active . '&plugin=' . urlencode( $this->plugin ), 'activate-plugin_' . $this->plugin )
			);
		}

		$this->decrement_update_count( 'plugin' );

		$update_actions = array(
			'activate_plugin' => sprintf(
				'<a href="%s" target="_parent">%s</a>',
				wp_nonce_url( 'plugins.php?action=activate&amp;plugin=' . urlencode( $this->plugin ), 'activate-plugin_' . $this->plugin ),
				__( 'Activate Plugin' )
			),
			'plugins_page'    => sprintf(
				'<a href="%s" target="_parent">%s</a>',
				self_admin_url( 'plugins.php' ),
				__( 'Go to Plugins page' )
			),
		);

		if ( $this->plugin_active || ! $this->result || is_wp_error( $this->result ) || ! current_user_can( 'activate_plugin', $this->plugin ) ) {
			unset( $update_actions['activate_plugin'] );
		}

		/**
		 * Filters the list of action links available following a single plugin update.
		 *
		 * @since 2.7.0
		 *
		 * @param string[] $update_actions Array of plugin action links.
		 * @param string   $plugin         Path to the plugin file relative to the plugins directory.
		 */
		$update_actions = apply_filters( 'update_plugin_complete_actions', $update_actions, $this->plugin );

		if ( ! empty( $update_actions ) ) {
			$this->feedback( implode( ' | ', (array) $update_actions ) );
		}
	}
}
class-wp-links-list-table.php000064400000022031151212616060012160 0ustar00<?php
/**
 * List Table API: WP_Links_List_Table class
 *
 * @package WordPress
 * @subpackage Administration
 * @since 3.1.0
 */

/**
 * Core class used to implement displaying links in a list table.
 *
 * @since 3.1.0
 *
 * @see WP_List_Table
 */
class WP_Links_List_Table extends WP_List_Table {

	/**
	 * Constructor.
	 *
	 * @since 3.1.0
	 *
	 * @see WP_List_Table::__construct() for more information on default arguments.
	 *
	 * @param array $args An associative array of arguments.
	 */
	public function __construct( $args = array() ) {
		parent::__construct(
			array(
				'plural' => 'bookmarks',
				'screen' => isset( $args['screen'] ) ? $args['screen'] : null,
			)
		);
	}

	/**
	 * @return bool
	 */
	public function ajax_user_can() {
		return current_user_can( 'manage_links' );
	}

	/**
	 * @global int    $cat_id
	 * @global string $s
	 * @global string $orderby
	 * @global string $order
	 */
	public function prepare_items() {
		global $cat_id, $s, $orderby, $order;

		$cat_id  = ! empty( $_REQUEST['cat_id'] ) ? absint( $_REQUEST['cat_id'] ) : 0;
		$orderby = ! empty( $_REQUEST['orderby'] ) ? sanitize_text_field( $_REQUEST['orderby'] ) : '';
		$order   = ! empty( $_REQUEST['order'] ) ? sanitize_text_field( $_REQUEST['order'] ) : '';
		$s       = ! empty( $_REQUEST['s'] ) ? sanitize_text_field( $_REQUEST['s'] ) : '';

		$args = array(
			'hide_invisible' => 0,
			'hide_empty'     => 0,
		);

		if ( 'all' !== $cat_id ) {
			$args['category'] = $cat_id;
		}
		if ( ! empty( $s ) ) {
			$args['search'] = $s;
		}
		if ( ! empty( $orderby ) ) {
			$args['orderby'] = $orderby;
		}
		if ( ! empty( $order ) ) {
			$args['order'] = $order;
		}

		$this->items = get_bookmarks( $args );
	}

	/**
	 */
	public function no_items() {
		_e( 'No links found.' );
	}

	/**
	 * @return array
	 */
	protected function get_bulk_actions() {
		$actions           = array();
		$actions['delete'] = __( 'Delete' );

		return $actions;
	}

	/**
	 * @global int $cat_id
	 * @param string $which
	 */
	protected function extra_tablenav( $which ) {
		global $cat_id;

		if ( 'top' !== $which ) {
			return;
		}
		?>
		<div class="alignleft actions">
			<?php
			$dropdown_options = array(
				'selected'        => $cat_id,
				'name'            => 'cat_id',
				'taxonomy'        => 'link_category',
				'show_option_all' => get_taxonomy( 'link_category' )->labels->all_items,
				'hide_empty'      => true,
				'hierarchical'    => 1,
				'show_count'      => 0,
				'orderby'         => 'name',
			);

			echo '<label class="screen-reader-text" for="cat_id">' . get_taxonomy( 'link_category' )->labels->filter_by_item . '</label>';

			wp_dropdown_categories( $dropdown_options );

			submit_button( __( 'Filter' ), '', 'filter_action', false, array( 'id' => 'post-query-submit' ) );
			?>
		</div>
		<?php
	}

	/**
	 * @return string[] Array of column titles keyed by their column name.
	 */
	public function get_columns() {
		return array(
			'cb'         => '<input type="checkbox" />',
			'name'       => _x( 'Name', 'link name' ),
			'url'        => __( 'URL' ),
			'categories' => __( 'Categories' ),
			'rel'        => __( 'Relationship' ),
			'visible'    => __( 'Visible' ),
			'rating'     => __( 'Rating' ),
		);
	}

	/**
	 * @return array
	 */
	protected function get_sortable_columns() {
		return array(
			'name'    => array( 'name', false, _x( 'Name', 'link name' ), __( 'Table ordered by Name.' ), 'asc' ),
			'url'     => array( 'url', false, __( 'URL' ), __( 'Table ordered by URL.' ) ),
			'visible' => array( 'visible', false, __( 'Visible' ), __( 'Table ordered by Visibility.' ) ),
			'rating'  => array( 'rating', false, __( 'Rating' ), __( 'Table ordered by Rating.' ) ),
		);
	}

	/**
	 * Gets the name of the default primary column.
	 *
	 * @since 4.3.0
	 *
	 * @return string Name of the default primary column, in this case, 'name'.
	 */
	protected function get_default_primary_column_name() {
		return 'name';
	}

	/**
	 * Handles the checkbox column output.
	 *
	 * @since 4.3.0
	 * @since 5.9.0 Renamed `$link` to `$item` to match parent class for PHP 8 named parameter support.
	 *
	 * @param object $item The current link object.
	 */
	public function column_cb( $item ) {
		// Restores the more descriptive, specific name for use within this method.
		$link = $item;

		?>
		<input type="checkbox" name="linkcheck[]" id="cb-select-<?php echo $link->link_id; ?>" value="<?php echo esc_attr( $link->link_id ); ?>" />
		<label for="cb-select-<?php echo $link->link_id; ?>">
			<span class="screen-reader-text">
			<?php
			/* translators: Hidden accessibility text. %s: Link name. */
			printf( __( 'Select %s' ), $link->link_name );
			?>
			</span>
		</label>
		<?php
	}

	/**
	 * Handles the link name column output.
	 *
	 * @since 4.3.0
	 *
	 * @param object $link The current link object.
	 */
	public function column_name( $link ) {
		$edit_link = get_edit_bookmark_link( $link );
		printf(
			'<strong><a class="row-title" href="%s" aria-label="%s">%s</a></strong>',
			$edit_link,
			/* translators: %s: Link name. */
			esc_attr( sprintf( __( 'Edit &#8220;%s&#8221;' ), $link->link_name ) ),
			$link->link_name
		);
	}

	/**
	 * Handles the link URL column output.
	 *
	 * @since 4.3.0
	 *
	 * @param object $link The current link object.
	 */
	public function column_url( $link ) {
		$short_url = url_shorten( $link->link_url );
		echo "<a href='$link->link_url'>$short_url</a>";
	}

	/**
	 * Handles the link categories column output.
	 *
	 * @since 4.3.0
	 *
	 * @global int $cat_id
	 *
	 * @param object $link The current link object.
	 */
	public function column_categories( $link ) {
		global $cat_id;

		$cat_names = array();
		foreach ( $link->link_category as $category ) {
			$cat = get_term( $category, 'link_category', OBJECT, 'display' );
			if ( is_wp_error( $cat ) ) {
				echo $cat->get_error_message();
			}
			$cat_name = $cat->name;
			if ( (int) $cat_id !== $category ) {
				$cat_name = "<a href='link-manager.php?cat_id=$category'>$cat_name</a>";
			}
			$cat_names[] = $cat_name;
		}
		echo implode( ', ', $cat_names );
	}

	/**
	 * Handles the link relation column output.
	 *
	 * @since 4.3.0
	 *
	 * @param object $link The current link object.
	 */
	public function column_rel( $link ) {
		echo empty( $link->link_rel ) ? '<br />' : $link->link_rel;
	}

	/**
	 * Handles the link visibility column output.
	 *
	 * @since 4.3.0
	 *
	 * @param object $link The current link object.
	 */
	public function column_visible( $link ) {
		if ( 'Y' === $link->link_visible ) {
			_e( 'Yes' );
		} else {
			_e( 'No' );
		}
	}

	/**
	 * Handles the link rating column output.
	 *
	 * @since 4.3.0
	 *
	 * @param object $link The current link object.
	 */
	public function column_rating( $link ) {
		echo $link->link_rating;
	}

	/**
	 * Handles the default column output.
	 *
	 * @since 4.3.0
	 * @since 5.9.0 Renamed `$link` to `$item` to match parent class for PHP 8 named parameter support.
	 *
	 * @param object $item        Link object.
	 * @param string $column_name Current column name.
	 */
	public function column_default( $item, $column_name ) {
		// Restores the more descriptive, specific name for use within this method.
		$link = $item;

		/**
		 * Fires for each registered custom link column.
		 *
		 * @since 2.1.0
		 *
		 * @param string $column_name Name of the custom column.
		 * @param int    $link_id     Link ID.
		 */
		do_action( 'manage_link_custom_column', $column_name, $link->link_id );
	}

	/**
	 * Generates the list table rows.
	 *
	 * @since 3.1.0
	 */
	public function display_rows() {
		foreach ( $this->items as $link ) {
			$link                = sanitize_bookmark( $link );
			$link->link_name     = esc_attr( $link->link_name );
			$link->link_category = wp_get_link_cats( $link->link_id );
			?>
		<tr id="link-<?php echo $link->link_id; ?>">
			<?php $this->single_row_columns( $link ); ?>
		</tr>
			<?php
		}
	}

	/**
	 * Generates and displays row action links.
	 *
	 * @since 4.3.0
	 * @since 5.9.0 Renamed `$link` to `$item` to match parent class for PHP 8 named parameter support.
	 *
	 * @param object $item        Link being acted upon.
	 * @param string $column_name Current column name.
	 * @param string $primary     Primary column name.
	 * @return string Row actions output for links, or an empty string
	 *                if the current column is not the primary column.
	 */
	protected function handle_row_actions( $item, $column_name, $primary ) {
		if ( $primary !== $column_name ) {
			return '';
		}

		// Restores the more descriptive, specific name for use within this method.
		$link = $item;

		$edit_link = get_edit_bookmark_link( $link );

		$actions           = array();
		$actions['edit']   = '<a href="' . $edit_link . '">' . __( 'Edit' ) . '</a>';
		$actions['delete'] = sprintf(
			'<a class="submitdelete" href="%s" onclick="return confirm( \'%s\' );">%s</a>',
			wp_nonce_url( "link.php?action=delete&amp;link_id=$link->link_id", 'delete-bookmark_' . $link->link_id ),
			/* translators: %s: Link name. */
			esc_js( sprintf( __( "You are about to delete this link '%s'\n  'Cancel' to stop, 'OK' to delete." ), $link->link_name ) ),
			__( 'Delete' )
		);

		return $this->row_actions( $actions );
	}
}
class-ftp-pure.php000064400000012462151212616060010127 0ustar00<?php
/**
 * PemFTP - An Ftp implementation in pure PHP
 *
 * @package PemFTP
 * @since 2.5.0
 *
 * @version 1.0
 * @copyright Alexey Dotsenko
 * @author Alexey Dotsenko
 * @link https://www.phpclasses.org/package/1743-PHP-FTP-client-in-pure-PHP.html
 * @license LGPL https://opensource.org/licenses/lgpl-license.html
 */

/**
 * FTP implementation using fsockopen to connect.
 *
 * @package PemFTP
 * @subpackage Pure
 * @since 2.5.0
 *
 * @version 1.0
 * @copyright Alexey Dotsenko
 * @author Alexey Dotsenko
 * @link https://www.phpclasses.org/package/1743-PHP-FTP-client-in-pure-PHP.html
 * @license LGPL https://opensource.org/licenses/lgpl-license.html
 */
class ftp_pure extends ftp_base {

	function __construct($verb=FALSE, $le=FALSE) {
		parent::__construct(false, $verb, $le);
	}

// <!-- --------------------------------------------------------------------------------------- -->
// <!--       Private functions                                                                 -->
// <!-- --------------------------------------------------------------------------------------- -->

	function _settimeout($sock) {
		if(!@stream_set_timeout($sock, $this->_timeout)) {
			$this->PushError('_settimeout','socket set send timeout');
			$this->_quit();
			return FALSE;
		}
		return TRUE;
	}

	function _connect($host, $port) {
		$this->SendMSG("Creating socket");
		$sock = @fsockopen($host, $port, $errno, $errstr, $this->_timeout);
		if (!$sock) {
			$this->PushError('_connect','socket connect failed', $errstr." (".$errno.")");
			return FALSE;
		}
		$this->_connected=true;
		return $sock;
	}

	function _readmsg($fnction="_readmsg"){
		if(!$this->_connected) {
			$this->PushError($fnction, 'Connect first');
			return FALSE;
		}
		$result=true;
		$this->_message="";
		$this->_code=0;
		$go=true;
		do {
			$tmp=@fgets($this->_ftp_control_sock, 512);
			if($tmp===false) {
				$go=$result=false;
				$this->PushError($fnction,'Read failed');
			} else {
				$this->_message.=$tmp;
				if(preg_match("/^([0-9]{3})(-(.*[".CRLF."]{1,2})+\\1)? [^".CRLF."]+[".CRLF."]{1,2}$/", $this->_message, $regs)) $go=false;
			}
		} while($go);
		if($this->LocalEcho) echo "GET < ".rtrim($this->_message, CRLF).CRLF;
		$this->_code=(int)$regs[1];
		return $result;
	}

	function _exec($cmd, $fnction="_exec") {
		if(!$this->_ready) {
			$this->PushError($fnction,'Connect first');
			return FALSE;
		}
		if($this->LocalEcho) echo "PUT > ",$cmd,CRLF;
		$status=@fputs($this->_ftp_control_sock, $cmd.CRLF);
		if($status===false) {
			$this->PushError($fnction,'socket write failed');
			return FALSE;
		}
		$this->_lastaction=time();
		if(!$this->_readmsg($fnction)) return FALSE;
		return TRUE;
	}

	function _data_prepare($mode=FTP_ASCII) {
		if(!$this->_settype($mode)) return FALSE;
		if($this->_passive) {
			if(!$this->_exec("PASV", "pasv")) {
				$this->_data_close();
				return FALSE;
			}
			if(!$this->_checkCode()) {
				$this->_data_close();
				return FALSE;
			}
			$ip_port = explode(",", preg_replace("/^.+ \\(?([0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]+,[0-9]+)\\)?.*$/s", "\\1", $this->_message));
			$this->_datahost=$ip_port[0].".".$ip_port[1].".".$ip_port[2].".".$ip_port[3];
            $this->_dataport=(((int)$ip_port[4])<<8) + ((int)$ip_port[5]);
			$this->SendMSG("Connecting to ".$this->_datahost.":".$this->_dataport);
			$this->_ftp_data_sock=@fsockopen($this->_datahost, $this->_dataport, $errno, $errstr, $this->_timeout);
			if(!$this->_ftp_data_sock) {
				$this->PushError("_data_prepare","fsockopen fails", $errstr." (".$errno.")");
				$this->_data_close();
				return FALSE;
			}
			else $this->_ftp_data_sock;
		} else {
			$this->SendMSG("Only passive connections available!");
			return FALSE;
		}
		return TRUE;
	}

	function _data_read($mode=FTP_ASCII, $fp=NULL) {
		if(is_resource($fp)) $out=0;
		else $out="";
		if(!$this->_passive) {
			$this->SendMSG("Only passive connections available!");
			return FALSE;
		}
		while (!feof($this->_ftp_data_sock)) {
			$block=fread($this->_ftp_data_sock, $this->_ftp_buff_size);
			if($mode!=FTP_BINARY) $block=preg_replace("/\r\n|\r|\n/", $this->_eol_code[$this->OS_local], $block);
			if(is_resource($fp)) $out+=fwrite($fp, $block, strlen($block));
			else $out.=$block;
		}
		return $out;
	}

	function _data_write($mode=FTP_ASCII, $fp=NULL) {
		if(is_resource($fp)) $out=0;
		else $out="";
		if(!$this->_passive) {
			$this->SendMSG("Only passive connections available!");
			return FALSE;
		}
		if(is_resource($fp)) {
			while(!feof($fp)) {
				$block=fread($fp, $this->_ftp_buff_size);
				if(!$this->_data_write_block($mode, $block)) return false;
			}
		} elseif(!$this->_data_write_block($mode, $fp)) return false;
		return TRUE;
	}

	function _data_write_block($mode, $block) {
		if($mode!=FTP_BINARY) $block=preg_replace("/\r\n|\r|\n/", $this->_eol_code[$this->OS_remote], $block);
		do {
			if(($t=@fwrite($this->_ftp_data_sock, $block))===FALSE) {
				$this->PushError("_data_write","Can't write to socket");
				return FALSE;
			}
			$block=substr($block, $t);
		} while(!empty($block));
		return true;
	}

	function _data_close() {
		@fclose($this->_ftp_data_sock);
		$this->SendMSG("Disconnected data from remote host");
		return TRUE;
	}

	function _quit($force=FALSE) {
		if($this->_connected or $force) {
			@fclose($this->_ftp_control_sock);
			$this->_connected=false;
			$this->SendMSG("Socket closed");
		}
	}
}

?>
class-language-pack-upgrader.php000064400000036311151212616060012672 0ustar00<?php
/**
 * Upgrade API: Language_Pack_Upgrader class
 *
 * @package WordPress
 * @subpackage Upgrader
 * @since 4.6.0
 */

/**
 * Core class used for updating/installing language packs (translations)
 * for plugins, themes, and core.
 *
 * @since 3.7.0
 * @since 4.6.0 Moved to its own file from wp-admin/includes/class-wp-upgrader.php.
 *
 * @see WP_Upgrader
 */
class Language_Pack_Upgrader extends WP_Upgrader {

	/**
	 * Result of the language pack upgrade.
	 *
	 * @since 3.7.0
	 * @var array|WP_Error $result
	 * @see WP_Upgrader::$result
	 */
	public $result;

	/**
	 * Whether a bulk upgrade/installation is being performed.
	 *
	 * @since 3.7.0
	 * @var bool $bulk
	 */
	public $bulk = true;

	/**
	 * Asynchronously upgrades language packs after other upgrades have been made.
	 *
	 * Hooked to the {@see 'upgrader_process_complete'} action by default.
	 *
	 * @since 3.7.0
	 *
	 * @param false|WP_Upgrader $upgrader Optional. WP_Upgrader instance or false. If `$upgrader` is
	 *                                    a Language_Pack_Upgrader instance, the method will bail to
	 *                                    avoid recursion. Otherwise unused. Default false.
	 */
	public static function async_upgrade( $upgrader = false ) {
		// Avoid recursion.
		if ( $upgrader && $upgrader instanceof Language_Pack_Upgrader ) {
			return;
		}

		// Nothing to do?
		$language_updates = wp_get_translation_updates();
		if ( ! $language_updates ) {
			return;
		}

		/*
		 * Avoid messing with VCS installations, at least for now.
		 * Noted: this is not the ideal way to accomplish this.
		 */
		$check_vcs = new WP_Automatic_Updater();
		if ( $check_vcs->is_vcs_checkout( WP_CONTENT_DIR ) ) {
			return;
		}

		foreach ( $language_updates as $key => $language_update ) {
			$update = ! empty( $language_update->autoupdate );

			/**
			 * Filters whether to asynchronously update translation for core, a plugin, or a theme.
			 *
			 * @since 4.0.0
			 *
			 * @param bool   $update          Whether to update.
			 * @param object $language_update The update offer.
			 */
			$update = apply_filters( 'async_update_translation', $update, $language_update );

			if ( ! $update ) {
				unset( $language_updates[ $key ] );
			}
		}

		if ( empty( $language_updates ) ) {
			return;
		}

		// Re-use the automatic upgrader skin if the parent upgrader is using it.
		if ( $upgrader && $upgrader->skin instanceof Automatic_Upgrader_Skin ) {
			$skin = $upgrader->skin;
		} else {
			$skin = new Language_Pack_Upgrader_Skin(
				array(
					'skip_header_footer' => true,
				)
			);
		}

		$lp_upgrader = new Language_Pack_Upgrader( $skin );
		$lp_upgrader->bulk_upgrade( $language_updates );
	}

	/**
	 * Initializes the upgrade strings.
	 *
	 * @since 3.7.0
	 */
	public function upgrade_strings() {
		$this->strings['starting_upgrade'] = __( 'Some of your translations need updating. Sit tight for a few more seconds while they are updated as well.' );
		$this->strings['up_to_date']       = __( 'Your translations are all up to date.' );
		$this->strings['no_package']       = __( 'Update package not available.' );
		/* translators: %s: Package URL. */
		$this->strings['downloading_package'] = sprintf( __( 'Downloading translation from %s&#8230;' ), '<span class="code pre">%s</span>' );
		$this->strings['unpack_package']      = __( 'Unpacking the update&#8230;' );
		$this->strings['process_failed']      = __( 'Translation update failed.' );
		$this->strings['process_success']     = __( 'Translation updated successfully.' );
		$this->strings['remove_old']          = __( 'Removing the old version of the translation&#8230;' );
		$this->strings['remove_old_failed']   = __( 'Could not remove the old translation.' );
	}

	/**
	 * Upgrades a language pack.
	 *
	 * @since 3.7.0
	 *
	 * @param string|false $update Optional. Whether an update offer is available. Default false.
	 * @param array        $args   Optional. Other optional arguments, see
	 *                             Language_Pack_Upgrader::bulk_upgrade(). Default empty array.
	 * @return array|bool|WP_Error The result of the upgrade, or a WP_Error object instead.
	 */
	public function upgrade( $update = false, $args = array() ) {
		if ( $update ) {
			$update = array( $update );
		}

		$results = $this->bulk_upgrade( $update, $args );

		if ( ! is_array( $results ) ) {
			return $results;
		}

		return $results[0];
	}

	/**
	 * Upgrades several language packs at once.
	 *
	 * @since 3.7.0
	 *
	 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
	 *
	 * @param object[] $language_updates Optional. Array of language packs to update. See {@see wp_get_translation_updates()}.
	 *                                   Default empty array.
	 * @param array    $args {
	 *     Other arguments for upgrading multiple language packs. Default empty array.
	 *
	 *     @type bool $clear_update_cache Whether to clear the update cache when done.
	 *                                    Default true.
	 * }
	 * @return array|bool|WP_Error Will return an array of results, or true if there are no updates,
	 *                             false or WP_Error for initial errors.
	 */
	public function bulk_upgrade( $language_updates = array(), $args = array() ) {
		global $wp_filesystem;

		$defaults    = array(
			'clear_update_cache' => true,
		);
		$parsed_args = wp_parse_args( $args, $defaults );

		$this->init();
		$this->upgrade_strings();

		if ( ! $language_updates ) {
			$language_updates = wp_get_translation_updates();
		}

		if ( empty( $language_updates ) ) {
			$this->skin->header();
			$this->skin->set_result( true );
			$this->skin->feedback( 'up_to_date' );
			$this->skin->bulk_footer();
			$this->skin->footer();
			return true;
		}

		if ( 'upgrader_process_complete' === current_filter() ) {
			$this->skin->feedback( 'starting_upgrade' );
		}

		// Remove any existing upgrade filters from the plugin/theme upgraders #WP29425 & #WP29230.
		remove_all_filters( 'upgrader_pre_install' );
		remove_all_filters( 'upgrader_clear_destination' );
		remove_all_filters( 'upgrader_post_install' );
		remove_all_filters( 'upgrader_source_selection' );

		add_filter( 'upgrader_source_selection', array( $this, 'check_package' ), 10, 2 );

		$this->skin->header();

		// Connect to the filesystem first.
		$res = $this->fs_connect( array( WP_CONTENT_DIR, WP_LANG_DIR ) );
		if ( ! $res ) {
			$this->skin->footer();
			return false;
		}

		$results = array();

		$this->update_count   = count( $language_updates );
		$this->update_current = 0;

		/*
		 * The filesystem's mkdir() is not recursive. Make sure WP_LANG_DIR exists,
		 * as we then may need to create a /plugins or /themes directory inside of it.
		 */
		$remote_destination = $wp_filesystem->find_folder( WP_LANG_DIR );
		if ( ! $wp_filesystem->exists( $remote_destination ) ) {
			if ( ! $wp_filesystem->mkdir( $remote_destination, FS_CHMOD_DIR ) ) {
				return new WP_Error( 'mkdir_failed_lang_dir', $this->strings['mkdir_failed'], $remote_destination );
			}
		}

		$language_updates_results = array();

		foreach ( $language_updates as $language_update ) {

			$this->skin->language_update = $language_update;

			$destination = WP_LANG_DIR;
			if ( 'plugin' === $language_update->type ) {
				$destination .= '/plugins';
			} elseif ( 'theme' === $language_update->type ) {
				$destination .= '/themes';
			}

			++$this->update_current;

			$options = array(
				'package'                     => $language_update->package,
				'destination'                 => $destination,
				'clear_destination'           => true,
				'abort_if_destination_exists' => false, // We expect the destination to exist.
				'clear_working'               => true,
				'is_multi'                    => true,
				'hook_extra'                  => array(
					'language_update_type' => $language_update->type,
					'language_update'      => $language_update,
				),
			);

			$result = $this->run( $options );

			$results[] = $this->result;

			// Prevent credentials auth screen from displaying multiple times.
			if ( false === $result ) {
				break;
			}

			$language_updates_results[] = array(
				'language' => $language_update->language,
				'type'     => $language_update->type,
				'slug'     => isset( $language_update->slug ) ? $language_update->slug : 'default',
				'version'  => $language_update->version,
			);
		}

		// Remove upgrade hooks which are not required for translation updates.
		remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
		remove_action( 'upgrader_process_complete', 'wp_version_check' );
		remove_action( 'upgrader_process_complete', 'wp_update_plugins' );
		remove_action( 'upgrader_process_complete', 'wp_update_themes' );

		/** This action is documented in wp-admin/includes/class-wp-upgrader.php */
		do_action(
			'upgrader_process_complete',
			$this,
			array(
				'action'       => 'update',
				'type'         => 'translation',
				'bulk'         => true,
				'translations' => $language_updates_results,
			)
		);

		// Re-add upgrade hooks.
		add_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
		add_action( 'upgrader_process_complete', 'wp_version_check', 10, 0 );
		add_action( 'upgrader_process_complete', 'wp_update_plugins', 10, 0 );
		add_action( 'upgrader_process_complete', 'wp_update_themes', 10, 0 );

		$this->skin->bulk_footer();

		$this->skin->footer();

		// Clean up our hooks, in case something else does an upgrade on this connection.
		remove_filter( 'upgrader_source_selection', array( $this, 'check_package' ) );

		if ( $parsed_args['clear_update_cache'] ) {
			wp_clean_update_cache();
		}

		return $results;
	}

	/**
	 * Checks that the package source contains .mo and .po files.
	 *
	 * Hooked to the {@see 'upgrader_source_selection'} filter by
	 * Language_Pack_Upgrader::bulk_upgrade().
	 *
	 * @since 3.7.0
	 *
	 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
	 *
	 * @param string|WP_Error $source        The path to the downloaded package source.
	 * @param string          $remote_source Remote file source location.
	 * @return string|WP_Error The source as passed, or a WP_Error object on failure.
	 */
	public function check_package( $source, $remote_source ) {
		global $wp_filesystem;

		if ( is_wp_error( $source ) ) {
			return $source;
		}

		// Check that the folder contains a valid language.
		$files = $wp_filesystem->dirlist( $remote_source );

		// Check to see if the expected files exist in the folder.
		$po  = false;
		$mo  = false;
		$php = false;
		foreach ( (array) $files as $file => $filedata ) {
			if ( str_ends_with( $file, '.po' ) ) {
				$po = true;
			} elseif ( str_ends_with( $file, '.mo' ) ) {
				$mo = true;
			} elseif ( str_ends_with( $file, '.l10n.php' ) ) {
				$php = true;
			}
		}

		if ( $php ) {
			return $source;
		}

		if ( ! $mo || ! $po ) {
			return new WP_Error(
				'incompatible_archive_pomo',
				$this->strings['incompatible_archive'],
				sprintf(
					/* translators: 1: .po, 2: .mo, 3: .l10n.php */
					__( 'The language pack is missing either the %1$s, %2$s, or %3$s files.' ),
					'<code>.po</code>',
					'<code>.mo</code>',
					'<code>.l10n.php</code>'
				)
			);
		}

		return $source;
	}

	/**
	 * Gets the name of an item being updated.
	 *
	 * @since 3.7.0
	 *
	 * @param object $update The data for an update.
	 * @return string The name of the item being updated.
	 */
	public function get_name_for_update( $update ) {
		switch ( $update->type ) {
			case 'core':
				return 'WordPress'; // Not translated.

			case 'theme':
				$theme = wp_get_theme( $update->slug );
				if ( $theme->exists() ) {
					return $theme->get( 'Name' );
				}
				break;
			case 'plugin':
				$plugin_data = get_plugins( '/' . $update->slug );
				$plugin_data = reset( $plugin_data );
				if ( $plugin_data ) {
					return $plugin_data['Name'];
				}
				break;
		}
		return '';
	}

	/**
	 * Clears existing translations where this item is going to be installed into.
	 *
	 * @since 5.1.0
	 *
	 * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
	 *
	 * @param string $remote_destination The location on the remote filesystem to be cleared.
	 * @return bool|WP_Error True upon success, WP_Error on failure.
	 */
	public function clear_destination( $remote_destination ) {
		global $wp_filesystem;

		$language_update    = $this->skin->language_update;
		$language_directory = WP_LANG_DIR . '/'; // Local path for use with glob().

		if ( 'core' === $language_update->type ) {
			$files = array(
				$remote_destination . $language_update->language . '.po',
				$remote_destination . $language_update->language . '.mo',
				$remote_destination . $language_update->language . '.l10n.php',
				$remote_destination . 'admin-' . $language_update->language . '.po',
				$remote_destination . 'admin-' . $language_update->language . '.mo',
				$remote_destination . 'admin-' . $language_update->language . '.l10n.php',
				$remote_destination . 'admin-network-' . $language_update->language . '.po',
				$remote_destination . 'admin-network-' . $language_update->language . '.mo',
				$remote_destination . 'admin-network-' . $language_update->language . '.l10n.php',
				$remote_destination . 'continents-cities-' . $language_update->language . '.po',
				$remote_destination . 'continents-cities-' . $language_update->language . '.mo',
				$remote_destination . 'continents-cities-' . $language_update->language . '.l10n.php',
			);

			$json_translation_files = glob( $language_directory . $language_update->language . '-*.json' );
			if ( $json_translation_files ) {
				foreach ( $json_translation_files as $json_translation_file ) {
					$files[] = str_replace( $language_directory, $remote_destination, $json_translation_file );
				}
			}
		} else {
			$files = array(
				$remote_destination . $language_update->slug . '-' . $language_update->language . '.po',
				$remote_destination . $language_update->slug . '-' . $language_update->language . '.mo',
				$remote_destination . $language_update->slug . '-' . $language_update->language . '.l10n.php',
			);

			$language_directory     = $language_directory . $language_update->type . 's/';
			$json_translation_files = glob( $language_directory . $language_update->slug . '-' . $language_update->language . '-*.json' );
			if ( $json_translation_files ) {
				foreach ( $json_translation_files as $json_translation_file ) {
					$files[] = str_replace( $language_directory, $remote_destination, $json_translation_file );
				}
			}
		}

		$files = array_filter( $files, array( $wp_filesystem, 'exists' ) );

		// No files to delete.
		if ( ! $files ) {
			return true;
		}

		// Check all files are writable before attempting to clear the destination.
		$unwritable_files = array();

		// Check writability.
		foreach ( $files as $file ) {
			if ( ! $wp_filesystem->is_writable( $file ) ) {
				// Attempt to alter permissions to allow writes and try again.
				$wp_filesystem->chmod( $file, FS_CHMOD_FILE );
				if ( ! $wp_filesystem->is_writable( $file ) ) {
					$unwritable_files[] = $file;
				}
			}
		}

		if ( ! empty( $unwritable_files ) ) {
			return new WP_Error( 'files_not_writable', $this->strings['files_not_writable'], implode( ', ', $unwritable_files ) );
		}

		foreach ( $files as $file ) {
			if ( ! $wp_filesystem->delete( $file ) ) {
				return new WP_Error( 'remove_old_failed', $this->strings['remove_old_failed'] );
			}
		}

		return true;
	}
}
upgrade.php000064400000342462151212616060006717 0ustar00<?php
/**
 * WordPress Upgrade API
 *
 * Most of the functions are pluggable and can be overwritten.
 *
 * @package WordPress
 * @subpackage Administration
 */

/** Include user installation customization script. */
if ( file_exists( WP_CONTENT_DIR . '/install.php' ) ) {
	require WP_CONTENT_DIR . '/install.php';
}

/** WordPress Administration API */
require_once ABSPATH . 'wp-admin/includes/admin.php';

/** WordPress Schema API */
require_once ABSPATH . 'wp-admin/includes/schema.php';

if ( ! function_exists( 'wp_install' ) ) :
	/**
	 * Installs the site.
	 *
	 * Runs the required functions to set up and populate the database,
	 * including primary admin user and initial options.
	 *
	 * @since 2.1.0
	 *
	 * @param string $blog_title    Site title.
	 * @param string $user_name     User's username.
	 * @param string $user_email    User's email.
	 * @param bool   $is_public     Whether the site is public.
	 * @param string $deprecated    Optional. Not used.
	 * @param string $user_password Optional. User's chosen password. Default empty (random password).
	 * @param string $language      Optional. Language chosen. Default empty.
	 * @return array {
	 *     Data for the newly installed site.
	 *
	 *     @type string $url              The URL of the site.
	 *     @type int    $user_id          The ID of the site owner.
	 *     @type string $password         The password of the site owner, if their user account didn't already exist.
	 *     @type string $password_message The explanatory message regarding the password.
	 * }
	 */
	function wp_install(
		$blog_title,
		$user_name,
		$user_email,
		$is_public,
		$deprecated = '',
		#[\SensitiveParameter]
		$user_password = '',
		$language = ''
	) {
		if ( ! empty( $deprecated ) ) {
			_deprecated_argument( __FUNCTION__, '2.6.0' );
		}

		wp_check_mysql_version();
		wp_cache_flush();
		make_db_current_silent();

		/*
		 * Ensure update checks are delayed after installation.
		 *
		 * This prevents users being presented with a maintenance mode screen
		 * immediately after installation.
		 */
		wp_unschedule_hook( 'wp_version_check' );
		wp_unschedule_hook( 'wp_update_plugins' );
		wp_unschedule_hook( 'wp_update_themes' );

		wp_schedule_event( time() + HOUR_IN_SECONDS, 'twicedaily', 'wp_version_check' );
		wp_schedule_event( time() + ( 1.5 * HOUR_IN_SECONDS ), 'twicedaily', 'wp_update_plugins' );
		wp_schedule_event( time() + ( 2 * HOUR_IN_SECONDS ), 'twicedaily', 'wp_update_themes' );

		populate_options();
		populate_roles();

		update_option( 'blogname', $blog_title );
		update_option( 'admin_email', $user_email );
		update_option( 'blog_public', $is_public );

		// Freshness of site - in the future, this could get more specific about actions taken, perhaps.
		update_option( 'fresh_site', 1, false );

		if ( $language ) {
			update_option( 'WPLANG', $language );
		}

		$guessurl = wp_guess_url();

		update_option( 'siteurl', $guessurl );

		// If not a public site, don't ping.
		if ( ! $is_public ) {
			update_option( 'default_pingback_flag', 0 );
		}

		/*
		 * Create default user. If the user already exists, the user tables are
		 * being shared among sites. Just set the role in that case.
		 */
		$user_id        = username_exists( $user_name );
		$user_password  = trim( $user_password );
		$email_password = false;
		$user_created   = false;

		if ( ! $user_id && empty( $user_password ) ) {
			$user_password = wp_generate_password( 12, false );
			$message       = __( '<strong><em>Note that password</em></strong> carefully! It is a <em>random</em> password that was generated just for you.' );
			$user_id       = wp_create_user( $user_name, $user_password, $user_email );
			update_user_meta( $user_id, 'default_password_nag', true );
			$email_password = true;
			$user_created   = true;
		} elseif ( ! $user_id ) {
			// Password has been provided.
			$message      = '<em>' . __( 'Your chosen password.' ) . '</em>';
			$user_id      = wp_create_user( $user_name, $user_password, $user_email );
			$user_created = true;
		} else {
			$message = __( 'User already exists. Password inherited.' );
		}

		$user = new WP_User( $user_id );
		$user->set_role( 'administrator' );

		if ( $user_created ) {
			$user->user_url = $guessurl;
			wp_update_user( $user );
		}

		wp_install_defaults( $user_id );

		wp_install_maybe_enable_pretty_permalinks();

		flush_rewrite_rules();

		wp_new_blog_notification( $blog_title, $guessurl, $user_id, ( $email_password ? $user_password : __( 'The password you chose during installation.' ) ) );

		wp_cache_flush();

		/**
		 * Fires after a site is fully installed.
		 *
		 * @since 3.9.0
		 *
		 * @param WP_User $user The site owner.
		 */
		do_action( 'wp_install', $user );

		return array(
			'url'              => $guessurl,
			'user_id'          => $user_id,
			'password'         => $user_password,
			'password_message' => $message,
		);
	}
endif;

if ( ! function_exists( 'wp_install_defaults' ) ) :
	/**
	 * Creates the initial content for a newly-installed site.
	 *
	 * Adds the default "Uncategorized" category, the first post (with comment),
	 * first page, and default widgets for default theme for the current version.
	 *
	 * @since 2.1.0
	 *
	 * @global wpdb       $wpdb         WordPress database abstraction object.
	 * @global WP_Rewrite $wp_rewrite   WordPress rewrite component.
	 * @global string     $table_prefix The database table prefix.
	 *
	 * @param int $user_id User ID.
	 */
	function wp_install_defaults( $user_id ) {
		global $wpdb, $wp_rewrite, $table_prefix;

		// Default category.
		$cat_name = __( 'Uncategorized' );
		/* translators: Default category slug. */
		$cat_slug = sanitize_title( _x( 'Uncategorized', 'Default category slug' ) );

		$cat_id = 1;

		$wpdb->insert(
			$wpdb->terms,
			array(
				'term_id'    => $cat_id,
				'name'       => $cat_name,
				'slug'       => $cat_slug,
				'term_group' => 0,
			)
		);
		$wpdb->insert(
			$wpdb->term_taxonomy,
			array(
				'term_id'     => $cat_id,
				'taxonomy'    => 'category',
				'description' => '',
				'parent'      => 0,
				'count'       => 1,
			)
		);
		$cat_tt_id = $wpdb->insert_id;

		// First post.
		$now             = current_time( 'mysql' );
		$now_gmt         = current_time( 'mysql', true );
		$first_post_guid = get_option( 'home' ) . '/?p=1';

		if ( is_multisite() ) {
			$first_post = get_site_option( 'first_post' );

			if ( ! $first_post ) {
				$first_post = "<!-- wp:paragraph -->\n<p>" .
				/* translators: First post content. %s: Site link. */
				__( 'Welcome to %s. This is your first post. Edit or delete it, then start writing!' ) .
				"</p>\n<!-- /wp:paragraph -->";
			}

			$first_post = sprintf(
				$first_post,
				sprintf( '<a href="%s">%s</a>', esc_url( network_home_url() ), get_network()->site_name )
			);

			// Back-compat for pre-4.4.
			$first_post = str_replace( 'SITE_URL', esc_url( network_home_url() ), $first_post );
			$first_post = str_replace( 'SITE_NAME', get_network()->site_name, $first_post );
		} else {
			$first_post = "<!-- wp:paragraph -->\n<p>" .
			/* translators: First post content. %s: Site link. */
			__( 'Welcome to WordPress. This is your first post. Edit or delete it, then start writing!' ) .
			"</p>\n<!-- /wp:paragraph -->";
		}

		$wpdb->insert(
			$wpdb->posts,
			array(
				'post_author'           => $user_id,
				'post_date'             => $now,
				'post_date_gmt'         => $now_gmt,
				'post_content'          => $first_post,
				'post_excerpt'          => '',
				'post_title'            => __( 'Hello world!' ),
				/* translators: Default post slug. */
				'post_name'             => sanitize_title( _x( 'hello-world', 'Default post slug' ) ),
				'post_modified'         => $now,
				'post_modified_gmt'     => $now_gmt,
				'guid'                  => $first_post_guid,
				'comment_count'         => 1,
				'to_ping'               => '',
				'pinged'                => '',
				'post_content_filtered' => '',
			)
		);

		if ( is_multisite() ) {
			update_posts_count();
		}

		$wpdb->insert(
			$wpdb->term_relationships,
			array(
				'term_taxonomy_id' => $cat_tt_id,
				'object_id'        => 1,
			)
		);

		// Default comment.
		if ( is_multisite() ) {
			$first_comment_author = get_site_option( 'first_comment_author' );
			$first_comment_email  = get_site_option( 'first_comment_email' );
			$first_comment_url    = get_site_option( 'first_comment_url', network_home_url() );
			$first_comment        = get_site_option( 'first_comment' );
		}

		$first_comment_author = ! empty( $first_comment_author ) ? $first_comment_author : __( 'A WordPress Commenter' );
		$first_comment_email  = ! empty( $first_comment_email ) ? $first_comment_email : 'wapuu@wordpress.example';
		$first_comment_url    = ! empty( $first_comment_url ) ? $first_comment_url : esc_url( __( 'https://wordpress.org/' ) );
		$first_comment        = ! empty( $first_comment ) ? $first_comment : sprintf(
			/* translators: %s: Gravatar URL. */
			__(
				'Hi, this is a comment.
To get started with moderating, editing, and deleting comments, please visit the Comments screen in the dashboard.
Commenter avatars come from <a href="%s">Gravatar</a>.'
			),
			/* translators: The localized Gravatar URL. */
			esc_url( __( 'https://gravatar.com/' ) )
		);
		$wpdb->insert(
			$wpdb->comments,
			array(
				'comment_post_ID'      => 1,
				'comment_author'       => $first_comment_author,
				'comment_author_email' => $first_comment_email,
				'comment_author_url'   => $first_comment_url,
				'comment_date'         => $now,
				'comment_date_gmt'     => $now_gmt,
				'comment_content'      => $first_comment,
				'comment_type'         => 'comment',
			)
		);

		// First page.
		if ( is_multisite() ) {
			$first_page = get_site_option( 'first_page' );
		}

		if ( empty( $first_page ) ) {
			$first_page = "<!-- wp:paragraph -->\n<p>";
			/* translators: First page content. */
			$first_page .= __( "This is an example page. It's different from a blog post because it will stay in one place and will show up in your site navigation (in most themes). Most people start with an About page that introduces them to potential site visitors. It might say something like this:" );
			$first_page .= "</p>\n<!-- /wp:paragraph -->\n\n";

			$first_page .= "<!-- wp:quote -->\n<blockquote class=\"wp-block-quote\">\n<!-- wp:paragraph -->\n<p>";
			/* translators: First page content. */
			$first_page .= __( "Hi there! I'm a bike messenger by day, aspiring actor by night, and this is my website. I live in Los Angeles, have a great dog named Jack, and I like pi&#241;a coladas. (And gettin' caught in the rain.)" );
			$first_page .= "</p>\n<!-- /wp:paragraph -->\n</blockquote>\n<!-- /wp:quote -->\n\n";

			$first_page .= "<!-- wp:paragraph -->\n<p>";
			/* translators: First page content. */
			$first_page .= __( '...or something like this:' );
			$first_page .= "</p>\n<!-- /wp:paragraph -->\n\n";

			$first_page .= "<!-- wp:quote -->\n<blockquote class=\"wp-block-quote\">\n<!-- wp:paragraph -->\n<p>";
			/* translators: First page content. */
			$first_page .= __( 'The XYZ Doohickey Company was founded in 1971, and has been providing quality doohickeys to the public ever since. Located in Gotham City, XYZ employs over 2,000 people and does all kinds of awesome things for the Gotham community.' );
			$first_page .= "</p>\n<!-- /wp:paragraph -->\n</blockquote>\n<!-- /wp:quote -->\n\n";

			$first_page .= "<!-- wp:paragraph -->\n<p>";
			$first_page .= sprintf(
				/* translators: First page content. %s: Site admin URL. */
				__( 'As a new WordPress user, you should go to <a href="%s">your dashboard</a> to delete this page and create new pages for your content. Have fun!' ),
				admin_url()
			);
			$first_page .= "</p>\n<!-- /wp:paragraph -->";
		}

		$first_post_guid = get_option( 'home' ) . '/?page_id=2';
		$wpdb->insert(
			$wpdb->posts,
			array(
				'post_author'           => $user_id,
				'post_date'             => $now,
				'post_date_gmt'         => $now_gmt,
				'post_content'          => $first_page,
				'post_excerpt'          => '',
				'comment_status'        => 'closed',
				'post_title'            => __( 'Sample Page' ),
				/* translators: Default page slug. */
				'post_name'             => __( 'sample-page' ),
				'post_modified'         => $now,
				'post_modified_gmt'     => $now_gmt,
				'guid'                  => $first_post_guid,
				'post_type'             => 'page',
				'to_ping'               => '',
				'pinged'                => '',
				'post_content_filtered' => '',
			)
		);
		$wpdb->insert(
			$wpdb->postmeta,
			array(
				'post_id'    => 2,
				'meta_key'   => '_wp_page_template',
				'meta_value' => 'default',
			)
		);

		// Privacy Policy page.
		if ( is_multisite() ) {
			// Disable by default unless the suggested content is provided.
			$privacy_policy_content = get_site_option( 'default_privacy_policy_content' );
		} else {
			if ( ! class_exists( 'WP_Privacy_Policy_Content' ) ) {
				require_once ABSPATH . 'wp-admin/includes/class-wp-privacy-policy-content.php';
			}

			$privacy_policy_content = WP_Privacy_Policy_Content::get_default_content();
		}

		if ( ! empty( $privacy_policy_content ) ) {
			$privacy_policy_guid = get_option( 'home' ) . '/?page_id=3';

			$wpdb->insert(
				$wpdb->posts,
				array(
					'post_author'           => $user_id,
					'post_date'             => $now,
					'post_date_gmt'         => $now_gmt,
					'post_content'          => $privacy_policy_content,
					'post_excerpt'          => '',
					'comment_status'        => 'closed',
					'post_title'            => __( 'Privacy Policy' ),
					/* translators: Privacy Policy page slug. */
					'post_name'             => __( 'privacy-policy' ),
					'post_modified'         => $now,
					'post_modified_gmt'     => $now_gmt,
					'guid'                  => $privacy_policy_guid,
					'post_type'             => 'page',
					'post_status'           => 'draft',
					'to_ping'               => '',
					'pinged'                => '',
					'post_content_filtered' => '',
				)
			);
			$wpdb->insert(
				$wpdb->postmeta,
				array(
					'post_id'    => 3,
					'meta_key'   => '_wp_page_template',
					'meta_value' => 'default',
				)
			);
			update_option( 'wp_page_for_privacy_policy', 3 );
		}

		// Set up default widgets for default theme.
		update_option(
			'widget_block',
			array(
				2              => array( 'content' => '<!-- wp:search /-->' ),
				3              => array( 'content' => '<!-- wp:group --><div class="wp-block-group"><!-- wp:heading --><h2>' . __( 'Recent Posts' ) . '</h2><!-- /wp:heading --><!-- wp:latest-posts /--></div><!-- /wp:group -->' ),
				4              => array( 'content' => '<!-- wp:group --><div class="wp-block-group"><!-- wp:heading --><h2>' . __( 'Recent Comments' ) . '</h2><!-- /wp:heading --><!-- wp:latest-comments {"displayAvatar":false,"displayDate":false,"displayExcerpt":false} /--></div><!-- /wp:group -->' ),
				5              => array( 'content' => '<!-- wp:group --><div class="wp-block-group"><!-- wp:heading --><h2>' . __( 'Archives' ) . '</h2><!-- /wp:heading --><!-- wp:archives /--></div><!-- /wp:group -->' ),
				6              => array( 'content' => '<!-- wp:group --><div class="wp-block-group"><!-- wp:heading --><h2>' . __( 'Categories' ) . '</h2><!-- /wp:heading --><!-- wp:categories /--></div><!-- /wp:group -->' ),
				'_multiwidget' => 1,
			)
		);
		update_option(
			'sidebars_widgets',
			array(
				'wp_inactive_widgets' => array(),
				'sidebar-1'           => array(
					0 => 'block-2',
					1 => 'block-3',
					2 => 'block-4',
				),
				'sidebar-2'           => array(
					0 => 'block-5',
					1 => 'block-6',
				),
				'array_version'       => 3,
			)
		);

		if ( ! is_multisite() ) {
			update_user_meta( $user_id, 'show_welcome_panel', 1 );
		} elseif ( ! is_super_admin( $user_id ) && ! metadata_exists( 'user', $user_id, 'show_welcome_panel' ) ) {
			update_user_meta( $user_id, 'show_welcome_panel', 2 );
		}

		if ( is_multisite() ) {
			// Flush rules to pick up the new page.
			$wp_rewrite->init();
			$wp_rewrite->flush_rules();

			$user = new WP_User( $user_id );
			$wpdb->update( $wpdb->options, array( 'option_value' => $user->user_email ), array( 'option_name' => 'admin_email' ) );

			// Remove all perms except for the login user.
			$wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->usermeta WHERE user_id != %d AND meta_key = %s", $user_id, $table_prefix . 'user_level' ) );
			$wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->usermeta WHERE user_id != %d AND meta_key = %s", $user_id, $table_prefix . 'capabilities' ) );

			/*
			 * Delete any caps that snuck into the previously active blog. (Hardcoded to blog 1 for now.)
			 * TODO: Get previous_blog_id.
			 */
			if ( ! is_super_admin( $user_id ) && 1 !== $user_id ) {
				$wpdb->delete(
					$wpdb->usermeta,
					array(
						'user_id'  => $user_id,
						'meta_key' => $wpdb->base_prefix . '1_capabilities',
					)
				);
			}
		}
	}
endif;

/**
 * Maybe enable pretty permalinks on installation.
 *
 * If after enabling pretty permalinks don't work, fallback to query-string permalinks.
 *
 * @since 4.2.0
 *
 * @global WP_Rewrite $wp_rewrite WordPress rewrite component.
 *
 * @return bool Whether pretty permalinks are enabled. False otherwise.
 */
function wp_install_maybe_enable_pretty_permalinks() {
	global $wp_rewrite;

	// Bail if a permalink structure is already enabled.
	if ( get_option( 'permalink_structure' ) ) {
		return true;
	}

	/*
	 * The Permalink structures to attempt.
	 *
	 * The first is designed for mod_rewrite or nginx rewriting.
	 *
	 * The second is PATHINFO-based permalinks for web server configurations
	 * without a true rewrite module enabled.
	 */
	$permalink_structures = array(
		'/%year%/%monthnum%/%day%/%postname%/',
		'/index.php/%year%/%monthnum%/%day%/%postname%/',
	);

	foreach ( (array) $permalink_structures as $permalink_structure ) {
		$wp_rewrite->set_permalink_structure( $permalink_structure );

		/*
		 * Flush rules with the hard option to force refresh of the web-server's
		 * rewrite config file (e.g. .htaccess or web.config).
		 */
		$wp_rewrite->flush_rules( true );

		$test_url = '';

		// Test against a real WordPress post.
		$first_post = get_page_by_path( sanitize_title( _x( 'hello-world', 'Default post slug' ) ), OBJECT, 'post' );
		if ( $first_post ) {
			$test_url = get_permalink( $first_post->ID );
		}

		/*
		 * Send a request to the site, and check whether
		 * the 'X-Pingback' header is returned as expected.
		 *
		 * Uses wp_remote_get() instead of wp_remote_head() because web servers
		 * can block head requests.
		 */
		$response          = wp_remote_get( $test_url, array( 'timeout' => 5 ) );
		$x_pingback_header = wp_remote_retrieve_header( $response, 'X-Pingback' );
		$pretty_permalinks = $x_pingback_header && get_bloginfo( 'pingback_url' ) === $x_pingback_header;

		if ( $pretty_permalinks ) {
			return true;
		}
	}

	/*
	 * If it makes it this far, pretty permalinks failed.
	 * Fallback to query-string permalinks.
	 */
	$wp_rewrite->set_permalink_structure( '' );
	$wp_rewrite->flush_rules( true );

	return false;
}

if ( ! function_exists( 'wp_new_blog_notification' ) ) :
	/**
	 * Notifies the site admin that the installation of WordPress is complete.
	 *
	 * Sends an email to the new administrator that the installation is complete
	 * and provides them with a record of their login credentials.
	 *
	 * @since 2.1.0
	 *
	 * @param string $blog_title Site title.
	 * @param string $blog_url   Site URL.
	 * @param int    $user_id    Administrator's user ID.
	 * @param string $password   Administrator's password. Note that a placeholder message is
	 *                           usually passed instead of the actual password.
	 */
	function wp_new_blog_notification(
		$blog_title,
		$blog_url,
		$user_id,
		#[\SensitiveParameter]
		$password
	) {
		$user      = new WP_User( $user_id );
		$email     = $user->user_email;
		$name      = $user->user_login;
		$login_url = wp_login_url();

		$message = sprintf(
			/* translators: New site notification email. 1: New site URL, 2: User login, 3: User password or password reset link, 4: Login URL. */
			__(
				'Your new WordPress site has been successfully set up at:

%1$s

You can log in to the administrator account with the following information:

Username: %2$s
Password: %3$s
Log in here: %4$s

We hope you enjoy your new site. Thanks!

--The WordPress Team
https://wordpress.org/
'
			),
			$blog_url,
			$name,
			$password,
			$login_url
		);

		$installed_email = array(
			'to'      => $email,
			'subject' => __( 'New WordPress Site' ),
			'message' => $message,
			'headers' => '',
		);

		/**
		 * Filters the contents of the email sent to the site administrator when WordPress is installed.
		 *
		 * @since 5.6.0
		 *
		 * @param array $installed_email {
		 *     Used to build wp_mail().
		 *
		 *     @type string $to      The email address of the recipient.
		 *     @type string $subject The subject of the email.
		 *     @type string $message The content of the email.
		 *     @type string $headers Headers.
		 * }
		 * @param WP_User $user          The site administrator user object.
		 * @param string  $blog_title    The site title.
		 * @param string  $blog_url      The site URL.
		 * @param string  $password      The site administrator's password. Note that a placeholder message
		 *                               is usually passed instead of the user's actual password.
		 */
		$installed_email = apply_filters( 'wp_installed_email', $installed_email, $user, $blog_title, $blog_url, $password );

		wp_mail(
			$installed_email['to'],
			$installed_email['subject'],
			$installed_email['message'],
			$installed_email['headers']
		);
	}
endif;

if ( ! function_exists( 'wp_upgrade' ) ) :
	/**
	 * Runs WordPress Upgrade functions.
	 *
	 * Upgrades the database if needed during a site update.
	 *
	 * @since 2.1.0
	 *
	 * @global int $wp_current_db_version The old (current) database version.
	 * @global int $wp_db_version         The new database version.
	 */
	function wp_upgrade() {
		global $wp_current_db_version, $wp_db_version;

		$wp_current_db_version = (int) __get_option( 'db_version' );

		// We are up to date. Nothing to do.
		if ( $wp_db_version === $wp_current_db_version ) {
			return;
		}

		if ( ! is_blog_installed() ) {
			return;
		}

		wp_check_mysql_version();
		wp_cache_flush();
		pre_schema_upgrade();
		make_db_current_silent();
		upgrade_all();
		if ( is_multisite() && is_main_site() ) {
			upgrade_network();
		}
		wp_cache_flush();

		if ( is_multisite() ) {
			update_site_meta( get_current_blog_id(), 'db_version', $wp_db_version );
			update_site_meta( get_current_blog_id(), 'db_last_updated', microtime() );
		}

		delete_transient( 'wp_core_block_css_files' );

		/**
		 * Fires after a site is fully upgraded.
		 *
		 * @since 3.9.0
		 *
		 * @param int $wp_db_version         The new $wp_db_version.
		 * @param int $wp_current_db_version The old (current) $wp_db_version.
		 */
		do_action( 'wp_upgrade', $wp_db_version, $wp_current_db_version );
	}
endif;

/**
 * Functions to be called in installation and upgrade scripts.
 *
 * Contains conditional checks to determine which upgrade scripts to run,
 * based on database version and WP version being updated-to.
 *
 * @ignore
 * @since 1.0.1
 *
 * @global int $wp_current_db_version The old (current) database version.
 * @global int $wp_db_version         The new database version.
 */
function upgrade_all() {
	global $wp_current_db_version, $wp_db_version;

	$wp_current_db_version = (int) __get_option( 'db_version' );

	// We are up to date. Nothing to do.
	if ( $wp_db_version === $wp_current_db_version ) {
		return;
	}

	// If the version is not set in the DB, try to guess the version.
	if ( empty( $wp_current_db_version ) ) {
		$wp_current_db_version = 0;

		// If the template option exists, we have 1.5.
		$template = __get_option( 'template' );
		if ( ! empty( $template ) ) {
			$wp_current_db_version = 2541;
		}
	}

	if ( $wp_current_db_version < 6039 ) {
		upgrade_230_options_table();
	}

	populate_options();

	if ( $wp_current_db_version < 2541 ) {
		upgrade_100();
		upgrade_101();
		upgrade_110();
		upgrade_130();
	}

	if ( $wp_current_db_version < 3308 ) {
		upgrade_160();
	}

	if ( $wp_current_db_version < 4772 ) {
		upgrade_210();
	}

	if ( $wp_current_db_version < 4351 ) {
		upgrade_old_slugs();
	}

	if ( $wp_current_db_version < 5539 ) {
		upgrade_230();
	}

	if ( $wp_current_db_version < 6124 ) {
		upgrade_230_old_tables();
	}

	if ( $wp_current_db_version < 7499 ) {
		upgrade_250();
	}

	if ( $wp_current_db_version < 7935 ) {
		upgrade_252();
	}

	if ( $wp_current_db_version < 8201 ) {
		upgrade_260();
	}

	if ( $wp_current_db_version < 8989 ) {
		upgrade_270();
	}

	if ( $wp_current_db_version < 10360 ) {
		upgrade_280();
	}

	if ( $wp_current_db_version < 11958 ) {
		upgrade_290();
	}

	if ( $wp_current_db_version < 15260 ) {
		upgrade_300();
	}

	if ( $wp_current_db_version < 19389 ) {
		upgrade_330();
	}

	if ( $wp_current_db_version < 20080 ) {
		upgrade_340();
	}

	if ( $wp_current_db_version < 22422 ) {
		upgrade_350();
	}

	if ( $wp_current_db_version < 25824 ) {
		upgrade_370();
	}

	if ( $wp_current_db_version < 26148 ) {
		upgrade_372();
	}

	if ( $wp_current_db_version < 26691 ) {
		upgrade_380();
	}

	if ( $wp_current_db_version < 29630 ) {
		upgrade_400();
	}

	if ( $wp_current_db_version < 33055 ) {
		upgrade_430();
	}

	if ( $wp_current_db_version < 33056 ) {
		upgrade_431();
	}

	if ( $wp_current_db_version < 35700 ) {
		upgrade_440();
	}

	if ( $wp_current_db_version < 36686 ) {
		upgrade_450();
	}

	if ( $wp_current_db_version < 37965 ) {
		upgrade_460();
	}

	if ( $wp_current_db_version < 44719 ) {
		upgrade_510();
	}

	if ( $wp_current_db_version < 45744 ) {
		upgrade_530();
	}

	if ( $wp_current_db_version < 48575 ) {
		upgrade_550();
	}

	if ( $wp_current_db_version < 49752 ) {
		upgrade_560();
	}

	if ( $wp_current_db_version < 51917 ) {
		upgrade_590();
	}

	if ( $wp_current_db_version < 53011 ) {
		upgrade_600();
	}

	if ( $wp_current_db_version < 55853 ) {
		upgrade_630();
	}

	if ( $wp_current_db_version < 56657 ) {
		upgrade_640();
	}

	if ( $wp_current_db_version < 57155 ) {
		upgrade_650();
	}

	if ( $wp_current_db_version < 58975 ) {
		upgrade_670();
	}

	if ( $wp_current_db_version < 60421 ) {
		upgrade_682();
	}

	maybe_disable_link_manager();

	maybe_disable_automattic_widgets();

	update_option( 'db_version', $wp_db_version );
	update_option( 'db_upgraded', true );
}

/**
 * Execute changes made in WordPress 1.0.
 *
 * @ignore
 * @since 1.0.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 */
function upgrade_100() {
	global $wpdb;

	// Get the title and ID of every post, post_name to check if it already has a value.
	$posts = $wpdb->get_results( "SELECT ID, post_title, post_name FROM $wpdb->posts WHERE post_name = ''" );
	if ( $posts ) {
		foreach ( $posts as $post ) {
			if ( '' === $post->post_name ) {
				$newtitle = sanitize_title( $post->post_title );
				$wpdb->query( $wpdb->prepare( "UPDATE $wpdb->posts SET post_name = %s WHERE ID = %d", $newtitle, $post->ID ) );
			}
		}
	}

	$categories = $wpdb->get_results( "SELECT cat_ID, cat_name, category_nicename FROM $wpdb->categories" );
	foreach ( $categories as $category ) {
		if ( '' === $category->category_nicename ) {
			$newtitle = sanitize_title( $category->cat_name );
			$wpdb->update( $wpdb->categories, array( 'category_nicename' => $newtitle ), array( 'cat_ID' => $category->cat_ID ) );
		}
	}

	$sql = "UPDATE $wpdb->options
		SET option_value = REPLACE(option_value, 'wp-links/links-images/', 'wp-images/links/')
		WHERE option_name LIKE %s
		AND option_value LIKE %s";
	$wpdb->query( $wpdb->prepare( $sql, $wpdb->esc_like( 'links_rating_image' ) . '%', $wpdb->esc_like( 'wp-links/links-images/' ) . '%' ) );

	$done_ids = $wpdb->get_results( "SELECT DISTINCT post_id FROM $wpdb->post2cat" );
	if ( $done_ids ) :
		$done_posts = array();
		foreach ( $done_ids as $done_id ) :
			$done_posts[] = $done_id->post_id;
		endforeach;
		$catwhere = ' AND ID NOT IN (' . implode( ',', $done_posts ) . ')';
	else :
		$catwhere = '';
	endif;

	$allposts = $wpdb->get_results( "SELECT ID, post_category FROM $wpdb->posts WHERE post_category != '0' $catwhere" );
	if ( $allposts ) :
		foreach ( $allposts as $post ) {
			// Check to see if it's already been imported.
			$cat = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->post2cat WHERE post_id = %d AND category_id = %d", $post->ID, $post->post_category ) );
			if ( ! $cat && 0 !== (int) $post->post_category ) { // If there's no result.
				$wpdb->insert(
					$wpdb->post2cat,
					array(
						'post_id'     => $post->ID,
						'category_id' => $post->post_category,
					)
				);
			}
		}
	endif;
}

/**
 * Execute changes made in WordPress 1.0.1.
 *
 * @ignore
 * @since 1.0.1
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 */
function upgrade_101() {
	global $wpdb;

	// Clean up indices, add a few.
	add_clean_index( $wpdb->posts, 'post_name' );
	add_clean_index( $wpdb->posts, 'post_status' );
	add_clean_index( $wpdb->categories, 'category_nicename' );
	add_clean_index( $wpdb->comments, 'comment_approved' );
	add_clean_index( $wpdb->comments, 'comment_post_ID' );
	add_clean_index( $wpdb->links, 'link_category' );
	add_clean_index( $wpdb->links, 'link_visible' );
}

/**
 * Execute changes made in WordPress 1.2.
 *
 * @ignore
 * @since 1.2.0
 * @since 6.8.0 User passwords are no longer hashed with md5.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 */
function upgrade_110() {
	global $wpdb;

	// Set user_nicename.
	$users = $wpdb->get_results( "SELECT ID, user_nickname, user_nicename FROM $wpdb->users" );
	foreach ( $users as $user ) {
		if ( '' === $user->user_nicename ) {
			$newname = sanitize_title( $user->user_nickname );
			$wpdb->update( $wpdb->users, array( 'user_nicename' => $newname ), array( 'ID' => $user->ID ) );
		}
	}

	// Get the GMT offset, we'll use that later on.
	$all_options = get_alloptions_110();

	$time_difference = $all_options->time_difference;

	$server_time    = time() + (int) gmdate( 'Z' );
	$weblogger_time = $server_time + $time_difference * HOUR_IN_SECONDS;
	$gmt_time       = time();

	$diff_gmt_server       = ( $gmt_time - $server_time ) / HOUR_IN_SECONDS;
	$diff_weblogger_server = ( $weblogger_time - $server_time ) / HOUR_IN_SECONDS;
	$diff_gmt_weblogger    = $diff_gmt_server - $diff_weblogger_server;
	$gmt_offset            = -$diff_gmt_weblogger;

	// Add a gmt_offset option, with value $gmt_offset.
	add_option( 'gmt_offset', $gmt_offset );

	/*
	 * Check if we already set the GMT fields. If we did, then
	 * MAX(post_date_gmt) can't be '0000-00-00 00:00:00'.
	 * <michel_v> I just slapped myself silly for not thinking about it earlier.
	 */
	$got_gmt_fields = ( '0000-00-00 00:00:00' !== $wpdb->get_var( "SELECT MAX(post_date_gmt) FROM $wpdb->posts" ) );

	if ( ! $got_gmt_fields ) {

		// Add or subtract time to all dates, to get GMT dates.
		$add_hours   = (int) $diff_gmt_weblogger;
		$add_minutes = (int) ( 60 * ( $diff_gmt_weblogger - $add_hours ) );
		$wpdb->query( "UPDATE $wpdb->posts SET post_date_gmt = DATE_ADD(post_date, INTERVAL '$add_hours:$add_minutes' HOUR_MINUTE)" );
		$wpdb->query( "UPDATE $wpdb->posts SET post_modified = post_date" );
		$wpdb->query( "UPDATE $wpdb->posts SET post_modified_gmt = DATE_ADD(post_modified, INTERVAL '$add_hours:$add_minutes' HOUR_MINUTE) WHERE post_modified != '0000-00-00 00:00:00'" );
		$wpdb->query( "UPDATE $wpdb->comments SET comment_date_gmt = DATE_ADD(comment_date, INTERVAL '$add_hours:$add_minutes' HOUR_MINUTE)" );
		$wpdb->query( "UPDATE $wpdb->users SET user_registered = DATE_ADD(user_registered, INTERVAL '$add_hours:$add_minutes' HOUR_MINUTE)" );
	}
}

/**
 * Execute changes made in WordPress 1.5.
 *
 * @ignore
 * @since 1.5.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 */
function upgrade_130() {
	global $wpdb;

	// Remove extraneous backslashes.
	$posts = $wpdb->get_results( "SELECT ID, post_title, post_content, post_excerpt, guid, post_date, post_name, post_status, post_author FROM $wpdb->posts" );
	if ( $posts ) {
		foreach ( $posts as $post ) {
			$post_content = addslashes( deslash( $post->post_content ) );
			$post_title   = addslashes( deslash( $post->post_title ) );
			$post_excerpt = addslashes( deslash( $post->post_excerpt ) );
			if ( empty( $post->guid ) ) {
				$guid = get_permalink( $post->ID );
			} else {
				$guid = $post->guid;
			}

			$wpdb->update( $wpdb->posts, compact( 'post_title', 'post_content', 'post_excerpt', 'guid' ), array( 'ID' => $post->ID ) );

		}
	}

	// Remove extraneous backslashes.
	$comments = $wpdb->get_results( "SELECT comment_ID, comment_author, comment_content FROM $wpdb->comments" );
	if ( $comments ) {
		foreach ( $comments as $comment ) {
			$comment_content = deslash( $comment->comment_content );
			$comment_author  = deslash( $comment->comment_author );

			$wpdb->update( $wpdb->comments, compact( 'comment_content', 'comment_author' ), array( 'comment_ID' => $comment->comment_ID ) );
		}
	}

	// Remove extraneous backslashes.
	$links = $wpdb->get_results( "SELECT link_id, link_name, link_description FROM $wpdb->links" );
	if ( $links ) {
		foreach ( $links as $link ) {
			$link_name        = deslash( $link->link_name );
			$link_description = deslash( $link->link_description );

			$wpdb->update( $wpdb->links, compact( 'link_name', 'link_description' ), array( 'link_id' => $link->link_id ) );
		}
	}

	$active_plugins = __get_option( 'active_plugins' );

	/*
	 * If plugins are not stored in an array, they're stored in the old
	 * newline separated format. Convert to new format.
	 */
	if ( ! is_array( $active_plugins ) ) {
		$active_plugins = explode( "\n", trim( $active_plugins ) );
		update_option( 'active_plugins', $active_plugins );
	}

	// Obsolete tables.
	$wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'optionvalues' );
	$wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'optiontypes' );
	$wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'optiongroups' );
	$wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'optiongroup_options' );

	// Update comments table to use comment_type.
	$wpdb->query( "UPDATE $wpdb->comments SET comment_type='trackback', comment_content = REPLACE(comment_content, '<trackback />', '') WHERE comment_content LIKE '<trackback />%'" );
	$wpdb->query( "UPDATE $wpdb->comments SET comment_type='pingback', comment_content = REPLACE(comment_content, '<pingback />', '') WHERE comment_content LIKE '<pingback />%'" );

	// Some versions have multiple duplicate option_name rows with the same values.
	$options = $wpdb->get_results( "SELECT option_name, COUNT(option_name) AS dupes FROM `$wpdb->options` GROUP BY option_name" );
	foreach ( $options as $option ) {
		if ( $option->dupes > 1 ) { // Could this be done in the query?
			$limit    = $option->dupes - 1;
			$dupe_ids = $wpdb->get_col( $wpdb->prepare( "SELECT option_id FROM $wpdb->options WHERE option_name = %s LIMIT %d", $option->option_name, $limit ) );
			if ( $dupe_ids ) {
				$dupe_ids = implode( ',', $dupe_ids );
				$wpdb->query( "DELETE FROM $wpdb->options WHERE option_id IN ($dupe_ids)" );
			}
		}
	}

	make_site_theme();
}

/**
 * Execute changes made in WordPress 2.0.
 *
 * @ignore
 * @since 2.0.0
 *
 * @global wpdb $wpdb                  WordPress database abstraction object.
 * @global int  $wp_current_db_version The old (current) database version.
 */
function upgrade_160() {
	global $wpdb, $wp_current_db_version;

	populate_roles_160();

	$users = $wpdb->get_results( "SELECT * FROM $wpdb->users" );
	foreach ( $users as $user ) :
		if ( ! empty( $user->user_firstname ) ) {
			update_user_meta( $user->ID, 'first_name', wp_slash( $user->user_firstname ) );
		}
		if ( ! empty( $user->user_lastname ) ) {
			update_user_meta( $user->ID, 'last_name', wp_slash( $user->user_lastname ) );
		}
		if ( ! empty( $user->user_nickname ) ) {
			update_user_meta( $user->ID, 'nickname', wp_slash( $user->user_nickname ) );
		}
		if ( ! empty( $user->user_level ) ) {
			update_user_meta( $user->ID, $wpdb->prefix . 'user_level', $user->user_level );
		}
		if ( ! empty( $user->user_icq ) ) {
			update_user_meta( $user->ID, 'icq', wp_slash( $user->user_icq ) );
		}
		if ( ! empty( $user->user_aim ) ) {
			update_user_meta( $user->ID, 'aim', wp_slash( $user->user_aim ) );
		}
		if ( ! empty( $user->user_msn ) ) {
			update_user_meta( $user->ID, 'msn', wp_slash( $user->user_msn ) );
		}
		if ( ! empty( $user->user_yim ) ) {
			update_user_meta( $user->ID, 'yim', wp_slash( $user->user_icq ) );
		}
		if ( ! empty( $user->user_description ) ) {
			update_user_meta( $user->ID, 'description', wp_slash( $user->user_description ) );
		}

		if ( isset( $user->user_idmode ) ) :
			$idmode = $user->user_idmode;
			if ( 'nickname' === $idmode ) {
				$id = $user->user_nickname;
			}
			if ( 'login' === $idmode ) {
				$id = $user->user_login;
			}
			if ( 'firstname' === $idmode ) {
				$id = $user->user_firstname;
			}
			if ( 'lastname' === $idmode ) {
				$id = $user->user_lastname;
			}
			if ( 'namefl' === $idmode ) {
				$id = $user->user_firstname . ' ' . $user->user_lastname;
			}
			if ( 'namelf' === $idmode ) {
				$id = $user->user_lastname . ' ' . $user->user_firstname;
			}
			if ( ! $idmode ) {
				$id = $user->user_nickname;
			}
			$wpdb->update( $wpdb->users, array( 'display_name' => $id ), array( 'ID' => $user->ID ) );
		endif;

		// FIXME: RESET_CAPS is temporary code to reset roles and caps if flag is set.
		$caps = get_user_meta( $user->ID, $wpdb->prefix . 'capabilities' );
		if ( empty( $caps ) || defined( 'RESET_CAPS' ) ) {
			$level = get_user_meta( $user->ID, $wpdb->prefix . 'user_level', true );
			$role  = translate_level_to_role( $level );
			update_user_meta( $user->ID, $wpdb->prefix . 'capabilities', array( $role => true ) );
		}

	endforeach;
	$old_user_fields = array( 'user_firstname', 'user_lastname', 'user_icq', 'user_aim', 'user_msn', 'user_yim', 'user_idmode', 'user_ip', 'user_domain', 'user_browser', 'user_description', 'user_nickname', 'user_level' );
	$wpdb->hide_errors();
	foreach ( $old_user_fields as $old ) {
		$wpdb->query( "ALTER TABLE $wpdb->users DROP $old" );
	}
	$wpdb->show_errors();

	// Populate comment_count field of posts table.
	$comments = $wpdb->get_results( "SELECT comment_post_ID, COUNT(*) as c FROM $wpdb->comments WHERE comment_approved = '1' GROUP BY comment_post_ID" );
	if ( is_array( $comments ) ) {
		foreach ( $comments as $comment ) {
			$wpdb->update( $wpdb->posts, array( 'comment_count' => $comment->c ), array( 'ID' => $comment->comment_post_ID ) );
		}
	}

	/*
	 * Some alpha versions used a post status of object instead of attachment
	 * and put the mime type in post_type instead of post_mime_type.
	 */
	if ( $wp_current_db_version > 2541 && $wp_current_db_version <= 3091 ) {
		$objects = $wpdb->get_results( "SELECT ID, post_type FROM $wpdb->posts WHERE post_status = 'object'" );
		foreach ( $objects as $object ) {
			$wpdb->update(
				$wpdb->posts,
				array(
					'post_status'    => 'attachment',
					'post_mime_type' => $object->post_type,
					'post_type'      => '',
				),
				array( 'ID' => $object->ID )
			);

			$meta = get_post_meta( $object->ID, 'imagedata', true );
			if ( ! empty( $meta['file'] ) ) {
				update_attached_file( $object->ID, $meta['file'] );
			}
		}
	}
}

/**
 * Execute changes made in WordPress 2.1.
 *
 * @ignore
 * @since 2.1.0
 *
 * @global int  $wp_current_db_version The old (current) database version.
 * @global wpdb $wpdb                  WordPress database abstraction object.
 */
function upgrade_210() {
	global $wp_current_db_version, $wpdb;

	if ( $wp_current_db_version < 3506 ) {
		// Update status and type.
		$posts = $wpdb->get_results( "SELECT ID, post_status FROM $wpdb->posts" );

		if ( ! empty( $posts ) ) {
			foreach ( $posts as $post ) {
				$status = $post->post_status;
				$type   = 'post';

				if ( 'static' === $status ) {
					$status = 'publish';
					$type   = 'page';
				} elseif ( 'attachment' === $status ) {
					$status = 'inherit';
					$type   = 'attachment';
				}

				$wpdb->query( $wpdb->prepare( "UPDATE $wpdb->posts SET post_status = %s, post_type = %s WHERE ID = %d", $status, $type, $post->ID ) );
			}
		}
	}

	if ( $wp_current_db_version < 3845 ) {
		populate_roles_210();
	}

	if ( $wp_current_db_version < 3531 ) {
		// Give future posts a post_status of future.
		$now = gmdate( 'Y-m-d H:i:59' );
		$wpdb->query( "UPDATE $wpdb->posts SET post_status = 'future' WHERE post_status = 'publish' AND post_date_gmt > '$now'" );

		$posts = $wpdb->get_results( "SELECT ID, post_date FROM $wpdb->posts WHERE post_status ='future'" );
		if ( ! empty( $posts ) ) {
			foreach ( $posts as $post ) {
				wp_schedule_single_event( mysql2date( 'U', $post->post_date, false ), 'publish_future_post', array( $post->ID ) );
			}
		}
	}
}

/**
 * Execute changes made in WordPress 2.3.
 *
 * @ignore
 * @since 2.3.0
 *
 * @global int  $wp_current_db_version The old (current) database version.
 * @global wpdb $wpdb                  WordPress database abstraction object.
 */
function upgrade_230() {
	global $wp_current_db_version, $wpdb;

	if ( $wp_current_db_version < 5200 ) {
		populate_roles_230();
	}

	// Convert categories to terms.
	$tt_ids     = array();
	$have_tags  = false;
	$categories = $wpdb->get_results( "SELECT * FROM $wpdb->categories ORDER BY cat_ID" );
	foreach ( $categories as $category ) {
		$term_id     = (int) $category->cat_ID;
		$name        = $category->cat_name;
		$description = $category->category_description;
		$slug        = $category->category_nicename;
		$parent      = $category->category_parent;
		$term_group  = 0;

		// Associate terms with the same slug in a term group and make slugs unique.
		$exists = $wpdb->get_results( $wpdb->prepare( "SELECT term_id, term_group FROM $wpdb->terms WHERE slug = %s", $slug ) );
		if ( $exists ) {
			$term_group = $exists[0]->term_group;
			$id         = $exists[0]->term_id;
			$num        = 2;
			do {
				$alt_slug = $slug . "-$num";
				++$num;
				$slug_check = $wpdb->get_var( $wpdb->prepare( "SELECT slug FROM $wpdb->terms WHERE slug = %s", $alt_slug ) );
			} while ( $slug_check );

			$slug = $alt_slug;

			if ( empty( $term_group ) ) {
				$term_group = $wpdb->get_var( "SELECT MAX(term_group) FROM $wpdb->terms GROUP BY term_group" ) + 1;
				$wpdb->query( $wpdb->prepare( "UPDATE $wpdb->terms SET term_group = %d WHERE term_id = %d", $term_group, $id ) );
			}
		}

		$wpdb->query(
			$wpdb->prepare(
				"INSERT INTO $wpdb->terms (term_id, name, slug, term_group) VALUES
		(%d, %s, %s, %d)",
				$term_id,
				$name,
				$slug,
				$term_group
			)
		);

		$count = 0;
		if ( ! empty( $category->category_count ) ) {
			$count    = (int) $category->category_count;
			$taxonomy = 'category';
			$wpdb->query( $wpdb->prepare( "INSERT INTO $wpdb->term_taxonomy (term_id, taxonomy, description, parent, count) VALUES ( %d, %s, %s, %d, %d)", $term_id, $taxonomy, $description, $parent, $count ) );
			$tt_ids[ $term_id ][ $taxonomy ] = (int) $wpdb->insert_id;
		}

		if ( ! empty( $category->link_count ) ) {
			$count    = (int) $category->link_count;
			$taxonomy = 'link_category';
			$wpdb->query( $wpdb->prepare( "INSERT INTO $wpdb->term_taxonomy (term_id, taxonomy, description, parent, count) VALUES ( %d, %s, %s, %d, %d)", $term_id, $taxonomy, $description, $parent, $count ) );
			$tt_ids[ $term_id ][ $taxonomy ] = (int) $wpdb->insert_id;
		}

		if ( ! empty( $category->tag_count ) ) {
			$have_tags = true;
			$count     = (int) $category->tag_count;
			$taxonomy  = 'post_tag';
			$wpdb->insert( $wpdb->term_taxonomy, compact( 'term_id', 'taxonomy', 'description', 'parent', 'count' ) );
			$tt_ids[ $term_id ][ $taxonomy ] = (int) $wpdb->insert_id;
		}

		if ( empty( $count ) ) {
			$count    = 0;
			$taxonomy = 'category';
			$wpdb->insert( $wpdb->term_taxonomy, compact( 'term_id', 'taxonomy', 'description', 'parent', 'count' ) );
			$tt_ids[ $term_id ][ $taxonomy ] = (int) $wpdb->insert_id;
		}
	}

	$select = 'post_id, category_id';
	if ( $have_tags ) {
		$select .= ', rel_type';
	}

	$posts = $wpdb->get_results( "SELECT $select FROM $wpdb->post2cat GROUP BY post_id, category_id" );
	foreach ( $posts as $post ) {
		$post_id  = (int) $post->post_id;
		$term_id  = (int) $post->category_id;
		$taxonomy = 'category';
		if ( ! empty( $post->rel_type ) && 'tag' === $post->rel_type ) {
			$taxonomy = 'tag';
		}
		$tt_id = $tt_ids[ $term_id ][ $taxonomy ];
		if ( empty( $tt_id ) ) {
			continue;
		}

		$wpdb->insert(
			$wpdb->term_relationships,
			array(
				'object_id'        => $post_id,
				'term_taxonomy_id' => $tt_id,
			)
		);
	}

	// < 3570 we used linkcategories. >= 3570 we used categories and link2cat.
	if ( $wp_current_db_version < 3570 ) {
		/*
		 * Create link_category terms for link categories. Create a map of link
		 * category IDs to link_category terms.
		 */
		$link_cat_id_map  = array();
		$default_link_cat = 0;
		$tt_ids           = array();
		$link_cats        = $wpdb->get_results( 'SELECT cat_id, cat_name FROM ' . $wpdb->prefix . 'linkcategories' );
		foreach ( $link_cats as $category ) {
			$cat_id     = (int) $category->cat_id;
			$term_id    = 0;
			$name       = wp_slash( $category->cat_name );
			$slug       = sanitize_title( $name );
			$term_group = 0;

			// Associate terms with the same slug in a term group and make slugs unique.
			$exists = $wpdb->get_results( $wpdb->prepare( "SELECT term_id, term_group FROM $wpdb->terms WHERE slug = %s", $slug ) );
			if ( $exists ) {
				$term_group = $exists[0]->term_group;
				$term_id    = $exists[0]->term_id;
			}

			if ( empty( $term_id ) ) {
				$wpdb->insert( $wpdb->terms, compact( 'name', 'slug', 'term_group' ) );
				$term_id = (int) $wpdb->insert_id;
			}

			$link_cat_id_map[ $cat_id ] = $term_id;
			$default_link_cat           = $term_id;

			$wpdb->insert(
				$wpdb->term_taxonomy,
				array(
					'term_id'     => $term_id,
					'taxonomy'    => 'link_category',
					'description' => '',
					'parent'      => 0,
					'count'       => 0,
				)
			);
			$tt_ids[ $term_id ] = (int) $wpdb->insert_id;
		}

		// Associate links to categories.
		$links = $wpdb->get_results( "SELECT link_id, link_category FROM $wpdb->links" );
		if ( ! empty( $links ) ) {
			foreach ( $links as $link ) {
				if ( 0 === (int) $link->link_category ) {
					continue;
				}
				if ( ! isset( $link_cat_id_map[ $link->link_category ] ) ) {
					continue;
				}
				$term_id = $link_cat_id_map[ $link->link_category ];
				$tt_id   = $tt_ids[ $term_id ];
				if ( empty( $tt_id ) ) {
					continue;
				}

				$wpdb->insert(
					$wpdb->term_relationships,
					array(
						'object_id'        => $link->link_id,
						'term_taxonomy_id' => $tt_id,
					)
				);
			}
		}

		// Set default to the last category we grabbed during the upgrade loop.
		update_option( 'default_link_category', $default_link_cat );
	} else {
		$links = $wpdb->get_results( "SELECT link_id, category_id FROM $wpdb->link2cat GROUP BY link_id, category_id" );
		foreach ( $links as $link ) {
			$link_id  = (int) $link->link_id;
			$term_id  = (int) $link->category_id;
			$taxonomy = 'link_category';
			$tt_id    = $tt_ids[ $term_id ][ $taxonomy ];
			if ( empty( $tt_id ) ) {
				continue;
			}
			$wpdb->insert(
				$wpdb->term_relationships,
				array(
					'object_id'        => $link_id,
					'term_taxonomy_id' => $tt_id,
				)
			);
		}
	}

	if ( $wp_current_db_version < 4772 ) {
		// Obsolete linkcategories table.
		$wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'linkcategories' );
	}

	// Recalculate all counts.
	$terms = $wpdb->get_results( "SELECT term_taxonomy_id, taxonomy FROM $wpdb->term_taxonomy" );
	foreach ( (array) $terms as $term ) {
		if ( 'post_tag' === $term->taxonomy || 'category' === $term->taxonomy ) {
			$count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_relationships, $wpdb->posts WHERE $wpdb->posts.ID = $wpdb->term_relationships.object_id AND post_status = 'publish' AND post_type = 'post' AND term_taxonomy_id = %d", $term->term_taxonomy_id ) );
		} else {
			$count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d", $term->term_taxonomy_id ) );
		}
		$wpdb->update( $wpdb->term_taxonomy, array( 'count' => $count ), array( 'term_taxonomy_id' => $term->term_taxonomy_id ) );
	}
}

/**
 * Remove old options from the database.
 *
 * @ignore
 * @since 2.3.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 */
function upgrade_230_options_table() {
	global $wpdb;
	$old_options_fields = array( 'option_can_override', 'option_type', 'option_width', 'option_height', 'option_description', 'option_admin_level' );
	$wpdb->hide_errors();
	foreach ( $old_options_fields as $old ) {
		$wpdb->query( "ALTER TABLE $wpdb->options DROP $old" );
	}
	$wpdb->show_errors();
}

/**
 * Remove old categories, link2cat, and post2cat database tables.
 *
 * @ignore
 * @since 2.3.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 */
function upgrade_230_old_tables() {
	global $wpdb;
	$wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'categories' );
	$wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'link2cat' );
	$wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . 'post2cat' );
}

/**
 * Upgrade old slugs made in version 2.2.
 *
 * @ignore
 * @since 2.2.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 */
function upgrade_old_slugs() {
	// Upgrade people who were using the Redirect Old Slugs plugin.
	global $wpdb;
	$wpdb->query( "UPDATE $wpdb->postmeta SET meta_key = '_wp_old_slug' WHERE meta_key = 'old_slug'" );
}

/**
 * Execute changes made in WordPress 2.5.0.
 *
 * @ignore
 * @since 2.5.0
 *
 * @global int $wp_current_db_version The old (current) database version.
 */
function upgrade_250() {
	global $wp_current_db_version;

	if ( $wp_current_db_version < 6689 ) {
		populate_roles_250();
	}
}

/**
 * Execute changes made in WordPress 2.5.2.
 *
 * @ignore
 * @since 2.5.2
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 */
function upgrade_252() {
	global $wpdb;

	$wpdb->query( "UPDATE $wpdb->users SET user_activation_key = ''" );
}

/**
 * Execute changes made in WordPress 2.6.
 *
 * @ignore
 * @since 2.6.0
 *
 * @global int $wp_current_db_version The old (current) database version.
 */
function upgrade_260() {
	global $wp_current_db_version;

	if ( $wp_current_db_version < 8000 ) {
		populate_roles_260();
	}
}

/**
 * Execute changes made in WordPress 2.7.
 *
 * @ignore
 * @since 2.7.0
 *
 * @global int  $wp_current_db_version The old (current) database version.
 * @global wpdb $wpdb                  WordPress database abstraction object.
 */
function upgrade_270() {
	global $wp_current_db_version, $wpdb;

	if ( $wp_current_db_version < 8980 ) {
		populate_roles_270();
	}

	// Update post_date for unpublished posts with empty timestamp.
	if ( $wp_current_db_version < 8921 ) {
		$wpdb->query( "UPDATE $wpdb->posts SET post_date = post_modified WHERE post_date = '0000-00-00 00:00:00'" );
	}
}

/**
 * Execute changes made in WordPress 2.8.
 *
 * @ignore
 * @since 2.8.0
 *
 * @global int  $wp_current_db_version The old (current) database version.
 * @global wpdb $wpdb                  WordPress database abstraction object.
 */
function upgrade_280() {
	global $wp_current_db_version, $wpdb;

	if ( $wp_current_db_version < 10360 ) {
		populate_roles_280();
	}
	if ( is_multisite() ) {
		$start = 0;
		while ( $rows = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options ORDER BY option_id LIMIT $start, 20" ) ) {
			foreach ( $rows as $row ) {
				$value = maybe_unserialize( $row->option_value );
				if ( $value === $row->option_value ) {
					$value = stripslashes( $value );
				}
				if ( $value !== $row->option_value ) {
					update_option( $row->option_name, $value );
				}
			}
			$start += 20;
		}
		clean_blog_cache( get_current_blog_id() );
	}
}

/**
 * Execute changes made in WordPress 2.9.
 *
 * @ignore
 * @since 2.9.0
 *
 * @global int $wp_current_db_version The old (current) database version.
 */
function upgrade_290() {
	global $wp_current_db_version;

	if ( $wp_current_db_version < 11958 ) {
		/*
		 * Previously, setting depth to 1 would redundantly disable threading,
		 * but now 2 is the minimum depth to avoid confusion.
		 */
		if ( 1 === (int) get_option( 'thread_comments_depth' ) ) {
			update_option( 'thread_comments_depth', 2 );
			update_option( 'thread_comments', 0 );
		}
	}
}

/**
 * Execute changes made in WordPress 3.0.
 *
 * @ignore
 * @since 3.0.0
 *
 * @global int  $wp_current_db_version The old (current) database version.
 * @global wpdb $wpdb                  WordPress database abstraction object.
 */
function upgrade_300() {
	global $wp_current_db_version, $wpdb;

	if ( $wp_current_db_version < 15093 ) {
		populate_roles_300();
	}

	if ( $wp_current_db_version < 14139 && is_multisite() && is_main_site() && ! defined( 'MULTISITE' ) && get_site_option( 'siteurl' ) === false ) {
		add_site_option( 'siteurl', '' );
	}

	// 3.0 screen options key name changes.
	if ( wp_should_upgrade_global_tables() ) {
		$sql    = "DELETE FROM $wpdb->usermeta
			WHERE meta_key LIKE %s
			OR meta_key LIKE %s
			OR meta_key LIKE %s
			OR meta_key LIKE %s
			OR meta_key LIKE %s
			OR meta_key LIKE %s
			OR meta_key = 'manageedittagscolumnshidden'
			OR meta_key = 'managecategoriescolumnshidden'
			OR meta_key = 'manageedit-tagscolumnshidden'
			OR meta_key = 'manageeditcolumnshidden'
			OR meta_key = 'categories_per_page'
			OR meta_key = 'edit_tags_per_page'";
		$prefix = $wpdb->esc_like( $wpdb->base_prefix );
		$wpdb->query(
			$wpdb->prepare(
				$sql,
				$prefix . '%' . $wpdb->esc_like( 'meta-box-hidden' ) . '%',
				$prefix . '%' . $wpdb->esc_like( 'closedpostboxes' ) . '%',
				$prefix . '%' . $wpdb->esc_like( 'manage-' ) . '%' . $wpdb->esc_like( '-columns-hidden' ) . '%',
				$prefix . '%' . $wpdb->esc_like( 'meta-box-order' ) . '%',
				$prefix . '%' . $wpdb->esc_like( 'metaboxorder' ) . '%',
				$prefix . '%' . $wpdb->esc_like( 'screen_layout' ) . '%'
			)
		);
	}
}

/**
 * Execute changes made in WordPress 3.3.
 *
 * @ignore
 * @since 3.3.0
 *
 * @global int   $wp_current_db_version The old (current) database version.
 * @global wpdb  $wpdb                  WordPress database abstraction object.
 * @global array $wp_registered_widgets
 * @global array $sidebars_widgets
 */
function upgrade_330() {
	global $wp_current_db_version, $wpdb, $wp_registered_widgets, $sidebars_widgets;

	if ( $wp_current_db_version < 19061 && wp_should_upgrade_global_tables() ) {
		$wpdb->query( "DELETE FROM $wpdb->usermeta WHERE meta_key IN ('show_admin_bar_admin', 'plugins_last_view')" );
	}

	if ( $wp_current_db_version >= 11548 ) {
		return;
	}

	$sidebars_widgets  = get_option( 'sidebars_widgets', array() );
	$_sidebars_widgets = array();

	if ( isset( $sidebars_widgets['wp_inactive_widgets'] ) || empty( $sidebars_widgets ) ) {
		$sidebars_widgets['array_version'] = 3;
	} elseif ( ! isset( $sidebars_widgets['array_version'] ) ) {
		$sidebars_widgets['array_version'] = 1;
	}

	switch ( $sidebars_widgets['array_version'] ) {
		case 1:
			foreach ( (array) $sidebars_widgets as $index => $sidebar ) {
				if ( is_array( $sidebar ) ) {
					foreach ( (array) $sidebar as $i => $name ) {
						$id = strtolower( $name );
						if ( isset( $wp_registered_widgets[ $id ] ) ) {
							$_sidebars_widgets[ $index ][ $i ] = $id;
							continue;
						}

						$id = sanitize_title( $name );
						if ( isset( $wp_registered_widgets[ $id ] ) ) {
							$_sidebars_widgets[ $index ][ $i ] = $id;
							continue;
						}

						$found = false;

						foreach ( $wp_registered_widgets as $widget_id => $widget ) {
							if ( strtolower( $widget['name'] ) === strtolower( $name ) ) {
								$_sidebars_widgets[ $index ][ $i ] = $widget['id'];

								$found = true;
								break;
							} elseif ( sanitize_title( $widget['name'] ) === sanitize_title( $name ) ) {
								$_sidebars_widgets[ $index ][ $i ] = $widget['id'];

								$found = true;
								break;
							}
						}

						if ( $found ) {
							continue;
						}

						unset( $_sidebars_widgets[ $index ][ $i ] );
					}
				}
			}
			$_sidebars_widgets['array_version'] = 2;
			$sidebars_widgets                   = $_sidebars_widgets;
			unset( $_sidebars_widgets );

			// Intentional fall-through to upgrade to the next version.
		case 2:
			$sidebars_widgets                  = retrieve_widgets();
			$sidebars_widgets['array_version'] = 3;
			update_option( 'sidebars_widgets', $sidebars_widgets );
	}
}

/**
 * Execute changes made in WordPress 3.4.
 *
 * @ignore
 * @since 3.4.0
 *
 * @global int  $wp_current_db_version The old (current) database version.
 * @global wpdb $wpdb                  WordPress database abstraction object.
 */
function upgrade_340() {
	global $wp_current_db_version, $wpdb;

	if ( $wp_current_db_version < 19798 ) {
		$wpdb->hide_errors();
		$wpdb->query( "ALTER TABLE $wpdb->options DROP COLUMN blog_id" );
		$wpdb->show_errors();
	}

	if ( $wp_current_db_version < 19799 ) {
		$wpdb->hide_errors();
		$wpdb->query( "ALTER TABLE $wpdb->comments DROP INDEX comment_approved" );
		$wpdb->show_errors();
	}

	if ( $wp_current_db_version < 20022 && wp_should_upgrade_global_tables() ) {
		$wpdb->query( "DELETE FROM $wpdb->usermeta WHERE meta_key = 'themes_last_view'" );
	}

	if ( $wp_current_db_version < 20080 ) {
		if ( 'yes' === $wpdb->get_var( "SELECT autoload FROM $wpdb->options WHERE option_name = 'uninstall_plugins'" ) ) {
			$uninstall_plugins = get_option( 'uninstall_plugins' );
			delete_option( 'uninstall_plugins' );
			add_option( 'uninstall_plugins', $uninstall_plugins, null, false );
		}
	}
}

/**
 * Execute changes made in WordPress 3.5.
 *
 * @ignore
 * @since 3.5.0
 *
 * @global int  $wp_current_db_version The old (current) database version.
 * @global wpdb $wpdb                  WordPress database abstraction object.
 */
function upgrade_350() {
	global $wp_current_db_version, $wpdb;

	if ( $wp_current_db_version < 22006 && $wpdb->get_var( "SELECT link_id FROM $wpdb->links LIMIT 1" ) ) {
		update_option( 'link_manager_enabled', 1 ); // Previously set to 0 by populate_options().
	}

	if ( $wp_current_db_version < 21811 && wp_should_upgrade_global_tables() ) {
		$meta_keys = array();
		foreach ( array_merge( get_post_types(), get_taxonomies() ) as $name ) {
			if ( str_contains( $name, '-' ) ) {
				$meta_keys[] = 'edit_' . str_replace( '-', '_', $name ) . '_per_page';
			}
		}
		if ( $meta_keys ) {
			$meta_keys = implode( "', '", $meta_keys );
			$wpdb->query( "DELETE FROM $wpdb->usermeta WHERE meta_key IN ('$meta_keys')" );
		}
	}

	if ( $wp_current_db_version < 22422 ) {
		$term = get_term_by( 'slug', 'post-format-standard', 'post_format' );
		if ( $term ) {
			wp_delete_term( $term->term_id, 'post_format' );
		}
	}
}

/**
 * Execute changes made in WordPress 3.7.
 *
 * @ignore
 * @since 3.7.0
 *
 * @global int $wp_current_db_version The old (current) database version.
 */
function upgrade_370() {
	global $wp_current_db_version;

	if ( $wp_current_db_version < 25824 ) {
		wp_clear_scheduled_hook( 'wp_auto_updates_maybe_update' );
	}
}

/**
 * Execute changes made in WordPress 3.7.2.
 *
 * @ignore
 * @since 3.7.2
 *
 * @global int $wp_current_db_version The old (current) database version.
 */
function upgrade_372() {
	global $wp_current_db_version;

	if ( $wp_current_db_version < 26148 ) {
		wp_clear_scheduled_hook( 'wp_maybe_auto_update' );
	}
}

/**
 * Execute changes made in WordPress 3.8.0.
 *
 * @ignore
 * @since 3.8.0
 *
 * @global int $wp_current_db_version The old (current) database version.
 */
function upgrade_380() {
	global $wp_current_db_version;

	if ( $wp_current_db_version < 26691 ) {
		deactivate_plugins( array( 'mp6/mp6.php' ), true );
	}
}

/**
 * Execute changes made in WordPress 4.0.0.
 *
 * @ignore
 * @since 4.0.0
 *
 * @global int $wp_current_db_version The old (current) database version.
 */
function upgrade_400() {
	global $wp_current_db_version;

	if ( $wp_current_db_version < 29630 ) {
		if ( ! is_multisite() && false === get_option( 'WPLANG' ) ) {
			if ( defined( 'WPLANG' ) && ( '' !== WPLANG ) && in_array( WPLANG, get_available_languages(), true ) ) {
				update_option( 'WPLANG', WPLANG );
			} else {
				update_option( 'WPLANG', '' );
			}
		}
	}
}

/**
 * Execute changes made in WordPress 4.2.0.
 *
 * @ignore
 * @since 4.2.0
 */
function upgrade_420() {}

/**
 * Executes changes made in WordPress 4.3.0.
 *
 * @ignore
 * @since 4.3.0
 *
 * @global int  $wp_current_db_version The old (current) database version.
 * @global wpdb $wpdb                  WordPress database abstraction object.
 */
function upgrade_430() {
	global $wp_current_db_version, $wpdb;

	if ( $wp_current_db_version < 32364 ) {
		upgrade_430_fix_comments();
	}

	// Shared terms are split in a separate process.
	if ( $wp_current_db_version < 32814 ) {
		update_option( 'finished_splitting_shared_terms', 0 );
		wp_schedule_single_event( time() + ( 1 * MINUTE_IN_SECONDS ), 'wp_split_shared_term_batch' );
	}

	if ( $wp_current_db_version < 33055 && 'utf8mb4' === $wpdb->charset ) {
		if ( is_multisite() ) {
			$tables = $wpdb->tables( 'blog' );
		} else {
			$tables = $wpdb->tables( 'all' );
			if ( ! wp_should_upgrade_global_tables() ) {
				$global_tables = $wpdb->tables( 'global' );
				$tables        = array_diff_assoc( $tables, $global_tables );
			}
		}

		foreach ( $tables as $table ) {
			maybe_convert_table_to_utf8mb4( $table );
		}
	}
}

/**
 * Executes comments changes made in WordPress 4.3.0.
 *
 * @ignore
 * @since 4.3.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 */
function upgrade_430_fix_comments() {
	global $wpdb;

	$content_length = $wpdb->get_col_length( $wpdb->comments, 'comment_content' );

	if ( is_wp_error( $content_length ) ) {
		return;
	}

	if ( false === $content_length ) {
		$content_length = array(
			'type'   => 'byte',
			'length' => 65535,
		);
	} elseif ( ! is_array( $content_length ) ) {
		$length         = (int) $content_length > 0 ? (int) $content_length : 65535;
		$content_length = array(
			'type'   => 'byte',
			'length' => $length,
		);
	}

	if ( 'byte' !== $content_length['type'] || 0 === $content_length['length'] ) {
		// Sites with malformed DB schemas are on their own.
		return;
	}

	$allowed_length = (int) $content_length['length'] - 10;

	$comments = $wpdb->get_results(
		"SELECT `comment_ID` FROM `{$wpdb->comments}`
			WHERE `comment_date_gmt` > '2015-04-26'
			AND LENGTH( `comment_content` ) >= {$allowed_length}
			AND ( `comment_content` LIKE '%<%' OR `comment_content` LIKE '%>%' )"
	);

	foreach ( $comments as $comment ) {
		wp_delete_comment( $comment->comment_ID, true );
	}
}

/**
 * Executes changes made in WordPress 4.3.1.
 *
 * @ignore
 * @since 4.3.1
 */
function upgrade_431() {
	// Fix incorrect cron entries for term splitting.
	$cron_array = _get_cron_array();
	if ( isset( $cron_array['wp_batch_split_terms'] ) ) {
		unset( $cron_array['wp_batch_split_terms'] );
		_set_cron_array( $cron_array );
	}
}

/**
 * Executes changes made in WordPress 4.4.0.
 *
 * @ignore
 * @since 4.4.0
 *
 * @global int  $wp_current_db_version The old (current) database version.
 * @global wpdb $wpdb                  WordPress database abstraction object.
 */
function upgrade_440() {
	global $wp_current_db_version, $wpdb;

	if ( $wp_current_db_version < 34030 ) {
		$wpdb->query( "ALTER TABLE {$wpdb->options} MODIFY option_name VARCHAR(191)" );
	}

	// Remove the unused 'add_users' role.
	$roles = wp_roles();
	foreach ( $roles->role_objects as $role ) {
		if ( $role->has_cap( 'add_users' ) ) {
			$role->remove_cap( 'add_users' );
		}
	}
}

/**
 * Executes changes made in WordPress 4.5.0.
 *
 * @ignore
 * @since 4.5.0
 *
 * @global int  $wp_current_db_version The old (current) database version.
 * @global wpdb $wpdb                  WordPress database abstraction object.
 */
function upgrade_450() {
	global $wp_current_db_version, $wpdb;

	if ( $wp_current_db_version < 36180 ) {
		wp_clear_scheduled_hook( 'wp_maybe_auto_update' );
	}

	// Remove unused email confirmation options, moved to usermeta.
	if ( $wp_current_db_version < 36679 && is_multisite() ) {
		$wpdb->query( "DELETE FROM $wpdb->options WHERE option_name REGEXP '^[0-9]+_new_email$'" );
	}

	// Remove unused user setting for wpLink.
	delete_user_setting( 'wplink' );
}

/**
 * Executes changes made in WordPress 4.6.0.
 *
 * @ignore
 * @since 4.6.0
 *
 * @global int $wp_current_db_version The old (current) database version.
 */
function upgrade_460() {
	global $wp_current_db_version;

	// Remove unused post meta.
	if ( $wp_current_db_version < 37854 ) {
		delete_post_meta_by_key( '_post_restored_from' );
	}

	// Remove plugins with callback as an array object/method as the uninstall hook, see #13786.
	if ( $wp_current_db_version < 37965 ) {
		$uninstall_plugins = get_option( 'uninstall_plugins', array() );

		if ( ! empty( $uninstall_plugins ) ) {
			foreach ( $uninstall_plugins as $basename => $callback ) {
				if ( is_array( $callback ) && is_object( $callback[0] ) ) {
					unset( $uninstall_plugins[ $basename ] );
				}
			}

			update_option( 'uninstall_plugins', $uninstall_plugins );
		}
	}
}

/**
 * Executes changes made in WordPress 5.0.0.
 *
 * @ignore
 * @since 5.0.0
 * @deprecated 5.1.0
 */
function upgrade_500() {
}

/**
 * Executes changes made in WordPress 5.1.0.
 *
 * @ignore
 * @since 5.1.0
 */
function upgrade_510() {
	delete_site_option( 'upgrade_500_was_gutenberg_active' );
}

/**
 * Executes changes made in WordPress 5.3.0.
 *
 * @ignore
 * @since 5.3.0
 */
function upgrade_530() {
	/*
	 * The `admin_email_lifespan` option may have been set by an admin that just logged in,
	 * saw the verification screen, clicked on a button there, and is now upgrading the db,
	 * or by populate_options() that is called earlier in upgrade_all().
	 * In the second case `admin_email_lifespan` should be reset so the verification screen
	 * is shown next time an admin logs in.
	 */
	if ( function_exists( 'current_user_can' ) && ! current_user_can( 'manage_options' ) ) {
		update_option( 'admin_email_lifespan', 0 );
	}
}

/**
 * Executes changes made in WordPress 5.5.0.
 *
 * @ignore
 * @since 5.5.0
 *
 * @global int $wp_current_db_version The old (current) database version.
 */
function upgrade_550() {
	global $wp_current_db_version;

	if ( $wp_current_db_version < 48121 ) {
		$comment_previously_approved = get_option( 'comment_whitelist', '' );
		update_option( 'comment_previously_approved', $comment_previously_approved );
		delete_option( 'comment_whitelist' );
	}

	if ( $wp_current_db_version < 48575 ) {
		// Use more clear and inclusive language.
		$disallowed_list = get_option( 'blacklist_keys' );

		/*
		 * This option key was briefly renamed `blocklist_keys`.
		 * Account for sites that have this key present when the original key does not exist.
		 */
		if ( false === $disallowed_list ) {
			$disallowed_list = get_option( 'blocklist_keys' );
		}

		update_option( 'disallowed_keys', $disallowed_list );
		delete_option( 'blacklist_keys' );
		delete_option( 'blocklist_keys' );
	}

	if ( $wp_current_db_version < 48748 ) {
		update_option( 'finished_updating_comment_type', 0 );
		wp_schedule_single_event( time() + ( 1 * MINUTE_IN_SECONDS ), 'wp_update_comment_type_batch' );
	}
}

/**
 * Executes changes made in WordPress 5.6.0.
 *
 * @ignore
 * @since 5.6.0
 *
 * @global int  $wp_current_db_version The old (current) database version.
 * @global wpdb $wpdb                  WordPress database abstraction object.
 */
function upgrade_560() {
	global $wp_current_db_version, $wpdb;

	if ( $wp_current_db_version < 49572 ) {
		/*
		 * Clean up the `post_category` column removed from schema in version 2.8.0.
		 * Its presence may conflict with `WP_Post::__get()`.
		 */
		$post_category_exists = $wpdb->get_var( "SHOW COLUMNS FROM $wpdb->posts LIKE 'post_category'" );
		if ( ! is_null( $post_category_exists ) ) {
			$wpdb->query( "ALTER TABLE $wpdb->posts DROP COLUMN `post_category`" );
		}

		/*
		 * When upgrading from WP < 5.6.0 set the core major auto-updates option to `unset` by default.
		 * This overrides the same option from populate_options() that is intended for new installs.
		 * See https://core.trac.wordpress.org/ticket/51742.
		 */
		update_option( 'auto_update_core_major', 'unset' );
	}

	if ( $wp_current_db_version < 49632 ) {
		/*
		 * Regenerate the .htaccess file to add the `HTTP_AUTHORIZATION` rewrite rule.
		 * See https://core.trac.wordpress.org/ticket/51723.
		 */
		save_mod_rewrite_rules();
	}

	if ( $wp_current_db_version < 49735 ) {
		delete_transient( 'dirsize_cache' );
	}

	if ( $wp_current_db_version < 49752 ) {
		$results = $wpdb->get_results(
			$wpdb->prepare(
				"SELECT 1 FROM {$wpdb->usermeta} WHERE meta_key = %s LIMIT 1",
				WP_Application_Passwords::USERMETA_KEY_APPLICATION_PASSWORDS
			)
		);

		if ( ! empty( $results ) ) {
			$network_id = get_main_network_id();
			update_network_option( $network_id, WP_Application_Passwords::OPTION_KEY_IN_USE, 1 );
		}
	}
}

/**
 * Executes changes made in WordPress 5.9.0.
 *
 * @ignore
 * @since 5.9.0
 *
 * @global int $wp_current_db_version The old (current) database version.
 */
function upgrade_590() {
	global $wp_current_db_version;

	if ( $wp_current_db_version < 51917 ) {
		$crons = _get_cron_array();

		if ( $crons && is_array( $crons ) ) {
			// Remove errant `false` values, see #53950, #54906.
			$crons = array_filter( $crons );
			_set_cron_array( $crons );
		}
	}
}

/**
 * Executes changes made in WordPress 6.0.0.
 *
 * @ignore
 * @since 6.0.0
 *
 * @global int $wp_current_db_version The old (current) database version.
 */
function upgrade_600() {
	global $wp_current_db_version;

	if ( $wp_current_db_version < 53011 ) {
		wp_update_user_counts();
	}
}

/**
 * Executes changes made in WordPress 6.3.0.
 *
 * @ignore
 * @since 6.3.0
 *
 * @global int $wp_current_db_version The old (current) database version.
 */
function upgrade_630() {
	global $wp_current_db_version;

	if ( $wp_current_db_version < 55853 ) {
		if ( ! is_multisite() ) {
			// Replace non-autoload option can_compress_scripts with autoload option, see #55270
			$can_compress_scripts = get_option( 'can_compress_scripts', false );
			if ( false !== $can_compress_scripts ) {
				delete_option( 'can_compress_scripts' );
				add_option( 'can_compress_scripts', $can_compress_scripts, '', true );
			}
		}
	}
}

/**
 * Executes changes made in WordPress 6.4.0.
 *
 * @ignore
 * @since 6.4.0
 *
 * @global int $wp_current_db_version The old (current) database version.
 */
function upgrade_640() {
	global $wp_current_db_version;

	if ( $wp_current_db_version < 56657 ) {
		// Enable attachment pages.
		update_option( 'wp_attachment_pages_enabled', 1 );

		// Remove the wp_https_detection cron. Https status is checked directly in an async Site Health check.
		$scheduled = wp_get_scheduled_event( 'wp_https_detection' );
		if ( $scheduled ) {
			wp_clear_scheduled_hook( 'wp_https_detection' );
		}
	}
}

/**
 * Executes changes made in WordPress 6.5.0.
 *
 * @ignore
 * @since 6.5.0
 *
 * @global int  $wp_current_db_version The old (current) database version.
 * @global wpdb $wpdb                  WordPress database abstraction object.
 */
function upgrade_650() {
	global $wp_current_db_version, $wpdb;

	if ( $wp_current_db_version < 57155 ) {
		$stylesheet = get_stylesheet();

		// Set autoload=no for all themes except the current one.
		$theme_mods_options = $wpdb->get_col(
			$wpdb->prepare(
				"SELECT option_name FROM $wpdb->options WHERE autoload = 'yes' AND option_name != %s AND option_name LIKE %s",
				"theme_mods_$stylesheet",
				$wpdb->esc_like( 'theme_mods_' ) . '%'
			)
		);

		$autoload = array_fill_keys( $theme_mods_options, false );
		wp_set_option_autoload_values( $autoload );
	}
}

/**
 * Executes changes made in WordPress 6.7.0.
 *
 * @ignore
 * @since 6.7.0
 *
 * @global int  $wp_current_db_version The old (current) database version.
 */
function upgrade_670() {
	global $wp_current_db_version;

	if ( $wp_current_db_version < 58975 ) {
		$options = array(
			'recently_activated',
			'_wp_suggested_policy_text_has_changed',
			'dashboard_widget_options',
			'ftp_credentials',
			'adminhash',
			'nav_menu_options',
			'wp_force_deactivated_plugins',
			'delete_blog_hash',
			'allowedthemes',
			'recovery_keys',
			'https_detection_errors',
			'fresh_site',
		);

		wp_set_options_autoload( $options, false );
	}
}

/**
 * Executes changes made in WordPress 6.8.2.
 *
 * @ignore
 * @since 6.8.2
 *
 * @global int $wp_current_db_version The old (current) database version.
 */
function upgrade_682() {
	global $wp_current_db_version;

	if ( $wp_current_db_version < 60421 ) {
		// Upgrade Ping-O-Matic and Twingly to use HTTPS.
		$ping_sites_value = get_option( 'ping_sites' );
		$ping_sites_value = explode( "\n", $ping_sites_value );
		$ping_sites_value = array_map(
			function ( $url ) {
				$url = trim( $url );
				$url = sanitize_url( $url );
				if (
					str_ends_with( trailingslashit( $url ), '://rpc.pingomatic.com/' )
					|| str_ends_with( trailingslashit( $url ), '://rpc.twingly.com/' )
				) {
					$url = set_url_scheme( $url, 'https' );
				}
				return $url;
			},
			$ping_sites_value
		);
		$ping_sites_value = array_filter( $ping_sites_value );
		$ping_sites_value = implode( "\n", $ping_sites_value );
		update_option( 'ping_sites', $ping_sites_value );
	}
}

/**
 * Executes network-level upgrade routines.
 *
 * @since 3.0.0
 *
 * @global int  $wp_current_db_version The old (current) database version.
 * @global wpdb $wpdb                  WordPress database abstraction object.
 */
function upgrade_network() {
	global $wp_current_db_version, $wpdb;

	// Always clear expired transients.
	delete_expired_transients( true );

	// 2.8.0
	if ( $wp_current_db_version < 11549 ) {
		$wpmu_sitewide_plugins   = get_site_option( 'wpmu_sitewide_plugins' );
		$active_sitewide_plugins = get_site_option( 'active_sitewide_plugins' );
		if ( $wpmu_sitewide_plugins ) {
			if ( ! $active_sitewide_plugins ) {
				$sitewide_plugins = (array) $wpmu_sitewide_plugins;
			} else {
				$sitewide_plugins = array_merge( (array) $active_sitewide_plugins, (array) $wpmu_sitewide_plugins );
			}

			update_site_option( 'active_sitewide_plugins', $sitewide_plugins );
		}
		delete_site_option( 'wpmu_sitewide_plugins' );
		delete_site_option( 'deactivated_sitewide_plugins' );

		$start = 0;
		while ( $rows = $wpdb->get_results( "SELECT meta_key, meta_value FROM {$wpdb->sitemeta} ORDER BY meta_id LIMIT $start, 20" ) ) {
			foreach ( $rows as $row ) {
				$value = $row->meta_value;
				if ( ! @unserialize( $value ) ) {
					$value = stripslashes( $value );
				}
				if ( $value !== $row->meta_value ) {
					update_site_option( $row->meta_key, $value );
				}
			}
			$start += 20;
		}
	}

	// 3.0.0
	if ( $wp_current_db_version < 13576 ) {
		update_site_option( 'global_terms_enabled', '1' );
	}

	// 3.3.0
	if ( $wp_current_db_version < 19390 ) {
		update_site_option( 'initial_db_version', $wp_current_db_version );
	}

	if ( $wp_current_db_version < 19470 ) {
		if ( false === get_site_option( 'active_sitewide_plugins' ) ) {
			update_site_option( 'active_sitewide_plugins', array() );
		}
	}

	// 3.4.0
	if ( $wp_current_db_version < 20148 ) {
		// 'allowedthemes' keys things by stylesheet. 'allowed_themes' keyed things by name.
		$allowedthemes  = get_site_option( 'allowedthemes' );
		$allowed_themes = get_site_option( 'allowed_themes' );
		if ( false === $allowedthemes && is_array( $allowed_themes ) && $allowed_themes ) {
			$converted = array();
			$themes    = wp_get_themes();
			foreach ( $themes as $stylesheet => $theme_data ) {
				if ( isset( $allowed_themes[ $theme_data->get( 'Name' ) ] ) ) {
					$converted[ $stylesheet ] = true;
				}
			}
			update_site_option( 'allowedthemes', $converted );
			delete_site_option( 'allowed_themes' );
		}
	}

	// 3.5.0
	if ( $wp_current_db_version < 21823 ) {
		update_site_option( 'ms_files_rewriting', '1' );
	}

	// 3.5.2
	if ( $wp_current_db_version < 24448 ) {
		$illegal_names = get_site_option( 'illegal_names' );
		if ( is_array( $illegal_names ) && count( $illegal_names ) === 1 ) {
			$illegal_name  = reset( $illegal_names );
			$illegal_names = explode( ' ', $illegal_name );
			update_site_option( 'illegal_names', $illegal_names );
		}
	}

	// 4.2.0
	if ( $wp_current_db_version < 31351 && 'utf8mb4' === $wpdb->charset ) {
		if ( wp_should_upgrade_global_tables() ) {
			$wpdb->query( "ALTER TABLE $wpdb->usermeta DROP INDEX meta_key, ADD INDEX meta_key(meta_key(191))" );
			$wpdb->query( "ALTER TABLE $wpdb->site DROP INDEX domain, ADD INDEX domain(domain(140),path(51))" );
			$wpdb->query( "ALTER TABLE $wpdb->sitemeta DROP INDEX meta_key, ADD INDEX meta_key(meta_key(191))" );
			$wpdb->query( "ALTER TABLE $wpdb->signups DROP INDEX domain_path, ADD INDEX domain_path(domain(140),path(51))" );

			$tables = $wpdb->tables( 'global' );

			// sitecategories may not exist.
			if ( ! $wpdb->get_var( "SHOW TABLES LIKE '{$tables['sitecategories']}'" ) ) {
				unset( $tables['sitecategories'] );
			}

			foreach ( $tables as $table ) {
				maybe_convert_table_to_utf8mb4( $table );
			}
		}
	}

	// 4.3.0
	if ( $wp_current_db_version < 33055 && 'utf8mb4' === $wpdb->charset ) {
		if ( wp_should_upgrade_global_tables() ) {
			$upgrade = false;
			$indexes = $wpdb->get_results( "SHOW INDEXES FROM $wpdb->signups" );
			foreach ( $indexes as $index ) {
				if ( 'domain_path' === $index->Key_name && 'domain' === $index->Column_name && '140' !== $index->Sub_part ) {
					$upgrade = true;
					break;
				}
			}

			if ( $upgrade ) {
				$wpdb->query( "ALTER TABLE $wpdb->signups DROP INDEX domain_path, ADD INDEX domain_path(domain(140),path(51))" );
			}

			$tables = $wpdb->tables( 'global' );

			// sitecategories may not exist.
			if ( ! $wpdb->get_var( "SHOW TABLES LIKE '{$tables['sitecategories']}'" ) ) {
				unset( $tables['sitecategories'] );
			}

			foreach ( $tables as $table ) {
				maybe_convert_table_to_utf8mb4( $table );
			}
		}
	}

	// 5.1.0
	if ( $wp_current_db_version < 44467 ) {
		$network_id = get_main_network_id();
		delete_network_option( $network_id, 'site_meta_supported' );
		is_site_meta_supported();
	}
}

//
// General functions we use to actually do stuff.
//

/**
 * Creates a table in the database, if it doesn't already exist.
 *
 * This method checks for an existing database table and creates a new one if it's not
 * already present. It doesn't rely on MySQL's "IF NOT EXISTS" statement, but chooses
 * to query all tables first and then run the SQL statement creating the table.
 *
 * @since 1.0.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param string $table_name Database table name.
 * @param string $create_ddl SQL statement to create table.
 * @return bool True on success or if the table already exists. False on failure.
 */
function maybe_create_table( $table_name, $create_ddl ) {
	global $wpdb;

	$query = $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $table_name ) );

	if ( $wpdb->get_var( $query ) === $table_name ) {
		return true;
	}

	// Didn't find it, so try to create it.
	$wpdb->query( $create_ddl );

	// We cannot directly tell that whether this succeeded!
	if ( $wpdb->get_var( $query ) === $table_name ) {
		return true;
	}

	return false;
}

/**
 * Drops a specified index from a table.
 *
 * @since 1.0.1
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param string $table Database table name.
 * @param string $index Index name to drop.
 * @return true True, when finished.
 */
function drop_index( $table, $index ) {
	global $wpdb;

	$wpdb->hide_errors();

	$wpdb->query( "ALTER TABLE `$table` DROP INDEX `$index`" );

	// Now we need to take out all the extra ones we may have created.
	for ( $i = 0; $i < 25; $i++ ) {
		$wpdb->query( "ALTER TABLE `$table` DROP INDEX `{$index}_$i`" );
	}

	$wpdb->show_errors();

	return true;
}

/**
 * Adds an index to a specified table.
 *
 * @since 1.0.1
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param string $table Database table name.
 * @param string $index Database table index column.
 * @return true True, when done with execution.
 */
function add_clean_index( $table, $index ) {
	global $wpdb;

	drop_index( $table, $index );
	$wpdb->query( "ALTER TABLE `$table` ADD INDEX ( `$index` )" );

	return true;
}

/**
 * Adds column to a database table, if it doesn't already exist.
 *
 * @since 1.3.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param string $table_name  Database table name.
 * @param string $column_name Table column name.
 * @param string $create_ddl  SQL statement to add column.
 * @return bool True on success or if the column already exists. False on failure.
 */
function maybe_add_column( $table_name, $column_name, $create_ddl ) {
	global $wpdb;

	foreach ( $wpdb->get_col( "DESC $table_name", 0 ) as $column ) {
		if ( $column === $column_name ) {
			return true;
		}
	}

	// Didn't find it, so try to create it.
	$wpdb->query( $create_ddl );

	// We cannot directly tell that whether this succeeded!
	foreach ( $wpdb->get_col( "DESC $table_name", 0 ) as $column ) {
		if ( $column === $column_name ) {
			return true;
		}
	}

	return false;
}

/**
 * If a table only contains utf8 or utf8mb4 columns, convert it to utf8mb4.
 *
 * @since 4.2.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param string $table The table to convert.
 * @return bool True if the table was converted, false if it wasn't.
 */
function maybe_convert_table_to_utf8mb4( $table ) {
	global $wpdb;

	$results = $wpdb->get_results( "SHOW FULL COLUMNS FROM `$table`" );
	if ( ! $results ) {
		return false;
	}

	foreach ( $results as $column ) {
		if ( $column->Collation ) {
			list( $charset ) = explode( '_', $column->Collation );
			$charset         = strtolower( $charset );
			if ( 'utf8' !== $charset && 'utf8mb4' !== $charset ) {
				// Don't upgrade tables that have non-utf8 columns.
				return false;
			}
		}
	}

	$table_details = $wpdb->get_row( "SHOW TABLE STATUS LIKE '$table'" );
	if ( ! $table_details ) {
		return false;
	}

	list( $table_charset ) = explode( '_', $table_details->Collation );
	$table_charset         = strtolower( $table_charset );
	if ( 'utf8mb4' === $table_charset ) {
		return true;
	}

	return $wpdb->query( "ALTER TABLE $table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci" );
}

/**
 * Retrieve all options as it was for 1.2.
 *
 * @since 1.2.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @return stdClass List of options.
 */
function get_alloptions_110() {
	global $wpdb;
	$all_options = new stdClass();
	$options     = $wpdb->get_results( "SELECT option_name, option_value FROM $wpdb->options" );
	if ( $options ) {
		foreach ( $options as $option ) {
			if ( 'siteurl' === $option->option_name || 'home' === $option->option_name || 'category_base' === $option->option_name ) {
				$option->option_value = untrailingslashit( $option->option_value );
			}
			$all_options->{$option->option_name} = stripslashes( $option->option_value );
		}
	}
	return $all_options;
}

/**
 * Utility version of get_option that is private to installation/upgrade.
 *
 * @ignore
 * @since 1.5.1
 * @access private
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param string $setting Option name.
 * @return mixed
 */
function __get_option( $setting ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionDoubleUnderscore,PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.FunctionDoubleUnderscore
	global $wpdb;

	if ( 'home' === $setting && defined( 'WP_HOME' ) ) {
		return untrailingslashit( WP_HOME );
	}

	if ( 'siteurl' === $setting && defined( 'WP_SITEURL' ) ) {
		return untrailingslashit( WP_SITEURL );
	}

	$option = $wpdb->get_var( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s", $setting ) );

	if ( 'home' === $setting && ! $option ) {
		return __get_option( 'siteurl' );
	}

	if ( in_array( $setting, array( 'siteurl', 'home', 'category_base', 'tag_base' ), true ) ) {
		$option = untrailingslashit( $option );
	}

	return maybe_unserialize( $option );
}

/**
 * Filters for content to remove unnecessary slashes.
 *
 * @since 1.5.0
 *
 * @param string $content The content to modify.
 * @return string The de-slashed content.
 */
function deslash( $content ) {
	// Note: \\\ inside a regex denotes a single backslash.

	/*
	 * Replace one or more backslashes followed by a single quote with
	 * a single quote.
	 */
	$content = preg_replace( "/\\\+'/", "'", $content );

	/*
	 * Replace one or more backslashes followed by a double quote with
	 * a double quote.
	 */
	$content = preg_replace( '/\\\+"/', '"', $content );

	// Replace one or more backslashes with one backslash.
	$content = preg_replace( '/\\\+/', '\\', $content );

	return $content;
}

/**
 * Modifies the database based on specified SQL statements.
 *
 * Useful for creating new tables and updating existing tables to a new structure.
 *
 * @since 1.5.0
 * @since 6.1.0 Ignores display width for integer data types on MySQL 8.0.17 or later,
 *              to match MySQL behavior. Note: This does not affect MariaDB.
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param string[]|string $queries Optional. The query to run. Can be multiple queries
 *                                 in an array, or a string of queries separated by
 *                                 semicolons. Default empty string.
 * @param bool            $execute Optional. Whether or not to execute the query right away.
 *                                 Default true.
 * @return string[] Strings containing the results of the various update queries.
 */
function dbDelta( $queries = '', $execute = true ) { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.FunctionNameInvalid
	global $wpdb;

	if ( in_array( $queries, array( '', 'all', 'blog', 'global', 'ms_global' ), true ) ) {
		$queries = wp_get_db_schema( $queries );
	}

	// Separate individual queries into an array.
	if ( ! is_array( $queries ) ) {
		$queries = explode( ';', $queries );
		$queries = array_filter( $queries );
	}

	/**
	 * Filters the dbDelta SQL queries.
	 *
	 * @since 3.3.0
	 *
	 * @param string[] $queries An array of dbDelta SQL queries.
	 */
	$queries = apply_filters( 'dbdelta_queries', $queries );

	$cqueries   = array(); // Creation queries.
	$iqueries   = array(); // Insertion queries.
	$for_update = array();

	// Create a tablename index for an array ($cqueries) of recognized query types.
	foreach ( $queries as $qry ) {
		if ( preg_match( '|CREATE TABLE ([^ ]*)|', $qry, $matches ) ) {
			$table_name = trim( $matches[1], '`' );

			$cqueries[ $table_name ]   = $qry;
			$for_update[ $table_name ] = 'Created table ' . $matches[1];
			continue;
		}

		if ( preg_match( '|CREATE DATABASE ([^ ]*)|', $qry, $matches ) ) {
			array_unshift( $cqueries, $qry );
			continue;
		}

		if ( preg_match( '|INSERT INTO ([^ ]*)|', $qry, $matches ) ) {
			$iqueries[] = $qry;
			continue;
		}

		if ( preg_match( '|UPDATE ([^ ]*)|', $qry, $matches ) ) {
			$iqueries[] = $qry;
			continue;
		}
	}

	/**
	 * Filters the dbDelta SQL queries for creating tables and/or databases.
	 *
	 * Queries filterable via this hook contain "CREATE TABLE" or "CREATE DATABASE".
	 *
	 * @since 3.3.0
	 *
	 * @param string[] $cqueries An array of dbDelta create SQL queries.
	 */
	$cqueries = apply_filters( 'dbdelta_create_queries', $cqueries );

	/**
	 * Filters the dbDelta SQL queries for inserting or updating.
	 *
	 * Queries filterable via this hook contain "INSERT INTO" or "UPDATE".
	 *
	 * @since 3.3.0
	 *
	 * @param string[] $iqueries An array of dbDelta insert or update SQL queries.
	 */
	$iqueries = apply_filters( 'dbdelta_insert_queries', $iqueries );

	$text_fields = array( 'tinytext', 'text', 'mediumtext', 'longtext' );
	$blob_fields = array( 'tinyblob', 'blob', 'mediumblob', 'longblob' );
	$int_fields  = array( 'tinyint', 'smallint', 'mediumint', 'int', 'integer', 'bigint' );

	$global_tables  = $wpdb->tables( 'global' );
	$db_version     = $wpdb->db_version();
	$db_server_info = $wpdb->db_server_info();

	foreach ( $cqueries as $table => $qry ) {
		// Upgrade global tables only for the main site. Don't upgrade at all if conditions are not optimal.
		if ( in_array( $table, $global_tables, true ) && ! wp_should_upgrade_global_tables() ) {
			unset( $cqueries[ $table ], $for_update[ $table ] );
			continue;
		}

		// Fetch the table column structure from the database.
		$suppress    = $wpdb->suppress_errors();
		$tablefields = $wpdb->get_results( "DESCRIBE {$table};" );
		$wpdb->suppress_errors( $suppress );

		if ( ! $tablefields ) {
			continue;
		}

		// Clear the field and index arrays.
		$cfields                  = array();
		$indices                  = array();
		$indices_without_subparts = array();

		// Get all of the field names in the query from between the parentheses.
		preg_match( '|\((.*)\)|ms', $qry, $match2 );
		$qryline = trim( $match2[1] );

		// Separate field lines into an array.
		$flds = explode( "\n", $qryline );

		// For every field line specified in the query.
		foreach ( $flds as $fld ) {
			$fld = trim( $fld, " \t\n\r\0\x0B," ); // Default trim characters, plus ','.

			// Extract the field name.
			preg_match( '|^([^ ]*)|', $fld, $fvals );
			$fieldname            = trim( $fvals[1], '`' );
			$fieldname_lowercased = strtolower( $fieldname );

			// Verify the found field name.
			$validfield = true;
			switch ( $fieldname_lowercased ) {
				case '':
				case 'primary':
				case 'index':
				case 'fulltext':
				case 'unique':
				case 'key':
				case 'spatial':
					$validfield = false;

					/*
					 * Normalize the index definition.
					 *
					 * This is done so the definition can be compared against the result of a
					 * `SHOW INDEX FROM $table_name` query which returns the current table
					 * index information.
					 */

					// Extract type, name and columns from the definition.
					preg_match(
						'/^
							(?P<index_type>             # 1) Type of the index.
								PRIMARY\s+KEY|(?:UNIQUE|FULLTEXT|SPATIAL)\s+(?:KEY|INDEX)|KEY|INDEX
							)
							\s+                         # Followed by at least one white space character.
							(?:                         # Name of the index. Optional if type is PRIMARY KEY.
								`?                      # Name can be escaped with a backtick.
									(?P<index_name>     # 2) Name of the index.
										(?:[0-9a-zA-Z$_-]|[\xC2-\xDF][\x80-\xBF])+
									)
								`?                      # Name can be escaped with a backtick.
								\s+                     # Followed by at least one white space character.
							)*
							\(                          # Opening bracket for the columns.
								(?P<index_columns>
									.+?                 # 3) Column names, index prefixes, and orders.
								)
							\)                          # Closing bracket for the columns.
						$/imx',
						$fld,
						$index_matches
					);

					// Uppercase the index type and normalize space characters.
					$index_type = strtoupper( preg_replace( '/\s+/', ' ', trim( $index_matches['index_type'] ) ) );

					// 'INDEX' is a synonym for 'KEY', standardize on 'KEY'.
					$index_type = str_replace( 'INDEX', 'KEY', $index_type );

					// Escape the index name with backticks. An index for a primary key has no name.
					$index_name = ( 'PRIMARY KEY' === $index_type ) ? '' : '`' . strtolower( $index_matches['index_name'] ) . '`';

					// Parse the columns. Multiple columns are separated by a comma.
					$index_columns                  = array_map( 'trim', explode( ',', $index_matches['index_columns'] ) );
					$index_columns_without_subparts = $index_columns;

					// Normalize columns.
					foreach ( $index_columns as $id => &$index_column ) {
						// Extract column name and number of indexed characters (sub_part).
						preg_match(
							'/
								`?                      # Name can be escaped with a backtick.
									(?P<column_name>    # 1) Name of the column.
										(?:[0-9a-zA-Z$_-]|[\xC2-\xDF][\x80-\xBF])+
									)
								`?                      # Name can be escaped with a backtick.
								(?:                     # Optional sub part.
									\s*                 # Optional white space character between name and opening bracket.
									\(                  # Opening bracket for the sub part.
										\s*             # Optional white space character after opening bracket.
										(?P<sub_part>
											\d+         # 2) Number of indexed characters.
										)
										\s*             # Optional white space character before closing bracket.
									\)                  # Closing bracket for the sub part.
								)?
							/x',
							$index_column,
							$index_column_matches
						);

						// Escape the column name with backticks.
						$index_column = '`' . $index_column_matches['column_name'] . '`';

						// We don't need to add the subpart to $index_columns_without_subparts
						$index_columns_without_subparts[ $id ] = $index_column;

						// Append the optional sup part with the number of indexed characters.
						if ( isset( $index_column_matches['sub_part'] ) ) {
							$index_column .= '(' . $index_column_matches['sub_part'] . ')';
						}
					}

					// Build the normalized index definition and add it to the list of indices.
					$indices[]                  = "{$index_type} {$index_name} (" . implode( ',', $index_columns ) . ')';
					$indices_without_subparts[] = "{$index_type} {$index_name} (" . implode( ',', $index_columns_without_subparts ) . ')';

					// Destroy no longer needed variables.
					unset( $index_column, $index_column_matches, $index_matches, $index_type, $index_name, $index_columns, $index_columns_without_subparts );

					break;
			}

			// If it's a valid field, add it to the field array.
			if ( $validfield ) {
				$cfields[ $fieldname_lowercased ] = $fld;
			}
		}

		// For every field in the table.
		foreach ( $tablefields as $tablefield ) {
			$tablefield_field_lowercased = strtolower( $tablefield->Field );
			$tablefield_type_lowercased  = strtolower( $tablefield->Type );

			$tablefield_type_without_parentheses = preg_replace(
				'/'
				. '(.+)'       // Field type, e.g. `int`.
				. '\(\d*\)'    // Display width.
				. '(.*)'       // Optional attributes, e.g. `unsigned`.
				. '/',
				'$1$2',
				$tablefield_type_lowercased
			);

			// Get the type without attributes, e.g. `int`.
			$tablefield_type_base = strtok( $tablefield_type_without_parentheses, ' ' );

			// If the table field exists in the field array...
			if ( array_key_exists( $tablefield_field_lowercased, $cfields ) ) {

				// Get the field type from the query.
				preg_match( '|`?' . $tablefield->Field . '`? ([^ ]*( unsigned)?)|i', $cfields[ $tablefield_field_lowercased ], $matches );
				$fieldtype            = $matches[1];
				$fieldtype_lowercased = strtolower( $fieldtype );

				$fieldtype_without_parentheses = preg_replace(
					'/'
					. '(.+)'       // Field type, e.g. `int`.
					. '\(\d*\)'    // Display width.
					. '(.*)'       // Optional attributes, e.g. `unsigned`.
					. '/',
					'$1$2',
					$fieldtype_lowercased
				);

				// Get the type without attributes, e.g. `int`.
				$fieldtype_base = strtok( $fieldtype_without_parentheses, ' ' );

				// Is actual field type different from the field type in query?
				if ( $tablefield->Type !== $fieldtype_lowercased ) {
					$do_change = true;
					if ( in_array( $fieldtype_lowercased, $text_fields, true ) && in_array( $tablefield_type_lowercased, $text_fields, true ) ) {
						if ( array_search( $fieldtype_lowercased, $text_fields, true ) < array_search( $tablefield_type_lowercased, $text_fields, true ) ) {
							$do_change = false;
						}
					}

					if ( in_array( $fieldtype_lowercased, $blob_fields, true ) && in_array( $tablefield_type_lowercased, $blob_fields, true ) ) {
						if ( array_search( $fieldtype_lowercased, $blob_fields, true ) < array_search( $tablefield_type_lowercased, $blob_fields, true ) ) {
							$do_change = false;
						}
					}

					if ( in_array( $fieldtype_base, $int_fields, true ) && in_array( $tablefield_type_base, $int_fields, true )
						&& $fieldtype_without_parentheses === $tablefield_type_without_parentheses
					) {
						/*
						 * MySQL 8.0.17 or later does not support display width for integer data types,
						 * so if display width is the only difference, it can be safely ignored.
						 * Note: This is specific to MySQL and does not affect MariaDB.
						 */
						if ( version_compare( $db_version, '8.0.17', '>=' )
							&& ! str_contains( $db_server_info, 'MariaDB' )
						) {
							$do_change = false;
						}
					}

					if ( $do_change ) {
						// Add a query to change the column type.
						$cqueries[] = "ALTER TABLE {$table} CHANGE COLUMN `{$tablefield->Field}` " . $cfields[ $tablefield_field_lowercased ];

						$for_update[ $table . '.' . $tablefield->Field ] = "Changed type of {$table}.{$tablefield->Field} from {$tablefield->Type} to {$fieldtype}";
					}
				}

				// Get the default value from the array.
				if ( preg_match( "| DEFAULT '(.*?)'|i", $cfields[ $tablefield_field_lowercased ], $matches ) ) {
					$default_value = $matches[1];
					if ( $tablefield->Default !== $default_value ) {
						// Add a query to change the column's default value
						$cqueries[] = "ALTER TABLE {$table} ALTER COLUMN `{$tablefield->Field}` SET DEFAULT '{$default_value}'";

						$for_update[ $table . '.' . $tablefield->Field ] = "Changed default value of {$table}.{$tablefield->Field} from {$tablefield->Default} to {$default_value}";
					}
				}

				// Remove the field from the array (so it's not added).
				unset( $cfields[ $tablefield_field_lowercased ] );
			} else {
				// This field exists in the table, but not in the creation queries?
			}
		}

		// For every remaining field specified for the table.
		foreach ( $cfields as $fieldname => $fielddef ) {
			// Push a query line into $cqueries that adds the field to that table.
			$cqueries[] = "ALTER TABLE {$table} ADD COLUMN $fielddef";

			$for_update[ $table . '.' . $fieldname ] = 'Added column ' . $table . '.' . $fieldname;
		}

		// Index stuff goes here. Fetch the table index structure from the database.
		$tableindices = $wpdb->get_results( "SHOW INDEX FROM {$table};" );

		if ( $tableindices ) {
			// Clear the index array.
			$index_ary = array();

			// For every index in the table.
			foreach ( $tableindices as $tableindex ) {
				$keyname = strtolower( $tableindex->Key_name );

				// Add the index to the index data array.
				$index_ary[ $keyname ]['columns'][]  = array(
					'fieldname' => $tableindex->Column_name,
					'subpart'   => $tableindex->Sub_part,
				);
				$index_ary[ $keyname ]['unique']     = ( '0' === (string) $tableindex->Non_unique ) ? true : false;
				$index_ary[ $keyname ]['index_type'] = $tableindex->Index_type;
			}

			// For each actual index in the index array.
			foreach ( $index_ary as $index_name => $index_data ) {

				// Build a create string to compare to the query.
				$index_string = '';
				if ( 'primary' === $index_name ) {
					$index_string .= 'PRIMARY ';
				} elseif ( $index_data['unique'] ) {
					$index_string .= 'UNIQUE ';
				}

				if ( 'FULLTEXT' === strtoupper( $index_data['index_type'] ) ) {
					$index_string .= 'FULLTEXT ';
				}

				if ( 'SPATIAL' === strtoupper( $index_data['index_type'] ) ) {
					$index_string .= 'SPATIAL ';
				}

				$index_string .= 'KEY ';
				if ( 'primary' !== $index_name ) {
					$index_string .= '`' . $index_name . '`';
				}

				$index_columns = '';

				// For each column in the index.
				foreach ( $index_data['columns'] as $column_data ) {
					if ( '' !== $index_columns ) {
						$index_columns .= ',';
					}

					// Add the field to the column list string.
					$index_columns .= '`' . $column_data['fieldname'] . '`';
				}

				// Add the column list to the index create string.
				$index_string .= " ($index_columns)";

				// Check if the index definition exists, ignoring subparts.
				$aindex = array_search( $index_string, $indices_without_subparts, true );
				if ( false !== $aindex ) {
					// If the index already exists (even with different subparts), we don't need to create it.
					unset( $indices_without_subparts[ $aindex ] );
					unset( $indices[ $aindex ] );
				}
			}
		}

		// For every remaining index specified for the table.
		foreach ( (array) $indices as $index ) {
			// Push a query line into $cqueries that adds the index to that table.
			$cqueries[] = "ALTER TABLE {$table} ADD $index";

			$for_update[] = 'Added index ' . $table . ' ' . $index;
		}

		// Remove the original table creation query from processing.
		unset( $cqueries[ $table ], $for_update[ $table ] );
	}

	$allqueries = array_merge( $cqueries, $iqueries );
	if ( $execute ) {
		foreach ( $allqueries as $query ) {
			$wpdb->query( $query );
		}
	}

	return $for_update;
}

/**
 * Updates the database tables to a new schema.
 *
 * By default, updates all the tables to use the latest defined schema, but can also
 * be used to update a specific set of tables in wp_get_db_schema().
 *
 * @since 1.5.0
 *
 * @uses dbDelta
 *
 * @param string $tables Optional. Which set of tables to update. Default is 'all'.
 */
function make_db_current( $tables = 'all' ) {
	$alterations = dbDelta( $tables );
	echo "<ol>\n";
	foreach ( $alterations as $alteration ) {
		echo "<li>$alteration</li>\n";
	}
	echo "</ol>\n";
}

/**
 * Updates the database tables to a new schema, but without displaying results.
 *
 * By default, updates all the tables to use the latest defined schema, but can
 * also be used to update a specific set of tables in wp_get_db_schema().
 *
 * @since 1.5.0
 *
 * @see make_db_current()
 *
 * @param string $tables Optional. Which set of tables to update. Default is 'all'.
 */
function make_db_current_silent( $tables = 'all' ) {
	dbDelta( $tables );
}

/**
 * Creates a site theme from an existing theme.
 *
 * {@internal Missing Long Description}}
 *
 * @since 1.5.0
 *
 * @param string $theme_name The name of the theme.
 * @param string $template   The directory name of the theme.
 * @return bool
 */
function make_site_theme_from_oldschool( $theme_name, $template ) {
	$home_path   = get_home_path();
	$site_dir    = WP_CONTENT_DIR . "/themes/$template";
	$default_dir = WP_CONTENT_DIR . '/themes/' . WP_DEFAULT_THEME;

	if ( ! file_exists( "$home_path/index.php" ) ) {
		return false;
	}

	/*
	 * Copy files from the old locations to the site theme.
	 * TODO: This does not copy arbitrary include dependencies. Only the standard WP files are copied.
	 */
	$files = array(
		'index.php'             => 'index.php',
		'wp-layout.css'         => 'style.css',
		'wp-comments.php'       => 'comments.php',
		'wp-comments-popup.php' => 'comments-popup.php',
	);

	foreach ( $files as $oldfile => $newfile ) {
		if ( 'index.php' === $oldfile ) {
			$oldpath = $home_path;
		} else {
			$oldpath = ABSPATH;
		}

		// Check to make sure it's not a new index.
		if ( 'index.php' === $oldfile ) {
			$index = implode( '', file( "$oldpath/$oldfile" ) );
			if ( str_contains( $index, 'WP_USE_THEMES' ) ) {
				if ( ! copy( "$default_dir/$oldfile", "$site_dir/$newfile" ) ) {
					return false;
				}

				// Don't copy anything.
				continue;
			}
		}

		if ( ! copy( "$oldpath/$oldfile", "$site_dir/$newfile" ) ) {
			return false;
		}

		chmod( "$site_dir/$newfile", 0777 );

		// Update the blog header include in each file.
		$lines = explode( "\n", implode( '', file( "$site_dir/$newfile" ) ) );
		if ( $lines ) {
			$f = fopen( "$site_dir/$newfile", 'w' );

			foreach ( $lines as $line ) {
				if ( preg_match( '/require.*wp-blog-header/', $line ) ) {
					$line = '//' . $line;
				}

				// Update stylesheet references.
				$line = str_replace(
					"<?php echo __get_option('siteurl'); ?>/wp-layout.css",
					"<?php bloginfo('stylesheet_url'); ?>",
					$line
				);

				// Update comments template inclusion.
				$line = str_replace(
					"<?php include(ABSPATH . 'wp-comments.php'); ?>",
					'<?php comments_template(); ?>',
					$line
				);

				fwrite( $f, "{$line}\n" );
			}
			fclose( $f );
		}
	}

	// Add a theme header.
	$header = "/*\n" .
		"Theme Name: $theme_name\n" .
		'Theme URI: ' . __get_option( 'siteurl' ) . "\n" .
		"Description: A theme automatically created by the update.\n" .
		"Version: 1.0\n" .
		"Author: Moi\n" .
		"*/\n";

	$stylelines = file_get_contents( "$site_dir/style.css" );
	if ( $stylelines ) {
		$f = fopen( "$site_dir/style.css", 'w' );

		fwrite( $f, $header );
		fwrite( $f, $stylelines );
		fclose( $f );
	}

	return true;
}

/**
 * Creates a site theme from the default theme.
 *
 * {@internal Missing Long Description}}
 *
 * @since 1.5.0
 *
 * @param string $theme_name The name of the theme.
 * @param string $template   The directory name of the theme.
 * @return void|false
 */
function make_site_theme_from_default( $theme_name, $template ) {
	$site_dir    = WP_CONTENT_DIR . "/themes/$template";
	$default_dir = WP_CONTENT_DIR . '/themes/' . WP_DEFAULT_THEME;

	/*
	 * Copy files from the default theme to the site theme.
	 * $files = array( 'index.php', 'comments.php', 'comments-popup.php', 'footer.php', 'header.php', 'sidebar.php', 'style.css' );
	 */

	$theme_dir = @opendir( $default_dir );
	if ( $theme_dir ) {
		while ( ( $theme_file = readdir( $theme_dir ) ) !== false ) {
			if ( is_dir( "$default_dir/$theme_file" ) ) {
				continue;
			}

			if ( ! copy( "$default_dir/$theme_file", "$site_dir/$theme_file" ) ) {
				return;
			}

			chmod( "$site_dir/$theme_file", 0777 );
		}

		closedir( $theme_dir );
	}

	// Rewrite the theme header.
	$stylelines = explode( "\n", implode( '', file( "$site_dir/style.css" ) ) );
	if ( $stylelines ) {
		$f = fopen( "$site_dir/style.css", 'w' );

		$headers = array(
			'Theme Name:'  => $theme_name,
			'Theme URI:'   => __get_option( 'url' ),
			'Description:' => 'Your theme.',
			'Version:'     => '1',
			'Author:'      => 'You',
		);

		foreach ( $stylelines as $line ) {
			foreach ( $headers as $header => $value ) {
				if ( str_contains( $line, $header ) ) {
					$line = $header . ' ' . $value;
					break;
				}
			}

			fwrite( $f, $line . "\n" );
		}

		fclose( $f );
	}

	// Copy the images.
	umask( 0 );
	if ( ! mkdir( "$site_dir/images", 0777 ) ) {
		return false;
	}

	$images_dir = @opendir( "$default_dir/images" );
	if ( $images_dir ) {
		while ( ( $image = readdir( $images_dir ) ) !== false ) {
			if ( is_dir( "$default_dir/images/$image" ) ) {
				continue;
			}

			if ( ! copy( "$default_dir/images/$image", "$site_dir/images/$image" ) ) {
				return;
			}

			chmod( "$site_dir/images/$image", 0777 );
		}

		closedir( $images_dir );
	}
}

/**
 * Creates a site theme.
 *
 * {@internal Missing Long Description}}
 *
 * @since 1.5.0
 *
 * @return string|false
 */
function make_site_theme() {
	// Name the theme after the blog.
	$theme_name = __get_option( 'blogname' );
	$template   = sanitize_title( $theme_name );
	$site_dir   = WP_CONTENT_DIR . "/themes/$template";

	// If the theme already exists, nothing to do.
	if ( is_dir( $site_dir ) ) {
		return false;
	}

	// We must be able to write to the themes dir.
	if ( ! is_writable( WP_CONTENT_DIR . '/themes' ) ) {
		return false;
	}

	umask( 0 );
	if ( ! mkdir( $site_dir, 0777 ) ) {
		return false;
	}

	if ( file_exists( ABSPATH . 'wp-layout.css' ) ) {
		if ( ! make_site_theme_from_oldschool( $theme_name, $template ) ) {
			// TODO: rm -rf the site theme directory.
			return false;
		}
	} else {
		if ( ! make_site_theme_from_default( $theme_name, $template ) ) {
			// TODO: rm -rf the site theme directory.
			return false;
		}
	}

	// Make the new site theme active.
	$current_template = __get_option( 'template' );
	if ( WP_DEFAULT_THEME === $current_template ) {
		update_option( 'template', $template );
		update_option( 'stylesheet', $template );
	}
	return $template;
}

/**
 * Translate user level to user role name.
 *
 * @since 2.0.0
 *
 * @param int $level User level.
 * @return string User role name.
 */
function translate_level_to_role( $level ) {
	switch ( $level ) {
		case 10:
		case 9:
		case 8:
			return 'administrator';
		case 7:
		case 6:
		case 5:
			return 'editor';
		case 4:
		case 3:
		case 2:
			return 'author';
		case 1:
			return 'contributor';
		case 0:
		default:
			return 'subscriber';
	}
}

/**
 * Checks the version of the installed MySQL binary.
 *
 * @since 2.1.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 */
function wp_check_mysql_version() {
	global $wpdb;
	$result = $wpdb->check_database_version();
	if ( is_wp_error( $result ) ) {
		wp_die( $result );
	}
}

/**
 * Disables the Automattic widgets plugin, which was merged into core.
 *
 * @since 2.2.0
 */
function maybe_disable_automattic_widgets() {
	$plugins = __get_option( 'active_plugins' );

	foreach ( (array) $plugins as $plugin ) {
		if ( 'widgets.php' === basename( $plugin ) ) {
			array_splice( $plugins, array_search( $plugin, $plugins, true ), 1 );
			update_option( 'active_plugins', $plugins );
			break;
		}
	}
}

/**
 * Disables the Link Manager on upgrade if, at the time of upgrade, no links exist in the DB.
 *
 * @since 3.5.0
 *
 * @global int  $wp_current_db_version The old (current) database version.
 * @global wpdb $wpdb                  WordPress database abstraction object.
 */
function maybe_disable_link_manager() {
	global $wp_current_db_version, $wpdb;

	if ( $wp_current_db_version >= 22006 && get_option( 'link_manager_enabled' ) && ! $wpdb->get_var( "SELECT link_id FROM $wpdb->links LIMIT 1" ) ) {
		update_option( 'link_manager_enabled', 0 );
	}
}

/**
 * Runs before the schema is upgraded.
 *
 * @since 2.9.0
 *
 * @global int  $wp_current_db_version The old (current) database version.
 * @global wpdb $wpdb                  WordPress database abstraction object.
 */
function pre_schema_upgrade() {
	global $wp_current_db_version, $wpdb;

	// Upgrade versions prior to 2.9.
	if ( $wp_current_db_version < 11557 ) {
		// Delete duplicate options. Keep the option with the highest option_id.
		$wpdb->query( "DELETE o1 FROM $wpdb->options AS o1 JOIN $wpdb->options AS o2 USING (`option_name`) WHERE o2.option_id > o1.option_id" );

		// Drop the old primary key and add the new.
		$wpdb->query( "ALTER TABLE $wpdb->options DROP PRIMARY KEY, ADD PRIMARY KEY(option_id)" );

		// Drop the old option_name index. dbDelta() doesn't do the drop.
		$wpdb->query( "ALTER TABLE $wpdb->options DROP INDEX option_name" );
	}

	// Multisite schema upgrades.
	if ( $wp_current_db_version < 60497 && is_multisite() && wp_should_upgrade_global_tables() ) {

		// Upgrade versions prior to 3.7.
		if ( $wp_current_db_version < 25179 ) {
			// New primary key for signups.
			$wpdb->query( "ALTER TABLE $wpdb->signups ADD signup_id BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST" );
			$wpdb->query( "ALTER TABLE $wpdb->signups DROP INDEX domain" );
		}

		if ( $wp_current_db_version < 25448 ) {
			// Convert archived from enum to tinyint.
			$wpdb->query( "ALTER TABLE $wpdb->blogs CHANGE COLUMN archived archived varchar(1) NOT NULL default '0'" );
			$wpdb->query( "ALTER TABLE $wpdb->blogs CHANGE COLUMN archived archived tinyint(2) NOT NULL default 0" );
		}

		// Upgrade versions prior to 6.9
		if ( $wp_current_db_version < 60497 ) {
			// Convert ID columns from signed to unsigned
			$wpdb->query( "ALTER TABLE $wpdb->blogs MODIFY blog_id bigint(20) unsigned NOT NULL auto_increment" );
			$wpdb->query( "ALTER TABLE $wpdb->blogs MODIFY site_id bigint(20) unsigned NOT NULL default 0" );
			$wpdb->query( "ALTER TABLE $wpdb->blogmeta MODIFY blog_id bigint(20) unsigned NOT NULL default 0" );
			$wpdb->query( "ALTER TABLE $wpdb->registration_log MODIFY ID bigint(20) unsigned NOT NULL auto_increment" );
			$wpdb->query( "ALTER TABLE $wpdb->registration_log MODIFY blog_id bigint(20) unsigned NOT NULL default 0" );
			$wpdb->query( "ALTER TABLE $wpdb->site MODIFY id bigint(20) unsigned NOT NULL auto_increment" );
			$wpdb->query( "ALTER TABLE $wpdb->sitemeta MODIFY meta_id bigint(20) unsigned NOT NULL auto_increment" );
			$wpdb->query( "ALTER TABLE $wpdb->sitemeta MODIFY site_id bigint(20) unsigned NOT NULL default 0" );
			$wpdb->query( "ALTER TABLE $wpdb->signups MODIFY signup_id bigint(20) unsigned NOT NULL auto_increment" );
		}
	}

	// Upgrade versions prior to 4.2.
	if ( $wp_current_db_version < 31351 ) {
		if ( ! is_multisite() && wp_should_upgrade_global_tables() ) {
			$wpdb->query( "ALTER TABLE $wpdb->usermeta DROP INDEX meta_key, ADD INDEX meta_key(meta_key(191))" );
		}
		$wpdb->query( "ALTER TABLE $wpdb->terms DROP INDEX slug, ADD INDEX slug(slug(191))" );
		$wpdb->query( "ALTER TABLE $wpdb->terms DROP INDEX name, ADD INDEX name(name(191))" );
		$wpdb->query( "ALTER TABLE $wpdb->commentmeta DROP INDEX meta_key, ADD INDEX meta_key(meta_key(191))" );
		$wpdb->query( "ALTER TABLE $wpdb->postmeta DROP INDEX meta_key, ADD INDEX meta_key(meta_key(191))" );
		$wpdb->query( "ALTER TABLE $wpdb->posts DROP INDEX post_name, ADD INDEX post_name(post_name(191))" );
	}

	// Upgrade versions prior to 4.4.
	if ( $wp_current_db_version < 34978 ) {
		// If compatible termmeta table is found, use it, but enforce a proper index and update collation.
		if ( $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->termmeta}'" ) && $wpdb->get_results( "SHOW INDEX FROM {$wpdb->termmeta} WHERE Column_name = 'meta_key'" ) ) {
			$wpdb->query( "ALTER TABLE $wpdb->termmeta DROP INDEX meta_key, ADD INDEX meta_key(meta_key(191))" );
			maybe_convert_table_to_utf8mb4( $wpdb->termmeta );
		}
	}
}

/**
 * Determine if global tables should be upgraded.
 *
 * This function performs a series of checks to ensure the environment allows
 * for the safe upgrading of global WordPress database tables. It is necessary
 * because global tables will commonly grow to millions of rows on large
 * installations, and the ability to control their upgrade routines can be
 * critical to the operation of large networks.
 *
 * In a future iteration, this function may use `wp_is_large_network()` to more-
 * intelligently prevent global table upgrades. Until then, we make sure
 * WordPress is on the main site of the main network, to avoid running queries
 * more than once in multi-site or multi-network environments.
 *
 * @since 4.3.0
 *
 * @return bool Whether to run the upgrade routines on global tables.
 */
function wp_should_upgrade_global_tables() {

	// Return false early if explicitly not upgrading.
	if ( defined( 'DO_NOT_UPGRADE_GLOBAL_TABLES' ) ) {
		return false;
	}

	// Assume global tables should be upgraded.
	$should_upgrade = true;

	// Set to false if not on main network (does not matter if not multi-network).
	if ( ! is_main_network() ) {
		$should_upgrade = false;
	}

	// Set to false if not on main site of current network (does not matter if not multi-site).
	if ( ! is_main_site() ) {
		$should_upgrade = false;
	}

	/**
	 * Filters if upgrade routines should be run on global tables.
	 *
	 * @since 4.3.0
	 *
	 * @param bool $should_upgrade Whether to run the upgrade routines on global tables.
	 */
	return apply_filters( 'wp_should_upgrade_global_tables', $should_upgrade );
}
widgets/class-better-weather-widget.php000064400000011003151214002350014215 0ustar00<?php

/**
 * Recent Tab Widget
 */
class Better_Weather_Widget extends BF_Widget {

	/**
	 * Register widget with WordPress.
	 */
	function __construct() {

		// Back end form fields
		$this->fields = array(

			array(
				'name'          => __( 'Title', 'better-studio' ),
				'attr_id'       => 'title',
				'type'          => 'text',
				'section_class' => 'widefat',
			),

			array(
				'name'          => __( 'Location', 'better-studio' ),
				'attr_id'       => 'location',
				'type'          => 'text',
				'section_class' => 'widefat',
				'desc'          => '<a target="_blank" href="http://better-studio.net/plugins/better-weather/wp/#how-to-find-location">' . __( 'How to find location value!?', 'better-studio' ) . '</a>',
			),

			array(
				'name'          => __( 'Custom Location Name:', 'better-studio' ),
				'attr_id'       => 'locationName',
				'type'          => 'text',
				'section_class' => 'widefat',
			),

			array(
				'name'    => __( 'Show Location Name?', 'better-studio' ),
				'attr_id' => 'showLocation',
				'type'    => 'checkbox',
			),

			array(
				'name'    => __( 'Show Date?', 'better-studio' ),
				'attr_id' => 'showDate',
				'type'    => 'checkbox',
			),

			array(
				'name'          => __( 'Widget Style', 'better-studio' ),
				'attr_id'       => 'widgetStyle',
				'type'          => 'select',
				'section_class' => 'widefat',
				"options"       => array(
					'modern' => __( 'Modern Style', 'better-studio' ),
					'normal' => __( 'Normal Style', 'better-studio' ),
				),
			),

			array(
				'name'    => __( 'Show Next 4 Days Forecast!?', 'better-studio' ),
				'attr_id' => 'nextDays',
				'type'    => 'checkbox',
			),

			array(
				'name'          => __( 'Background Style', 'better-studio' ),
				'attr_id'       => 'bgType',
				'type'          => 'select',
				'section_class' => 'widefat',
				"options"       => array(
					'natural' => __( 'Natural Photo', 'better-studio' ),
					'static'  => __( 'Static Color', 'better-studio' ),
				),
			),

			array(
				'name'    => __( 'Background Color', 'better-studio' ),
				'attr_id' => 'bgColor',
				'type'    => 'color',
			),

			array(
				'name'          => __( 'Icons Style', 'better-studio' ),
				'attr_id'       => 'iconsType',
				'type'          => 'select',
				'section_class' => 'widefat',
				"options"       => array(
					'animated' => __( 'Animated Icon', 'better-studio' ),
					'static'   => __( 'Static Icon', 'better-studio' ),
				),
			),

			array(
				'name'    => __( 'Font Color', 'better-studio' ),
				'attr_id' => 'fontColor',
				'type'    => 'color',
			),

			array(
				'name'          => __( 'Temperature Unit', 'better-studio' ),
				'attr_id'       => 'unit',
				'type'          => 'select',
				'section_class' => 'widefat',
				"options"       => array(
					'C' => __( 'Celsius', 'better-studio' ),
					'F' => __( 'Fahrenheit', 'better-studio' ),
				),
			),

			array(
				'name'    => __( 'Show Temperature Unit?', 'better-studio' ),
				'attr_id' => 'showUnit',
				'type'    => 'checkbox',
			),

			array(
				'name'    => __( 'Show Visitors Location Status!?', 'better-studio' ),
				'attr_id' => 'visitorLocation',
				'type'    => 'checkbox',
				'desc'    => '<span style="display: block;color: #FF5353;">' . __( 'Before using this you should read <a target="_blank" href="http://better-studio.net/plugins/better-weather/wp/#requests-note">this note</a>', 'better-studio' ) . '</span>',
			),


		);

		parent::__construct(
			'BetterWeather',
			__( 'Better Weather', 'better-studio' ),
			array( 'description' => __( 'Boxed Weather Widget', 'better-studio' ) ),
			'better_weather_widget'
		);
	}


	/**
	 * Front-end display of widget.
	 *
	 * @see BetterWidget::widget()
	 * @see WP_Widget::widget()
	 *
	 * @param array $args     Widget arguments.
	 * @param array $instance Saved values from database.
	 */
	public function widget( $args, $instance ) {

		$instance = $this->parse_args( $this->defaults, $instance );

		echo $args['before_widget'];

		$title = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->base_widget_id );
		if ( ! empty( $title ) && $this->with_title ) {
			echo $args['before_title'] . $title . $args['after_title'];
		}

		$instance['style'] = $instance['widgetStyle'];

		if ( $instance['bgType'] == 'static' ) {
			$instance['naturalBackground'] = FALSE;
		}

		if ( $instance['iconsType'] == 'static' ) {
			$instance['animatedIcons'] = FALSE;
		}

		BW_Generator_Factory::generator()->generate( $instance );

		echo $args['after_widget'];
	}


}widgets/class-better-weather-inline-widget.php000064400000010277151214002350015505 0ustar00<?php

/**
 * Better Weather Inline Widget
 */
class Better_Weather_Inline_Widget extends BF_Widget {

	/**
	 * Register widget with WordPress.
	 */
	function __construct() {

		// Back end form fields
		$this->fields = array(

			array(
				'name'          => __( 'Title', 'better-studio' ),
				'attr_id'       => 'title',
				'type'          => 'text',
				'section_class' => 'widefat',
			),

			array(
				'name'          => __( 'Location', 'better-studio' ),
				'attr_id'       => 'location',
				'type'          => 'text',
				'section_class' => 'widefat',
				'desc'          => '<a target="_blank" href="http://better-studio.net/plugins/better-weather/wp/#how-to-find-location">' . __( 'How to find location value!?', 'better-studio' ) . '</a>',
			),

			array(
				'name'          => __( 'Widget Size', 'better-studio' ),
				'attr_id'       => 'inline_size',
				'type'          => 'select',
				'section_class' => 'widefat',
				"options"       => array(
					'large'  => __( 'Large Style', 'better-studio' ),
					'medium' => __( 'Medium Style', 'better-studio' ),
					'small'  => __( 'Small Style', 'better-studio' ),
				),
			),

			array(
				'name'          => __( 'Icons Style', 'better-studio' ),
				'attr_id'       => 'icons_type',
				'type'          => 'select',
				'section_class' => 'widefat',
				"options"       => array(
					'animated' => __( 'Animated Icon', 'better-studio' ),
					'static'   => __( 'Static Icon', 'better-studio' ),
				),
			),

			array(
				'name'    => __( 'Font Color', 'better-studio' ),
				'attr_id' => 'font_color',
				'type'    => 'color',
			),

			array(
				'name'          => __( 'Temperature Unit', 'better-studio' ),
				'attr_id'       => 'unit',
				'type'          => 'select',
				'section_class' => 'widefat',
				"options"       => array(
					'C' => __( 'Celsius', 'better-studio' ),
					'F' => __( 'Fahrenheit', 'better-studio' ),
				),
			),

			array(
				'name'    => __( 'Show Temperature Unit?', 'better-studio' ),
				'attr_id' => 'show_unit',
				'type'    => 'checkbox',
			),

			array(
				'name'    => __( 'Show Visitors Location Status!?', 'better-studio' ),
				'attr_id' => 'visitor_location',
				'type'    => 'checkbox',
				'desc'    => '<span style="display: block;color: #FF5353;">' . __( 'Before using this you should read <a target="_blank" href="http://better-studio.net/plugins/better-weather/wp/#requests-note">this note</a>', 'better-studio' ) . '</span>',
			),

		);

		parent::__construct(
			'BetterWeather-inline',
			__( 'Better Weather Inline', 'better-studio' ),
			array( 'description' => __( 'Inline Weather Widget', 'better-studio' ) )
		);
	}


	/**
	 * Front-end display of widget.
	 *
	 * @see BetterWidget::widget()
	 * @see WP_Widget::widget()
	 *
	 * @param array $args     Widget arguments.
	 * @param array $instance Saved values from database.
	 */
	public function widget( $args, $instance ) {

		$instance = $this->parse_args( $this->defaults, $instance );


		echo $args['before_widget'];

		$title = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->base_widget_id );
		if ( ! empty( $title ) && $this->with_title ) {
			echo $args['before_title'] . $title . $args['after_title'];
		}

		$options = array(
			"showLocation"    => TRUE,
			"locationName"    => '',
			"showDate"        => TRUE,
			"nextDays"        => FALSE,
			"location"        => isset( $instance['location'] ) ? $instance['location'] : '',
			"fontColor"       => isset( $instance['font_color'] ) ? $instance['font_color'] : '#606568',
			"visitorLocation" => isset( $instance['visitor_location'] ) ? $instance['visitor_location'] : FALSE,
			"inlineSize"      => isset( $instance['inline_size'] ) ? $instance['inline_size'] : 'medium',
			"unit"            => isset( $instance['unit'] ) ? $instance['unit'] : 'C',
			"iconsType"       => isset( $instance['icons_type'] ) ? $instance['icons_type'] : 'animated',
			"showUnit"        => isset( $instance['show_unit'] ) ? $instance['show_unit'] : 'off',
			"mode"            => 'inline',
		);

		if ( $options['iconsType'] == 'static' ) {
			$options['animatedIcons'] = FALSE;
		}

		BW_Generator_Factory::generator()->generate_inline( $options );

		echo $args['after_widget'];
	}


}shortcodes/class-better-weather-inline-shortcode.php000064400000003337151214002350016722 0ustar00<?php

/**
 * Better Weather Inline Shortcode
 */
class Better_Weather_Inline_Shortcode extends BF_Shortcode {

	function __construct( $id, $options ) {

		$id = 'BetterWeather-inline';

		$_options = array(
			'defaults' => array(
				'location'         => '',
				'visitor_location' => FALSE,
				'font_color'       => '#000000',
				'icons_type'       => 'animated',
				'inline_size'      => 'large',
				"unit"             => 'C',
				"show_unit"        => FALSE,
			),

			'have_widget'    => TRUE,
			'have_vc_add_on' => FALSE,
		);

		$_options = wp_parse_args( $_options, $options );

		parent::__construct( $id, $_options );

	}


	/**
	 * Handle displaying of shortcode
	 *
	 * @param array  $atts
	 * @param string $content
	 *
	 * @return string
	 */
	function display( array $atts, $content = '' ) {

		$options = array(
			"location"        => isset( $atts['location'] ) ? $atts['location'] : '',
			"fontColor"       => isset( $atts['font_color'] ) ? $atts['font_color'] : '#fff',
			"visitorLocation" => isset( $atts['visitor_location'] ) ? $atts['visitor_location'] : FALSE,
			"inlineSize"      => isset( $atts['inline_size'] ) ? $atts['inline_size'] : 'medium',
			"unit"            => isset( $atts['unit'] ) ? $atts['unit'] : 'C',
			"iconsType"       => isset( $atts['icons_type'] ) ? $atts['icons_type'] : 'animated',
			"showUnit"        => isset( $atts['show_unit'] ) ? $atts['show_unit'] : 'off',
		);

		$options['visitorLocation'] = $options['visitorLocation'] == 'on' ? TRUE : FALSE;

		$options['showUnit'] = $options['showUnit'] == 'on' ? TRUE : FALSE;

		if ( $options['iconsType'] == 'static' ) {
			$options['animatedIcons'] = FALSE;
		}

		return BW_Generator_Factory::generator()->generate_inline( $options, FALSE );

	}

}shortcodes/class-better-weather-shortcode.php000064400000005667151214002350015456 0ustar00<?php

/**
 * Better Weather Shortcode
 */
class Better_Weather_Shortcode extends BF_Shortcode {

	function __construct( $id, $options ) {

		$id = 'BetterWeather';

		$this->name = __( 'BetterWeather', 'better-studio' );

		$this->description = __( 'Modern listing with 2, 3 and 4 column option', 'better-studio' );

		$this->icon = ( '' . 'images/vc-' . $id . '.png' );

		$_options = array(
			'defaults' => array(

				'title' => '',

				'location'        => '',
				'locationName'    => '',
				'fontColor'       => '#fff',
				'bgColor'         => '#4f4f4f',
				'style'           => 'modern',
				'nextDays'        => 'on',
				'visitorLocation' => FALSE,
				'bgType'          => 'natural',
				'iconsType'       => 'animated',
				'unit'            => 'C',
				'showUnit'        => 'off',
				'showDate'        => 'on',
				'showLocation'    => 'on',
			),

			'have_widget'    => TRUE,
			'have_vc_add_on' => FALSE,
		);

		$_options = wp_parse_args( $_options, $options );

		parent::__construct( $id, $_options );

	}

	/**
	 * Handle displaying of shortcode
	 *
	 * @param array  $atts
	 * @param string $content
	 *
	 * @return string
	 */
	function display( array $atts, $content = '' ) {

		$options = array(
			"location"        => isset( $atts['location'] ) ? $atts['location'] : '',
			"locationName"    => isset( $atts['location_name'] ) ? $atts['location_name'] : '',
			"fontColor"       => isset( $atts['font_color'] ) ? $atts['font_color'] : '#fff',
			"bgColor"         => isset( $atts['bg_color'] ) ? $atts['bg_color'] : '#4f4f4f',
			"style"           => isset( $atts['style'] ) ? $atts['style'] : 'modern',
			"nextDays"        => isset( $atts['next_days'] ) ? $atts['next_days'] : 'on',
			"visitorLocation" => isset( $atts['visitor_location'] ) ? $atts['visitor_location'] : FALSE,
			"showLocation"    => isset( $atts['show_location'] ) ? $atts['show_location'] : 'on',
			"showDate"        => isset( $atts['show_date'] ) ? $atts['show_date'] : 'on',
			"unit"            => isset( $atts['unit'] ) ? $atts['unit'] : 'C',
			"showUnit"        => isset( $atts['show_unit'] ) ? $atts['show_unit'] : 'off',
		);

		if ( ! isset( $atts['bg_type'] ) ) {
			$atts['bg_type'] = 'natural';
		}

		$options['showLocation']    = $options['showLocation'] == 'on' ? TRUE : FALSE;
		$options['nextDays']        = $options['nextDays'] == 'on' ? TRUE : FALSE;
		$options['visitorLocation'] = $options['visitorLocation'] == 'on' ? TRUE : FALSE;
		$options['showUnit']        = $options['showUnit'] == 'on' ? TRUE : FALSE;
		$options['showDate']        = $options['showDate'] == 'on' ? TRUE : FALSE;

		if ( $atts['bg_type'] == 'static' ) {
			$options['naturalBackground'] = FALSE;
		}

		if ( ! isset( $atts['icons_type'] ) ) {
			$atts['icons_type'] = 'animated';
		}

		if ( $atts['icons_type'] == 'static' ) {
			$options['animatedIcons'] = FALSE;
		} else {
			$options['animatedIcons'] = TRUE;
		}

		return BW_Generator_Factory::generator()->generate( $options, FALSE );

	}

}libs/better-framework/page-builder/compatibility/kc/kc.nocache_templates.php000064400000003175151214002350023345 0ustar00<?php
/**
*
*	King Composer
*	(c) KingComposer.com
*
*/
if(!defined('KC_FILE')) {
	header('HTTP/1.0 403 Forbidden');
	exit;
}

global $kc;

?>
<div id="kc-right-click-helper"><i class="sl-close"></i></div>
<div style="display:none;" id="kc-storage-prepare">
	<div id="kc-css-box-test"></div>
</div>
<img width="50" src="<?php echo KC_URL; ?>/assets/images/drag.png" id="kc-ui-handle-image" />
<img width="50" src="<?php echo KC_URL; ?>/assets/images/drag-copy.png" id="kc-ui-handle-image-copy" />
<div id="kc-undo-deleted-element">
	<a href="javascript:void(0)" class="do-action">
		<i class="sl-action-undo"></i> <?php _e('Restore deleted items', 'kingcomposer'); ?>
		<span class="amount">0</span>
	</a>	
	<div id="drop-to-delete"><span></span></div>
	<i class="sl-close"></i>	
</div>
<script type="text/html" id="tmpl-kc-top-nav-template">
<?php do_action('kc-top-nav'); ?>
</script>
<script type="text/html" id="tmpl-kc-wp-widgets-template">
<div id="kc-wp-list-widgets"><?php

	if( !function_exists( 'submit_button' ) ){
		function submit_button( $text = null, $type = 'primary', $name = 'submit', $wrap = true, $other_attributes = null ) {
			echo kc_get_submit_button( $text, $type, $name, $wrap, $other_attributes );
		}
	}

	ob_start();

	global $wp_registered_widget_controls;

	$controls = $wp_registered_widget_controls;

	$wp_registered_widget_controls = array();
	wp_list_widgets();

	$wp_registered_widget_controls = $controls;

		$content = str_replace( array( '<script', '</script>' ), array( '&lt;script', '&lt;/script&gt;' ), ob_get_contents() );
	ob_end_clean();

	echo $content;

?></div>
</script>
<?php do_action('kc_tmpl_nocache'); ?>


libs/better-framework/page-builder/compatibility/kc/class-bf-kc-compatibility.php000064400000016774151214002350024240 0ustar00<?php

if ( ! class_exists( 'BF_KC_Compatibility' ) ) {

	/**
	 * @since 4.0.0
	 */
	class BF_KC_Compatibility {

		/**
		 * @var self
		 */
		protected static $instance;


		/**
		 * @var array
		 */
		public static $deferred_fields_maps = array();


		/**
		 * @var array
		 */
		public static $dynamic_fields_maps = array();


		/**
		 * Get singleton instance of class
		 */
		public static function instance() {

			if ( ! self::$instance instanceof self ) {
				self::$instance = new self();
				self::$instance->init();
			}

			return self::$instance;
		}


		/**
		 * Initialize the library
		 *
		 * @since 4.0.0
		 */
		public function init() {

			global $kc_pro;

			//		 TODO: load widget lists via ajax
			// add_action( 'admin_footer', array( $this, 'optimized_kc_admin_footer' ) );
			// remove_action( 'admin_footer', 'kc_admin_footer' );

			if ( bf_is_doing_ajax() ) {

				add_action( 'wp_ajax_bf_kc_tmpl_storage', array( $this, 'kc_tmpl_storage' ) );
			}

			if ( $kc_pro && isset( $kc_pro->action ) && 'live-editor' === $kc_pro->action ) {

				add_action( 'kc_after_admin_footer', array( $this, 'append_security_token' ), 0 );
			}

			add_action( 'wp_ajax_bf_load_kc_fields', array( $this, 'ajax_load_fields' ) );
			add_action( 'edit_form_after_editor', array( $this, 'append_security_token' ) );

			add_filter( 'kc_maps', array( $this, 'filter_kc_maps_var' ) );
		}


		/**
		 * @see kc_ajax::tmpl_storage
		 */
		public function kc_tmpl_storage() {

			check_ajax_referer( 'kc-nonce', 'security' );

			global $kc;

			/**
			 * $kc->param_types_cache don't have getter method >.< i have to take it force
			 */
			$reflectionClass   = new ReflectionClass( $kc );
			$param_types_cache = $reflectionClass->getProperty( 'param_types_cache' );
			$param_types_cache->setAccessible( true );
			$param_types = $param_types_cache->getValue( $kc );

			if ( ! empty( $param_types ) ) {

				foreach ( $param_types as $name => $func ) {
					if ( function_exists( $func ) ) {

						echo '<script type="text/html" id="tmpl-kc-field-type-' . esc_attr( $name ) . '-template">';
						ob_start();
						$func();
						$field = ob_get_clean();

						$this->wrap_show_on_atts( $field );

						echo "</script>\n";

					}
				}
			}

			require_once KC_PATH . '/includes/kc.templates.php';
			do_action( 'kc_tmpl_storage' );

			echo '<!----END_KC_TMPL---->';

			exit;
		}


		public function wrap_show_on_atts( $input ) {

			include BF_PATH . 'page-builder/generators/kc/templates/default-js.php';
		}


		/**
		 * Optimized version of the kc_admin_footer() callback
		 *
		 * @hooked admin_footer
		 */
		public function optimized_kc_admin_footer() {

			if ( ! function_exists( 'kc_admin_enable' ) ) {
				return;
			}

			if ( is_admin() && ! kc_admin_enable() ) {
				return;
			}

			do_action( 'kc_before_admin_footer' );

			require_once KC_PATH . '/includes/kc.js_languages.php';
			require_once BF_PATH . 'page-builder/compatibility/kc/kc.nocache_templates.php';

			do_action( 'kc_after_admin_footer' );
		}


		/**
		 * @hooked wp_ajax_bf_load_kc_fields
		 */
		public function ajax_load_fields() {

			if ( empty( $_REQUEST['shortcode'] ) || empty( $_REQUEST['token'] ) ) {
				return;
			}

			check_ajax_referer( 'ajax-load-kc-fields', 'token' );

			$shortcode = $_REQUEST['shortcode'];

			if ( ! $shortcode_instance = BF_Shortcodes_Manager::factory( $shortcode, array(), true ) ) {

				wp_send_json_error( new WP_Error( 'invalid_shortcode' ) );
			}

			$deferred_fields = $this->filter_deferred_fields( $shortcode_instance->page_builder_fields( 'KC' ) );
			$shortcode_atts  = isset( $_REQUEST['shortcode_atts'] ) && is_array( $_REQUEST['shortcode_atts'] )
				? $_REQUEST['shortcode_atts'] : array();

			foreach ( $deferred_fields as $field ) {

				if ( 'js' === $field['_render_engine'] ) {

					$global_fields[] = array(
						//				'html' => $this->get_field( $field_type ),
						'html' => $this->get_field( $field, array(
							'input_name' => '{{data.name}}',
							'value'      => '{{data.value}}',
						) ),
						'id'   => $field['name']
					);

				} elseif ( 'php' === $field['_render_engine'] ) {

					$name = $field['name'];

					//
					$dedicated_fields[] = array(
						'html' => $this->get_field( $field, array(
							'input_name' => $name,
							'value'      => isset( $shortcode_atts[ $name ] ) ? $shortcode_atts[ $name ] : '',
						) ),
						'id'   => $field['type'],
						'name' => $name,
					);
				}
			}

			wp_send_json_success( compact( 'dedicated_fields', 'global_fields' ) );
		}


		/**
		 * @hooked edit_form_after_editor
		 */
		public function append_security_token() {

			wp_nonce_field( 'ajax-load-kc-fields', 'bf_kc_ajax_field', false );
		}


		/**
		 * Mark map as deferred to load field HTML markup via ajax.
		 *
		 * @param string $map_id
		 * @param array  $fields_type
		 */
		public static function mark_fields_as_deferred( $map_id, $fields_type ) {

			self::$deferred_fields_maps[ $map_id ][] = array_unique( $fields_type );
		}


		/**
		 * @param string $map_id
		 */
		public static function always_fetch_map_fields( $map_id ) {

			if ( ! in_array( $map_id, self::$dynamic_fields_maps ) ) {
				self::$dynamic_fields_maps[] = $map_id;
			}
		}


		/**
		 * @param array $kc_maps
		 *
		 * @hooked kc_maps
		 *
		 * @return array
		 */
		public function filter_kc_maps_var( $kc_maps ) {

			foreach ( self::$dynamic_fields_maps as $map_id ) {

				$kc_maps[ $map_id ]['always_fetch_fields'] = true;
			}

			foreach ( self::$deferred_fields_maps as $map_id => $fields_type ) {

				if ( isset( $kc_maps[ $map_id ] ) && empty( $kc_maps[ $map_id ]['always_fetch_fields'] ) ) {
					$kc_maps[ $map_id ]['deferred_fields'] = $fields_type;
				}
			}

			return $kc_maps;
		}


		/**
		 * List deferred fields type.
		 *
		 * @param array $fields
		 *
		 * @return array
		 */
		public function filter_deferred_fields( $fields ) {

			/**
			 * @var BF_KC_Wrapper $kc_wrapper
			 */
			$kc_wrapper = Better_Framework::factory( 'page-builder' )->wrapper_class( 'KC' );
			$kc_wrapper = new $kc_wrapper();

			$deferred_fields         = array();
			$dynamic_deferred_fields = $kc_wrapper->dynamic_deferred_fields();
			$static_deferred_fields  = $kc_wrapper->static_deferred_fields();

			foreach ( $fields as $tab_fields ) {

				foreach ( $tab_fields as $field ) {

					if ( in_array( $field['type'], $dynamic_deferred_fields ) ) {

						$deferred_fields[ $field['name'] ]                   = $field;
						$deferred_fields[ $field['name'] ]['_render_engine'] = 'php';

					} elseif ( in_array( $field['type'], $static_deferred_fields ) ) {

						$deferred_fields[ $field['name'] ]                   = $field;
						$deferred_fields[ $field['name'] ]['_render_engine'] = 'js';
					}
				}
			}

			return $deferred_fields;
		}


		/**
		 * @param string $field
		 * @param array  $options
		 *
		 * @return string
		 */
		public function get_field( $field, $options = array() ) {

			$field = array_merge( $field, $options );

			if ( ! class_exists( 'BF_KC_Fields_Generator' ) ) {

				require BF_PATH . 'page-builder/generators/kc/class-bf-kc-fields-generator.php';
			}

			if ( isset( $field['name'] ) && ! isset( $field['id'] ) ) {
				$field['id'] = $field['name'];
			}

			$generator = new BF_KC_Fields_Generator( $field, $field['input_name'] );

			return $generator->get_field();
		}


		/**
		 * @param array $field
		 *
		 * @return string
		 */
		public function get_field_placeholder( $field ) {

			return sprintf( '<div class="bf-deferred-kc-field" data-field-name="%s"></div>', esc_attr( $field['name'] ) );
		}
	}


	BF_KC_Compatibility::instance();
}
libs/better-framework/page-builder/compatibility/kc/index.php000064400000000050151214002350020367 0ustar00<?php

// let's show them we are better
libs/better-framework/page-builder/compatibility/index.php000064400000000050151214002350017772 0ustar00<?php

// let's show them we are better
libs/better-framework/page-builder/compatibility/vc/index.php000064400000000050151214002350020402 0ustar00<?php

// let's show them we are better
libs/better-framework/page-builder/compatibility/vc/vc_column_inner.php000064400000001653151214002350022465 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

global $_vc_column_inner_template_file, $_bf_vc_column_inner_atts;


$_bf_vc_column_inner_atts = $atts;
if ( $_vc_column_inner_template_file ) {
	include $_vc_column_inner_template_file;
}

libs/better-framework/page-builder/compatibility/vc/vc_column.php000064400000002224151214002350021265 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

global $_vc_column_template_file, $_bf_vc_column_inner_atts, $_bf_vc_column_atts;


//todo: include $variable can cause security concerns
$_bf_vc_column_atts       = $atts;
$_bf_vc_column_inner_atts = array();
if ( $_vc_column_template_file ) {
	include $_vc_column_template_file;
}

// Clear atts again to make sure it works in pages with 2 different vc contents
$_bf_vc_column_atts = $_bf_vc_column_inner_atts = array();
libs/better-framework/page-builder/generators/kc/kc-field-generator-functions.php000064400000001650151214002350024237 0ustar00<?php

if ( ! function_exists( 'bf_kc_field_generator' ) ) {

	function bf_kc_field_generator( $type, $settings = array() ) {

		if ( ! class_exists( 'BF_KC_Fields_Generator' ) ) {
			require BF_PATH . 'page-builder/generators/kc/class-bf-kc-fields-generator.php';
		}

		$options = wp_parse_args( array(
			'input_name'     => '{{data.name}}',
			'value'          => '{{data.value}}',
			'type'           => $type,
			'bypass_wrapper' => true,
		), $settings );


		$generator = new BF_KC_Fields_Generator( $options, $options['input_name'] );
		$input     = $generator->get_field();

		include BF_PATH . 'page-builder/generators/kc/templates/default-js.php';
	}
}

if ( ! function_exists( 'bf_kc_field_switch' ) ) {

	function bf_kc_field_switch() {

		bf_kc_field_generator( 'switch' );
	}
}
//
//if ( ! function_exists( 'bf_kc_field_color' ) ) {
//
//	function bf_kc_field_color() {
//
//		bf_kc_field_generator( 'color' );
//	}
//}
libs/better-framework/page-builder/generators/kc/fields/heading.php000064400000001745151214002350021441 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div class="bf-section-container bf-clearfix">
	<div class="bf-section-heading bf-clearfix" data-id="{{data.name}}"
	     id="{{data.name}}">
		<div class="bf-section-heading-title bf-clearfix">
			<h3>{{data.label}}</h3>
		</div>
	</div>
</div>libs/better-framework/page-builder/generators/kc/fields/ajax_select.php000064400000001500151214002350022311 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

include BF_PATH . 'core/field-generator/fields/ajax_select.php';libs/better-framework/page-builder/generators/kc/fields/switch.php000064400000002676151214002350021347 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */
?>
<div class="bf-switch bf-clearfix">

	<#
			var onLabel = data.options['on-label'] || '<?php _e( 'On', 'better-studio' ) ?>',
			offLabel = data.options['off-label'] || '<?php _e( 'Off', 'better-studio' ) ?>',
			inputClasses = data.options['input-class'];
			#>

		<label class="cb-enable <# if(data.value && data.value !== '0') { #> selected<# } #>"><span>{{{onLabel}}}</span></label>
		<label class="cb-disable <# if(!data.value || data.value === '0') { #> selected<# } #>"><span>{{{offLabel}}}</span></label>

		<input type="hidden" name="{{data.name}}" value="<# if(data.value && data.value !== '0') {#>1<#}else {#>0<#}#>"
		       class="kc-param checkbox {{inputClasses}}">
</div>libs/better-framework/page-builder/generators/kc/fields/select.php000064400000001624151214002350021315 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

if ( isset( $options['_options'] ) ) {
	$options['options'] = $options['_options'];
}
include BF_PATH . 'core/field-generator/fields/select.php';libs/better-framework/page-builder/generators/kc/fields/editor.php000064400000000101151214002350021311 0ustar00<?php
include BF_PATH . 'core/field-generator/fields/editor.php';libs/better-framework/page-builder/generators/kc/fields/term_select.php000064400000001456151214002350022347 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

include BF_PATH . 'core/field-generator/fields/term_select.php';
libs/better-framework/page-builder/generators/kc/fields/icon_select.php000064400000006362151214002350022331 0ustar00<?php


/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// Default selected
$current = array(
	'key'    => '',
	'title'  => __( 'Chose an Icon', 'better-studio' ),
	'width'  => '',
	'height' => '',
	'type'   => '',
);


if ( isset( $options['value'] ) ) {

	if ( is_array( $options['value'] ) ) {

		if ( in_array( $options['value']['type'], array( 'custom-icon', 'custom' ) ) ) {
			$current['key']    = isset( $options['value']['icon'] ) ? $options['value']['icon'] : '';
			$current['title']  = bf_get_icon_tag( isset( $options['value'] ) ? $options['value'] : '' ) . ' ' . __( 'Custom icon', 'better-studio' );
			$current['width']  = isset( $options['value']['width'] ) ? $options['value']['width'] : '';
			$current['height'] = isset( $options['value']['height'] ) ? $options['value']['height'] : '';
			$current['type']   = 'custom-icon';
		} else {
			Better_Framework::factory( 'icon-factory' );

			$fontawesome = BF_Icons_Factory::getInstance( 'fontawesome' );

			if ( isset( $fontawesome->icons[ $options['value']['icon'] ] ) ) {
				$current['key']    = $options['value']['icon'];
				$current['title']  = bf_get_icon_tag( $options['value'] ) . $fontawesome->icons[ $options['value']['icon'] ]['label'];
				$current['width']  = $options['value']['width'];
				$current['height'] = $options['value']['height'];
				$current['type']   = 'fontawesome';
			}
		}

	} elseif ( ! empty( $options['value'] ) ) {

		Better_Framework::factory( 'icon-factory' );

		$fontawesome = BF_Icons_Factory::getInstance( 'fontawesome' );

		$icon_label = '';
		if ( substr( $options['value'], 0, 3 ) == 'fa-' ) {
			$icon_label      = bf_get_icon_tag( $options['value'] ) . ' ' . $fontawesome->icons[ $options['value'] ]['label'];
			$current['type'] = 'fontawesome';
		} else {
			$icon_label      = bf_get_icon_tag( $options['value'] );
			$current['type'] = 'custom-icon';
		}

		$current['key']    = $options['value'];
		$current['title']  = $icon_label;
		$current['width']  = '';
		$current['height'] = '';

	}

}

$icon_handler = 'bf-icon-modal-handler-' . mt_rand();


?>
	<div class="bf-icon-modal-handler" id="<?php echo esc_attr( $icon_handler ); ?>">

		<div class="select-options">
			<span class="selected-option"><?php echo wp_kses( $current['title'], bf_trans_allowed_html() ); ?></span>
		</div>

		<input type="hidden" class="kc-param wpb-textinput title textfield icon-input"
		       data-label=""
		       name="<?php echo esc_attr( $options['input_name'] ); ?>"
		       value="<?php echo esc_attr( $current['key'] ); ?>"/>

	</div><!-- modal handler container -->
<?php

bf_enqueue_modal( 'icon' );
libs/better-framework/page-builder/generators/kc/fields/slider.php000064400000001475151214002350021324 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


include BF_PATH . 'core/field-generator/fields/slider.php';libs/better-framework/page-builder/generators/kc/fields/info.php000064400000000123151214002350020762 0ustar00<div class="info-value">
	<?php echo $options['std']; // escaped before ?>
</div>libs/better-framework/page-builder/generators/kc/fields/custom.php000064400000002014151214002350021342 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

$classes   = array();
$classes[] = 'bf-section-container';

if ( ! empty( $options['container_class'] ) ) {
	$classes[] = $options['container_class'];
}

printf( '<div class="%s">', implode( ' ', $classes ) );

include BF_PATH . 'core/field-generator/fields/custom.php';

echo '</div>';
libs/better-framework/page-builder/generators/kc/fields/select_popup.php000064400000001457151214002350022544 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


include BF_PATH . 'core/field-generator/fields/select_popup.php';libs/better-framework/page-builder/generators/kc/fields/background_image.php000064400000010323151214002350023313 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// stripcslashes for when json is splashed!
if ( ! empty( $options['value'] ) ) {
	$value = $options['value'];
} else {
	$value = array(
		'img'  => '',
		'type' => 'cover'
	);
}

$media_title = empty( $options['media_title'] ) ? __( 'Upload', 'better-studio' ) : $options['media_title'];
$button_text = empty( $options['button_text'] ) ? __( 'Upload', 'better-studio' ) : $options['button_text'];

// Upload Button
$upload_button = Better_Framework::html()
                                 ->add( 'a' )
                                 ->class( 'bf-button bf-background-image-upload-btn button' )
                                 ->data( 'mediatitle', $media_title )
                                 ->data( 'buttontext', $button_text );

if ( isset( $options['upload_label'] ) ) {
	$upload_button->text( $options['upload_label'] );
} else {
	$upload_button->text( __( 'Upload', 'better-studio' ) );
}

// Remove Button
$remove_button = Better_Framework::html()
                                 ->add( 'a' )
                                 ->class( 'bf-button bf-background-image-remove-btn button' );

if ( isset( $options['remove_label'] ) ) {
	$remove_button->text( $options['remove_label'] );
} else {
	$remove_button->text( __( 'Remove', 'better-studio' ) );
}

if ( $value['img'] == "" ) {
	$remove_button->css( 'display', 'none' );
}

// Select
$select = Better_Framework::html()
                          ->add( 'select' )
                          ->attr( 'id', $options['id'] . '-select' )
                          ->class( 'bf-background-image-uploader-select' )
                          ->name( $options['input_name'] . '[type]' );


$select->text( '<option value="repeat" ' . ( $value['type'] == 'repeat' ? 'selected="selected"' : '' ) . '>' . __( 'Repeat Horizontal and Vertical - Pattern', 'better-studio' ) . '</option>' );
$select->text( '<option value="cover" ' . ( $value['type'] == 'cover' ? 'selected="selected"' : '' ) . '>' . __( 'Fully Cover Background - Photo', 'better-studio' ) . '</option>' );
$select->text( '<option value="repeat-y" ' . ( $value['type'] == 'repeat-y' ? 'selected="selected"' : '' ) . '>' . __( 'Repeat Horizontal', 'better-studio' ) . '</option>' );
$select->text( '<option value="repeat-x" ' . ( $value['type'] == 'repeat-x' ? 'selected="selected"' : '' ) . '>' . __( 'Repeat Vertical', 'better-studio' ) . '</option>' );
$select->text( '<option value="no-repeat" ' . ( $value['type'] == 'no-repeat' ? 'selected="selected"' : '' ) . '>' . __( 'No Repeat', 'better-studio' ) . '</option>' );

if ( $value['img'] == "" ) {
	$select->css( 'display', 'none' );
}

// Main Input
$input = Better_Framework::html()
                         ->add( 'input' )
                         ->type( 'hidden' )
                         ->class( 'bf-background-image-input' )
                         ->name( $options['input_name'] . '[img]' )
                         ->val( $value['img'] );

if ( isset( $options['input_class'] ) ) {
	$input->class( $options['input_class'] );
}

echo $upload_button->display(); // escaped before
echo $remove_button->display(); // escaped before
echo '<br>';

echo $select->display(); // escaped before
echo $input->display(); // escaped before

if ( $value['img'] != "" ) {
	echo '<div class="bf-background-image-preview">';
} else {
	echo '<div class="bf-background-image-preview" style="display: none">';
}

echo '<img src="' . esc_url( $value['img'] ) . '" />';
echo '</div>';
libs/better-framework/page-builder/generators/kc/fields/index.php000064400000000050151214002350021135 0ustar00<?php

// let's show them we are better
libs/better-framework/page-builder/generators/kc/fields/color.php000064400000001712151214002350021152 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */
?>


<div class="bs-color-picker-wrapper">

	<input type="text" name="{{data.name}}" value="{{data.value}}" class="bs-color-picker-value color-picker kc-param"
	       data-alpha="true">
</div>

libs/better-framework/page-builder/generators/kc/fields/text.php000064400000002265151214002350021024 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$wrapper = Better_Framework::html()->add( 'div' )->class( 'bf-clearfix' );
$input   = Better_Framework::html()->add( 'input' )->type( 'text' )->name( $options['input_name'] );

if ( isset( $options['input_class'] ) ) {
	$input->class( $options['input_class'] );
}

if ( ! empty( $options['value'] ) ) {
	$input->value( $options['value'] )->css( 'border-color', $options['value'] );
}

$wrapper->add( $input );

echo $wrapper->display(); // escaped before
libs/better-framework/page-builder/generators/kc/fields/media_image.php000064400000001502151214002350022252 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


include BF_PATH . 'core/field-generator/fields/media_image.php';libs/better-framework/page-builder/generators/kc/fields/image_radio.php000064400000001502151214002350022271 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


include BF_PATH . 'core/field-generator/fields/image_radio.php';libs/better-framework/page-builder/generators/kc/fields/sorter_checkbox.php000064400000012367151214002360023231 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

// set options from deferred callback
if ( isset( $options['deferred-options'] ) ) {
	if ( is_string( $options['deferred-options'] ) && is_callable( $options['deferred-options'] ) ) {
		$options['options'] = call_user_func( $options['deferred-options'] );
	} elseif ( is_array( $options['deferred-options'] ) && ! empty( $options['deferred-options']['callback'] ) && is_callable( $options['deferred-options']['callback'] ) ) {
		if ( isset( $options['deferred-options']['args'] ) ) {
			$options['options'] = call_user_func_array( $options['deferred-options']['callback'], $options['deferred-options']['args'] );
		} else {
			$options['options'] = call_user_func( $options['deferred-options']['callback'] );
		}
	}
}

if ( empty( $options['options'] ) ) {
	return;
}

if ( isset( $options['value'] ) && ! empty( $options['value'] ) ) {
	if ( is_string( $options['value'] ) ) {
		$value            = array_flip( explode( ',', $options['value'] ) );
		$options['value'] = array_fill_keys( array_keys( $value ), true );
	}
} else {
	$options['value'] = array();
}


$value     = $options['value'];
$check_all = ( ! isset( $options['check_all'] ) || $options['check_all'] ) && ! bf_count( $value ) ? true : false;

$groups_ids = array();

$selected_items = array();

// Options That Saved Before
foreach ( $value as $item_id => $item ) {

	if ( ! $item ) {
		continue;
	}

	$selected_items[ $item_id ] = $item;
}

$input = Better_Framework::html()->add( 'input' )->type( 'hidden' )->name( $options['input_name'] )->attr( 'value', implode( ',', array_keys( $selected_items ) ) );

if ( isset( $options['input_class'] ) ) {
	$input->class( $options['input_class'] );
}

echo $input->display(); // escaped before

?>
<div class="bf-sorter-groups-container">
	<ul id="bf-sorter-group-<?php echo esc_attr( $options['id'] ); ?>"
	    class="bf-sorter-list bf-vc-sorter-list bf-vc-sorter-checkbox-list bf-sorter-<?php echo esc_attr( $options['id'] ); ?>">
		<?php
		// Options That Saved Before
		foreach ( $selected_items as $item_id => $item ) {
			?>
			<li id="bf-sorter-group-item-<?php echo esc_attr( $options['id'] ); ?>-<?php echo esc_attr( $item_id ); ?>"
			    class="<?php echo isset( $options['options'][ $item_id ]['css-class'] ) ? esc_attr( $options['options'][ $item_id ]['css-class'] ) : ''; ?> item-<?php echo esc_attr( $item_id ); ?> checked-item"
			    style="<?php echo isset( $options['options'][ $item_id ]['css'] ) ? esc_attr( $options['options'][ $item_id ]['css'] ) : ''; ?>">
				<label>
					<input name="<?php echo esc_attr( $item_id ); ?>" value="<?php echo esc_attr( $item_id ); ?>"
					       type="checkbox" checked="checked"/>
					<?php echo $options['options'][ $item_id ]['label']; ?>
				</label>
			</li>
			<?php

			unset( $options['options'][ $item_id ] );

		}

		// Options That Not Saved but are Active
		foreach ( $options['options'] as $item_id => $item ) {

			// Skip Disabled Items
			if ( isset( $item['css-class'] ) && strpos( $item['css-class'], 'active-item' ) === false ) {
				continue;
			}
			?>
			<li id="bf-sorter-group-item-<?php echo esc_attr( $options['id'] ); ?>-<?php echo esc_attr( $item_id ); ?>"
			    class="<?php echo isset( $item['css-class'] ) ? esc_attr( $item['css-class'] ) : ''; ?> item-<?php echo esc_attr( $item_id ); ?> <?php echo $check_all ? ' checked-item' : ''; ?>" <?php echo $check_all ? ' checked="checked" ' : ''; ?>
			    style="<?php echo isset( $item['css'] ) ? esc_attr( $item['css'] ) : ''; ?>">
				<label>
					<input name="<?php echo esc_attr( $item_id ); ?>" value="<?php echo esc_attr( $item_id ); ?>"
					       type="checkbox" <?php echo $check_all ? ' checked="checked" ' : ''; ?>/>
					<?php echo is_array( $item ) ? $item['label'] : $item; // escaped before ?>
				</label>
			</li>
			<?php

			unset( $options['options'][ $item_id ] );
		}

		// Disable Items
		foreach ( $options['options'] as $item_id => $item ) { ?>
			<li id="bf-sorter-group-item-<?php echo esc_attr( $options['id'] ); ?>-<?php echo esc_attr( $item_id ); ?>"
			    class="<?php echo isset( $item['css-class'] ) ? esc_attr( $item['css-class'] ) : ''; ?> item-<?php echo esc_attr( $item_id ); ?>"
			    style="<?php echo isset( $item['css'] ) ? esc_attr( $item['css'] ) : ''; ?>">
				<label>
					<input name="<?php echo esc_attr( $item_id ); ?>" value="<?php echo esc_attr( $item_id ); ?>"
					       type="checkbox" disabled/>
					<?php echo is_array( $item ) ? $item['label'] : $item; // escaped before ?>
				</label>
			</li>
			<?php
		}

		?>
	</ul>
	<?php

	echo $this->get_filed_input_desc( $options ); // escaped before

	?>
</div>
libs/better-framework/page-builder/generators/kc/class-bf-kc-fields-generator.php000064400000002436151214002360024110 0ustar00<?php


/**
 * Class BF_KC_Front_End_Generator
 *
 * @since 4.0.0
 */
class BF_KC_Fields_Generator extends BF_Admin_Fields {

	/**
	 * Holds Items Array
	 *
	 * @since  1.0
	 * @access public
	 * @var array|null
	 */
	public $item;

	/**
	 * Panel ID
	 *
	 * @since  1.0
	 * @access public
	 * @var string
	 */
	public $id;


	/**
	 * Constructor
	 *
	 * @param array $item Contain details of one field
	 * @param       $id
	 */
	public function __construct( $item = array(), $id = array() ) {

		$generator_options = array(
			'fields_dir'    => BF_PATH . 'page-builder/generators/kc/fields/',
			'templates_dir' => BF_PATH . 'page-builder/generators/kc/templates/'
		);

		parent::__construct( $generator_options );

		$item['input_class'] = 'kc-param';

		$this->item = $item;
		$this->id   = $id;
	}


	/**
	 * Display HTML output of panel array
	 *
	 * Display full html of panel array which is defined in object parameter
	 *
	 * @since  1.0
	 * @access public
	 * @return string
	 */
	public function get_field() {

		$output = '';
		$field  = $this->item;

		if ( ! isset( $field['value'] ) && isset( $field['std'] ) ) {
			$field['value'] = $field['std'];
		}

		$output .= $this->section(
			call_user_func(
				array( $this, $field['type'] ),
				$field
			),
			$field
		);

		return $output;
	}
}
libs/better-framework/page-builder/generators/kc/index.php000064400000000050151214002360017670 0ustar00<?php

// let's show them we are better
libs/better-framework/page-builder/generators/kc/templates/default.php000064400000002242151214002360022210 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

if ( ! isset( $options['id'] ) && isset( $options['name'] ) ) {
	$options['id'] = $options['name'];
}

if ( ! empty( $options['bypass_wrapper'] ) ) {

	echo $input;

	return;
}
?>
<div class="bf-section-container <?php echo isset( $options['section_class'] ) ? esc_attr( $options['section_class'] ) : ''; ?>" <?php echo bf_show_on_attributes( $options ) ?>>
	<?php echo $input; // escaped before ?>
</div>libs/better-framework/page-builder/generators/kc/templates/heading.php000064400000002751151214002360022170 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

$style = ! empty( $options['layout'] ) ? $options['layout'] : 'style-1';

if ( ! isset( $options['id'] ) ) {
	$options['id'] = '';
}

if ( ! isset( $options['title'] ) ) {
	$options['title'] = $options['label'];
}

?>
<div class="bf-section-container bf-clearfix">
	<div class="bf-section-heading bf-clearfix <?php echo $style; ?>"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>"
	     id="<?php echo esc_attr( $options['id'] ); ?>">
		<div class="bf-section-heading-title bf-clearfix">
			<h4><?php echo esc_html( $options['title'] ); ?></h4>
		</div>
		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div class="bf-section-heading-desc bf-clearfix"><?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?></div>
		<?php } ?>
	</div>
</div>libs/better-framework/page-builder/generators/kc/templates/default-js.php000064400000000506151214002360022623 0ustar00<#
		var sectionClass = data.options['section_class'] || '',
		settings = data.options['show_on'] ? JSON.stringify(data.options['show_on']) : '';
		#>
	<div
			class="bf-section-container {{sectionClass}}" data-param-name="{{data.name}}"
			data-param-settings="{{settings}}">
		<?php echo $input; // escaped before ?>
	</div>libs/better-framework/page-builder/generators/kc/templates/index.php000064400000000050151214002360021666 0ustar00<?php

// let's show them we are better
libs/better-framework/page-builder/generators/index.php000064400000000050151214002360017273 0ustar00<?php

// let's show them we are better
libs/better-framework/page-builder/generators/vc/fields/heading.php000064400000002072151214002360021447 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div class="bf-section-container bf-clearfix">
	<div class="bf-section-heading bf-clearfix" data-id="<?php echo esc_attr( $options['id'] ); ?>"
	     id="<?php echo esc_attr( $options['id'] ); ?>">
		<div class="bf-section-heading-title bf-clearfix">
			<h3><?php echo esc_html( $options['name'] ); ?></h3>
		</div>
	</div>
</div>libs/better-framework/page-builder/generators/vc/fields/ajax_select.php000064400000001500151214002360022325 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

include BF_PATH . 'core/field-generator/fields/ajax_select.php';libs/better-framework/page-builder/generators/vc/fields/vc-switchery.php000064400000003461151214002360022502 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

$checkbox = Better_Framework()->html()->add( 'input' )->type( 'input' )->name( $options['input_name'] )->val( '' )->class( 'checkbox' );


// On Label
$on_label = __( 'On', 'better-studio' );
if ( isset( $options['on-label'] ) ) {
	$on_label = $options['on-label'];
}

// On Label
$off_label = __( 'Off', 'better-studio' );
if ( isset( $options['off-label'] ) ) {
	$off_label = $options['off-label'];
}

if ( $options['value'] ) {
	$on_checked  = 'selected';
	$off_checked = '';
	$checkbox->val( 1 );

} else {
	$on_checked  = '';
	$off_checked = 'selected';
	$checkbox->val( 0 );
}

if ( isset( $options['input_class'] ) ) {
	$checkbox->class( $options['input_class'] );
}

?>
<div class="bf-switch bf-clearfix">

	<label
			class="cb-enable <?php echo esc_attr( $on_checked ); ?>"><span><?php echo esc_html( $on_label ); ?></span></label>
	<label class="cb-disable <?php echo esc_attr( $off_checked ); ?>"><span><?php echo esc_html( $off_label ); ?></span></label>
	<?php

	echo $checkbox->display(); // escaped before

	?>
</div>libs/better-framework/page-builder/generators/vc/fields/select.php000064400000001475151214002360021335 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


include BF_PATH . 'core/field-generator/fields/select.php';libs/better-framework/page-builder/generators/vc/fields/term_select.php000064400000001456151214002360022363 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

include BF_PATH . 'core/field-generator/fields/term_select.php';
libs/better-framework/page-builder/generators/vc/fields/vc-image_radio.php000064400000003773151214002360022727 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$value = ! empty( $options['value'] ) ? $options['value'] : '';


$wrapper = Better_Framework::html()->add( 'div' )->class( 'bf-clearfix' );
$input   = Better_Framework::html()->add( 'input' )->type( 'hidden' )->name( $options['input_name'] );

if ( isset( $options['input_class'] ) ) {
	$input->class( $options['input_class'] );
}

if ( ! empty( $options['value'] ) ) {
	$input->value( $options['value'] )->css( 'border-color', $options['value'] );
}

$wrapper->add( $input );

echo $wrapper->display(); // escaped before

foreach ( $options['options'] as $key => $item ) {

	$is_checked = ! empty( $value ) && ( $key == $value );

	$image = Better_Framework::html()->add( 'img' )->src( $item['img'] )->alt( $item['label'] )->title( $item['label'] );
	$label = Better_Framework::html()->add( 'label' );


	$label->text( $image );
	if ( isset( $item['label'] ) ) {
		$p = Better_Framework::html()->add( 'p' )->text( $item['label'] )->class( 'item-label' );
		$label->text( $p );
	}

	$object = Better_Framework::html()->add( 'div' )->class( 'vc-bf-image-radio-option' )->data( 'id', $key );

	if ( $is_checked ) {
		$object->class( 'checked' );
	}

	$object->text( $label->display() );

	echo $object->display(); // escaped before
}libs/better-framework/page-builder/generators/vc/fields/icon_select.php000064400000006372151214002360022346 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// Default selected
$current = array(
	'key'    => '',
	'title'  => __( 'Chose an Icon', 'better-studio' ),
	'width'  => '',
	'height' => '',
	'type'   => '',
);


if ( isset( $options['value'] ) ) {

	if ( is_array( $options['value'] ) ) {

		if ( in_array( $options['value']['type'], array( 'custom-icon', 'custom' ) ) ) {
			$current['key']    = isset( $options['value']['icon'] ) ? $options['value']['icon'] : '';
			$current['title']  = bf_get_icon_tag( isset( $options['value'] ) ? $options['value'] : '' ) . ' ' . __( 'Custom icon', 'better-studio' );
			$current['width']  = isset( $options['value']['width'] ) ? $options['value']['width'] : '';
			$current['height'] = isset( $options['value']['height'] ) ? $options['value']['height'] : '';
			$current['type']   = 'custom-icon';
		} else {
			Better_Framework::factory( 'icon-factory' );

			$fontawesome = BF_Icons_Factory::getInstance( 'fontawesome' );

			if ( isset( $fontawesome->icons[ $options['value']['icon'] ] ) ) {
				$current['key']    = $options['value']['icon'];
				$current['title']  = bf_get_icon_tag( $options['value'] ) . $fontawesome->icons[ $options['value']['icon'] ]['label'];
				$current['width']  = $options['value']['width'];
				$current['height'] = $options['value']['height'];
				$current['type']   = 'fontawesome';
			}
		}

	} elseif ( ! empty( $options['value'] ) ) {

		Better_Framework::factory( 'icon-factory' );

		$fontawesome = BF_Icons_Factory::getInstance( 'fontawesome' );

		$icon_label = '';
		if ( substr( $options['value'], 0, 3 ) == 'fa-' ) {
			$icon_label      = bf_get_icon_tag( $options['value'] ) . ' ' . $fontawesome->icons[ $options['value'] ]['label'];
			$current['type'] = 'fontawesome';
		} else {
			$icon_label      = bf_get_icon_tag( $options['value'] );
			$current['type'] = 'custom-icon';
		}

		$current['key']    = $options['value'];
		$current['title']  = $icon_label;
		$current['width']  = '';
		$current['height'] = '';

	}

}

$icon_handler = 'bf-icon-modal-handler-' . mt_rand();


?>
	<div class="bf-icon-modal-handler" id="<?php echo esc_attr( $icon_handler ); ?>">

		<div class="select-options">
			<span class="selected-option"><?php echo wp_kses( $current['title'], bf_trans_allowed_html() ); ?></span>
		</div>

		<input type="hidden" class="wpb_vc_param_value wpb-textinput title textfield icon-input"
		       data-label=""
		       name="<?php echo esc_attr( $options['input_name'] ); ?>"
		       value="<?php echo esc_attr( $current['key'] ); ?>"/>

	</div><!-- modal handler container -->
<?php

bf_enqueue_modal( 'icon' );
libs/better-framework/page-builder/generators/vc/fields/slider.php000064400000001475151214002360021340 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


include BF_PATH . 'core/field-generator/fields/slider.php';libs/better-framework/page-builder/generators/vc/fields/custom.php000064400000002014151214002360021356 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

$classes   = array();
$classes[] = 'bf-section-container';

if ( ! empty( $options['container_class'] ) ) {
	$classes[] = $options['container_class'];
}

printf( '<div class="%s">', implode( ' ', $classes ) );

include BF_PATH . 'core/field-generator/fields/custom.php';

echo '</div>';
libs/better-framework/page-builder/generators/vc/fields/select_popup.php000064400000001457151214002360022560 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


include BF_PATH . 'core/field-generator/fields/select_popup.php';libs/better-framework/page-builder/generators/vc/fields/background_image.php000064400000010323151214002360023327 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// stripcslashes for when json is splashed!
if ( ! empty( $options['value'] ) ) {
	$value = $options['value'];
} else {
	$value = array(
		'img'  => '',
		'type' => 'cover'
	);
}

$media_title = empty( $options['media_title'] ) ? __( 'Upload', 'better-studio' ) : $options['media_title'];
$button_text = empty( $options['button_text'] ) ? __( 'Upload', 'better-studio' ) : $options['button_text'];

// Upload Button
$upload_button = Better_Framework::html()
                                 ->add( 'a' )
                                 ->class( 'bf-button bf-background-image-upload-btn button' )
                                 ->data( 'mediatitle', $media_title )
                                 ->data( 'buttontext', $button_text );

if ( isset( $options['upload_label'] ) ) {
	$upload_button->text( $options['upload_label'] );
} else {
	$upload_button->text( __( 'Upload', 'better-studio' ) );
}

// Remove Button
$remove_button = Better_Framework::html()
                                 ->add( 'a' )
                                 ->class( 'bf-button bf-background-image-remove-btn button' );

if ( isset( $options['remove_label'] ) ) {
	$remove_button->text( $options['remove_label'] );
} else {
	$remove_button->text( __( 'Remove', 'better-studio' ) );
}

if ( $value['img'] == "" ) {
	$remove_button->css( 'display', 'none' );
}

// Select
$select = Better_Framework::html()
                          ->add( 'select' )
                          ->attr( 'id', $options['id'] . '-select' )
                          ->class( 'bf-background-image-uploader-select' )
                          ->name( $options['input_name'] . '[type]' );


$select->text( '<option value="repeat" ' . ( $value['type'] == 'repeat' ? 'selected="selected"' : '' ) . '>' . __( 'Repeat Horizontal and Vertical - Pattern', 'better-studio' ) . '</option>' );
$select->text( '<option value="cover" ' . ( $value['type'] == 'cover' ? 'selected="selected"' : '' ) . '>' . __( 'Fully Cover Background - Photo', 'better-studio' ) . '</option>' );
$select->text( '<option value="repeat-y" ' . ( $value['type'] == 'repeat-y' ? 'selected="selected"' : '' ) . '>' . __( 'Repeat Horizontal', 'better-studio' ) . '</option>' );
$select->text( '<option value="repeat-x" ' . ( $value['type'] == 'repeat-x' ? 'selected="selected"' : '' ) . '>' . __( 'Repeat Vertical', 'better-studio' ) . '</option>' );
$select->text( '<option value="no-repeat" ' . ( $value['type'] == 'no-repeat' ? 'selected="selected"' : '' ) . '>' . __( 'No Repeat', 'better-studio' ) . '</option>' );

if ( $value['img'] == "" ) {
	$select->css( 'display', 'none' );
}

// Main Input
$input = Better_Framework::html()
                         ->add( 'input' )
                         ->type( 'hidden' )
                         ->class( 'bf-background-image-input' )
                         ->name( $options['input_name'] . '[img]' )
                         ->val( $value['img'] );

if ( isset( $options['input_class'] ) ) {
	$input->class( $options['input_class'] );
}

echo $upload_button->display(); // escaped before
echo $remove_button->display(); // escaped before
echo '<br>';

echo $select->display(); // escaped before
echo $input->display(); // escaped before

if ( $value['img'] != "" ) {
	echo '<div class="bf-background-image-preview">';
} else {
	echo '<div class="bf-background-image-preview" style="display: none">';
}

echo '<img src="' . esc_url( $value['img'] ) . '" />';
echo '</div>';
libs/better-framework/page-builder/generators/vc/fields/vc-sorter_checkbox.php000064400000012367151214002360023652 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

// set options from deferred callback
if ( isset( $options['deferred-options'] ) ) {
	if ( is_string( $options['deferred-options'] ) && is_callable( $options['deferred-options'] ) ) {
		$options['options'] = call_user_func( $options['deferred-options'] );
	} elseif ( is_array( $options['deferred-options'] ) && ! empty( $options['deferred-options']['callback'] ) && is_callable( $options['deferred-options']['callback'] ) ) {
		if ( isset( $options['deferred-options']['args'] ) ) {
			$options['options'] = call_user_func_array( $options['deferred-options']['callback'], $options['deferred-options']['args'] );
		} else {
			$options['options'] = call_user_func( $options['deferred-options']['callback'] );
		}
	}
}

if ( empty( $options['options'] ) ) {
	return;
}

if ( isset( $options['value'] ) && ! empty( $options['value'] ) ) {
	if ( is_string( $options['value'] ) ) {
		$value            = array_flip( explode( ',', $options['value'] ) );
		$options['value'] = array_fill_keys( array_keys( $value ), true );
	}
} else {
	$options['value'] = array();
}


$value     = $options['value'];
$check_all = ( ! isset( $options['check_all'] ) || $options['check_all'] ) && ! bf_count( $value ) ? true : false;

$groups_ids = array();

$selected_items = array();

// Options That Saved Before
foreach ( $value as $item_id => $item ) {

	if ( ! $item ) {
		continue;
	}

	$selected_items[ $item_id ] = $item;
}

$input = Better_Framework::html()->add( 'input' )->type( 'hidden' )->name( $options['input_name'] )->attr( 'value', implode( ',', array_keys( $selected_items ) ) );

if ( isset( $options['input_class'] ) ) {
	$input->class( $options['input_class'] );
}

echo $input->display(); // escaped before

?>
<div class="bf-sorter-groups-container">
	<ul id="bf-sorter-group-<?php echo esc_attr( $options['id'] ); ?>"
	    class="bf-sorter-list bf-vc-sorter-list bf-vc-sorter-checkbox-list bf-sorter-<?php echo esc_attr( $options['id'] ); ?>">
		<?php
		// Options That Saved Before
		foreach ( $selected_items as $item_id => $item ) {
			?>
			<li id="bf-sorter-group-item-<?php echo esc_attr( $options['id'] ); ?>-<?php echo esc_attr( $item_id ); ?>"
			    class="<?php echo isset( $options['options'][ $item_id ]['css-class'] ) ? esc_attr( $options['options'][ $item_id ]['css-class'] ) : ''; ?> item-<?php echo esc_attr( $item_id ); ?> checked-item"
			    style="<?php echo isset( $options['options'][ $item_id ]['css'] ) ? esc_attr( $options['options'][ $item_id ]['css'] ) : ''; ?>">
				<label>
					<input name="<?php echo esc_attr( $item_id ); ?>" value="<?php echo esc_attr( $item_id ); ?>"
					       type="checkbox" checked="checked"/>
					<?php echo $options['options'][ $item_id ]['label']; ?>
				</label>
			</li>
			<?php

			unset( $options['options'][ $item_id ] );

		}

		// Options That Not Saved but are Active
		foreach ( $options['options'] as $item_id => $item ) {

			// Skip Disabled Items
			if ( isset( $item['css-class'] ) && strpos( $item['css-class'], 'active-item' ) === false ) {
				continue;
			}
			?>
			<li id="bf-sorter-group-item-<?php echo esc_attr( $options['id'] ); ?>-<?php echo esc_attr( $item_id ); ?>"
			    class="<?php echo isset( $item['css-class'] ) ? esc_attr( $item['css-class'] ) : ''; ?> item-<?php echo esc_attr( $item_id ); ?> <?php echo $check_all ? ' checked-item' : ''; ?>" <?php echo $check_all ? ' checked="checked" ' : ''; ?>
			    style="<?php echo isset( $item['css'] ) ? esc_attr( $item['css'] ) : ''; ?>">
				<label>
					<input name="<?php echo esc_attr( $item_id ); ?>" value="<?php echo esc_attr( $item_id ); ?>"
					       type="checkbox" <?php echo $check_all ? ' checked="checked" ' : ''; ?>/>
					<?php echo is_array( $item ) ? $item['label'] : $item; // escaped before ?>
				</label>
			</li>
			<?php

			unset( $options['options'][ $item_id ] );
		}

		// Disable Items
		foreach ( $options['options'] as $item_id => $item ) { ?>
			<li id="bf-sorter-group-item-<?php echo esc_attr( $options['id'] ); ?>-<?php echo esc_attr( $item_id ); ?>"
			    class="<?php echo isset( $item['css-class'] ) ? esc_attr( $item['css-class'] ) : ''; ?> item-<?php echo esc_attr( $item_id ); ?>"
			    style="<?php echo isset( $item['css'] ) ? esc_attr( $item['css'] ) : ''; ?>">
				<label>
					<input name="<?php echo esc_attr( $item_id ); ?>" value="<?php echo esc_attr( $item_id ); ?>"
					       type="checkbox" disabled/>
					<?php echo is_array( $item ) ? $item['label'] : $item; // escaped before ?>
				</label>
			</li>
			<?php
		}

		?>
	</ul>
	<?php

	echo $this->get_filed_input_desc( $options ); // escaped before

	?>
</div>
libs/better-framework/page-builder/generators/vc/fields/color.php000064400000001474151214002360021173 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


include BF_PATH . 'core/field-generator/fields/color.php';libs/better-framework/page-builder/generators/vc/fields/text.php000064400000002265151214002360021040 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$wrapper = Better_Framework::html()->add( 'div' )->class( 'bf-clearfix' );
$input   = Better_Framework::html()->add( 'input' )->type( 'text' )->name( $options['input_name'] );

if ( isset( $options['input_class'] ) ) {
	$input->class( $options['input_class'] );
}

if ( ! empty( $options['value'] ) ) {
	$input->value( $options['value'] )->css( 'border-color', $options['value'] );
}

$wrapper->add( $input );

echo $wrapper->display(); // escaped before
libs/better-framework/page-builder/generators/vc/fields/vc-info.php000064400000001471151214002360021413 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

include BF_PATH . 'core/field-generator/fields/info.php';libs/better-framework/page-builder/generators/vc/fields/vc-media_image.php000064400000001502151214002360022674 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


include BF_PATH . 'core/field-generator/fields/media_image.php';libs/better-framework/page-builder/generators/vc/class-bf-vc-front-end-generator.php000064400000004523151214002360024563 0ustar00<?php


/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */
class BF_VC_Front_End_Generator extends BF_Admin_Fields {

	/**
	 * Holds Items Array
	 *
	 * @since  1.0
	 * @access public
	 * @var array|null
	 */
	public $item;

	/**
	 * Panel ID
	 *
	 * @since  1.0
	 * @access public
	 * @var string
	 */
	public $id;

	/**
	 * Panel Values
	 *
	 * @since  1.0
	 * @access public
	 * @var array
	 */
	public $values;


	/**
	 * Constructor Function
	 *
	 * @param array $item Contain details of one field
	 * @param       $id
	 *
	 * @since  1.0
	 * @access public
	 * @return \BF_VC_Front_End_Generator
	 */
	public function __construct( array &$item, &$id ) {

		// Parent Constructor
		$generator_options = array(
			'fields_dir'    => BF_PATH . 'page-builder/generators/vc/fields/',
			'templates_dir' => BF_PATH . 'page-builder/generators/vc/templates/'
		);

		$this->supported_fields[] = 'vc-image_radio';
		$this->supported_fields[] = 'vc-media_image';
		$this->supported_fields[] = 'vc-switchery';
		$this->supported_fields[] = 'vc-sorter_checkbox';
		$this->supported_fields[] = 'vc-info';

		parent::__construct( $generator_options );

		$this->item = $item;

		$this->id = $id;
	}


	/**
	 * Display HTML output of panel array
	 *
	 * Display full html of panel array which is defined in object parameter
	 *
	 * @since  1.0
	 * @access public
	 * @return string
	 */
	public function get_field() {

		$output = '';
		$field  = $this->item;

		if ( ! isset( $field['value'] ) && isset( $field['std'] ) ) {
			$field['value'] = $field['std'];
		}

		$output .= $this->section(
			call_user_func(
				array( $this, $field['type'] ),
				$field
			),
			$field
		);

		return $output;
	}
}libs/better-framework/page-builder/generators/vc/index.php000064400000000050151214002360017703 0ustar00<?php

// let's show them we are better
libs/better-framework/page-builder/generators/vc/class-bf-vc-shortcode-extender.php000064400000001700151214002360024503 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! class_exists( "WPBakeryShortCode" ) ) {
	class WPBakeryShortCode {

	}
}


/**
 * Wrapper for WPBakeryShortCode Class for handling editor
 */
class BF_VC_Shortcode_Extender extends WPBakeryShortCode {

}libs/better-framework/page-builder/generators/vc/templates/default.php000064400000001717151214002360022231 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div
		class="bf-section-container vc-input bf-clearfix <?php echo isset( $options['section_class'] ) ? esc_attr( $options['section_class'] ) : ''; ?>">
	<?php echo $input; // escaped before ?>
</div>libs/better-framework/page-builder/generators/vc/templates/heading.php000064400000002553151214002360022203 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

$style = ! empty( $options['layout'] ) ? $options['layout'] : 'style-1';

?>
<div class="bf-section-container  vc-input bf-clearfix">
	<div class="bf-section-heading bf-clearfix <?php echo $style; ?>"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>"
	     id="<?php echo esc_attr( $options['id'] ); ?>">
		<div class="bf-section-heading-title bf-clearfix">
			<h4><?php echo esc_html( $options['title'] ); ?></h4>
		</div>
		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div
					class="bf-section-heading-desc bf-clearfix"><?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?></div>
		<?php } ?>
	</div>
</div>libs/better-framework/page-builder/generators/vc/templates/vc-info.php000064400000005646151214002360022153 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes = $classes['section'] . ' bf-widget-field-section';

$heading_classes  = $classes['heading'] . ' bf-heading';
$controls_classes = $classes['controls'] . ' bf-control not-prepared';
$explain_classes  = $classes['explain'] . ' bf-desc';

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];


if ( ! isset( $options['info-type'] ) ) {
	$options['info-type'] = 'info';
}

if ( ! isset( $options['state'] ) ) {
	$options['state'] = 'open';
}

?>
<div class="bf-section-container bf-clearfix">
	<div
			class="bf-section-info <?php echo esc_attr( $options['info-type'] ); ?> <?php echo esc_attr( $options['state'] ); ?> bf-clearfix">
		<div class="bf-section-info-title bf-clearfix">
			<h3><?php

				switch ( $options['info-type'] ) {

					case 'help':
						echo '<i class="fa fa-support"></i> ';
						break;

					case 'info':
						echo '<i class="fa fa-info"></i> ';
						break;

					case 'warning':
						echo '<i class="fa fa-warning"></i> ';
						break;

					case 'danger':
						echo '<i class="fa fa-exclamation"></i> ';
						break;

					default:
						echo '<i class="fa fa-info"></i> ';
						break;

				}

				echo esc_html( $options['name'] ); ?></h3>
		</div>
		<div class="<?php echo esc_attr( $controls_classes ); ?>  bf-clearfix">
			<?php echo $input; // escaped before ?>
		</div>
	</div>
</div>libs/better-framework/page-builder/index.php000064400000000050151214002360015122 0ustar00<?php

// let's show them we are better
libs/better-framework/page-builder/misc/class-bf-widget-artificial.php000064400000002006151214002360022031 0ustar00<?php


class BF_Widget_Artificial extends BF_Widget {


	/**
	 * @var string
	 */
	protected $shortcode_id;


	/**
	 * @var BF_Shortcode
	 */
	protected $shortcode_instance;


	public function __construct( $shortcode_id ) {

		$this->set_shortcode_id( $shortcode_id );

		if ( ! $this->shortcode_instance ) {
			return;
		}

		$settings = $this->shortcode_instance->page_builder_settings();

		parent::__construct(
			$shortcode_id,
			$settings['name'],
			isset( $settings['description'] ) ? $settings['description'] : ''
		);
	}


	/**
	 * Loads fields
	 */
	public function load_fields() {

		$this->fields = array_values( $this->shortcode_instance->get_fields() );
	}


	/**
	 * @param string $shortcode_id
	 */
	public function set_shortcode_id( $shortcode_id ) {

		$this->shortcode_id       = $shortcode_id;
		$this->shortcode_instance = BF_Shortcodes_Manager::factory(
			$this->shortcode_id, array(), true
		);
	}


	/**
	 * @return string
	 */
	public function get_shortcode_id() {

		return $this->shortcode_id;
	}
}
libs/better-framework/page-builder/class-bf-page-builder-wrapper.php000064400000002312151214002360021524 0ustar00<?php


/**
 * Class BF_Page_Builders_Wrapper
 *
 * @since 4.0.0
 */
abstract class BF_Page_Builder_Wrapper {

	/**
	 * Register supported fields.
	 *
	 * @since 4.0.0
	 * @return bool true on success.
	 */
	abstract public function register_fields();


	/**
	 * Unique id of the page builder.
	 *
	 * @since 4.0.0
	 * @return string
	 */
	abstract public function unique_id();

	/**
	 * Register shortcode map.
	 *
	 * @param array $settings
	 * @param mixed $fields transformed fields
	 *
	 * @since 4.0.0
	 * @return bool true on success
	 */
	abstract public function register_map( array $settings, $fields );


	/**
	 * List of supported fields type.
	 *
	 * @since 4.0.0
	 * @return array
	 */
	abstract public function supported_fields();


	/**
	 * Call register_map method when this hook has been fired.
	 *
	 * Empty return value will fire the method immediately.
	 *
	 * @since 4.0.0
	 * @return string
	 */
	public static function register_map_hook() {

		return '';
	}


	/**
	 * Call register_fields method when this hook has been fired.
	 *
	 * Empty return value will fire the method immediately.
	 *
	 * @since 4.0.0
	 * @return string
	 */
	public static function register_fields_hook() {

		return '';
	}
}
libs/better-framework/page-builder/wrappers/class-bf-vc-wrapper.php000064400000033600151214002360021443 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Initialize custom functionality to VC
 */
class BF_VC_Wrapper extends BF_Page_Builder_Wrapper {


	/**
	 * Register shortcode map.
	 *
	 * @param array $settings
	 * @param array $fields transformed fields
	 *
	 * @since 4.0.0
	 * @return bool true on success
	 */
	public function register_map( array $settings, $fields ) {

		if ( empty( $settings['name'] ) ) {
			return false;
		}

		if ( isset( $settings['id'] ) ) {
			$settings['base'] = $settings['id'];
			unset( $settings['id'] );
		}

		$settings['params'] = $fields;

		vc_map( $settings );
	}


	function register_fields() {

		if ( ! class_exists( 'BF_VC_Shortcode_Extender' ) ) {
			require_once BF_PATH . 'page-builder/generators/vc/class-bf-vc-shortcode-extender.php';
		}

		if ( ! class_exists( 'BF_Admin_Fields' ) ) {
			include BF_PATH . 'core/field-generator/class-bf-admin-fields.php';
		}

		if ( ! class_exists( 'BF_VC_Front_End_Generator' ) ) {
			require_once BF_PATH . 'page-builder/generators/vc/class-bf-vc-front-end-generator.php';
		}

		// Make it theme check plugin friendly ;)
		$shortcode_param_add_func = 'vc_add' . '_' . 'shortcode' . '_' . 'param';

		if ( ! function_exists( $shortcode_param_add_func ) ) {
			return;
		}

		call_user_func( $shortcode_param_add_func, 'bf_select', array( $this, 'select_param' ) );
		call_user_func( $shortcode_param_add_func, 'bf_color', array( $this, 'color_param' ) );
		call_user_func( $shortcode_param_add_func, 'bf_background_image', array( $this, 'background_image_param' ) );
		call_user_func( $shortcode_param_add_func, 'bf_media_image', array( $this, 'media_image_param' ) );
		call_user_func( $shortcode_param_add_func, 'bf_image_radio', array( $this, 'image_radio' ) );
		call_user_func( $shortcode_param_add_func, 'bf_info', array( $this, 'info' ) );
		call_user_func( $shortcode_param_add_func, 'bf_slider', array( $this, 'slider_param' ) );
		call_user_func( $shortcode_param_add_func, 'bf_sorter_checkbox', array( $this, 'sorter_checkbox_param' ) );
		call_user_func( $shortcode_param_add_func, 'bf_switch', array( $this, 'switchery' ) );
		call_user_func( $shortcode_param_add_func, 'bf_switchery', array(
			$this,
			'switchery'
		) ); // old. deprecated, fallback
		call_user_func( $shortcode_param_add_func, 'bf_ajax_select', array( $this, 'ajax_param' ) );
		call_user_func( $shortcode_param_add_func, 'bf_icon_select', array( $this, 'icon_select_param' ) );
		call_user_func( $shortcode_param_add_func, 'bf_heading', array( $this, 'heading_param' ) );
		call_user_func( $shortcode_param_add_func, 'bf_term_select', array( $this, 'term_select' ) );
		call_user_func( $shortcode_param_add_func, 'bf_custom', array( $this, 'custom_html' ) );
		call_user_func( $shortcode_param_add_func, 'bf_select_popup', array( $this, 'select_popup' ) );

		return true;
	}


	/**
	 * List of supported fields type.
	 *
	 * @since 4.0.0
	 * @return array
	 */
	public function supported_fields() {

		return array(
			'info',
			'switch',
			'slider',
			'color',
			'select',
			'custom',
			'heading',
			'switchery',
			'ajax_select',
			'icon_select',
			'term_select',
			'image_radio',
			'media_image',
			'select_popup',
			'sorter_checkbox',
			'background_image',
		);
	}


	/**
	 * Convert VC Field option to an BF Field Option
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return array
	 */
	private function convert_field_option( $settings, $value ) {

		$options = array(
			'name'        => $settings['heading'],
			'id'          => $settings['param_name'],
			'input_name'  => $settings['param_name'],
			'value'       => $value,
			'input_class' => "wpb_vc_param_value wpb-" . $settings['type'] . " " . $settings['param_name'] . ' ' . $settings['type'] . "_field",
		);

		if ( isset( $settings['description'] ) ) {
			$options['desc'] = $settings['description'];
		}

		if ( isset( $settings['input-desc'] ) ) {
			$options['input-desc'] = $settings['input-desc'];
		}

		if ( isset( $settings['deferred-options'] ) ) {
			$options['deferred-options'] = $settings['deferred-options'];
		}

		if ( isset( $settings['options'] ) ) {
			$options['options'] = $settings['options'];
		}

		if ( isset( $settings['section_class'] ) ) {
			$options['section_class'] = $settings['section_class'];
		}


		return $options;
	}


	/**
	 * Adds BF Image Radio Field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function image_radio( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'vc-image_radio';

		$generator = new BF_VC_Front_End_Generator( $options, $settings['param_name'] );

		return $generator->get_field();
	}


	/**
	 * Adds BF Info Field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function info( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'vc-info';

		$options['value'] = $settings['std'];

		if ( isset( $settings['state'] ) ) {
			$options['state'] = $settings['state'];
		}

		if ( isset( $settings['info-type'] ) ) {
			$options['info-type'] = $settings['info-type'];
		}

		$generator = new BF_VC_Front_End_Generator( $options, $settings['param_name'] );

		return $generator->get_field();
	}


	/**
	 * Adds BF Image Radio Field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function switchery( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'vc-switchery';

		if ( isset( $settings['on-label'] ) ) {
			$options['on-label'] = $settings['on-label'];
		}

		if ( isset( $settings['off-label'] ) ) {
			$options['off-label'] = $settings['off-label'];
		}

		$generator = new BF_VC_Front_End_Generator( $options, $settings['param_name'] );

		return $generator->get_field();
	}


	/**
	 * Adds BF Color field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function color_param( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'color';

		$generator = new BF_VC_Front_End_Generator( $options, $settings['param_name'] );

		return $generator->get_field();
	}


	/**
	 * Adds BF Select field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function select_param( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'select';

		if ( isset( $settings['multiple'] ) ) {
			$options['multiple'] = $settings['multiple'];
		}

		$generator = new BF_VC_Front_End_Generator( $options, $settings['param_name'] );

		return $generator->get_field();
	}


	/**
	 * Adds BF Select field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function term_select( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'term_select';

		$generator = new BF_VC_Front_End_Generator( $options, $settings['param_name'] );

		return $generator->get_field();
	}


	/**
	 * Adds custom field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function custom_html( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'custom';

		if ( isset( $settings['input_callback'] ) ) {
			$options['input_callback'] = $settings['input_callback'];
		}

		if ( isset( $settings['container_class'] ) ) {
			$options['container_class'] = $settings['container_class'];
		}

		$generator = new BF_VC_Front_End_Generator( $options, $settings['param_name'] );

		return $generator->get_field();
	}


	/**
	 * Adds select popup field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function select_popup( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );
		if ( $extra = wp_array_slice_assoc( $settings, bf_field_extra_options( 'select_popup' ) ) ) {
			$options = array_merge( $options, $extra );
		}

		$options['type'] = 'select_popup';

		if ( isset( $settings['input_callback'] ) ) {
			$options['input_callback'] = $settings['input_callback'];
		}

		if ( isset( $settings['container_class'] ) ) {
			$options['container_class'] = $settings['container_class'];
		}


		$generator = new BF_VC_Front_End_Generator( $options, $settings['param_name'] );

		return $generator->get_field();
	}


	/**
	 * Adds BF Ajax field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function ajax_param( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'ajax_select';

		$options['callback'] = $settings['callback'];

		$options['get_name'] = $settings['get_name'];

		if ( isset( $settings['placeholder'] ) ) {
			$options['placeholder'] = $settings['placeholder'];
		}

		$generator = new BF_VC_Front_End_Generator( $options, $settings['param_name'] );

		return $generator->get_field();
	}


	/**
	 * Adds BF Background Image field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function background_image_param( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'background_image';

		if ( isset( $settings['media_title'] ) ) {
			$options['media_title'] = $settings['media_title'];
		}

		if ( isset( $settings['button_text'] ) ) {
			$options['button_text'] = $settings['button_text'];
		}

		if ( isset( $settings['upload_label'] ) ) {
			$options['upload_label'] = $settings['upload_label'];
		}

		if ( isset( $settings['remove_label'] ) ) {
			$options['remove_label'] = $settings['remove_label'];
		}

		$generator = new BF_VC_Front_End_Generator( $options, $value );

		return $generator->get_field();
	}


	/**
	 * Adds BF Background Image field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function media_image_param( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'vc-media_image';

		if ( isset( $settings['upload_label'] ) ) {
			$options['upload_label'] = $settings['upload_label'];
		}

		if ( isset( $settings['remove_label'] ) ) {
			$options['remove_label'] = $settings['remove_label'];
		}

		if ( isset( $settings['media_title'] ) ) {
			$options['media_title'] = $settings['media_title'];
		}

		if ( isset( $settings['media_button'] ) ) {
			$options['media_button'] = $settings['media_button'];
		}

		if ( isset( $settings['data-type'] ) ) {
			$options['data-type'] = $settings['data-type'];
		}

		if ( isset( $settings['show_input'] ) ) {
			$options['show_input'] = $settings['show_input'];
		}

		if ( isset( $settings['hide_preview'] ) ) {
			$options['hide_preview'] = $settings['hide_preview'];
		}

		$generator = new BF_VC_Front_End_Generator( $options, $value );

		return $generator->get_field();
	}


	/**
	 * Adds BF slider field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function slider_param( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'slider';

		if ( isset( $settings['dimension'] ) ) {
			$options['dimension'] = $settings['dimension'];
		}

		if ( isset( $settings['min'] ) ) {
			$options['min'] = $settings['min'];
		}

		if ( isset( $settings['max'] ) ) {
			$options['max'] = $settings['max'];
		}

		if ( isset( $settings['step'] ) ) {
			$options['step'] = $settings['step'];
		}

		$generator = new BF_VC_Front_End_Generator( $options, $value );

		return $generator->get_field();
	}


	/**
	 * Adds BF slider field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function sorter_checkbox_param( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'vc-sorter_checkbox';

		if ( ! is_bool( $value ) && ! empty( $value ) ) {
			$options['value'] = $value;
		} elseif ( isset( $settings['value'] ) ) {
			$options['value'] = $settings['value'];
		}

		$generator = new BF_VC_Front_End_Generator( $options, $value );

		return $generator->get_field();
	}


	/**
	 * Adds BF Background Image field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function icon_select_param( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'icon_select';

		$generator = new BF_VC_Front_End_Generator( $options, $value );

		return $generator->get_field();
	}


	/**
	 * Adds BF Heading field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function heading_param( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'heading';
		if ( isset( $settings['heading'] ) ) {
			$options['title'] = $settings['heading'];
		} elseif ( isset( $options['title'] ) ) {
			$options['title']   = $settings['title'];
			$options['heading'] = $settings['title'];
		}

		$generator = new BF_VC_Front_End_Generator( $options, $value );

		return $generator->get_field();
	}


	/**
	 * Unique id of the page builder.
	 *
	 * @since 4.0.0
	 * @return string
	 */
	public function unique_id() {

		return 'VC';
	}
}
libs/better-framework/page-builder/wrappers/class-bf-elementor-wrapper.php000064400000005567151214002360023040 0ustar00<?php


class BF_Elementor_Wrapper extends BF_Page_Builder_Wrapper {

	/**
	 * @var array
	 */
	protected $elementor_built_in_fields = array(
		'text',
		'heading',
		'hr',
		'textarea',
		'wp_editor',
		'code',
		'switch',
		'select',
		'radio',
		'color',
		'media_image',
		'slider',
	);

	/**
	 * @var array
	 */
	protected $wrapper_fields_list = array(
		//		'date',
		//		'checkbox',
		//		'ajax_select',
		//		'ajax_action',
		//		'sorter',
		//		'sorter_checkbox',
		//		'media',
		//		'background_image',
		//		'image_upload',
		//		'image_checkbox',
		//		'image_radio',
		//		'image_select',
		//		'icon_select',
		//		'typography',
		//		'border',
		//		'export',
		//		'import',
		//		'custom',
		//		'group_close',
		//		'editor',
		//		'term_select',
		//		'image_preview',
		//		'select_popup',
		'info',
	);


	/**
	 * Register supported fields.
	 *
	 * @return bool true on success.
	 */
	public function register_fields() {

		if ( ! class_exists( 'BF_Elementor_Control_Wrapper' ) ) {

			require BF_PATH . 'page-builder/wrappers/class-bf-elementor-control-wrapper.php';
		}

		foreach ( $this->wrapper_fields_list as $field_type ) {

			$control = new BF_Elementor_Control_Wrapper();
			$control->set_bf_field_type( $field_type );

			\Elementor\Plugin::$instance->controls_manager->register_control( $field_type, $control );
		}

		return true;
	}


	/**
	 * Register shortcode map.
	 *
	 * @param array $settings
	 * @param array $fields transformed fields
	 *
	 * @return bool true on success
	 */
	public function register_map( array $settings, $fields ) {

		if ( $settings['id'] !== 'bs-about' ) {

			return;
		}

		if ( ! class_exists( 'BF_Elementor_Widget_Wrapper' ) ) {
			require BF_PATH . 'page-builder/wrappers/class-bf-elementor-widget-wrapper.php';
		}

		try {

			$widget = new BF_Elementor_Widget_Wrapper();
			$widget->set_bf_shortcode_settings( $settings );

			return \Elementor\Plugin::instance()->widgets_manager->register_widget_type( $widget );

		} catch( Exception $e ) {

			return false;
		}
	}


	/**
	 * List of supported fields type.
	 *
	 * @return array
	 */
	public function supported_fields() {

		return array_merge( $this->elementor_built_in_fields, $this->wrapper_fields_list );
	}


	/**
	 * Call register_map method when this hook has been fired.
	 *
	 * Empty return value will fire the method immediately.
	 *
	 * @since 4.0.0
	 * @return string
	 */
	public static function register_map_hook() {

		return 'elementor/widgets/widgets_registered';
	}


	/**
	 * Call register_map method when this hook has been fired.
	 *
	 * Empty return value will fire the method immediately.
	 *
	 * @since 4.0.0
	 * @return string
	 */
	public static function register_fields_hook() {

		return 'elementor/controls/controls_registered';
	}

	/**
	 * Unique id of the page builder.
	 *
	 * @since 4.0.0
	 * @return string
	 */
	public function unique_id() {

		return 'Elementor';
	}
}
libs/better-framework/page-builder/wrappers/class-bf-page-builder-widget-wrapper.php000064400000003242151214002360024653 0ustar00<?php


class BF_Page_Builder_Widget_Wrapper {

	public $widget_based_page_builders = array(
		'Elementor',
		'SiteOrigin',
	);


	public function __construct() {

		add_action( 'widgets_init', array( $this, 'init_widgets' ), 30 );

		if ( ! class_exists( 'BF_Widget_Artificial' ) ) {

			require BF_PATH . 'page-builder/misc/class-bf-widget-artificial.php';
		}
	}


	/**
	 * Init shortcodes as widget for known page builders.
	 */
	public function init_widgets() {

		if ( ! $this->can_init_widgets() ) {
			return;
		}

		foreach ( BF_Shortcodes_Manager::shortcodes_list() as $key => $shortcode ) {

			if ( isset( $shortcode['widget_class'] ) || ! empty( $shortcode['skip_page_builder'] ) ) {

				continue;
			}

			$this->register_widget( $key );
		}
	}


	/**
	 * @param string $shortcode_id
	 *
	 * @return BF_Widget_Artificial
	 */
	public function widget_class( $shortcode_id ) {

		return new BF_Widget_Artificial( $shortcode_id );
	}


	/**
	 * @param string $shortcode_id
	 */
	public function register_widget( $shortcode_id ) {

		global $wp_widget_factory;

		// we can't use register_widget( $widget ) because siteorigin page builder won't work when $widget is an object

		$wp_widget_factory->widgets["bf-page-builder-widget-$shortcode_id"] = $this->widget_class( $shortcode_id );

	}


	/**
	 * @return bool
	 */
	public function can_init_widgets() {

		if ( $this->is_wp_widgets_page() ) {
			return false;
		}

		$page_builder = Better_Framework::factory( 'page-builder' )->active_page_builders();

		return in_array( $page_builder, $this->widget_based_page_builders );
	}


	public function is_wp_widgets_page() {

		global $pagenow;

		return 'widgets.php' === $pagenow;
	}
}
libs/better-framework/page-builder/wrappers/class-bf-elementor-control-wrapper.php000064400000006124151214002360024504 0ustar00<?php


class BF_Elementor_Control_Wrapper extends \Elementor\Base_Data_Control {

	/**
	 * @var string
	 */
	public $bf_field_type;


	/**
	 * Get emoji one area control type.
	 *
	 * Retrieve the control type, in this case `emojionearea`.
	 *
	 * @since  1.0.0
	 * @access public
	 *
	 * @return string Control type.
	 */
	public function get_type() {

		return $this->bf_field_type;
	}


	/**
	 * Enqueue emoji one area control scripts and styles.
	 *
	 * Used to register and enqueue custom scripts and styles used by the emoji one
	 * area control.
	 *
	 * @since  1.0.0
	 * @access public
	 */
	public function enqueue() {
	}


	/**
	 * Get emoji one area control default settings.
	 *
	 * Retrieve the default settings of the emoji one area control. Used to return
	 * the default settings while initializing the emoji one area control.
	 *
	 * @since  1.0.0
	 * @access protected
	 *
	 * @return array Control default settings.
	 */
	protected function get_default_settings() {

		return array();
	}


	/**
	 * Render emoji one area control output in the editor.
	 *
	 * Used to generate the control HTML in the editor using Underscore JS
	 * template. The variables for the class are available using `data` JS
	 * object.
	 *
	 * @since  1.0.0
	 * @access public
	 */
	public function content_template() {

		$control_uid = $this->get_control_uid();
		?>

		<div class="elementor-control-field">
			<label for="<?php echo esc_attr( $control_uid ); ?>" class="elementor-control-title">
				{{{ data.label }}}
			</label>
			<div class="elementor-control-input-wrapper">
				<?php
				$this->render_field();
				?>
			</div>
		</div>
		<# if ( data.description ) { #>
			<div class="elementor-control-field-description">{{{ data.description }}}</div>
			<# } #>
		<?php
	}


	/**
	 * @param string $field_type
	 */
	public function set_bf_field_type( $field_type ) {

		$this->bf_field_type = $field_type;
	}


	/**
	 * @return string
	 */
	public function get_bf_field_type() {

		return $this->bf_field_type;
	}


	/**
	 *
	 */
	protected function render_field() {

		$fields_dir = BF_PATH . 'core/field-generator/fields/';
		$field_file = sprintf( '%s.php', $this->bf_field_type );


		$options = array(
			'value'      => '',
			'input_name' => '___INPUT_NAME_PLACEHOLDER___',
		);

		ob_start();

		include $fields_dir . $field_file;

		$field_markup = ob_get_clean();

		echo $this->embed_unique_id( $field_markup );
	}


	/**
	 * @param string $html
	 *
	 * @return html
	 */
	public function embed_unique_id( $html ) {


		$pattern = '/(
			\< \s*   [a-z]+    [^\>]*
				name\s*=\s*
				([\'\"])?
				___INPUT_NAME_PLACEHOLDER___
				(?(2) \\2)
				[^\>]*
			\>)/isx';

		return preg_replace_callback( $pattern, array( $this, 'embed_unique_id_in_field' ), $html );
	}


	public function embed_unique_id_in_field( $matches ) {

		$field          = $matches[1];
		$modified_field = preg_replace( '/ id\s*=\s* ([^\s\>]+)/isx', 'id="' . $this->get_control_uid() . '"', $field );

		if ( $modified_field !== $field ) {
			return $modified_field;
		}

		return preg_replace( '/(.+)\>/', '$1 id="' . $this->get_control_uid() . '">', $field );
	}
}
libs/better-framework/page-builder/wrappers/class-bf-elementor-widget-wrapper.php000064400000007347151214002360024317 0ustar00<?php


class BF_Elementor_Widget_Wrapper extends \Elementor\Widget_Base {

	public $widget_id;


	public function __construct( array $data = [], array $args = null ) {

		if ( isset( $data['widgetType'] ) ) {
			$this->widget_id = $data['widgetType'];
		}

		parent::__construct( $data, $args );
	}


	/**
	 * @var array
	 */
	protected $bf_shortcode_settings = array();


	/**
	 * Get widget name.
	 *
	 * @access public
	 *
	 * @return string Widget name.
	 */
	public function get_name() {

		return isset( $this->bf_shortcode_settings['id'] ) ? $this->bf_shortcode_settings['id'] : '';
	}


	/**
	 * Get widget title.
	 *
	 * @access public
	 *
	 * @return string Widget title.
	 */
	public function get_title() {

		return isset( $this->bf_shortcode_settings['name'] ) ? $this->bf_shortcode_settings['name'] : '';
	}


	/**
	 * Get widget icon.
	 *
	 * @access public
	 *
	 * @return string Widget icon.
	 */
	public function get_icon() {

		return isset( $this->bf_shortcode_settings['icon'] ) ? $this->bf_shortcode_settings['icon'] : '';
	}


	/**
	 * Get widget categories.
	 *
	 * @access public
	 *
	 * @return array Widget categories.
	 */
	public function get_categories() {

		if ( isset( $this->bf_shortcode_settings['category'] ) ) {

			return array(
				$this->bf_shortcode_settings['category']
			);
		}

		return array( 'general' );
	}


	/**
	 * Register oEmbed widget controls.
	 *
	 * @access protected
	 */
	protected function _register_controls() {

		if ( ! class_exists( 'BF_Fields_Adapter' ) ) {

			require BF_PATH . '/page-builder/class-bf-fields-adapter.php';
		}

		if ( ! class_exists( 'BF_To_Elementor_Fields_Adapter' ) ) {

			require BF_PATH . 'page-builder/adapters/elementor/class-bf-to-elementor-fields-adapter.php';
		}

		BF_Shortcodes_Manager::factory();
		$adapter = new BF_To_Elementor_Fields_Adapter();

		$adapter->set_elementor_widget( $this );


		$adapter->load_fields( $this->shortcode_fields() );
		$adapter->transform();
	}


	/**
	 * Render oEmbed widget output on the frontend.
	 *
	 * @access protected
	 */
	protected function render() {

		$content = '';

		echo BF_Shortcodes_Manager::handle_shortcodes(
			$this->attributes(),
			$content,
			$this->widget_id
		);
	}


	/**
	 * @return array
	 */
	protected function attributes() {

		$attrs = $this->get_settings();

		foreach ( $this->attributes_changes() as $id => $index ) {

			if ( ! isset( $attrs[ $id ] ) ) {
				continue;
			}

			$attrs[ $id ] = isset( $attrs[ $id ][ $index ] ) ? $attrs[ $id ][ $index ] : '';
		}

		return $attrs;
	}


	/**
	 * @return array
	 */
	protected function attributes_changes() {

		if ( ! $changes = get_option( 'bf-elementor-fields-comp' ) ) {
			return array();
		}

		return isset( $changes[ $this->widget_id ] ) ? $changes[ $this->widget_id ] : array();
	}


	/**
	 * @param array $settings
	 */
	public function set_bf_shortcode_settings( $settings ) {

		$this->bf_shortcode_settings = $settings;

		if ( ! empty( $settings['id'] ) ) {

			$this->widget_id = $settings['id'];
		}
	}


	/**
	 * @return array
	 */
	public function get_bf_shortcode_settings() {

		return $this->bf_shortcode_settings;
	}


	public function shortcode_fields() {

		$fields = array();

		if ( $shortcode = BF_Shortcodes_Manager::factory( $this->widget_id ) ) {

			$fields = $shortcode->get_fields();

			$this->fields_compatibility( $fields );
		}

		return $fields;
	}


	public function fields_compatibility( &$fields ) {

		$status = get_option( 'bf-elementor-fields-comp', array() );

		foreach ( $fields as $field ) {

			if ( isset( $field['type'] ) && 'media_image' === $field['type'] ) {

				$status[ $this->widget_id ][ $field['id'] ] = isset( $field['data-type'] ) ? $field['data-type'] : 'url';
			}
		}

		update_option( 'bf-elementor-fields-comp', $status );
	}
}
libs/better-framework/page-builder/wrappers/class-bf-kc-wrapper.php000064400000012400151214002360021423 0ustar00<?php


class BF_KC_Wrapper extends BF_Page_Builder_Wrapper {

	/**
	 * @var array
	 *
	 * @since 4.0.0
	 */
	public $static_fields = array();


	/**
	 * Register
	 *
	 * @return bool true on success.
	 */
	public function register_fields() {

		global $kc;

		if ( ! $kc || ! is_callable( array( $kc, 'add_param_type' ) ) ) {
			return false;
		}

		// Register fields except deferred ones, they will load via ajax
		// @see BF_KC_Compatibility::ajax_load_fields()

		$this->static_fields = array_diff(
			$this->supported_fields(),
			$this->dynamic_deferred_fields(),
			$this->static_deferred_fields()
		);

		/**
		 * We can't use  $kc->add_param_type because the second parameter doesn't accept object
		 * That's silly but we have to handle this part in hard way!
		 *
		 * @see KingComposer::convert_paramTypes
		 */
		//		add_action( 'kc_after_admin_footer', array( $this, 'print_static_fields_template' ) );

		require BF_PATH . 'page-builder/generators/kc/kc-field-generator-functions.php';
		foreach ( $this->static_fields as $field ) {

			if ( function_exists( 'bf_kc_field_' . $field ) ) {
				$kc->add_param_type( $field, 'bf_kc_field_' . $field );
			}
		}

		return true;
	}

	/**
	 * @since 4.0.0
	 */
	/*public function print_static_fields_template() {

		if ( empty( $this->static_fields ) ) {

			return;
		}

		if ( ! class_exists( 'BF_KC_Fields_Generator' ) ) {
			require BF_PATH . 'page-builder/generators/kc/class-bf-kc-fields-generator.php';
		}

		$generator = new BF_KC_Fields_Generator();

		foreach ( $this->static_fields as $field ) {

			echo '<script type="text/html" id="tmpl-kc-field-type-' . esc_attr( $field ) . '-template">';

			$options = array(
				'id'    => '{{data.name}}',
				'value' => '{{data.value}}',
				'type'  => $field,
			);

			call_user_func( array( $generator, $field ), $options );

			echo "</script>\n";
		}
	}*/

	/**
	 * Adds BF Select field to Visual Composer
	 *
	 * @param $settings
	 * @param $value
	 *
	 * @return string
	 */
	function select_param( $settings, $value ) {

		$options = $this->convert_field_option( $settings, $value );

		$options['type'] = 'select';

		if ( isset( $settings['multiple'] ) ) {
			$options['multiple'] = $settings['multiple'];
		}

		$generator = new BF_VC_Front_End_Generator( $options, $settings['param_name'] );

		return $generator->get_field();
	}


	/**
	 * Register shortcode map.
	 *
	 * @param array $settings
	 * @param array $fields transformed fields
	 *
	 * @return bool true on success
	 */
	public function register_map( array $settings, $fields ) {

		if ( empty( $settings['name'] ) || empty( $settings['id'] ) ) {
			return false;
		}
		if ( empty( $fields ) ) {
			return false;
		}

		$always_fetch_fields = false;
		$deferred_types      = $this->dynamic_deferred_fields();

		foreach ( $fields as $tab_fields ) {

			foreach ( $tab_fields as $field ) {

				if ( in_array( $field['type'], $deferred_types ) ) {

					BF_KC_Compatibility::always_fetch_map_fields( $settings['id'] );

					$always_fetch_fields = true;
					break 2;
				}
			}
		}

		if ( ! $always_fetch_fields ) {

			$deferred_types  = $this->static_deferred_fields();
			$deferred_fields = array();

			foreach ( $fields as $tab_fields ) {

				foreach ( $tab_fields as $field ) {

					if ( in_array( $field['type'], $deferred_types ) ) {

						$deferred_fields[] = $field['type'];
					}
				}
			}

			if ( ! empty( $deferred_fields ) ) {
				BF_KC_Compatibility::mark_fields_as_deferred( $settings['id'], $deferred_fields );
			}
		}

		$settings['params'] = $fields;

		if ( isset( $settings['desc'] ) ) {

			$settings['description'] = $settings['desc'];
			unset( $settings['desc'] );
		}

		return $this->kc_map( $settings['id'], $settings );
	}


	/**
	 * List of all supported fields type.
	 *
	 * @return array
	 */
	public function supported_fields() {

		return array(
			'text',
			'color',
			'switch',
			'heading',
			'icon_select',
			'select',
			'select_popup',
			'term_select',
			'ajax_select',
			'custom',
			'group',
			'group_close',
			'info',
			'heading',
			'image_radio',
			'media_image',
			'sorter_checkbox',
			// 'background_image',
		);
	}


	/**
	 * todo: add comment
	 *
	 * @return array
	 */
	public function static_deferred_fields() {

		return array();
	}


	/**
	 * todo: add comment
	 * List of fields types that should be fetch via ajax
	 *
	 * @return array
	 */
	public function dynamic_deferred_fields() {

		return array(
			'icon_select',
			'select',
			'select_popup',
			'term_select',
			'ajax_select',
			'heading',
			'custom',
			'group',
			'group_close',
			'info',
			'image_radio',
			'media_image',
			'sorter_checkbox',
			// 'background_image',
		);
	}


	/**
	 * @param string        $id
	 * @param array         $atts
	 *
	 * @global KingComposer $kc
	 *
	 * @since 4.0.0
	 * @return bool true on success or false on error.
	 */
	public function kc_map( $id, $atts ) {

		global $kc;

		if ( $kc && is_callable( array( $kc, 'add_map' ) ) ) {

			if ( empty( $atts['category'] ) ) {
				$atts['category'] = 'all';
			}

			if ( empty( $atts['icon'] ) ) {

				$atts['icon'] = "$id-icon";
			}

			$kc->add_map( array( $id => $atts ) );

			return true;
		}

		return false;
	}

	/**
	 * Unique id of the page builder.
	 *
	 * @since 4.0.0
	 * @return string
	 */
	public function unique_id() {

		return 'KC';
	}
}libs/better-framework/page-builder/wrappers/index.php000064400000000050151214002360016765 0ustar00<?php

// let's show them we are better
libs/better-framework/page-builder/class-bf-page-builder-extender.php000064400000011116151214002360021664 0ustar00<?php


class BF_Page_Builder_Extender {


	public function __construct() {

		/**
		 * @var BF_Page_Builder_Wrapper $wrapper
		 */

		foreach ( self::active_page_builders() as $page_builder ) {

			if ( ! $wrapper_class = $this->wrapper_class( $page_builder ) ) {
				continue;
			}

			if ( $hook = call_user_func( array( $wrapper_class, 'register_fields_hook' ) ) ) {

				add_action( $hook, array( $this, 'register_fields_hook' ) );

			} else {

				$wrapper = new $wrapper_class();
				$wrapper->register_fields();
			}
		}

		if ( self::is_kc_active() ) {

			require BF_PATH . 'page-builder/compatibility/kc/class-bf-kc-compatibility.php';
		}
	}


	/**
	 * @return bool
	 */
	public function register_fields_hook() {

		foreach ( self::active_page_builders() as $page_builder ) {

			if ( $wrapper_class = $this->wrapper_class( $page_builder ) ) {

				$wrapper = new $wrapper_class();
				$wrapper->register_fields();
			}
		}

		return true;
	}


	/**
	 * Detect current running page builder plugin.
	 *
	 * @since 4.0.0
	 * @return string empty string on error or plugin short name on success.
	 */
	public static function active_page_builders() {

		$page_builders = array();

		if ( defined( 'WPB_VC_VERSION' ) && WPB_VC_VERSION ) {
			$page_builders[] = 'VC';
		}

		if ( defined( 'KCP_VERSION' ) && KCP_VERSION ) {
			$page_builders[] = 'KCP';
		}

		if ( defined( 'KC_VERSION' ) && KC_VERSION ) {
			$page_builders[] = 'KC';
		}

		if ( defined( 'ELEMENTOR_VERSION' ) && ELEMENTOR_VERSION ) {
			$page_builders[] = 'Elementor';
		}

		if ( defined( 'SITEORIGIN_PANELS_VERSION' ) && SITEORIGIN_PANELS_VERSION ) {
			$page_builders[] = 'SiteOrigin';
		}

		if ( ! class_exists( 'BF_Gutenberg_Shortcode_Wrapper' ) ) {
			require BF_PATH . 'gutenberg/class-bf-gutenberg-shortcode-wrapper.php';
		}

		if ( BF_Gutenberg_Shortcode_Wrapper::is_gutenberg_active() ) {
			$page_builders[] = 'Gutenberg';
		}

		return $page_builders;
	}

	public static function is_kc_active() {

		return in_array( 'KCP', self::active_page_builders() )
		       ||
		       in_array( 'KC', self::active_page_builders() );
	}


	/**
	 * Get current active page builder wrapper class.
	 *
	 * @param $page_builder
	 *
	 * @since 4.0.0
	 * @return string empty on failure.
	 */
	public function wrapper_class( $page_builder ) {

		if ( ! class_exists( 'BF_Page_Builder_Wrapper' ) ) {

			require BF_PATH . '/page-builder/class-bf-page-builder-wrapper.php';
		}

		$class_name = '';

		switch ( $page_builder ) {

			case 'VC':

				if ( ! class_exists( 'BF_VC_Wrapper' ) ) {

					require BF_PATH . '/page-builder/wrappers/class-bf-vc-wrapper.php';
				}

				$class_name = 'BF_VC_Wrapper';

				break;

			case 'KC':
			case 'KCP':

				if ( ! class_exists( 'BF_KC_Wrapper' ) ) {

					require BF_PATH . '/page-builder/wrappers/class-bf-kc-wrapper.php';
				}

				$class_name = 'BF_KC_Wrapper';

				break;
			/*
						case 'Elementor':

							if ( ! class_exists( 'BF_Elementor_Wrapper' ) ) {

								require BF_PATH . '/page-builder/wrappers/class-bf-elementor-wrapper.php';
							}

							$class_name = 'BF_Elementor_Wrapper';

							break;

			*/
		}

		return $class_name;
	}


	/**
	 * Get current active page builder adapter class.
	 *
	 * @param string $page_builder
	 *
	 * @since 4.0.0
	 * @return bool|BF_Fields_Adapter false on failure.
	 */
	public function adapter_class( $page_builder ) {

		if ( ! class_exists( 'BF_Fields_Adapter' ) ) {

			require BF_PATH . '/page-builder/class-bf-fields-adapter.php';
		}

		switch ( $page_builder ) {

			case 'VC':

				if ( ! class_exists( 'BF_To_VC_Fields_Adapter' ) ) {

					require BF_PATH . 'page-builder/adapters/class-bf-to-vc-fields-adapter.php';
				}

				$class_name = 'BF_To_VC_Fields_Adapter';

				break;

			case 'KC':
			case 'KCP':

				if ( ! class_exists( 'BF_To_KC_Fields_Adapter' ) ) {

					require BF_PATH . 'page-builder/adapters/class-bf-to-kc-fields-adapter.php';
				}

				$class_name = 'BF_To_KC_Fields_Adapter';

				break;
		}

		if ( ! empty( $class_name ) ) {
			return $class_name;
		}

		return false;
	}


	/**
	 * Transform standard BF fields format to active page builder style.
	 *
	 * @param string      $page_builder_id
	 * @param array $fields
	 * @param array $defaults
	 *
	 * @return mixed WP_Error|false on failure otherwise array|object
	 * @since 4.0.0
	 */
	public function transform( $page_builder_id, array $fields, $defaults = array() ) {

		if ( ! $adapter_class = $this->adapter_class( $page_builder_id ) ) {
			return false;
		}

		$adapter = new $adapter_class();
		$adapter->load_fields( $fields );
		$adapter->load_defaults( $defaults );

		return $adapter->transform();
	}
}
libs/better-framework/page-builder/adapters/class-bf-to-kc-fields-adapter.php000064400000006727151214002370023227 0ustar00<?php


/**
 * Transform standard BF fields format to King Composer style
 *
 * @since 4.0.0
 */
class BF_To_KC_Fields_Adapter extends BF_Fields_Adapter {

	/**
	 * Transform
	 *
	 * @since 4.0.0
	 * @return array
	 */
	public function transform() {

		if ( empty( $this->fields ) ) {
			return array();
		}


		$shared_field_options = array(
			'type'          => '',
			'name'          => '',
			'value'         => '',
			'label'         => '',
			'admin_label'   => '',
			'description'   => '',
			'section_class' => '',
			'_options'      => '',
			'show_on'       => '',
			'multiple'      => '',
		);
		$replacements         = array(
			// 'bf key' => 'kc key'
			'name'           => 'label',
			'id'             => 'name',
			'desc'           => 'description',
			'vc_admin_label' => 'admin_label',
			'admin_label'    => 'admin_label',
		);

		$standard_fields  = $this->list_standard_fields();
		$supported_fields = $this->list_all_supported_fields();
		$current_tab      = __( 'General', 'better-studio' );

		$new_fields = array();

		foreach ( $this->fields as $idx => $field ) {

			if ( $field['type'] === 'tab' ) {
				$current_tab = $field['name'];
				continue;
			}

			if ( ! in_array( $field['type'], $supported_fields ) ) {
				continue;
			}

			$new_field                = $field;
			$new_field['is_standard'] = in_array( $field['type'], $standard_fields );

			// Set default value if exists
			if ( isset( $field['id'] ) && isset( $this->defaults[ $field['id'] ] ) ) {
				$new_field['value'] = $this->defaults[ $field['id'] ];
			}

			// Transform bf fields key to visual composer type
			foreach ( array_intersect_key( $replacements, $field ) as $key => $new_key ) {

				$new_field[ $new_key ] = $field[ $key ];

				unset( $new_field[ $key ] );
			}

			if ( isset( $new_field['options'] ) ) { // handle reserved 'options' key
				$new_field['_options'] = $new_field['options'];
				unset( $new_field['options'] );
			}
			$new_field['options'] = array_diff_key( $new_field, $shared_field_options );

			// Pass show_on value via options parameter only  for standard fields
			if ( $new_field['is_standard'] && ! empty( $field['show_on'] ) ) {

				$new_field['options']['show_on'] = array( 'show_on' => $field['show_on'] );
			}


			// Change 'group' type to bf_group to prevent conflict with king composer group field.]

			if ( 'group' === $new_field['type'] ) {

				$new_field['type'] = 'bf_group';

			} elseif ( 'group_close' === $new_field['type'] ) {

				$new_field['type'] = 'bf_group_close';
			}

			//TODO: add bf color picker support
			if ( 'color' === $new_field['type'] ) {

				$new_field['type'] = 'color_picker';
			}

			$new_fields[ $current_tab ][] = $new_field;
		}

		return $new_fields;
	}


	/**
	 * @since 4.0.0
	 * @return array
	 */
	public function list_standard_fields() {

		/**
		 * @var BF_KC_Wrapper $kc_wrapper
		 */

		if ( ! $kc_wrapper = Better_Framework::factory( 'page-builder' )->wrapper_class( 'KC' ) ) {
			return array();
		}

		$kc_wrapper = new $kc_wrapper();

		return array_diff(
			$kc_wrapper->supported_fields(),
			$kc_wrapper->dynamic_deferred_fields(),
			$kc_wrapper->static_deferred_fields()
		);
	}


	/**
	 * Get list of all supported fields in King Composer
	 *
	 * @since 4.0.0
	 * @return array
	 */
	public function list_all_supported_fields() {

		if ( ! $kc_wrapper = Better_Framework::factory( 'page-builder' )->wrapper_class( 'KC' ) ) {
			return array();
		}

		$kc_wrapper = new $kc_wrapper;

		return $kc_wrapper->supported_fields();
	}
}
libs/better-framework/page-builder/adapters/class-bf-to-vc-fields-adapter.php000064400000003164151214002370023232 0ustar00<?php


/**
 * Transform standard BF fields format to VisualComposer style
 *
 * @since 4.0.0
 */
class BF_To_VC_Fields_Adapter extends BF_Fields_Adapter {

	/**
	 * Transform
	 *
	 * @since 4.0.0
	 * @return array
	 */
	public function transform() {

		$replacements = array(
			// 'bf key' => 'vc key'
			'name'           => 'heading',
			'desc'           => 'description',
			'id'             => 'param_name',
			'vc_admin_label' => 'admin_label',
		);


		$wrapper_class    = Better_Framework::factory( 'page-builder' )->wrapper_class( 'VC' );
		$vc_wrapper       = new $wrapper_class;
		$supported_fields = $vc_wrapper->supported_fields();
		$current_tab      = __( 'General', 'better-studio' );
		$fields           = $this->fields;

		foreach ( $this->fields as $idx => $field ) {

			if ( $field['type'] === 'tab' ) {
				$current_tab = $field['name'];
				unset( $fields[ $idx ] );
				continue;
			}

			// Set default value if exists
			if ( isset( $field['id'] ) && isset( $this->defaults[ $field['id'] ] ) ) {
				$fields[ $idx ]['value'] = $this->defaults[ $field['id'] ];
			}

			// Transform field type to vc-extender standard
			if ( $field['type'] === 'text' ) {
				$fields[ $idx ]['type'] = 'textfield';
			} elseif ( in_array( $field['type'], $supported_fields ) ) {
				$fields[ $idx ]['type'] = 'bf_' . $field['type'];
			}

			// Transform bf fields key to visual composer type
			foreach ( array_intersect_key( $replacements, $field ) as $key => $new_key ) {

				$fields[ $idx ][ $new_key ] = $field[ $key ];

				unset( $fields[ $idx ][ $key ] );
			}

			$fields[ $idx ]['group'] = $current_tab;
		}

		return $fields;
	}
}
libs/better-framework/page-builder/adapters/index.php000064400000000050151214002370016726 0ustar00<?php

// let's show them we are better
libs/better-framework/page-builder/adapters/elementor/class-bf-elementor-field.php000064400000000772151214002370024367 0ustar00<?php


abstract class BF_Elementor_Field_Transformer {

	/**
	 * @var array
	 */
	protected $field;


	/**
	 *
	 * @return array
	 */
	abstract public function transform_field();


	/**
	 * @param array $field
	 */
	public function init( $field ) {

		$this->field = $field;
	}


	/**
	 * @param string $index
	 *
	 * @return mixed
	 */
	public function field( $index = '' ) {

		if ( $index ) {

			return isset( $this->field[ $index ] ) ? $this->field[ $index ] : null;
		}

		return $this->field;
	}
}
libs/better-framework/page-builder/adapters/elementor/class-bf-to-elementor-fields-adapter.php000064400000013267151214002370026613 0ustar00<?php


class BF_To_Elementor_Fields_Adapter extends BF_Fields_Adapter {

	/**
	 * @var Elementor\Widget_Base
	 */
	protected $widget;


	/**
	 * @var array
	 */
	protected $supported_fields = array();


	public function __construct( array $fields = array(), array $defaults = array() ) {

		parent::__construct( $fields, $defaults );

		$wrapper_class = Better_Framework::factory( 'page-builder' )->wrapper_class( 'Elementor' );

		$wrapper = new $wrapper_class();
		//
		$this->supported_fields = $wrapper->supported_fields();

	}


	/**
	 * @return mixed|WP_Error WP_Error on failure or transformed fields on success.
	 */
	public function transform() {

		if ( empty( $this->fields ) ) {
			return false;
		}

		reset( $this->fields );
		$first_index = key( $this->fields );
		$first_field = $this->fields[ $first_index ];
		//
		end( $this->fields );
		$last_index = key( $this->fields );
		$last_field = $this->fields[ $last_index ];
		//

		if ( ! isset( $first_field['type'] ) ||
		     ! in_array( $first_field['type'], array( 'group', 'tab' ) )
		) {

			$this->widget->start_controls_section(
				'section_title',
				array(
					'label' => $this->widget->get_title(),
				)
			);
		}
		$tab_started = false;

		foreach ( $this->fields as $id => $field ) {

			if ( empty( $field['type'] ) ) {
				continue;
			}

			$type = $field['type'];

			if ( $type === 'group' ) {

				$this->widget->start_controls_section(
					isset( $field['id'] ) ? $field['id'] : $id,
					array(
						'label' => $field['name'],
					)
				);

				continue;
			}

			if ( $type === 'group_close' ) {

				$this->widget->end_controls_section();

				continue;
			}

			if ( $type === 'tab' ) {

				$this->widget->end_controls_section();

				$this->widget->start_controls_section(
					isset( $field['id'] ) ? $field['id'] : $id,
					array(
						'label' => $field['name'],
					)
				);

				$tab_started = true;
			}

			if ( ! in_array( $type, $this->supported_fields ) ) {
				continue;
			}

			if ( empty( $field['id'] ) ) {
				continue;
			}

			if ( $factory = $this->factory( $field ) ) {
				$override_args = $factory->transform_field();
			} else {
				$override_args = array();
			}

			$type_const = strtoupper( $type );

			$this->widget->add_control( $field['id'], array_merge( array(

				'label'       => $field['name'],
				'type'        => defined( "Controls_Manager::$type_const" ) ? Controls_Manager::$type_const : $field['type'],
				'description' => isset( $field['desc'] ) ? $field['desc'] : '',
			), $override_args ) );
		}

		if ( $tab_started ) {
			$this->widget->end_controls_section();
		}

		if ( ! isset( $last_field['type'] ) ||
		     $last_field['type'] !== 'group_close'
		) {

			$this->widget->end_controls_section();
		}


		return true;
	}


	/**
	 * @param \Elementor\Widget_Base $widget
	 */
	public function set_elementor_widget( \Elementor\Widget_Base $widget ) {

		$this->widget = $widget;
	}


	/**
	 * @return \Elementor\Widget_Base
	 */
	public function get_elementor_widget() {

		return $this->widget;
	}


	/**
	 * @param array $field
	 *
	 * @since 3.9.0
	 * @return BF_Elementor_Field_Transformer on success or null on failure.
	 */
	public function factory( array $field ) {

		if ( empty( $field['type'] ) ) {
			return null;
		}

		if ( ! class_exists( 'BF_Elementor_Field_Transformer' ) ) {

			require BF_PATH . 'page-builder/adapters/elementor/class-bf-elementor-field.php';
		}

		switch ( $field['type'] ) {

			case 'custom';

				if ( ! class_exists( 'BF_Elementor_Raw_Field' ) ) {

					require BF_PATH . 'page-builder/adapters/elementor/fields/class-bf-elementor-raw-field.php';
				}

				$instance = new BF_Elementor_Raw_Field();

				break;

			case 'hr';

				if ( ! class_exists( 'BF_Elementor_Divider_Field' ) ) {

					require BF_PATH . 'page-builder/adapters/elementor/fields/class-bf-elementor-divider-field.php';
				}

				$instance = new BF_Elementor_Divider_Field();

				break;

			case 'wp_editor';

				if ( ! class_exists( 'BF_Elementor_WYSIWYG_Field' ) ) {

					require BF_PATH . 'page-builder/adapters/elementor/fields/class-bf-elementor-wysiwyg-field.php';
				}

				$instance = new BF_Elementor_WYSIWYG_Field();

				break;


			case 'editor';

				if ( ! class_exists( 'BF_Elementor_Code_Field' ) ) {

					require BF_PATH . 'page-builder/adapters/elementor/fields/class-bf-elementor-code-field.php';
				}

				$instance = new BF_Elementor_Code_Field();

				break;

			case 'switch';

				if ( ! class_exists( 'BF_Elementor_Switcher_Field' ) ) {

					require BF_PATH . 'page-builder/adapters/elementor/fields/class-bf-elementor-switcher-field.php';
				}

				$instance = new BF_Elementor_Switcher_Field();

				break;


			case 'select';

				if ( ! class_exists( 'BF_Elementor_Select_Field' ) ) {

					require BF_PATH . 'page-builder/adapters/elementor/fields/class-bf-elementor-select-field.php';
				}

				$instance = new BF_Elementor_Select_Field();

				break;

			case 'radio';

				if ( ! class_exists( 'BF_Elementor_Radio_Field' ) ) {

					require BF_PATH . 'page-builder/adapters/elementor/fields/class-bf-elementor-radio-field.php';
				}

				$instance = new BF_Elementor_Radio_Field();

				break;

			case 'media_image';

				if ( ! class_exists( 'BF_Elementor_Media_Field' ) ) {

					require BF_PATH . 'page-builder/adapters/elementor/fields/class-bf-elementor-media-field.php';
				}

				$instance = new BF_Elementor_Media_Field();

				break;


			case 'slider';

				if ( ! class_exists( 'BF_Elementor_Slider_Field' ) ) {

					require BF_PATH . 'page-builder/adapters/elementor/fields/class-bf-elementor-slider-field.php';
				}

				$instance = new BF_Elementor_Slider_Field();

				break;
		}

		if ( isset( $instance ) ) {
			$instance->init( $field );

			return $instance;
		}

		return null;
	}
}
libs/better-framework/page-builder/adapters/elementor/fields/class-bf-elementor-select-field.php000064400000000404151214002370027102 0ustar00<?php


class BF_Elementor_Select_Field extends BF_Elementor_Field_Transformer {

	/**
	 * @return array
	 */
	public function transform_field() {

		return array(
			'options' => isset( $this->field['options'] ) ? $this->field['options'] : array(),
		);
	}
}
libs/better-framework/page-builder/adapters/elementor/fields/class-bf-elementor-raw-field.php000064400000001700151214002370026414 0ustar00<?php


class BF_Elementor_Raw_Field extends BF_Elementor_Field_Transformer {

	/**
	 * @return array
	 */
	public function transform_field() {

		$raw = $this->raw_code();

		return compact( 'raw' );
	}


	/**
	 * @return string
	 */
	public function raw_code() {

		if ( ! isset( $this->field['input_callback'] ) ) {
			return '';
		}

		if ( is_array( $this->field['input_callback'] ) ) {

			$callback = $this->field['input_callback']['callback'];

			if ( isset( $this->field['input_callback']['args'][0] ) ) {

				$callback_args = $this->field['input_callback']['args'];

				$callback_args[0]['field_options'] = $this->field;
			} else {

				$callback_args = array( array( 'field_options' => $this->field ) );
			}

		} else {

			$callback = $this->field['input_callback'];

			$callback_args = array( array( 'field_options' => $this->field ) );
		}

		ob_start();

		call_user_func_array( $callback, $callback_args );

		return ob_get_clean();
	}
}
libs/better-framework/page-builder/adapters/elementor/fields/class-bf-elementor-wysiwyg-field.php000064400000000307151214002370027347 0ustar00<?php


class BF_Elementor_WYSIWYG_Field extends BF_Elementor_Field_Transformer {

	/**
	 * @return array
	 */
	public function transform_field() {

		return array(
			'type' => 'wysiwyg',
		);
	}
}
libs/better-framework/page-builder/adapters/elementor/fields/class-bf-elementor-slider-field.php000064400000000633151214002370027111 0ustar00<?php


class BF_Elementor_Slider_Field extends BF_Elementor_Field_Transformer {

	/**
	 * @return array
	 */
	public function transform_field() {

		if ( isset( $this->field['min'] ) ) {
			$min = $this->field['min'];
		}

		if ( isset( $this->field['max'] ) ) {
			$max = $this->field['max'];
		}

		$step = 1;

		return array(
			'type'  => 'slider',
			'range' => compact( 'min', 'max', 'step' ),
		);
	}
}
libs/better-framework/page-builder/adapters/elementor/fields/class-bf-elementor-code-field.php000064400000000421151214002370026534 0ustar00<?php


class BF_Elementor_Code_Field extends BF_Elementor_Field_Transformer {

	/**
	 * @return array
	 */
	public function transform_field() {

		return array(
			'type'     => 'code',
			'language' => isset( $this->field['lang'] ) ? $this->field['lang'] : '',
		);
	}
}
libs/better-framework/page-builder/adapters/elementor/fields/class-bf-elementor-divider-field.php000064400000000347151214002370027257 0ustar00<?php


class BF_Elementor_Divider_Field extends BF_Elementor_Field_Transformer {

	/**
	 * @return array
	 */
	public function transform_field() {

		return array(
			'type'      => 'divider',
			'separator' => 'after',
		);
	}
}
libs/better-framework/page-builder/adapters/elementor/fields/class-bf-elementor-radio-field.php000064400000000325151214002370026723 0ustar00<?php


class BF_Elementor_Radio_Field extends BF_Elementor_Field_Transformer {

	/**
	 * @return array
	 */
	public function transform_field() {

		return array(
			'options' => $this->field['options']
		);
	}
}
libs/better-framework/page-builder/adapters/elementor/fields/class-bf-elementor-switcher-field.php000064400000000572151214002370027461 0ustar00<?php


class BF_Elementor_Switcher_Field extends BF_Elementor_Field_Transformer {

	/**
	 * @return array
	 */
	public function transform_field() {

		return array(
			'type'      => 'switcher',
			'label_on'  => isset( $this->field['on-label'] ) ? $this->field['on-label'] : '',
			'label_off' => isset( $this->field['off-label'] ) ? $this->field['off-label'] : '',
		);
	}
}
libs/better-framework/page-builder/adapters/elementor/fields/index.php000064400000000050151214002370022166 0ustar00<?php

// let's show them we are better
libs/better-framework/page-builder/adapters/elementor/fields/class-bf-elementor-media-field.php000064400000000500151214002370026677 0ustar00<?php


class BF_Elementor_Media_Field extends BF_Elementor_Field_Transformer {

	/**
	 * @return array
	 */
	public function transform_field() {

		return array(
			'type'        => 'media',
			'show_label'  => ! empty( $this->field['show_input'] ),
			'label_block' => ! empty( $this->field['show_input'] ),
		);
	}
}
libs/better-framework/page-builder/adapters/elementor/index.php000064400000000050151214002370020720 0ustar00<?php

// let's show them we are better
libs/better-framework/page-builder/class-bf-fields-adapter.php000064400000001663151214002370020403 0ustar00<?php


abstract class BF_Fields_Adapter {

	/**
	 * @var array
	 *
	 * @since 4.0.0
	 */
	protected $fields = array();

	/**
	 * @var array
	 *
	 * @since 4.0.0
	 */
	protected $defaults = array();


	/**
	 * @return mixed|WP_Error WP_Error on failure or transformed fields on success.
	 */
	abstract public function transform();


	/**
	 * BF_Fields_Adapter constructor.
	 *
	 * @param array $fields
	 * @param array $defaults
	 *
	 */
	public function __construct( array $fields = array(), array $defaults = array() ) {

		$this->load_fields( $fields );
		$this->load_defaults( $defaults );
	}


	/**
	 * @param array $fields
	 *
	 * @return bool true on success
	 */
	public function load_fields( array $fields ) {

		$this->fields = $fields;

		return true;
	}


	/**
	 * @param array $defaults
	 *
	 * @return bool true on success
	 */
	public function load_defaults( array $defaults ) {

		$this->defaults = $defaults;

		return true;
	}
}
libs/better-framework/phpcs.xml.dist000064400000001011151214002370013542 0ustar00<?xml version="1.0"?>
<ruleset name="Version Check">
    <description>Version Compatibility Check</description>

    <!-- Run against the PHPCompatibility ruleset -->
    <rule ref="PHPCompatibility"/>

    <!-- Check for cross-version support for PHP 5.6 and higher. -->
    <config name="testVersion" value="5.6-"/>

    <exclude-pattern>*\.css</exclude-pattern>
    <exclude-pattern>*\.js</exclude-pattern>

    <exclude-pattern>*/vendor/*</exclude-pattern>
    <exclude-pattern>*/tests/*</exclude-pattern>
</ruleset>
libs/better-framework/user-metabox/class-bf-user-metabox-front-end-generator.php000064400000015230151214002370024056 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * User Metabox Fields Generator
 */
class BF_User_Metabox_Front_End_Generator extends BF_Admin_Fields {


	/**
	 * Constructor Function
	 *
	 * @param array  $items  Panel All Options
	 * @param string $id     Panel ID
	 * @param array  $values Panel Saved Values
	 *
	 * @since  1.4
	 * @access public
	 */
	public function __construct( array &$items, &$id, &$values = array() ) {

		// Parent Constructor
		parent::__construct( array(
			'templates_dir' => BF_PATH . 'metabox/templates/'
		) );

		$this->items  = $items;
		$this->id     = $id;
		$this->values = $values;
	}


	/**
	 * Used for creating input name
	 *
	 * @since 1.4
	 *
	 * @param $options
	 *
	 * @return string
	 */
	public function input_name( &$options ) {

		$id   = isset( $options['id'] ) ? $options['id'] : '';
		$type = isset( $options['type'] ) ? $options['type'] : '';

		switch ( $type ) {

			default:
				return "{$id}";
				break;

		}

	}


	/**
	 *  Metabox panel generator
	 *
	 * @since 1.4
	 */
	public function callback( $is_ajax = false ) {

		$skip_ajax_fields      = ! $is_ajax;
		$this->items['fields'] = BF_User_Metabox_Core::get_metabox_fields( $this->id );
		$metabox_config        = BF_User_Metabox_Core::get_metabox_config( $this->id );
		$items_has_tab         = ! $is_ajax && $this->has_tab();
		$has_tab               = false;

		if ( ! $is_ajax ) {
			$wrapper = Better_Framework::html()->add( 'div' )->class( 'bf-user-meta-wrap bf-metabox-wrap bf-clearfix' )->data( 'id', $this->id );

			// Better Option Title
			$wrapper->text(
				Better_Framework::html()->add( 'div' )->class( 'bf-user-metabox-title' )->text(
					Better_Framework::html()->add( 'h3' )->text( $metabox_config['title'] )
				)
			);

			// Add Class For Post Format Filter
			if ( isset( $metabox_config['post_format'] ) ) {
				$wrapper->data( 'bf_pf_filter', implode( ',', $metabox_config['post_format'] ) );
			}
		}

		$container = Better_Framework::html()->add( 'div' );
		if ( ! $is_ajax ) {
			$container = $container->class( 'bf-metabox-container' );
		}

		$tab_counter = 0;

		$group_counter = 0;

		if ( $items_has_tab && ! $is_ajax ) {
			$container->class( 'bf-with-tabs' );
			$tabs_container = Better_Framework::html()->add( 'div' )->class( 'bf-metabox-tabs' );
			$tabs_container->text( $this->get_tabs() );
			$wrapper->text( $tabs_container->display() );
		}

		if ( isset( $this->items['panel-id'] ) ) {
			$std_id = Better_Framework::options()->get_panel_std_id( $this->items['panel-id'] );
		} else {
			$std_id = 'std';
		}

		foreach ( $this->items['fields'] as $field ) {

			$field['input_name'] = $this->input_name( $field );

			$field['value'] = isset( $field['id'] ) && isset( $this->values[ $field['id'] ] ) ? $this->values[ $field['id'] ] : null;

			if ( is_null( $field['value'] ) && isset( $field[ $std_id ] ) ) {
				$field['value'] = $field[ $std_id ];
			} elseif ( is_null( $field['value'] ) && isset( $field['std'] ) ) {
				$field['value'] = $field['std'];
			}

			if ( $skip_ajax_fields && ! empty( $field['ajax-tab-field'] ) ) {  // Backward compatibility
				continue;
			}

			if ( $skip_ajax_fields && ! empty( $field['ajax-section-field'] ) ) {
				continue;
			}


			if ( $field['type'] == 'repeater' ) {
				$field['clone-name-format'] = 'bf-metabox-option[$1][$2][$3][$4]';
				$field['metabox-id']        = $this->id;
				$field['metabox-field']     = true;
			}

			if ( $field['type'] == 'tab' || $field['type'] == 'subtab' ) {

				// close tag for latest group in tab
				if ( $group_counter != 0 ) {
					$group_counter = 0;
					$container->text( $this->get_fields_group_close( $field ) );
				}

				$is_subtab = $field['type'] == 'subtab';

				if ( $tab_counter != 0 ) {
					$container->text( '</div><!-- /Section -->' );
				}

				if ( $is_subtab ) {
					$container->text( "\n\n<!-- Section -->\n<div class='group subtab-group' id='bf-metabox-{$this->id}-{$field["id"]}'>\n" );
				} else {
					$container->text( "\n\n<!-- Section -->\n<div class='group' id='bf-metabox-{$this->id}-{$field["id"]}'>\n" );
				}
				$has_tab = true;
				$tab_counter ++;
				continue;
			}

			if ( $field['type'] == 'group_close' ) {

				// close tag for latest group in tab
				if ( $group_counter != 0 ) {
					$group_counter = 0;
					$container->text( $this->get_fields_group_close( $field ) );
				}
				continue;
			}

			if ( $field['type'] == 'group' ) {

				// close tag for latest group in tab
				if ( $group_counter != 0 ) {
					$group_counter = 0;
					$container->text( $this->get_fields_group_close( $field ) );
				}

				$container->text( $this->get_fields_group_start( $field ) );

				$group_counter ++;
			}


			if ( ! in_array( $field['type'], $this->supported_fields ) ) {
				continue;
			}

			// Filter Each Field For Post Formats!
			if ( isset( $field['post_format'] ) ) {

				if ( is_array( $field['post_format'] ) ) {
					$field_post_formats = implode( ',', $field['post_format'] );
				} else {
					$field_post_formats = $field['post_format'];
				}
				$container->text( "<div class='bf-field-post-format-filter' data-bf_pf_filter='{$field_post_formats}'>" );
			}

			$container->text(
				$this->section(
					call_user_func(
						array( $this, $field['type'] ),
						$field
					),
					$field
				)
			);

			// End Post Format Filter Wrapper
			if ( isset( $field['post_format'] ) ) {

				$container->text( "</div>" );
			}
		}

		// close tag for latest group in tab
		if ( $group_counter != 0 ) {
			$container->text( $this->get_fields_group_close( $field ) );
		}

		// last sub tab closing
		if ( $has_tab ) {
			$container->text( "</div><!-- /Section -->" );
		}

		if ( $is_ajax ) {
			echo $container->display();
		} else {
			$wrapper->text( $container->display() );
			echo $wrapper; // escaped before
		}

	} // callback
}libs/better-framework/user-metabox/class-bf-user-metabox-core.php000064400000026460151214002370021135 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// Prevent Direct Access
defined( 'ABSPATH' ) or die;


/**
 * This class handles all functionality of BetterFramework Users Meta box feature for creating, saving, editing
 *
 * @package    BetterFramework
 * @since      1.4
 */
class BF_User_Metabox_Core {


	/**
	 * Contains all metabox's
	 *
	 * @var array
	 */
	public static $metabox = array();


	/**
	 * Contains config for all metabox's
	 *
	 * @var array
	 */
	public static $config = array();


	/**
	 * Contains all fields
	 *
	 * @var array
	 */
	public static $fields = array();


	/**
	 * Contains all std
	 *
	 * @var array
	 */
	public static $std = array();


	/**
	 * Contains all css
	 *
	 * @var array
	 */
	public static $css = array();


	/**
	 * Initializes all metaboxes
	 */
	public static function init_metabox() {

		static $loaded;

		if ( $loaded ) {
			return;
		}

		self::$metabox = apply_filters( 'better-framework/user-metabox/add', array() );

	}


	/**
	 * loads and returns metabox config
	 *
	 * @param string $metabox_id
	 *
	 * @return array
	 */
	public static function get_metabox_config( $metabox_id = '' ) {

		if ( empty( $metabox_id ) ) {
			return array();
		}

		if ( isset( self::$config[ $metabox_id ] ) ) {
			return self::$config[ $metabox_id ];
		}

		return self::$config[ $metabox_id ] = apply_filters( 'better-framework/user-metabox/' . $metabox_id . '/config', array() );
	}


	/**
	 * loads and returns metabox std values
	 *
	 * @param string $metabox_id
	 *
	 * @return array
	 */
	public static function get_metabox_std( $metabox_id = '' ) {

		if ( empty( $metabox_id ) || ! isset( self::$metabox[ $metabox_id ] ) ) {
			return array( 'asdsd' );
		}

		if ( isset( self::$std[ $metabox_id ] ) ) {
			return self::$std[ $metabox_id ];
		}

		return self::$std[ $metabox_id ] = apply_filters( 'better-framework/user-metabox/' . $metabox_id . '/std', array() );
	}


	/**
	 * loads and returns metabox std values
	 *
	 * @param string $metabox_id
	 *
	 * @return array
	 */
	public static function get_metabox_fields( $metabox_id = '' ) {

		if ( empty( $metabox_id ) || ! isset( self::$metabox[ $metabox_id ] ) ) {
			return array();
		}

		if ( isset( self::$fields[ $metabox_id ] ) ) {
			return self::$fields[ $metabox_id ];
		}

		return self::$fields[ $metabox_id ] = apply_filters( 'better-framework/user-metabox/' . $metabox_id . '/fields', array() );
	}


	/**
	 * loads and returns metabox css
	 *
	 * @param string $metabox_id
	 *
	 * @return array
	 */
	public static function get_metabox_css( $metabox_id = '' ) {

		if ( empty( $metabox_id ) || ! isset( self::$metabox[ $metabox_id ] ) ) {
			return array();
		}

		if ( isset( self::$css[ $metabox_id ] ) ) {
			return self::$css[ $metabox_id ];
		}

		return self::$css[ $metabox_id ] = apply_filters( 'better-framework/user-metabox/' . $metabox_id . '/css', array() );
	}


	/**
	 * Used to add action for constructing the meta box
	 *
	 * @since     1.4
	 * @access    public
	 */
	public function __construct() {

		self::init_metabox();

		// Add options form
		add_action( 'show_user_profile', array( $this, 'add_meta_boxes' ) );
		add_action( 'edit_user_profile', array( $this, 'add_meta_boxes' ) );

		add_action( 'edit_user_profile_update', array( $this, 'save' ), 1 );
		add_action( 'personal_options_update', array( $this, 'save' ), 1 );

		/**
		 * Action to handle ajax user metabox tabs
		 */
		add_action( 'better-framework/user-metabox/ajax-tab', array( $this, 'ajax_tab' ), 10, 3 );
	}


	/**
	 * Used for retrieve meta data values
	 *
	 * @param   string $id meta box id
	 * @param          $user
	 *
	 * @since    1.4
	 * @return  array
	 * @access   public
	 */
	public function get_full_meta_data( $id = '', $user ) {

		global $pagenow;

		$output = array();

		if ( isset( self::$metabox[ $id ]['panel-id'] ) ) {
			$std_id = Better_Framework::options()->get_panel_std_id( self::$metabox[ $id ]['panel-id'] );
		} else {
			$std_id = 'std';
		}

		$metabox_std = self::get_metabox_std( $id );

		if ( $pagenow == 'post-new.php' ) {

			if ( ! empty( $metabox_std ) ) {

				foreach ( (array) $metabox_std as $field_id => $field ) {

					if ( isset( $field[ $std_id ] ) ) {
						$output[ $field_id ] = $field[ $std_id ];
					} elseif ( isset( $field['std'] ) ) {
						$output[ $field_id ] = $field['std'];
					}
				}

			}

			return $output;
		}

		$meta = get_user_meta( $user->ID );

		foreach ( (array) $metabox_std as $field_id => $field ) {

			if ( isset( $meta[ $field_id ] ) ) {

				if ( is_serialized( $meta[ $field_id ][0] ) ) {
					$output[ $field_id ] = unserialize( $meta[ $field_id ][0] );
				} else {
					$output[ $field_id ] = $meta[ $field_id ][0];
				}

			} else {

				if ( isset( $field[ $std_id ] ) ) {
					$output[ $field_id ] = $field[ $std_id ];
				} elseif ( isset( $field['std'] ) ) {
					$output[ $field_id ] = $field['std'];
				}
			}

		}

		return $output;
	}


	/**
	 * Deprecated: Use bf_get_user_meta
	 *
	 * Used for finding user meta field value.
	 *
	 * @since   1.4
	 *
	 * @param $field_key    string              User field ID
	 * @param $user         string|WP_User      User ID or object
	 *
	 * @return mixed
	 */
	public function get_meta( $field_key, $user ) {

		return bf_get_user_meta( $field_key, $user );
	}


	/**
	 * Callback: Used for creating meta boxes
	 *
	 * Action: show_user_profile
	 * Action: edit_user_profile
	 *
	 * @since   1.4
	 * @access  public
	 *
	 * @param   $user   string|WP_User      User ID or object
	 */
	public function add_meta_boxes( $user ) {

		if ( ! class_exists( 'BF_User_Metabox_Front_End_Generator' ) ) {
			require BF_PATH . 'user-metabox/class-bf-user-metabox-front-end-generator.php';
		}

		foreach ( (array) self::$metabox as $metabox_id => $metabox ) {

			$metabox_value = $this->get_full_meta_data( $metabox_id, $user );

			$metabox_config = self::get_metabox_config( $metabox_id );

			if ( empty( $metabox_config['title'] ) ) {
				$metabox_config['title'] = __( 'Better User Options', 'better-studio' );
			}

			$front_end = new BF_User_Metabox_Front_End_Generator( $metabox_config, $metabox_id, $metabox_value );

			$front_end->callback();
		}

	} // add


	/**
	 * Updates user meta in safely
	 *
	 * @param   string|WP_User $user  User ID or object
	 * @param   string         $key   User meta key name
	 * @param   string         $value User meta value
	 *
	 * @static
	 * @since   1.4
	 * @return  bool
	 */
	public static function add_meta( $user, $key, $value ) {

		if ( ! is_object( $user ) ) {
			$user = get_user_by( 'id', $user );
		}

		$old_value = get_user_meta( $user->ID, $key, true );

		if ( $old_value === false ) {
			return add_user_meta( $user->ID, $key, $value );
		} else {
			if ( $old_value === $value ) {
				return true;
			} else {
				delete_user_meta( $user->ID, $key );

				return add_user_meta( $user->ID, $key, $value );
			}
		}

	}


	/**
	 * Callback: Save user meta box values
	 *
	 * Action: edit_user_profile_update
	 * Action: personal_options_update
	 *
	 * @param   int $user_id
	 *
	 * @static
	 * @return  mixed
	 * @since   1.4
	 */
	public function save( $user_id ) {

		if ( ! current_user_can( 'edit_user', $user_id ) ) {
			return false;
		}

		// Iterate all meta boxes
		foreach ( (array) self::$metabox as $metabox_id => $metabox ) {

			if ( isset( $metabox['panel-id'] ) ) {
				$std_id = Better_Framework::options()->get_panel_std_id( $metabox['panel-id'] );
			} else {
				$std_id = 'std';
			}

			$metabox_std = self::get_metabox_std( $metabox_id );

			// Iterate all fields
			foreach ( (array) $metabox_std as $field_id => $field ) {

				if ( ! isset( $_POST[ $field_id ] ) ) {
					continue;
				}

				// Save value if save-std is true or not defined
				if ( ! isset( $field['save-std'] ) || $field['save-std'] == true ) {

					self::add_meta( $user_id, $field_id, $_POST[ $field_id ] );

				} // Don't Save Default Value
				elseif ( isset( $field['save-std'] ) ) {

					// If style std defined then save it
					if ( isset( $field[ $std_id ] ) ) {

						if ( $field[ $std_id ] != $_POST[ $field_id ] ) {
							self::add_meta( $user_id, $field_id, $_POST[ $field_id ] );
						} else {
							delete_user_meta( $user_id, $field_id );
						}

					} // If style std defined then save it
					elseif ( isset( $field['std'] ) ) {

						if ( $field['std'] != $_POST[ $field_id ] ) {
							self::add_meta( $user_id, $field_id, $_POST[ $field_id ] );
						} else {
							delete_user_meta( $user_id, $field_id );
						}

					}

				} // Delete Custom field
				else {
					delete_user_meta( $user_id, $field_id );
				}

			}

		}

	} // save


	/**
	 *
	 *
	 * @param string     $tab_id
	 * @param string     $metabox_id
	 * @param int|string $user_id
	 */
	public function ajax_tab( $tab_id, $metabox_id, $user_id ) {

		$user           = get_user_to_edit( $user_id );
		$fields         = BF_User_Metabox_Core::get_metabox_fields( $metabox_id );
		$metabox_value  = array();
		$metabox_config = self::get_metabox_config( $metabox_id );
		$use_generator  = true;


		if ( empty( $fields[ $tab_id ]['ajax-section-handler'] ) ) {

			$metabox_value = $this->get_full_meta_data( $metabox_id, $user );

			// Modify fields array
			foreach ( $fields as $idx => $field ) {

				// Backward compatibility
				if ( isset( $field['ajax-tab-field'] ) ) {
					$field['ajax-section-field'] = $field['ajax-tab-field'];
				}

				if ( empty( $field['ajax-section-field'] ) || $field['ajax-section-field'] !== $tab_id ) {
					unset( $fields[ $idx ] );
				}
			}

		} else {

			$parent_field = $fields[ $tab_id ];

			$args = isset( $parent_field['ajax-section-handler-args'] ) ? $parent_field['ajax-section-handler-args'] : array();
			$args = array_merge( $args, compact( 'metabox_id', 'tab_id' ) );

			if (
				! isset( $parent_field['ajax-section-handler-type'] ) ||
				$parent_field['ajax-section-handler-type'] === 'field-generator'
			) {

				$fields = call_user_func( $parent_field['ajax-section-handler'], $args );

				foreach ( $fields as $key => $field ) {

					$metabox_value[ $field['id'] ] = bf_get_user_meta( $field['id'], $user_id );
				}
			} else {

				$use_generator = false;
				$out           = call_user_func( $parent_field['ajax-section-handler'], $args );

			}
		}

		if ( $use_generator ) {

			if ( ! class_exists( 'BF_User_Metabox_Front_End_Generator' ) ) {
				require BF_PATH . 'user-metabox/class-bf-user-metabox-front-end-generator.php';
			}
			$front_end = new BF_User_Metabox_Front_End_Generator( $metabox_config, $metabox_id, $metabox_value );

			BF_User_Metabox_Core::$fields[ $metabox_id ] = $fields;

			ob_start();
			// print output
			echo $front_end->callback( true );  // escaped before
			$out = ob_get_clean();
		}

		wp_send_json( array( 'out' => $out, 'tab_id' => $tab_id ) );
	}
}
libs/better-framework/user-metabox/functions.php000064400000006025151214002370016107 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_get_user_meta' ) ) {
	/**
	 * Used for finding user meta field value.
	 *
	 * @since   2.0
	 *
	 * @param   string         $field_key     User field ID
	 * @param   string|WP_User $user          User ID or object
	 * @param   null           $force_default Default value (Optional)
	 *
	 * @return mixed
	 */
	function bf_get_user_meta( $field_key, $user = null, $force_default = null ) {

		if ( is_null( $user ) ) {

			// Get current post author id
			if ( is_singular() ) {
				$user = get_the_author_meta( 'ID' );
			} // Get current archive user
			elseif ( is_author() ) {
				$user = bf_get_author_archive_user();
			} // Return default value
			else {
				return $force_default;
			}
		}

		// Get user id from object
		if ( is_object( $user ) ) {
			$user = $user->ID;
		}

		// get value if saved in DB
		$value = get_user_meta( $user, $field_key, true );

		if ( $value !== false ) {
			return $value;
		} // Or return force default value
		elseif ( ! is_null( $force_default ) ) {
			return $force_default;
		}

		// initialize base BF metabox
		if ( ! class_exists( 'BF_User_Metabox_Core' ) ) {
			Better_Framework()->user_meta();
		}

		// Iterate all meta boxes
		foreach ( BF_User_Metabox_Core::$metabox as $metabox_id => $metabox ) {

			// if this meta box connected to a panel for style field
			if ( isset( $metabox['panel-id'] ) ) {
				$std_id = Better_Framework()->options()->get_panel_std_id( $metabox['panel-id'] );
			} else {
				$std_id = 'std';
			}

			$metabox_std = BF_User_Metabox_Core::get_metabox_std( $metabox_id );

			// retrieve default value
			if ( isset( $metabox_std[ $field_key ][ $std_id ] ) ) {
				return $metabox_std[ $field_key ][ $std_id ];
			} elseif ( isset( $metabox_std[ $field_key ]['std'] ) ) {
				return $metabox_std[ $field_key ]['std'];
			}

		}

		return false;
	}
}


if ( ! function_exists( 'bf_echo_user_meta' ) ) {
	/**
	 * Used to echo user meta field value.
	 *
	 * @since   2.0
	 *
	 * @param   string         $field_key     User field ID
	 * @param   string|WP_User $user          User ID or object
	 * @param   null           $force_default Default value (Optional)
	 *
	 * @return mixed
	 */
	function bf_echo_user_meta( $field_key, $user = null, $force_default = null ) {

		echo bf_get_user_meta( $field_key, $user, $force_default );
	}
}

libs/better-framework/user-metabox/index.php000064400000000012151214002370015174 0ustar00<?php
die;libs/better-framework/user-metabox/templates/default.php000064400000005221151214002370017516 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes = $classes['section'];

$heading_classes  = $classes['heading'];
$controls_classes = $classes['controls'];
$explain_classes  = $classes['explain'];

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];

if ( empty( $options['desc'] ) ) {
	$section_classes .= ' no-desc ';
}
?>
<div class="bf-section-container bf-metabox bf-clearfix">
	<div class="<?php echo esc_attr( $section_classes ); ?> bf-clearfix"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>">

		<div class="<?php echo esc_attr( $heading_classes ); ?> bf-clearfix">
			<h3><label><?php echo esc_html( $options['name'] ); ?></label></h3>
		</div>

		<div class="<?php echo esc_attr( $controls_classes ); ?> bf-clearfix">
			<?php echo $input; // escaped before ?>
		</div>

		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div
					class="<?php echo esc_attr( $explain_classes ); ?> bf-clearfix"><?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?></div>
		<?php } ?>

	</div>
</div>libs/better-framework/user-metabox/templates/hr.php000064400000001600151214002370016500 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div class="bf-section-container bf-clearfix">
	<div class="bf-section-hr bf-clearfix">
		<?php echo $input; // escaped before ?>
	</div>
</div>libs/better-framework/user-metabox/templates/heading.php000064400000002405151214002370017472 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div class="bf-section-container bf-metabox bf-clearfix">
	<div class="bf-section-heading bf-clearfix" data-id="<?php echo esc_attr( $options['id'] ); ?>"
	     id="<?php echo esc_attr( $options['id'] ); ?>">
		<div class="bf-section-heading-title bf-clearfix">
			<h3><?php echo esc_html( $options['name'] ); ?></h3>
		</div>
		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div
					class="bf-section-heading-desc bf-clearfix"><?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?></div>
		<?php } ?>
	</div>
</div>libs/better-framework/product-updater/class-bf-product-upgrader-skin.php000064400000002726151214002370022533 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * override parent method to discard printed outputs
 *
 * Class BF_Product_Upgrader_Skin
 */
class BF_Product_Upgrader_Skin {

	public function header() {
	}


	public function footer() {
	}


	public function feedback( $string ) {
	}


	public function before() {
	}


	public function after() {
	}


	public function decrement_update_count( $type ) {
	}


	public function set_upgrader( &$upgrader ) {
	}


	public function add_strings() {
	}


	public function set_result( $result ) {
	}


	public function request_filesystem_credentials( $error = false, $context = false, $allow_relaxed_file_ownership = false ) {
	}


	public function error( $errors ) {
	}


	public function bulk_header() {
	}


	public function bulk_footer() {
	}
}libs/better-framework/product-updater/init.php000064400000002025151214002370015545 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


define( 'BS_PRODUCT_UPDATE_URI', trailingslashit( BF_URI . 'product-updater/' ) );
define( 'BS_PRODUCT_UPDATE_PATH', trailingslashit( BF_PATH . 'product-updater/' ) );

include_once BS_PRODUCT_UPDATE_PATH . 'class-bf-product-updater.php';
include_once BS_PRODUCT_UPDATE_PATH . 'functions.php';

libs/better-framework/product-updater/functions.php000064400000001633151214002370016616 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_remove_reject_unsafe_urls' ) ) {
	function bf_remove_reject_unsafe_urls( $args ) {

		$args['reject_unsafe_urls'] = false;

		return $args;
	}
}
libs/better-framework/product-updater/index.php000064400000000032151214002370015705 0ustar00<?php
// Silent is golden!libs/better-framework/product-updater/class-bf-product-updater.php000064400000027023151214002370021421 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


BF_Product_Updater::Run();


class BF_Product_Updater {

	public static $plugins_file = array();


	/**
	 * Initialize
	 */
	public static function Run() {

		global $bs_product_updater;

		if ( $bs_product_updater === false ) {
			return;
		}

		if ( ! $bs_product_updater instanceof self ) {
			$bs_product_updater = new self();
			$bs_product_updater->init();
		}

		return $bs_product_updater;
	}


	public function init() {

		add_action( 'wp_update_themes', array( $this, 'update_product_schedule' ) );
		add_action( 'load-themes.php', array( $this, 'update_product_schedule' ) );
		add_action( 'load-update.php', array( $this, 'update_product_schedule' ) );
		add_action( 'load-update-core.php', array( $this, 'update_product_schedule' ) );
		add_action( 'upgrader_process_complete', array( $this, 'update_product_schedule' ) );

		add_filter( 'site_transient_update_themes', array( $this, 'fetch_theme_download_link' ) );
		add_filter( 'upgrader_source_selection', array( $this, 'fix_source_directory' ), 30, 4 );

		$this->plugin_compatibility();
	}


	function fetch_theme_download_link( $value ) {

		global $pagenow;

		if ( isset( $_REQUEST['action'] ) &&
		     in_array( $pagenow, array( 'admin-ajax.php', 'update.php' ) ) &&
		     in_array( $_REQUEST['action'], array(
			     'upgrade-theme',
			     'update-selected-themes',
			     'update-theme',
		     ) )
		) {
			if ( ! empty( $value->response ) && is_array( $value->response ) ) {

				add_filter( 'http_request_args', 'bf_remove_reject_unsafe_urls', 99 );

				foreach ( $value->response as $idx => $product ) {
					if ( isset( $product['package'] ) && preg_match( '/^FETCH_FROM_BETTER_STUDIO\/(.+)/i', $product['package'], $matched ) ) {
						$r            = &$value->response[ $idx ];
						$dl_link      = $this->get_product_download_link( array_pop( $matched ), $product['slug'] );
						$r['package'] = $dl_link;
					}
				}

				set_site_transient( 'update_themes', $value );
				remove_filter( 'site_transient_update_themes', array( $this, 'fetch_theme_download_link' ) );
			}
		}

		return $value;
	}


	protected function get_product_download_link( $item_id ) {

		if ( $purchase_info = get_option( 'bf-product-updater-items' ) ) {
			if ( isset( $purchase_info[ $item_id ] ) ) {
				$purchase_code = &$purchase_info[ $item_id ];

				$product_data = $this->api_request( 'download-latest-version', array(), compact( 'item_id', 'purchase_code' ) );
				if ( ! empty( $product_data->success ) && ! empty( $product_data->download_link ) ) {
					return $product_data->download_link;
				}
			}
		}
	}


	protected function get_products_info() {

		$results = array();
		$info    = apply_filters( 'better-framework/product-updater/product-info', array() );

		if ( $info ) {

			$cache_data = array();
			foreach ( $info as $d ) {

				if ( isset( $d['item_id'] ) && isset( $d['purchase_code'] ) ) {
					$cache_data[ $d['item_id'] ] = $d['purchase_code'];
				}

				$results[ $d['item_id'] ] = $d;
			}
			update_option( 'bf-product-updater-items', $cache_data, 'no' );
		}

		return $results;
	}


	public function update_product_schedule() {

		static $loaded = false;
		remove_action( 'wp_update_themes', array( $this, 'update_product_schedule' ) );
		if ( $loaded ) {
			return;
		}
		$items_info = $this->get_products_info();
		if ( ! $items_info ) {
			return;
		}

		$status = $this->check_for_update( $items_info, true );

		if ( ! ( $plugins_update = get_site_transient( 'update_plugins' ) ) ) {
			$plugins_update = new stdClass();
		}
		if ( ! ( $themes_update = get_site_transient( 'update_themes' ) ) ) {
			$themes_update = new stdClass();
		}

		if ( ! empty( $status->plugins ) && is_array( $status->plugins ) ) {
			if ( empty( $plugins_update->response ) ) {
				$plugins_update->response = array();
			}

			$r = &$plugins_update->response;
			foreach ( $status->plugins as $plugin_data ) {
				$p_file = self::plugin_slug_to_file_path( $plugin_data['slug'] );

				$r[ $p_file ]          = (object) $plugin_data;
				$r[ $p_file ]->plugin  = $p_file;
				$r[ $p_file ]->package = 'FETCH_FROM_BETTER_STUDIO/' . $plugin_data['slug'];
			}

			set_site_transient( 'update_plugins', $plugins_update );
		}

		if ( ! empty( $status->themes ) && is_array( $status->themes ) ) {
			if ( empty( $themes_update->response ) ) {
				$themes_update->response = array();
			}

			$r = &$themes_update->response;
			foreach ( $status->themes as $item_id => $theme_data ) {

				$slug = &$theme_data['slug'];

				$r[ $slug ] = bf_merge_args( $theme_data, array(
					'package' => 'FETCH_FROM_BETTER_STUDIO/' . $item_id,
					//todo link to readme file
					'url'     => 'http://betterstudio.com/'
				) );
			}

			set_site_transient( 'update_themes', $themes_update );
		}

		$loaded = true;
	}


	/**
	 * Check group of items update
	 *
	 * @param array $items
	 * @param bool  $force
	 *
	 * @return bool|object object on success
	 */
	protected function check_for_update( $items, $force = false ) {

		global $wp_version, $pagenow;

		// Don't check update while updating another item!

		if (
			( isset( $_REQUEST['action'] ) && 'do-theme-upgrade' === $_REQUEST['action'] )
			||
			(
				isset( $_REQUEST['action'] ) &&
				in_array( $pagenow, array( 'admin-ajax.php', 'update.php' ) ) &&
				in_array( $_REQUEST['action'], array(
					'upgrade-theme',
					'update-selected-themes',
					'update-theme',
				) )
			)
		) {
			return false;
		}

		if ( empty( $items ) || ! is_array( $items ) ) {
			return false;
		}

		include ABSPATH . WPINC . '/version.php';

		$update_status               = new stdClass();
		$update_status->last_checked = time();
		$update_status->themes       = array();
		$update_status->plugins      = array();
		$update_status->misc         = array();

		if ( ! $force ) {
			$prev_status = get_option( 'bf-product-items-status' );

			if ( ! is_object( $prev_status ) ) {
				$prev_status               = new stdClass();
				$prev_status->last_checked = time();
				$skip_update               = false;
			} else {
				$skip_update = $this->check_update_duration > ( time() - $prev_status->last_checked );
			}

			if ( $skip_update ) {

				return $prev_status;
			}
		}

		/**
		 * check bundled plugins update
		 */

		$check_update = $this->api_request( 'check-products-update', compact( 'items' ) );

		if ( ! empty( $check_update->success ) && ! empty( $check_update->response ) ) {
			foreach ( $check_update->response as $item_id => $update_info ) {

				$ver       = &$update_info->version;
				$type      = &$update_info->type;
				$slug      = &$update_info->slug;
				$readme    = $update_info->readme ? $update_info->readme : false;
				$changelog = isset( $update_info->changelog ) ? $update_info->changelog : false;

				// Set active theme folder name instead of original folder name
				//  to handle changed folder names
				if ( ! empty( $items[ $item_id ]['active_theme'] ) ) {
					$slug = get_template();
				}

				if ( $ver !== 'latest' ) {

					$info_array = array(
						'slug'        => $slug,
						'new_version' => $ver,
						'url'         => $readme,
						'changelog'   => $changelog,
					);

					if ( $type === 'theme' ) {
						$update_status->themes[ $item_id ] = $info_array;
					} elseif ( $type === 'plugin' ) {
						$update_status->plugins[ $item_id ] = $info_array;
					} else {
						$update_status->misc[ $item_id ] = $info_array;
					}
				}
			}
		}

		do_action( 'better-framework/product-pages/product-update-check', $update_status, $check_update );

		update_option( 'bf-product-items-status', $update_status, 'no' );

		return $update_status;
	}


	/**
	 * Get plugin file path by plugin slug
	 *
	 * Ex: plugin_slug_to_file_path('js_composer') ==> js_composer/js_composer.php
	 *
	 * @param string $slug plugin slug (plugin directory)
	 *
	 * @return bool|string plugin file path on success or false on error
	 */
	public static function plugin_slug_to_file_path( $slug ) {

		if ( ! is_array( self::$plugins_file ) ) {

			self::$plugins_file = array();

			foreach ( get_plugins() as $file => $info ) {

				self::$plugins_file[ dirname( $file ) ] = $file;
			}
		}

		if ( isset( self::$plugins_file[ $slug ] ) ) {
			return self::$plugins_file[ $slug ];
		}

		return false;
	} // plugin_slug_to_file_path


	/**
	 * handle api request
	 *
	 * @see \BetterFramework_Oculus::request
	 *
	 * @param string $action
	 * @param array  $data
	 * @param array  $auth
	 * @param bool   $use_wp_error
	 *
	 * @return array|bool|object|WP_Error
	 */
	protected function api_request( $action, $data = array(), $auth = array(), $use_wp_error = false ) {

		if ( ! class_exists( 'BetterFramework_Oculus' ) ) {
			return false;
		}

		return BetterFramework_Oculus::request( $action, compact( 'auth', 'data', 'use_wp_error' ) );
	} //api_request


	/**
	 * Rename downloaded package folder to user-defined directory name
	 * for support renamed product folders while upgrading process.
	 *
	 * @param string      $source        File source location.
	 * @param string      $remote_source Remote file source location.
	 * @param WP_Upgrader $WP_Upgrader   WP_Upgrader instance. unused
	 * @param array       $hook_extra    Extra arguments passed to hooked filters.
	 *
	 * @hooked upgrader_source_selection
	 *
	 * @since  3.7.0
	 * @return string
	 */
	public function fix_source_directory( $source, $remote_source, $WP_Upgrader, $hook_extra ) {

		if ( ! $source ) {
			return $source;
		}

		if ( ! empty( $hook_extra['theme'] ) ) {

			$product_type        = 'theme';
			$current_folder_name = $hook_extra['theme'];

		} elseif ( ! empty( $hook_extra['plugin'] ) ) {

			$product_type        = 'plugin';
			$current_folder_name = $hook_extra['plugin'];

		} else {

			return $source;
		}

		$check = array(
			'product_type'   => $product_type,
			'product_folder' => basename( $source ),
		);

		$original_folder_name = &$check['product_folder'];

		// Dose user changed original product folder name?

		if ( $current_folder_name === $original_folder_name ) {

			return $source;
		}

		/// Is this a betterstudio product?
		$is_better_product = false;

		foreach ( apply_filters( 'better-framework/product-updater/product-info', array() ) as $info ) {

			if ( ! array_diff_assoc( $check, $info ) ) {

				$is_better_product = true;
				break;
			}
		}

		if ( ! $is_better_product ) {
			// Do not touch none betterstudio themes or plugins
			return $source;
		}

		$file_system   = bf_file_system_instance();
		$renamed_path  = $remote_source . '/' . $current_folder_name;
		$original_path = $remote_source . '/' . $original_folder_name;

		$file_system->delete( $renamed_path, true );

		if ( $file_system->move( $original_path, $renamed_path ) ) {

			return $renamed_path;
		}

		return $source;
	}


	/**
	 * Fix third-party plugin conflicts with our product updater.
	 */
	public function plugin_compatibility() {

		// Disable licensed visual composer update feature
		if ( function_exists( 'vc_manager' ) ) {

			vc_manager()->disableUpdater();
		}
	}
}
libs/better-framework/metabox/class-bf-metabox-front-end-generator.php000064400000022627151214002370022136 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Metabox Fields Generator
 */
class BF_Metabox_Front_End_Generator extends BF_Admin_Fields {


	/**
	 * Constructor Function
	 *
	 * @param array $items  Panel All Options
	 * @param int   $id     Panel ID
	 * @param array $values Panel Saved Values
	 *
	 * @since  1.0
	 * @access public
	 */
	public function __construct( array &$items, &$id, &$values = array() ) {

		// Parent Constructor
		parent::__construct( array(
			'templates_dir' => BF_PATH . 'metabox/templates/'
		) );

		$this->items  = $items;
		$this->id     = $id;
		$this->values = $values;
	}


	/**
	 * Used for creating input name
	 *
	 * @param $options
	 *
	 * @return string
	 */
	public function input_name( &$options ) {

		$id   = isset( $options['id'] ) ? $options['id'] : '';
		$type = isset( $options['type'] ) ? $options['type'] : '';

		switch ( $type ) {

			case 'repeater' :
				return "bf-metabox-option[%s][%s][%d][%s]";
				break;

			case 'select':

				if ( isset( $options['multiple'] ) && $options['multiple'] ) {
					return "bf-metabox-option[{$this->id}][{$id}][]";
				} else {
					return "bf-metabox-option[{$this->id}][{$id}]";
				}

				break;

			default:
				return "bf-metabox-option[{$this->id}][{$id}]";
				break;

		}

	}


	/**
	 *  Metabox panel generator
	 *
	 * @param bool $is_ajax ignore ajax items
	 */
	public function callback( $is_ajax = false ) {

		$metabox_config = BF_Metabox_Core::get_metabox_config( $this->id );
		$items_has_tab  = $this->has_tab();
		$has_tab        = false;
		$has_wrapper    = $is_ajax !== true;

		if ( $has_wrapper ) {
			$wrapper = Better_Framework::html()->add( 'div' )->class( 'bf-metabox-wrap bf-clearfix' )->data( 'id', $this->id );
		}

		// Add Class For Post Format Filter
		if ( isset( $metabox_config['post_format'] ) && $has_wrapper ) {
			$wrapper->data( 'bf_pf_filter', implode( ',', $metabox_config['post_format'] ) );
		}
		$container = Better_Framework::html()->add( 'div' );
		if ( $is_ajax !== true ) {
			$container = $container->class( 'bf-metabox-container' );
		}

		$tab_counter = 0;

		$group_counter = array();

		if ( $items_has_tab && $is_ajax !== true ) {
			$container->class( 'bf-with-tabs' );
			$tabs_container = Better_Framework::html()->add( 'div' )->class( 'bf-metabox-tabs' );
			$tabs_container->text( $this->get_tabs() );
			if ( $has_wrapper ) {
				$wrapper->text( $tabs_container->display() );
			}
			Better_Framework()->assets_manager()->add_admin_css( '#bf_' . $this->id . ' .inside{margin: 0 !important; padding: 0 !important;}' );
		}

		if ( isset( $this->items['panel-id'] ) ) {
			$std_id = Better_Framework::options()->get_panel_std_id( $this->items['panel-id'] );
		} else {
			$std_id = 'std';
		}

		$metabox_fields = BF_Metabox_Core::get_metabox_fields( $this->id );

		$metabox_std = BF_Metabox_Core::get_metabox_std( $this->id );

		foreach ( $metabox_fields as $field_id => $field ) {

			if ( ! empty( $field['type'] ) && $field['type'] === 'id-holder' ) {
				continue;
			}

			if ( $is_ajax !== true && ! empty( $field['ajax-tab-field'] ) ) {  // Backward compatibility
				continue;
			}

			if ( $is_ajax !== true && ! empty( $field['ajax-section-field'] ) ) {
				continue;
			}

			$field['input_name'] = $this->input_name( $field );

			if ( $field['type'] === 'info' ) {
				if ( isset( $field['std'] ) ) {
					$field['value'] = $field['std'];
				} else {
					$field['value'] = '';
				}
			} else {
				$field['value'] = isset( $field['id'] ) && isset( $this->values[ $field['id'] ] ) ? $this->values[ $field['id'] ] : null;
			}

			if ( is_null( $field['value'] ) && isset( $metabox_std[ $field_id ][ $std_id ] ) ) {
				$field['value'] = $metabox_std[ $field_id ][ $std_id ];
			} elseif ( is_null( $field['value'] ) && isset( $metabox_std[ $field_id ]['std'] ) ) {
				$field['value'] = $metabox_std[ $field_id ]['std'];
			}

			if ( isset( $field['filter-field'] ) && $field['filter-field-value'] ) {

				// Get value if is available
				$filter_field_value = isset( $this->values[ $field['filter-field'] ] ) ? $this->values[ $field['filter-field'] ] : null;

				// is null means this is post create screen and filter field default value should be used for
				// default comparison
				if ( is_null( $filter_field_value ) ) {

					if ( isset( $metabox_std[ $field['filter-field'] ][ $std_id ] ) ) {
						$filter_field_value = $metabox_std[ $field['filter-field'] ][ $std_id ];
					} elseif ( isset( $metabox_std[ $field['filter-field'] ]['std'] ) ) {
						$filter_field_value = $metabox_std[ $field['filter-field'] ]['std'];
					} else {
						$filter_field_value = false;
					}

				}

				if ( $field['filter-field-value'] !== $filter_field_value ) {
					$field['section-css']['display'] = "none";
				}

			}

			if ( $field['type'] == 'repeater' ) {
				$field['clone-name-format'] = 'bf-metabox-option[$3][$4][$5][$6]';
				$field['metabox-id']        = $this->id;
				$field['metabox-field']     = true;
			}

			if ( $field['type'] == 'tab' || $field['type'] == 'subtab' ) {

				if ( $has_tab ) {

					// close all opened groups
					foreach ( array_reverse( $group_counter ) as $level_k => $level_v ) {

						if ( $level_v === 0 ) {
							continue;
						}

						for ( $i = 0; $i < $level_v; $i ++ ) {
							$container->text( $this->get_fields_group_close( $field ) );
						}

						$group_counter[ $level_k ] = 0;
					}
				}
				$is_subtab = $field['type'] == 'subtab';

				if ( $tab_counter != 0 ) {
					$container->text( '</div><!-- /Section -->' );
				}

				if ( $is_subtab ) {
					$container->text( "\n\n<!-- Section -->\n<div class='group subtab-group' id='bf-metabox-{$this->id}-{$field["id"]}'>\n" );
				} else {
					$container->text( "\n\n<!-- Section -->\n<div class='group' id='bf-metabox-{$this->id}-{$field["id"]}'>\n" );
				}
				$has_tab = true;
				$tab_counter ++;
				continue;
			}
			//
			// Close group
			//
			if ( $field['type'] == 'group_close' ) {

				if ( isset( $field['level'] ) && $field['level'] === 'all' ) {

					krsort( $group_counter );

					// close all opened groups
					foreach ( $group_counter as $level_k => $level_v ) {

						if ( $level_v === 0 ) {
							continue;
						}

						for ( $i = 0; $i < $level_v; $i ++ ) {
							$container->text( $this->get_fields_group_close( $field ) );
						}

						$group_counter[ $level_k ] = 0;
					}

				} else {

					krsort( $group_counter );

					// close last opened group
					foreach ( $group_counter as $level_k => $level_v ) {

						if ( ! $level_v ) {
							continue;
						}

						for ( $i = 0; $i < $level_v; $i ++ ) {
							$container->text( $this->get_fields_group_close( $field ) );
							$group_counter[ $level_k ] --;
							break;
						}

					}
				}


				continue;
			}

			//
			// Group
			// All nested groups and same level groups should be closed
			//
			if ( $field['type'] == 'group' ) {

				if ( ! isset( $field['level'] ) ) {
					$field['level'] = 0;
				}

				if ( ! isset( $group_counter[ $field['level'] ] ) ) {
					$group_counter[ $field['level'] ] = 0;
				}

				krsort( $group_counter );

				foreach ( $group_counter as $level_k => $level_v ) {

					if ( $level_k < $field['level'] ) {
						continue;
					}

					for ( $i = 0; $i < $level_v; $i ++ ) {
						$container->text( $this->get_fields_group_close( $field ) );
					}

					$group_counter[ $level_k ] = 0;
				}

				$container->text( $this->get_fields_group_start( $field ) );

				$group_counter[ $field['level'] ] ++;
			}


			if ( ! in_array( $field['type'], $this->supported_fields ) ) {
				continue;
			}

			// Filter Each Field For Post Formats!
			if ( isset( $field['post_format'] ) ) {

				if ( is_array( $field['post_format'] ) ) {
					$field_post_formats = implode( ',', $field['post_format'] );
				} else {
					$field_post_formats = $field['post_format'];
				}
				$container->text( "<div class='bf-field-post-format-filter' data-bf_pf_filter='{$field_post_formats}'>" );
			}

			$container->text(
				$this->section(
					call_user_func(
						array( $this, $field['type'] ),
						$field
					),
					$field
				)
			);

			// End Post Format Filter Wrapper
			if ( isset( $field['post_format'] ) ) {

				$container->text( "</div>" );
			}
		}

		// last sub tab closing
		if ( $has_tab ) {
			$container->text( "</div><!-- /Section -->" );
		}

		if ( $has_wrapper ) {
			$wrapper->text(
				$container->display()
			);
			echo $wrapper;  // escaped before
		} else {
			echo $container->display();
		}
	} // callback
}
libs/better-framework/metabox/class-bf-metabox-core.php000064400000034117151214002370017203 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// Prevent Direct Access
defined( 'ABSPATH' ) or die;


// initialize all metaboxe
BF_Metabox_Core::init_metabox();


/**
 * This class handles all functionality of BetterFramework Meta box feature for creating, saving, editing
 * and another functionality like filtering metaboxe's for post types, pages and etc
 *
 * @package    BetterFramework
 * @since      1.0
 */
class BF_Metabox_Core {

	/**
	 * Contains all metabox's
	 *
	 * @var array
	 */
	public static $metabox = array();


	/**
	 * Contains config for all metabox's
	 *
	 * @var array
	 */
	public static $config = array();


	/**
	 * Contains all fields
	 *
	 * @var array
	 */
	public static $fields = array();


	/**
	 * Contains all std
	 *
	 * @var array
	 */
	public static $std = array();


	/**
	 * Contains all css
	 *
	 * @var array
	 */
	public static $css = array();


	/**
	 * Initializes all metaboxes
	 */
	public static function init_metabox() {

		static $loaded;

		if ( $loaded ) {
			return;
		}

		self::$metabox = apply_filters( 'better-framework/metabox/add', array() );

	}


	/**
	 * loads and returns metabox config
	 *
	 * @param string $metabox_id
	 *
	 * @return array
	 */
	public static function get_metabox_config( $metabox_id = '' ) {

		if ( empty( $metabox_id ) ) {
			return array();
		}

		if ( isset( self::$config[ $metabox_id ] ) ) {
			return self::$config[ $metabox_id ];
		}

		return self::$config[ $metabox_id ] = apply_filters( 'better-framework/metabox/' . $metabox_id . '/config', array() );
	}


	/**
	 * loads and returns metabox std values
	 *
	 * @param string $metabox_id
	 *
	 * @return array
	 */
	public static function get_metabox_std( $metabox_id = '' ) {

		if ( empty( $metabox_id ) || ! isset( self::$metabox[ $metabox_id ] ) ) {
			return array();
		}

		if ( isset( self::$std[ $metabox_id ] ) ) {
			return self::$std[ $metabox_id ];
		}

		return self::$std[ $metabox_id ] = apply_filters( 'better-framework/metabox/' . $metabox_id . '/std', array() );
	}


	/**
	 * loads and returns metabox std values
	 *
	 * @param string $metabox_id
	 *
	 * @return array
	 */
	public static function get_metabox_fields( $metabox_id = '' ) {

		if ( empty( $metabox_id ) || ! isset( self::$metabox[ $metabox_id ] ) ) {
			return array();
		}

		if ( isset( self::$fields[ $metabox_id ] ) ) {
			return self::$fields[ $metabox_id ];
		}

		return self::$fields[ $metabox_id ] = apply_filters( 'better-framework/metabox/' . $metabox_id . '/fields', array() );
	}


	/**
	 * loads and returns metabox css
	 *
	 * @param string $metabox_id
	 *
	 * @return array
	 */
	public static function get_metabox_css( $metabox_id = '' ) {

		if ( empty( $metabox_id ) || ! isset( self::$metabox[ $metabox_id ] ) ) {
			return array();
		}

		if ( isset( self::$css[ $metabox_id ] ) ) {
			return self::$css[ $metabox_id ];
		}

		return self::$css[ $metabox_id ] = apply_filters( 'better-framework/metabox/' . $metabox_id . '/css', array() );
	}


	/**
	 * Used to add action for constructing the meta box
	 *
	 * @since     1.0
	 * @access    public
	 */
	public function __construct() {

		self::init_metabox();

		add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ) );

		add_action( 'pre_post_update', array( $this, 'save' ), 1 );

		add_action( 'better-framework/metabox/ajax-tab', array( $this, 'ajax_tab' ), 10, 3 );
	}


	/**
	 * Used for creating meta boxes
	 *
	 * Callback: add_meta_boxes action
	 *
	 * @since   1.0
	 * @access  public
	 */
	public function add_meta_boxes() {

		if ( ! class_exists( 'BF_Metabox_Front_End_Generator' ) ) {
			require BF_PATH . 'metabox/class-bf-metabox-front-end-generator.php';
		}

		foreach ( (array) self::$metabox as $metabox_id => $metabox ) {

			$metabox_config = self::get_metabox_config( $metabox_id );

			if ( empty( $metabox_config ) ) {
				continue;
			}

			if ( ! $this->can_output( $metabox_config ) ) {
				continue;
			}

			$metabox_config['fields'] = self::get_metabox_fields( $metabox_id );
			$metabox_value            = $this->get_meta_data( $metabox_id );
			$title                    = empty( $metabox_config['title'] ) ? '' : $metabox_config['title'];
			$generator                = new BF_Metabox_Front_End_Generator( $metabox_config, $metabox_id, $metabox_value );

			if ( is_array( $metabox_config['pages'] ) ) {

				foreach ( $metabox_config['pages'] as $page ) {
					add_meta_box(
						'bf_' . $metabox_id,
						$title,
						array( $generator, 'callback' ),
						$page,
						isset( $metabox_config['context'] ) ? $metabox_config['context'] : 'normal',
						isset( $metabox_config['priority'] ) ? $metabox_config['priority'] : 'default'
					);
				}

			} elseif ( is_string( $metabox_config['pages'] ) ) {

				add_meta_box(
					'bf_' . $metabox_id,
					$title,
					array( $generator, 'callback' ),
					$metabox_config['pages'],
					isset( $metabox_config['context'] ) ? $metabox_config['context'] : 'normal',
					isset( $metabox_config['priority'] ) ? $metabox_config['priority'] : 'default'
				);

			}
		}// foreach

	} // add_meta_boxes


	/**
	 * Used for retrieve meta data values
	 *
	 * @param   string $id      meta box id
	 * @param   int    $post_id meta box id
	 *
	 * @since    1.0
	 * @return  array
	 * @access   public
	 */
	public function get_meta_data( $id = '', $post_id = 0 ) {

		global $pagenow;

		$output = array();

		if ( isset( self::$metabox['panel-id'] ) ) {
			$std_id = Better_Framework::options()->get_panel_std_id( self::$metabox['panel-id'] );
		} else {
			$std_id = 'std';
		}

		$metabox_std = self::get_metabox_std( $id );

		if ( $pagenow == 'post-new.php' ) {

			if ( ! empty( $metabox_std ) ) {

				foreach ( (array) $metabox_std as $field_id => $field ) {

					if ( isset( $field[ $std_id ] ) ) {
						$output[ $field_id ] = $field[ $std_id ];
					} elseif ( isset( $field['std'] ) ) {
						$output[ $field_id ] = $field['std'];
					}
				}

			}

			return $output;
		}

		$meta = get_post_custom( $post_id );

		foreach ( (array) $metabox_std as $field_id => $field ) {

			if ( isset( $meta[ $field_id ] ) ) {

				if ( is_serialized( $meta[ $field_id ][0] ) ) {
					$output[ $field_id ] = unserialize( $meta[ $field_id ][0] );
				} else {
					$output[ $field_id ] = $meta[ $field_id ][0];
				}

			} else {

				if ( isset( $field[ $std_id ] ) ) {
					$output[ $field_id ] = $field[ $std_id ];
				} elseif ( isset( $field['std'] ) ) {
					$output[ $field_id ] = $field['std'];
				}
			}

		}

		return $output;
	}


	/**
	 * Generates fields of ajaxified tab
	 *
	 * @param $tab_id
	 * @param $metabox_id
	 * @param $object_id
	 */
	public function ajax_tab( $tab_id, $metabox_id, $object_id ) {

		$metabox_config           = self::get_metabox_config( $metabox_id );
		$metabox_config['fields'] = self::get_metabox_fields( $metabox_id );
		$metabox_values           = array();
		$use_generator            = true;

		if ( empty( $metabox_config['fields'][ $tab_id ]['ajax-section-handler'] ) ) {

			$metabox_values = $this->get_meta_data( $metabox_id, $object_id );

			foreach ( $metabox_config['fields'] as $idx => $field ) {

				// Backward compatibility
				if ( isset( $field['ajax-tab-field'] ) ) {
					$field['ajax-section-field'] = $field['ajax-tab-field'];
				}

				if ( empty( $field['ajax-section-field'] ) || $field['ajax-section-field'] !== $tab_id ) {
					unset( $metabox_config['fields'][ $idx ] );
				}
			}
		} else {

			$parent_field = $metabox_config['fields'][ $tab_id ];

			$args = isset( $parent_field['ajax-section-handler-args'] ) ? $parent_field['ajax-section-handler-args'] : array();
			$args = array_merge( $args, compact( 'metabox_id', 'section_id' ) );

			if (
				! isset( $parent_field['ajax-section-handler-type'] ) ||
				$parent_field['ajax-section-handler-type'] === 'field-generator'
			) {

				$metabox_config['fields'] = call_user_func( $parent_field['ajax-section-handler'], $args );

				foreach ( $metabox_config['fields'] as $key => $field ) {
					$metabox_values[ $field['id'] ] = bf_get_post_meta( $field['id'], $object_id );
				}
			} else {

				$use_generator = false;
				$out           = call_user_func( $parent_field['ajax-section-handler'], $args );

			}
		}

		if ( $use_generator ) {

			if ( ! class_exists( 'BF_Metabox_Front_End_Generator' ) ) {
				require BF_PATH . 'metabox/class-bf-metabox-front-end-generator.php';
			}

			self::$fields[ $metabox_id ] = $metabox_config['fields'];
			$generator                   = new BF_Metabox_Front_End_Generator( $metabox_config, $metabox_id, $metabox_values );

			ob_start();
			$generator->callback( true );
			$out = ob_get_clean();

		}

		wp_send_json( array( 'out' => $out, 'tab_id' => $tab_id ) );

	}


	/**
	 * Calculate when meta box can added
	 *
	 * @param   array $config Configuration values of meta box
	 *
	 * @return bool
	 * @since   1.1.1
	 * @access  public
	 */
	public function can_output( $config ) {

		$post_id = bf_get_admin_current_post_id();

		// post types
		switch ( true ) {
			case ( ! isset( $config['pages'] ) || empty( $config['pages'] ) ):
				$post_types = array();
				break;
			case ( is_array( $config['pages'] ) ):
				$post_types = $config['pages'];
				break;
			case ( is_string( $config['pages'] ) ):
				$post_types[] = $config['pages'];
				break;
		}

		// include_template
		switch ( true ) {

			case( ! isset( $config['include_template'] ) || empty( $config['include_template'] ) ):
				$include_template = array();
				break;

			case( is_array( $config['include_template'] ) ):
				$include_template = $config['include_template'];
				break;

			case ( is_string( $config['include_template'] ) ):
				$include_template[] = $config['include_template'];
				break;
		}

		// exclude_template
		switch ( true ) {

			case ( ! isset( $config['exclude_template'] ) || empty( $config['exclude_template'] ) ):
				$exclude_template = array();
				break;

			case ( is_array( $config['exclude_template'] ) ):
				$exclude_template = $config['exclude_template'];
				break;

			case ( is_string( $config['exclude_template'] ) ):
				$exclude_template[] = $config['exclude_template'];
				break;

		}


		if ( ! empty( $include_template ) || ! empty( $exclude_template ) ) {
			$template_file = get_post_meta( $post_id, '_wp_page_template', true );
		}

		$can_output = true;

		// processing order: "exclude" then "include"
		// processing order: "template"

		if ( ! empty( $include_template ) || ! empty( $exclude_template ) ) {

			if ( ! empty( $exclude_template ) ) {
				if ( in_array( $template_file, $exclude_template ) ) {
					$can_output = false;
				}
			}

			// excludes are not set use "include only" mode
			if ( empty( $exclude_template ) ) {
				$can_output = false;
			}

			if ( ! empty( $include_template ) ) {

				if ( in_array( $template_file, $include_template ) ) {
					$can_output = true;
				}

			}
		}

		// Filter for post types
		$current_post_type = bf_get_admin_current_post_type();

		if ( isset( $current_post_type ) && ! in_array( $current_post_type, $post_types ) ) {
			$can_output = false;
		}

		return $can_output;
	}


	/**
	 * Update Post Meta
	 *
	 * @param   string $id  The id post
	 * @param   string $key Post meta key name
	 * @param   string $val Post meta key value
	 *
	 * @static
	 * @since   1.0
	 * @return  bool
	 */
	public static function update( $id, $key, $val ) {

		return update_post_meta( $id, $key, $val );
	}


	/**
	 * Save post meta box values
	 *
	 * Callback: pre_post_update action
	 *
	 * @param   int $post_id
	 *
	 * @static
	 * @return  mixed
	 * @since   1.0
	 */
	public function save( $post_id ) {

		if (
			empty( $_POST['bf-metabox-option'] )
			|| ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
			|| ( ! isset( $_POST['post_ID'] )
			     || $post_id != $_POST['post_ID'] )
			|| ! current_user_can( 'edit_post', $post_id )
		) {
			return $post_id;
		}


		foreach ( self::$metabox as $metabox_id => $metabox ) {

			if ( ! isset( $_POST['bf-metabox-option'][ $metabox_id ] ) ) {
				continue;
			}

			$metabox_std = self::get_metabox_std( $metabox_id );

			if ( empty( $metabox_std ) || ! is_array( $metabox_std ) ) {
				continue;
			}

			$new_value = &$_POST['bf-metabox-option'][ $metabox_id ];

			foreach ( $metabox_std as $field_key => $_field_value ) {

				// value not passed
				if ( ! isset( $new_value[ $field_key ] ) ) {
					continue;
				}

				$field_value = &$new_value[ $field_key ];

				if ( isset( $metabox['panel-id'] ) ) {
					$std_id = Better_Framework::options()->get_panel_std_id( $metabox['panel-id'] );
				} else {
					$std_id = 'std';
				}

				// Save value if save-std is true or not defined
				if ( ! isset( $metabox_std[ $field_key ]['save-std'] ) || $metabox_std[ $field_key ]['save-std'] == true ) {
					self::update( $post_id, $field_key, $field_value );
				} // Don't Save Default Value
				elseif ( isset( $metabox_std[ $field_key ]['save-std'] ) ) {

					// If style std defined then save it
					if ( isset( $metabox_std[ $field_key ][ $std_id ] ) ) {

						if ( $metabox_std[ $field_key ][ $std_id ] != $field_value ) {
							self::update( $post_id, $field_key, $field_value );
						} else {
							delete_post_meta( $post_id, $field_key );
						}

					} // If style std defined then save it
					elseif ( isset( $metabox_std[ $field_key ]['std'] ) ) {

						if ( $metabox_std[ $field_key ]['std'] != $field_value ) {
							self::update( $post_id, $field_key, $field_value );
						} else {
							delete_post_meta( $post_id, $field_key );
						}

					}

				} // Delete Custom field
				else {
					delete_post_meta( $post_id, $field_key );
				}
			}
		} // foreach
	} // save
}
libs/better-framework/metabox/functions.php000064400000006260151214002370015134 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_get_post_meta' ) ) {

	/**
	 * Used for retrieving meta fields ofr  posts and pages
	 *
	 * @param null        $key           Field ID
	 * @param null        $post_id       Post ID (Optional)
	 * @param null|string $force_default Default value (Optional)
	 *
	 * @global WPDB       $wpdb          WordPress database access object.
	 *
	 * @return mixed|void
	 */
	function bf_get_post_meta( $key = null, $post_id = null, $force_default = null ) {

		global $wp_query;

		if ( is_null( $post_id ) ) {
			global $post;
			$post_id = isset( $post->ID ) ? $post->ID : 0;
		}

		/**
		 * Detecting the BuddyPress $post object resetting to prevent returning false as default value.
		 *
		 * @see bp_theme_compat_reset_post function for more info
		 */
		static $bp_component_post_id;

		if ( empty( $post_id ) && $wp_query->is_main_query() ) {

			if ( ! isset( $bp_component_post_id ) ) {
				$bp_component_post_id = bf_bp_get_component_page_id();
			}

			$post_id = $bp_component_post_id;
		}

		$meta = get_post_meta( $post_id, $key, true );

		if ( $meta == '' && ! is_null( $force_default ) ) {
			return $force_default;
		}

		// If Meta check for default value
		if ( $meta !== '' ) {
			return $meta;
		}

		// initialize base BF metabox
		if ( ! class_exists( 'BF_Metabox_Core' ) ) {
			Better_Framework()->post_meta();
		}

		foreach ( (array) BF_Metabox_Core::$metabox as $metabox_id => $metabox ) {

			// get style id for current metabox
			if ( isset( $metabox['panel-id'] ) ) {
				$std_id = Better_Framework()->options()->get_panel_std_id( $metabox['panel-id'] );
			} else {
				$std_id = 'std';
			}

			$metabox_std = BF_Metabox_Core::get_metabox_std( $metabox_id );

			if ( isset( $metabox_std[ $key ] ) ) {
				if ( isset( $metabox_std[ $key ][ $std_id ] ) ) {
					return $metabox_std[ $key ][ $std_id ];
				} elseif ( isset( $metabox_std[ $key ]['std'] ) ) {
					return $metabox_std[ $key ]['std'];
				} else {
					return '';
				}
			}

		}

		return '';
	}
}


if ( ! function_exists( 'bf_echo_post_meta' ) ) {

	/**
	 * Used for retrieving meta fields ofr  posts and pages
	 *
	 * @param null        $key           Field ID
	 * @param null        $post_id       Post ID (Optional)
	 * @param null|string $force_default Default value (Optional)
	 *
	 * @return mixed|void
	 */
	function bf_echo_post_meta( $key = null, $post_id = null, $force_default = null ) {

		echo bf_get_post_meta( $key, $post_id, $force_default ); // escaped before
	}
}libs/better-framework/metabox/index.php000064400000000012151214002370014220 0ustar00<?php
die;libs/better-framework/metabox/templates/default.php000064400000006034151214002370016545 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes   = $classes['section'];
$container_classes = $classes['container'];

$heading_classes  = $classes['heading'];
$controls_classes = $classes['controls'];
$explain_classes  = $classes['explain'];

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];

if ( empty( $options['desc'] ) ) {
	$section_classes .= ' no-desc ';
}


$section_css_attr = $this->get_section_css_attr( $options );
$section_attr     = $this->get_section_filter_attr( $options );

?>
<div
		class="<?php echo esc_attr( $container_classes ); ?> bf-section-container bf-metabox bf-clearfix" <?php echo $section_css_attr; // escaped before ?> <?php echo $section_attr; // escaped before ?>>
	<div class="<?php echo esc_attr( $section_classes ); ?> bf-clearfix"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>">

		<div class="<?php echo esc_attr( $heading_classes ); ?> bf-clearfix">
			<h3><label
						for="<?php echo esc_attr( $options['input_name'] ); ?>"><?php echo esc_html( $options['name'] ); ?></label>
			</h3>
		</div>

		<div class="<?php echo esc_attr( $controls_classes ); ?> bf-clearfix">
			<?php echo $input; // escaped before ?>
		</div>

		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div
					class="<?php echo esc_attr( $explain_classes ); ?> bf-clearfix"><?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?></div>
		<?php } ?>

	</div>
</div>libs/better-framework/metabox/templates/hr.php000064400000001600151214002400015516 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div class="bf-section-container bf-clearfix">
	<div class="bf-section-hr bf-clearfix">
		<?php echo $input; // escaped before ?>
	</div>
</div>libs/better-framework/metabox/templates/heading.php000064400000002553151214002400016514 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

$style = ! empty( $options['layout'] ) ? $options['layout'] : 'style-1';

?>
<div class="bf-section-container bf-metabox bf-clearfix">
	<div class="bf-section-heading bf-clearfix <?php echo $style; ?>"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>"
	     id="<?php echo esc_attr( $options['id'] ); ?>">
		<div class="bf-section-heading-title bf-clearfix">
			<h3><?php echo esc_html( $options['name'] ); ?></h3>
		</div>
		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div
					class="bf-section-heading-desc bf-clearfix"><?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?></div>
		<?php } ?>
	</div>
</div>libs/better-framework/metabox/templates/info.php000064400000006014151214002400016044 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes = $classes['section'] . ' bf-widget-field-section';

$heading_classes  = $classes['heading'] . ' bf-heading';
$controls_classes = $classes['controls'] . ' bf-control not-prepared';
$explain_classes  = $classes['explain'] . ' bf-desc';

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];


if ( ! isset( $options['info-type'] ) ) {
	$options['info-type'] = 'info';
}

if ( ! isset( $options['state'] ) ) {
	$options['state'] = 'open';
}

$section_attr = $this->get_section_filter_attr( $options );

?>
<div class="bf-section-container bf-metabox bf-clearfix" <?php echo $section_attr; ?>>
	<div
			class="bf-section-info <?php echo esc_attr( $options['info-type'] ); ?> <?php echo esc_attr( $options['state'] ); ?> bf-clearfix">
		<div class="bf-section-info-title bf-clearfix">
			<h3><?php

				switch ( $options['info-type'] ) {

					case 'help':
						echo '<i class="fa fa-support"></i> ';
						break;

					case 'info':
						echo '<i class="fa fa-info"></i> ';
						break;

					case 'warning':
						echo '<i class="fa fa-warning"></i> ';
						break;

					case 'danger':
						echo '<i class="fa fa-exclamation"></i> ';
						break;

					default:
						echo '<i class="fa fa-info"></i> ';
						break;


				}

				echo esc_html( $options['name'] ); ?></h3>
		</div>
		<div class="<?php echo esc_attr( $controls_classes ); ?>  bf-clearfix">
			<?php echo $input; // escaped before ?>
		</div>
	</div>
</div>libs/better-framework/functions/archive.php000064400000010116151214002400015103 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_get_query_var_paged' ) ) {
	/**
	 * Handy function used to find current page paged query var
	 * This is home page firendly
	 *
	 * @since 2.0
	 *
	 * @param int $default
	 *
	 * @return int|mixed
	 */
	function bf_get_query_var_paged( $default = 1 ) {

		return get_query_var( 'paged' ) ? get_query_var( 'paged' ) : ( get_query_var( 'page' ) ? get_query_var( 'page' ) : $default );

	}
}


if ( ! function_exists( 'bf_is_search_page' ) ) {
	/**
	 * Used for detecting current page is search page or not
	 */
	function bf_is_search_page() {

		if ( stripos( $_SERVER['REQUEST_URI'], '/?s=' ) === false && stripos( $_SERVER['REQUEST_URI'], '/search/' ) === false ) {
			return false;
		} elseif ( ! is_search() ) {
			return false;
		}

		return true;
	}
}


if ( ! function_exists( 'bf_get_author_archive_user' ) ) {
	/**
	 * Used for finding user in author archive page
	 *
	 * @since   2.0
	 * @return WP_User|false WP_User object on success, false on failure.
	 */
	function bf_get_author_archive_user() {

		global $author_name, $author;

		return isset( $_GET['author_name'] ) ? get_user_by( 'slug', $author_name ) : get_userdata( intval( $author ) );

	}
}


if ( ! function_exists( 'bf_get_admin_current_post_type' ) ) {
	/**
	 * Used to check for the current post type, works when creating or editing a
	 * new post, page or custom post type.
	 *
	 * @since    1.0
	 * @return    string [custom_post_type], page or post
	 */
	function bf_get_admin_current_post_type() {

		// admin side
		if ( is_admin() ) {

			$uri = isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : null;

			if ( isset( $uri ) ) {

				$uri_parts = parse_url( $uri );

				$file = basename( $uri_parts['path'] );

				$_check = array(
					'post.php'     => '',
					'post-new.php' => '',
				);

				// Post types
				if ( $uri AND isset( $_check[ $file ] ) ) {
					$post_id = bf_get_admin_current_post_id();

					$post_type = isset( $_GET['post_type'] ) ? $_GET['post_type'] : null;

					$post_type = $post_id ? get_post_type( $post_id ) : $post_type;

					if ( isset( $post_type ) ) {

						return $post_type;

					} else {

						// because of the 'post.php' and 'post-new.php' checks above, we can default to 'post'
						return 'post';

					}
				} // Taxonomies
				elseif ( $uri AND ( $file === 'edit-tags.php' || $file === 'term.php' ) ) {

					$taxonomy = isset( $_GET['taxonomy'] ) ? $_GET['taxonomy'] : null;

					return $taxonomy;

				} // Pages custom css
				elseif ( isset( $_GET['bs_per_page_custom_css'] ) && ! empty( $_GET['bs_per_page_custom_css'] ) ) {

					if ( isset( $_GET['post_id'] ) && ! empty( $_GET['post_id'] ) ) {

						return get_post_type( $_GET['post_id'] );

					}

				}
			}

		} // if used in front end
		else {

			return get_post_type( bf_get_admin_current_post_id() );

		}


		return null;
	}
}


if ( ! function_exists( 'bf_get_admin_current_post_id' ) ) {
	/**
	 * Used to get the current post id.
	 *
	 * @since    1.0
	 * @return    int post ID
	 */
	function bf_get_admin_current_post_id() {

		global $post;

		$p_post_id = isset( $_POST['post_ID'] ) ? $_POST['post_ID'] : null;

		$g_post_id = isset( $_GET['post'] ) ? $_GET['post'] : null;

		$post_id = $g_post_id ? $g_post_id : $p_post_id;

		$post_id = isset( $post->ID ) ? $post->ID : $post_id;

		if ( isset( $post_id ) ) {
			return (integer) $post_id;
		} else {
			return 0;
		}

	}
}libs/better-framework/functions/enqueue.php000064400000030516151214002400015137 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_enqueue_modal' ) ) {
	/**
	 * Enqueue BetterFramework modals safely
	 *
	 * @param $modal_key
	 */
	function bf_enqueue_modal( $modal_key = '' ) {

		Better_Framework::assets_manager()->add_modal( $modal_key );

	}
}


if ( ! function_exists( 'bf_enqueue_style' ) ) {
	/**
	 * @see   wp_enqueue_style for more documentation.
	 *
	 * @param string           $handle
	 * @param string           $src
	 * @param array            $deps
	 * @param string           $file_path
	 * @param string|bool|null $ver
	 */
	function bf_enqueue_style( $handle, $src = '', $deps = array(), $file_path = '', $ver = false ) {

		// check list to change for backward compatibility
		$check = array(
			'better-social-font-icon' => 'bs-icons'
		);

		if ( isset( $check[ $handle ] ) ) {
			$handle = $check[ $handle ];
		}

		if ( ! function_exists( 'bf_booster_is_active' ) ||
		     ! bf_booster_is_active( 'minify-css' )
		) {
			wp_enqueue_style( $handle, $src, $deps, $ver );

			return;
		}

		if ( $src ) {
			bf_styles()->add( $handle, $src, $deps, $ver, 'all' );
		}

		if ( $file_path ) {
			bf_styles()->files_path[ $handle ] = $file_path;
		}

		bf_styles()->enqueue( $handle );
	}
}


if ( ! function_exists( 'bf_enqueue_wp_script_deps' ) ) {

	function bf_enqueue_wp_script_deps( $handle ) {

		if ( ! isset( bf_scripts()->registered[ $handle ] ) ) {
			return;
		}

		$deps = &bf_scripts()->registered[ $handle ]->deps;
		foreach ( $deps as $index => $dep ) {

			if ( ! isset( bf_scripts()->registered[ $dep ] ) ) {

				if ( ! isset( wp_scripts()->registered[ $dep ] ) ) {
					continue;
				}

				unset( $deps[ $index ] );

				if ( wp_scripts()->registered[ $dep ]->args === 1 ) {
					wp_scripts()->registered[ $dep ]->args = null;
				}

				if ( ! wp_script_is( $dep ) ) {
					wp_enqueue_script( $dep );
				}

			} else {

				bf_enqueue_wp_script_deps( $dep );
			}
		}
	}
}


if ( ! function_exists( 'bf_enqueue_script' ) ) {
	/**
	 * Enqueue BetterFramework scripts safely
	 *
	 * @see   wp_enqueue_script for more documentation.
	 *
	 * @param string           $handle
	 * @param string           $src
	 * @param array            $deps
	 * @param string           $file_path
	 * @param string|bool|null $ver
	 */
	function bf_enqueue_script( $handle, $src = '', $deps = array(), $file_path = '', $ver = false ) {

		if ( ! function_exists( 'bf_booster_is_active' ) ||
		     ! bf_booster_is_active( 'minify-js' )
		) {
			wp_enqueue_script( $handle, $src, $deps, $ver, true );

			return;
		}

		if ( $src ) {
			bf_scripts()->add( $handle, $src, $deps, $ver, '1' );
		}

		if ( $file_path ) {
			bf_scripts()->files_path[ $handle ] = $file_path;
		}

		bf_enqueue_wp_script_deps( $handle );

		bf_scripts()->enqueue( $handle );
	}
}


if ( ! function_exists( 'bf_register_script' ) ) {

	function bf_register_script( $handle, $src = '', $deps = array(), $file_path = '', $ver = false ) {

		if ( ! function_exists( 'bf_booster_is_active' ) ||
		     ! bf_booster_is_active( 'minify-js' )
		) {
			wp_register_script( $handle, $src, $deps, $ver );

			return;
		}

		if ( $file_path ) {
			bf_scripts()->files_path[ $handle ] = $file_path;
		}

		bf_scripts()->add( $handle, $src, $deps, $ver, '1' );
	}
}


if ( ! function_exists( 'bf_deregister_script' ) ) {

	function bf_deregister_script( $handle ) {

		if ( function_exists( 'bf_booster_is_active' ) &&
		     bf_booster_is_active( 'minify-js' )
		) {
			bf_scripts()->remove( $handle );
		} else {
			bf_call_func( 'wp' . '_' . 'deregister' . '_script', $handle );
		}
	}
}


if ( ! function_exists( 'bf_print_scripts' ) ) {

	/**
	 * Print scripts in document head that are in the $handles queue.
	 *
	 * @param string|bool|array $handles
	 *
	 * @return array
	 */
	function bf_print_scripts( $handles = false ) {

		if ( ! function_exists( 'bf_booster_is_active' ) ||
		     ! bf_booster_is_active( 'minify-js' )
		) {
			return wp_print_scripts( $handles );
		}

		return bf_scripts()->do_items( $handles );
	}
}


if ( ! function_exists( 'bf_add_style_file' ) ) {

	/**
	 * Append inline css content into a file
	 *
	 * @param string   $id unique name
	 * @param callable $content_cb
	 *
	 * @since 2.9.0
	 */
	function bf_add_style_file( $id, $content_cb ) {

		if ( function_exists( 'bf_styles' ) ) {

			bf_styles()->add_css_file( $id, $content_cb );

		} elseif ( function_exists( 'wp_add_inline_style' ) ) {

			if ( $style = call_user_func( $content_cb ) ) {

				wp_add_inline_style( $id, $style );
			}
		}
	}
}


if ( ! function_exists( 'bf_register_style' ) ) {

	function bf_register_style( $handle, $src = '', $deps = array(), $file_path = '', $ver = false, $media = '1' ) {

		if ( ! function_exists( 'bf_booster_is_active' ) ||
		     ! bf_booster_is_active( 'minify-css' )
		) {
			wp_register_style( $handle, $src, $deps, $ver );

			return;
		}

		if ( $file_path ) {
			bf_styles()->files_path[ $handle ] = $file_path;
		}

		bf_styles()->add( $handle, $src, $deps, $ver, $media );
	}
}


if ( ! function_exists( 'bf_deregister_style' ) ) {

	function bf_deregister_style( $handle ) {

		if ( function_exists( 'bf_booster_is_active' ) &&
		     bf_booster_is_active( 'minify-css' )
		) {
			bf_styles()->remove( $handle );
		} else {
			wp_deregister_style( $handle );
		}
	}
}


if ( ! function_exists( 'bf_print_styles' ) ) {

	/**
	 * Print scripts in document head that are in the $handles queue.
	 *
	 * @param string|bool|array $handles
	 *
	 * @return array
	 */
	function bf_print_styles( $handles ) {

		if ( ! function_exists( 'bf_booster_is_active' ) ||
		     ! bf_booster_is_active( 'minify-css' )
		) {
			return wp_print_styles( $handles );
		}

		return bf_styles()->do_items( $handles );
	}
}


if ( ! function_exists( 'bf_add_jquery_js' ) ) {
	/**
	 * Used for adding inline js to front end
	 *
	 * @param string $code
	 * @param bool   $to_top
	 * @param bool   $force
	 */
	function bf_add_jquery_js( $code = '', $to_top = false, $force = false ) {

		Better_Framework::assets_manager()->add_jquery_js( $code, $to_top, $force );

	}
}


if ( ! function_exists( 'bf_add_js' ) ) {
	/**
	 * Used for adding inline js to front end
	 *
	 * @param string $code
	 * @param bool   $to_top
	 * @param bool   $force
	 */
	function bf_add_js( $code = '', $to_top = false, $force = false ) {

		Better_Framework::assets_manager()->add_js( $code, $to_top, $force );

	}
}


if ( ! function_exists( 'bf_add_css' ) ) {
	/**
	 * Used for adding inline css to front end
	 *
	 * @param string $code
	 * @param bool   $to_top
	 * @param bool   $force
	 */
	function bf_add_css( $code = '', $to_top = false, $force = false ) {

		Better_Framework::assets_manager()->add_css( $code, $to_top, $force );

	}
}


if ( ! function_exists( 'bf_add_admin_js' ) ) {
	/**
	 * Used for adding inline js to back end
	 *
	 * @param string $code
	 * @param bool   $to_top
	 * @param bool   $force
	 */
	function bf_add_admin_js( $code = '', $to_top = false, $force = false ) {

		Better_Framework::assets_manager()->add_admin_js( $code, $to_top, $force );

	}
}


if ( ! function_exists( 'bf_add_admin_css' ) ) {
	/**
	 * Used for adding inline css to back end
	 *
	 * @param string $code
	 * @param bool   $to_top
	 * @param bool   $force
	 */
	function bf_add_admin_css( $code = '', $to_top = false, $force = false ) {

		Better_Framework::assets_manager()->add_admin_css( $code, $to_top, $force );

	}
}


if ( ! function_exists( 'bf_append_suffix' ) ) {
	/**
	 * Used for adding .min quickly
	 *
	 * @param string $before
	 * @param string $after
	 *
	 * @return string
	 */
	function bf_append_suffix( $before = '', $after = '' ) {

		static $suffix;

		if ( is_null( $suffix ) ) {
			$suffix = bf_is( 'dev' ) ? '' : '.min';
		}

		return $before . $suffix . $after;
	}
}

if ( ! function_exists( 'bf_enqueue_tinymce_style' ) ) {
	/**
	 * Register style for tinymce view add-on
	 *
	 * @param string $type inline|custom|extra|registered
	 * @param string $data
	 *                     bf_add_style_file() handle id if $type == extra
	 *                     unique handle id              if $type == registered
	 *                     custom inline css code        if $type == inline
	 *                     stylesheet url                if $type == inline
	 *
	 *
	 * @since 3.0.0
	 */
	function bf_enqueue_tinymce_style( $type, $data ) {

		$enqueue = array();

		if ( $type === 'inline' ) {
			$enqueue = array(
				'type' => 'inline',
				'data' => $data,
			);
		} elseif ( $type === 'custom' ) {
			$enqueue = array(
				'type' => 'custom',
				'url'  => $data,
			);
		} elseif ( $type === 'extra' ) {
			$enqueue = array(
				'type'    => 'extra',
				'handles' => (array) $data,
			);
		} elseif ( $type === 'registered' ) {
			$enqueue = array(
				'type'    => 'registered',
				'handles' => (array) $data,
			);
		}
		if ( empty( BF_Shortcodes_Manager::$tinymce_extra_enqueues['styles'] ) ) {
			BF_Shortcodes_Manager::$tinymce_extra_enqueues['styles'] = array();
		}

		BF_Shortcodes_Manager::$tinymce_extra_enqueues['styles'][] = $enqueue;
	}
}


if ( ! function_exists( '_bf_normalize_enqueue_tinymce' ) ) {
	/**
	 * @see   bf_enqueue_tinymce_style for documentation
	 * @see   BF_Shortcodes_Manager::tinymce_view_shortcode
	 *
	 * @param string $type
	 * @param string $data
	 *
	 * @since 3.0.0
	 * @return array
	 */
	function _bf_normalize_enqueue_tinymce( $type, $data ) {

		$enqueue = array();

		if ( $type === 'inline' ) {
			$enqueue = array(
				'type' => 'inline',
				'data' => $data,
			);
		} elseif ( $type === 'custom' ) {
			$enqueue = array(
				'type' => 'custom',
				'url'  => $data,
			);
		} elseif ( $type === 'extra' ) {
			$enqueue = array(
				'type'    => 'extra',
				'handles' => (array) $data,
			);
		} elseif ( $type === 'registered' ) {
			$enqueue = array(
				'type'    => 'registered',
				'handles' => (array) $data,
			);
		}

		return $enqueue;
	}

}
if ( ! function_exists( 'bf_enqueue_tinymce_style' ) ) {
	/**
	 * Register style for tinymce view add-on
	 *
	 * @param string $type inline|custom|extra|registered
	 * @param string $data
	 *                     bf_add_style_file() handle id if $type == extra
	 *                     unique handle id              if $type == registered
	 *                     custom inline css code        if $type == inline
	 *                     stylesheet url                if $type == custom
	 *
	 *
	 * @since 3.0.0
	 * @return true on success or false on failure
	 */
	function bf_enqueue_tinymce_style( $type, $data ) {

		if ( class_exists( 'BF_Shortcodes_Manager' ) ) {

			if ( empty( BF_Shortcodes_Manager::$tinymce_extra_enqueues['styles'] ) ) {
				BF_Shortcodes_Manager::$tinymce_extra_enqueues['styles'] = array();
			}

			BF_Shortcodes_Manager::$tinymce_extra_enqueues['styles'][] = _bf_normalize_enqueue_tinymce( $type, $data );

			return true;
		}

		return false;
	}
}
if ( ! function_exists( 'bf_enqueue_tinymce_script' ) ) {
	/**
	 * Register style for tinymce view add-on
	 *
	 * @param string $type inline|custom|extra|registered
	 * @param string $data
	 *                     bf_add_style_file() handle id if $type == extra
	 *                     unique handle id              if $type == registered
	 *                     custom inline css code        if $type == inline
	 *                     stylesheet url                if $type == custom
	 *
	 *
	 * @since 3.0.0
	 * @return true on success or false on failure
	 */
	function bf_enqueue_tinymce_script( $type, $data ) {

		if ( class_exists( 'BF_Shortcodes_Manager' ) ) {
			if ( empty( BF_Shortcodes_Manager::$tinymce_extra_enqueues['scripts'] ) ) {
				BF_Shortcodes_Manager::$tinymce_extra_enqueues['scripts'] = array();
			}

			BF_Shortcodes_Manager::$tinymce_extra_enqueues['scripts'][] = _bf_normalize_enqueue_tinymce( $type, $data );

			return true;
		}

		return false;
	}
}
libs/better-framework/functions/content.php000064400000004224151214002400015137 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// Callback For Video Format auto-embed
add_filter( 'better-framework/content/video-embed', 'bf_auto_embed_content' );
add_filter( 'better-framework/content/auto-embed', 'bf_auto_embed_content' );


if ( ! function_exists( 'bf_auto_embed_content' ) ) {
	/**
	 * Filter Callback: Auto-embed using a link
	 *
	 * @param string $content
	 *
	 * @return string
	 */
	function bf_auto_embed_content( $content ) {

		//
		// Custom External Videos
		//
		preg_match( '#^(http|https)://.+\.(mp4|m4v|webm|ogv|wmv|flv)$#i', $content, $matches );
		if ( ! empty( $matches[0] ) ) {
			return array(
				'type'    => 'external-video',
				'content' => do_shortcode( '[video src="' . $matches[0] . '"]' ),
			);
		}


		//
		// Custom External Audio
		//
		preg_match( '#^(http|https)://.+\.(mp3|m4a|ogg|wav|wma)$#i', $content, $matches );
		if ( ! empty( $matches[0] ) ) {
			return array(
				'type'    => 'external-audio',
				'content' => do_shortcode( '[audio src="' . $matches[0] . '"]' ),
			);
		}


		//
		// Default embeds and other registered
		//

		global $wp_embed;

		if ( ! is_object( $wp_embed ) ) {
			return array(
				'type'    => 'unknown',
				'content' => $content,
			);
		}

		$embed = $wp_embed->autoembed( $content );

		if ( $embed !== $content ) {
			return array(
				'type'    => 'embed',
				'content' => $embed,
			);
		}

		// No embed detected!
		return array(
			'type'    => 'unknown',
			'content' => $content,
		);
	}
}
libs/better-framework/functions/menu.php000064400000007320151214002400014431 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_get_menu_location_name_from_id' ) ) {
	/**
	 * Used For retrieving current sidebar
	 *
	 * #since 2.0
	 *
	 * @param $location
	 *
	 * @return
	 */
	function bf_get_menu_location_name_from_id( $location ) {

		$locations = get_registered_nav_menus();

		if ( isset( $locations[ $location ] ) ) {
			return $locations[ $location ];
		}

	}
}


if ( ! function_exists( 'bf_get_menus_option' ) ) {
	/**
	 * Handy function to get select option for using this as deferred callback
	 *
	 * @since 2.5.5
	 *
	 * @param bool   $default
	 * @param string $default_label
	 * @param string $menus_label
	 *
	 * @return array
	 */
	function bf_get_menus_option( $default = false, $default_label = '', $menus_label = '', $args = array() ) {

		$menus = array();

		if ( $default ) {
			$menus['default'] = ! empty( $default_label ) ? $default_label : __( 'Default Navigation', 'better-studio' );
		}

		$menus[] = array(
			'label'   => ! empty( $menus_label ) ? $menus_label : __( 'Menus', 'better-studio' ),
			'options' => bf_get_menus(),
		);

		if ( isset( $args['append'] ) ) {
			$menus = array_merge( $menus, $args['append'] );
		}

		return $menus;

	} // bf_get_menus_option
} // if


if ( ! function_exists( 'bf_get_menus_animations_option' ) ) {
	/**
	 * Handy function to get select option of all menu animations for using as deferred callback
	 *
	 * @since 2.5.5
	 *
	 * @param array $args used for future changes
	 *
	 * @return array
	 */
	function bf_get_menus_animations_option( $args = array() ) {

		$animations = array(

			'default' => __( '-- Default --', 'better-studio' ),
			'none'    => __( 'No Animation', 'better-studio' ),
			'random'  => __( 'Random Animation', 'better-studio' ),

			array(
				'label'   => __( 'Fading', 'better-studio' ),
				'options' => array(
					'fade'       => __( 'Simple Fade', 'better-studio' ),
					'slide-fade' => __( 'Fading Slide', 'better-studio' ),
				),
			),

			array(
				'label'   => __( 'Attention Seekers', 'better-studio' ),
				'options' => array(
					'bounce' => __( 'Bounce', 'better-studio' ),
					'tada'   => __( 'Tada', 'better-studio' ),
					'shake'  => __( 'Shake', 'better-studio' ),
					'swing'  => __( 'Swing', 'better-studio' ),
					'wobble' => __( 'Wobble', 'better-studio' ),
					'buzz'   => __( 'Buzz', 'better-studio' ),
				),
			),

			array(
				'label'   => __( 'Sliding', 'better-studio' ),
				'options' => array(
					'slide-top-in'    => __( 'Slide &#x2193; In', 'better-studio' ),
					'slide-bottom-in' => __( 'Slide &#x2191; In', 'better-studio' ),
					'slide-left-in'   => __( 'Slide &#x2192; In', 'better-studio' ),
					'slide-right-in'  => __( 'Slide &#x2190; In', 'better-studio' ),
				),
			),

			array(
				'label'   => __( 'Flippers', 'better-studio' ),
				'options' => array(
					'filip-in-x' => __( 'Filip In X - &#x2195;', 'better-studio' ),
					'filip-in-y' => __( 'Filip In Y - &#x2194;', 'better-studio' ),
				),
			),

		);

		return $animations;

	} // bf_get_menus_animations_option
} // if


libs/better-framework/functions/sidebar.php000064400000002572151214002400015102 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_get_current_sidebar' ) ) {
	/**
	 * Used For retrieving current sidebar
	 *
	 * @since 2.5.5
	 *
	 * @return string
	 */
	function bf_get_current_sidebar() {

		return Better_Framework::widget_manager()->get_current_sidebar();
	}
}


if ( ! function_exists( 'bf_get_sidebar_name_from_id' ) ) {
	/**
	 * Used For retrieving current sidebar
	 *
	 * @since 2.0
	 *
	 * @param $sidebar_id
	 *
	 * @return
	 */
	function bf_get_sidebar_name_from_id( $sidebar_id ) {

		global $wp_registered_sidebars;

		if ( isset( $wp_registered_sidebars[ $sidebar_id ] ) ) {
			return $wp_registered_sidebars[ $sidebar_id ]['name'];
		}

	}
}
libs/better-framework/functions/shortcodes.php000064400000020175151214002400015645 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_shortcode_show_title' ) ) {
	/**
	 * Used to show shortcodes heading in standard way!
	 * You can redefine this function or use 'better-framework/shortcodes/title' filter
	 * for changing values.
	 *
	 * @param array $atts
	 *
	 * @since 2.5.5
	 *
	 * @return string
	 */
	function bf_shortcode_show_title( $atts = array() ) {

		if ( isset( $atts['show_title'] ) && $atts['show_title'] == false ) {
			return;
		}

		if ( isset( $atts['hide_title'] ) && $atts['hide_title'] == true ) {
			return;
		}

		if ( empty( $atts['title'] ) ) {
			return;
		}

		if ( bf_get_current_sidebar() && bf_get_current_sidebar() !== 'bs-vc-sidebar-column' ) {
			return;
		}

		$result = apply_filters( 'better-framework/shortcodes/title', $atts );

		if ( is_string( $result ) ) {
			echo $result; // escaped before
		}

	}
}


if ( ! function_exists( 'bf_shortcode_custom_css_prop' ) ) {
	/**
	 * @param        $css
	 * @param        $prop_name
	 * @param string $default
	 *
	 * @return string
	 *
	 * @since 2.5.2
	 */
	function bf_shortcode_custom_css_prop( $css, $prop_name, $default = '' ) {

		preg_match( '/' . $prop_name . ':([^!]*)/', $css, $css );

		if ( ! empty( $css[1] ) ) {
			return trim( $css[1] );
		}

		return $default;
	}
}


if ( ! function_exists( 'bf_shortcode_custom_css_class' ) ) {
	/**
	 * Custom function used to get custom css class name form VC/Shortcode css atribute
	 *
	 * @param        $param_value
	 * @param string $prefix
	 * @param string $css_key
	 *
	 * @return string
	 *
	 * @since 2.5.2
	 */
	function bf_shortcode_custom_css_class( $param_value, $prefix = '', $css_key = 'css' ) {

		$css_class = '';

		// prepare field
		if ( is_array( $param_value ) && ! empty( $param_value[ $css_key ] ) ) {
			$param_value = $param_value[ $css_key ];
		} else {
			return $css_class;
		}

		if ( is_string( $param_value ) ) {
			$css_class = preg_match( '/\s*\.([^\{]+)\s*\{\s*([^\}]+)\s*\}\s*/', $param_value ) ? $prefix . preg_replace( '/\s*\.([^\{]+)\s*\{\s*([^\}]+)\s*\}\s*/', '$1', $param_value ) : '';
		}

		return $css_class;
	}
}


if ( ! function_exists( 'bf_vc_edit_form_classes' ) ) {
	/**
	 * Filter: vc_edit_form_class
	 * Description: add some class to visual composer edit form. used in admin-scripts.js setup_interactive_fields_for_vc() method
	 *
	 * @see setup_interactive_fields_for_vc method on `Better_Framework` JS Object
	 *
	 * @param array $classes
	 * @param array $atts
	 * @param array $params
	 *
	 * @return mixed
	 */
	function bf_vc_edit_form_classes( $classes, $atts, $params ) {

		$added_fields      = array();
		$interactive_added = false;
		foreach ( $params as $param ) {
			if ( ! empty( $param['show_on'] ) ) {
				if ( ! $interactive_added ) {
					array_push( $classes, 'bf-interactive-fields', 'bf-has-filters' );
					$interactive_added = true;
				}

				foreach ( (array) $param['show_on'] as $conditions ) {
					foreach ( (array) $conditions as $condition ) {
						$field_name = explode( '=', $condition, 2 );
						$field_name = $field_name[0];
						if ( ! in_array( $field_name, $added_fields ) ) {
							array_push( $classes, 'bf-filter-field-' . $field_name );
							$added_fields[] = $field_name;
						}
					}
				}
			}
		}

		return array_unique( $classes );
	}

	add_filter( 'vc_edit_form_class', 'bf_vc_edit_form_classes', 8, 3 );
}


if ( ! function_exists( 'bf_vc_layout_state' ) ) {
	/**
	 * Returns VC Columns state
	 *
	 * @return array
	 */
	function bf_vc_layout_state() {

		global $_bf_override_vc_layout_state, $_bf_vc_column_atts, $_bf_vc_column_inner_atts, $_bf_vc_row_columns;

		if ( ! empty( $_bf_override_vc_layout_state ) ) {
			return $_bf_override_vc_layout_state; # Allow to override state value
		}

		$_bf_vc_column_atts = array_filter( (array) $_bf_vc_column_atts );
		$_bf_vc_column_atts = bf_merge_args( $_bf_vc_column_atts, array(
			'width'      => '1',
			'list'       => $_bf_vc_row_columns,
			'list_count' => $_bf_vc_row_columns ? bf_count( $_bf_vc_row_columns ) : 0,
		) );

		$_bf_vc_column_inner_atts = array_filter( (array) $_bf_vc_column_inner_atts );
		$_bf_vc_column_inner_atts = bf_merge_args( $_bf_vc_column_inner_atts, array(
			'width' => '1'
		) );

		return array(
			'column' => $_bf_vc_column_atts,
			'row'    => $_bf_vc_column_inner_atts,
		);
	}
}


add_filter( 'vc_shortcode_set_template_vc_column', 'bf_vc_column_filter' );

if ( ! function_exists( 'bf_vc_column_filter' ) ) {
	/**
	 * Callback: Handy filter to calculate columns state
	 * Filter: vc_shortcode_set_template_vc_column
	 *
	 * @param $file
	 *
	 * @return string
	 */
	function bf_vc_column_filter( $file ) {

		global $_vc_column_template_file;

		$_vc_column_template_file = $file;

		return BF_PATH . 'page-builder/compatibility/vc/vc_column.php';
	}
}


add_filter( 'vc_shortcode_set_template_vc_column_inner', 'bf_vc_column_inner_filter' );

if ( ! function_exists( 'bf_vc_column_inner_filter' ) ) {
	/**
	 * Callback: Handy filter to calculate columns state
	 * Filter: vc_shortcode_set_template_vc_column_inner
	 *
	 * @param $file
	 *
	 * @return string
	 */
	function bf_vc_column_inner_filter( $file ) {

		global $_vc_column_inner_template_file;

		$_vc_column_inner_template_file = $file;

		return BF_PATH . 'page-builder/compatibility/vc/vc_column_inner.php';
	}
}


add_filter( 'better-framework/shortcodes/design-fields', 'bf_shortcpdes_design_fields', 10, 2 );

if ( ! function_exists( 'bf_shortcpdes_design_fields' ) ) {
	/**
	 * Generates general design options for shortcodes
	 *
	 * @param array  $fields
	 * @param string $shortcode_id
	 *
	 * @return array
	 */
	function bf_shortcpdes_design_fields( $fields = array(), $shortcode_id = '' ) {

		$fields['design_tab']       = array(
			'type' => 'tab',
			'name' => __( 'Design Options', 'better-studio' ),
			'id'   => 'design_tab',
		);
		$fields['bs-show-desktop']  = array(
			"type"           => 'switchery',
			"name"           => __( 'Show on Desktop', 'better-studio' ),
			"id"             => 'bs-show-desktop',
			'section_class'  => 'style-floated-left bordered bf-css-edit-switch',
			//
			"vc_admin_label" => false,
		);
		$fields['bs-show-tablet']   = array(
			"type"           => 'switchery',
			"name"           => __( 'Show on Tablet Portrait', 'better-studio' ),
			"id"             => 'bs-show-tablet',
			'section_class'  => 'style-floated-left bordered bf-css-edit-switch',
			'group'          => __( 'Design options', 'better-studio' ),
			//
			"vc_admin_label" => false,
		);
		$fields['bs-show-phone']    = array(
			"type"           => 'switchery',
			"name"           => __( 'Show on Phone', 'better-studio' ),
			"id"             => 'bs-show-phone',
			'section_class'  => 'style-floated-left bordered bf-css-edit-switch',
			//
			"vc_admin_label" => false,
		);
		$fields['css']              = array(
			'type'           => 'css_editor',
			'name'           => __( 'CSS box', 'better-studio' ),
			'id'             => 'css',
			"vc_admin_label" => false,
		);
		$fields['custom-css-class'] = array(
			'type'           => 'text',
			'name'           => __( 'Custom CSS Class', 'better-studio' ),
			'id'             => 'custom-css-class',
			'section_class'  => 'bf-section-two-column',
			//
			'vc_admin_label' => false,
		);
		$fields['custom-id']        = array(
			'type'           => 'text',
			'name'           => __( 'Custom ID', 'better-studio' ),
			'id'             => 'custom-id',
			'value'          => '',
			'section_class'  => 'bf-section-two-column',
			//
			'vc_admin_label' => false,
		);

		return $fields;
	}
}
libs/better-framework/functions/multilingual.php000064400000017015151214002400016175 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_get_current_lang_raw' ) ) {
	/**
	 * Used for finding current language in multilingual
	 *
	 * @sine 2.0
	 *
	 * @return string
	 */
	function bf_get_current_lang_raw() {

		static $lang;

		if ( $lang ) {
			return $lang;
		}

		// WPML : https://wpml.org/
		if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {

			$lang = icl_get_current_language();

			// Fix conditions WPML is active but not setup
			if ( is_null( $lang ) ) {
				$lang = 'none';
			}

		} // xili-language : https://wordpress.org/plugins/xili-language/
		elseif ( function_exists( 'xili_curlang' ) ) {

			// Tip for separating admin language when user selects specific locale
			if ( is_admin() ) {

				// get all xili active languages
				$languages = bf_get_all_languages();

				// get current locale
				$locale = get_locale();

				foreach ( (array) $languages as $_lang ) {

					if ( $_lang['locale'] == $locale ) {
						$lang = $_lang['id'];
					}

				}

			} else {
				$lang = xili_curlang();
			}

			if ( empty( $lang ) ) {
				$lang = 'all';
			}
		} // qTranslate : http://www.qianqin.de/qtranslate/
		elseif ( function_exists( 'qtrans_getLanguage' ) ) {
			$lang = qtrans_getLanguage();
		} // WPGlobe : http://www.wpglobus.com/
		elseif ( class_exists( 'WPGlobus' ) ) {

			// Tip for separating admin language when user selects specific locale
			if ( is_admin() ) {

				// get all xili active languages
				$languages = bf_get_all_languages();

				// get current locale
				$locale = get_locale();

				foreach ( (array) $languages as $_lang ) {

					if ( $_lang['locale'] == $locale ) {
						$lang = $_lang['id'];
					}

				}

			} else {
				$lang = WPGlobus::Config()->language;
			}

		} // Polylang : https://wordpress.org/plugins/polylang/
		elseif ( function_exists( 'pll_languages_list' ) ) {
			$lang = pll_current_language();

			$langs_list = pll_languages_list();

			// Fix conditions Polylang is active but not setup
			if ( ! $langs_list ) {
				$lang = 'none';
			} elseif ( $lang == false ) {
				$lang = 'all';
			}

		} else {
			$lang = 'none';
		}

		return $lang;
	}
}


if ( ! function_exists( 'bf_get_current_lang' ) ) {
	/**
	 * Used for finding current language in multilingual
	 *
	 * @sine 2.0
	 *
	 * @return string
	 */
	function bf_get_current_lang() {

		$lang = bf_get_current_lang_raw();

		// Default language is en!
		if ( $lang == 'en' ) {
			$lang = 'none';
		}

		return $lang;
	}
}


if ( ! function_exists( 'bf_get_all_languages' ) ) {
	/**
	 * Returns all active multilingual languages
	 *
	 * @since 2.0
	 *
	 * @return array
	 */
	function bf_get_all_languages() {

		$languages = array();

		// WPML : https://wpml.org/
		if ( defined( 'ICL_SITEPRESS_VERSION' ) ) {

			global $sitepress;

			// get filtered active language informations
			$temp_lang = icl_get_languages( 'skip_missing=1' );

			foreach ( $temp_lang as $lang ) {

				// Get language raw data from DB
				$_lang = $sitepress->get_language_details( $lang['language_code'] );

				$languages[] = array(
					'id'     => $lang['language_code'],
					'name'   => $_lang['english_name'], // english display name
					'flag'   => $lang['country_flag_url'],
					'locale' => $lang['default_locale'],
				);

			}

		} // xili-language : https://wordpress.org/plugins/xili-language/
		elseif ( function_exists( 'xili_curlang' ) ) {

			global $xili_language;

			$languages = array();

			foreach ( (array) $xili_language->get_listlanguages() as $lang ) {

				$desc = unserialize( $lang->description );

				$languages[] = array(
					'id'     => $lang->slug,
					'name'   => $lang->name,
					'flag'   => '',
					'locale' => $desc['locale'],
				);

			}

		} // qTranslate : http://www.qianqin.de/qtranslate/
		elseif ( function_exists( 'qtrans_getLanguage' ) ) {

			global $q_config;

			$languages = array();

			foreach ( (array) $q_config['enabled_languages'] as $lang ) {

				$languages[] = array(
					'id'     => $lang,
					'name'   => $q_config['language_name'][ $lang ],
					'flag'   => trailingslashit( WP_CONTENT_URL ) . $q_config['flag_location'] . $q_config['flag'][ $lang ],
					'locale' => $q_config['locale'][ $lang ],
				);

			}

		} // WPGlobe : http://www.wpglobus.com/
		elseif ( class_exists( 'WPGlobus' ) ) {

			$_languages = WPGlobus::Config()->enabled_languages;

			foreach ( (array) $_languages as $lang ) {

				$languages[] = array(
					'id'     => $lang,
					'name'   => WPGlobus::Config()->en_language_name[ $lang ], // english display name
					'flag'   => WPGlobus::Config()->flags_url . WPGlobus::Config()->flag[ $lang ],
					'locale' => WPGlobus::Config()->locale[ $lang ],
				);
			}

		} // Polylang : https://wordpress.org/plugins/polylang/
		elseif ( function_exists( 'pll_languages_list' ) ) {

			$_languages = pll_languages_list( array( 'fields' => 'locale' ) );

			foreach ( (array) $_languages as $_lang ) {

				//get_language
				global $polylang;

				$_raw_lang = $polylang->model->get_language( $_lang );

				$languages[] = array(
					'id'     => $_raw_lang->slug,
					'name'   => $_raw_lang->name, // english display name
					'flag'   => $_raw_lang->flag_url,
					'locale' => $_raw_lang->locale,
				);
			}

		}

		return $languages;

	}
}


if ( ! function_exists( 'bf_get_language_data' ) ) {
	/**
	 * Returns multilingual language information
	 *
	 * @since 2.0
	 *
	 * @param null $lang
	 *
	 * @return array
	 */
	function bf_get_language_data( $lang = null ) {

		$output = array(
			'id'     => '',
			'name'   => '',
			'flag'   => '',
			'locale' => '',
		);

		if ( is_null( $lang ) ) {
			return $output;
		}

		$languages = bf_get_all_languages();

		foreach ( $languages as $_language ) {

			if ( $_language['id'] == $lang ) {

				$output = $_language;

			}

		}

		return $output;

	}
}


if ( ! function_exists( 'bf_get_language_name' ) ) {
	/**
	 * Returns multilingual language name from ID
	 *
	 * @since 2.0
	 *
	 * @param null $lang
	 *
	 * @return array
	 */
	function bf_get_language_name( $lang = null ) {

		$lang = bf_get_language_data( $lang );

		if ( isset( $lang['name'] ) ) {
			return $lang['name'];
		}

		return '';
	}
}


if ( ! function_exists( 'bf_get_current_language_option_code' ) ) {
	/**
	 * Returns multilingual language option id that starts with _
	 * ex: _fa
	 * for english and all language code returns empty
	 *
	 * @since 2.3
	 *
	 * @return array
	 */
	function bf_get_current_language_option_code( $lang = null ) {

		static $_lang;

		// for special codes that passes the lang
		if ( ! is_null( $lang ) ) {

			$lang = bf_get_current_lang();

			if ( $lang == 'none' || $lang == 'all' ) {
				$lang = '';
			} else {
				$lang = '_' . $lang;
			}

			return $lang;
		}

		// from cache
		if ( $_lang ) {
			return $_lang;
		}

		$_lang = bf_get_current_lang();

		if ( $_lang == 'none' || $_lang == 'all' ) {
			$_lang = '';
		} else {
			$_lang = '_' . $_lang;
		}

		return $_lang;
	}
}libs/better-framework/functions/path.php000064400000006725151214002400014431 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Handy functions for making development quicker in getting addresses.
 *
 * @package    BetterFramework
 * @author     BetterStudio <info@betterstudio.com>
 * @copyright  Copyright (c) 2015, BetterStudio
 */


if ( ! function_exists( 'bf_get_dir' ) ) {
	/**
	 * Get BetterFramework directory path
	 *
	 * @param string $append
	 *
	 * @return string
	 */
	function bf_get_dir( $append = '' ) {

		return BF_PATH . $append;
	}
}


if ( ! function_exists( 'bf_require' ) ) {
	/**
	 * Used to require file inside BetterFramework
	 *
	 * @param string $append
	 *
	 * @return string
	 */
	function bf_require( $append = '' ) {

		require BF_PATH . $append;
	}
}


if ( ! function_exists( 'bf_require_once' ) ) {
	/**
	 * Used to require_once file inside BetterFramework
	 *
	 * @param string $append
	 *
	 * @return string
	 */
	function bf_require_once( $append = '' ) {

		require_once BF_PATH . $append;
	}
}


if ( ! function_exists( 'bf_get_uri' ) ) {
	/**
	 * Get BetterFramework directory URI (URL)
	 *
	 * @param string $append
	 *
	 * @return string
	 */
	function bf_get_uri( $append = '' ) {

		return BF_URI . $append;
	}
}


if ( ! function_exists( 'bf_get_theme_dir' ) ) {
	/**
	 * Parent theme directory.
	 *
	 * @param string $append
	 *
	 * @return string
	 */
	function bf_get_theme_dir( $append = '' ) {

		static $directory;

		if ( ! $directory ) {
			$directory = get_template_directory() . '/';
		}

		return $directory . $append;
	}
}


if ( ! function_exists( 'bf_get_theme_uri' ) ) {
	/**
	 * Parent theme directory URI.
	 *
	 * @param string $append
	 *
	 * @return string
	 */
	function bf_get_theme_uri( $append = '' ) {

		static $uri;

		if ( ! $uri ) {
			$uri = get_template_directory_uri() . '/';
		}

		return $uri . $append;
	}
}


if ( ! function_exists( 'bf_get_child_theme_dir' ) ) {
	/**
	 * Child theme directory.
	 *
	 * @param string $append
	 *
	 * @return string
	 */
	function bf_get_child_theme_dir( $append = '' ) {

		static $directory;

		if ( ! $directory ) {
			$directory = get_stylesheet_directory() . '/';
		}

		return $directory . $append;
	}
}


if ( ! function_exists( 'bf_get_child_theme_uri' ) ) {
	/**
	 * Child theme directory URI.
	 *
	 * @param string $append
	 *
	 * @return string
	 */
	function bf_get_child_theme_uri( $append = '' ) {

		static $uri;

		if ( ! $uri ) {
			$uri = get_stylesheet_directory_uri() . '/';
		}

		return $uri . $append;
	}
}


if ( ! function_exists( 'bf_basename' ) ) {
	/**
	 * Fixes basename functionality when file name start with an accent
	 * https://stackoverflow.com/questions/32115609/basename-fail-when-file-name-start-by-an-accent
	 *
	 * @param $url
	 *
	 * @return mixed
	 */
	function bf_basename( $url ) {

		$file_name = explode( '/', $url );

		return end( $file_name );
	}
}libs/better-framework/functions/query.php000064400000063725151214002400014645 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_get_pages' ) ) {
	/**
	 * Get Pages
	 *
	 * @param array $extra Extra Options.
	 *
	 * @since 2.3
	 *
	 * @return array
	 */
	function bf_get_pages( $extra = array() ) {

		/*
			Extra Usage:

			array(
				'sort_order'        =>  'ASC',
				'sort_column'       =>  'post_title',
				'hierarchical'      =>  1,
				'exclude'           =>  '',
				'include'           =>  '',
				'meta_key'          =>  '',
				'meta_value'        =>  '',
				'authors'           =>  '',
				'child_of'          =>  0,
				'parent'            =>  -1,
				'exclude_tree'      =>  '',
				'number'            =>  '',
				'offset'            =>  0,
				'post_type'         =>  'page',
				'post_status'       =>  'publish'
			)

		*/

		if ( ! empty( $extra['advanced-label'] ) ) {
			$advanced_label = true;
			unset( $extra['advanced-label'] );

			if ( 'page' == get_option( 'show_on_front' ) && get_option( 'page_on_front' ) ) {
				$front_page = get_option( 'page_on_front' );
			} else {
				$front_page = - 1;
			}
		} else {
			$advanced_label = false;
			$front_page     = - 1;
		}

		$output = array();

		if ( empty( $extra['post_type'] ) ) {
			$extra['post_type'] = 'page';
		}

		$query = get_posts( $extra );

		foreach ( $query as $page ) {

			/** @var WP_Post $page */

			if ( $advanced_label ) {

				$append = '';

				if ( $page->post_status === 'private' ) {
					$append .= '(' . __( 'Private', 'better-studio' ) . ')';
				} elseif ( $page->post_status === 'draft' ) {
					$append .= '(' . __( 'Draft', 'better-studio' ) . ')';
				}

				if ( $page->ID == $front_page ) {
					$append .= '(' . __( 'Front Page', 'better-studio' ) . ')';
				}

				if ( ! empty( $append ) ) {
					$output[ $page->ID ] = $page->post_title . ' - ' . $append;
				} else {
					$output[ $page->ID ] = $page->post_title;
				}

			} else {
				$output[ $page->ID ] = $page->post_title;
			}
		}

		return $output;

	} // bf_get_pages
} // if


if ( ! function_exists( 'bf_get_posts' ) ) {

	/**
	 * Get Posts
	 *
	 * @param array $extra Extra Options.
	 *
	 * @since 2.3
	 *
	 * @return array
	 */
	function bf_get_posts( $extra = array() ) {

		/*
			Extra Usage:

			array(
				'posts_per_page'  => 5,
				'offset'          => 0,
				'category'        => '',
				'orderby'         => 'post_date',
				'order'           => 'DESC',
				'include'         => '',
				'exclude'         => '',
				'meta_key'        => '',
				'meta_value'      => '',
				'post_type'       => 'post',
				'post_mime_type'  => '',
				'post_parent'     => '',
				'post_status'     => 'publish',
				'suppress_filters' => true
			)
		*/

		$output = array();

		$query = get_posts( $extra );

		foreach ( $query as $post ) {
			$output[ $post->ID ] = $post->post_title;
		}

		return $output;

	} // bf_get_posts

} // if


if ( ! function_exists( 'bf_get_random_post_link' ) ) {
	/**
	 * Get an link for a random post
	 *
	 * @param bool $echo
	 *
	 * @return bool|string
	 */
	function bf_get_random_post_link( $echo = true ) {

		$query = new WP_Query(
			array(
				'orderby'        => 'rand',
				'posts_per_page' => '1'
			)
		);

		if ( $echo ) {
			echo get_permalink( $query->posts[0] ); // escaped before inside WP Core
		} else {
			return get_permalink( $query->posts[0] );
		}

	} // bf_get_random_post_link
} // if


if ( ! function_exists( 'bf_get_categories' ) ) {
	/**
	 * Get categories
	 *
	 * @param array $extra Extra Options.
	 *
	 * @since 1.0
	 * @return array
	 */
	function bf_get_categories( $extra = array() ) {

		/*
			Extra Usage:

			array(
				'type'          => 'post',
				'child_of'      => 0,
				'parent'        => '',
				'orderby'       => 'name',
				'order'         => 'ASC',
				'hide_empty'    => 1,
				'hierarchical'  => 1,
				'exclude'       => '',
				'include'       => '',
				'number'        => '',
				'taxonomy'      => 'category',
				'pad_counts'    => false
			)
		*/

		$output = array();

		$query = get_categories( $extra );

		foreach ( $query as $cat ) {
			$output[ $cat->cat_ID ] = $cat->name;
		}

		return $output;

	} // bf_get_categories
} // if


if ( ! function_exists( 'bf_get_categories_by_slug' ) ) {
	/**
	 * Get categories
	 *
	 * @param array $extra Extra Options.
	 *
	 * @since 1.0
	 * @return array
	 */
	function bf_get_categories_by_slug( $extra = array() ) {

		/*
			Extra Usage:

			array(
				'type'          => 'post',
				'child_of'      => 0,
				'parent'        => '',
				'orderby'       => 'name',
				'order'         => 'ASC',
				'hide_empty'    => 1,
				'hierarchical'  => 1,
				'exclude'       => '',
				'include'       => '',
				'number'        => '',
				'taxonomy'      => 'category',
				'pad_counts'    => false
			)
		*/

		$output = array();

		$query = get_categories( $extra );

		foreach ( $query as $cat ) {
			$output[ $cat->slug ] = $cat->name;
		}

		return $output;

	} // bf_get_categories_by_slug
} // if


if ( ! function_exists( 'bf_get_tags' ) ) {
	/**
	 * Get Tags
	 *
	 * @param array $extra Extra Options.
	 *
	 * @since 1.0
	 * @return mixed
	 */
	function bf_get_tags( $extra = array() ) {

		$output = array();
		$query  = get_tags( $extra );

		foreach ( $query as $tag ) {
			$output[ $tag->term_id ] = $tag->name;
		}

		return $output;

	} // bf_get_tags
} // if


if ( ! function_exists( 'bf_get_users' ) ) {
	/**
	 * Get users
	 *
	 * @param array      $extra           Extra Options.
	 * @param array|bool $advanced_output Advanced Query is the results with query other resutls
	 *
	 * @since 1.0
	 * @return array
	 */
	function bf_get_users( $extra = array(), $advanced_output = false ) {

		$output = array();

		$extra = bf_merge_args(
			$extra,
			array(
				'orderby' => 'post_count',
				'order'   => 'DESC'
			)
		);

		$advanced_label = isset( $extra['advanced-label'] ) && $extra['advanced-label'];

		if ( $advanced_label ) {

			$current_user = wp_get_current_user();
		}

		$query = new WP_User_Query( $extra );

		foreach ( $query->results as $user ) {

			if ( $advanced_label ) {

				$label = $user->data->display_name . " ({$user->data->user_login})";

				if ( $user->data->ID === $current_user->get( 'ID' ) ) {
					$label = __( 'Me: ', 'better-studio' ) . $label;
				}

				$output[ $user->data->ID ] = $label;
			} else {
				$output[ $user->data->ID ] = $user->data->display_name;
			}
		}

		if ( $advanced_output ) {
			// Unset the result for make free the memory
			unset( $query->results );

			return array( $output, $query );
		}

		return $output;

	} // bf_get_users
} // if


if ( ! function_exists( 'bf_get_post_types' ) ) {
	/**
	 * Get Post Types
	 *
	 * @param array $extra Extra Options.
	 *
	 * @since 1.0
	 * @return array
	 */
	function bf_get_post_types( $extra = array() ) {

		$output = array();

		if ( ! isset( $extra['exclude'] ) || ! is_array( $extra['exclude'] ) ) {
			$extra['exclude'] = array();
		}

		// Add revisions, nave menu and attachment post types to excludes
		$extra['exclude'] = array_merge( $extra['exclude'], array( 'revision', 'nav_menu_item', 'attachment' ) );

		$query = get_post_types();

		foreach ( $query as $key => $val ) {

			if ( in_array( $key, $extra['exclude'] ) ) {
				continue;
			}

			$output[ $key ] = ucfirst( $val );
		}

		return $output;

	} // bf_get_post_types
} // if


if ( ! function_exists( 'bf_get_page_templates' ) ) {
	/**
	 * Get Page Templates
	 *
	 * @param array $extra Extra Options.
	 *
	 * @since 1.0
	 * @return mixed
	 */
	function bf_get_page_templates( $extra = array() ) {

		$output = array();

		if ( ! isset( $extra['exclude'] ) || ! is_array( $extra['exclude'] ) ) {
			$extra['exclude'] = array();
		}

		$query = wp_get_theme()->get_page_templates();

		foreach ( $query as $key => $val ) {

			if ( in_array( $key, $extra['exclude'] ) ) {
				continue;
			}

			$output[ $key ] = $val;
		}

		return $output;

	} // bf_get_page_templates
} // if


if ( ! function_exists( 'bf_get_taxonomies' ) ) {
	/**
	 * Get Taxonomies
	 *
	 * @param array $extra Extra Options.
	 *
	 * @since 1.0
	 * @return array
	 */
	function bf_get_taxonomies( $extra = array() ) {

		$output = array();

		$query = get_taxonomies();

		if ( ! isset( $extra['exclude'] ) || ! is_array( $extra['exclude'] ) ) {
			$extra['exclude'] = array();
		}

		foreach ( $query as $key => $val ) {

			if ( in_array( $key, $extra['exclude'] ) ) {
				continue;
			}

			$output[ $key ] = ucfirst( str_replace( '_', ' ', $val ) );
		}

		return $output;

	} // bf_get_taxonomies
} // if


if ( ! function_exists( 'bf_get_terms' ) ) {
	/**
	 * Get All Terms of Specific Taxonomy
	 *
	 * @param array|string $tax   Taxonomy Slug
	 * @param array        $extra Extra Options.
	 *
	 * @since 1.0
	 * @return array
	 */
	function bf_get_terms( $tax = 'category', $extra = array() ) {

		if ( ! isset( $extra['exclude'] ) || ! is_array( $extra['exclude'] ) ) {
			$extra['exclude'] = array();
		}

		$query  = get_terms( $tax, $extra );
		$output = array();

		foreach ( $query as $taxonomy ) {

			if ( in_array( $taxonomy->slug, $extra['exclude'] ) ) {
				continue;
			}

			$output[ $taxonomy->slug ] = $taxonomy->name;
		}

		return $output;

	} // bf_get_terms
}// if


if ( ! function_exists( 'bf_get_roles' ) ) {
	/**
	 * Get Roles
	 *
	 * @param array $extra Extra Options.
	 *
	 * @since 1.0
	 * @return array
	 */
	function bf_get_roles( $extra = array() ) {

		global $wp_roles;

		$output = array();

		if ( ! isset( $extra['exclude'] ) || ! is_array( $extra['exclude'] ) ) {
			$extra['exclude'] = array();
		}

		foreach ( $wp_roles->roles as $key => $val ) {

			if ( in_array( $key, $extra['exclude'] ) ) {
				continue;
			}

			$output[ $key ] = $val['name'];
		}

		return $output;

	} // bf_get_roles
} // if


if ( ! function_exists( 'bf_get_menus' ) ) {
	/**
	 * Get Menus
	 *
	 * @param bool $hide_empty
	 *
	 * @since 1.0
	 * @return array
	 */
	function bf_get_menus( $hide_empty = false ) {

		$output = array();

		$menus = get_terms( 'nav_menu', array( 'hide_empty' => $hide_empty ) );

		foreach ( $menus as $menu ) {
			$output[ $menu->term_id ] = $menu->name;
		}

		return $output;

	} // bf_get_menus
} // if

if ( ! function_exists( 'bf_is_a_category' ) ) {
	/**
	 * Used to detect category from id
	 *
	 * todo: change the algorithm
	 *
	 * @param null $id
	 *
	 * @return bool|mixed
	 */
	function bf_is_a_category( $id = null ) {

		if ( is_null( $id ) ) {
			return false;
		}

		$cat = get_category( $id );

		if ( $cat && ! is_wp_error( $cat ) ) {
			return current( $cat );
		} else {
			return false;
		}

	}// bf_is_a_category
} // if


if ( ! function_exists( 'bf_is_a_tag' ) ) {
	/**
	 * Used to detect tag from id
	 *
	 * todo: change the algorithm
	 *
	 * @param null $id
	 *
	 * @return bool|mixed
	 */
	function bf_is_a_tag( $id = null ) {

		if ( is_null( $id ) ) {
			return false;
		}

		$tag = get_tag( $id );

		if ( $tag && ! is_wp_error( $tag ) ) {
			return current( $tag );
		} else {
			return false;
		}

	} // bf_is_a_tag
} // if


if ( ! function_exists( 'bf_get_rev_sliders' ) ) {
	/**
	 * Used to find list of all RevolutionSlider Sliders.zip
	 *
	 * @return array
	 */
	function bf_get_rev_sliders() {

		if ( ! class_exists( 'RevSlider' ) ) {
			return array();
		}

		try {

			$slider = new RevSlider();

			return $slider->getArrSlidersShort();

		} catch( Exception $e ) {
			return array();
		}

	} // bf_get_rev_sliders
} // if


if ( ! function_exists( 'bf_get_wp_query_vars' ) ) {
	/**
	 * Creats flatted and valid query_vars from an instance of WP_Query object
	 *
	 * @param WP_Query $wp_query
	 *
	 * @return array
	 */
	function bf_get_wp_query_vars( $wp_query ) {

		if ( ! is_a( $wp_query, 'WP_Query' ) ) {
			return array();
		}

		$args = $wp_query->query_vars;

		// remove empty vars
		foreach ( $args as $_a => $_v ) {
			if ( is_array( $_v ) ) {
				if ( count( $_v ) === 0 ) {
					unset( $args[ $_a ] );
				}
			} else {
				if ( empty( $_v ) || $_v === 0 ) {
					unset( $args[ $_a ] );
				}
			}
		}

		// Remove extra vars
		unset( $args['suppress_filters'] );
		unset( $args['cache_results'] );
		unset( $args['update_post_term_cache'] );
		unset( $args['update_post_meta_cache'] );
		unset( $args['comments_per_page'] );
		unset( $args['no_found_rows'] );
		unset( $args['search_orderby_title'] );

		// create tax query
		if ( ! empty( $args['tax_query']['queries'] ) ) {
			$args['tax_query'] = $args['tax_query']['queries'];
		}

		return $args;

	} // bf_get_wp_query_vars
} // if


if ( ! function_exists( 'bf_get_wp_query_total_pages' ) ) {
	/**
	 * Calculates query total pages with support of offset and custom posts per page
	 *
	 * @param WP_Query $wp_query
	 * @param int      $offset
	 * @param int      $posts_per_page
	 * @param bool     $use_query_offset
	 *
	 * @return float|int
	 */
	function bf_get_wp_query_total_pages( &$wp_query, $offset = 0, $posts_per_page = 0, $use_query_offset = true ) {

		$offset = intval( $offset );

		$posts_per_page = intval( $posts_per_page );
		if ( $posts_per_page <= 0 ) {
			$posts_per_page = $wp_query->get( 'posts_per_page' );

			if ( $posts_per_page <= 0 ) {
				$posts_per_page = $wp_query->get( 'showposts' );
			}
		}

		// use the query offset if it was set
		if ( $use_query_offset && $offset <= 0 ) {

			if ( ! $offset = $wp_query->get( 'original_offset' ) ) { # original_offset is our custom name
				$offset = $wp_query->get( 'offset' );
			}

			$offset = intval( $offset );
		}

		if ( $offset > 0 && empty( $wp_query->_bs_optimization['found-rows'] ) && $posts_per_page > 0 ) {
			$total = ceil( ( $wp_query->found_posts - $offset ) / $posts_per_page );
		} else {
			$total = $wp_query->max_num_pages;
		}

		return $total;
	}
}

if ( ! function_exists( 'bf_get_comment_query_total_pages' ) ) {
	/**
	 * Calculates query total pages with support of offset and custom posts per page
	 *
	 * @param WP_Comment_Query $cm_query
	 * @param int              $offset
	 * @param int              $posts_per_page
	 * @param bool             $use_query_offset
	 *
	 * @return float|int
	 */
	function bf_get_comment_query_total_pages( &$cm_query, $offset = 0, $posts_per_page = 0, $use_query_offset = true ) {

		$offset = intval( $offset );


		$posts_per_page = intval( $posts_per_page );
		if ( $posts_per_page <= 0 ) {
			$posts_per_page = $cm_query->query_vars['number'];
		}

		// use the query offset if it was set
		if ( $use_query_offset && $offset <= 0 ) {
			$offset = $cm_query->query_vars['offset'];
		}


		if ( $offset > 0 && $posts_per_page > 0 ) {
			$total = ceil( ( $cm_query->found_comments - $offset ) / $posts_per_page );
		} else {
			$total = $cm_query->max_num_pages;
		}

		return $total;
	}
}


if ( ! function_exists( 'bf_get_child_categories' ) ) {
	/**
	 * Gets category child or siblings if enabled
	 *
	 * @param null $term        Term object or ID
	 * @param int  $limit       Number of cats
	 * @param bool $or_siblings Return siblings if there is nor child
	 *
	 * @return array
	 */
	function bf_get_child_categories( $term = null, $limit = - 1, $or_siblings = false ) {

		if ( ! $term ) {
			return array();
		} elseif ( is_int( $term ) || is_string( $term ) ) {
			$term = get_term( $term, 'category' );
			if ( ! $term || is_wp_error( $term ) ) {
				return array();
			}
		} elseif ( is_object( $term ) && ! is_a( $term, 'WP_Term' ) ) {
			return array();
		}

		// fix limit number for get_categories
		if ( $limit === - 1 ) {
			$limit = 0;
		}

		$cat_args = array(
			'parent'     => $term->term_id,
			'hide_empty' => 0,
			'number'     => $limit === - 1 ? 0 : $limit
		);

		// Get child categories
		$child_categories = get_categories( $cat_args );

		// Get sibling cats if there is no child category
		if ( ( empty( $child_categories ) || is_wp_error( $child_categories ) ) && $or_siblings ) {
			$child_categories = bf_get_sibling_categories( $term, $limit );
		}

		return $child_categories;

	} // bf_get_child_categories
} // if


if ( ! function_exists( 'bf_get_sibling_categories' ) ) {
	/**
	 * Gets category siblings
	 *
	 * @param null $term  Term object or ID
	 * @param int  $limit Number of cats
	 *
	 * @return array
	 */
	function bf_get_sibling_categories( $term = null, $limit = - 1 ) {

		if ( ! $term ) {
			return array();
		} elseif ( is_int( $term ) || is_string( $term ) ) {
			$term = get_term( $term, 'category' );
			if ( ! $term || is_wp_error( $term ) ) {
				return array();
			}
		} elseif ( is_object( $term ) && ! is_a( $term, 'WP_Term' ) ) {
			return array();
		}

		// fix limit number
		if ( $limit === - 1 ) {
			$limit = 0;
		}

		$cat_args = array(
			'parent'     => $term->parent,
			'hide_empty' => 0,
			'number'     => $limit === - 1 ? 0 : $limit,
			'exclude'    => $term->term_id,
		);

		$child_categories = get_categories( $cat_args );

		return $child_categories;

	} // bf_get_sibling_categories
} // if


if ( ! function_exists( 'bf_get_term_posts_count' ) ) {

	/**
	 * Returns count of all posts of category
	 *
	 * @param null  $term_id
	 * @param array $args
	 *
	 * @return int
	 */
	function bf_get_term_posts_count( $term_id = null, $args = array() ) {

		if ( is_null( $term_id ) ) {
			return 0;
		}

		$args = bf_merge_args( $args, array(
			'include_childs' => false,
			'post_type'      => 'post',
			'taxonomy'       => 'category',
			'term_field'     => 'term_id',
		) );


		// simple term posts count using get_term, this will work quicker because of WP Cache
		// but this is not real post count, because this wouldn't count sub terms posts count in hierarchical taxonomies
		if ( ! is_taxonomy_hierarchical( $args['taxonomy'] ) || ! $args['include_childs'] ) {

			$term = get_term( get_queried_object()->term_id, $args['taxonomy'] );

			if ( ! is_wp_error( $term ) ) {
				return $term->count;
			} else {
				return 0;
			}

		} // Real term posts count in hierarchical taxonomies
		else {

			$query = new WP_Query( array(
				'post_type'      => $args['post_type'],
				'tax_query'      => array(
					array(
						'taxonomy' => $args['taxonomy'],
						'field'    => $args['term_field'],
						'terms'    => $term_id,
					),
				),
				'posts_per_page' => 1,
				'fields'         => 'ids',
			) );
			return $query->found_posts;
		}

	} // bf_get_term_posts_count
}

if ( ! function_exists( 'bf_get_term_childs' ) ) {

	/**
	 * Retrieves children of terms as Term IDs - Except the excludes ones
	 *
	 * @param array  $include  List of term_id to include
	 * @param string $taxonomy Term taxonomy
	 * @param array  $exclude  List of term_id to exclude
	 *
	 * @return array
	 */
	function bf_get_term_childs( $include, $exclude = array(), $taxonomy = 'category' ) {

		$hierarchy_struct = _get_term_hierarchy( $taxonomy );
		$parents_ID       = array_keys( $hierarchy_struct );

		$includes_list = array();

		if ( $include ) {
			_bs_get_term_childs( $include, $hierarchy_struct, $exclude, $includes_list );
		}


		$parents = array();
		do {

			$_parents = $parents;
			$parents  = array_intersect(
				$includes_list,
				$parents_ID
			);
			_bs_get_term_childs( $parents, $hierarchy_struct, $exclude, $includes_list );

		} while( sizeOf( $_parents ) !== sizeOf( $parents ) );

		return $includes_list;
	}


	function _bs_get_term_childs( $terms_id, $hierarchy_struct, $exclude, &$includes_list ) {

		foreach ( $terms_id as $maybe_parent ) {
			$includes_list[] = $maybe_parent;

			if ( isset( $hierarchy_struct[ $maybe_parent ] ) ) {

				$includes_list = array_merge( array_diff( $hierarchy_struct[ $maybe_parent ], $exclude ), $includes_list );
				#$exclude_list = array_merge( array_intersect( $exclude, $hierarchy_struct[ $maybe_parent ] ), $exclude_list ); // List of childrens ID to exclude
			}

		}

		$includes_list = array_unique( $includes_list );
		#$exclude_list  = array_unique( $exclude_list );
	}
}


if ( ! function_exists( 'bf_taxonomy_supports_post_type' ) ) {
	/**
	 * Checks taxonomy to make sure that was added to a post type
	 *
	 * @param $taxonomy
	 * @param $post_type
	 *
	 * @return bool|mixed
	 */
	function bf_taxonomy_supports_post_type( $taxonomy, $post_type ) {

		static $supports;

		if ( is_null( $supports ) ) {
			$supports = array();
		}

		if ( isset( $supports[ $post_type ] ) ) {
			return $supports[ $post_type ];
		}

		global $wp_taxonomies;

		if ( empty( $wp_taxonomies[ $taxonomy ]->object_type ) ) {
			return $supports[ $post_type ] = false;
		}

		return $supports[ $post_type ] = in_array( $post_type, $wp_taxonomies[ $taxonomy ]->object_type );

	}
}


if ( ! function_exists( 'bf_get_post_attached_media' ) ) {
	/**
	 * Retrieves media attached to the passed post.
	 *
	 * @since 2.8.11
	 *
	 * @param string      $type Mime type.
	 * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post.
	 * @param array       $args
	 *
	 * @return array Found attachments.
	 */
	function bf_get_post_attached_media( $type, $post = 0, $args = array() ) {

		if ( ! $post = get_post( $post ) ) {
			return array();
		}

		$args = bf_merge_args( $args, array(
			'post_parent'    => $post->ID,
			'post_type'      => 'attachment',
			'post_mime_type' => $type,
			'posts_per_page' => - 1,
			'orderby'        => 'menu_order',
			'order'          => 'ASC',
		) );


		/**
		 * Filters arguments used to retrieve media attached to the given post.
		 *
		 * @since 3.6.0
		 *
		 * @param array  $args Post query arguments.
		 * @param string $type Mime type of the desired media.
		 * @param mixed  $post Post ID or object.
		 */
		$args = apply_filters( 'get_attached_media_args', $args, $type, $post );

		$children = get_children( $args );

		/**
		 * Filters the list of media attached to the given post.
		 *
		 * @since 3.6.0
		 *
		 * @param array  $children Associative array of media attached to the given post.
		 * @param string $type     Mime type of the media desired.
		 * @param mixed  $post     Post ID or object.
		 */
		return (array) apply_filters( 'get_attached_media', $children, $type, $post );
	}
}

if ( ! function_exists( 'bf_get_post_primary_cat' ) ) {
	/**
	 * Returns post main category object
	 *
	 * @param bool $post_id
	 *
	 * @return array|mixed|null|object|\WP_Error
	 */
	function bf_get_post_primary_cat( $post_id = false ) {

		return bf_get_post_primary_term( $post_id, 'category' );
	} // bf_get_post_primary_cat
} // if


if ( ! function_exists( 'bf_get_post_primary_term' ) ) {
	/**
	 * Returns post main category object
	 *
	 * @param bool   $post_id
	 * @param string $taxonomy
	 *
	 * @return array|mixed|null|object|\WP_Error
	 */
	function bf_get_post_primary_term( $post_id = false, $taxonomy = 'category' ) {

		if ( ! $post_id ) {
			$post_id = get_the_ID();
		}

		$prim_cat = bf_get_post_meta( '_bs_primary_category', null, 'auto-detect' );

		//
		// Detect it from Yoast SEO or Publisher field
		//
		if ( $prim_cat === 'auto-detect' ) {

			// Primary category from Yoast SEO plugin
			if ( class_exists( 'WPSEO_Primary_Term' ) ) {

				$prim_cat = get_post_meta( $post_id, "_yoast_wpseo_primary_$taxonomy", true );

				if ( $prim_cat ) {

					$prim_cat = get_term( $prim_cat, $taxonomy );

					if ( ! is_wp_error( $prim_cat ) ) {
						return $prim_cat;
					}
				}
			}

		}
		//
		// specific term ID
		//
		else {

			$prim_cat = get_term( $prim_cat, $taxonomy );

			//
			// Valid term
			//
			if ( $prim_cat && ! is_wp_error( $prim_cat ) ) {
				return $prim_cat;
			}
		}

		// get all terms
		$terms = get_the_terms( $post_id, $taxonomy );

		if ( ! $terms || is_wp_error( $terms ) ) {
			return array(); // fallback -> first category
		}

		// return first term
		return current( $terms ); // // fallback -> first category
	} // bf_get_post_primary_cat
} // if


if ( ! function_exists( 'bf_get_term_link' ) ) {
	/**
	 * Retrieve term link URL.
	 *
	 * @since 1.0.0
	 * @see   get_term_link()
	 *
	 * @param int|object $term Category ID or object.
	 * @param string     $taxonomy
	 *
	 * @return string Link on success, empty string if term does not exist.
	 */
	function bf_get_term_link( $term, $taxonomy = 'category' ) {

		if ( ! is_object( $term ) ) {
			$term = (int) $term;
		}

		$term = get_term_link( $term, $taxonomy );

		if ( is_wp_error( $term ) ) {
			return '';
		}

		return $term;
	}
}

if ( ! function_exists( 'bf_get_attachment_id_by_url' ) ) {
	/**
	 * Get attachment ID of the given url
	 *
	 * @param string $url
	 * @param bool   $deep deep scan, default: false
	 *
	 * @global wpdb  $wpdb wordpress database object
	 * @since 3.0.0
	 * @return int
	 */
	function bf_get_attachment_id_by_url( $url, $deep = false ) {

		global $wpdb;

		$attachment_id = 0;

		if ( ! $deep ) {

			$results = $wpdb->get_col( 'SELECT ID FROM ' . $wpdb->posts .
			                           $wpdb->prepare( ' WHERE guid = %s LIMIT 2', $url )
			);

			if ( bf_count( $results ) === 1 ) {
				$attachment_id = intval( $results[0] );
			}

			return $attachment_id;
		}

		$dir = wp_upload_dir();
		if ( false !== strpos( $url, $dir['baseurl'] . '/' ) ) { // Is URL in uploads directory?
			$file       = basename( $url );
			$query_args = array(
				'post_type'   => 'attachment',
				'post_status' => 'inherit',
				'fields'      => 'ids',
				'meta_query'  => array(
					array(
						'value'   => $file,
						'compare' => 'LIKE',
						'key'     => '_wp_attachment_metadata',
					),
				)
			);
			$query      = new WP_Query( $query_args );
			if ( $query->have_posts() ) {
				foreach ( $query->posts as $post_id ) {
					$meta                = wp_get_attachment_metadata( $post_id );
					$original_file       = basename( $meta['file'] );
					$cropped_image_files = wp_list_pluck( $meta['sizes'], 'file' );
					if ( $original_file === $file || in_array( $file, $cropped_image_files ) ) {
						$attachment_id = $post_id;
						break;
					}
				}
			}
		}

		return $attachment_id;
	}
}libs/better-framework/functions/options.php000064400000052560151214002410015167 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_inject_panel_custom_css_fields' ) ) {
	/**
	 * Handy function for adding panel/metaboxe custom CSS fields in standard/centralized way
	 *
	 * @param            $fields $fields array by reference
	 * @param array      $args
	 */
	function bf_inject_panel_custom_css_fields( &$fields, $args = array() ) {

		$args = bf_merge_args( $args, array(
			'css'                  => true,
			'css-default'          => '',
			'css-class'            => true,
			'loop-css-class'       => false,
			'responsive'           => true,
			'responsive-group'     => 'close',
			'advanced-class'       => false,
			'advanced-class-group' => 'close',
		) );


		/**
		 *
		 * Base Tab
		 *
		 */
		$fields['_custom_css_settings'] = array(
			'name'       => __( 'Custom CSS', 'better-studio' ),
			'id'         => '_custom_css_settings',
			'type'       => 'tab',
			'icon'       => 'bsai-css3',
			'margin-top' => '20',
			'ajax-tab'   => true,
		);


		/**
		 *
		 * Custom CSS
		 *
		 */
		if ( $args['css'] ) {
			$fields['_custom_css_code'] = array(
				'name'           => __( 'Custom CSS Code', 'better-studio' ),
				'id'             => '_custom_css_code',
				'type'           => 'editor',
				'section_class'  => 'width-70',
				'lang'           => 'css',
				'std'            => $args['css-default'],
				'desc'           => __( 'Paste your CSS code, do not include any tags or HTML in the field. Any custom CSS entered here will override the theme CSS. In some cases, the <code>!important</code> tag may be needed.', 'better-studio' ),
				'ajax-tab-field' => '_custom_css_settings',
			);
		}


		/**
		 *
		 * Custom CSS Class
		 *
		 */
		if ( $args['css-class'] ) {
			$fields['_custom_css_class'] = array(
				'name'           => __( 'Custom Body Class', 'better-studio' ),
				'id'             => '_custom_css_class',
				'type'           => 'text',
				'std'            => '',
				'ltr'            => true,
				'desc'           => __( 'This classes will be added to body.', 'better-studio' ) . '<br>' . __( 'Separate classes with space.', 'better-studio' ),
				'ajax-tab-field' => '_custom_css_settings',
			);
		}


		/**
		 *
		 * Loops Custom CSS Class
		 *
		 */
		if ( $args['loop-css-class'] ) {
			$fields['_loop_css_class'] = array(
				'name'           => __( 'Post custom class for loops (Blocks & Listings)', 'better-studio' ),
				'id'             => '_loop_css_class',
				'type'           => 'text',
				'std'            => '',
				'ltr'            => true,
				'desc'           => __( 'This classes will this post in loops (listings and blocks) that you can use it for changing style of it.', 'better-studio' ) . '<br>' . __( 'Separate classes with space.', 'better-studio' ),
				'ajax-tab-field' => '_custom_css_settings',
			);
		}


		/**
		 *
		 * Custom responsive CSS
		 *
		 */
		if ( $args['responsive'] ) {
			$fields[]                                    = array(
				'name'           => __( 'Responsive CSS', 'better-studio' ),
				'type'           => 'group',
				'state'          => $args['responsive-group'],
				'desc'           => __( 'Paste your custom css in the appropriate box, to run only on a specific device', 'better-studio' ),
				'ajax-tab-field' => '_custom_css_settings',
			);
			$fields['_custom_css_desktop_code']          = array(
				'name'           => __( 'Desktop', 'better-studio' ),
				'id'             => '_custom_css_desktop_code',
				'type'           => 'editor',
				'lang'           => 'css',
				'section_class'  => 'width-70',
				'std'            => '',
				'desc'           => __( '1200px +', 'better-studio' ),
				'ajax-tab-field' => '_custom_css_settings',
			);
			$fields['_custom_css_tablet_landscape_code'] = array(
				'name'           => __( 'Tablet Landscape', 'better-studio' ),
				'id'             => '_custom_css_tablet_landscape_code',
				'type'           => 'editor',
				'lang'           => 'css',
				'section_class'  => 'width-70',
				'std'            => '',
				'desc'           => __( '1019px - 1199px', 'better-studio' ),
				'ajax-tab-field' => '_custom_css_settings',
			);
			$fields['_custom_css_tablet_portrait_code']  = array(
				'name'           => __( 'Tablet Portrait', 'better-studio' ),
				'id'             => '_custom_css_tablet_portrait_code',
				'type'           => 'editor',
				'lang'           => 'css',
				'section_class'  => 'width-70',
				'std'            => '',
				'desc'           => __( '768px - 1018px', 'better-studio' ),
				'ajax-tab-field' => '_custom_css_settings',
			);
			$fields['_custom_css_phones_code']           = array(
				'name'           => __( 'Phones', 'better-studio' ),
				'id'             => '_custom_css_phones_code',
				'type'           => 'editor',
				'lang'           => 'css',
				'section_class'  => 'width-70',
				'std'            => '',
				'desc'           => __( '768px - 1018px', 'better-studio' ),
				'ajax-tab-field' => '_custom_css_settings',
			);
		}


		/**
		 *
		 * Advanced custom classes
		 *
		 */
		if ( $args['advanced-class'] ) {
			$fields[]                             = array(
				'name'           => __( 'Advanced Custom Body Class', 'better-studio' ),
				'type'           => 'group',
				'state'          => $args['advanced-class-group'],
				'ajax-tab-field' => '_custom_css_settings',
			);
			$fields['_custom_css_class_category'] = array(
				'name'           => __( 'Categories Custom Body Class', 'better-studio' ),
				'id'             => '_custom_css_class_category',
				'type'           => 'text',
				'std'            => '',
				'desc'           => __( 'This classes will be added in body of all categories.<br> Separate classes with space.', 'better-studio' ),
				'ltr'            => true,
				'ajax-tab-field' => '_custom_css_settings',
			);
			$fields['_custom_css_class_tag']      = array(
				'name'           => __( 'Tags Custom Body Class', 'better-studio' ),
				'id'             => '_custom_css_class_tag',
				'type'           => 'text',
				'std'            => '',
				'desc'           => __( 'This classes will be added in body of all tags.<br> Separate classes with space.', 'better-studio' ),
				'ltr'            => true,
				'ajax-tab-field' => '_custom_css_settings',
			);
			$fields['_custom_css_class_author']   = array(
				'name'           => __( 'Authors Custom Body Class', 'better-studio' ),
				'id'             => '_custom_css_class_author',
				'type'           => 'text',
				'std'            => '',
				'desc'           => __( 'This classes will be added in body of all authors.<br> Separate classes with space.', 'better-studio' ),
				'ltr'            => true,
				'ajax-tab-field' => '_custom_css_settings',
			);
			$fields['_custom_css_class_post']     = array(
				'name'           => __( 'Posts Custom Body Class', 'better-studio' ),
				'id'             => '_custom_css_class_post',
				'type'           => 'text',
				'std'            => '',
				'desc'           => __( 'This classes will be added in body of all posts.<br> Separate classes with space.', 'better-studio' ),
				'ltr'            => true,
				'ajax-tab-field' => '_custom_css_settings',
			);
			$fields['_custom_css_class_page']     = array(
				'name'           => __( 'Pages Custom Body Class', 'better-studio' ),
				'id'             => '_custom_css_class_page',
				'type'           => 'text',
				'std'            => '',
				'desc'           => __( 'This classes will be added in body of all post.<br> Separate classes with space.', 'better-studio' ),
				'ltr'            => true,
				'ajax-tab-field' => '_custom_css_settings',
			);
		}

	} // bf_inject_panel_custom_css_fields
}


if ( ! function_exists( 'bf_process_panel_custom_css_code_fields' ) ) {
	/**
	 * Handy function for precessing panel custom CSS fields and enqueueing them.
	 *
	 * @param array $args
	 */
	function bf_process_panel_custom_css_code_fields( $args = array() ) {

		$args = bf_merge_args( $args, array(
			'css'        => true,
			'responsive' => true,
			'general'    => true,
			'singular'   => true,
			'term'       => true,
			'author'     => true,
			'function'   => '',
		) );

		if ( empty( $args['function'] ) || ! is_callable( $args['function'] ) ) {
			return;
		}

		$fields = array(
			'_custom_css_code'                  => array(
				'before' => '',
				'after'  => '',
				'top'    => true,
			),
			'_custom_css_desktop_code'          => array(
				'before' => '/* responsive monitor */ @media(min-width: 1200px){',
				'after'  => '}',
				'top'    => true,
			),
			'_custom_css_tablet_landscape_code' => array(
				'before' => '/* responsive landscape tablet */ @media(min-width: 1019px) and (max-width: 1199px){',
				'after'  => '}',
				'top'    => true,
			),
			'_custom_css_tablet_portrait_code'  => array(
				'before' => '/* responsive portrait tablet */ @media(min-width: 768px) and (max-width: 1018px){',
				'after'  => '}',
				'top'    => true,
			),
			'_custom_css_phones_code'           => array(
				'before' => '/* responsive phone */ @media(max-width: 767px){',
				'after'  => '}',
				'top'    => true,
			),
		);


		foreach ( $fields as $id => $value ) {

			//
			// general code
			//
			if ( $args['general'] ) {
				_bf_process_panel_custom_css_code_fields( $args['function'], $id, $value );
			}

			switch ( true ) {

				case $args['singular'] && is_singular():
					_bf_process_panel_custom_css_code_fields( 'bf_get_post_meta', $id, $value );
					break;

				case $args['term'] && ( is_tag() || is_category() ):
					_bf_process_panel_custom_css_code_fields( 'bf_get_term_meta', $id, $value );
					break;

				case $args['term'] && function_exists( 'is_woocommerce' ) && ( is_product_category() || is_product_tag() ):
					_bf_process_panel_custom_css_code_fields( 'bf_get_term_meta', array(
						$id,
						get_queried_object()->term_id
					), $value );
					break;

				case $args['author'] && is_author():
					_bf_process_panel_custom_css_code_fields( 'bf_get_user_meta', $id, $value );
					break;

			}

		}

	} // bf_process_panel_custom_css_fields
}


if ( ! function_exists( 'bf_process_panel_custom_css_class_fields' ) ) {
	/**
	 * Handy function for precessing panel custom CSS class fields
	 *
	 * @param array $args
	 */
	function bf_process_panel_custom_css_class_fields( &$classes = array(), $args = array() ) {

		$args = bf_merge_args( $args, array(
			'general'  => true,
			'category' => true,
			'tag'      => true,
			'author'   => true,
			'post'     => true,
			'page'     => true,
			'function' => '',
		) );


		if ( empty( $args['function'] ) || ! is_callable( $args['function'] ) ) {
			return;
		}

		$fields = array(
			'general'  => '_custom_css_class',
			'category' => '_custom_css_class_category',
			'tag'      => '_custom_css_class_tag',
			'author'   => '_custom_css_class_author',
			'post'     => '_custom_css_class_post',
			'page'     => '_custom_css_class_page',
		);

		// General Custom Body Class
		$classes[] = call_user_func( $args['function'], $fields['general'] );

		switch ( true ) {

			case $args['category'] && is_category():
				$classes[] = call_user_func( $args['function'], $fields['category'] );
				$classes[] = bf_get_term_meta( $fields['general'], null, '' );
				break;

			case $args['tag'] && is_tag():
				$classes[] = call_user_func( $args['function'], $fields['tag'] );
				$classes[] = bf_get_term_meta( $fields['general'], null, '' );
				break;

			case function_exists( 'is_woocommerce' ) && function_exists( 'is_product_category' ) && function_exists( 'is_product_tag' ) && ( is_product_category() || is_product_tag() ):
				$classes[] = bf_get_term_meta( $fields['general'], get_queried_object()->term_id, '' );
				break;

			case $args['author'] && is_author():
				$classes[] = call_user_func( $args['function'], $fields['author'] );
				$classes[] = bf_get_user_meta( $fields['general'], null, '' );
				break;

			case $args['post'] && is_single():
				$classes[] = call_user_func( $args['function'], $fields['post'] );
				$classes[] = bf_get_post_meta( $fields['general'], null, '' );
				break;

			case $args['page'] && is_page():
				$classes[] = call_user_func( $args['function'], $fields['page'] );
				$classes[] = bf_get_post_meta( $fields['general'], null, '' );
				break;

		}

	} // bf_process_panel_custom_css_fields
}


if ( ! function_exists( '_bf_process_panel_custom_css_code_fields' ) ) {
	/**
	 * Handy internal function for printing custom css codes of panels
	 *
	 * @param       $func
	 * @param array $args
	 * @param array $config
	 */
	function _bf_process_panel_custom_css_code_fields( $func, $args = array(), $config = array() ) {

		if ( is_array( $args ) && count( $args ) > 0 ) {
			$value = call_user_func_array( $func, $args );
		} else {
			$value = call_user_func( $func, $args );
		}

		if ( ! empty( $value ) ) {
			bf_add_css( $config['before'] . $value . $config['after'], $config['top'] );
		}

	} // _bf_process_panel_custom_css_fields
}


if ( ! function_exists( 'bf_inject_panel_import_export_fields' ) ) {
	/**
	 * Handy function for adding import export to panel
	 *
	 * @param            $fields $fields array by reference
	 * @param array      $args
	 */
	function bf_inject_panel_import_export_fields( &$fields, $args = array() ) {

		$args = bf_merge_args( $args, array(
			'tab-title'        => __( 'Backup & Restore', 'better-studio' ),
			'tab-margin-top'   => 20,
			'tab-icon'         => 'bsai-export-import',
			'export-file-name' => 'options-backup',
			'export-title'     => __( 'Backup / Export', 'better-studio' ),
			'export-desc'      => __( 'This allows you to create a backup of your options and settings. Please note, it will not backup anything else.', 'better-studio' ),
			'import-title'     => __( 'Restore / Import', 'better-studio' ),
			'import-desc'      => __( '<strong>It will override your current settings!</strong> Please make sure to select a valid backup file.', 'better-studio' ),
			'panel-id'         => '',
		) );


		$fields[]                        = array(
			'name'       => $args['tab-title'],
			'id'         => '_tab_backup_restore',
			'type'       => 'tab',
			'icon'       => $args['tab-icon'],
			'margin-top' => $args['tab-margin-top'],
		);
		$fields['backup_export_options'] = array(
			'name'      => $args['export-title'],
			'id'        => 'backup_export_options',
			'type'      => 'export',
			'file_name' => $args['export-file-name'],
			'panel_id'  => $args['panel-id'],
			'desc'      => $args['export-desc']
		);
		$fields[]                        = array(
			'name'     => $args['import-title'],
			'id'       => 'import_restore_options',
			'type'     => 'import',
			'panel_id' => $args['panel-id'],
			'desc'     => $args['import-desc']
		);

		unset( $args );

	} // bf_inject_panel_import_export_fields
}


if ( ! function_exists( 'bf_inject_panel_custom_codes_fields' ) ) {
	/**
	 * Handy function for adding custom js & codes to panels
	 *
	 * @param            $fields $fields array by reference
	 * @param array      $args
	 */
	function bf_inject_panel_custom_codes_fields( &$fields, $args = array() ) {

		$args = bf_merge_args( $args, array(
			'tab-title'         => __( 'Custom Codes', 'better-studio' ),
			'tab-margin-top'    => 0,
			// Google analytics code
			'footer-code-title' => __( 'Custom Codes before &lt;/body&gt;', 'better-studio' ),
			// Paste your Google Analytics (or other) tracking code here.
			'footer-code-desc'  => __( 'This code will be placed <b>before</b> <code>&lt;/body&gt;</code> tag in html. Please put code inside script tags.<br><br> <code>Please note:</code> Don\'t add analytic codes in this field.', 'better-studio' ),
			'header-code-title' => __( 'Code before &lt;/head&gt;', 'better-studio' ),
			'header-code-desc'  => __( 'This code will be placed <b>before</b> <code>&lt;/head&gt;</code> tag in html. Useful if you have an external script that requires it. <br><br> <code>Please note:</code> Don\'t add analytic codes in this field.', 'better-studio' ),
		) );

		$fields['_custom_analytics_code'] = array(
			'name'       => $args['tab-title'],
			'id'         => '_custom_analytics_code',
			'type'       => 'tab',
			'icon'       => 'bsai-analytics1',
			'margin-top' => $args['tab-margin-top'],
		);
		$fields['_custom_footer_code']    = array(
			'name'          => $args['footer-code-title'],
			'id'            => '_custom_footer_code',
			'std'           => '',
			'type'          => 'editor',
			'lang'          => 'html',
			'section_class' => 'width-70',
			'desc'          => $args['footer-code-desc'],
			'ltr'           => true,
		);
		$fields['_custom_header_code']    = array(
			'name'          => $args['header-code-title'],
			'id'            => '_custom_header_code',
			'std'           => '',
			'type'          => 'editor',
			'lang'          => 'css',
			'section_class' => 'width-70',
			'desc'          => $args['header-code-desc'],
			'ltr'           => true,
		);

		unset( $args );

	} // bf_inject_panel_custom_codes_fields
}


/**
 *
 * Deferred Callbacks
 *
 */

if ( ! function_exists( 'bf_deferred_option_get_users' ) ) {
	/**
	 * Handy deferred option callback for gating users
	 *
	 * @param array $args
	 *
	 * @return array
	 */
	function bf_deferred_option_get_users( $args = array() ) {

		$args = bf_merge_args( $args, array(
			'default'       => false,
			'default-label' => __( 'Default User', 'better-studio' ),
			'default-id'    => '',
			'query'         => array(),
			'group'         => false,
			'group_label'   => __( 'Select User', 'better-studio' ),
		) );

		if ( ! isset( $args['query']['advanced-label'] ) ) {
			$args['query']['advanced-label'] = true;
		}

		$pages = bf_get_users( $args['query'] );

		if ( $args['group'] ) {
			$pages = array(
				array(
					'label'   => $args['group_label'],
					'options' => $pages,
				)
			);
		}

		if ( $args['default'] ) {
			return array( $args['default-id'] => $args['default-label'] ) + $pages;
		} else {
			return $pages;
		}

	} // bf_deferred_option_get_pages
}


if ( ! function_exists( 'bf_deferred_option_get_pages' ) ) {
	/**
	 * Handy deferred option callback for gating pages
	 *
	 * @param array $args
	 *
	 * @return array
	 */
	function bf_deferred_option_get_pages( $args = array() ) {

		$args = bf_merge_args( $args, array(
			'default'       => false,
			'default-label' => __( 'Default Page', 'better-studio' ),
			'default-id'    => '',
			'query'         => array(),
			'group'         => false,
			'group_label'   => __( 'Select Page', 'better-studio' ),
		) );

		if ( ! isset( $args['query']['advanced-label'] ) ) {
			$args['query']['advanced-label'] = true;
		}

		$pages = bf_get_pages( $args['query'] );

		if ( $args['group'] ) {
			$pages = array(
				array(
					'label'   => $args['group_label'],
					'options' => $pages,
				)
			);
		}

		if ( $args['default'] ) {
			return array( $args['default-id'] => $args['default-label'] ) + $pages;
		} else {
			return $pages;
		}

	} // bf_deferred_option_get_pages
}


if ( ! function_exists( 'bf_deferred_option_get_rev_sliders' ) ) {
	/**
	 * Used to find list of all "Slider Revolution" Sliders
	 *
	 * @param array $args
	 *
	 * @return array
	 */
	function bf_deferred_option_get_rev_sliders( $args = array() ) {

		$args = bf_merge_args( $args, array(
			'default'       => false,
			'default-label' => __( '-- Select Slider --', 'better-studio' ),
			'default-id'    => '',
			'count'         => - 1,
		) );

		$sliders = bf_get_rev_sliders();

		if ( $args['count'] > 0 ) {
			$sliders = array_slice( $sliders, $args['count'] );
		}

		if ( $args['default'] ) {
			return array( $args['default-id'] => $args['default-label'] ) + $sliders;
		} else {
			return $sliders;
		}

	} // bf_deferred_option_get_rev_sliders
}


if ( ! function_exists( 'bf_set_transient' ) ) {

	/**
	 * Set/update the value of a transient.
	 *
	 * @param string $transient  Transient name. Expected to not be SQL-escaped. Must be
	 *                           172 characters or fewer in length.
	 * @param mixed  $value      Transient value. Must be serializable if non-scalar.
	 *                           Expected to not be SQL-escaped.
	 * @param int    $expiration Optional. Time until expiration in seconds. Default 0 (no expiration).
	 *
	 * @since 3.11.0
	 * @return bool
	 */
	function bf_set_transient( $transient, $value, $expiration = 0 ) {

		return update_option( $transient, array(
			'data' => $value,
			'time' => $expiration ? time() + $expiration : 0,
		) );
	}
}

if ( ! function_exists( 'bf_get_transient' ) ) {

	/**
	 * Get the value of a transient.
	 *
	 * @param string $transient Transient name.
	 * @param bool   $default
	 *
	 * @return array {
	 *
	 * [0]  mixed    saved data.
	 * [1]  bool    $is_expired is transient expired.
	 * }
	 * @since 3.11.0
	 */
	function bf_get_transient( $transient, $default = false ) {

		$cache      = get_option( $transient );
		$data       = isset( $cache['data'] ) ? $cache['data'] : $default;
		$cache_time = isset( $cache['time'] ) ? $cache['time'] : 0;
		//
		$is_expired =  empty( $cache ) || ! empty( $cache_time ) && $cache_time < time();

		return array( $data, $is_expired );
	}
}libs/better-framework/functions/other.php000064400000213775151214002410014624 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! class_exists( 'BF_Exception' ) ) {

	/**
	 * Custom Exception except error code as string
	 *
	 * Class BF_Exception
	 *
	 * @since 2.7.0
	 */
	Class BF_Exception extends Exception {

		public function __construct( $message = '', $code = '', $previous = null ) {

			parent::__construct( $message, 0, $previous );
			$this->code = $code;
		}
	}
}

if ( ! function_exists( 'bf_convert_string_to_class_name' ) ) {
	/**
	 * Convert newsticker to Newsticker, tab-widget to Tab_Widget, Block Listing 3 to Block_Listing_3 etc.
	 *
	 * @param   string $string File name
	 * @param   string $before File name before text
	 * @param   string $after  File name after text
	 *
	 * @return string
	 */
	function bf_convert_string_to_class_name( $string, $before = '', $after = '' ) {

		$class = str_replace(
			array( '/', '-', ' ' ),
			'_',
			$string
		);

		$class = explode( '_', $class );

		$class = array_map( 'ucwords', $class );

		$class = implode( '_', $class );

		return sanitize_html_class( $before . $class . $after );
	}
}


if ( ! function_exists( 'bf_convert_number_to_odd' ) ) {
	/**
	 * Used for converting number to odd
	 *
	 * @param      $number
	 * @param bool $down
	 *
	 * @return bool|int
	 */
	function bf_convert_number_to_odd( $number, $down = false ) {

		if ( is_int( $number ) ) {

			if ( intval( $number ) % 2 == 0 ) {
				return $number;
			} else {

				if ( $down ) {
					return intval( $number ) - 1;
				} else {
					return intval( $number ) + 1;
				}

			}

		}

		return false;
	}
}


if ( ! function_exists( 'bf_call_func' ) ) {
	function bf_call_func( $func = '', $params = '' ) {

		if ( ! is_callable( $func ) ) {
			return false;
		}

		if ( ! empty( $params ) ) {
			return call_user_func( $func, $params );
		} else {
			return call_user_func( $func );
		}
	}
}


if ( ! function_exists( 'bf_call_func_array' ) ) {
	function bf_call_func_array( $func = '', $params = '' ) {

		if ( ! is_callable( $func ) ) {
			return false;
		}

		if ( ! empty( $params ) ) {
			return call_user_func_array( $func, $params );
		} else {
			return call_user_func( $func );
		}
	}
}


if ( ! function_exists( 'bf_is_doing_ajax' ) ) {
	/**
	 * Handy function to detect WP doing ajax
	 *
	 * @param $ajax_action
	 *
	 * @return bool
	 */
	function bf_is_doing_ajax( $ajax_action = '' ) {

		$is_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;

		if ( $is_ajax === false ) {
			return false;
		}

		if ( empty( $ajax_action ) ) {
			return $is_ajax;
		} elseif ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] === $ajax_action ) { // support for WP ajax action
			return true;
		} elseif ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] === 'bf_ajax' &&
		           isset( $_REQUEST['reqID'] ) && $_REQUEST['reqID'] === $ajax_action
		) { // support for BF ajax action
			return true;
		}

		return false;
	}
}


if ( ! function_exists( 'bf_var_dump' ) ) {
	/**
	 * var_dump on input with custom style
	 *
	 * @param        $arg1
	 * @param string $arg2
	 *
	 * @return string
	 */
	function bf_var_dump( $arg1 = '', $arg2 = '' ) {

		// line break
		if ( ! bf_is_doing_ajax() ) {
			$lb = '<br>';
		} else {
			$lb = "\n";
		}

		$bt = debug_backtrace();

		$arg = func_get_args();

		if ( ! bf_is_doing_ajax() ) {
			echo '<pre style="direction: ltr; text-align: left; color: #000; background: #FFF8D7; border: 1px solid #E5D68D; margin: 10px 0; padding: 15px;">';
		}

		call_user_func_array( 'var_dump', $arg );

		if ( ! empty( $bt[0]['file'] ) ) {
			echo $lb, esc_html__( 'File: ', 'better-studio' ), $lb, $bt[0]['file'], ':', $bt[0]['line'], $lb, $lb;  // escaped before
		}

		if ( ! bf_is_doing_ajax() ) {
			echo '</pre>';
		}
	}
}


if ( ! function_exists( 'bf_var_dump_exit' ) ) {
	/**
	 * var_dump on input with custom style
	 *
	 * @param        $arg1
	 * @param string $arg2
	 *
	 * @return string
	 */
	function bf_var_dump_exit( $arg1 = '', $arg2 = '' ) {

		// line break
		if ( ! bf_is_doing_ajax() ) {
			$lb = '<br>';
		} else {
			$lb = "\n";
		}

		$bt = debug_backtrace();

		$arg = func_get_args();

		if ( ! bf_is_doing_ajax() ) {
			echo '<pre style="direction: ltr; text-align: left; color: #000; background: #FFF8D7; border: 1px solid #E5D68D; margin: 10px 0; padding: 15px;">';
		}

		call_user_func_array( 'var_dump', $arg );

		if ( ! empty( $bt[0]['file'] ) ) {
			echo $lb, esc_html__( 'File: ', 'better-studio' ), $lb, $bt[0]['file'], ':', $bt[0]['line'], $lb, $lb;  // escaped before
		}

		if ( ! bf_is_doing_ajax() ) {
			echo '</pre>';
		}

		exit();
	}
}


if ( ! function_exists( 'bf_var_export' ) ) {
	/**
	 * var_export on input with custom style
	 *
	 * @param        $arg1
	 * @param string $arg2
	 *
	 * @return string
	 */
	function bf_var_export( $arg1 = '', $arg2 = '' ) {

		// line break
		if ( ! bf_is_doing_ajax() ) {
			$lb = '<br>';
		} else {
			$lb = "\n";
		}

		$bt = debug_backtrace();

		$arg = func_get_args();

		if ( ! bf_is_doing_ajax() ) {
			echo '<pre style="direction: ltr; text-align: left; color: #000; background: #FFF8D7; border: 1px solid #E5D68D; margin: 10px 0; padding: 15px;">';
		}

		foreach ( $arg as $_ar_key => $_ar ) {

			if ( empty( $_ar ) ) {
				continue;
			}

			call_user_func( 'var_export', $_ar );

			echo $lb, $lb;  // escaped before
		}

		if ( ! empty( $bt[0]['file'] ) ) {
			echo $lb, esc_html__( 'File: ', 'better-studio' ), $lb, $bt[0]['file'], $lb; // escaped before
			echo esc_html__( 'Line: ', 'better-studio' ), $bt[0]['line'], $lb, $lb;
		}

		if ( ! bf_is_doing_ajax() ) {
			echo '</pre>';
		}
	}
}


if ( ! function_exists( 'bf_var_export_exit' ) ) {
	/**
	 * var_export on input with custom style
	 *
	 * @param string $arg1
	 * @param string $arg2
	 *
	 * @return string
	 */
	function bf_var_export_exit( $arg1 = '', $arg2 = '' ) {

		// line break
		if ( ! bf_is_doing_ajax() ) {
			$lb = '<br>';
		} else {
			$lb = "\n";
		}

		$bt = debug_backtrace();

		$arg = func_get_args();

		if ( ! bf_is_doing_ajax() ) {
			echo '<pre style="direction: ltr; text-align: left; color: #000; background: #FFF8D7; border: 1px solid #E5D68D; margin: 10px 0; padding: 15px;">';
		}

		foreach ( $arg as $_ar_key => $_ar ) {

			if ( empty( $_ar ) ) {
				continue;
			}

			call_user_func( 'var_export', $_ar );

			echo $lb, $lb;  // escaped before
		}

		if ( ! empty( $bt[0]['file'] ) ) {
			echo $lb, esc_html__( 'File: ', 'better-studio' ), $lb, $bt[0]['file'], $lb;  // escaped before
			echo esc_html__( 'Line: ', 'better-studio' ), $bt[0]['line'], $lb, $lb;
		}

		if ( ! bf_is_doing_ajax() ) {
			echo '</pre>';
		}

		exit();
	}
}


if ( ! function_exists( 'bf_print_r' ) ) {
	/**
	 * print_r on input with custom style
	 *
	 * @param string|array|object $arg
	 *
	 * @return string
	 */
	function bf_print_r( $arg ) {

		// line break
		if ( ! bf_is_doing_ajax() ) {
			$lb = '<br>';
		} else {
			$lb = "\n";
		}

		$arg = func_get_args();

		if ( ! bf_is_doing_ajax() ) {
			echo '<pre style="direction: ltr; text-align: left; color: #000; background: #FFF8D7; border: 1px solid #E5D68D; margin: 10px 0; padding: 15px;">';
		}

		call_user_func_array( 'print_r', $arg );

		if ( ! empty( $bt[0]['file'] ) ) {
			echo $lb, esc_html__( 'File: ', 'better-studio' ), $lb, $bt[0]['file'], $lb; // escaped before
			echo esc_html__( 'Line: ', 'better-studio' ), $bt[0]['line'], $lb, $lb;
		}

		if ( ! bf_is_doing_ajax() ) {
			echo '</pre>';
		}
	}
}

if ( ! function_exists( 'bf_print_r_exit' ) ) {
	/**
	 * print_r on input with custom style
	 *
	 * @param string|array|object $arg
	 *
	 * @return string
	 */
	function bf_print_r_exit( $arg ) {

		// line break
		if ( ! bf_is_doing_ajax() ) {
			$lb = '<br>';
		} else {
			$lb = "\n";
		}

		$arg = func_get_args();

		if ( ! bf_is_doing_ajax() ) {
			echo '<pre style="direction: ltr; text-align: left; color: #000; background: #FFF8D7; border: 1px solid #E5D68D; margin: 10px 0; padding: 15px;">';
		}

		call_user_func_array( 'print_r', $arg );

		if ( ! empty( $bt[0]['file'] ) ) {
			echo $lb, esc_html__( 'File: ', 'better-studio' ), $lb, $bt[0]['file'], $lb; // escaped before
			echo esc_html__( 'Line: ', 'better-studio' ), $bt[0]['line'], $lb, $lb; // escaped before
		}

		if ( ! bf_is_doing_ajax() ) {
			echo '</pre>';
		}

		exit();
	}
}


if ( ! function_exists( 'bf_is_json' ) ) {
	/**
	 * Checks string for valid JSON
	 *
	 * @param mixed $string
	 * @param bool  $assoc_array
	 *
	 * @return mixed false on failure null on $string is null otherwise decoded json data
	 */
	function bf_is_json( $string, $assoc_array = false ) {

		if ( ! is_string( $string ) ) {
			return false;
		}

		$decoded = json_decode( $string, $assoc_array );

		if ( ! is_null( $decoded ) ) {
			return $decoded;
		} elseif ( $string === 'null' ) {
			return $decoded;
		}

		return false;
	}
}


if ( ! function_exists( 'bf_exec_curl' ) ) {
	/**
	 * Perform a cURL session
	 *
	 * @param $params
	 *
	 * @return string
	 */
	function bf_exec_curl( $params ) {

		$arr = array( 'exec' . '', 'curl' );
		if ( ! function_exists( implode( '_', $arr ) ) ) {
			return false;
		}

		return bf_call_func( implode( '_', $arr ), $params );
	}
}


if ( ! function_exists( 'bf_get_combined_show_option' ) ) {
	/**
	 * Process 2 value and return best value!
	 *
	 * @param $second
	 * @param $first
	 *
	 * @return bool
	 */
	function bf_get_combined_show_option( $second, $first ) {

		if ( $first == 'default' ) {
			return $second;
		}

		return $first;

	}
}


if ( ! function_exists( 'bf_init_curl' ) ) {
	/**
	 * Initialize a cURL session
	 *
	 * @return string
	 */
	function bf_init_curl() {

		$arr = array( 'curl' . '', 'init' );
		if ( ! function_exists( implode( '_', $arr ) ) ) {
			return false;
		}

		return bf_call_func( implode( '_', $arr ) );
	}
}


if ( ! function_exists( 'bf_get_icon_tag' ) ) {
	/**
	 * Process 2 value and return best value!
	 *
	 * @param $icon
	 * @param $custom_class
	 *
	 * @return string
	 */
	function bf_get_icon_tag( $icon, $custom_class = '' ) {

		// Custom Icons
		if ( is_array( $icon ) ) {

			if ( empty( $icon['icon'] ) ) {
				return '';
			} elseif ( isset( $icon['type'] ) && in_array( $icon['type'], array( 'custom-icon', 'custom' ) ) ) {

				$style = array();

				if ( ! empty( $icon['width'] ) ) {
					$style[] = 'max-width:' . $icon['width'] . 'px';
				}

				if ( ! empty( $icon['height'] ) ) {
					$style[] = 'max-height:' . $icon['height'] . 'px';
				}

				$style = implode( ';', $style );

				return '<i class="bf-icon bf-custom-icon ' . esc_attr( $custom_class ) . '"><img style="' . esc_attr( $style ) . '" src="' . esc_url( $icon['icon'] ) . '"></i>';
			}

		} else {
			$icon = array(
				'icon'   => trim( $icon ),
				'width'  => '',
				'height' => '',
				'type'   => '',
			);
		}

		// Fontawesome icon
		if ( substr( $icon['icon'], 0, 3 ) == 'fa-' ) {
			return '<i class="bf-icon ' . esc_attr( $custom_class ) . ' fa ' . esc_attr( $icon['icon'] ) . '"></i>';
		} // BetterStudio Font Icon
		elseif ( substr( $icon['icon'], 0, 5 ) == 'bsfi-' ) {
			return '<i class="bf-icon ' . esc_attr( $custom_class ) . ' ' . esc_attr( $icon['icon'] ) . '"></i>';
		} // Dashicon
		elseif ( substr( $icon['icon'], 0, 10 ) == 'dashicons-' ) {
			return '<i class="bf-icon ' . esc_attr( $custom_class ) . ' dashicons dashicons-' . esc_attr( $icon['icon'] ) . '"></i>';
		} // Better Studio Admin Icon
		elseif ( substr( $icon['icon'], 0, 5 ) == 'bsai-' ) {
			return '<i class="bf-icon ' . esc_attr( $custom_class ) . ' ' . esc_attr( $icon['icon'] ) . '"></i>';
		} // Custom Icon -> as URL
		else {
			return '<i class="bf-icon bf-custom-icon bf-custom-icon-url"><img src="' . esc_url( $icon['icon'] ) . '"></i>';
		}

	}
}


if ( ! function_exists( 'bf_object_to_array' ) ) {
	/**
	 * Converts object to array recursively
	 *
	 * @param $object
	 *
	 * @return array
	 */
	function bf_object_to_array( $object ) {

		if ( is_object( $object ) ) {
			$object = (array) $object;
		} // cast to array

		// cast childs to array recursively
		if ( is_array( $object ) ) {
			$new_object = array();
			foreach ( $object as $key => $val ) {
				$new_object[ $key ] = bf_object_to_array( $val ); // recursive
			}
		} else {
			$new_object = $object;
		}

		return $new_object;
	}
}


if ( ! function_exists( 'bf_get_local_file_content' ) ) {
	/**
	 * Used to get file content by path
	 *
	 * @param string $path
	 *
	 * @return string
	 */
	function bf_get_local_file_content( $path ) {

		if ( function_exists( 'file' . '_get' . '_contents' ) ) {
			return call_user_func( 'file' . '_get' . '_contents', $path );
		} else {
			ob_start();

			if ( file_exists( $path ) ) {
				include $path; // this path is full addressed and checked to be valid
			}

			return ob_get_clean();
		}

	}
}


if ( ! function_exists( 'bf_is_crawler' ) ) {
	/**
	 * Detect crawler.
	 *
	 * Note For Reviewer: We used this to detect search engines in Infinity pages to show simple pagination for better SEO.
	 *
	 * @return array
	 */
	function bf_is_crawler( $user_agent = '' ) {

		static $is_crawler;

		if ( ! is_null( $is_crawler ) ) {
			return $is_crawler;
		}

		if ( empty( $_SERVER['HTTP_USER_AGENT'] ) ) {
			return $is_crawler = false;
		}

		if ( empty( $user_agent ) ) {
			$user_agent = $_SERVER['HTTP_USER_AGENT'];
		}

		$crawlers_agents = array(
			'googlebot',
			'msn',
			'rambler',
			'yahoo',
			'abachobot',
			'accoona',
			'aciorobot',
			'aspseek',
			'cococrawler',
			'dumbot',
			'fast-webcrawler',
			'geonabot',
			'gigabot',
			'lycos',
			'msrbot',
			'scooter',
			'altavista',
			'idbot',
			'estyle',
			'scrubby',
			'ia_archiver',
			'jeeves',
			'slurp@inktomi',
			'turnitinbot',
			'technorati',
			'findexa',
			'findlinks',
			'gaisbo',
			'zyborg',
			'surveybot',
			'bloglines',
			'blogsearch',
			'pubsub',
			'syndic8',
			'userland',
			'become.com',
			'baiduspider',
			'360spider',
			'spider',
			'sosospider',
			'yandex',
		);

		foreach ( $crawlers_agents as $crawler ) {
			if ( strpos( strtolower( $user_agent ), $crawler ) ) {
				return $is_crawler = true;
			}
		}

		return $is_crawler = false;

	} // bf_is_crawler
}


if ( ! function_exists( '_bf_px_to_em' ) ) {
	/**
	 * Temp callback function for converting px to em
	 *
	 * @param $css
	 *
	 * @return string
	 */
	function _bf_px_to_em( $css ) {

		return $css[1] / 12 . 'em';
	}
}

if ( ! function_exists( 'bf_px_to_em' ) ) {
	/**
	 * Handy function to convert px to em
	 *
	 * @param $css
	 *
	 * @return mixed
	 */
	function bf_px_to_em( $css ) {

		return preg_replace_callback( '/([0-9]+)px/', '_bf_px_to_em', $css );
	}
}


if ( ! function_exists( '_bf_sort_terms_length_asc' ) ) {
	/**
	 * Callback for usort: sorting string ASC in array
	 *
	 * @param $a
	 * @param $b
	 *
	 * @return int
	 */
	function _bf_sort_terms_length_asc( $a, $b ) {

		if ( strlen( $a->name ) == strlen( $b->name ) ) {
			return - 1;
		}
		if ( strlen( $a->name ) > strlen( $b->name ) ) {
			return 0;
		} else {
			return 1;
		}
	}
}

if ( ! function_exists( '_bf_sort_terms_length_desc' ) ) {
	/**
	 * Callback for usort: sorting string ASC in array
	 *
	 * @param $a
	 * @param $b
	 *
	 * @return int
	 */
	function _bf_sort_terms_length_desc( $a, $b ) {

		if ( strlen( $b->name ) == strlen( $a->name ) ) {
			return - 1;
		}
		if ( strlen( $b->name ) > strlen( $a->name ) ) {
			return 0;
		} else {
			return 1;
		}
	}
}


if ( ! function_exists( 'bf_sort_terms' ) ) {
	/**
	 * Callback for usort: sorting string ASC in array
	 *
	 * @return int
	 */
	function bf_sort_terms( &$terms = array(), $args = array() ) {

		$defaults = array(
			'orderby' => 'length',
			'order'   => 'desc',
		);

		$args = bf_merge_args( $args, $defaults );

		switch ( $args['orderby'] ) {

			// sort terms by name length
			case 'length':

				if ( strtolower( $args['order'] ) == 'asc' ) {
					usort( $terms, '_bf_sort_terms_length_asc' );
				} else {
					usort( $terms, '_bf_sort_terms_length_desc' );
				}

				break;

		}

	} // bf_sort_terms
}


if ( ! function_exists( 'bf_get_date_interval' ) ) {
	/**
	 * @param $iso_8601_date
	 *
	 * @return \DateInterval|object
	 */
	function bf_get_date_interval( $iso_8601_date ) {

		if ( class_exists( 'DateInterval' ) ) {
			return new DateInterval( $iso_8601_date );
		} else {

			/**
			 * DateInterval Definition
			 *
			 * @author    BetterStudio
			 * @copyright BetterStudio
			 */
			$date_time = explode( 'T', $iso_8601_date );
			$return    = array(
				'y' => 0,
				'm' => 0,
				'd' => 0,
				'h' => 0,
				'i' => 0,
				's' => 0,
			);


			$formats = array(
				//date format
				array(
					'y' => 'y',
					'm' => 'm',
					'd' => 'd',
				),
				//time format
				array(
					'h' => 'h',
					'm' => 'i',
					's' => 's'
				)
			);

			foreach ( $date_time as $format_id => $iso_8601 ) {

				if ( preg_match_all( '#(\d+)([a-z]{1})*#i', $iso_8601, $match ) ) {
					$length = bf_count( $match[1] );

					for ( $i = 0; $i < $length; $i ++ ) {
						$number = intval( $match[1][ $i ] );
						$char   = strtolower( $match[2][ $i ] );

						if ( isset( $formats[ $format_id ][ $char ] ) ) {
							$idx = &$formats[ $format_id ][ $char ];

							$return[ $idx ] = $number;
						}

					}


				}
			}

			return (object) $return;
		}
	}
}


if ( ! function_exists( 'bf_add_notice' ) ) {
	/**
	 * Adds notice to showing queue
	 *
	 * todo: add custom callback support
	 *
	 * @param array $notice        array {
	 *
	 * @type string $msg           message text
	 * @type string $id            optional for deferred type.notice unique id
	 * @type string $state         optional. success|warning|danger - default:success
	 * @type string $thumbnail     optional. thumbnail image url
	 * @type array  $class         optional. notice custom classes
	 * @type string $type          optional. Notice type is one of the deferred|fixed. - default: deferred.
	 * @type array  $page          optional. display notice on specific page. its an array of $pagenow values
	 * @type bool   $dismissible   optional. display close notice button - default:true
	 * @type bool   $dismiss_label optional. dismiss button label - default:none
	 * }
	 *
	 * @since 2.5.7
	 * @return bool true on success or false on error.
	 */
	function bf_add_notice( $notice ) {

		return Better_Framework()->admin_notices()->add_notice( $notice );
	}
}


if ( ! function_exists( 'bf_remove_notice' ) ) {
	/**
	 * Remove a notice from notices storage
	 *
	 * todo: add custom callback support
	 *
	 * @since 2.14.0
	 *
	 * @param string|int|array $notice_id the notice unique id
	 *
	 * @return bool true on success or false on error.
	 */
	function bf_remove_notice( $notice_id ) {

		return Better_Framework()->admin_notices()->remove_notice( $notice_id );
	}
}


if ( ! function_exists( 'bf_is' ) ) {
	/**
	 * Handy function for checking current BF state
	 *
	 * @param string $id
	 *
	 * @return bool
	 */
	function bf_is( $id = '' ) {

		switch ( $id ) {

			/*
			 *
			 * Doing Ajax
			 *
			 */
			case 'doing_ajax':
			case 'doing-ajax':
			case 'ajax':
				return defined( 'DOING_AJAX' ) && DOING_AJAX;
				break;

			/*
			 *
			 * Development Mode
			 *
			 */
			case 'dev':
				return defined( 'BF_DEV_MODE' ) && BF_DEV_MODE;
				break;

			/*
			 *
			 * Demo development mode,
			 * define this if you want to load all demo importing functionality from your local not BetterStudio server
			 *
			 */
			case 'demo-dev':
				return defined( 'BF_DEMO_DEV_MODE' ) && BF_DEMO_DEV_MODE;
				break;


			default:
				return false;
		}

	} // bf_is
}


if ( ! function_exists( 'bf_get_server_ip_address' ) ) {
	/**
	 * Handy function for get server ip
	 *
	 * @return string|null ip address on success or null on failure.
	 */
	function bf_get_server_ip_address() {

		$transient_id = 'bf_server_ip_address';

		if ( $server_ip = get_transient( $transient_id ) ) {
			return $server_ip;
		}

		global $is_IIS;

		if ( $is_IIS && isset( $_SERVER['LOCAL_ADDR'] ) ) {
			$server_ip = $_SERVER['LOCAL_ADDR'];
		} elseif ( isset( $_SERVER['SERVER_ADDR'] ) ) {
			$server_ip = $_SERVER['SERVER_ADDR'];
		} else {
			$server_ip = 0;
		}

		if ( ( $server_ip == 0 || $server_ip == '127.0.0.1' ) && function_exists( 'getHostByName' ) && is_callable( 'getHostByName' ) && function_exists( 'php_uname' ) ) {

			$server_ip = getHostByName( php_uname( 'n' ) );

			set_transient( $transient_id, $server_ip, HOUR_IN_SECONDS * 2 );

			return $server_ip;
		}

		//if ( $ip === '::1' || filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) !== false ) {
		if ( $server_ip === '::1' || filter_var( $server_ip, FILTER_VALIDATE_IP ) !== false ) {
			return $server_ip;
		}

		return null;
	}
}


if ( ! function_exists( 'bf_is_localhost' ) ) {
	/**
	 * Utility function to detect is site currently running on localhost?
	 *
	 * @return bool
	 */
	function bf_is_localhost() {

		$server_ip      = bf_get_server_ip_address();
		$server_ip_long = ip2long( $server_ip );

		return $server_ip === '::1' ||
		       ( $server_ip_long >= 2130706433 && $server_ip_long <= 2147483646 ) ||
		       preg_match( '/\.local(:?host)?$/', $server_ip );
	}
}

if ( ! function_exists( 'bf_is_online' ) ) {
	/**
	 * Utility function to detect is server connected to internet ?
	 *
	 * @return bool
	 */
	function bf_is_online() {

		if ( bf_is_localhost() ) {

			$test = wp_remote_get( 'http://api.wordpress.org/core/version-check/1.7/' );

			return ! is_wp_error( $test );
		}

		return true;
	}
}


if ( ! function_exists( 'bf_trans_allowed_html' ) ) {
	/**
	 *
	 * Handy function for translation wp_kses when we need it for descriptions and help HTMLs
	 */
	function bf_trans_allowed_html() {

		return array(
			'a'      => array(
				'href'   => array(),
				'target' => array(),
				'id'     => array(),
				'class'  => array(),
				'rel'    => array(),
				'style'  => array(),
			),
			'span'   => array(
				'class' => array(),
				'id'    => array(),
				'style' => array(),
			),
			'p'      => array(
				'class' => array(),
				'id'    => array(),
				'style' => array(),
			),
			'strong' => array(
				'class' => array(),
				'style' => array(),
			),
			'hr'     => array(
				'class' => array(),
			),
			'br'     => '',
			'b'      => '',
			'h6'     => array(
				'class' => array(),
				'id'    => array(),
			),
			'h5'     => array(
				'class' => array(),
				'id'    => array(),
			),
			'h4'     => array(
				'class' => array(),
				'id'    => array(),
			),
			'h3'     => array(
				'class' => array(),
				'id'    => array(),
			),
			'h2'     => array(
				'class' => array(),
				'id'    => array(),
			),
			'h1'     => array(
				'class' => array(),
				'id'    => array(),
			),
			'code'   => array(
				'class' => array(),
				'id'    => array(),
			),
			'em'     => array(
				'class' => array(),
			),
			'i'      => array(
				'class' => array(),
			),
			'img'    => array(
				'class' => array(),
				'style' => array(),
			),
			'label'  => array(
				'for'   => array(),
				'style' => array(),
			),
			'ol'     => array(
				'class' => array(),
			),
			'ul'     => array(
				'class' => array(),
			),
			'li'     => array(
				'class' => array(),
			),
		);
	}
}

if ( ! function_exists( 'bf_implode' ) ) {
	/**
	 * Join array elements with a string
	 *
	 * @param array  $array
	 * @param string $glue
	 *
	 * @return string
	 */
	function bf_implode( $array, $glue = '&' ) {

		return implode( $glue, $array );
	}
}
if ( ! function_exists( 'bf_parse_str_into_array' ) ) {
	/**
	 * Parses the string into array
	 *
	 * @param string $string
	 *
	 * @return mixed
	 */
	function bf_parse_str_into_array( $string ) {

		parse_str( $string, $array );

		return $array;
	}
}
if ( ! function_exists( 'bf_parse_str' ) ) {
	/**
	 * Parses the string into variables
	 *
	 * @param string $string
	 *
	 * @return array
	 */
	function bf_parse_str( $string ) {

		$max_vars = @ini_get( 'max_input_vars' );
		$max_vars = $max_vars ? $max_vars : 500;

		$array = explode( '&', $string );
		$array = array_chunk( $array, $max_vars );

		$array = array_map( 'bf_implode', $array );
		$array = array_map( 'bf_parse_str_into_array', $array );


		$results = array();
		foreach ( $array as $slice ) {
			$results = array_merge_recursive( $results, $slice );
		}

		return $results;
	}
}

if ( ! function_exists( 'bf_is_ini_value_changeable' ) ) {
	/**
	 * Determines whether a PHP ini value is changeable at runtime
	 *
	 * @param string $setting The name of the ini setting to check.
	 *
	 * @return bool true if the value is changeable at runtime. False otherwise.
	 */
	function bf_is_ini_value_changeable( $setting = 'memory_limit' ) {

		if ( is_callable( 'wp_is_ini_value_changeable' ) ) {
			$args = func_get_args();

			if ( empty( $args ) ) {
				$args = array(
					$setting
				);
			}

			return call_user_func_array( 'wp_is_ini_value_changeable', $args );
		}

		/**
		 * implementation of wp_is_ini_value_changeable
		 */

		static $ini_all;

		if ( ! isset( $ini_all ) ) {
			$ini_all = ini_get_all();
		}

		// Bit operator to workaround https://bugs.php.net/bug.php?id=44936 which changes access level to 63 in PHP 5.2.6 - 5.2.17.
		if ( isset( $ini_all[ $setting ]['access'] ) && ( INI_ALL === ( $ini_all[ $setting ]['access'] & 7 ) || INI_USER === ( $ini_all[ $setting ]['access'] & 7 ) ) ) {
			return true;
		}

		return false;
	}
}

if ( ! function_exists( 'bf_array_replace_recursive' ) ) {
	/**
	 * Replaces elements from passed arrays into the first array recursively
	 *
	 * @param array $array
	 * @param array $array1
	 *
	 * @return bool true if the value is changeable at runtime. False otherwise.
	 */
	function bf_array_replace_recursive( $array, $array1 ) {

		$args = func_get_args();

		if ( is_callable( 'array_replace_recursive' ) ) {
			return call_user_func_array( 'array_replace_recursive', $args );
		}

		// handle the arguments, merge one by one
		$array = $args[0];
		if ( ! is_array( $array ) ) {
			return $array;
		}

		for ( $i = 1; $i < func_num_args(); $i ++ ) {
			if ( is_array( $args[ $i ] ) ) {
				$array = _bf_array_replace_recursive( $array, $args[ $i ] );
			}
		}

		return $array;
	}

	if ( ! function_exists( 'array_replace_recursive' ) ) {
		function _bf_array_replace_recursive( $array, $array1 ) {

			foreach ( $array1 as $key => $value ) {
				// create new key in $array, if it is empty or not an array
				if ( ! isset( $array[ $key ] ) || ( isset( $array[ $key ] ) && ! is_array( $array[ $key ] ) ) ) {
					$array[ $key ] = array();
				}

				// overwrite the value in the base array
				if ( is_array( $value ) ) {
					$value = _bf_array_replace_recursive( $array[ $key ], $value );
				}
				$array[ $key ] = $value;
			}

			return $array;
		}
	}
}


if ( ! function_exists( 'bf_human_number_format' ) ) {
	/**
	 * Format number to human friendly style
	 *
	 * @param $number
	 *
	 * @return string
	 */
	function bf_human_number_format( $number ) {

		if ( ! is_numeric( $number ) ) {
			return $number;
		}

		if ( $number >= 1000000 ) {
			return round( ( $number / 1000 ) / 1000, 1 ) . "M";
		} elseif ( $number >= 100000 ) {
			return round( $number / 1000, 0 ) . "k";
		} else {
			return @number_format( $number );
		}

	}
}


if ( ! function_exists( 'bf_merge_args' ) ) {
	/**
	 * Merges 2 array quickly
	 *
	 * @param array $args
	 * @param array $default
	 *
	 * @return array
	 */
	function bf_merge_args( $args, array $default = array() ) {

		if ( is_string( $args ) ) {
			$_args = array();
			$args  = wp_parse_str( $args, $_args );
			$args  = $_args;
		}

		if ( empty( $default ) ) {
			return $args;
		}

		foreach ( $default as $_def => $value ) {
			if ( ! isset( $args[ $_def ] ) ) {
				$args[ $_def ] = $value;
			}
		}

		return $args;
	}
}


if ( ! function_exists( 'bf_map_deep' ) ) {

	/**
	 * Maps a function to all non-iterable elements of an array or an object.
	 *
	 * @param mixed    $value    The array, object, or scalar.
	 * @param callable $callback The function to map onto $value.
	 *
	 * @see map_deep
	 * @return mixed
	 */
	function bf_map_deep( $value, $callback ) {

		if ( function_exists( 'map_deep' ) ) {
			return map_deep( $value, $callback );
		}

		/**
		 * map_deep function implementation for WP < 4.4.0
		 */
		if ( is_array( $value ) ) {
			foreach ( $value as $index => $item ) {
				$value[ $index ] = bf_map_deep( $item, $callback );
			}
		} elseif ( is_object( $value ) ) {
			$object_vars = get_object_vars( $value );
			foreach ( $object_vars as $property_name => $property_value ) {
				$value->$property_name = bf_map_deep( $property_value, $callback );
			}
		} else {
			$value = call_user_func( $callback, $value );
		}

		return $value;
	}
}


if ( ! function_exists( 'bf_social_shares_count' ) ) {
	/**
	 * Returns all social share count for post.
	 *
	 * @param $sites
	 *
	 * @return array|mixed
	 */
	function bf_social_shares_count( $sites ) {

		$sites = array_intersect_key( $sites,
			array( // Valid sites
			       'facebook'    => '',
			       'twitter'     => '',
			       'google_plus' => '',
			       'pinterest'   => '',
			       'linkedin'    => '',
			       'tumblr'      => '',
			       'reddit'      => '',
			       'stumbleupon' => '',
			)
		);


		// Disable social share in localhost
		if ( bf_is_localhost() ) {
			return array();
		}


		$post_id = get_the_ID();
		$expired = (int) get_post_meta( $post_id, 'bs_social_share_interval', true );
		$results = array();

		$update_cache = false;

		if ( $expired < time() ) {
			$update_cache = true;
		} else {

			// get count from cache storage
			foreach ( $sites as $site_id => $is_active ) {
				if ( ! $is_active ) {
					continue;
				}

				$count_number = get_post_meta( $post_id, 'bs_social_share_' . $site_id, true );
				$update_cache = $count_number === '';

				if ( $update_cache ) {
					break;
				}

				$results[ $site_id ] = $count_number;
			}
		}

		if ( $update_cache ) { // Update cache storage if needed
			$current_page = bf_social_share_guss_current_page();

			foreach ( $sites as $site_id => $is_active ) {
				if ( ! $is_active ) {
					continue;
				}

				$count_number = bf_social_share_fetch_count( $site_id, $current_page['page_permalink'] );

				update_post_meta( $post_id, 'bs_social_share_' . $site_id, $count_number );

				$results[ $site_id ] = $count_number;
			}

			/**
			 *
			 * This filter can be used to change share count time.
			 *
			 */
			$cache_time = apply_filters( 'bs-social-share/cache-time', MINUTE_IN_SECONDS * 120, $post_id );

			update_post_meta( $post_id, 'bs_social_share_interval', time() + $cache_time );
		}

		return apply_filters( 'bs-social-share/shares-count', $results );

	} // bf_social_shares_count
}


if ( ! function_exists( 'bf_social_share_guss_current_page' ) ) {
	/**
	 * Detects and returns current page info for social share
	 *
	 * @param WP_Query $query
	 *
	 * @return array
	 */
	function bf_social_share_guss_current_page( $query = null ) {

		if ( is_null( $query ) ) {
			global $wp_query;
			$query = $wp_query;
		}

		if ( bf_is_doing_ajax() ) {
			$page_title = get_the_title();

			if ( bf_social_share_permalink_type() === 'permalink' ) {
				$page_permalink = get_the_permalink();
			} else {
				$page_permalink = wp_get_shortlink();
			}
		} elseif ( $query->is_singular() ) {
			$page_title = get_the_title();

			if ( bf_social_share_permalink_type() === 'permalink' ) {
				$page_permalink = get_the_permalink();
			} else {
				$page_permalink = wp_get_shortlink();
			}
		} elseif ( $query->is_home() || $query->is_front_page() ) {
			$page_title     = get_bloginfo( 'name' );
			$page_permalink = home_url( '/' );
		} elseif ( $query->is_category() || $query->is_tag() || $query->is_tax() ) {
			$page_title     = single_term_title( '', false );
			$page_permalink = '';

			if ( bf_social_share_permalink_type() === 'shortlink' ) {

				$queried_object = get_queried_object();

				if ( ! empty( $queried_object->taxonomy ) ) {

					if ( 'category' == $queried_object->taxonomy ) {
						$page_permalink = "?cat=$queried_object->term_id";
					} else {
						$tax = get_taxonomy( $queried_object->taxonomy );

						if ( $tax->query_var ) {
							$page_permalink = "?$tax->query_var=$queried_object->slug";
						} else {
							$page_permalink = "?taxonomy=$queried_object->taxonomy&term=$queried_object->term_id";
						}
					}

					$page_permalink = home_url( $page_permalink );
				}
			}

			if ( empty( $page_permalink ) ) {
				$page_permalink = get_term_link( $query->get_queried_object_id() );
			}

		} else {
			$page_title     = get_bloginfo( 'name' );
			$page_permalink = get_home_url();
		}

		if ( ! empty( $page_title ) ) {
			$page_title = urlencode( strip_tags( $page_title ) );
		}

		return compact( 'page_title', 'page_permalink' );
	}
}


if ( ! function_exists( 'bf_social_share_permalink_type' ) ) {
	/**
	 * Returns permalink type for share system
	 *
	 * @return array
	 */
	function bf_social_share_permalink_type() {

		static $type;

		if ( $type ) {
			return $type;
		}

		return $type = apply_filters( 'better-framework/share/permalink/type', 'permalink' );
	}
}


if ( ! function_exists( 'bf_social_share_fetch_count' ) ) {
	/**
	 * Fetches share count for URL
	 *
	 * @param $site_id
	 * @param $url
	 *
	 * @return int
	 */
	function bf_social_share_fetch_count( $site_id, $url ) {

		$count       = 0;
		$remote_args = array(
			'sslverify' => false,
		);

		switch ( $site_id ) {

			case 'facebook':

				static $fb_api;

				if ( ! $fb_api ) {
					$fb_api = apply_filters( 'better-framework/api/token/facebook', array(
						'id'     => '',
						'secret' => '',
					) );
				}

				if ( ! empty( $fb_api['id'] ) && ! empty( $fb_api['secret'] ) ) {
					$api_url = 'https://graph.facebook.com/v2.9/?id=' . urlencode( $url ) . '&fields=engagement&access_token=' . $fb_api['id'] . '|' . $fb_api['secret'];
				} else {
					$api_url = 'http://graph.facebook.com/?id=' . urlencode( $url );
				}

				$remote = wp_remote_get( $api_url, $remote_args );

				if ( ! is_wp_error( $remote ) ) {

					$response = json_decode( wp_remote_retrieve_body( $remote ), true );

					$count = 0;

					if ( isset( $response['engagement']['reaction_count'] ) ) {
						$count += $response['engagement']['reaction_count'];
					}

					if ( isset( $response['engagement']['comment_count'] ) ) {
						$count += $response['engagement']['comment_count'];
					}

					if ( isset( $response['engagement']['comment_plugin_count'] ) ) {
						$count += $response['engagement']['comment_plugin_count'];
					}

					if ( isset( $response['engagement']['share_count'] ) ) {
						$count += $response['engagement']['share_count'];
					} elseif ( isset( $response['share']['share_count'] ) ) {
						$count += $response['share']['share_count'];
					}
				}

				// FB limit
				if ( wp_remote_retrieve_response_code( $remote ) == 403 ) {
					Better_Framework()->admin_notices()->add_notice( array(
						'type'        => 'static',
						'dismissible' => true,
						'id'          => 'share-facebook-rate-limit',
						'state'       => 'warning',
						'msg'         => __( 'Facebook API rate limitation was reached. You\'r site will have some limitation in Facebook share count.', 'better-studio' ),
						'user_role'   => array( 'administrator' ),
					) );
				}

				break;

			case 'google_plus':
				$post_data = '[{"method":"pos.plusones.get","id":"p","params":{"nolog":true,"id":"' . rawurldecode( $url ) . '","source":"widget","userId":"@viewer","groupId":"@self"},"jsonrpc":"2.0","key":"p","apiVersion":"v1"}]';

				$remote = wp_remote_post( 'https://clients6.google.com/rpc', array(
					'body'      => $post_data,
					'headers'   => 'Content-type: application/json',
					'sslverify' => false,
				) );

				if ( ! is_wp_error( $remote ) ) {

					$response = json_decode( wp_remote_retrieve_body( $remote ), true );

					if ( isset( $response[0]['result']['metadata']['globalCounts']['count'] ) ) {
						$count = $response[0]['result']['metadata']['globalCounts']['count'];
					}

				}

				break;

			case 'pinterest':
				$remote = wp_remote_get( 'http://api.pinterest.com/v1/urls/count.json?callback=CALLBACK&url=' . $url, $remote_args );

				if ( ! is_wp_error( $remote ) ) {

					if ( preg_match( '/^\s*CALLBACK\s*\((.+)\)\s*$/', wp_remote_retrieve_body( $remote ), $match ) ) {
						$response = json_decode( $match[1], true );

						if ( isset( $response['count'] ) ) {
							$count = $response['count'];
						}
					}

				}

				break;

			case 'linkedin':
				$remote = wp_remote_get( 'https://www.linkedin.com/countserv/count/share?format=json&url=' . $url, $remote_args );

				if ( ! is_wp_error( $remote ) ) {

					$response = json_decode( wp_remote_retrieve_body( $remote ), true );

					if ( isset( $response['count'] ) ) {
						$count = $response['count'];
					}

				}

				break;

			case 'tumblr':
				$remote = wp_remote_get( 'http://api.tumblr.com/v2/share/stats?url=' . $url, $remote_args );

				if ( ! is_wp_error( $remote ) ) {

					$response = json_decode( wp_remote_retrieve_body( $remote ), true );

					if ( isset( $response['response']['note_count'] ) ) {
						$count = $response['response']['note_count'];
					}

				}

				break;


			case 'reddit':
				$remote = wp_remote_get( 'http://www.reddit.com/api/info.json?url=' . $url, $remote_args );

				if ( ! is_wp_error( $remote ) ) {

					$response = json_decode( $remote['body'], true );

					if ( isset( $response['data']['children']['0']['data']['score'] ) ) {
						$count = $response['data']['children']['0']['data']['score'];
					}

				}

				break;

			case 'stumbleupon':
				$remote = wp_remote_get( 'http://www.stumbleupon.com/services/1.01/badge.getinfo?url=' . $url, $remote_args );

				if ( ! is_wp_error( $remote ) ) {

					$response = json_decode( $remote['body'], true );

					if ( isset( $response['result']['views'] ) ) {
						$count = $response['result']['views'];
					}

				}


				break;

		}

		return $count;
	} // bf_social_share_fetch_count
}

if ( ! function_exists( 'bf_esc_file_path' ) ) {

	/**
	 * Sanitize file path
	 *
	 * @param string $path
	 *
	 * @since 2.9.0
	 * @return string
	 */
	function bf_esc_file_path( $path ) {

		$path = str_replace( '/./', '/', $path );
		if ( strstr( $path, '..' ) ) {
			$join = explode( '/', $path );
			$key  = - 1;
			foreach ( $join as $j ) {
				$key ++;
				if ( trim( $j ) == '..' ) {
					unset( $join[ $key - 1 ] );
					unset( $join[ $key ] );
					$key  -= 2;
					$join = array_merge( $join, array() );//sort keys
				}
			}
			$path = implode( '/', $join );
		}

		return $path;
	}
}


if ( ! function_exists( 'bf_array_insert_before' ) ) {

	/**
	 * Inserts a new key/value before the key in the array.
	 *
	 * @param  string $key       The key to insert before.
	 * @param  array  $array     An array to insert in to.
	 * @param  string $new_key   The key to insert.
	 * @param  mixed  $new_value An value to insert.
	 *
	 * @since 2.10.0
	 * @return array The new array if the key exists, false otherwise.
	 */
	function bf_array_insert_before( $key, array &$array, $new_key, $new_value ) {

		if ( array_key_exists( $key, $array ) ) {
			$new = array();
			foreach ( $array as $k => $value ) {
				if ( $k === $key ) {
					$new[ $new_key ] = $new_value;
				}
				$new[ $k ] = $value;
			}

			return $new;
		}

		return false;
	}
}


if ( ! function_exists( 'bf_array_insert_after' ) ) {

	/**
	 * Inserts a new key/value after the key in the array.
	 *
	 * @param string $key       The key to insert after.
	 * @param array  $array     An array to insert in to.
	 * @param string $new_key   The key to insert.
	 * @param mixed  $new_value An value to insert.
	 *
	 * @since 2.10.0
	 * @return array The new array if the key exists, false otherwise.
	 */
	function bf_array_insert_after( $key, array &$array, $new_key, $new_value ) {

		if ( array_key_exists( $key, $array ) ) {

			$new = array();

			foreach ( $array as $k => $value ) {

				$new[ $k ] = $value;

				if ( $k === $key ) {
					$new[ $new_key ] = $new_value;
				}
			}

			return $array = $new;

		} else {
			$array[ $new_key ] = $new_value;
		}

		return $array;
	}
}


if ( ! function_exists( 'bf_list_attributes' ) ) {

	/**
	 * List all html tag attributes
	 *
	 * @note
	 *
	 * use wp_kses_hair to parse attributes in more detail
	 *
	 * @param string $tag
	 *
	 * @note  use wp_kses_hair to parse attributes in more detail
	 *
	 * @since 2.10.0
	 * @return array|bool array on success or false on failure.
	 */
	function bf_list_attributes( $tag ) {

		if ( ! preg_match_all( "'\s+(.*?)\s*=\s*	    # find  attribute=
						([\"\'])?					    # find single or double quote
						(?(2) (.*?)\\2 | ([^\s\>]+))	# if quote found, match up to next matching
						'isx", $tag, $match )
		) {
			return false;
		}

		$atts = array();

		foreach ( $match[1] as $index => $attr_key ) {

			$value_index = $match[2][ $index ] ? 3 : 4;
			$attr_value  = $match[ $value_index ][ $index ];

			$atts[ $attr_key ] = $attr_value;
		}

		return $atts;
	}
}


if ( ! function_exists( 'bf_get_align' ) ) {
	/**
	 * Get current direction
	 *
	 * @param boolean $opposite
	 *
	 * @since 2.10.0
	 * @return string
	 */
	function bf_get_align( $opposite = false ) {

		return ( ( is_rtl() xor $opposite ) ? 'right' : 'left' );
	}
}


if ( ! function_exists( '_bf_reverse_right_left' ) ) {
	/**
	 *
	 *
	 * @param array $matches
	 *
	 * @use   private
	 *
	 * @since 2.10.0
	 * @return string
	 */
	function _bf_reverse_right_left( $matches ) {

		return $matches[1] === 'right' ? 'left' : 'right';
	}
}


if ( ! function_exists( 'bf_reverse_direction' ) ) {
	/**
	 * Reverse right/left words in RTL site direction
	 *
	 * @param string $string
	 *
	 * @since 2.10.0
	 * @return string
	 */
	function bf_reverse_direction( $string ) {

		if ( is_rtl() ) {
			$string = preg_replace_callback( '/\b(left|right)\b/', '_bf_reverse_right_left', $string );
		}

		return $string;
	}
}


if ( ! function_exists( 'bf_remove_class_filter' ) ) {
	/**
	 * Remove Class Filter Without Access to Class Object
	 *
	 * In order to use the core WordPress remove_filter() on a filter added with the callback
	 * to a class, you either have to have access to that class object, or it has to be a call
	 * to a static method.  This method allows you to remove filters with a callback to a class
	 * you don't have access to.
	 *
	 * Works with WordPress 1.2+ (4.7+ support added 9-19-2016)
	 * Updated 2-27-2017 to use internal WordPress removal for 4.7+ (to prevent PHP warnings output)
	 *
	 * @param string $tag         Filter to remove
	 * @param string $class_name  Class name for the filter's callback
	 * @param string $method_name Method name for the filter's callback
	 * @param int    $priority    Priority of the filter (default 10)
	 *
	 *
	 * Copyright: https://gist.github.com/tripflex/c6518efc1753cf2392559866b4bd1a53
	 *
	 * @return bool Whether the function is removed.
	 */
	function bf_remove_class_filter( $tag, $class_name = '', $method_name = '', $priority = 10 ) {

		global $wp_filter;

		// Check that filter actually exists first
		if ( ! isset( $wp_filter[ $tag ] ) ) {
			return false;
		}

		/**
		 * If filter config is an object, means we're using WordPress 4.7+ and the config is no longer
		 * a simple array, rather it is an object that implements the ArrayAccess interface.
		 *
		 * To be backwards compatible, we set $callbacks equal to the correct array as a reference (so $wp_filter is updated)
		 *
		 * @see https://make.wordpress.org/core/2016/09/08/wp_hook-next-generation-actions-and-filters/
		 */
		if ( is_object( $wp_filter[ $tag ] ) && isset( $wp_filter[ $tag ]->callbacks ) ) {
			// Create $fob object from filter tag, to use below
			$fob       = $wp_filter[ $tag ];
			$callbacks = &$wp_filter[ $tag ]->callbacks;
		} else {
			$callbacks = &$wp_filter[ $tag ];
		}

		// Exit if there aren't any callbacks for specified priority
		if ( ! isset( $callbacks[ $priority ] ) || empty( $callbacks[ $priority ] ) ) {
			return false;
		}

		// Loop through each filter for the specified priority, looking for our class & method
		foreach ( (array) $callbacks[ $priority ] as $filter_id => $filter ) {
			// Filter should always be an array - array( $this, 'method' ), if not goto next
			if ( ! isset( $filter['function'] ) || ! is_array( $filter['function'] ) ) {
				continue;
			}
			// If first value in array is not an object, it can't be a class
			if ( ! is_object( $filter['function'][0] ) ) {
				continue;
			}
			// Method doesn't match the one we're looking for, goto next
			if ( $filter['function'][1] !== $method_name ) {
				continue;
			}
			// Method matched, now let's check the Class
			if ( get_class( $filter['function'][0] ) === $class_name ) {
				// WordPress 4.7+ use core remove_filter() since we found the class object
				if ( isset( $fob ) ) {
					// Handles removing filter, reseting callback priority keys mid-iteration, etc.
					$fob->remove_filter( $tag, $filter['function'], $priority );
				} else {
					// Use legacy removal process (pre 4.7)
					unset( $callbacks[ $priority ][ $filter_id ] );
					// and if it was the only filter in that priority, unset that priority
					if ( empty( $callbacks[ $priority ] ) ) {
						unset( $callbacks[ $priority ] );
					}
					// and if the only filter for that tag, set the tag to an empty array
					if ( empty( $callbacks ) ) {
						$callbacks = array();
					}
					// Remove this filter from merged_filters, which specifies if filters have been sorted
					unset( $GLOBALS['merged_filters'][ $tag ] );
				}

				return true;
			}
		}

		return false;
	} // bf_remove_class_filter
}


if ( ! function_exists( 'bf_remove_class_action' ) ) {
	/**
	 * Remove Class Action Without Access to Class Object
	 *
	 * In order to use the core WordPress remove_action() on an action added with the callback
	 * to a class, you either have to have access to that class object, or it has to be a call
	 * to a static method.  This method allows you to remove actions with a callback to a class
	 * you don't have access to.
	 *
	 * Works with WordPress 1.2+ (4.7+ support added 9-19-2016)
	 *
	 * @param string $tag         Action to remove
	 * @param string $class_name  Class name for the action's callback
	 * @param string $method_name Method name for the action's callback
	 * @param int    $priority    Priority of the action (default 10)
	 *
	 * Copyright: https://gist.github.com/tripflex/c6518efc1753cf2392559866b4bd1a53
	 *
	 * @return bool               Whether the function is removed.
	 */
	function bf_remove_class_action( $tag, $class_name = '', $method_name = '', $priority = 10 ) {

		return bf_remove_class_filter( $tag, $class_name, $method_name, $priority );
	}
}


if ( ! function_exists( 'bf_item_can_shown' ) ) {
	/**
	 * detects item can shown or not
	 *
	 * @param array $item
	 *
	 * @return bool
	 */
	function bf_item_can_shown( $item = array() ) {

		if ( empty( $item ) ) {
			return false;
		}

		// Page filter
		if ( ! empty( $item['page'] ) ) {

			if ( is_admin() ) {
				global $pagenow;

				return in_array( $pagenow, (array) $item['page'] );
			}
		}


		// User role filter
		if ( ! empty( $item['user_role'] ) ) {

			if ( is_string( $item['user_role'] ) ) {
				$item['user_role'] = array( $item['user_role'] );
			}

			$user = wp_get_current_user();

			if ( ! array_intersect( $item['user_role'], (array) $user->roles ) ) {
				return false;
			}
		}

		return true;
	}
}


if ( ! function_exists( 'bf_render_css_block_array' ) ) {
	/**
	 * Converts BF CSS Array to CSS code
	 *
	 * @param array $block
	 * @param       $value
	 *
	 * @return array
	 */
	function bf_render_css_block_array( $block, $value ) {

		if ( empty( $block ) || ! is_array( $block ) ) {
			return array( 'code' => '' );
		}

		$result = array(
			'code' => '',
		);

		$skip_validation = empty( $block['skip_validation'] );

		// if value is empty
		if ( ( $value === false || $value == '' ) && $skip_validation ) {
			return $result;
		} elseif ( ! $skip_validation ) {
			unset( $block['skip_validation'] );
		}

		// Custom callbacks for generating CSS
		if ( isset( $block['callback'] ) && is_callable( $block['callback'] ) ) {
			call_user_func_array( $block['callback'], array( &$block, &$value ) );
		}


		$after_value = '';
		$after_block = '';

		// Uncompressed in dev mode
		if ( bf_is( 'dev' ) ) {
			$ln_char  = "\n";
			$tab_char = "\t";
		} else {
			$ln_char  = "";
			$tab_char = "";
		}

		if ( isset( $block['newline'] ) ) {
			$result['code'] .= "\r\n";
		}

		if ( isset( $block['comment'] ) || ! empty( $block['comment'] ) ) {
			$result['code'] .= '/* ' . $block['comment'] . ' */' . "\r\n";
		}


		// Filters
		if ( isset( $block['filter'] ) ) {

			//
			// Last versions compatibility
			//
			if ( ( $index = array_search( 'woocommerce', $block['filter'] ) ) !== false ) {
				$block['filter'][ $index ] = array(
					'type'      => 'function',
					'condition' => 'is_woocommerce',
				);
			}
			if ( ( $index = array_search( 'bbpress', $block['filter'] ) ) !== false ) {
				$block['filter'][ $index ] = array(
					'type'      => 'class',
					'condition' => 'bbpress',
				);
			}
			if ( ( $index = array_search( 'buddypress', $block['filter'] ) ) !== false ) {
				$block['filter'][ $index ] = array(
					'type'      => 'function',
					'condition' => 'bp_is_active',
				);
			}

			if ( ( $index = array_search( 'wpml', $block['filter'] ) ) !== false ) {
				$block['filter'][ $index ] = array(
					'type'      => 'constantn',
					'condition' => 'ICL_SITEPRESS_VERSIOe',
				);
			}

			//
			// /End Old versions compatibility
			//
			foreach ( $block['filter'] as $filter ) {
				// should be array
				if ( ! is_array( $filter ) ) {
					continue;
				}

				switch ( $filter['type'] ) {

					case 'function':
						if ( ! function_exists( $filter['condition'] ) ) {
							return array(
								'code' => ''
							);
						}
						break;

					case 'class':
						if ( ! class_exists( $filter['condition'] ) ) {
							return array(
								'code' => ''
							);
						}
						break;

					case 'constant':
						if ( ! defined( $filter['condition'] ) ) {
							return array(
								'code' => ''
							);
						}
						break;

				}

			}

		}

		// Before than css code. For example used for adding media queries!.
		if ( isset( $block['before'] ) ) {

			if ( is_string( $value ) ) {
				$result['code'] .= str_replace( '%%value%%', $value, $block['before'] ) . $ln_char;
			} else {
				$result['code'] .= $block['before'] . $ln_char;
			}
		}

		// Prepare Selectors.
		if ( isset( $block['selector'] ) ) {
			if ( ! is_array( $block['selector'] ) ) {
				$result['code'] .= $block['selector'] . '{' . $ln_char;
			} else {
				$result['code'] .= implode( ',' . $ln_char, $block['selector'] ) . '{' . $ln_char;
			}
		}

		// Prepare Value For Font Field
		if ( isset( $block['type'] ) && $block['type'] == 'font' ) {

			// If font is not enable then don't echo css
			if ( isset( $value['enable'] ) && ! $value['enable'] ) {
				return array(
					'code' => ''
				);
			}

			if ( isset( $block['exclude'] ) ) {
				foreach ( (array) $block['exclude'] as $exclude ) {
					unset( $value[ $exclude ] );
				}
			}

			$font_stacks = Better_Framework::fonts_manager()->font_stacks()->get_font( $value['family'] );

			if ( isset( $block['important-attr'] ) && in_array( 'font-family', $block['important-attr'] ) ) {
				$_temp = '!important';
			} else {
				$_temp = '';
			}

			if ( $font_stacks ) {
				$result['code'] .= $tab_char . 'font-family:' . $font_stacks['stack'] . $_temp . ';' . $ln_char;
			} else {
				$result['code'] .= $tab_char . 'font-family:\'' . $value['family'] . $_temp . '\';' . $ln_char;
			}

			// new api fix
			if ( $value['variant'] == 'regular' ) {
				$value['variant'] = '400';
			} elseif ( $value['variant'] == 'italic' ) {
				$value['variant'] = '400italic';
			}

			if ( preg_match( '/\d{3}\w./i', $value['variant'] ) ) {
				$pretty_variant = preg_replace( '/(\d{3})/i', '${1} ', $value['variant'] );
				$pretty_variant = explode( ' ', $pretty_variant );
			} else {
				$pretty_variant[] = $value['variant'];
			}

			if ( isset( $block['important-attr'] ) && in_array( 'font-weight', $block['important-attr'] ) ) {
				$_temp = '!important';
			} else {
				$_temp = '';
			}

			if ( isset( $pretty_variant[0] ) ) {
				$result['code'] .= $tab_char . 'font-weight:' . $pretty_variant[0] . $_temp . ';' . $ln_char;
			}

			if ( isset( $block['important-attr'] ) && in_array( 'font-style', $block['important-attr'] ) ) {
				$_temp = '!important';
			} else {
				$_temp = '';
			}

			if ( isset( $pretty_variant[1] ) ) {
				$result['code'] .= $tab_char . 'font-style:' . $pretty_variant[1] . $_temp . ';' . $ln_char;
			}


			$line_height_id = 'line-height';

			if ( isset( $value['line_height'] ) ) {
				$line_height_id = 'line_height';
			} // older versions compatibility

			if ( isset( $block['important-attr'] ) && in_array( $line_height_id, $block['important-attr'] ) ) {
				$_temp = '!important';
			} else {
				$_temp = '';
			}

			if ( isset( $value[ $line_height_id ] ) && ! empty( $value[ $line_height_id ] ) ) {
				$result['code'] .= $tab_char . 'line-height:' . $value[ $line_height_id ] . 'px;' . $_temp . $ln_char;
			}

			if ( isset( $block['important-attr'] ) && in_array( 'size', $block['important-attr'] ) ) {
				$_temp = '!important';
			} else {
				$_temp = '';
			}

			if ( isset( $value['size'] ) ) {
				$result['code'] .= $tab_char . 'font-size:' . $value['size'] . 'px;' . $_temp . $ln_char;
			}

			if ( isset( $block['important-attr'] ) && in_array( 'align', $block['important-attr'] ) ) {
				$_temp = '!important';
			} else {
				$_temp = '';
			}

			if ( isset( $value['align'] ) ) {
				$result['code'] .= $tab_char . 'text-align:' . $value['align'] . $_temp . ';' . $ln_char;
			}

			if ( isset( $block['important-attr'] ) && in_array( 'transform', $block['important-attr'] ) ) {
				$_temp = '!important';
			} else {
				$_temp = '';
			}

			if ( isset( $value['transform'] ) ) {
				$result['code'] .= $tab_char . 'text-transform:' . $value['transform'] . $_temp . ';' . $ln_char;
			}

			if ( isset( $block['important-attr'] ) && in_array( 'color', $block['important-attr'] ) ) {
				$_temp = '!important';
			} else {
				$_temp = '';
			}

			if ( isset( $value['color'] ) ) {
				$result['code'] .= $tab_char . 'color:' . $value['color'] . $_temp . ';' . $ln_char;
			}

			if ( isset( $block['important-attr'] ) && in_array( 'letter-spacing', $block['important-attr'] ) ) {
				$_temp = '!important';
			} else {
				$_temp = '';
			}

			if ( ! empty( $value['letter-spacing'] ) ) {
				$result['code'] .= $tab_char . 'letter-spacing:' . $value['letter-spacing'] . $_temp . ';' . $ln_char;
			}

			// Add Font To Fonts Queue
			$result['font'] = array(
				'family'  => $value['family'],
				'variant' => $value['variant'],
				'subset'  => $value['subset'],
			);
		}

		// prepare value for "background-image" type
		if ( isset( $block['type'] ) && $block['type'] == 'background-image' ) {

			if ( empty( $value['img'] ) ) {
				return array(
					'code' => ''
				);
			}

			// Full Cover Image
			if ( $value['type'] == 'cover' ) {
				$after_value .= $tab_char . 'background-repeat: no-repeat;background-position: center center; -webkit-background-size: cover; -moz-background-size: cover;-o-background-size: cover; background-size: cover;'
				                . 'filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' . $value['img'] . '\', sizingMethod=\'scale\');
-ms-filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' . $value['img'] . '\', sizingMethod=\'scale\')";'
				                . $ln_char;

				$value = 'url(' . $value['img'] . ')';
			} // Fit Cover
			elseif ( $value['type'] == 'fit-cover' ) {
				$after_value .= $tab_char . 'background-repeat: no-repeat;background-position: center center; -webkit-background-size: contain; -moz-background-size: contain;-o-background-size: contain; background-size: contain;'
				                . 'filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' . $value['img'] . '\', sizingMethod=\'scale\');
-ms-filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' . $value['img'] . '\', sizingMethod=\'scale\')";'
				                . $ln_char;

				$value = 'url(' . $value['img'] . ')';
			} // Parallax Image
			elseif ( $value['type'] == 'parallax' ) {
				$after_value .= $tab_char . 'background-repeat: no-repeat;background-attachment: fixed; background-position: center center; -webkit-background-size: cover; -moz-background-size: cover;-o-background-size: cover; background-size: cover;'
				                . 'filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' . $value['img'] . '\', sizingMethod=\'scale\');
-ms-filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' . $value['img'] . '\', sizingMethod=\'scale\')";'
				                . $ln_char;

				$value = 'url(' . $value['img'] . ')';
			} else {
				switch ( $value['type'] ) {

					case 'repeat':
					case 'cover':
					case 'repeat-y':
					case 'repeat-x':
						$after_value .= $tab_char . 'background-repeat:' . $value['type'] . ';' . $ln_char;
						break;

					case 'top-left':
						$after_value .= $tab_char . 'background-repeat: no-repeat;' . $ln_char;
						$after_value .= $tab_char . 'background-position: top left;' . $ln_char;
						break;

					case 'top-center':
						$after_value .= $tab_char . 'background-repeat: no-repeat;' . $ln_char;
						$after_value .= $tab_char . 'background-position: top center;' . $ln_char;
						break;

					case 'top-right':
						$after_value .= $tab_char . 'background-repeat: no-repeat;' . $ln_char;
						$after_value .= $tab_char . 'background-position: top right;' . $ln_char;
						break;

					case 'left-center':
						$after_value .= $tab_char . 'background-repeat: no-repeat;' . $ln_char;
						$after_value .= $tab_char . 'background-position: left center;' . $ln_char;
						break;

					case 'center-center':
						$after_value .= $tab_char . 'background-repeat: no-repeat;' . $ln_char;
						$after_value .= $tab_char . 'background-position: center center;' . $ln_char;
						break;

					case 'right-center':
						$after_value .= $tab_char . 'background-repeat: no-repeat;' . $ln_char;
						$after_value .= $tab_char . 'background-position: right center;' . $ln_char;
						break;

					case 'bottom-left':
						$after_value .= $tab_char . 'background-repeat: no-repeat;' . $ln_char;
						$after_value .= $tab_char . 'background-position: bottom left;' . $ln_char;
						break;

					case 'bottom-center':
						$after_value .= $tab_char . 'background-repeat: no-repeat;' . $ln_char;
						$after_value .= $tab_char . 'background-position: bottom center;' . $ln_char;
						break;

					case 'bottom-right':
						$after_value .= $tab_char . 'background-repeat: no-repeat;' . $ln_char;
						$after_value .= $tab_char . 'background-position: bottom right;' . $ln_char;
						break;

				}
				$value = 'url(' . $value['img'] . ')';
			}

		}

		// prepare value for "color" type
		if ( isset( $block['type'] ) && $block['type'] == 'color' ) {
			if ( preg_match( '/%%value([-|+]\d*)%%/', $block['value'], $change ) ) {
				Better_Framework::factory( 'color' );
				$value = preg_replace( '/(%%value[-|+]\d*%%)/', BF_Color::change_color( $value, intval( $change[1] ) ), $block['value'] );
			} elseif ( preg_match( '/%%value-opacity-(.*)%%/', $block['value'], $opacity ) ) {
				Better_Framework::factory( 'color' );
				$value = preg_replace( '/(%%value-opacity-.*%%)/', BF_Color::hex_to_rgba( $value, $opacity[1] ), $block['value'] );
			}
		}

		// prepare value for "border" type
		if ( isset( $block['type'] ) && $block['type'] == 'border' ) {

			if ( isset( $value['all'] ) ) {

				$result['code'] .= $tab_char . 'border:';

				if ( isset( $value['all']['width'] ) ) {
					$result['code'] .= $value['all']['width'] . 'px ';
				}
				if ( isset( $value['all']['style'] ) ) {
					$result['code'] .= $value['all']['style'] . ' ';
				}
				if ( isset( $value['all']['color'] ) ) {
					$result['code'] .= $value['all']['color'] . ' ';
				}

				$result['code'] .= ';' . $ln_char;

			} else {

				if ( isset( $value['top'] ) ) {

					$result['code'] .= $tab_char . 'border-top:';

					if ( isset( $value['top']['width'] ) ) {
						$result['code'] .= $value['top']['width'] . 'px ';
					}
					if ( isset( $value['top']['style'] ) ) {
						$result .= $value['top']['style'] . ' ';
					}
					if ( isset( $value['top']['color'] ) ) {
						$result['code'] .= $value['top']['color'] . ' ';
					}

					$result['code'] .= ';' . $ln_char;

				}

				if ( isset( $value['right'] ) ) {

					$result['code'] .= $tab_char . 'border-right:';

					if ( isset( $value['right']['width'] ) ) {
						$result['code'] .= $value['right']['width'] . 'px ';
					}
					if ( isset( $value['right']['style'] ) ) {
						$result['code'] .= $value['right']['style'] . ' ';
					}
					if ( isset( $value['right']['color'] ) ) {
						$result['code'] .= $value['right']['color'] . ' ';
					}

					$result['code'] .= ';' . $ln_char;

				}
				if ( isset( $value['bottom'] ) ) {

					$result['code'] .= $tab_char . 'border-bottom:';

					if ( isset( $value['bottom']['width'] ) ) {
						$result['code'] .= $value['bottom']['width'] . 'px ';
					}
					if ( isset( $value['bottom']['style'] ) ) {
						$result['code'] .= $value['bottom']['style'] . ' ';
					}
					if ( isset( $value['bottom']['color'] ) ) {
						$result['code'] .= $value['bottom']['color'] . ' ';
					}

					$result['code'] .= ';' . $ln_char;

				}

				if ( isset( $value['left'] ) ) {

					$result['code'] .= $tab_char . 'border-left:';

					if ( isset( $value['left']['width'] ) ) {
						$result['code'] .= $value['left']['width'] . 'px ';
					}
					if ( isset( $value['left']['style'] ) ) {
						$result['code'] .= $value['left']['style'] . ' ';
					}
					if ( isset( $value['left']['color'] ) ) {
						$result['code'] .= $value['left']['color'] . ' ';
					}

					$result['code'] .= ';' . $ln_char;

				}

			}

		}

		// Prepare Properties
		if ( isset( $block['prop'] ) ) {

			foreach ( (array) $block['prop'] as $key => $val ) {

				// Customized value template for property
				if ( strpos( $val, '%%value%%' ) !== false ) {

					$result['code'] .= $tab_char . $key . ':';
					$result['code'] .= str_replace( '%%value%%', $value, $val ) . ';' . $ln_char;

				} // Simply set value to property
				else {

					if ( ! is_int( $key ) ) {

						$result['code'] .= $tab_char . $key . ':' . $val . ';' . $ln_char;

					} elseif ( ! is_array( $value ) ) {

						$result['code'] .= $tab_char . $val . ':' . $value . ';' . $ln_char;

					}

				}
			}

		}

		// add after value
		if ( isset( $after_value ) && $after_value != '' ) {
			$result['code'] .= $after_value;
		}

		// Remove last ';'
		$result['code'] = rtrim( $result['code'], ';' );

		if ( isset( $block['selector'] ) ) {
			$result['code'] .= "}" . $ln_char;
		}

		// After css code. For example used for adding media queries!.
		if ( isset( $block['after'] ) && is_string( $value ) ) {
			$result['code'] .= str_replace( '%%value%%', $value, $block['after'] ) . $ln_char;
		}

		return $result;
	}
}

if ( ! function_exists( 'bf_starts_with' ) ) {
	/**
	 * Check string start with
	 *
	 * @param $haystack
	 * @param $needle
	 *
	 * @return bool
	 */
	function bf_starts_with( $haystack, $needle ) {

		return $needle === '' || strrpos( $haystack, $needle, - strlen( $haystack ) ) !== false;
	}
}

if ( ! function_exists( 'bf_ends_with' ) ) {

	/**
	 * Check string end with
	 *
	 * @param $haystack
	 * @param $needle
	 *
	 * @return bool
	 */
	function bf_ends_with( $haystack, $needle ) {

		return $needle === '' || ( ( $temp = strlen( $haystack ) - strlen( $needle ) ) >= 0 && strpos( $haystack, $needle, $temp ) !== false );
	}
}

if ( ! function_exists( 'bf_found_closest_number' ) ) {

	/**
	 * Find closest number in the array
	 *
	 * @param array  $array  Ascending sorted array
	 * @param int    $number number you are looking for
	 * @param string $round  up|down  round fractions up/down
	 *
	 * TODO: optimized it!
	 *
	 * @since 3.0.1
	 * @return void|int index of array on success
	 */
	function bf_found_closest_number( $array, $number, $round = 'up' ) {

		$pivot       = array_rand( $array );
		$status      = 0; // 1: increasing, 2: decreasing
		$found_pivot = null;


		while( isset( $array[ $pivot ] ) ) {

			if ( $array[ $pivot ] === $number ) {
				return $array[ $pivot ];
			}

			if ( $array[ $pivot ] > $number ) {

				if ( $status === 1 ) {
					$found_pivot = $pivot;
					break;
				}

				$pivot --;
				$status = 2;

			} else {

				$pivot ++;

				if ( $status === 2 ) {
					$found_pivot = $pivot;
					break;
				}

				$status = 1;
			}
		}

		if ( is_null( $found_pivot ) ) {

			$first = $array[ key( $array ) ];
			if ( $first > $number ) {

				if ( $round === 'up' ) {
					return $first;
				}

			} else {

				if ( $round === 'down' ) {

					return end( $array );
				}
			}
		}

		if ( ! is_null( $found_pivot ) ) {

			if ( $round === 'up' ) {
				return $array[ $found_pivot ];
			}

			return $array[ $found_pivot - 1 ];
		}
	}
}


if ( ! function_exists( 'bf_is_user_logged_in' ) ) {
	/**
	 * Performance optimized function to check current user login status
	 *
	 * @return bool
	 */
	function bf_is_user_logged_in() {

		static $logged_in;

		if ( is_null( $logged_in ) ) {
			$logged_in = is_user_logged_in();
		}

		return $logged_in;
	}
}


if ( ! function_exists( 'bf_is_amp' ) ) {
	/**
	 * Detects active AMP page & plugin
	 *
	 * @return bool
	 */
	function bf_is_amp() {

		static $is_amp;

		if ( ! is_null( $is_amp ) ) {
			return $is_amp;
		}

		// BetterAMP plugin
		if ( function_exists( 'is_better_amp' ) && is_better_amp() ) {
			$is_amp = 'better';
		} // Official AMP Plugin
		elseif ( function_exists( 'is_amp_endpoint' ) && is_amp_endpoint() ) {
			$is_amp = 'amp';
		} else {
			$is_amp = false;
		}

		return $is_amp;
	}
}


if ( ! function_exists( 'bf_is_fia' ) ) {
	/**
	 * Detects active Facebook Instant Article plugin
	 *
	 * @return bool
	 */
	function bf_is_fia() {

		static $state;

		if ( ! is_null( $state ) ) {
			return $state;
		}

		$state = defined( 'IA_PLUGIN_VERSION' ) && function_exists( 'is_transforming_instant_article' ) && is_transforming_instant_article();

		return $state;
	}
}

if ( ! function_exists( 'bf_the_content_by_id' ) ) {
	/**
	 * Prints content of post by the ID.
	 * It handles extra actions like custom CSS prints of blocks and page.
	 *
	 * @param null  $post_id
	 * @param array $args
	 *
	 * @return mixed|string|void
	 */
	function bf_the_content_by_id( $post_id = null, $args = array() ) {

		if ( ! $post_id ) {
			return;
		}

		$post_object = get_post( $post_id );
		$args        = bf_merge_args( $args, array(
			'echo'         => true,
			'context'      => '',
			'add_vs_style' => false,
		) );

		if ( ! $post_object ) {
			return;
		} else {
			$content = apply_filters( 'the_content', $post_object->post_content, $args['context'] );
			$content = do_shortcode( $content );
		}

		//
		// Add custom css of VC page
		//

		if ( apply_filters( 'better-framework/the-content/append-styles', $args['add_vs_style'], $post_object, $args ) ) {
			//
			// Post custom CSS
			//
			$post_custom_css = get_post_meta( $post_id, '_wpb_post_custom_css', true );
			if ( ! empty( $post_custom_css ) ) {
				$post_custom_css = strip_tags( $post_custom_css );
				$content         .= '<style type="text/css" data-type="vc_custom-css">';
				$content         .= $post_custom_css;
				$content         .= '</style>';
			}


			//
			// Post shortcodes CSS
			//
			$shortcodes_custom_css = get_post_meta( $post_id, '_wpb_shortcodes_custom_css', true );
			if ( ! empty( $shortcodes_custom_css ) ) {
				$shortcodes_custom_css = strip_tags( $shortcodes_custom_css );
				$content               .= '<style type="text/css" data-type="vc_shortcodes-custom-css">';
				$content               .= $shortcodes_custom_css;
				$content               .= '</style>';
			}
		}

		if ( $args['echo'] ) {
			echo $content;
		} else {
			return $content;
		}

	}
}

if ( ! function_exists( 'bf_bp_get_current_core_component' ) ) {

	/**
	 * Return current BuddyPress component ID
	 *
	 * @since 3.5.4
	 * @return string
	 */
	function bf_bp_get_current_core_component() {

		if ( ! function_exists( 'bp_core_get_packaged_component_ids' ) ||
		     ! function_exists( 'bp_is_current_component' )
		) {
			return '';
		}

		foreach ( bp_core_get_packaged_component_ids() as $active_component ) {

			if ( bp_is_current_component( $active_component ) ) {

				return $active_component;
			}
		}

		return '';
	}
}

if ( ! function_exists( 'bf_bp_get_component_page_id' ) ) {

	/**
	 * Get page ID of given BuddyPress component
	 *
	 * @param string      $component . optional. default:current component
	 *
	 * @global BuddyPress $bp        Main BuddyPress Class.
	 *
	 * @since 3.5.4
	 * @return int
	 */
	function bf_bp_get_component_page_id( $component = 'auto' ) {

		global $bp;

		if ( ! $bp || ! isset( $bp->pages ) ) {
			return 0;
		}

		if ( 'auto' === $component ) {
			$component = bf_bp_get_current_core_component();
		}

		if ( $component && isset( $bp->pages->$component->id ) ) {
			return $bp->pages->$component->id;
		}

		return 0;
	}
}

if ( ! function_exists( 'bf_file_system_instance' ) ) {

	/**
	 * Get WP FileSystem Object
	 *
	 * @global WP_Filesystem_Base $wp_filesystem WordPress Filesystem Class
	 *
	 * @since 3.9.1
	 * @return WP_Filesystem_Base
	 */
	function bf_file_system_instance() {

		global $wp_filesystem;

		if ( ! $wp_filesystem instanceof WP_Filesystem_Base ) {

			if ( ! function_exists( 'WP_Filesystem' ) ) {
				require_once ABSPATH . '/wp-admin/includes/file.php';
			}

			$credentials['hostname'] = defined( 'FTP_HOST' ) ? FTP_HOST : '';
			$credentials['username'] = defined( 'FTP_USER' ) ? FTP_USER : '';
			$credentials['password'] = defined( 'FTP_PASS' ) ? FTP_PASS : '';

			WP_Filesystem( $credentials, WP_CONTENT_DIR, false );
		}

		return $wp_filesystem;
	}
}

if ( ! function_exists( 'bf_is_block_render_request' ) ) {

	/**
	 * @return bool
	 */
	function bf_is_block_render_request() {

		return (bool) stristr( $_SERVER['REQUEST_URI'], '/block-renderer/better-studio/' );
	}
}


/**
 * Safe count function
 *
 * @since 3.9.3
 * @return integer
 */
function bf_count( $variable ) {

	// PHP > 7.1
	if ( function_exists( 'is_countable' ) && is_countable( $variable ) ) {
		return count( $variable );
	}

	// PHP < 7.2
	if ( is_array( $variable ) ) {
		return count( $variable );
	}

	return 0;
}

libs/better-framework/widget/class-bf-widgets-general-fields.php000064400000042723151214002410020764 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Used for adding fields for all WordPress widgets
 */
class BF_Widgets_General_Fields {


	/**
	 * Contain active general fields
	 *
	 * @var array
	 */
	var $fields = array();


	/**
	 * Contain current fields options
	 *
	 * @var array
	 */
	private $options = array();


	/**
	 * Contains list of all valid general field ID
	 *
	 * @var array
	 */
	static $valid_general_fields = array(

		// title Fields
		'bf-widget-bg-color',
		'bf-widget-title-color',
		'bf-widget-title-bg-color',
		'bs-text-color-scheme',
		'bf-widget-title-icon',
		'bf-widget-title-link',
		'bf-widget-title-style',

		// Responsive Fields
		'bf-widget-show-desktop',
		'bf-widget-show-tablet',
		'bf-widget-show-mobile',

		// Responsive Fields
		'bf-widget-custom-class',
		'bf-widget-custom-id',

	);


	/**
	 * Contains default value of general fields
	 *
	 * @var array
	 */
	static $default_values = array();


	function __construct() {

		// Load and prepare options only in backend for better performance
		if ( is_admin() ) {

			// Loads all active fields
			$this->fields = apply_filters( 'better-framework/widgets/options/general', $this->fields );

			// Prepare fields for generator
			$this->prepare_options();

			// Add input fields(priority 10, 3 parameters)
			add_action( 'in_widget_form', array( $this, 'in_widget_form' ), 5, 3 );

			// Callback function for options update (priority 5, 3 parameters)
			add_filter( 'widget_update_callback', array( $this, 'in_widget_form_update' ), 99, 2 );

		} else {

			add_filter( 'dynamic_sidebar_params', array( $this, 'dynamic_sidebar_params' ), 99, 2 );

		}

	}


	/**
	 * Check for when a field is general field
	 *
	 * @param $field
	 *
	 * @return bool
	 */
	public static function is_valid_field( $field ) {

		return in_array( $field, self::$valid_general_fields );

	}


	/**
	 * Returns list of all valid general fields
	 *
	 * @return array
	 */
	public static function get_general_fields() {

		return self::$valid_general_fields;
	}


	/**
	 * Get default value for general fields
	 *
	 * @param $field
	 *
	 * @return bool
	 */
	public static function get_default_value( $field ) {

		// Return default value from cache
		if ( isset( self::$default_values[ $field ] ) ) {
			return self::$default_values[ $field ];
		}

		$_default = '';

		switch ( $field ) {

			case 'bf-widget-show-desktop':
			case 'bf-widget-show-tablet':
			case 'bf-widget-show-mobile':
				$_default = 'show';

		}


		// Get field default value from filters
		self::$default_values[ $field ] = apply_filters( "better-framework/widgets/options/general/{$field}/default", $_default );

		return self::$default_values[ $field ];

	}


	/**
	 * Save active fields values
	 *
	 * @param $instance
	 * @param $new_instance
	 *
	 * @return mixed
	 */
	function in_widget_form_update( $instance, $new_instance ) {

		// Create default fields

		foreach ( $this->options as $option ) {
			if ( ! empty( $option['id'] ) && isset( $option['std'] ) ) {
				$def[ $option['id'] ] = $option['std'];
			}
		}

		// Save all valid general fields
		foreach ( $this->get_general_fields() as $field ) {
			if ( isset( $new_instance[ $field ] ) ) {
				if ( $new_instance[ $field ] != $def[ $field ] ) {
					$instance[ $field ] = $new_instance[ $field ];
				} else {
					unset( $new_instance[ $field ] );
					unset( $instance[ $field ] );
				}
			}
		}

		return $instance;
	}


	/**
	 * load options and prepare to admin form generation for active fields
	 */
	function prepare_options() {

		$color_fields['group-1'] = array(
			'name'  => __( 'Color Options', 'better-studio' ),
			'type'  => 'group',
			'id'    => 'group-1',
			// Keep Widget Group State After Widget Settings Saved
			'state' => isset( $_POST['_group_status']['group-1'] ) ? $_POST['_group_status']['group-1'] : 'close',
		);

		$title_fields['group-2'] = array(
			'name'  => __( 'Title Options', 'better-studio' ),
			'type'  => 'group',
			'id'    => 'group-2',
			// Keep Widget Group State After Widget Settings Saved
			'state' => isset( $_POST['_group_status']['group-2'] ) ? $_POST['_group_status']['group-2'] : 'close',
		);

		$responsive_fields['group-3'] = array(
			'name'  => __( 'Responsive Options', 'better-studio' ),
			'type'  => 'group',
			'id'    => 'group-3',
			// Keep Widget Group State After Widget Settings Saved
			'state' => isset( $_POST['_group_status']['group-3'] ) ? $_POST['_group_status']['group-3'] : 'close',
		);

		$advanced_fields['group-4'] = array(
			'name'  => __( 'Advanced Options', 'better-studio' ),
			'type'  => 'group',
			'id'    => 'group-4',
			// Keep Widget Group State After Widget Settings Saved
			'state' => isset( $_POST['_group_status']['group-4'] ) ? $_POST['_group_status']['group-4'] : 'close',
		);


		// Iterate all fields to find active fields
		foreach ( (array) $this->fields as $field_id => $field ) {

			// detect advanced fields category
			if ( self::is_valid_field( $field ) ) {

				// Color Fields
				$raw_field = $this->register_color_option( $field );

				if ( $raw_field != false ) {
					$color_fields[] = $raw_field;
					continue;
				}

				// Advanced Fields
				$raw_field = $this->register_title_option( $field );

				if ( $raw_field != false ) {
					$title_fields[] = $raw_field;
					continue;
				}

				// Responsive Fields
				$raw_field = $this->register_responsive_option( $field );

				if ( $raw_field != false ) {
					$responsive_fields[] = $raw_field;
					continue;
				}

				// Responsive Fields
				$raw_field = $this->register_advanced_option( $field );

				if ( $raw_field != false ) {
					$advanced_fields[] = $raw_field;
					continue;
				}

			}

		}

		// Add advanced fields to main fields
		if ( bf_count( $title_fields ) > 1 ) {
			// Fix group title for 1 field
			if ( bf_count( $title_fields ) == 2 ) {
				$title_fields['group-2']['name'] = $title_fields[0]['name'];
				$title_fields[0]['name']         = '';
			}

			$this->options = array_merge( $this->options, $title_fields );
		}

		// Add color fields to main fields
		if ( bf_count( $color_fields ) > 1 ) {
			// Fix group title for 1 field
			if ( bf_count( $color_fields ) == 2 ) {
				$color_fields['group-1']['name'] = $color_fields[0]['name'];
				$color_fields[0]['name']         = '';
			}

			$this->options = array_merge( $this->options, $color_fields );
		}

		// Add responsive fields to main fields
		if ( bf_count( $responsive_fields ) > 1 ) {
			// Fix group title for 1 field
			if ( bf_count( $responsive_fields ) == 2 ) {
				$responsive_fields['group-3']['name'] = $responsive_fields[0]['name'];
				$responsive_fields[0]['name']         = '';
			}

			$this->options = array_merge( $this->options, $responsive_fields );
		}

		// Add advanced fields to main fields
		if ( bf_count( $advanced_fields ) > 1 ) {
			// Fix group title for 1 field
			if ( bf_count( $advanced_fields ) == 2 ) {
				$advanced_fields['group-3']['name'] = $advanced_fields[0]['name'];
				$advanced_fields[0]['name']         = '';
			}

			$this->options = array_merge( $this->options, $advanced_fields );
		}

	}


	/**
	 * Init a general field generator options
	 *
	 * @param $field
	 *
	 * @return array|bool
	 */
	private function register_color_option( $field ) {

		switch ( $field ) {

			case 'bf-widget-title-color':
				return array(
					'name' => __( 'Widget Title Text Color', 'better-studio' ),
					'id'   => $field,
					'type' => 'color',
					'std'  => $this->get_default_value( $field ),
				);
				break;

			case 'bf-widget-title-bg-color':
				return array(
					'name' => __( 'Widget Title Background Color', 'better-studio' ),
					'id'   => $field,
					'type' => 'color',
					'std'  => $this->get_default_value( $field ),
				);
				break;

			case 'bf-widget-bg-color':
				return array(
					'name' => __( 'Widget Background Color', 'better-studio' ),
					'id'   => $field,
					'type' => 'color',
					'std'  => $this->get_default_value( $field ),
				);
				break;

			case 'bs-text-color-scheme':
				return array(
					'name'    => __( 'Widget Text Color Scheme', 'better-studio' ),
					'id'      => $field,
					'type'    => 'select',
					'std'     => $this->get_default_value( $field ),
					'options' => array(
						''      => __( '-- Default --', 'better-studio' ),
						'light' => __( 'White Color Texts', 'better-studio' ),
					),
				);
				break;

		}

		return false;
	}


	/**
	 * Init a general field generator options
	 *
	 * @param $field
	 *
	 * @return array|bool
	 */
	private function register_title_option( $field ) {

		switch ( $field ) {

			case 'bf-widget-title-icon':
				return array(
					'name' => __( 'Widget Title Icon', 'better-studio' ),
					'id'   => $field,
					'type' => 'icon_select',
					'std'  => $this->get_default_value( $field ),
				);
				break;

			case 'bf-widget-title-link':
				return array(
					'name' => __( 'Widget Title Link', 'better-studio' ),
					'id'   => $field,
					'type' => 'text',
					'std'  => $this->get_default_value( $field ),
					'ltr'  => true,
				);
				break;

			case 'bf-widget-title-style':
				return array(
					'name'             => __( 'Widget Title Style', 'better-studio' ),
					'id'               => $field,
					'type'             => 'select_popup',
					'std'              => 'default',
					'deferred-options' => array(
						'callback' => $this->get_default_value( $field ),
						'args'     => array(
							true
						),
					),
					'column_class'     => 'one-column',
				);
				break;

		}

		return false;
	}


	/**
	 * Init a general field generator options
	 *
	 * @param $field
	 *
	 * @return array|bool
	 */
	private function register_responsive_option( $field ) {

		switch ( $field ) {

			case 'bf-widget-show-desktop':
				return array(
					'name'    => __( 'Show On Desktop', 'better-studio' ),
					'id'      => $field,
					'type'    => 'select',
					'std'     => $this->get_default_value( $field ),
					'options' => array(
						'show' => __( 'Show', 'better-studio' ),
						'hide' => __( 'Hide', 'better-studio' ),
					),
				);
				break;

			case 'bf-widget-show-tablet':
				return array(
					'name'    => __( 'Show On Tablet', 'better-studio' ),
					'id'      => $field,
					'type'    => 'select',
					'std'     => $this->get_default_value( $field ),
					'options' => array(
						'show' => __( 'Show', 'better-studio' ),
						'hide' => __( 'Hide', 'better-studio' ),
					),
				);
				break;

			case 'bf-widget-show-mobile':
				return array(
					'name'    => __( 'Show On Mobile', 'better-studio' ),
					'id'      => $field,
					'type'    => 'select',
					'std'     => $this->get_default_value( $field ),
					'options' => array(
						'show' => __( 'Show', 'better-studio' ),
						'hide' => __( 'Hide', 'better-studio' ),
					),
				);
				break;

		}

		return false;
	}


	/**
	 * Init a advanced fields
	 *
	 * @param $field
	 *
	 * @return array|bool
	 */
	private function register_advanced_option( $field ) {

		switch ( $field ) {

			case 'bf-widget-custom-class':
				return array(
					'name' => __( 'Custom CSS Class', 'better-studio' ),
					'id'   => $field,
					'type' => 'text',
					'std'  => $this->get_default_value( $field ),
				);
				break;

			case 'bf-widget-custom-id':
				return array(
					'name' => __( 'Custom ID', 'better-studio' ),
					'id'   => $field,
					'type' => 'text',
					'std'  => $this->get_default_value( $field ),
				);
				break;

		}

		return false;
	}


	/**
	 * @param $widget WP_Widget
	 */
	function prepare_fields( $widget ) {

		for ( $i = 0; $i < bf_count( $this->options ); $i ++ ) {

			if ( isset( $this->options[ $i ]['attr_id'] ) ) { //  Backward compatibility
				$this->options[ $i ]['id'] = $this->options[ $i ]['attr_id'];
			}

			// do not do anything on fields that haven't ID, ex: group fields
			if ( ! isset( $this->options[ $i ]['id'] ) ) {
				continue;
			}

			$this->options[ $i ]['input_name'] = $widget->get_field_name( $this->options[ $i ]['id'] );

			if ( $this->options[ $i ]['type'] == 'repeater' ) {

				for ( $j = 0; $j < bf_count( $this->options[ $i ]['options'] ); $j ++ ) {

					$this->options[ $i ]['options'][ $j ]['input_name'] = $this->options[ $i ]['input_name'] . '[%d][' . $this->options[ $i ]['options'][ $j ]['id'] . ']';

				}

			} elseif ( $this->options[ $i ]['type'] == 'select' && ! empty( $this->options[ $i ]['multiple'] ) && $this->options[ $i ]['multiple'] ) {
				$this->options[ $i ]['input_name'] .= '[]';
			}

		}

	}


	/**
	 * Add input fields to widget form
	 *
	 * @param $t
	 * @param $return
	 * @param $instance
	 */
	function in_widget_form( $t, $return, $instance ) {

		Better_Framework::factory( 'widgets-field-generator', false, true );

		$this->prepare_fields( $t );

		// Return if there is no general field
		if ( bf_count( $this->options ) <= 0 ) {
			return;
		}

		// Prepare generator config file
		$options = array(
			'fields' => $this->options
		);

		// Create generator instance
		$generator = new BF_Widgets_Field_Generator( $options, $instance );

		echo $generator->get_fields(); // escaped before inside generator

	}


	/**
	 * Callback: Used to change sidebar params to add general fields
	 *
	 * Filter: dynamic_sidebar_params
	 *
	 * @param $params
	 *
	 * @return mixed
	 */
	public function dynamic_sidebar_params( $params ) {

		global $wp_registered_widgets;

		$id = $params[0]['widget_id']; // Current widget ID

		if ( isset( $wp_registered_widgets[ $id ]['callback'][0] ) && is_object( $wp_registered_widgets[ $id ]['callback'][0] ) ) {

			$custom_class = array();

			// Get settings for all widgets of this type
			$settings = $wp_registered_widgets[ $id ]['callback'][0]->get_settings();

			// Get settings for this instance of the widget
			$setting_key = substr( $id, strrpos( $id, '-' ) + 1 );
			$instance    = isset( $settings[ $setting_key ] ) ? $settings[ $setting_key ] : array();

			// Add custom link to widget title
			if ( ! empty( $instance['bf-widget-title-link'] ) ) {
				$params[0]['before_title'] .= "<a href='{$instance['bf-widget-title-link']}'>";
				$params[0]['after_title']  = "</a>" . $params[0]['after_title'];
			}

			// Append custom css class
			if ( ! empty( $instance['bf-widget-custom-class'] ) ) {
				$custom_class[] = sanitize_html_class( $instance['bf-widget-custom-class'] );
			}

			// Add icon before widget title
			if ( ! empty( $instance['bf-widget-title-icon'] ) ) {

				if ( is_array( $instance['bf-widget-title-icon'] ) && $instance['bf-widget-title-icon']['icon'] != '' ) {
					$params[0]['before_title'] .= bf_get_icon_tag( $instance['bf-widget-title-icon'] ) . ' ';
					$custom_class[]            = 'h-i'; // Have Icon
				} elseif ( is_string( $instance['bf-widget-title-icon'] ) ) {
					$params[0]['before_title'] .= bf_get_icon_tag( $instance['bf-widget-title-icon'] ) . ' ';
					$custom_class[]            = 'h-i'; // Have Icon
				} else {
					$custom_class[] = 'h-ni'; // Have Not Icon
				}

			} else {
				$custom_class[] = 'h-ni'; // Have Not Icon
			}

			// Add class for bg color
			if ( ! empty( $instance['bf-widget-bg-color'] ) ) {
				$custom_class[] = 'w-bg'; // Wdiegt BG Color
				$custom_class[] = 'w-bg-' . sanitize_html_class( $instance['bf-widget-bg-color'] );
			}

			// Add class for title color
			if ( ! empty( $instance['bf-widget-title-color'] ) ) {
				$custom_class[] = 'h-c'; // Heading Color
				$custom_class[] = 'h-c-' . sanitize_html_class( $instance['bf-widget-title-color'] );
			}

			// Add class for title bg color
			if ( ! empty( $instance['bf-widget-title-bg-color'] ) ) {
				$custom_class[] = 'h-bg'; // Heading BG
				$custom_class[] = 'h-bg-' . sanitize_html_class( $instance['bf-widget-title-bg-color'] );
			}

			// Show on desktop
			if ( ! empty( $instance['bf-widget-show-desktop'] ) ) {
				if ( $instance['bf-widget-show-desktop'] == 'hide' ) {
					$custom_class[] = 'bs-hidden-lg';
					$custom_class[] = 'bs-hidden-md';
				}
			}

			// Show on tablet
			if ( ! empty( $instance['bf-widget-show-tablet'] ) ) {
				if ( $instance['bf-widget-show-tablet'] == 'hide' ) {
					$custom_class[] = 'bs-hidden-sm';
				}
			}

			// Show on mobile
			if ( ! empty( $instance['bf-widget-show-mobile'] ) ) {
				if ( $instance['bf-widget-show-mobile'] == 'hide' ) {
					$custom_class[] = 'bs-hidden-xs';
				}
			}

			// add title classes
			if ( ! empty( $instance['title'] ) ) {
				$custom_class[] = 'w-t'; // Have Title
			} else {
				$custom_class[] = 'w-nt'; // Have No Title
			}

			// Prepare custom classes
			$class_to_add = 'class=" ' . implode( ' ', $custom_class ) . ' '; // Make sure you leave a space at the end

			// Add classes
			$params[0]['before_widget'] = str_replace(
				'class="',
				$class_to_add,
				$params[0]['before_widget']
			);


			// Change id to custom ID
			if ( ! empty( $instance['bf-widget-custom-id'] ) ) {

				$params[0]['before_widget'] = str_replace(
					' id="' . $params[0]['widget_id'] . '"',
					' id="' . sanitize_html_class( $instance['bf-widget-custom-id'] ) . '"',
					$params[0]['before_widget']
				);
			}
		}

		return $params;
	}
}libs/better-framework/widget/class-bf-widget.php000064400000014173151214002410015720 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Base class for widgets
 */
class BF_Widget extends WP_Widget {


	/**
	 * Widget Position in wp-admin/widgets.php
	 *
	 * @var int
	 */
	var $position = 30;

	/**
	 * $default values for widget fields
	 *
	 * @var array
	 */
	var $defaults = array();


	/**
	 * Flag to load default only one time
	 *
	 * @var bool
	 */
	var $defaults_loaded = false;


	/**
	 * Contains shortcode id of widget
	 *
	 * @var string
	 */
	var $base_widget_id;


	/**
	 * Contain all fields of widget
	 *
	 * @var array
	 */
	var $fields = array();


	/**
	 * Show widget title
	 *
	 * @var bool
	 */
	var $with_title = true;


	/**
	 * Register widget with WordPress.
	 *
	 * @param string $shortcode_id
	 * @param string $title
	 * @param array  $desc
	 * @param bool   $widget_id
	 */
	function __construct( $shortcode_id = '', $title = '', $desc = array(), $widget_id = false ) {

		if ( empty( $shortcode_id ) ) {
			return;
		}


		$this->base_widget_id = $shortcode_id;

		if ( $widget_id != false ) {
			parent::__construct(
				$widget_id,
				$title,
				$desc
			);
		} else {
			parent::__construct(
				$shortcode_id,
				$title,
				$desc
			);
		}

	}


	/**
	 * Loads widget -> shortcode default attrs
	 */
	public function load_defaults() {

		if ( $this->defaults_loaded ) {
			return;
		}

		$this->defaults_loaded = true;
		$this->defaults        = BF_Shortcodes_Manager::factory( $this->base_widget_id, array(), true )->defaults;
	}


	/**
	 * Loads fields
	 */
	public function load_fields() {
	}


	/**
	 * Prepare fields for field generator
	 */
	function prepare_fields() {

		for ( $i = 0; $i < bf_count( $this->fields ); $i ++ ) {

			if ( isset( $this->fields[ $i ]['attr_id'] ) ) { //  Backward compatibility
				$this->fields[ $i ]['id'] = $this->fields[ $i ]['attr_id'];
			}
			// do not do anything on fields that haven't ID, ex: group fields
			if ( ! isset( $this->fields[ $i ]['id'] ) ) {
				continue;
			}

			$this->fields[ $i ]['input_name'] = $this->get_field_name( $this->fields[ $i ]['id'] );

			// TODO: check this
			// $this->fields[ $i ]['id'] = $this->get_field_id( $this->fields[ $i ]['id'] );


			if ( $this->fields[ $i ]['type'] == 'repeater' ) {

				foreach ( $this->fields[ $i ]['options'] as $_id => $_item ) {

					$this->fields[ $i ]['options'][ $_id ]['input_name'] = $this->fields[ $i ]['input_name'] . '[%d][' . $_item['id'] . ']';
				}

			} elseif ( $this->fields[ $i ]['type'] == 'select' && ! empty( $this->fields[ $i ]['multiple'] ) && $this->fields[ $i ]['multiple'] ) {
				$this->fields[ $i ]['input_name'] .= '[]';
			}
		}
	}


	/**
	 * Merge two arrays to one, if $atts key not defined or is empty then $default value will be set.
	 *
	 * @param $default
	 * @param $atts
	 *
	 * @return mixed
	 */
	function parse_args( $default, $atts ) {

		foreach ( (array) $default as $key => $value ) {

			// empty fields in $atts is ok!
			if ( ! isset( $atts[ $key ] ) ) {
				$atts[ $key ] = $value;
			}

		}

		$atts['shortcode-id'] = $this->base_widget_id; // adds shortcode id to atts for using it inside filters

		return $atts;
	}


	/**
	 * Front-end display of widget.
	 *
	 * @see BetterWidget::widget()
	 * @see WP_Widget::widget()
	 *
	 * @param array $args     Widget arguments.
	 * @param array $instance Saved values from database.
	 */
	public function widget( $args, $instance ) {

		$this->load_defaults();
		$instance = $this->parse_args( $this->defaults, $instance );

		echo $args['before_widget'];  // escaped before inside WP

		$title = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->base_widget_id );
		if ( ! empty( $title ) && $this->with_title ) {
			echo $args['before_title'] . $title . $args['after_title']; // escaped before inside WP
		}

		echo BF_Shortcodes_Manager::factory( $this->base_widget_id )->handle_widget( $instance ); // escaped before inside WP

		echo $args['after_widget']; // escaped before inside WP
	}


	/**
	 * Sanitize widget form values as they are saved.
	 *
	 * @see WP_Widget::update()
	 *
	 * @param array $new_instance Values just sent to be saved.
	 * @param array $old_instance Previously saved values from database.
	 *
	 * @return array Updated safe values to be saved.
	 */
	public function update( $new_instance, $old_instance ) {

		$this->load_defaults();

		return $this->parse_args( $this->defaults, $new_instance );
	}


	/**
	 * Back-end widget form.
	 *
	 * @see WP_Widget::form()
	 *
	 * @param array $instance Previously saved values from database.
	 *
	 * @return string|void
	 */
	public function form( $instance ) {

		$this->load_defaults();
		$instance = $this->parse_args( $this->defaults, $instance );

		Better_Framework::factory( 'widgets-field-generator', false, true );

		// prepare fields for generator
		$this->load_fields();
		$this->prepare_fields();
		$options = array(
			'fields' => $this->fields
		);

		/**
		 * Keep Widget Group State After Widget Settings Saved
		 */
		if ( ! empty( $_POST['_group_status'] ) ) {
			foreach ( $options['fields'] as $idx => $field ) {
				if ( $field['type'] === 'group' && ! empty( $field['id'] ) ) {
					$id = &$field['id'];

					if ( ! empty( $_POST['_group_status'][ $id ] ) ) {
						$options['fields'][ $idx ]['state'] = $_POST['_group_status'][ $id ];
					}
				}
			}
		}

		$generator = new BF_Widgets_Field_Generator( $options, $instance );

		echo $generator->get_fields(); // escaped before
	}


	public function get_fields() {

		return $this->fields;
	}
}
libs/better-framework/widget/class-bf-widgets-field-generator.php000064400000007645151214002410021156 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Class BF_Widgets_Field_Generator
 */
class BF_Widgets_Field_Generator extends BF_Admin_Fields {


	/**
	 * Constructor Function
	 *
	 * @param array $items  Panel All Options
	 * @param array $values Panel ID
	 *
	 * @since  1.0
	 * @access public
	 * @return \BF_Widgets_Field_Generator
	 */
	public function __construct( array $items, $values = array() ) {

		$default_options = array(
			'templates_dir' => BF_PATH . 'widget/templates/',
		);
		$items           = array_merge( $default_options, $items );

		foreach ( $items['fields'] as $idx => $field ) {

			if ( isset( $field['id'] ) ) {
				$items['fields'][ $idx ]['id'] = $field['id'];
			}
		}

		// Parent Constructor
		parent::__construct( $items );

		$this->items  = $items;
		$this->values = $values;
	}


	/**
	 * Display HTML output of one field
	 *
	 * @param $field
	 *
	 * @return string
	 */
	public function get_field( $field ) {

		$field['value'] = isset( $this->values[ $field['id'] ] ) ? $this->values[ $field['id'] ] : null;
		if ( is_null( $field['value'] ) && isset( $field['std'] ) && $field['type'] != 'repeater' ) {
			$field['value'] = $field['std'];
		}

		if ( ! in_array( $field['type'], $this->supported_fields ) ) {
			return '';
		}

		if ( $field['type'] == 'repeater' ) {
			$field['widget_field'] = true;
		}

		// filter field
		if ( isset( $field['filter-field'] ) && $field['filter-field-value'] ) {

			// filter field value
			$filter_field_value = isset( $this->values[ $field['filter-field'] ] ) ? $this->values[ $field['filter-field'] ] : null;
			if ( is_null( $filter_field_value ) ) {

				foreach ( $this->items['fields'] as $_field ) {

					if ( $_field == $field['filter-field'] ) {

						if ( isset( $_field['std'] ) && $_field['type'] != 'repeater' ) {

							$filter_field_value = $_field['std'];

						}

					}

				}

			}

			if ( $field['filter-field-value'] !== $filter_field_value ) {

				$field['section-css']['display'] = "none";

			}

		}

		return $this->section(
			call_user_func(
				array( $this, $field['type'] ),
				$field
			),
			$field
		);

	}


	/**
	 * Display HTML output of widget fields array
	 *
	 * @since  1.0
	 * @access public
	 * @return string
	 */
	public function get_fields() {

		$output = '';

		// Flag for detecting Groups
		$group_counter = 0;

		foreach ( $this->items['fields'] as $field ) {

			if ( $field['type'] == 'group_close' ) {

				// close tag for latest group in tab
				if ( $group_counter != 0 ) {
					$group_counter = 0;
					$output        .= $this->get_fields_group_close( $field );
				}
				continue;
			}

			if ( $field['type'] == 'group' ) {

				// close tag for latest group in tab
				if ( $group_counter != 0 ) {
					$group_counter = 0;
					$output        .= $this->get_fields_group_close( $field );
				}

				if ( isset( $field['container-class'] ) ) {
					$field['container-class'] .= ' bf-widgets';
				} else {
					$field['container-class'] = 'bf-widgets';
				}

				$output .= $this->get_fields_group_start( $field );

				$group_counter ++;

			} else {

				$output .= $this->get_field( $field );

			}

		}

		// close tag for latest group
		if ( $group_counter != 0 ) {
			$output .= $this->get_fields_group_close();
		}

		return $output;
	}

}
libs/better-framework/widget/class-bf-widgets-manager.php000064400000011336151214002410017511 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Manager for base and public functionality related to Widgets and dynamic sidebars
 */
class BF_Widgets_Manager {

	/**
	 * Contain current showed dynamic sidebar location id
	 *
	 * @var string
	 */
	public static $current_sidebar = '';


	/**
	 * Contain top-bar sidebars locations
	 *
	 * @var array
	 */
	public static $top_bar_sidebars = array();


	/**
	 * Contain footer sidebars locations
	 *
	 * @var array
	 */
	public static $footer_sidebars = array();


	function __construct() {

		$this->load_special_sidebars();

		$this->load_widgets_general_fields();

		add_action( 'dynamic_sidebar_before', array( 'BF_Widgets_Manager', 'dynamic_sidebar_before' ) );
		add_action( 'dynamic_sidebar_after', array( 'BF_Widgets_Manager', 'dynamic_sidebar_after' ) );

		add_filter( 'widget_title', array( $this, 'widget_title_filter' ), 99 );
		add_filter( 'in_widget_form', array( $this, 'append_position_field' ), 20, 4 );
	}


	/**
	 * This filter used for delete widgets title on special sidebar locations
	 *
	 * @param $title
	 *
	 * @return string
	 */
	function widget_title_filter( $title ) {

		if ( self::is_special_sidebar() ) {
			$title = '';
		}

		return $title;
	}


	/**
	 * Filter special sidebars
	 */
	function load_special_sidebars() {

		self::$top_bar_sidebars = apply_filters( 'better-framework/sidebars/locations/top-bar', array() );

		self::$footer_sidebars = apply_filters( 'better-framework/sidebars/locations/footer-bar', array() );

	}


	/**
	 * Init general fields for all WordPress widgets
	 */
	function load_widgets_general_fields() {

		require_once BF_PATH . 'widget/class-bf-widgets-general-fields.php';

		new BF_Widgets_General_Fields();

	}


	public function append_position_field( $instance ) {

		if ( property_exists( $instance, 'position' ) ) {
			$position = $instance->position;
		} else {
			$position = apply_filters( 'better-framework/widget/default-position', 30, $instance );
		}

		$position = apply_filters( 'better-framework/widget/position', $position, $instance );

		printf( '<input type="hidden"  value="%d" class="bf-widget-position">', $position );
	}


	/**
	 * Fires before widgets are rendered in a dynamic sidebar.
	 *
	 * @param $index
	 */
	public static function dynamic_sidebar_before( $index ) {

		self::$current_sidebar = $index;

	}


	/**
	 * Fires after widgets are rendered in a dynamic sidebar.
	 *
	 * @param $index
	 */
	public static function dynamic_sidebar_after( $index ) {

		self::$current_sidebar = '';

	}


	/**
	 * Used For retrieving current sidebar
	 *
	 */
	public static function get_current_sidebar() {

		return self::$current_sidebar;

	}


	/**
	 * Load widget for shortcode
	 *
	 * @param string $id
	 * @param array  $options
	 */
	public static function register_widget_for_shortcode( $id = '', $options = array() ) {

		// custom class for widget. 3rd party shortcode widget that is outside of BF
		if ( isset( $options['widget_class'] ) && class_exists( $options['widget_class'] ) && is_subclass_of( $options['widget_class'], 'WP_Widget' ) ) {

			$class = $options['widget_class'];

			register_widget( $class );

		} else {

			$class = bf_convert_string_to_class_name( $id, 'BF_', '_Widget' );

			if ( ! class_exists( $class ) ) {

				if ( file_exists( BF_PATH . 'widget/widgets/class-bf-' . $id . '-widget.php' ) ) {

					require_once BF_PATH . 'widget/widgets/class-bf-' . $id . '-widget.php';

					register_widget( $class );

				}

			}
		}

	}


	/**
	 * Determine current showing sidebar is a top bar sidebar!
	 */
	public static function is_top_bar_sidebar() {

		return in_array( self::$current_sidebar, self::$top_bar_sidebars );

	}


	/**
	 * Determine current showing sidebar is a footer sidebar!
	 */
	public static function is_footer_sidebar() {

		return in_array( self::$current_sidebar, self::$footer_sidebars );

	}


	/**
	 * Determine current showing sidebar is a special sidebar!
	 */
	public static function is_special_sidebar() {

		if ( self::is_top_bar_sidebar() || self::is_footer_sidebar() ) {
			return true;
		}

		return false;

	}

}libs/better-framework/widget/templates/default.php000064400000005741151214002410016370 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes   = $classes['section'] . ' bf-widget-field-section';
$container_classes = $classes['container'];

$heading_classes  = $classes['heading'] . ' bf-heading';
$controls_classes = $classes['controls'] . ' bf-control not-prepared';
$explain_classes  = $classes['explain'] . ' bf-desc';

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];

$section_css_attr = $this->get_section_css_attr( $options );
$section_attr     = $this->get_section_filter_attr( $options );

?>
<div
		class="<?php echo esc_attr( $container_classes ); ?> bf-section-container bf-widgets bf-clearfix" <?php echo $section_css_attr; // escaped before ?> <?php echo $section_attr; // escaped before ?>>
	<div class="<?php echo esc_attr( $section_classes ); ?> bf-clearfix"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>">

		<div class="<?php echo esc_attr( $heading_classes ); ?> bf-clearfix">
			<h4><label><?php echo esc_html( $options['name'] ); ?></label></h4>
		</div>

		<div class="<?php echo esc_attr( $controls_classes ); ?> bf-clearfix">
			<?php echo $input; // escaped before ?>
		</div>

		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div
					class="<?php echo esc_attr( $explain_classes ); ?> bf-clearfix"><?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?></div>
		<?php } ?>

	</div>
</div>libs/better-framework/widget/templates/hr.php000064400000001600151214002410015343 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div class="bf-section-container bf-clearfix">
	<div class="bf-section-hr bf-clearfix">
		<?php echo $input; // escaped before ?>
	</div>
</div>libs/better-framework/widget/templates/info.php000064400000005662151214002410015701 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes = $classes['section'] . ' bf-widget-field-section';

$heading_classes  = $classes['heading'] . ' bf-heading';
$controls_classes = $classes['controls'] . ' bf-control not-prepared';
$explain_classes  = $classes['explain'] . ' bf-desc';

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];


if ( ! isset( $options['info-type'] ) ) {
	$options['info-type'] = 'info';
}

if ( ! isset( $options['state'] ) ) {
	$options['state'] = 'open';
}

?>
<div class="bf-section-container bf-widgets bf-clearfix">
	<div
			class="bf-section-info <?php echo esc_attr( $options['info-type'] ); ?> <?php echo esc_attr( $options['state'] ); ?> bf-clearfix">
		<div class="bf-section-info-title bf-clearfix">
			<h3><?php

				switch ( $options['info-type'] ) {

					case 'help':
						echo '<i class="fa fa-support"></i> ';
						break;

					case 'info':
						echo '<i class="fa fa-info"></i> ';
						break;

					case 'warning':
						echo '<i class="fa fa-warning"></i> ';
						break;

					case 'danger':
						echo '<i class="fa fa-exclamation"></i> ';
						break;

					default:
						echo '<i class="fa fa-info"></i> ';
						break;


				}

				echo esc_html( $options['name'] ); ?></h3>
		</div>
		<div class="<?php echo esc_attr( $controls_classes ); ?>  bf-clearfix">
			<?php echo $input; // escaped before ?>
		</div>
	</div>
</div>libs/better-framework/widget/templates/checkbox.php000064400000005106151214002410016525 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes = $classes['section'] . ' bf-widget-field-section';

$heading_classes  = $classes['heading'] . ' bf-heading';
$controls_classes = $classes['controls'] . ' bf-control not-prepared';
$explain_classes  = $classes['explain'] . ' bf-desc';

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];


?>
<div class="bf-section-container bf-widgets bf-clearfix">
	<div class="<?php echo esc_attr( $section_classes ); ?> bf-clearfix"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>">

		<div class="<?php echo esc_attr( $heading_classes ); ?> bf-clearfix">
			<h4><label> <?php echo $input; // escaped before ?><?php echo esc_attr( $options['name'] ); ?></label></h4>
		</div>

		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div
					class="<?php echo esc_attr( $explain_classes ); ?> bf-clearfix"><?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?></div>
		<?php } ?>

	</div>
</div>libs/better-framework/tinymce/fields/icon_select.php000064400000006360151214002410016666 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

// Default selected
$current = array(
	'key'    => '',
	'title'  => __( 'Chose an Icon', 'better-studio' ),
	'width'  => '',
	'height' => '',
	'type'   => '',
);


if ( isset( $options['value'] ) ) {

	if ( is_array( $options['value'] ) ) {

		if ( in_array( $options['value']['type'], array( 'custom-icon', 'custom' ) ) ) {
			$current['key']    = isset( $options['value']['icon'] ) ? $options['value']['icon'] : '';
			$current['title']  = bf_get_icon_tag( isset( $options['value'] ) ? $options['value'] : '' ) . ' ' . __( 'Custom icon', 'better-studio' );
			$current['width']  = isset( $options['value']['width'] ) ? $options['value']['width'] : '';
			$current['height'] = isset( $options['value']['height'] ) ? $options['value']['height'] : '';
			$current['type']   = 'custom-icon';
		} else {
			Better_Framework::factory( 'icon-factory' );

			$fontawesome = BF_Icons_Factory::getInstance( 'fontawesome' );

			if ( isset( $fontawesome->icons[ $options['value']['icon'] ] ) ) {
				$current['key']    = $options['value']['icon'];
				$current['title']  = bf_get_icon_tag( $options['value'] ) . $fontawesome->icons[ $options['value']['icon'] ]['label'];
				$current['width']  = $options['value']['width'];
				$current['height'] = $options['value']['height'];
				$current['type']   = 'fontawesome';
			}
		}

	} elseif ( ! empty( $options['value'] ) ) {

		Better_Framework::factory( 'icon-factory' );

		$fontawesome = BF_Icons_Factory::getInstance( 'fontawesome' );

		$icon_label = '';
		if ( substr( $options['value'], 0, 3 ) == 'fa-' ) {
			$icon_label      = bf_get_icon_tag( $options['value'] ) . ' ' . $fontawesome->icons[ $options['value'] ]['label'];
			$current['type'] = 'fontawesome';
		} else {
			$icon_label      = bf_get_icon_tag( $options['value'] );
			$current['type'] = 'custom-icon';
		}

		$current['key']    = $options['value'];
		$current['title']  = $icon_label;
		$current['width']  = '';
		$current['height'] = '';

	}

}

$icon_handler = 'bf-icon-modal-handler-' . mt_rand();


?>
	<div class="bf-icon-modal-handler" id="<?php echo esc_attr( $icon_handler ); ?>">

		<div class="select-options">
			<span class="selected-option"><?php echo wp_kses( $current['title'], bf_trans_allowed_html() ); ?></span>
		</div>

		<input type="hidden" class="mce-field wpb-textinput title textfield icon-input"
		       data-label=""
		       name="<?php echo esc_attr( $options['input_name'] ); ?>"
		       value="<?php echo esc_attr( $current['key'] ); ?>"/>

	</div><!-- modal handler container -->
<?php

bf_enqueue_modal( 'icon' );
libs/better-framework/tinymce/fields/repeater.php000064400000000164151214002410016202 0ustar00<?php

$options['clone-name-format'] = '$4[$5][$6]';

include BF_PATH . 'core/field-generator/fields/repeater.php';
libs/better-framework/tinymce/index.php000064400000000006151214002410014227 0ustar00<?php
libs/better-framework/tinymce/class-bf-tinymce-view-field-generator.php000064400000013564151214002410022312 0ustar00<?php


/**
 * TinyMCE Views field generator
 */
class BF_Tinymce_View_Field_Generator extends BF_Admin_Fields {

	/**
	 * @var array
	 */
	public $shortcode_content_fields = array();


	/**
	 * Constructor Method
	 *
	 * @param array $items  Panel All Options
	 * @param int   $id     Panel ID
	 * @param array $values Panel Saved Values
	 *
	 * @since  1.0
	 * @access public
	 */
	public function __construct( array &$items, &$id, &$values = array() ) {

		// Parent Constructor
		parent::__construct( array(
			'templates_dir' => BF_PATH . 'tinymce/templates/'
		) );

		$this->items  = $items;
		$this->id     = $id;
		$this->values = $values;
	}


	public function output() {

		$this->callback( true );
	}


	/**
	 * Field Generator
	 */
	public function callback() {

		$has_tab = false;

		// Add Class For Post Format Filter
		$container = Better_Framework::html()->add( 'div' )->class( 'tinymce-addon-fields' );

		$tab_counter   = 0;
		$group_counter = 0;

		$fields_std = $this->get_stds();

		$container->text( '<div class="tabs-wrapper">' . $this->get_tabs() . '</div>' );

		foreach ( $this->get_fields() as $field ) {

			if ( ! empty( $field['type'] ) && $field['type'] === 'id-holder' ) {
				continue;
			}

			if ( ! isset( $field['input_class'] ) ) {
				$field['input_class'] = '';
			}

			$field['input_class'] .= ' mce-field';
			$field['input_name']  = $this->input_name( $field );

			$field_id = isset( $field['id'] ) ? $field['id'] : false;

			if ( $field['type'] === 'info' ) {
				if ( isset( $field['std'] ) ) {
					$field['value'] = $field['std'];
				} else {
					$field['value'] = '';
				}
			} else {
				$field['value'] = isset( $field['id'] ) && isset( $this->values[ $field['id'] ] ) ? $this->values[ $field['id'] ] : null;
			}

			if ( is_null( $field['value'] ) && isset( $fields_std[ $field_id ] ) ) {
				$field['value'] = $fields_std[ $field_id ];
			}

			if ( $field['type'] == 'repeater' ) {
				$field['clone-name-format'] = 'bf-metabox-option[$3][$4][$5][$6]';
				$field['metabox-id']        = $this->id;
				$field['metabox-field']     = true;
			}

			if ( $field['type'] == 'tab' || $field['type'] == 'subtab' ) {

				// close tag for latest group in tab
				if ( $group_counter != 0 ) {
					$group_counter = 0;
					$container->text( $this->get_fields_group_close( $field ) );
				}

				$is_subtab = $field['type'] == 'subtab';

				if ( $tab_counter != 0 ) {
					$container->text( '</div><!-- /Section -->' );
				}

				if ( $is_subtab ) {
					$container->text( "\n\n<!-- Section -->\n<div class='group subtab-group' id='bf-tmv-{$field["id"]}'>\n" );
				} else {
					$container->text( "\n\n<!-- Section -->\n<div class='group' id='bf-tmv-{$field["id"]}'>\n" );
				}
				$has_tab = true;
				$tab_counter ++;
				continue;
			}

			if ( $field['type'] == 'group_close' ) {

				// close tag for latest group in tab
				if ( $group_counter != 0 ) {
					$group_counter = 0;
					$container->text( $this->get_fields_group_close( $field ) );
				}
				continue;
			}


			if ( $field['type'] == 'group' ) {

				// close tag for latest group in tab
				if ( $group_counter != 0 ) {
					$group_counter = 0;
					$container->text( $this->get_fields_group_close( $field ) );
				}

				$container->text( $this->get_fields_group_start( $field ) );

				$group_counter ++;
			}


			if ( ! in_array( $field['type'], $this->supported_fields ) ) {
				continue;
			}

			// Filter Each Field For Post Formats!
			if ( isset( $field['post_format'] ) ) {

				if ( is_array( $field['post_format'] ) ) {
					$field_post_formats = implode( ',', $field['post_format'] );
				} else {
					$field_post_formats = $field['post_format'];
				}
				$container->text( "<div class='bf-field-post-format-filter' data-bf_pf_filter='{$field_post_formats}'>" );
			}

			$container->text(
				$this->section(
					call_user_func(
						array( $this, $field['type'] ),
						$field
					),
					$field
				)
			);

			// End Post Format Filter Wrapper
			if ( isset( $field['post_format'] ) ) {

				$container->text( "</div>" );
			}
		}

		// close tag for latest group in tab
		if ( $group_counter != 0 ) {
			$container->text( $this->get_fields_group_close( $field ) );
		}

		// last sub tab closing
		if ( $has_tab ) {
			$container->text( "</div><!-- /Section -->" );
		}

		echo $container->display();
	} // callback


	/**
	 * Used for creating input name
	 *
	 * @param $options
	 *
	 * @return string
	 */
	public function input_name( &$options ) {

		if ( isset( $options['type'] ) && $options['type'] === 'repeater' ) {
			return '%2$s[%3$d][%4$s]';
		}

		return isset( $options['id'] ) ? $options['id'] : '';
	}


	/**
	 * Get shortcode fields std values
	 *
	 * @return array
	 */
	public function get_stds() {

		if ( $shortcode = BF_Shortcodes_Manager::factory( $this->id ) ) {
			return $shortcode->defaults;
		}

		return array();
	}


	public function generate_repeater_field( $tinymce, $field, $defaults, $name_format, $number ) {

		if ( ! isset( $field['input_class'] ) ) {
			$field['input_class'] = '';
		}
		$field['input_class'] .= ' mce-field';

		if ( ! empty( $field['shortcode_content'] ) ) {
			$this->shortcode_content_fields[ $tinymce['id'] ] = $field['id'];
		}

		return parent::generate_repeater_field( $tinymce, $field, $defaults, $name_format, $number );
	}


	public function generate_repeater_field_script( $tinymce, $field, $defaults ) {

		if ( ! isset( $field['input_class'] ) ) {
			$field['input_class'] = '';
		}
		$field['input_class'] .= ' mce-field';

		return parent::generate_repeater_field_script( $tinymce, $field, $defaults );
	}


	public function __call( $name, $arguments ) {

		$file = BF_PATH . 'tinymce/fields/' . $name . '.php';

		// Check if requested field (method) does exist!
		if ( ! file_exists( $file ) ) {
			return parent::__call( $name, $arguments );
		}


		$options = $arguments[0];

		// Capture output
		ob_start();
		require $file;

		$data = ob_get_clean();

		return $data;
	}
}
libs/better-framework/tinymce/templates/default.php000064400000006034151214002410016551 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes   = $classes['section'];
$container_classes = $classes['container'];

$heading_classes  = $classes['heading'];
$controls_classes = $classes['controls'];
$explain_classes  = $classes['explain'];

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];

if ( empty( $options['desc'] ) ) {
	$section_classes .= ' no-desc ';
}


$section_css_attr = $this->get_section_css_attr( $options );
$section_attr     = $this->get_section_filter_attr( $options );

?>
<div
		class="<?php echo esc_attr( $container_classes ); ?> bf-section-container bf-metabox bf-clearfix" <?php echo $section_css_attr; // escaped before ?> <?php echo $section_attr; // escaped before ?>>
	<div class="<?php echo esc_attr( $section_classes ); ?> bf-clearfix"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>">

		<div class="<?php echo esc_attr( $heading_classes ); ?> bf-clearfix">
			<h3><label
						for="<?php echo esc_attr( $options['input_name'] ); ?>"><?php echo esc_html( $options['name'] ); ?></label>
			</h3>
		</div>

		<div class="<?php echo esc_attr( $controls_classes ); ?> bf-clearfix">
			<?php echo $input; // escaped before ?>
		</div>

		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div
					class="<?php echo esc_attr( $explain_classes ); ?> bf-clearfix"><?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?></div>
		<?php } ?>

	</div>
</div>libs/better-framework/tinymce/templates/index.php000064400000000006151214002410016225 0ustar00<?php
libs/better-framework/bbpress/abstract-class-bf-bbpress.php000064400000002301151214002410020041 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * BetterFramework bbPress Functionality For Themes
 */
abstract class BF_bbPress {

	public function __construct() {

		add_theme_support( 'bbpress' );

		add_filter( 'init', array( $this, 'init' ) );
	}


	/**
	 * Register WooCommrece related hooks
	 */
	public function init() {

		add_action( 'wp_enqueue_scripts', array( $this, 'register_assets' ) );

	}


	/**
	 * Action callback: Add WooCommerce assets
	 */
	abstract public function register_assets();

}libs/better-framework/woocommerce/abstract-class-bf-woocommerce.php000064400000003122151214002410021601 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * BetterFramework Bas Functionality For Themes
 */
abstract class BF_WooCommerce {

	public function __construct() {

		add_theme_support( 'woocommerce' );

		add_filter( 'init', array( $this, 'init' ) );
	}


	/**
	 * Register WooCommrece related hooks
	 */
	public function init() {

		add_action( 'wp_enqueue_scripts', array( $this, 'register_assets' ) );

		add_filter( 'woocommerce_add_to_cart_fragments', array( $this, 'add_to_cart_fragments' ) );

	}


	/**
	 * Action callback: Add WooCommerce assets
	 */
	abstract public function register_assets();


	/**
	 * Filter Callback: Used for adding total items in cart
	 *
	 * @param $fragments
	 *
	 * @return mixed
	 */
	public function add_to_cart_fragments( $fragments ) {

		global $woocommerce;

		$fragments['total-items-in-cart'] = $woocommerce->cart->cart_contents_count;

		return $fragments;

	}

}libs/better-framework/compatibility/class-bf-version-compatibility.php000064400000017550151214002410022361 0ustar00<?php
/***
 *  BetterStudio Themes Core.
 *
 *  ______  _____   _____ _                           _____
 *  | ___ \/  ___| |_   _| |                         /  __ \
 *  | |_/ /\ `--.    | | | |__   ___ _ __ ___   ___  | /  \/ ___  _ __ ___
 *  | ___ \ `--. \   | | | '_ \ / _ \ '_ ` _ \ / _ \ | |    / _ \| '__/ _ \
 *  | |_/ //\__/ /   | | | | | |  __/ | | | | |  __/ | \__/\ (_) | | |  __/
 *  \____/ \____/    \_/ |_| |_|\___|_| |_| |_|\___|  \____/\___/|_|  \___|
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

BF_Version_Compatibility::init();


/**
 * BetterFramework version compatibility manager.
 *
 * @package   BetterFramework
 * @author    BetterStudio <info@betterstudio.com>
 * @link      http://www.betterstudio.com
 *
 * @version   2.14.0
 * @access    public
 */
class BF_Version_Compatibility {

	/**
	 * Contains main compatibility log option ID
	 *
	 * @var string
	 */
	public static $option_id = 'bf-version-compatibility';

	/**
	 * Library Unique ID
	 *
	 * @var string
	 */
	public static $id = 'version-compatibility';


	/**
	 * Initialize !
	 *
	 * @since 2.14.0
	 */
	public static function init() {

		add_action( 'better-framework/after_setup', array( __CLASS__, 'init_compatibility' ), 1 );
	}


	/**
	 * Object of Theme
	 *
	 * @return WP_Theme
	 */
	protected static function WP_Theme_Object() {

		$theme = wp_get_theme();

		if ( '' != $theme->get( 'Template' ) ) {
			$theme = wp_get_theme( $theme->get( 'Template' ) );
		}

		return $theme;
	}


	/**
	 * Fire compatibility
	 */
	public static function init_compatibility() {

		$config = apply_filters( 'better-framework/' . self::$id . '/config', array( 'compatibility-actions' => array() ) );

		return self::do_compatibility( $config );
	}


	/**
	 * Logs theme versions and make theme compatible with latest version
	 *
	 * @param array $config
	 *
	 * @return bool
	 */
	public static function do_compatibility( $config ) {

		/**
		 * Config version compatibility array {
		 *
		 * @type array $products the product information array{
		 *
		 *   key: unique-id => value: array(
		 *      'active-version' => current version of the product
		 *    }
		 *    ...
		 *  }
		 *
		 * @type array ${'compatibility-actions'}  the product update actions array {
		 *
		 *   key: unique-id => value: array(
		 *      'version number' => custom callback
		 *    }
		 *    ...
		 * }
		 * }
		 *
		 */

		if ( empty( $config['products'] ) ) {
			return false;
		}

		$comp_info = self::get_compatibility_info();

		$must_update  = false;
		$must_refresh = false;
		$history      = &$comp_info['history'];
		$comp         = &$comp_info['comp'];

		if ( ! empty( $config['compatibility-actions'] ) ) {

			foreach ( $config['compatibility-actions'] as $product_id => $list_of_updates ) {
				$product_info  = &$config['products'][ $product_id ];
				$product_ver   = &$product_info['active-version']; // product active version
				$last_comp_ver = isset( $comp_info['last'][ $product_id ] ) ? $comp_info['last'][ $product_id ] : 0;
				// maybe need compatibility
				if ( $last_comp_ver ) {
					uksort( $list_of_updates, array( __CLASS__, 'version_compare' ) );

					foreach ( $list_of_updates as $version => $callback ) {
						/**
						 * Just apply update when:
						 * $last_comp_ver < update version <= active product version
						 */
						if (
							self::version_compare( $last_comp_ver, $version, '<' ) &&
							self::version_compare( $version, $product_ver, '<=' )
						) {

							if ( ! isset( $comp[ $product_id ] ) || ! in_array( $version, $comp[ $product_id ] ) ) {
								if ( is_callable( $callback ) ) {

									if ( call_user_func( $callback, $version, $product_id ) ) {
										$comp_info['last'][ $product_id ] = $version;

										$comp[ $product_id ][] = $version;
										$must_update           = true;
										$must_refresh          = true;
									} else {
										break;
									}
								}
							}
						}
					}
				} else {
					// First installation

					//setup compatibility pointer
					$comp_info['last'][ $product_id ] = $product_ver;
					$must_update                      = true;
				}
			}
		}

		if ( ! $must_update ) {
			$active_theme_version = self::WP_Theme_Object()->get( 'Version' );

			//Set version number in history if necessary
			if ( empty( $history[ $active_theme_version ] ) ) {
				$history[ $active_theme_version ] = time();
				$must_update                      = true;
			}
		}

		// Update log
		if ( $must_update ) {

			do_action( 'better-framework/' . self::$id . '/checked', $comp_info );

			self::set_compatibility_info( $comp_info );
			self::clear_css_cache();
		}

		if ( $must_refresh ) {
			header( 'Location: ' . ( isset( $_SERVER['HTTPS'] ) ? "https" : "http" ) . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
		}

		return true;
	} // do_compatibility


	/**
	 * Clear css generator cache storage
	 *
	 */
	public static function clear_css_cache() {

		// Clears BF transients for preventing of happening any problem
		delete_transient( '__better_framework__widgets_css' );
		delete_transient( '__better_framework__panel_css' );
		delete_transient( '__better_framework__menu_css' );
		delete_transient( '__better_framework__terms_css' );
		delete_transient( '__better_framework__final_fe_css' );
		delete_transient( '__better_framework__final_fe_css_version' );
		delete_transient( '__better_framework__backend_css' );

		// Delete all pages css transients
		global $wpdb;
		$wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->postmeta WHERE meta_key LIKE %s", '_bf_post_css_%' ) );

	}


	/**
	 * Get least version of several versions
	 *
	 * @param array $history_array list of version numbers
	 *
	 * @return string|null|bool string version number on success or null|false on failure.
	 */
	protected static function get_initial_version( $history_array ) {

		if ( $history_array ) {
			$history_array = array_flip( $history_array );
			usort( $history_array, array( __CLASS__, 'version_compare' ) );

			return array_shift( $history_array );
		}

		return false;
	}


	/**
	 * Set compatibility status array
	 *
	 * @param array $comp_info {@see get_compatibility_info return value}
	 *
	 * @since 2.14.0
	 */
	public static function set_compatibility_info( $comp_info ) {

		$comp_info = wp_parse_args( $comp_info );
		update_option( self::$option_id, $comp_info, true );
	}


	/**
	 * Get information about compatibility situation
	 *
	 * @return array none empty array on success. array {
	 * @type string $active  active theme version number
	 * @type array  $history theme updates history array{
	 *     key:version number => value: updated time stamp
	 *      ...
	 *    }
	 *
	 * }
	 *
	 * @since 2.14.0
	 */
	public static function get_compatibility_info() {

		if ( $info = get_option( self::$option_id, array() ) ) {
			return $info;
		}

		// TODO: Remove This Backward compatibility
		if ( $info = get_option( 'publisher-theme-comp-info', array() ) ) {

			update_option( self::$option_id, $info );
			delete_option( 'publisher-theme-comp-info' );

			return $info;
		}

		self::apply_default_compatibility_info(); // First installation

		return get_option( self::$option_id, array() );
	}


	/**
	 * Creates base compatibility data
	 *
	 * @since 2.14.0
	 */
	protected static function apply_default_compatibility_info() {

		self::set_compatibility_info( array(
			'history' => array(),
			'comp'    => array(),
		) );
	}


	/**
	 * Compare two version
	 *
	 * @param string $current_version
	 * @param string $another_version
	 * @param string $operator [optional] comparison operator
	 *
	 * @since 2.14.0
	 * @return int
	 *
	 * -1 if $current_version is lower than $another_version,
	 *  0 if they are equal
	 *  1 if $another_version is lower.
	 */
	protected static function version_compare( $current_version, $another_version, $operator = '>' ) {

		return version_compare( $current_version, $another_version, $operator );
	}
}
libs/better-framework/compatibility/class-bf-template-compatibility.php000064400000015365151214002410022511 0ustar00<?php
/***
 *  BetterStudio Themes Core.
 *
 *  ______  _____   _____ _                           _____
 *  | ___ \/  ___| |_   _| |                         /  __ \
 *  | |_/ /\ `--.    | | | |__   ___ _ __ ___   ___  | /  \/ ___  _ __ ___
 *  | ___ \ `--. \   | | | '_ \ / _ \ '_ ` _ \ / _ \ | |    / _ \| '__/ _ \
 *  | |_/ //\__/ /   | | | | | |  __/ | | | | |  __/ | \__/\ (_) | | |  __/
 *  \____/ \____/    \_/ |_| |_|\___|_| |_| |_|\___|  \____/\___/|_|  \___|
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

BF_Template_Compatibility::init();


/**
 * BetterFramework static files compatibility manager.
 *
 * @package   BetterFramework
 * @author    BetterStudio <info@betterstudio.com>
 * @link      http://www.betterstudio.com
 *
 * @version   2.14.0
 * @access    public
 */
class BF_Template_Compatibility {

	/**
	 * @var string
	 */
	public static $id = 'bf-template-compatibility';


	/**
	 * Initialize library
	 *
	 * @since 2.14.0
	 */
	public static function init() {

		add_action( 'better-framework/after_setup', 'BF_Template_Compatibility::init_compatibility' );
	}


	/**
	 * Fire compatibility
	 *
	 * @since 2.14.0
	 * @return array
	 */
	public static function init_compatibility() {

		$config = apply_filters( 'better-framework/template-compatibility/config', array( 'scan_dir' => array() ) );

		return self::do_compatibility( $config );
	}


	/**
	 * Scan files/folders for outdated items
	 *
	 * @since 2.14.0
	 *
	 * @param array $config
	 * @param bool  $fire_callback
	 *
	 * @return array
	 */
	public static function do_compatibility( $config = array(), $fire_callback = true ) {

		/**
		 * @var array $config array
		 *
		 *  array['scan_dir] configuration array
		 *
		 *      array['version']
		 *      array['override']
		 *      array['parent']
		 *      array['callback']
		 *      array['options']
		 *           array['recursive']
		 *           array['include_hidden']
		 *           array['exclude']
		 *           array['valid_extensions']
		 * }
		 */


		if ( empty( $config['scan_dir'] ) ) {
			return array();
		}

		$config['scan_dir'] = array_map( 'BF_Template_Compatibility::_normalize_indexes', $config['scan_dir'] );

		$outdated_files_all = array();
		$outdated_files     = array();
		$update_status      = false;
		$wp_filesystem      = bf_file_system_instance();
		$current_status     = (array) get_option( self::$id, array() );

		foreach ( $config['scan_dir'] as $info ) {

			if ( ! empty( $current_status[ $info['hash'] ] ) && empty( $info['force'] ) ) { // is compatibility executed previously?
				continue;
			}

			//
			// Validate configuration indexes
			//

			if ( empty( $info['version'] ) ) {
				continue;
			}

			if ( empty( $info['callback'] ) || ! is_callable( $info['callback'] ) ) {
				continue;
			}

			$override_dir = trailingslashit( $info['override'] );
			$parent_dir   = trailingslashit( $info['parent'] );

			if ( $override_dir === $parent_dir ) {
				continue;
			}

			$options = &$info['options'];

			$dirlist = $wp_filesystem->dirlist( $override_dir, $options['include_hidden'], $options['recursive'] );
			if ( ! $dirlist ) {
				$current_status[ $info['hash'] ] = time();
				$update_status                   = true;
				continue;
			}
			$dirlist = $options['exclude'] ? array_diff_key( $dirlist, array_flip( $options['exclude'] ) ) : $dirlist;

			$outdated_files      = array();
			$validate_extensions = isset( $options['valid_extensions'] );
			$valid_extensions    = $validate_extensions ? array_flip( $options['valid_extensions'] ) : array();

			foreach ( $dirlist as $item ) {

				$basedir = basename( $override_dir );

				foreach ( self::get_files( $item ) as $path => $file ) {

					// only check file with specified extension
					if ( $validate_extensions ) {
						$ext = substr( $path, strrpos( $path, '.' ) + 1 );
						if ( ! isset( $valid_extensions[ $ext ] ) ) {
							continue;
						}
					}

					$override_version = self::get_file_version( $override_dir . $path );
					$parent_version   = self::get_file_version( $parent_dir . $path );

					if ( $parent_version && ( ! $override_version || version_compare( $override_version, $parent_version, '<' ) ) ) {
						$path             = $basedir . '/' . $path;
						$outdated_files[] = compact( 'path', 'override_version', 'parent_version' );
					}
				}
			}

			$outdated_files_all[ $parent_dir ] = $outdated_files;

			if ( $fire_callback && call_user_func( $info['callback'], $outdated_files, $options, $override_dir, $parent_dir ) ) {
				$current_status[ $info['hash'] ] = time();
				$update_status                   = true;
			}
		}

		if ( $update_status ) {
			do_action( 'better-framework/template-compatibility/done', $outdated_files_all, $config );

			update_option( self::$id, $current_status );
		}

		return $outdated_files;
	}


	/**
	 * Arrange configuration array indexes
	 *
	 * @param array $config
	 *
	 * @access private
	 *
	 * @return array
	 */
	public static function _normalize_indexes( $config ) {

		$config['options'] = bf_merge_args( ( isset( $config['options'] ) ? $config['options'] : array() ), array(
			'recursive'      => false,
			'include_hidden' => false,
			'exclude'        => array(),
		) );

		$config['hash'] = md5( serialize( array(
			'version'  => $config['override'],
			'override' => $config['override'],
			'parent'   => $config['parent'],
			'options'  => $config['options'],
		) ) );

		return $config;
	}


	/**
	 * List Directory Files Recursively
	 *
	 * @param array  $filesystem_item
	 * @param string $_base_dir
	 *
	 * @return array
	 */
	public static function get_files( $filesystem_item, $_base_dir = '' ) {

		if ( $filesystem_item['type'] === 'd' ) {

			$_base_dir .= $filesystem_item['name'] . '/';

			$results = array();
			foreach ( $filesystem_item['files'] as $file ) {
				$results += self::get_files( $file, $_base_dir );
			}

			return $results;
		}

		$key = $_base_dir . $filesystem_item['name'];

		return array( $key => $filesystem_item );
	}


	/**
	 * Retrieve metadata from a file. Based on WP Core's get_file_data function.
	 *
	 * @param  string               $file          Path to the file
	 *
	 * @global WP_Filesystem_Direct $wp_filesystem WordPress Filesystem Class
	 *
	 * @return string
	 */
	public static function get_file_version( $file ) {

		global $wp_filesystem;

		/**
		 * @var WP_Filesystem_Direct $wp_filesystem
		 */

		if ( ! $wp_filesystem->exists( $file ) ) {
			return '';
		}

		// Make sure we catch CR-only line endings.
		$file_data = str_replace( "\r", "\n", $wp_filesystem->get_contents( $file ) );
		$version   = '';

		if ( preg_match( '/^[ \t\/*#@]*' . preg_quote( '@version', '/' ) . '(.*)$/mi', $file_data, $match ) && $match[1] ) {
			$version = _cleanup_header_comment( $match[1] );
		}

		return $version;
	}
}
libs/better-framework/compatibility/index.php000064400000000056151214002410015435 0ustar00<?php
// Silent is golden and we believe it ;)libs/better-framework/admin-panel/class-bf-options.php000064400000021226151214002410017027 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// Initializes all panels
BF_Options::init();


/**
 * Panels Options Handler
 */
class BF_Options {


	/**
	 * Contains all values
	 *
	 * @var array
	 */
	public static $values = array();


	/**
	 * Contains ID's of active panels
	 *
	 * @var null
	 */
	public static $panels = null;


	/**
	 * Configuration of all panels
	 *
	 * @var null
	 */
	public static $panels_config = null;


	/**
	 * std value for all panels
	 *
	 * @var array
	 */
	public static $panel_std = array();


	/**
	 * style of all panels
	 *
	 * @var array
	 */
	public static $panel_style = array();


	/**
	 * css of all panels
	 *
	 * @var array
	 */
	public static $panel_css = array();


	/**
	 * fields of all panels
	 *
	 * @var null
	 */
	public static $fields = null;


	/**
	 * Store key of paneles that their value updated and should be saved in DB.
	 *
	 * @var null
	 */
	public static $updated_panels = array();


	/**
	 * Initialize panels
	 */
	public static function init() {

		self::get_panels();

		$lang = bf_get_current_language_option_code();

		foreach ( self::$panels as $panel_id => $panel ) {

			if ( ! isset( $panel['id'] ) ) {
				continue;
			}

			// Gets data from DB
			$saved_value = get_option( $panel_id . $lang );
			if ( $saved_value == false ) {
				$saved_value = get_option( $panel_id );
			}


			// Adds default style option if needed
			if ( isset( $panel['style'] ) && $panel['style'] ) {


				$current_style = self::get_panel_style( $panel_id );

				// when have style form last
				if ( $current_style == false ) {
					update_option( $panel_id . $lang . '_current_style', bf_get_panel_default_style() );
					self::$panel_style[ $panel_id ] = bf_get_panel_default_style();
				}
			}


			// Save options value to database if is not saved before
			if ( $saved_value == false ) {

				// save to db
				self::save_panel_default_values( $panel_id );

			} else {
				self::$values[ $panel_id ] = $saved_value;
			}

		} // for


		add_action( 'wp_footer', array( 'BF_Options', 'wp_footer' ) );

	} // init


	/**
	 * Loads all panels and return
	 *
	 * @return mixed|null|void
	 */
	public static function get_panels() {

		if ( ! is_null( self::$panels ) ) {
			return self::$panels;
		}

		return self::$panels = apply_filters( 'better-framework/panel/add', array() );
	}


	/**
	 * Loads and return panel config
	 *
	 * @param string $panel_id
	 *
	 * @return array|mixed|void
	 */
	public static function load_panel_config( $panel_id = '' ) {

		self::get_panels();

		if ( ! isset( self::$panels[ $panel_id ] ) ) {
			return array();
		}

		if ( isset( self::$panels_config[ $panel_id ] ) ) {
			return self::$panels_config[ $panel_id ];
		}

		return self::$panels_config[ $panel_id ] = apply_filters( 'better-framework/panel/' . $panel_id . '/config', array() );
	}


	/**
	 * Loads and return panel fields
	 *
	 * @param string $panel_id
	 *
	 * @return array|mixed|void
	 */
	public static function load_panel_fields( $panel_id = '' ) {

		if ( empty( $panel_id ) ) {
			return array();
		}

		if ( isset( self::$fields[ $panel_id ] ) ) {
			return self::$fields[ $panel_id ];
		}

		return self::$fields[ $panel_id ] = apply_filters( 'better-framework/panel/' . $panel_id . '/fields', array() );
	}


	/**
	 * Loads and return panel css
	 *
	 * @param string $panel_id
	 *
	 * @return array|mixed|void
	 */
	public static function load_panel_css( $panel_id = '' ) {

		if ( empty( $panel_id ) ) {
			return array();
		}

		if ( isset( self::$panel_css[ $panel_id ] ) ) {
			return self::$panel_css[ $panel_id ];
		}

		return self::$panel_css[ $panel_id ] = apply_filters( 'better-framework/panel/' . $panel_id . '/css', array(), $panel_id );
	}


	/**
	 * Saves panel all options to database
	 *
	 * @param      $id
	 * @param null $lang
	 *
	 * @return bool
	 */
	public static function save_panel_default_values( $id, $lang = null ) {

		if ( is_null( $lang ) || empty( $lang ) ) {
			$lang = bf_get_current_lang();
		}
		if ( $lang == 'none' || $lang == 'all' ) {
			$lang = '';
		}

		$std_fields = self::get_panel_std( $id );

		$current_style = self::get_panel_style( $id );

		$std_id = 'std-' . $current_style;

		$values = array();

		foreach ( $std_fields as $field_id => $field ) {

			if ( isset( $field[ $std_id ] ) ) {
				$value = $field[ $std_id ];
			} elseif ( isset( $field['std'] ) ) {
				$value = $field['std'];
			} elseif ( isset( $field['default'] ) ) {
				$value = $field['default'];
			} else {
				$value = '';
			}

			if ( $field_id == 'style' && $value != $current_style ) {
				if ( $lang != '' ) {
					update_option( $id . '_' . $lang . '_current_style', $value );
				} else {
					update_option( $id . '_current_style', $value );
				}
				$values[ $field_id ] = $value;
			} else {
				$values[ $field_id ] = $value;
			}

		}

		delete_transient( $id . 'panel_css' );

		return self::add_option( $id, $values, $lang );
	}


	/**
	 * Deprecated! Use bf_get_option function.
	 *
	 * Get an option from the database (cached) or the default value provided
	 * by the options setup.
	 *
	 * @param   string $key       Option ID
	 * @param   string $panel_key Panel ID
	 * @param   string $lang      Language
	 *
	 * @return  mixed|null
	 */
	public static function get( $key, $panel_key = '', $lang = null ) {

		return bf_get_option( $key, $panel_key, $lang );
	}


	/**
	 * Return default std id for fields
	 *
	 * @param $panel_id
	 *
	 * @return string
	 */
	public static function get_panel_std_id( $panel_id = false, $lang = null ) {

		// default std
		if ( $panel_id == false ) {
			return 'std';
		}

		static $panel_std_ids;

		// from cache
		if ( isset( $panel_std_ids[ $panel_id ] ) ) {
			return $panel_std_ids[ $panel_id ];
		}

		$current_style = self::get_panel_style( $panel_id, $lang );

		if ( $current_style && $current_style == 'default' ) {
			return $panel_std_ids[ $panel_id ] = 'std';
		} else {
			return $panel_std_ids[ $panel_id ] = 'std-' . $current_style;
		}

	}


	/**
	 * Return default value field id
	 *
	 * @param $panel_id
	 *
	 * @return array
	 */
	public static function get_panel_std( $panel_id = false ) {

		// default std
		if ( $panel_id == false ) {
			return '';
		}

		// from cache
		if ( isset( self::$panel_std[ $panel_id ] ) ) {
			return self::$panel_std[ $panel_id ];
		}

		return self::$panel_std[ $panel_id ] = apply_filters( 'better-framework/panel/' . $panel_id . '/std', array(), $panel_id );
	}


	/**
	 * Returns panel current style
	 *
	 * @param bool $panel_id
	 * @param null $lang
	 *
	 * @return mixed|string|void
	 */
	public static function get_panel_style( $panel_id = false, $lang = null ) {

		// default std
		if ( $panel_id == false ) {
			return 'std';
		}

		// from cache
		if ( isset( self::$panel_style[ $panel_id ] ) ) {
			return self::$panel_style[ $panel_id ];
		}

		return self::$panel_style[ $panel_id ] = get_option( $panel_id . bf_get_current_language_option_code( $lang ) . '_current_style' );
	}


	/**
	 * Used for safe add option
	 *
	 * @param   Int    $ID    Option ID
	 * @param   Array  $value Option Value
	 * @param   string $lang  Option Language
	 *
	 * @return  bool
	 */
	public static function add_option( $ID = null, $value = null, $lang = null ) {

		// if the parameters are not defined stop the process.
		if ( $ID === null || $value === null ) {
			return false;
		}

		if ( is_null( $lang ) ) {
			$lang = bf_get_current_lang();
		}

		if ( $lang != 'none' && ! empty( $lang ) && $lang != 'all' ) {
			$ID .= '_' . $lang;
		}

		$old_value = get_option( $ID );

		if ( $old_value === false ) {
			return add_option( $ID, $value );
		} else {
			if ( $old_value === $value ) {
				return true;
			} else {

				return update_option( $ID, $value );
			}
		}
	}


	/**
	 * Callback: store updated panel values
	 * Action: wp_footer
	 */
	public static function wp_footer() {

		if ( empty( self::$updated_panels ) ) {
			return;
		}

		foreach ( self::$updated_panels as $panel_id ) {

			if ( ! isset( self::$values[ $panel_id ] ) ) {
				continue;
			}

			update_option( $panel_id, self::$values[ $panel_id ] );

		}

	}
}
libs/better-framework/admin-panel/class-bf-admin-panel-front-end-generator.php000064400000017700151214002420023402 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Class BF_Admin_Panel_Front_End_Generator
 */
class BF_Admin_Panel_Front_End_Generator extends BF_Admin_Fields {


	/**
	 * Constructor Function
	 *
	 * @param array $items            Panel All Options
	 * @param       $id               Panel ID
	 * @param array $values           Panel Saved Values
	 *
	 * @since  1.0
	 * @access public
	 * @return \BF_Admin_Panel_Front_End_Generator
	 */
	public function __construct( array &$items, &$id, &$values = array() ) {

		$default = array(
			'templates_dir' => bf_get_dir( 'admin-panel/templates/' )
		);

		// Parent Constructor
		parent::__construct( $default );

		// Ads fields when needed
		$items['fields'] = BF_Options::load_panel_fields( $id );

		$this->items  = $items;
		$this->id     = $id;
		$this->values = $values;

	}


	/**
	 * Display HTML output of panel array
	 *
	 * Display full html of panel array which is defined in object parameter
	 *
	 * @since  1.0
	 * @access public
	 *
	 * @param bool $repeater
	 * @param bool $skip_ajax ignore ajax items
	 *
	 * @return string
	 */
	public function get_fields( $repeater = false, $skip_ajax = true ) {


		/**
		 * Fires before generating panel HTML
		 *
		 * @since 2.0
		 *
		 * @param string $args arguments
		 */
		do_action( 'better-framework/panel/' . $this->id . '/generate/before', $this->items, $this->values );

		$output        = '';
		$counter       = 0;
		$group_counter = array();
		$has_tab       = false;

		$_lang = bf_get_current_language_option_code();

		$current_style = get_option( $this->id . $_lang . '_current_style' );

		$_check = array(
			'tab'         => '',
			'custom'      => '',
			'export'      => '',
			'import'      => '',
			'ajax_action' => '',
			'group'       => '',
			'info'        => '',
		);

		foreach ( $this->items['fields'] as $field ) {

			if ( isset( $field['style'] ) && ! in_array( $current_style, $field['style'] ) ) {
				continue;
			}

			if ( $skip_ajax && ! empty( $field['ajax-tab-field'] ) ) { // Backward compatibility
				continue;
			}

			if ( $skip_ajax && ! empty( $field['ajax-section-field'] ) ) {
				continue;
			}

			if ( ! isset( $field['type'] ) ) {
				continue;
			}

			$field = $this->standardize_field( $field );

			// If value have been saved before
			if ( isset( $field['id'] ) && ! isset( $_check[ $field['type'] ] )
			) {
				$field['value'] = bf_get_option( $field['id'], $this->id );
			}

			if ( $field['type'] === 'info' ) {
				if ( isset( $field['std'] ) ) {
					$field['value'] = $field['std'];
				} else {
					$field['value'] = '';
				}
			}

			if ( $field['type'] != 'repeater' ) {

				$field['input_name'] = $this->input_name( $field );

				if ( ! isset( $field['value'] ) ) {
					$field['value'] = false;
				}
			}


			if ( isset( $field['filter-field'] ) && $field['filter-field-value'] ) {
				if ( $field['filter-field-value'] != bf_get_option( $field['filter-field'], $this->id ) ) {
					$field['section-css']['display'] = "none";
				}
			}

			if ( $field['type'] == 'tab' || $field['type'] == 'subtab' ) {


				if ( $has_tab ) {

					// close all opened groups
					foreach ( array_reverse( $group_counter ) as $level_k => $level_v ) {

						if ( $level_v === 0 ) {
							continue;
						}

						for ( $i = 0; $i < $level_v; $i ++ ) {
							$output .= $this->get_fields_group_close( $field );
						}

						$group_counter[ $level_k ] = 0;
					}
				}


				$is_subtab = $field['type'] == 'subtab';

				if ( $counter != 0 ) {
					$output .= '</div>';
				}

				if ( $is_subtab ) {
					$output .= "\n\n<!-- Section -->\n<div class='group subtab-group' id='bf-group-{$field['id']}'>\n";
				} else {
					$output .= "\n\n<!-- Section -->\n<div class='group' id='bf-group-{$field['id']}'>\n";
				}

				$has_tab = true;

				continue;
			}


			//
			// Close group
			//
			if ( $field['type'] == 'group_close' ) {

				if ( isset( $field['level'] ) && $field['level'] === 'all' ) {

					krsort( $group_counter );

					// close all opened groups
					foreach ( $group_counter as $level_k => $level_v ) {

						if ( $level_v === 0 ) {
							continue;
						}

						for ( $i = 0; $i < $level_v; $i ++ ) {
							$output .= $this->get_fields_group_close( $field );
						}

						$group_counter[ $level_k ] = 0;
					}

				} else {

					krsort( $group_counter );

					// close last opened group
					foreach ( $group_counter as $level_k => $level_v ) {

						if ( ! $level_v ) {
							continue;
						}

						for ( $i = 0; $i < $level_v; $i ++ ) {
							$output .= $this->get_fields_group_close( $field );
							$group_counter[ $level_k ] --;
							break;
						}

					}
				}


				continue;
			}


			//
			// Group
			// All nested groups and same level groups should be closed
			//
			if ( $field['type'] == 'group' ) {

				if ( ! isset( $field['level'] ) ) {
					$field['level'] = 0;
				}

				if ( ! isset( $group_counter[ $field['level'] ] ) ) {
					$group_counter[ $field['level'] ] = 0;
				}

				krsort( $group_counter );

				foreach ( $group_counter as $level_k => $level_v ) {

					if ( $level_k < $field['level'] ) {
						continue;
					}

					for ( $i = 0; $i < $level_v; $i ++ ) {
						$output .= $this->get_fields_group_close( $field );
					}

					$group_counter[ $level_k ] = 0;
				}

				$output .= $this->get_fields_group_start( $field );

				$group_counter[ $field['level'] ] ++;
			}


			if ( ! in_array( $field['type'], $this->supported_fields ) ) {
				continue;
			}

			// for image checkbox sortable option
			if ( isset( $field['is_sortable'] ) && ( $field['is_sortable'] == '1' ) ) {
				$field['section_class'] .= ' is-sortable';
			}

			if ( isset( $field['template'] ) ) {

				$input = call_user_func( array( $this, $field['type'] ), $field );

				$output .= str_replace( '%%input%%', $input, $field['template'] );

			} else {

				$output .= $this->section(
					call_user_func(
						array( $this, $field['type'] ),
						$field
					),
					$field
				);
			}

			$counter ++;

		} // foreach

		if ( $has_tab ) {
			$output .= '</div>';
		}

		/**
		 * Fires after generating panel HTML
		 *
		 * @since 2.0
		 *
		 * @param string $args arguments
		 */
		do_action( 'better-framework/panel/' . $this->id . '/generate/after', $this->items, $this->values, $output );

		return $output;
	}


	/**
	 * PHP __call Magic Function
	 *
	 * @param $name
	 * @param $arguments
	 *
	 * @throws Exception
	 * @internal param $ (string) $name      name of requested method
	 * @internal param $ (array)  $arguments arguments of requested method
	 *
	 * @since    1.0
	 * @access   public
	 * @return mixed
	 */
	public function __call( $name, $arguments ) {

		$file = $this->options['fields_dir'] . $name . '.php';

		// Check if requested field (method) does exist!
		if ( ! file_exists( $file ) ) {
			throw new Exception( $name . ' does not exist!' );
		}

		$options  = $arguments[0];
		$panel_id = $this->id;

		// Capture output
		ob_start();
		require $file;

		$data = ob_get_clean();

		return $data;
	}


}libs/better-framework/admin-panel/class-bf-admin-panel.php000064400000063722151214002420017531 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// Prevent Direct Access
defined( 'ABSPATH' ) or die;


/**
 * BF Admin Panel Main Class
 *
 * @package BetterFramework
 * @since   1.0
 */
class BF_Admin_Panel {


	/**
	 * Holds everything about the front-end template
	 *
	 * @since  1.0
	 * @access public
	 * @var array
	 */
	public $template = array();


	/**
	 * Init Function
	 *
	 * Hook Initial Functions
	 *
	 * @static
	 * @since  1.0
	 * @access public
	 * @return BF_Admin_Panel
	 */
	public static function init() {

		$class = __CLASS__;

		return new $class;
	}


	/**
	 * Constructor Function
	 *
	 * @since  1.0
	 * @access public
	 * @return BF_Admin_Panel
	 */
	public function __construct() {

		// loads all fields
		if ( ! BF_Options::get_panels() ) {
			return;
		}

		// Callback for adding admin menus
		add_action( 'better-framework/admin-menus/admin-menu/before', array( $this, 'add_menu' ) );

		add_action( 'better-framework/panel/save', array( $this, 'handle_saving_option_panel' ) );

		add_action( 'better-framework/panel/reset', array( $this, 'reset_options' ) );

		add_action( 'better-framework/panel/import', array( $this, 'handle_ajax_import' ), 10, 2 );

		// Ajax panel groups handler
		add_action( 'better-framework/panel/ajax-panel-field', array( $this, 'ajax_panel_field' ), 10, 2 );

		if ( is_admin() && isset( $_POST['bf-export'] ) && $_POST['bf-export'] == 1 ) {

			if ( is_user_logged_in() ) {
				add_action( 'admin_init', array( $this, 'handle_export_download' ) );
			}
		}

		// Callback for adding page custom classes
		add_filter( 'admin_body_class', array( $this, 'admin_body_class' ), 999 );

	}


	/**
	 * Handle ajax group loading requests in panel
	 *
	 * @param string $panel_id
	 * @param string $section_id
	 *
	 * @since 2.10.0
	 */
	public function ajax_panel_field( $panel_id, $section_id ) {

		if ( ! class_exists( 'BF_Admin_Panel_Front_End_Generator' ) ) {
			require BF_PATH . 'admin-panel/class-bf-admin-panel-front-end-generator.php';
		}

		$data = $this->get_page_data_by_id( $panel_id );

		if ( ! $data ) {
			return;
		}

		$feg_instance = new BF_Admin_Panel_Front_End_Generator( $data, $panel_id );
		$items        = $feg_instance->get_items();
		$fields       = &$items['fields'];

		if ( empty( $fields[ $section_id ]['ajax-section-handler'] ) ) {

			foreach ( $fields as $idx => $field ) {

				// Backward compatibility
				if ( isset( $field['ajax-tab-field'] ) ) {
					$field['ajax-section-field'] = $field['ajax-tab-field'];
				}

				if ( empty( $field['ajax-section-field'] ) || $field['ajax-section-field'] !== $section_id ) {
					unset( $fields[ $idx ] );
				}
			}

			$feg_instance->set_items( $items );
			$out = $feg_instance->get_fields( false, false );
		} else {

			$args = isset( $fields[ $section_id ]['ajax-section-handler-args'] ) ? $fields[ $section_id ]['ajax-section-handler-args'] : array();
			$args = array_merge( $args, compact( 'panel_id', 'section_id' ) );

			if (
				! isset( $fields[ $section_id ]['ajax-section-handler-type'] ) ||
				$fields[ $section_id ]['ajax-section-handler-type'] === 'field-generator'
			) {

				$items['fields'] = call_user_func( $fields[ $section_id ]['ajax-section-handler'], $args );

				$feg_instance->set_items( $items );
				$out = $feg_instance->get_fields( false, false );

			} else {

				$out = call_user_func( $fields[ $section_id ]['ajax-section-handler'], $args );
			}
		}


		wp_send_json( compact( 'out', 'section_id' ) );
	}


	/**
	 * Callback: Used for adding page custom classes to admin body
	 *
	 * @since   2.0
	 *
	 * @param $classes
	 *
	 * @return string
	 */
	function admin_body_class( $classes ) {

		if ( ! $this->get_current_page_id() ) {

			return $classes;
		}

		$classes = explode( ' ', $classes );

		$classes = array_flip( $classes );

		$classes['bf-admin-panel'] = 'bf-admin-panel';
		$classes['hide-notices']   = 'hide-notices';

		return implode( ' ', $classes );
	}


	/**
	 * Hook register menus to WordPress
	 *
	 * @since  1.0
	 * @access public
	 * @return void
	 */
	public function add_menu() {

		if ( ! is_admin() || bf_is_doing_ajax() ) {
			return;
		}

		foreach ( BF_Options::$panels as $panel_id => $panel ) {

			$config = BF_Options::load_panel_config( $panel_id );

			if ( ! isset( $config['config'] ) ) {
				continue;
			}

			$menu = $config['config'];

			$menu['id'] = $panel_id;

			if ( isset( $panel['theme-panel'] ) ) {
				$menu['theme-panel'] = true;
			}

			// prepare slug
			if ( ! isset( $menu['callback'] ) ) {
				$menu['callback'] = array( $this, 'menu_callback' );
			}

			Better_Framework()->admin_menus()->add_menupage( $menu );
		}

	}


	/**
	 * Get All Paths
	 *
	 * get all paths, such as template directories
	 *
	 * @since  1.0
	 * @access public
	 * @return array|bool
	 */
	public function get_all_paths() {

		$id = $this->get_current_page_id();

		if ( $id == false ) {
			return false;
		}

		$i = BF_PATH . '/includes/';

		$output                                            = array();
		$output['custom-panel-main-default-template']      = $i . 'templates/admin-panel/default/';
		$output['custom-panel-main-template-current-page'] = $i . "templates/admin-panel/{$id}/";
		$output['default-panel-main-template']             = bf_get_dir( "admin-panel/templates/default/" );

		return $output;
	}


	/**
	 * Get current page
	 *
	 * Return current page id
	 *
	 * static
	 *
	 * @since  1.0
	 * @access public
	 * @return string
	 */
	public function get_current_page_id() {

		if ( ! isset( $_GET['page'] ) ) {
			return false;
		}

		$page = explode( '/', $_GET['page'] );

		if ( empty( $page[1] ) ) {
			return false;
		}

		switch ( $page[1] ) {

			// Support better-translation slug
			case 'translations':
				return $page[2];

			default:
				// Validating panel id by slug.
				if ( $this->get_page_data_by_id( $page[1] ) ) {

					return $page[1];
				}

				return false;

		}
	}


	/**
	 * Get page data which is hooked to better-framework/panel/options
	 *
	 * @param string $panel_id Needed page ID
	 *
	 * @since  1.0
	 * @access public
	 * @return bool|array
	 */
	public function get_page_data_by_id( $panel_id ) {


		// If panel slug is page id
		if ( isset( BF_Options::$panels[ $panel_id ] ) ) {

			return BF_Options::load_panel_config( $panel_id );

		} // Check for panels with custom slug
		else {

			foreach ( BF_Options::$panels as $_panel_id => $panel ) {

				$panel = BF_Options::load_panel_config( $_panel_id );

				if (
					isset( $panel['config']['slug'] ) &&
					( $panel['config']['slug'] == $panel_id ||
					  $panel['config']['slug'] == ( 'better-studio/' . $panel_id ) ||
					  $panel['config']['slug'] == ( 'better-studio/translations/' . $panel_id )
					)
				) {
					$panel['panel-id'] = $_panel_id;

					return $panel;
				}

			}
		}

		return false;
	}


	/**
	 * Get page current data
	 *
	 * @since  1.0
	 * @access public
	 * @return bool|array
	 */
	public function get_current_page_data() {

		return $this->get_page_data_by_id( $this->get_current_page_id() );
	}


	/**
	 * Menu Callback
	 *
	 * The callback of add_menupage which is about the front-end stuff
	 *
	 * todo add support for custom template for each panel
	 *
	 * @since  1.0
	 * @access public
	 * @return mixed
	 */
	public function menu_callback() {

		$id = $this->get_current_page_id();

		// If panel id is not valid.
		if ( ! $id ) {
			return;
		}

		$data = (array) $this->get_current_page_data();

		// Update panel id, this used because of custom slug for pages
		if ( isset( $data['panel-id'] ) ) {
			$id = $data['panel-id'];
		}

		if ( ! class_exists( 'BF_Admin_Panel_Front_End_Generator' ) ) {
			require BF_PATH . 'admin-panel/class-bf-admin-panel-front-end-generator.php';
		}

		$front_end_instance = new BF_Admin_Panel_Front_End_Generator( $data, $id );

		// Defined Template Tags
		$this->template = array(
			'id'     => $id,
			'data'   => $data,
			'tabs'   => $front_end_instance->get_tabs(),
			'fields' => $front_end_instance->get_fields(),
			'texts'  => array(
				// Reset Buttons
				'reset-button'      => isset( $data['texts']['reset-button'] ) ? $data['texts']['reset-button'] : __( 'Reset Settings', 'better-studio' ),
				'reset-button-all'  => isset( $data['texts']['reset-button-all'] ) ? $data['texts']['reset-button-all'] : __( 'Reset All Settings', 'better-studio' ),

				// Reset Confirms
				'reset-confirm'     => isset( $data['texts']['reset-confirm'] ) ? $data['texts']['reset-confirm'] : __( 'Are you sure to reset settings?', 'better-studio' ),
				'reset-confirm-all' => isset( $data['texts']['reset-confirm-all'] ) ? $data['texts']['reset-confirm-all'] : __( 'Are you sure to reset all settings?', 'better-studio' ),

				// Save Buttons
				'save-button'       => isset( $data['texts']['save-button'] ) ? $data['texts']['save-button'] : __( 'Save Settings', 'better-studio' ),
				'save-button-all'   => isset( $data['texts']['save-button-all'] ) ? $data['texts']['save-button-all'] : __( 'Save All Settings', 'better-studio' ),

				// Save Confirms
				'save-confirm'      => isset( $data['texts']['save-confirm'] ) ? $data['texts']['save-confirm'] : '',
				'save-confirm-all'  => isset( $data['texts']['save-confirm-all'] ) ? $data['texts']['save-confirm-all'] : __( 'Are you sure to save all settings? this will override specified settings per languages', 'better-studio' ),
			)
		);

		// Add tab class
		$has_tab = $front_end_instance->has_tab();
		if ( $has_tab ) {
			$this->template['css-class'][] = 'panel-with-tab';
		} else {
			$this->template['css-class'][] = 'panel-without-tab';
		}

		if ( isset( $data['panel-desc'] ) ) {
			$this->template['desc'] = $data['panel-desc'];
		}

		$lang = bf_get_current_lang_raw();

		if ( $lang != 'none' ) {

			if ( $lang == 'all' && isset( $data['texts']['panel-desc-lang-all'] ) ) {

				$this->template['desc'] = $data['texts']['panel-desc-lang-all'];

			} elseif ( isset( $data['texts']['panel-desc-lang'] ) ) {

				$this->template['desc'] = sprintf( $data['texts']['panel-desc-lang'], bf_get_language_name( $lang ) );

			}

		}

		$paths = $this->get_all_paths();

		if ( file_exists( $paths['custom-panel-main-template-current-page'] . 'main.php' ) ) {
			require_once $paths['custom-panel-main-template-current-page'] . 'main.php';
		} elseif ( file_exists( $paths['custom-panel-main-default-template'] . 'main.php' ) ) {
			require_once $paths['custom-panel-main-default-template'] . 'main.php';
		} else {
			require_once $paths['default-panel-main-template'] . 'main.php';
		}

	}


	/**
	 * Handle Save Options
	 *
	 * @param array $args The variable that includes all options in array
	 *
	 * @since 1.0
	 * @return void
	 */
	public function handle_saving_option_panel( $args ) {

		/**
		 * Fires before options save
		 *
		 * @since 2.0
		 *
		 * @param string $args arguments
		 */
		do_action( 'better-framework/panel/save/before', $args );

		if ( ! isset( $args['lang'] ) ) {
			$args['lang'] = '';
		}

		if ( $args['lang'] != 'all' ) {

			// Prepare Language
			if ( is_null( $args['lang'] ) || $args['lang'] == 'en' || $args['lang'] == 'none' ) {
				$lang_full = '';
			} else {
				$lang_full = '_' . $args['lang'];
			}

			// Fix for magic_quotes_gpc
			if ( function_exists( 'get_magic_quotes_gpc' ) && is_callable( 'get_magic_quotes_gpc' ) && get_magic_quotes_gpc() ) {
				$args['data'] = stripslashes_deep( $args['data'] );
			}

			// init value if not before
			if ( ! isset( BF_Options::$values[ $args['id'] ] ) ) {
				BF_Options::$values[ $args['id'] ] = get_option( $args['id'] . $lang_full );
			}

			// combine values
			foreach ( (array) $args['data'] as $field_id => $field_value ) {
				BF_Options::$values[ $args['id'] ][ $field_id ] = $field_value;
			}

			$skin_state = $this->prepare_skin( $args['id'], BF_Options::$values[ $args['id'] ], $args['lang'] );

			if ( Better_Framework()->options()->add_option( $args['id'], BF_Options::$values[ $args['id'] ], $args['lang'] ) !== false ) {

				Better_Framework()->factory( 'custom-css-fe' )->clear_cache( 'all' );

				$output = array(
					'status'  => 'succeed',
					'msg'     => __( 'Options saved.', 'better-studio' ),
					'notice'  => $skin_state ? __( 'Pre-defined Skin and Styles updated.', 'better-studio' ) : __( 'All options saved.', 'better-studio' ),
					'refresh' => $skin_state,
				);

			} else {
				$output = array(
					'status' => 'error',
					'msg'    => __( 'Error happened in saving option.', 'better-studio' )
				);
			}

		} else {

			foreach ( bf_get_all_languages() as $lang ) {

				if ( $lang['id'] == 'en' ) {
					$_lang = 'none';
				} else {
					$_lang = $lang['id'];
				}

				// Prepare Language
				if ( is_null( $lang['id'] ) || $lang['id'] == 'en' || $lang['id'] == 'none' ) {
					$lang_full = '';
				} else {
					$lang_full = '_' . $lang['id'];
				}

				// Fix for magic_quotes_gpc
				if ( function_exists( 'get_magic_quotes_gpc' ) && is_callable( 'get_magic_quotes_gpc' ) && get_magic_quotes_gpc() ) {
					$args['data'] = stripslashes_deep( $args['data'] );
				}

				// init value if not before
				if ( ! isset( BF_Options::$values[ $args['id'] . $lang_full ] ) ) {
					$saved_before = get_option( $args['id'] . $lang_full );
					if ( $saved_before == false ) {
						$saved_before = get_option( $args['id'] );
					}
					BF_Options::$values[ $args['id'] . $lang_full ] = $saved_before;
				}

				// combine values
				foreach ( (array) $args['data'] as $field_id => $field_value ) {
					BF_Options::$values[ $args['id'] . $lang_full ][ $field_id ] = $field_value;
				}

				$skin_state = $this->prepare_skin( $args['id'], BF_Options::$values[ $args['id'] . $lang_full ], $_lang );

				if ( Better_Framework()->options()->add_option( $args['id'], BF_Options::$values[ $args['id'] . $lang_full ], $_lang ) !== false ) {

					Better_Framework()->factory( 'custom-css-fe' )->clear_cache( 'all' );

					$output = array(
						'status'  => 'succeed',
						'msg'     => __( 'Options saved.', 'better-studio' ),
						'notice'  => $skin_state ? __( 'Pre-defined Skin and Styles updated.', 'better-studio' ) : __( 'All options saved.', 'better-studio' ),
						'refresh' => $skin_state,
					);

				} else {
					$output = array(
						'status' => 'error',
						'msg'    => __( 'Error happened in saving option.', 'better-studio' )
					);
				}

			}

		}


		/**
		 * Filter result of save panel
		 *
		 * @since 2.0
		 *
		 * @param array  $output  contains result of save
		 * @param string $options contain options
		 */
		$output = apply_filters( 'better-framework/panel/save/result', $output, $args );


		if ( $skin_state && ( $output['status'] == 'succeed' ) ) {
			Better_Framework()->admin_notices()->add_notice( array( 'msg' => $output['notice'] ) );
		}


		/**
		 * Fires after panel save
		 *
		 * @since 2.0
		 *
		 * @param string $args   contain options
		 * @param array  $output arguments
		 */
		do_action( 'better-framework/panel/reset/after', $output, $args );


		echo json_encode( $output );
	}


	/**
	 * Prepare values of options before save for specified values for styles.
	 *
	 * Checks if "style" was changed then check all fields for custom value for new style and change them and returns
	 * changed option.
	 *
	 * @param   string $panel_id Panel ID
	 * @param   array  $data     Panel Data
	 * @param   null   $lang     Panel Language
	 *
	 * @return bool
	 */
	function prepare_skin( $panel_id, &$data = array(), $lang = null ) {

		BF_Options::get_panels();

		// if panel have not valid or have not style
		if ( ! isset( BF_Options::$panels[ $panel_id ] ) || ! isset( BF_Options::$panels[ $panel_id ]['style'] ) || ! BF_Options::$panels[ $panel_id ]['style'] ) {
			return false;
		}

		// if data is empty or not added to function
		if ( bf_count( $data ) <= 0 ) {
			return false;
		}

		if ( is_null( $lang ) || empty( $lang ) ) {
			$lang = bf_get_current_lang();
		}

		if ( $lang == 'en' || $lang == 'none' || $lang == 'all' ) {
			$_lang = '';
		} else {
			$_lang = '_' . $lang;
		}

		$current_style = get_option( $panel_id . $_lang . '_current_style' );

		// if skin not changed
		if ( $current_style == $data['style'] ) {
			return false;
		}

		// update style
		update_option( $panel_id . $_lang . '_current_style', $data['style'], ! empty( $_lang ) ? 'no' : 'yes' );

		// Panel all default values
		$default = BF_Options::get_panel_std( $panel_id );

		// Panel all fields
		$fields = BF_Options::load_panel_fields( $panel_id );

		// Panel std id
		if ( $data['style'] == bf_get_panel_default_style() ) {
			$std_id = 'std';
		} else {
			$std_id = 'std-' . $data['style'];
		}

		foreach ( (array) $fields as $field ) {

			// no style
			// not in this style
			if ( ! isset( $field['style'] ) || ! in_array( $current_style, $field['style'] ) ) {
				continue;
			}

			// If field have std value then change current value std std value
			if ( isset( $default[ $field['id'] ][ $std_id ] ) ) {
				$data[ $field['id'] ] = $default[ $field['id'] ][ $std_id ];
			} elseif ( isset( $default[ $field['id'] ]['std'] ) ) {
				$data[ $field['id'] ] = $default[ $field['id'] ]['std'];
			}

		}

		return true;
	}


	/**
	 * Reset All Options
	 *
	 * @since 1.0
	 *
	 * @param $data
	 *
	 * @return void
	 */
	public function reset_options( $data ) {

		/**
		 * Fires before options reset
		 *
		 * @since 2.0
		 *
		 * @param string $data contain options
		 */
		do_action( 'better-framework/panel/reset/before', $data );

		$fields = BF_Options::load_panel_fields( $data['id'] );

		// Reset specific language panel data
		if ( $data['lang'] != 'all' ) {

			if ( isset( $fields['style'] ) ) {

				if ( $data['lang'] != 'none' && ! empty( $data['lang'] ) ) {
					update_option( $data['id'] . '_' . $data['lang'] . '_current_style', 'default' );
				} else {
					update_option( $data['id'] . '_current_style', bf_get_panel_default_style( $data['id'] ) );
				}
			}

			if ( Better_Framework::options()->save_panel_default_values( $data['id'], $data['lang'] ) !== false ) {

				Better_Framework::factory( 'custom-css-fe' )->clear_cache( 'all' );

				$result = array(
					'status'  => 'succeed',
					'msg'     => __( 'Options Reset to default.', 'better-studio' ),
					'refresh' => true,
				);

			} else {

				$result = array(
					'status' => 'error',
					'msg'    => __( 'An error occurred while resetting options.', 'better-studio' )
				);

			}


		} // Reset panel data for all languages
		else {
			foreach ( bf_get_all_languages() as $lang ) {

				if ( $lang['language_code'] == 'en' ) {
					$_lang = 'none';
				} else {
					$_lang = $lang['language_code'];
				}

				if ( isset( $fields['style'] ) ) {

					if ( $data['lang'] != 'none' && ! empty( $data['lang'] ) ) {
						update_option( $data['id'] . '_' . $_lang . '_current_style', 'default' );
					} else {
						update_option( $data['id'] . '_current_style', 'default' );
					}

				}

				if ( Better_Framework::options()->save_panel_default_values( $data['id'], $_lang ) !== false ) {

					Better_Framework::factory( 'custom-css-fe' )->clear_cache( 'all' );

					$result = array(
						'status'  => 'succeed',
						'msg'     => __( 'Options Reset to default.', 'better-studio' ),
						'refresh' => true,
					);

				} else {

					$result = array(
						'status' => 'error',
						'msg'    => __( 'An error occurred while resetting options.', 'better-studio' )
					);

				}

			}


		}


		/**
		 * Filter result of resetting panel
		 *
		 * @since 1.4.0
		 *
		 * @param array  $result contains result of reset
		 * @param string $data   contain options
		 */
		$result = apply_filters( 'better-framework/panel/reset/result', $result, $data );


		/**
		 * Fires after options reset
		 *
		 * @since 2.0
		 *
		 * @param string $data   contain options
		 * @param array  $result contains result of reset
		 */
		do_action( 'better-framework/panel/reset/after', $data, $result );

		// Print result
		echo json_encode( $result );

		Better_Framework::admin_notices()->add_notice( array( 'msg' => $result['msg'] ) );


	}


	/**
	 * Handle Ajax Import
	 *
	 * @since 1.0
	 *
	 * @param $file
	 * @param $args
	 *
	 * @return void
	 */
	public function handle_ajax_import( $file, $args ) {

		$data = bf_get_local_file_content( $file['tmp_name'] );

		$data = json_decode( $data, true );

		/**
		 * Fires before options import
		 *
		 * @since 2.0
		 *
		 * @param string $data contain import file data
		 */
		do_action( 'better-framework/panel/import/before', $data );

		// data is not correct
		if (
			$data === false ||
			! isset( $data['panel-id'] ) ||
			empty( $data['panel-id'] ) ||
			! isset( $data['panel-data'] ) ||
			empty( $data['panel-data'] ) ||
			! isset( $args['panel-id'] ) ||
			empty( $args['panel-id'] )
		) {

			$result = array(
				'msg'    => __( 'Imported data is not correct or was corrupted.', 'better-studio' ),
				'status' => 'error'
			);

		} elseif ( $args['panel-id'] != $data['panel-id'] ) {
			$result = array(
				'msg'    => __( 'Imported data is not for this panel.', 'better-studio' ),
				'status' => 'error'
			);

		} else {

			if ( isset( $args['lang'] ) && $args['lang'] != 'none' ) {
				$lang = $args['lang'];
			} else {
				$lang = '';
			}

			// Save options
			update_option( $data['panel-id'] . ( empty( $lang ) ? '' : '_' . $lang ), $data['panel-data'] );

			// Imports style
			if ( isset( $data['panel-data']['style'] ) && ! empty( $data['panel-data']['style'] ) ) {
				update_option( $data['panel-id'] . ( empty( $lang ) ? '' : '_' . $lang ) . '_current_style', $data['panel-data']['style'] );
			}

			// Clear CSS caches
			Better_Framework::factory( 'custom-css-fe' )->clear_cache( 'all' );

			$result = array(
				'msg'     => __( 'Theme Options successfully imported.', 'better-studio' ),
				'status'  => 'succeed',
				'refresh' => true,
			);

		}


		/**
		 * Filter result of import options
		 *
		 * @since 2.0
		 *
		 * @param string $data   contains file data
		 * @param array  $result contains result of reset
		 * @param array  $args   arguments
		 */
		$result = apply_filters( 'better-framework/panel/import/result', $result, $data, $args );


		/**
		 * Fires after options import
		 *
		 * @since 2.0
		 *
		 * @param string $data   contains file data
		 * @param array  $result contains result of reset
		 */
		do_action( 'better-framework/panel/import/after', $data, $result );


		// Print result
		echo json_encode( $result );

		// Success notice
		if ( $result['status'] == 'succeed' ) {
			Better_Framework::admin_notices()->add_notice( array( 'msg' => $result['msg'], 'product' ) );
		}

	}


	/**
	 * @param string $panel_id
	 * @param string $lang
	 *
	 * @return array|bool array on success or false on failure.
	 */
	public function get_export_data( $panel_id, $lang = 'none' ) {

		$export   = array();
		$panel_id = sanitize_key( $panel_id );

		// validate panel id
		$config = apply_filters( "better-framework/panel/$panel_id/config", array() );

		if ( empty( $config ) ) {

			return false;
		}

		$export['panel-id'] = $panel_id;

		$lang = $export['panel-multilingual'] = sanitize_key( $lang );

		if ( $lang != 'none' ) {
			$lang = '_' . $lang;
		} else {
			$lang = '';
		}

		$export['panel-data'] = get_option( $panel_id . $lang );


		/**
		 * Filter for export data
		 *
		 * @since 2.0
		 *
		 * @param string $options contains export data
		 */
		return apply_filters( 'better-framework/panel/export/data', $export );
	}


	/**
	 * Add Default Options After Theme Activated.
	 *
	 * @since 1.0
	 * @return void
	 */
	public function handle_export_download() {

		if ( ! is_user_logged_in() ) {
			die( "Illegal access." );
		}

		if ( empty( $_POST['panel_id'] ) ) {
			return;
		}

		$panel_id = sanitize_key( $_POST['panel_id'] );
		$lang     = isset( $_POST['lang'] ) ? sanitize_key( $_POST['lang'] ) : '';

		// Get panel capability
		$cap = empty( $config['config']['capability'] ) ? 'manage_options' : $config['config']['capability'];

		if ( ! current_user_can( $cap ) ) {
			die( "Illegal access." );
		}

		$options_array = $this->get_export_data( $panel_id, $lang );

		/**
		 * Fires before options export
		 *
		 * @since 2.0
		 *
		 * @param string $options contains export data
		 */
		do_action( 'better-framework/panel/export/before', $options_array );


		// Custom file name for each theme
		if ( isset( $_POST['file_name'] ) && ! empty( $_POST['file_name'] ) ) {
			$file_name = $_POST['file_name'] . '-' . date( 'm-d-Y h:i:s a', time() );
		} else {
			$file_name = 'options-backup-' . date( 'm-d-Y h:i:s a', time() );
		}

		/**
		 * Filter export file name
		 *
		 * @since 2.0
		 *
		 * @param string $filename contains current file name
		 * @param string $options  contains export data
		 */
		$file_name     = apply_filters( 'better-framework/panel/export/file-name', sanitize_file_name( $file_name ), $options_array );
		$options_array = json_encode( $options_array );


		// No Cache
		header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' );
		header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
		header( 'Cache-Control: no-store, no-cache, must-revalidate' );
		header( 'Cache-Control: post-check=0, pre-check=0', false );
		header( 'Pragma: no-cache' );
		header( 'Content-Type: application/force-download' );
		header( 'Content-Length: ' . strlen( $options_array ) );
		header( 'Content-Disposition: attachment; filename="' . $file_name . '.json"' );

		add_filter( 'wp_die_handler', array( $this, 'wp_die_handler' ) );

		wp_die( $options_array );
	}


	/**
	 * @hooked wp_die_handler in handle_export_download method
	 *
	 * @return array
	 */
	public function wp_die_handler() {

		return array( $this, 'print_and_exit' );
	}


	/**
	 * @param string $data
	 */
	public function print_and_exit( $data ) {

		echo $data;

		exit;
	}
}
libs/better-framework/admin-panel/functions.php000064400000014646151214002420015665 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_get_option' ) ) {
	/**
	 * Get an option from the database (cached) or the default value provided
	 * by the options setup.
	 *
	 * @param   string $key       Option ID
	 * @param   string $panel_key Panel ID
	 * @param   string $lang      Language
	 *
	 * @return  mixed|null
	 */
	function bf_get_option( $key, $panel_key = '', $lang = null ) {

		if ( empty( $panel_key ) ) {
			return null;
		}

		static $lang_full;

		// create lang id and cache it
		if ( $lang_full ) {

			// Prepare Language
			if ( is_null( $lang ) || $lang == 'en' || $lang == 'none' ) {
				$lang_full = bf_get_current_lang();
			}

			if ( $lang == 'en' || $lang == 'none' || $lang == 'all' ) {
				$lang_full = '';
			} else {
				$lang_full = '_' . $lang;
			}
		}


		// init value if not before
		if ( ! isset( BF_Options::$values[ $panel_key ] ) ) {

			$saved_value = get_option( $panel_key . $lang_full );

			if ( ! empty( $lang_full ) && $saved_value == false ) {
				$saved_value = get_option( $panel_key );
			}

			BF_Options::$values[ $panel_key ] = $saved_value;
		}


		// return saved value
		if ( isset( BF_Options::$values[ $panel_key ][ $key ] ) ) {

			return BF_Options::$values[ $panel_key ][ $key ];
		}


		return bf_get_std( $key, $panel_key, $lang );

	} // bf_get_option
} // if


if ( ! function_exists( 'bf_echo_option' ) ) {
	/**
	 * echo an option from the database (cached) or the default value provided
	 * by the options setup.
	 *
	 * @see bf_get_option
	 *
	 * @param   string $key       Option ID
	 * @param   string $panel_key Panel ID
	 * @param   string $lang      Language
	 *
	 * @return  mixed|null
	 */
	function bf_echo_option( $key, $panel_key = '', $lang = null ) {

		echo bf_get_option( $key, $panel_key, $lang ); // escaped before in saving inside option!
	} // bf_echo_option
} // if


if ( ! function_exists( 'bf_set_option' ) ) {
	/**
	 * Used to change option only in cache
	 *
	 * @param   string  $key       Option ID
	 * @param   complex $value     Value
	 * @param   string  $panel_key Panel ID
	 * @param   string  $lang      Language
	 *
	 * @return mixed|null
	 */
	function bf_set_option( $key, $value, $panel_key = '', $lang = null ) {

		if ( empty( $panel_key ) ) {
			$panel_key = Better_Framework::options()->get_theme_panel_id();
		}

		// Prepare Language
		if ( is_null( $lang ) || $lang == 'en' || $lang == 'none' ) {
			$lang = bf_get_current_lang();
		}

		if ( $lang == 'en' || $lang == 'none' || $lang == 'all' ) {
			$_lang = '';
		} else {
			$_lang = '_' . $lang;
		}

		Better_Framework::options()->cache[ $panel_key . $_lang ][ $key ] = $value;

	} // bf_set_option
} // if


if ( ! function_exists( 'bf_get_panel_default_style' ) ) {
	/**
	 * Handy function to get panels default style field id
	 *
	 * @param string $panel_id
	 *
	 * @return string
	 */
	function bf_get_panel_default_style( $panel_id = '' ) {

		return 'default';
	}
}


if ( ! function_exists( 'bf_main_option' ) ) {
	/**
	 * Get wordpress  option
	 *
	 * @param string $option      Name of option to retrieve. Expected to not be SQL-escaped.
	 * @param mixed  $default     Optional. Default value to return if the option does not exist.
	 * @param bool   $is_autoload Optional. is the option autoload?
	 *
	 * @see get_option
	 * @return mixed Value set for the option.
	 */
	function bf_main_option( $option, $default = false, $is_autoload = true ) {

		if ( $is_autoload ) {
			$alloptions = wp_load_alloptions();

			if ( isset( $alloptions[ $option ] ) ) {
				return $alloptions[ $option ];
			} else {
				$value = wp_cache_get( $option, 'options' );
				if ( $value !== false ) {
					return $value;
				}
			}

			return $default;
		}

		return get_option( $option, $default );
	}
}


if ( ! function_exists( 'bf_get_std' ) ) {
	/**
	 * Get default value of an option
	 *
	 * @param   string $key       Option ID
	 * @param   string $panel_key Panel ID
	 * @param   string $lang      Language
	 *
	 * @return  mixed|null
	 */
	function bf_get_std( $key, $panel_key = '', $lang = null ) {

		if ( empty( $panel_key ) ) {
			return null;
		}

		static $lang_full;

		// create lang id and cache it
		if ( $lang_full ) {

			// Prepare Language
			if ( is_null( $lang ) || $lang == 'en' || $lang == 'none' ) {
				$lang_full = bf_get_current_lang();
			}

			if ( $lang == 'en' || $lang == 'none' || $lang == 'all' ) {
				$lang_full = '';
			} else {
				$lang_full = '_' . $lang;
			}
		}


		// init panel std values
		BF_Options::get_panel_std( $panel_key );


		// if std is not defined for field
		if ( ! isset( BF_Options::$panel_std[ $panel_key ][ $key ] ) ) {
			//bf_var_dump_exit( 'here', $panel_key, $key, BF_Options::$panel_std[ $panel_key ] );

			return null;
		}

		// just simple force for repeater default!
		if ( isset( BF_Options::$panel_std[ $panel_key ][ $key ]['default'] ) ) {
			return BF_Options::$panel_std[ $panel_key ][ $key ]['default'];
		}

		// std id
		$std_id = BF_Options::get_panel_std_id( $panel_key, $lang );

		// detect std value
		if ( isset( BF_Options::$panel_std[ $panel_key ][ $key ][ $std_id ] ) ) {
			return BF_Options::$panel_std[ $panel_key ][ $key ][ $std_id ];
		} elseif ( isset( BF_Options::$panel_std[ $panel_key ][ $key ]['std'] ) ) {
			return BF_Options::$panel_std[ $panel_key ][ $key ]['std'];
		} else {
			return null;
		}

	} // bf_get_std
} // if


if ( ! function_exists( 'bf_echo_std' ) ) {
	/**
	 * echo an option default value
	 *
	 * @see bf_get_std
	 *
	 * @param   string $key       Option ID
	 * @param   string $panel_key Panel ID
	 * @param   string $lang      Language
	 *
	 * @return  mixed|null
	 */
	function bf_echo_std( $key, $panel_key = '', $lang = null ) {

		echo bf_get_std( $key, $panel_key, $lang ); // escaped before in saving inside option!
	} // bf_echo_std
}
libs/better-framework/admin-panel/index.php000064400000000012151214002420014742 0ustar00<?php
die;libs/better-framework/admin-panel/templates/default.php000064400000004456151214002420017275 0ustar00<?php
$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes   = $classes['section'];
$container_classes = $classes['container'];

$heading_classes  = $classes['heading'];
$controls_classes = $classes['controls'];
$explain_classes  = $classes['explain'];

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];

if ( ! isset( $options['desc'] ) || empty( $options['desc'] ) ) {
	$controls_classes .= ' ' . 'no-desc';
}

$section_css_attr = $this->get_section_css_attr( $options );
$section_attr     = $this->get_section_filter_attr( $options );

?>
<div
		class="<?php echo esc_attr( $container_classes ); ?> bf-admin-panel bf-clearfix" <?php echo $section_css_attr; // escaped before ?> <?php echo $section_attr// escaped before; ?>
	<?php echo bf_show_on_attributes( $options ); ?>>
	<div class="<?php echo esc_attr( $section_classes ); ?> bf-clearfix"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>">

		<div class="<?php echo esc_attr( $heading_classes ); ?> bf-clearfix">
			<h3><label><?php echo esc_html( $options['name'] ); ?></label></h3>
		</div>

		<div class="<?php echo esc_attr( $controls_classes ); ?> bf-clearfix">
			<?php echo $input; // escaped before in generating ?>
		</div>

		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div
					class="<?php echo esc_attr( $explain_classes ); ?> bf-clearfix"><?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?></div>
		<?php } ?>

	</div>
</div>libs/better-framework/admin-panel/templates/hr.php000064400000000320151214002420016244 0ustar00<div class="bf-section-container bf-clearfix" <?php echo bf_show_on_attributes( $options ); ?>>

	<div class="bf-section-hr bf-clearfix">
		<?php echo $input; // escaped before in generating ?>
	</div>
</div>libs/better-framework/admin-panel/templates/heading.php000064400000002444151214002420017243 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

$style = ! empty( $options['layout'] ) ? $options['layout'] : 'style-1';

?>
<div class="bf-section-container bf-clearfix" <?php echo bf_show_on_attributes( $options ); ?>>

	<div class="bf-section-heading bf-clearfix <?php echo $style; ?>">
		<div class="bf-section-heading-title bf-clearfix">
			<h3><?php echo esc_html( $options['name'] ); ?></h3>
		</div>
		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div
					class="bf-section-heading-desc bf-clearfix"><?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?></div>
		<?php } ?>
	</div>
</div>
libs/better-framework/admin-panel/templates/info.php000064400000004417151214002420016601 0ustar00<?php

$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes = $classes['section'] . ' bf-widget-field-section';

$heading_classes  = $classes['heading'] . ' bf-heading';
$controls_classes = $classes['controls'] . ' bf-control not-prepared';
$explain_classes  = $classes['explain'] . ' bf-desc';

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];


if ( ! isset( $options['info-type'] ) ) {
	$options['info-type'] = 'info';
}

if ( ! isset( $options['state'] ) ) {
	$options['state'] = 'open';
}

?>
<div class="bf-section-container bf-admin-panel bf-clearfix" <?php echo bf_show_on_attributes( $options ); ?>>

	<div
			class="bf-section-info <?php echo esc_attr( $options['info-type'] ); ?> <?php echo esc_attr( $options['state'] ); ?> bf-clearfix">
		<div class="bf-section-info-title bf-clearfix">
			<h3><?php

				switch ( $options['info-type'] ) {

					case 'help':
						echo '<i class="fa fa-support"></i> ';
						break;

					case 'info':
						echo '<i class="fa fa-info"></i> ';
						break;

					case 'warning':
						echo '<i class="fa fa-warning"></i> ';
						break;

					case 'danger':
						echo '<i class="fa fa-exclamation"></i> ';
						break;

					default:
						echo '<i class="fa fa-info"></i> ';
						break;


				}

				echo esc_html( $options['name'] ); ?></h3>
		</div>
		<div class="<?php echo esc_attr( $controls_classes ); ?>  bf-clearfix">
			<?php echo $input; // escaped before in generating ?>
		</div>
	</div>
</div>libs/better-framework/admin-panel/templates/border.php000064400000004453151214002420017123 0ustar00<?php
$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes = $classes['section'];

$heading_classes  = $classes['heading'];
$controls_classes = $classes['controls'];
$explain_classes  = $classes['explain'];

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];

?>
<div class="bf-section-container bf-admin-panel bf-clearfix" data-id="<?php echo esc_attr( $options['id'] ); ?>"
	<?php echo bf_show_on_attributes( $options ); ?>>
	<div class="<?php echo esc_attr( $section_classes ); ?> bf-clearfix"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>">

		<div class="<?php echo esc_attr( $heading_classes ); ?> bf-clearfix">
			<h3><label><?php echo esc_html( $options['name'] ); ?></label></h3>
		</div>

		<div class="<?php echo esc_attr( $controls_classes ); ?> bf-clearfix">
			<?php echo $input; // escaped before in generating ?>


			<?php if ( isset( $options['desc'] ) && ! empty( $options['desc'] ) ) { ?>
				<div class="typography-desc">
					<?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?>
				</div>
			<?php } ?>
		</div>

		<?php if ( isset( $options['preview'] ) && $options['preview'] ) { ?>
			<div class="<?php echo esc_attr( $explain_classes ); ?> bf-clearfix">
				<?php
				?>

				<div class="border-preview">
					<div class="preview-box"
					     style="<?php echo isset( $options['preview-css'] ) ? $options['preview-css'] : ''; // escaped before in saving to options ?>">

					</div>
				</div>
			</div>
		<?php } ?>
	</div>
</div>libs/better-framework/admin-panel/templates/repeater.php000064400000004030151214002420017444 0ustar00<?php
$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes   = $classes['section'];
$container_classes = $classes['container'];

$heading_classes  = $classes['heading'];
$controls_classes = $classes['controls'];
$explain_classes  = $classes['explain'];

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];

if ( ! isset( $options['desc'] ) || empty( $options['desc'] ) ) {
	$controls_classes .= ' ' . 'no-desc';
}

?>
<div
		class="<?php echo esc_attr( $container_classes ); ?> bf-admin-panel bf-clearfix" <?php echo bf_show_on_attributes( $options ); ?>>

	<div class="<?php echo esc_attr( $section_classes ); ?> bf-clearfix"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>">

		<div class="<?php echo esc_attr( $heading_classes ); ?> bf-clearfix">
			<h3><label><?php echo esc_html( $options['name'] ); ?></label></h3>
		</div>

		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div class="<?php echo esc_attr( $explain_classes ); ?> bf-clearfix">
				<?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?>
			</div>
		<?php } ?>

		<div class="<?php echo esc_attr( $controls_classes ); ?> bf-clearfix">
			<?php echo $input; // escaped before in generating  ?>
		</div>

	</div>
</div>libs/better-framework/admin-panel/templates/typography.php000064400000010227151214002420020050 0ustar00<?php
$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes = $classes['section'];

$heading_classes  = $classes['heading'];
$controls_classes = $classes['controls'];
$explain_classes  = $classes['explain'];

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];

?>
<div class="bf-section-container bf-admin-panel bf-clearfix" data-id="<?php echo esc_attr( $options['id'] ); ?>"
	<?php echo bf_show_on_attributes( $options ); ?>>

	<div class="<?php echo esc_attr( $section_classes ); ?> bf-clearfix"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>">

		<div class="<?php echo esc_attr( $heading_classes ); ?> bf-clearfix">
			<h3><label><?php echo esc_attr( $options['name'] ); ?></label></h3>
		</div>

		<div class="<?php echo esc_attr( $controls_classes ); ?> bf-clearfix">
			<?php echo $input; // escaped before in generating ?>
		</div>

		<?php if ( isset( $options['preview'] ) && $options['preview'] ) { ?>
			<div class="<?php echo esc_attr( $explain_classes ); ?> bf-clearfix">
				<?php if ( isset( $options['desc'] ) && ! empty( $options['desc'] ) ) { ?>
					<div class="typography-desc">
						<?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?>
					</div>
				<?php } ?>

				<?php if ( ! isset( $options['preview_tab'] ) ) {
					$options['preview_tab'] = 'title';
				}
				?>
				<a class="load-preview-texts"
				   href="javascript: void(0);"><?php esc_html_e( 'Load Preview', 'better-studio' ); ?></a>
				<div class="typography-preview">
					<ul class="preview-tab bf-clearfix">
						<li class="tab <?php echo $options['preview_tab'] == 'title' ? 'current' : ''; ?>"
						    data-tab="title"><a
									href="javascript: void(0);"><?php esc_html_e( 'Heading', 'better-studio' ); ?></a>
						</li>
						<li class="tab <?php echo $options['preview_tab'] == 'paragraph' ? 'current' : ''; ?>"
						    data-tab="paragraph"><a
									href="javascript: void(0);"><?php esc_html_e( 'Paragraph', 'better-studio' ); ?></a>
						</li>
						<li class="tab <?php echo $options['preview_tab'] == 'divided' ? 'current' : ''; ?>"
						    data-tab="divided"><a
									href="javascript: void(0);"><?php esc_html_e( 'Divided', 'better-studio' ); ?></a>
						</li>
					</ul>

					<p class="preview-text <?php echo $options['preview_tab'] == 'title' ? 'current' : ''; ?> title">
						<?php if ( isset( $options['preview_text'] ) && ! empty( $options['preview_text'] ) ) {
							echo esc_html( $options['preview_text'] );
						} else {
							echo bf_get_option( 'typo_text_heading', 'better-framework-custom-fonts' );
						} ?>
					</p>
					<p class="preview-text paragraph <?php echo $options['preview_tab'] == 'paragraph' ? 'current' : ''; ?>">
						<?php if ( isset( $options['preview_text'] ) && ! empty( $options['preview_text'] ) ) {
							echo esc_html( $options['preview_text'] );
						} else {
							echo bf_get_option( 'typo_text_paragraph', 'better-framework-custom-fonts' );
						} ?>
					</p>

					<p class="preview-text divided <?php echo $options['preview_tab'] == 'divided' ? 'current' : ''; ?>">
						<?php if ( isset( $options['preview_text'] ) && ! empty( $options['preview_text'] ) ) {
							echo esc_html( $options['preview_text'] );
						} else {
							echo bf_get_option( 'typo_text_divided', 'better-framework-custom-fonts' );

						} ?>
					</p>

				</div>
			</div>
		<?php } ?>
	</div>
</div>
libs/better-framework/admin-panel/templates/image_preview.php000064400000002303151214002420020461 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div class="bf-section-container bf-clearfix">
	<div
			class="bf-section bf-section-image-preview bf-clearfix">
		<?php if ( ! empty( $options['name'] ) ) { ?>
			<div class="bf-section-info-title bf-clearfix">
				<h3><?php echo esc_html( $options['name'] ); ?></h3>
			</div>
		<?php } ?>
		<div class="<?php echo isset( $controls_classes ) ? esc_attr( $controls_classes ) : ''; ?>  bf-clearfix">
			<?php echo $input; // escaped before ?>
		</div>
	</div>
</div>
libs/better-framework/admin-panel/templates/default/main.php000064400000005057151214002420020217 0ustar00<?php
$template = $this->template;

$lang = bf_get_current_lang();

?>
<div class="panel-wrapper">
	<div id="bf-panel"
	     class="panel-<?php echo esc_attr( $template['id'] ); ?> <?php echo isset( $template['css-class'] ) ? implode( ' ', $template['css-class'] ) : ''; ?>">

		<header class="bf-page-header">
			<div class="bf-page-header-inner bf-clearfix">
				<h2 class="page-title"><?php echo esc_html( $template['data']['panel-name'] ); ?></h2>
				<?php
				if ( ! empty( $template['desc'] ) ) {
					echo '<div class="page-desc">' . wp_kses( $template['desc'], bf_trans_allowed_html() ) . '</div>';  // escaped before
				} ?>

				<div class="reset-sec">
					<div class="btn-sec">
						<a class="fleft bf-button bf-reset-button"
						   data-confirm="<?php echo $lang == 'all' ? esc_attr( $template['texts']['reset-confirm-all'] ) : esc_attr( $template['texts']['reset-confirm'] ); ?>">
							<i class="bsai-reset-clean"></i><?php echo $lang == 'all' ? esc_html( $template['texts']['reset-button-all'] ) : esc_html( $template['texts']['reset-button'] ); ?>
						</a>
					</div>
				</div>
				<div class="btn-sec">
					<a class="fright bf-save-button bf-button bf-main-button"
					   data-confirm="<?php echo $lang == 'all' ? esc_attr( $template['texts']['save-confirm-all'] ) : esc_attr( $template['texts']['save-confirm'] ); ?>">
						<i class="bsai-save-clean"></i> <?php echo $lang == 'all' ? esc_html( $template['texts']['save-button-all'] ) : esc_html( $template['texts']['save-button'] ); ?>
					</a>
					<input type="hidden" id="bf-panel-id" value="<?php echo esc_attr( $template['id'] ); ?>"/>
				</div>

				<div class="bf-options-change-notice" style="display: none;">
					<?php esc_html_e( 'Options Changed', 'better-studio' ) ?>
				</div>
			</div>
		</header>

		<div id="bf-main" class="bf-clearfix">

			<div id="bf-nav"><?php echo $template['tabs']; // escaped before in generating ?></div>

			<div id="bf-content">
				<form id="bf_options_form">
					<?php echo $template['fields']; // escaped before in generating ?>
				</form>
			</div>
		</div>

		<div class="bf-loading">
			<div class="loader">
				<div class="loader-icon in-loading-icon "><i class="dashicons dashicons-update"></i></div>
				<div class="loader-icon loaded-icon"><i class="dashicons dashicons-yes"></i></div>
				<div class="loader-icon not-loaded-icon"><i class="dashicons dashicons-no-alt"></i></div>
				<div class="message"><?php esc_html_e( 'An Error Occurred!', 'better-studio' ); ?></div>
			</div>
		</div>
	</div>
</div>libs/better-framework/core/class-bf-assets-manager.php000064400000023271151214002420017014 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Handles enqueue scripts and styles for preventing conflict and also multiple version of assets in on page
 */
class BF_Assets_Manager {


	/**
	 * Contains footer js codes
	 *
	 * @var array
	 */
	private $footer_js = array();


	/**
	 * Contains head js codes
	 *
	 * @var array
	 */
	private $head_js = array();


	/**
	 * Contains footer js codes
	 *
	 * @var array
	 */
	private $footer_jquery_js = array();


	/**
	 * Contains head js codes
	 *
	 * @var array
	 */
	private $head_jquery_js = array();


	/**
	 * Contains footer css codes
	 *
	 * @var array
	 */
	private $footer_css = array();


	/**
	 * Contains head css codes
	 *
	 * @var array
	 */
	private $head_css = array();


	/**
	 * Contains admin footer js codes
	 *
	 * @var array
	 */
	private $admin_footer_js = array();


	/**
	 * Contains admin head js codes
	 *
	 * @var array
	 */
	private $admin_head_js = array();


	/**
	 * Contains admin footer css codes
	 *
	 * @var array
	 */
	private $admin_footer_css = array();


	/**
	 * Contains admin head css codes
	 *
	 * @var array
	 */
	private $admin_head_css = array();

	/**
	 * Contains header codes
	 *
	 * @var array
	 */
	private $head_codes = array();


	function __construct() {

		// Front End Inline Codes
		add_action( 'wp_head', array( $this, 'print_head' ), 100 );
		add_action( 'wp_head', array( $this, 'force_head_print' ), 100 );
		add_action( 'wp_footer', array( $this, 'print_footer' ), 100 );

		// Backend Inline Codes
		add_action( 'admin_head', array( $this, 'force_head_print' ), 100 );
		add_action( 'admin_head', array( $this, 'print_admin_head' ), 100 );
		add_action( 'admin_footer', array( $this, 'print_admin_footer' ), 100 );

		// Backend Modal
		if ( is_admin() ) {
			add_action( 'admin_footer', array( 'BF_Assets_Manager', 'enqueue_modals' ) );
		}

	}


	/**
	 * DRY!
	 *
	 * @param array  $code
	 * @param string $type
	 * @param string $comment
	 * @param string $before
	 * @param string $after
	 */
	private function _print( $code = array(), $type = 'style', $comment = '', $before = '', $after = '' ) {

		$output = '';

		foreach ( (array) $code as $_code ) {
			$output .= $_code . "\n";
		}

		if ( $output ) {

			if ( ! empty( $comment ) ) {
				echo "\n<!-- {$comment} -->\n<{$type}>{$before}\n{$output}\n{$after}</{$type}>\n<!-- /{$comment}-->\n";
			} else {
				echo "\n<{$type}>{$before}\n{$output}\n{$after}</{$type}>\n";
			}
		}

	}


	/**
	 * Filter Callback: used for printing style and js codes in header
	 */
	function print_head() {

		$this->_print( $this->head_css, 'style', __( 'BetterFramework Head Inline CSS', 'better-studio' ) );
		$this->head_css = array();

		$this->_print( $this->head_js, 'script', __( 'BetterFramework Head Inline JS', 'better-studio' ) );
		$this->head_js = array();

		$this->_print( $this->head_jquery_js, 'script', __( 'BetterFramework Head Inline jQuery Code', 'better-studio' ), 'jQuery(function($){', '});' );
		$this->head_jquery_js = array();

	}


	/**
	 * Filter Callback: used for printing style and js codes in footer
	 */
	function print_footer() {

		// Print header lagged CSS
		$this->_print( $this->head_css, 'style', __( 'BetterFramework Header Lagged Inline CSS', 'better-studio' ) );

		// Print footer CSS
		$this->_print( $this->footer_css, 'style', __( 'BetterFramework Footer Inline CSS', 'better-studio' ) );

		// Print header lagged JS
		$this->_print( $this->head_js, 'script', __( 'BetterFramework Header Lagged Inline JS', 'better-studio' ) );

		// Print header lagged jQuery JS
		$this->_print( $this->head_jquery_js, 'script', __( 'BetterFramework Header Lagged Inline jQuery JS', 'better-studio' ), 'jQuery(function($){', '});' );

		// Print footer JS
		$this->_print( $this->footer_js, 'script', __( 'BetterFramework Footer Inline JS', 'better-studio' ) );

		// Print footer jQuery JS
		$this->_print( $this->footer_jquery_js, 'script', __( 'BetterFramework Footer Inline jQuery JS', 'better-studio' ), 'jQuery(function($){', '});' );

	}


	/**
	 * Filter Callback: used for printing style and js codes in admin header
	 */
	function print_admin_head() {

		// Print admin header CSS
		$this->_print( $this->admin_head_css, 'style', __( 'BetterFramework Admin Head Inline CSS', 'better-studio' ) );
		$this->admin_head_css = array();

		// Print admin header JS
		$this->_print( $this->admin_head_js, 'script', __( 'BetterFramework Head Inline JS', 'better-studio' ) );
		$this->admin_head_js = array();

	}


	/**
	 * Filter Callback: used for printing style and js codes in admin footer
	 */
	function print_admin_footer() {

		// Print header lagged CSS
		$this->_print( $this->admin_head_css, 'style', __( 'BetterFramework Admin Header Lagged Inline CSS', 'better-studio' ) );

		// Print footer CSS
		$this->_print( $this->admin_footer_css, 'style', __( 'BetterFramework Admin Footer Inline CSS', 'better-studio' ) );

		// Print header lagged JS
		$this->_print( $this->admin_head_js, 'script', __( 'BetterFramework Admin Footer Inline JS', 'better-studio' ) );

		// Print footer JS
		$this->_print( $this->admin_footer_js, 'script', __( 'BetterFramework Admin Footer Inline JS', 'better-studio' ) );

	}


	protected function force_print( $code = array(), $type = 'style', $comment = '', $before = '', $after = '' ) {

		// Before head script print or inside TinyMCE ajax callback
		if ( bf_is_doing_ajax( 'fetch-mce-view-shortcode' ) ||
		     bf_is_block_render_request() ||
		     did_action( is_admin() ? 'admin_head' : 'wp_head' )
		) {
			$this->_print( $code, $type, $comment, $before, $after );
		} else {
			$this->head_codes[] = func_get_args();
		}
	}


	public function force_head_print() {

		if ( $this->head_codes ) {
			foreach ( $this->head_codes as $args ) {
				call_user_func_array( array( $this, '_print' ), $args );
			}

			$this->head_codes = array();
		}
	}


	/**
	 * Used for adding inline js
	 *
	 * @param string $code
	 * @param bool   $to_top
	 * @param bool   $force
	 */
	function add_js( $code = '', $to_top = false, $force = false ) {

		if ( $force ) {
			$this->force_print( $code, 'script' );

			return;
		}

		if ( $to_top ) {
			$this->head_js[] = $code;
		} else {
			$this->footer_js[] = $code;
		}
	}


	/**
	 * Used for adding inline js
	 *
	 * @param string $code
	 * @param bool   $to_top
	 * @param bool   $force
	 */
	function add_jquery_js( $code = '', $to_top = false, $force = false ) {

		if ( $force ) {
			$this->force_print( $code, 'script', 'jQuery(function($){', '});' );

			return;
		}

		if ( $to_top ) {
			$this->head_jquery_js[] = $code;
		} else {
			$this->footer_jquery_js[] = $code;
		}

	}


	/**
	 * Used for adding inline css
	 *
	 * @param string $code
	 * @param bool   $to_top
	 * @param bool   $force
	 */
	function add_css( $code = '', $to_top = false, $force = false ) {

		//
		// Handle inline custom css code inside AMP
		//
		if ( bf_is_amp() === 'better' ) {

			better_amp_add_inline_style( $code );

			return;
		}


		if ( $force ) {
			$this->force_print( $code, 'style' );

			return;
		}


		if ( $to_top ) {
			$this->head_css[] = $code;
		} else {
			$this->footer_css[] = $code;
		}
	}


	/**
	 * Used for adding inline js
	 *
	 * @param string $code
	 * @param bool   $to_top
	 * @param bool   $force
	 */
	function add_admin_js( $code = '', $to_top = false, $force = false ) {

		if ( $force ) {
			$this->force_print( $code, 'script' );

			return;
		}

		if ( $to_top ) {
			$this->admin_head_js[] = $code;
		} else {
			$this->admin_footer_js[] = $code;
		}

	}


	/**
	 * Used for adding inline css
	 *
	 * @param string $code
	 * @param bool   $to_top
	 * @param bool   $force
	 */
	function add_admin_css( $code = '', $to_top = false, $force = false ) {

		if ( $force ) {
			$this->force_print( $code, 'style' );

			return;
		}

		if ( $to_top ) {
			$this->admin_head_css[] = $code;
		} else {
			$this->admin_footer_css[] = $code;
		}

	}


	/**
	 * Enqueue styles safely
	 *
	 * @param $style_key
	 */
	function enqueue_style( $style_key = '' ) {

		bf_enqueue_style( $style_key );
	}


	/**
	 * Enqueue scripts safely
	 *
	 * @param $script_key
	 */
	function enqueue_script( $script_key ) {

		bf_enqueue_script( $script_key );
	}


	public static function print_ace_editor_oldie_js() {

		static $loaded = false;

		if ( $loaded ) {
			return;
		}
		?>
		<!--[if lt IE 9]>
		<script type='text/javascript'
		        src='https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.8/ext-old_ie.js'></script>
		<![endif]-->
		<?php

		$loaded = true;
	}


	/**
	 * Contains list of active modals that should be printed in bottom of page
	 *
	 * @var array
	 */
	public static $active_modals;


	/**
	 * Adds modals to active modals list
	 *
	 * @param $modal_id
	 */
	public static function add_modal( $modal_id ) {

		self::$active_modals[ $modal_id ] = $modal_id;
	}


	/**
	 * Callback: Hooked to admin_footer to print all modals in bottom of page
	 */
	public static function enqueue_modals() {

		foreach ( (array) self::$active_modals as $modal ) {
			$modal_template_file = BF_PATH . '/core/field-generator/modals/' . $modal . '.php';
			include $modal_template_file;
		}

	} // enqueue_modals

}
libs/better-framework/core/class-bf-html-generator.php000064400000020164151214002420017030 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * BF Field Generator
 */
class BF_HTML_Generator {


	/**
	 * Holds All Data
	 *
	 * @since  1.0
	 * @access private
	 * @var array
	 */
	private $options = array(
		'attrs' => array(),
		'sub'   => array()
	);


	/**
	 * @var $allowed_tags
	 *
	 */
	private $allowed_tags = array(
		'span',
		'p',
		'div',
		'img',
		'br',
		'a',
		'table',
		'tbody',
		'link',
		'script',
		'meta',
		'form',
		'input',
		'select',
		'ul',
		'ol',
		'h1',
		'h2',
		'h3',
		'h4',
		'h5',
		'h6',
		'strong',
		'textarea',
		'label',
		'button',
		'li',
		'optgroup'
	);


	/**
	 * @var $self_closing_tags
	 *
	 */
	private $self_closing_tags = array(
		'img',
		'br',
		'link',
		'meta',
		'input'
	);


	/**
	 * @var $self_closing_tags
	 *
	 */
	private $form_methods = array(
		'post',
		'get'
	);


	/**
	 * Add New Element
	 *
	 * Return $this for method chaining
	 *
	 * @param string $tag HTML tag name
	 *
	 * @return BF_HTML_Generator
	 */
	public function add( $tag ) {

		if ( ! empty( $this->options['tag'] ) ) {
			$this->options['sub'][] = (string) $tag;

			return $this;
		}

		$this->options['tag'] = $tag;

		return $this;
	}


	/**
	 * Add The Element Content
	 *
	 * Return $this for method chaining
	 *
	 * @param string $val User defined value
	 *
	 * @return BF_HTML_Generator
	 */
	public function _text_( $val ) {

		$this->options['sub'][] = $val;

		return $this;

	}


	/**
	 * Element type attribute
	 *
	 * Return $this for method chaining
	 *
	 * @param string $type Attribute value
	 *
	 * @return BF_HTML_Generator
	 */
	public function _type_( $type ) {

		$this->options['attrs']['type'] = $type;

		return $this;

	}


	/**
	 * Element name attribute
	 *
	 * Return $this for method chaining
	 *
	 * @param string $type Attribute value
	 *
	 * @return BF_HTML_Generator
	 */
	public function _name_( $type ) {

		$this->options['attrs']['name'] = $type;

		return $this;

	}


	/**
	 * Makes CSS Inline Styles For Element
	 *
	 * Return $this for method chaining
	 *
	 * @return BF_HTML_Generator
	 */
	public function _css_() {

		$args     = func_get_args();
		$args_num = func_num_args();
		$css      = '';

		if ( $args_num === 1 ) {
			$css .= ltrim( rtrim( $args[0], ';' ), ';' );
		} elseif ( $args_num === 2 ) {
			$css .= "{$args['0']}:{$args['1']};";
		}

		if ( empty( $this->options['attrs']['style'] ) ) {
			$this->options['attrs']['style'] = '';
		}

		$this->options['attrs']['style'] .= ";{$css};";
		$this->options['attrs']['style'] = preg_replace( '/(^;)|(;$)|(;{,1})/', '', $this->options['attrs']['style'] );

		return $this;
	}


	/**
	 * Add New Attribute To Element
	 *
	 * Return $this for method chaining
	 *
	 * @param string $attr The name of attr
	 * @param string $val  Value if value
	 *
	 * @return BF_HTML_Generator
	 */
	public function attr( $attr, $val ) {

		$this->options['attrs'][ $attr ] = $val;

		return $this;

	}


	/**
	 * Set Action Attribute For Element
	 *
	 * @param string $val Action Value
	 *
	 * @return BF_HTML_Generator
	 */
	public function _action_( $val ) {

		$this->options['attrs']['action'] = $val;

		return $this;

	}


	/**
	 * Set Value Attribute For Element
	 *
	 * @return BF_HTML_Generator
	 */
	public function _val_() {

		$params = func_get_args();

		return call_user_func_array( array( $this, '_value_' ), $params );

	}


	/**
	 * Set Value Attribute For Element
	 *
	 * @param string $val Value
	 *
	 * @return BF_HTML_Generator
	 */
	public function _value_( $val ) {

		if ( $this->options['tag'] == 'textarea' ) {
			$this->options['sub'][] = $val;
		} else {
			$this->options['attrs']['value'] = $val;
		}

		return $this;

	}


	/**
	 * Set ID Attribute For Element
	 *
	 * @param string $val Value
	 *
	 * @return BF_HTML_Generator
	 */
	public function _id_( $val ) {

		$this->options['attrs']['id'] = $val;

		return $this;

	}


	/**
	 * Set Class Attribute For Element
	 *
	 * @param string $val Value
	 *
	 * @return BF_HTML_Generator
	 */
	public function _class_( $val ) {

		$this->options['attrs']['class'][] = $val;

		return $this;

	}


	/**
	 * Set Element SRC Attribute
	 *
	 * @param string $src image src
	 *
	 * @return BF_HTML_Generator
	 */
	public function _src_( $src ) {

		$this->options['attrs']['src'] = $src;

		return $this;

	}


	/**
	 * Set place holder attr
	 *
	 * @param string $val image src
	 *
	 * @return BF_HTML_Generator
	 */
	public function _placeholder_( $val ) {

		$this->options['attrs']['placeholder'] = $val;

		return $this;

	}


	/**
	 * Set title attribute
	 *
	 * @param string $val title
	 *
	 * @return BF_HTML_Generator
	 */
	public function _title_( $val ) {

		$this->options['attrs']['title'] = $val;

		return $this;

	}


	/**
	 * Set alt attribute
	 *
	 * @param string $val alt
	 *
	 * @return BF_HTML_Generator
	 */
	public function _alt_( $val ) {

		$this->options['attrs']['alt'] = $val;

		return $this;

	}


	/**
	 * Set Element Data Attribute
	 *
	 * @param string $name  name of data attr
	 * @param string $value value of data attr
	 *
	 * @return BF_HTML_Generator
	 */
	public function _data_( $name, $value ) {

		$this->options['attrs'][ 'data-' . $name ] = $value;

		return $this;

	}


	/**
	 * Set Method Attribute For Element
	 *
	 * @param string $method Action Value
	 *
	 * @throws Exception if method is not valid
	 *
	 * @return BF_HTML_Generator
	 */
	public function _method_( $method ) {

		// Check for correct form method
		if ( ! in_array( strtolower( $method ), $this->form_methods ) ) {
			throw new Exception( 'Form method should be either post or get.' );
		}

		$this->options['attrs']['method'] = $method;

		return $this;

	}


	public function __call( $name, $arguments ) {

		if ( method_exists( $this, "_{$name}_" ) ) {
			call_user_func_array( array( $this, "_{$name}_" ), $arguments );

			return $this;
		} else {
			throw new Exception( 'Method is inaccessible in object context.' );
		}

	}


	/**
	 * Generate String Of Element Attributes
	 *
	 * @return String
	 */
	public function generate_attrs_string() {

		$attrs  = (array) $this->options['attrs'];
		$output = ' ';
		$i      = 0;

		foreach ( $attrs as $name => $val ) {
			$i ++;
			if ( $name == 'class' ) {
				$output .= $name . '="' . implode( ' ', $val ) . '"';
			} else {
				$output .= $name . '="' . $val . '"';
			}
			if ( $i != bf_count( $attrs ) ) {
				$output .= ' ';
			}
		}

		return $output;

	}


	/**
	 * Display HTML
	 *
	 * @throws Exception if tag is not defined
	 * @since 1.0
	 * @return string
	 */
	public function display() {

		// Stop process if tag name is not defined
		if ( empty( $this->options['tag'] ) ) {
			throw new Exception( 'Tag is not defined.' );
		}

		$tag = $this->options['tag'];

		// Stop process if the tag is not allowed
		if ( ! in_array( $this->options['tag'], $this->allowed_tags ) ) {
			throw new Exception( 'Tag Name is not allowed.' );
		}

		$attrs_string = $this->generate_attrs_string();
		$output       = "<{$tag}{$attrs_string}";
		$output       .= in_array( $tag, $this->self_closing_tags ) ? ' />' : ' >';

		if ( bf_count( $this->options['sub'] ) > 0 ) {
			foreach ( $this->options['sub'] as $sub ) {
				$output .= $sub;
			}
		}

		if ( ! in_array( $tag, $this->self_closing_tags ) ) {
			$output .= "</{$tag}>";
		}

		return $output;

	}


	/**
	 * toString
	 *
	 * Displaying the HTML if object is echoing
	 *
	 * @since 1.0
	 * @return string
	 */
	public function __toString() {

		try {
			return $this->display();
		} catch( Exception $e ) {
			die( $e->getMessage() );
		}

	}

} // BF_HTML_Generatorlibs/better-framework/core/class-bf-helper.php000064400000005273151214002420015363 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Deprecated!
 *
 * Helper functions for BetterFramework
 */
class BF_Helper {


	/**
	 * Deprecated! Use bf_convert_number_to_odd
	 *
	 * @param      $number
	 * @param bool $down
	 *
	 * @return bool|int
	 */
	public static function convert_number_to_odd( $number, $down = false ) {

		return bf_convert_number_to_odd( $number, $down );
	}


	/**
	 * Deprecated! Use bf_is_search_page
	 */
	function is_search_page() {

		return bf_is_search_page();
	}


	/**
	 * Deprecated! Use bf_get_query_var_paged
	 */
	function get_query_var_paged( $default = 1 ) {

		return bf_get_query_var_paged( $default );
	}


	/**
	 * Deprecated! Use bf_get_sidebar_name_from_id
	 */
	public static function get_sidebar_name( $sidebar_id ) {

		return bf_get_sidebar_name_from_id( $sidebar_id );
	}


	/**
	 * Deprecated! Use bf_get_menu_location_name_from_id
	 */
	public static function get_menu_location_name( $location ) {

		return bf_get_menu_location_name_from_id( $location );
	}


	/////////////////////////////////////////////////
	//
	// Multilingual Helper Functions
	//
	/////////////////////////////////////////////////


	/**
	 * Deprecated! Use bf_get_current_lang
	 */
	static function get_current_lang() {

		return bf_get_current_lang();
	}


	/**
	 * Deprecated! Use bf_get_current_lang_raw
	 */
	static function get_current_lang_raw() {

		return bf_get_current_lang_raw();
	}


	/**
	 * Deprecated! Use bf_get_all_languages
	 */
	static function get_languages() {

		return bf_get_all_languages();
	}


	/**
	 * Deprecated! Use bf_get_language_data
	 */
	static function get_language( $lang = null ) {

		return bf_get_language_data( $lang );
	}


	/**
	 *
	 * @deprecated use bf_convert_string_to_class_name()
	 *
	 * @param string $string
	 * @param string $before
	 * @param string $after
	 *
	 * @return string
	 */
	public static function get_file_to_class_name( $string = '', $before = '', $after = '' ) {

		return bf_convert_string_to_class_name( $string, $before, $after );
	}
}libs/better-framework/core/fonts-manager/panel-config.php000064400000005405151214002420017514 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// Language  name for smart admin texts
$lang = bf_get_current_lang_raw();
if ( $lang != 'none' ) {
	$lang = bf_get_language_name( $lang );
} else {
	$lang = '';
}


$panels = array(
	'panel-name' => _x( 'Font Manager', 'Panel title', 'better-studio' ),
	'panel-desc' => '<p>' . __( 'Upload custom fonts and add CSS font stacks.', 'better-studio' ) . '</p>',

	'config' => array(
		'name'                => __( 'Font Manager', 'better-studio' ),
		'parent'              => 'better-studio',
		'slug'                => 'better-studio/fonts-manager',
		'page_title'          => __( 'Font Manager', 'better-studio' ),
		'menu_title'          => __( 'Font Manager', 'better-studio' ),
		'capability'          => 'manage_options',
		'menu_slug'           => __( 'Font Manager', 'better-studio' ),
		'notice-icon'         => BF_URI . 'assets/img/bs-notice-logo.png',
		'icon_url'            => null,
		'position'            => 100.01,
		'exclude_from_export' => false,
		'register_menu'       => apply_filters( 'better-framework/fonts-manager/show-menu', true ),
	),

	'texts' => array(
		'panel-desc-lang'     => '<p>' . __( '%s Language Fonts.', 'better-studio' ) . '</p>',
		'panel-desc-lang-all' => '<p>' . __( 'All Languages Fonts.', 'better-studio' ) . '</p>',

		'reset-button'     => ! empty( $lang ) ? sprintf( __( 'Reset %s Fonts', 'better-studio' ), $lang ) : __( 'Reset Fonts', 'better-studio' ),
		'reset-button-all' => __( 'Reset All Fonts', 'better-studio' ),

		'reset-confirm'     => ! empty( $lang ) ? sprintf( __( 'Are you sure to reset %s fonts?', 'better-studio' ), $lang ) : __( 'Are you sure to reset fonts?', 'better-studio' ),
		'reset-confirm-all' => __( 'Are you sure to reset all fonts?', 'better-studio' ),

		'save-button'     => ! empty( $lang ) ? sprintf( __( 'Save %s Fonts', 'better-studio' ), $lang ) : __( 'Save Fonts', 'better-studio' ),
		'save-button-all' => __( 'Save All Fonts', 'better-studio' ),

		'save-confirm-all' => __( 'Are you sure to save all fonts? this will override specified fonts per languages', 'better-studio' )
	),


);libs/better-framework/core/fonts-manager/class-bf-fm-google-ea-fonts-helper.php000064400000010055151214002420023502 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Used For retrieving Google EA fonts list.
 * Also contain some helper functions for general usage
 */
class BF_FM_Google_EA_Fonts_Helper {


	/**
	 * Contain array of all Google EA Fonts List
	 *
	 * @var array
	 */
	private static $fonts_list = null;


	/**
	 * Used for Retrieving list of all Google EA Fonts
	 */
	public static function get_all_fonts() {

		if ( self::$fonts_list != null ) {
			return self::$fonts_list;
		}

		// standard and current Google EA fonts
		self::$fonts_list = include BF_PATH . 'core/fonts-manager/fonts-google-ea.php';

		// Old fonts that was removed from EA but works!
		// many of our customers are using them!
		self::$fonts_list = include BF_PATH . 'core/fonts-manager/fonts-google-ea-old.php';

		return self::$fonts_list;
	}


	/**
	 * Used for retrieving single font info
	 *
	 * @param   $font_name      string      Font name
	 *
	 * @return  bool
	 */
	public static function get_font( $font_name ) {

		$fonts = self::get_all_fonts();

		if ( isset( $fonts[ $font_name ] ) ) {
			return $fonts[ $font_name ];
		}

		return false;
	}


	/**
	 * Generate and return Option elements of all font for select element
	 *
	 * @param   string $active_font  Family name of selected font in options
	 * @param   bool   $option_group Add options into option group?
	 *
	 * @return string
	 */
	public static function get_fonts_family_option_elements( $active_font = '', $option_group = true ) {

		$output = '';

		if ( $option_group ) {
			$output .= '<optgroup label="' . __( 'Google Early Access Fonts', 'better-studio' ) . '">';
		}

		foreach ( self::get_all_fonts() as $key => $font ) {
			$output .= '<option value="' . esc_attr( $key ) . '"' . ( $key == $active_font ? 'selected' : '' ) . '>' . esc_html( $font['name'] ) . '</option>';
		}

		if ( $option_group ) {
			$output .= '</optgroup>';
		}

		return $output;
	}


	/**
	 * Generate and return Option elements of font variants
	 *
	 * @param   $font               string|array        Font array or ID
	 * @param   $font_variant       string              Active or selected variant
	 *
	 * @return  string
	 */
	public static function get_font_variants_option_elements( $font, $font_variant ) {

		$output = '';

		if ( ! is_array( $font ) ) {
			$font_info = self::get_font( $font );
		} else {
			$font_info = $font;
		}

		if ( $font_variant == '400' || $font_variant == '400italic' ) {
			foreach ( $font_info['variants'] as $variant ) {
				if ( $font_variant == '400' && $variant['id'] == 'regular' ) {
					$font_variant = 'regular';
					break;
				} elseif ( $font_variant == '400italic' && $variant['id'] == 'italic' ) {
					$font_variant = 'italic';
					break;
				}
			}
		}

		foreach ( $font_info['variants'] as $variant ) {
			$output .= '<option value="' . esc_html( $variant['id'] ) . '"' . ( $variant['id'] == $font_variant ? ' selected="selected" ' : '' ) . '>' . esc_html( $variant['name'] ) . '</option>';
		}

		return $output;
	}


	/**
	 * Generate and return Option elements of font subsets
	 *
	 * @param   $font               string|array        Font array or ID
	 * @param   $active_subset      string              Active or selected subset
	 *
	 * @return  string
	 */
	public static function get_font_subset_option_elements( $font, $active_subset ) {

		return '<option value="unknown">' . esc_html__( 'Unknown', 'better-studio' ) . '</option>';
	}

}
libs/better-framework/core/fonts-manager/panel-std.php000064400000007705151214002420017046 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$fields['custom_fonts'] = array(
	'default' => array(
		array(
			'id'    => __( 'Font %i%', 'better-studio' ),
			'woff2' => '',
			'woff'  => '',
			'ttf'   => '',
			'svg'   => '',
			'eot'   => '',
			'otf'   => '',
		),
	),
);

$font_stacks['id']                = array(
	'std' => '',
);
$font_stacks['stack']             = array(
	'std' => '',
);
$fields['font_stacks']            = array(
	'default' => array(
		array(
			'id'    => 'Arial',
			'stack' => 'Arial,"Helvetica Neue",Helvetica,sans-serif',
		),
		array(
			'id'    => 'Arial Black',
			'stack' => '"Arial Black","Arial Bold",Gadget,sans-serif',
		),
		array(
			'id'    => 'Arial Narrow',
			'stack' => '"Arial Narrow",Arial,sans-serif',
		),
		array(
			'id'    => 'Calibri',
			'stack' => 'Calibri,Candara,Segoe,"Segoe UI",Optima,Arial,sans-serif',
		),
		array(
			'id'    => 'Gill Sans',
			'stack' => '"Gill Sans","Gill Sans MT",Calibri,sans-serif',
		),
		array(
			'id'    => 'Helvetica',
			'stack' => '"Helvetica Neue",Helvetica,Arial,sans-serif',
		),
		array(
			'id'    => 'Tahoma',
			'stack' => 'Tahoma,Verdana,Segoe,sans-serif',
		),
		array(
			'id'    => 'Trebuchet MS',
			'stack' => '"Trebuchet MS","Lucida Grande","Lucida Sans Unicode","Lucida Sans",Tahoma,sans-serif',
		),
		array(
			'id'    => 'Verdana',
			'stack' => 'Verdana,Geneva,sans-serif',
		),
		array(
			'id'    => 'Georgia',
			'stack' => 'Georgia,Times,"Times New Roman",serif',
		),
		array(
			'id'    => 'Palatino',
			'stack' => 'Palatino,"Palatino Linotype","Palatino LT STD","Book Antiqua",Georgia,serif',
		),
		array(
			'id'    => 'Courier New',
			'stack' => '"Courier New",Courier,"Lucida Sans Typewriter","Lucida Typewriter",monospace',
		),
		array(
			'id'    => 'Lucida Sans Typewriter',
			'stack' => '"Lucida Sans Typewriter","Lucida Console",monaco,"Bitstream Vera Sans Mono",monospace',
		),
		array(
			'id'    => 'Copperplate',
			'stack' => 'Copperplate,"Copperplate Gothic Light",fantasy',
		),
		array(
			'id'    => 'Papyrus',
			'stack' => 'Papyrus,fantasy',
		),
		array(
			'id'    => 'Brush Script MT',
			'stack' => '"Brush Script MT",cursive',
		),
		array(
			'id'    => 'System Font',
			'stack' => '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", "Open Sans", sans-serif',
		),
	),
);
$fields['typekit_code']           = array(
	'std' => '',
);
$fields['typekit_fonts']          = array(
	'default' => array(
		array(
			'name' => '',
			'id'   => '',
		),
	),
);
$fields['google_fonts_protocol']  = array(
	'std' => 'http',
);
$fields['typo_text_heading']      = array(
	'std' => __( 'This is a test heading text', 'better-studio' ),
);
$fields['typo_text_font_manager'] = array(
	'std' => __( 'The face of the moon was in shadow', 'better-studio' ),
);
$fields['typo_text_paragraph']    = array(
	'std' => __( 'Grumpy wizards make toxic brew for the evil Queen and Jack. One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.', 'better-studio' ),
);
$fields['typo_text_divided']      = array(
	'std' => __( 'a b c d e f g h i j k l m n o p q r s t u v w x y z
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
0123456789 (!@#$%&.,?:;)', 'better-studio' ),
);

libs/better-framework/core/fonts-manager/class-bf-fonts-manager.php000064400000054420151214002420021404 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Better Framework Font Manager
 *
 *
 * @package  BetterFramework
 * @author   BetterStudio <info@betterstudio.com>
 * @access   public
 * @see      http://www.betterstudio.com
 */
class BF_Fonts_Manager {


	/**
	 * Panel ID
	 *
	 * @var string
	 */
	public $option_panel_id = 'better-framework-custom-fonts';


	/**
	 * Inner array of object instances and caches
	 *
	 * @var array
	 */
	protected static $instances = array();


	/**
	 *
	 */
	function __construct() {

		add_filter( 'better-framework/panel/add', array(
			$this,
			'panel_add'
		), 100 );

		add_filter( 'better-framework/panel/' . $this->option_panel_id . '/config', array(
			$this,
			'panel_config'
		), 100 );

		add_filter( 'better-framework/panel/' . $this->option_panel_id . '/fields', array(
			$this,
			'panel_fields'
		), 100 );

		add_filter( 'better-framework/panel/' . $this->option_panel_id . '/std', array(
			$this,
			'panel_std'
		), 100 );

		// Callback for resetting data
		add_filter( 'better-framework/panel/reset/result', array( $this, 'callback_panel_reset_result' ), 10, 2 );

		// Callback for importing data
		add_filter( 'better-framework/panel/import/result', array( $this, 'callback_panel_import_result' ), 10, 3 );

		// Callback changing save result
		add_filter( 'better-framework/panel/save/result', array( $this, 'callback_panel_save_result' ), 10, 2 );

		// Adds fonts file types to WP uploader
		if ( is_admin() ) {
			add_filter( 'upload_mimes', array( $this, 'filter_upload_mimes_types' ), 1000 );
		}

		// Hook BF admin assets enqueue
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );

		// Output custom css for custom fonts
		add_action( 'template_redirect', array( $this, 'admin_custom_css' ), 1 );

		// Prints TypeKit font head js code
		add_action( 'wp_head', 'BF_Fonts_Manager::print_typekit_head_code' );
	}


	public static function ajax_add_custom_font( $data ) {

		$POST = array();
		wp_parse_str( urldecode( $data ), $POST );

		if ( ! isset( $POST['fonts'] ) || ! isset( $POST['font-name'] ) ) {
			return false;
		}

		$valid_keys = array(
			'woff'  => '',
			'woff2' => '',
			'ttf'   => '',
			'svg'   => '',
			'eot'   => '',
			'otf'   => '',
		);
		$font       = array_intersect_key( $POST['fonts'], $valid_keys ); // Filter sent data
		$font['id'] = sanitize_text_field( $POST['font-name'] ); // Font name

		$instance = BF_Fonts_Manager::factory();

		// Update options
		$options = get_option( $instance->option_panel_id );
		if ( ! isset( $options['custom_fonts'] ) ) {
			$options['custom_fonts'] = array();
		}
		array_push( $options['custom_fonts'], $font );
		$success = update_option( $instance->option_panel_id, $options );


		// clear cache
		BF_Options::$values[ $instance->option_panel_id ] = null;

		$new_font_id = $font['id'];

		return compact( 'success', 'new_font_id' );
	}


	/**
	 * Build the required object instance
	 *
	 * @param   string $object
	 * @param   bool   $fresh
	 * @param   bool   $just_include
	 *
	 * @return  null|BF_Fonts_Manager|BF_FM_Custom_Fonts_Helper|BF_FM_Font_Stacks_Helper|BF_FM_Google_Fonts_Helper
	 */
	public static function factory( $object = 'self', $fresh = false, $just_include = false ) {

		if ( isset( self::$instances[ $object ] ) && ! $fresh ) {
			return self::$instances[ $object ];
		}

		switch ( $object ) {

			/**
			 * Main BF_Fonts_Manager Class
			 */
			case 'self':
				$class = 'BF_Fonts_Manager';
				break;

			/**
			 * Theme Fonts: BF_FM_Theme_Fonts_Helper Class
			 */
			case 'theme-fonts':

				bf_require_once( 'core/fonts-manager/class-bf-fm-theme-fonts-helper.php' );

				$class = 'BF_FM_Theme_Fonts_Helper';

				break;

			/**
			 * Google Fonts: BF_FM_Google_Fonts_Helper Class
			 */
			case 'google-fonts':

				bf_require_once( 'core/fonts-manager/class-bf-fm-google-fonts-helper.php' );

				$class = 'BF_FM_Google_Fonts_Helper';

				break;

			/**
			 * Google Early Access Fonts: BF_FM_Google_EA_Fonts_Helper Class
			 */
			case 'google-ea-fonts':

				bf_require_once( 'core/fonts-manager/class-bf-fm-google-ea-fonts-helper.php' );

				$class = 'BF_FM_Google_EA_Fonts_Helper';

				break;

			/**
			 * Custom Fonts: BF_FM_Custom_Fonts_Helper Class
			 */
			case 'custom-fonts':

				bf_require_once( 'core/fonts-manager/class-bf-fm-custom-fonts-helper.php' );

				$class = 'BF_FM_Custom_Fonts_Helper';

				break;

			/**
			 * Font Stacks: BF_FM_Font_Stacks_Helper Class
			 */
			case 'font-stacks':

				bf_require_once( 'core/fonts-manager/class-bf-fm-font-stacks-helper.php' );

				$class = 'BF_FM_Font_Stacks_Helper';

				break;

			/**
			 * TypeKit Fonts: BF_FM_Typekit_Fonts_Helper Class
			 */
			case 'typekit-fonts':

				bf_require_once( 'core/fonts-manager/class-bf-fm-typekit-fonts-helper.php' );

				$class = 'BF_FM_Typekit_Fonts_Helper';

				break;

			default:
				return null;
		}


		// Just prepare/includes files
		if ( $just_include ) {
			return;
		}

		// don't cache fresh objects
		if ( $fresh ) {
			return new $class;
		}

		self::$instances[ $object ] = new $class;

		return self::$instances[ $object ];
	}


	/**
	 * @return BF_FM_Google_Fonts_Helper
	 */
	public static function google_fonts() {

		return self::factory( 'google-fonts' );
	}


	/**
	 * @return BF_FM_Google_EA_Fonts_Helper
	 */
	public static function google_ea_fonts() {

		return self::factory( 'google-ea-fonts' );
	}


	/**
	 * @return BF_FM_Custom_Fonts_Helper
	 */
	public static function custom_fonts() {

		return self::factory( 'custom-fonts' );
	}


	/**
	 * @return BF_FM_Font_Stacks_Helper
	 */
	public static function font_stacks() {

		return self::factory( 'font-stacks' );
	}


	/**
	 * @return BF_FM_Typekit_Fonts_Helper
	 */
	public static function typekit_fonts() {

		return self::factory( 'typekit-fonts' );
	}


	/**
	 * @return BF_FM_Theme_Fonts_Helper
	 */
	public static function theme_fonts() {

		return self::factory( 'theme-fonts' );
	}


	/**
	 * Used for getting protocol for links of google fonts
	 *
	 * @param string $protocol custom protocol for using outside
	 *
	 * @return string
	 */
	public function get_protocol( $protocol = '' ) {

		if ( empty( $protocol ) ) {
			$protocol = $this->get_option( 'google_fonts_protocol' );
		}

		switch ( $protocol ) {

			case 'http':
				$protocol = 'http://';
				break;

			case 'https':
				$protocol = 'https://';
				break;

			case 'relative':
				$protocol = '//';
				break;

			default:
				$protocol = 'https://';

		}

		return $protocol;

	}


	/**
	 * Used for retrieving options simply and safely for next versions
	 *
	 * @param $option_key
	 *
	 * @return mixed|null
	 */
	public function get_option( $option_key ) {

		return bf_get_option( $option_key, $this->option_panel_id );
	}


	/**
	 * Callback: Output Custom CSS for Custom Fonts
	 *
	 * Filter: template_redirect
	 */
	public function admin_custom_css() {

		// just when custom css requested
		if ( empty( $_GET['better_fonts_manager_custom_css'] ) OR intval( $_GET['better_fonts_manager_custom_css'] ) != 1 ) {
			return;
		}

		// Custom font requested
		if ( ! empty( $_GET['custom_font_id'] ) ) {

			$font_id      = $_GET['custom_font_id'];
			$custom_fonts = self::custom_fonts()->get_all_fonts();

		}// Google EA Font
		elseif ( ! empty( $_GET['google_ea_font_id'] ) ) {

			$font_id      = $_GET['google_ea_font_id'];
			$custom_fonts = self::google_ea_fonts()->get_font( $font_id );

			// Send output with import
			status_header( 200 );
			header( "Content-type: text/css; charset: utf-8" );
			die( '@import url(' . $custom_fonts['url'] . ');' );

		} // Theme font requested
		elseif ( ! empty( $_GET['theme_font_id'] ) ) {
			$font_id      = $_GET['theme_font_id'];
			$custom_fonts = self::theme_fonts()->get_all_fonts();
		} else {
			die;
		}

		// If custom font is not valid
		if ( ! isset( $custom_fonts[ $font_id ] ) ) {
			return;
		}

		status_header( 200 );
		header( "Content-type: text/css; charset: utf-8" );

		$font = $custom_fonts[ $font_id ];
		$src  = array(
			'main'  => array(),
			'extra' => array(),
		);

		$output = " @font-face { font-family: '" . $font_id . "';";

		// .EOT
		if ( ! empty( $font['eot'] ) ) {
			$src['extra'][] = "url('" . $font['eot'] . "')";
			$src['extra'][] = "url('" . $font['eot'] . "?#iefix') format('embedded-opentype')";
		}

		// .WOFF2
		if ( ! empty( $font['woff2'] ) ) {
			$src['main'][] = "url('" . $font['woff2'] . "') format('woff2')";
		}

		// .WOFF
		if ( ! empty( $font['woff'] ) ) {
			$src['main'][] = "url('" . $font['woff'] . "') format('woff')";
		}

		// .TTF
		if ( ! empty( $font['ttf'] ) ) {
			$src['main'][] = "url('" . $font['ttf'] . "') format('truetype')";
		}

		// .SVG
		if ( ! empty( $font['svg'] ) ) {
			$src['main'][] = "url('" . $font['svg'] . "#" . $font_id . "') format('svg')";
		}

		// .OTF
		if ( ! empty( $font['otf'] ) ) {
			$src['main'][] = "url('" . $font['otf'] . "#" . $font_id . "') format('opentype')";
		}

		//
		// Generate SRC attrs
		//
		{
			if ( ! empty( $src['extra'] ) ) {
				foreach ( $src['extra'] as $_src ) {
					$output .= "src: $_src;";
				}
			}

			if ( ! empty( $src['main'] ) ) {
				$output .= 'src: ' . implode( ",\n", $src['main'] ) . ';';
			}
		}

		$output .= "
    font-weight: normal;
    font-style: normal;
}";

		echo $output; // escaped before
		exit;
	}


	/**
	 * Used for getting font when we do not know what type is the font!
	 *
	 * Priority:
	 *  1. Theme Fonts
	 *  2. Custom Fonts
	 *  3. Font Stacks
	 *  4. Google fonts
	 *
	 * @param   string $font_name Font ID
	 *
	 * @return bool
	 */
	public static function get_font( $font_name ) {

		// Get from theme fonts
		$font = self::theme_fonts()->get_font( $font_name );

		if ( $font !== false ) {
			return $font;
		}

		// Get from custom fonts
		$font = self::custom_fonts()->get_font( $font_name );

		if ( $font !== false ) {
			return $font;
		}

		// Get from font stacks
		$font = self::font_stacks()->get_font( $font_name );

		if ( $font !== false ) {
			return $font;
		}

		// Get from TypeKit Fonts
		$font = self::typekit_fonts()->get_font( $font_name );

		if ( $font !== false ) {
			return $font;
		}

		// Get from font Google EA fonts
		$font = self::google_ea_fonts()->get_font( $font_name );

		if ( $font !== false ) {
			return $font;
		}

		// Get from google fonts
		$font = self::google_fonts()->get_font( $font_name );

		if ( $font !== false ) {
			return $font;
		}

		return false;
	}


	/**
	 * Get font variants HTML option tags
	 *
	 * @param   string|array $font            Font ID
	 * @param   string       $current_variant Active or Selected Variant ID
	 */
	public static function get_font_variants_option_elements( $font, $current_variant = '' ) {

		switch ( $font['type'] ) {

			// Theme fonts variants
			case 'theme-font':

				echo self::theme_fonts()->get_font_variants_option_elements( $current_variant ); // escaped before

				return;
				break;

			// Custom fonts variants
			case 'custom-font':

				echo self::custom_fonts()->get_font_variants_option_elements( $current_variant ); // escaped before

				return;
				break;

			// Font stacks variants
			case 'font-stack':

				echo self::font_stacks()->get_font_variants_option_elements( $current_variant ); // escaped before

				return;
				break;

			// TypeKit Font variants
			case 'typekit-font':

				echo self::typekit_fonts()->get_font_variants_option_elements( $current_variant ); // escaped before

				return;
				break;

			// Google fonts variants
			case 'google-font':

				echo self::google_fonts()->get_font_variants_option_elements( $font, $current_variant ); // escaped before

				return;
				break;

			// Google EA fonts variants
			case 'google-ea-font':

				echo self::google_ea_fonts()->get_font_variants_option_elements( $font, $current_variant ); // escaped before

				return;
				break;

		}

	}


	/**
	 * Get font subsets HTML option tags
	 *
	 * @param   string|array $font           Font ID
	 * @param   string       $current_subset Active or Selected Subset ID
	 */
	public static function get_font_subset_option_elements( $font, $current_subset = '' ) {

		switch ( $font['type'] ) {

			case 'theme-font':

				echo self::custom_fonts()->get_font_subset_option_elements(); // escaped before

				return;
				break;

			case 'custom-font':

				echo self::custom_fonts()->get_font_subset_option_elements(); // escaped before

				return;
				break;

			case 'font-stack':

				echo self::font_stacks()->get_font_subset_option_elements(); // escaped before

				return;
				break;

			case 'typekit-fonts':

				echo self::typekit_fonts()->get_font_subset_option_elements(); // escaped before

				return;
				break;

			case 'google-font':

				echo self::google_fonts()->get_font_subset_option_elements( $font, $current_subset ); // escaped before

				return;
				break;

			case 'google-ea-font':

				echo self::google_ea_fonts()->get_font_subset_option_elements( $font, $current_subset ); // escaped before

				return;
				break;

		}

	}


	/**
	 * List all available fonts by font category
	 *
	 * @return array
	 */
	public function get_all_fonts() {

		return array(
			'google_fonts'    => Better_Framework()->fonts_manager()->google_fonts()->get_all_fonts(),
			'google_ea_fonts' => Better_Framework()->fonts_manager()->google_ea_fonts()->get_all_fonts(),
			'theme_fonts'     => Better_Framework()->fonts_manager()->theme_fonts()->get_all_fonts(),
			'custom_fonts'    => Better_Framework()->fonts_manager()->custom_fonts()->get_all_fonts(),
			'font_stacks'     => Better_Framework()->fonts_manager()->font_stacks()->get_all_fonts(),
			'typekit_fonts'   => Better_Framework()->fonts_manager()->typekit_fonts()->get_all_fonts(),
		);
	}


	/**
	 * Callback: Used for enqueue font manager assets
	 *
	 * Filter: admin_enqueue_scripts
	 */
	function admin_enqueue_scripts() {

		if ( Better_Framework()->sections['admin_panel'] != true || Better_Framework()->get_current_page_type() != 'panel' ) {
			return;
		}

		bf_enqueue_script( 'better-fonts-manager' );

		bf_localize_script(
			'better-fonts-manager',
			'better_fonts_manager_loc',
			apply_filters(
				'better-framework/fonts-manager/localized-items',
				array(
					'type'  => 'panel',

					// Fonts lib
					'fonts' => $this->get_all_fonts(),

					'admin_fonts_css_url' => get_site_url() . '/?better_fonts_manager_custom_css=1&ver=' . time(),

					'texts'    => array(
						'variant_100'       => __( 'Ultra-Light 100', 'better-studio' ),
						'variant_300'       => __( 'Book 300', 'better-studio' ),
						'variant_400'       => __( 'Normal 400', 'better-studio' ),
						'variant_500'       => __( 'Medium 500', 'better-studio' ),
						'variant_700'       => __( 'Bold 700', 'better-studio' ),
						'variant_900'       => __( 'Ultra-Bold 900', 'better-studio' ),
						'variant_100italic' => __( 'Ultra-Light 100 Italic', 'better-studio' ),
						'variant_300italic' => __( 'Book 300 Italic', 'better-studio' ),
						'variant_400italic' => __( 'Normal 400 Italic', 'better-studio' ),
						'variant_500italic' => __( 'Medium 500 Italic', 'better-studio' ),
						'variant_700italic' => __( 'Bold 700 Italic', 'better-studio' ),
						'variant_900italic' => __( 'Ultra-Bold 900 Italic', 'better-studio' ),

						'subset_unknown' => __( 'Unknown', 'better-studio' ),
					),
					'labels'   => array(
						'types' => array(
							'theme_fonts'     => __( 'Theme Fonts', 'better-studio' ),
							'google_fonts'    => __( 'Google Fonts', 'better-studio' ),
							'google_ea_fonts' => __( 'Google Early Access Font', 'better-studio' ),
							'custom_fonts'    => __( 'Custom Fonts', 'better-studio' ),
							'typekit_font'    => __( 'TypeKit Fonts', 'better-studio' ),
							'font_stacks'     => __( 'Font Stack', 'better-studio' ),
						),

						'style'  => __( '%s style(s)', 'better-studio' ),
						'search' => __( 'Search Font...', 'better-studio' ),

						'preview_text' => bf_get_option( 'typo_text_font_manager', 'better-framework-custom-fonts' ),
						'choose_font'  => __( 'Choose a font', 'better-studio' ),
						'upload_font'  => __( 'Upload Custom Font', 'better-studio' ),
						'add_font'     => __( 'Add Custom Font', 'better-studio' ),

						'filter_cat_title' => __( 'Category', 'better-studio' ),
						'filter_cats'      => array(
							'serif'       => __( 'Serif', 'better-studio' ),
							'sans-serif'  => __( 'Sans Serif', 'better-studio' ),
							'display'     => __( 'Display', 'better-studio' ),
							'handwriting' => __( 'Handwriting', 'better-studio' ),
							'monospace'   => __( 'Monospace', 'better-studio' ),
						),


						'all_l10n'          => __( 'All Fonts', 'better-studio' ),
						'filter_type_title' => __( 'Type', 'better-studio' ),
						'filter_types'      => array(
							'google_font'    => __( 'Google Fonts', 'better-studio' ),
							'custom_font'    => __( 'Custom Fonts', 'better-studio' ),
							'font_stacks'    => __( 'Font Stacks', 'better-studio' ),
							'google_ea_font' => __( 'Google Early Access Fonts', 'better-studio' ),
							'theme_font'     => __( 'Theme Fonts', 'better-studio' ),
							'typekit_font'   => __( 'TypeKit Fonts', 'better-studio' ),
						),

						'font_name'    => __( 'Font Name', 'better-studio' ),
						'font_woff'    => __( 'Font .woff', 'better-studio' ),
						'upload_woff'  => __( 'Upload .woff', 'better-studio' ),
						'font_woff2'   => __( 'Font .woff2', 'better-studio' ),
						'upload_woff2' => __( 'Upload .woff2', 'better-studio' ),
						'font_ttf'     => __( 'Font .ttf', 'better-studio' ),
						'upload_ttf'   => __( 'Upload .ttf', 'better-studio' ),
						'font_svg'     => __( 'Font .svg', 'better-studio' ),
						'upload_svg'   => __( 'Upload .svg', 'better-studio' ),
						'font_eot'     => __( 'Font .eot', 'better-studio' ),
						'upload_eot'   => __( 'Upload .eot', 'better-studio' ),
						'font_otf'     => __( 'Font .otf', 'better-studio' ),
						'upload_otf'   => __( 'Upload .otf', 'better-studio' ),
					),
					'add_font' => array(
						'callback'      => 'BF_Fonts_Manager::ajax_add_custom_font',
						'bf_call_token' => Better_Framework::callback_token( 'BF_Fonts_Manager::ajax_add_custom_font' ),
					)
				)
			)
		);

	}


	/**
	 * Callback: Used for adding fonts mimes to WordPress uploader
	 *
	 * Filter: upload_mimes
	 *
	 * @param $mimes
	 *
	 * @return mixed
	 */
	function filter_upload_mimes_types( $mimes ) {

		$mimes['ttf']   = 'application/x-font-ttf';
		$mimes['woff']  = 'application/x-font-woff';
		$mimes['woff2'] = 'application/x-font-woff2';
		$mimes['svg']   = 'image/svg+xml';
		$mimes['eot']   = 'application/vnd.ms-fontobject';
		$mimes['otf']   = 'application/x-font-otf';

		return $mimes;
	}


	/**
	 * Callback: Setup panel
	 *
	 * Filter: better-framework/panel/options
	 *
	 * @param array $panels
	 *
	 * @return array
	 */
	function panel_add( $panels ) {

		$panels[ $this->option_panel_id ] = array(
			'id'    => $this->option_panel_id,
			'style' => false,

		);

		return $panels;
	}


	/**
	 * Callback: Init's BF options
	 *
	 * Filter: better-framework/panel/options
	 *
	 * @param $panels
	 *
	 * @return mixed
	 */
	public function panel_config( $panels ) {

		include BF_PATH . 'core/fonts-manager/panel-config.php';

		return $panels;
	}


	/**
	 * Callback: Init's BF options
	 *
	 * Filter: better-framework/panel/options
	 *
	 * @param $fields
	 *
	 * @return mixed
	 */
	public function panel_fields( $fields ) {

		include BF_PATH . 'core/fonts-manager/panel-fields.php';

		return $fields;
	}


	/**
	 * Callback: Init's BF options
	 *
	 * Filter: better-framework/panel/options
	 *
	 * @param $fields
	 *
	 * @return mixed
	 */
	public function panel_std( $fields ) {

		include BF_PATH . 'core/fonts-manager/panel-std.php';

		return $fields;
	}


	/**
	 * Filter callback: Used for resetting current language on resetting panel
	 *
	 * @param   $options
	 * @param   $result
	 *
	 * @return array
	 */
	function callback_panel_reset_result( $result, $options ) {

		// check panel
		if ( $options['id'] != $this->option_panel_id ) {
			return $result;
		}

		// change messages
		if ( $result['status'] == 'succeed' ) {
			$result['msg'] = __( 'Font manager reset to default.', 'better-studio' );
		} else {
			$result['msg'] = __( 'An error occurred while resetting font manager.', 'better-studio' );
		}

		return $result;
	}


	/**
	 * Filter callback: Used for changing current language on importing translation panel data
	 *
	 * @param $result
	 * @param $data
	 * @param $args
	 *
	 * @return array
	 */
	function callback_panel_import_result( $result, $data, $args ) {

		// check panel
		if ( $args['panel-id'] != $this->option_panel_id ) {
			return $result;
		}

		// change messages
		if ( $result['status'] == 'succeed' ) {
			$result['msg'] = __( 'Font manager options imported successfully.', 'better-studio' );
		} else {
			if ( $result['msg'] == __( 'Imported data is not for this panel.', 'better-studio' ) ) {
				$result['msg'] = __( 'Imported translation is not for fonts manager.', 'better-studio' );
			} else {
				$result['msg'] = __( 'An error occurred while importing font manager options.', 'better-studio' );
			}
		}

		return $result;
	}


	/**
	 * Filter callback: Used for changing save translation panel result
	 *
	 * @param $output
	 * @param $args
	 *
	 * @return string
	 */
	function callback_panel_save_result( $output, $args ) {

		// change only for translation panel
		if ( $args['id'] == $this->option_panel_id ) {
			if ( $output['status'] == 'succeed' ) {
				$output['msg'] = __( 'Fonts saved.', 'better-studio' );
			} else {
				$output['msg'] = __( 'An error occurred while saving fonts.', 'better-studio' );
			}
		}

		return $output;
	}


	/**
	 * Prints TypeKit head js code
	 *
	 * @hooked wp_head
	 *
	 * @since  2.10.0
	 */
	public static function print_typekit_head_code() {

		if ( $code = bf_get_option( 'typekit_code', Better_Framework::fonts_manager()->option_panel_id ) ) {
			echo $code;
		}

	}

}
libs/better-framework/core/fonts-manager/class-bf-fm-custom-fonts-helper.php000064400000010342151214002430023155 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Used For retrieving custom fonts.
 */
class BF_FM_Custom_Fonts_Helper {


	/**
	 * Contain array of all fonts
	 *
	 * @var array
	 */
	private static $fonts_list = null;


	/**
	 * Used for Retrieving list of all fonts
	 */
	public static function get_all_fonts() {

		if ( self::$fonts_list != null ) {
			return self::$fonts_list;
		}

		// load option
		$custom_fonts = bf_get_option( 'custom_fonts', Better_Framework::fonts_manager()->option_panel_id );

		// create array
		$_custom_fonts = array();
		foreach ( (array) $custom_fonts as $font ) {

			if ( empty( $font['svg'] ) && empty( $font['ttf'] ) && empty( $font['eot'] ) && empty( $font['woff'] ) && empty( $font['woff2'] ) && empty( $font['otf'] ) ) {
				continue;
			}

			$_custom_fonts[ $font['id'] ]         = $font;
			$_custom_fonts[ $font['id'] ]['type'] = 'custom-font';
		}

		// save to cache
		return self::$fonts_list = $_custom_fonts;
	}


	/**
	 * Used for retrieving single font info
	 *
	 * @param $font_name
	 *
	 * @return bool
	 */
	public static function get_font( $font_name ) {

		$fonts = self::get_all_fonts();

		if ( isset( $fonts[ $font_name ] ) ) {
			return $fonts[ $font_name ];
		} else {
			return false;
		}
	}


	/**
	 * Generate and return Option elements of all font for select element
	 *
	 * @param   string $active_font  Family name of selected font in options
	 * @param   bool   $option_group Add options to option group?
	 *
	 * @return  string
	 */
	public static function get_fonts_family_option_elements( $active_font = '', $option_group = true ) {

		$output = '';

		if ( $option_group ) {
			$output .= '<optgroup label="' . __( 'Custom Fonts', 'better-studio' ) . '">';
		}

		foreach ( self::get_all_fonts() as $key => $font ) {
			$output .= '<option value="' . esc_attr( $key ) . '" ' . ( $key == $active_font ? 'selected' : '' ) . '>' . esc_html( $key ) . '</option>';
		}

		if ( $option_group ) {
			$output .= '</optgroup>';
		}

		return $output;
	}


	/**
	 * Generate and return Option elements of font variants
	 *
	 * @param   string $font_variant Active or selected variant
	 *
	 * @return string
	 */
	public static function get_font_variants_option_elements( $font_variant = '400' ) {

		// default value
		if ( empty( $font_variant ) ) {
			$font_variant = '400';
		}

		$output = '';

		$variants = array(
			'100'       => __( 'Ultra-Light 100', 'better-studio' ),
			'300'       => __( 'Book 300', 'better-studio' ),
			'400'       => __( 'Normal 400', 'better-studio' ),
			'500'       => __( 'Medium 500', 'better-studio' ),
			'700'       => __( 'Bold 700', 'better-studio' ),
			'900'       => __( 'Ultra-Bold 900', 'better-studio' ),
			'100italic' => __( 'Ultra-Light 100 Italic', 'better-studio' ),
			'300italic' => __( 'Book 300 Italic', 'better-studio' ),
			'400italic' => __( 'Normal 400 Italic', 'better-studio' ),
			'500italic' => __( 'Medium 500 Italic', 'better-studio' ),
			'700italic' => __( 'Bold 700 Italic', 'better-studio' ),
			'900italic' => __( 'Ultra-Bold 900 Italic', 'better-studio' ),
		);

		foreach ( $variants as $variant_id => $variant_name ) {
			$output .= '<option value="' . esc_attr( $variant_id ) . '" ' . ( $variant_id == $font_variant ? 'selected' : '' ) . '>' . esc_html( $variant_name ) . '</option>';
		}

		return $output;
	}


	/**
	 * Generate and return Option elements of font subsets
	 *
	 * @return string
	 */
	public static function get_font_subset_option_elements() {

		return '<option value="unknown" selected>' . esc_html__( 'Unknown', 'better-studio' ) . '</option>';
	}

}libs/better-framework/core/fonts-manager/panel-fields.php000064400000025006151214002430017515 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


//
// Custom Fonts
//
$fields[]               = array(
	'name' => __( 'Custom Fonts', 'better-studio' ),
	'id'   => 'custom_fonts_tab',
	'type' => 'tab',
	'icon' => 'bsai-add',
);
$custom_fonts           = array();
$custom_fonts['id']     = array(
	'name'            => __( 'Font Name', 'better-studio' ),
	'id'              => 'id',
	'std'             => '',
	'type'            => 'text',
	'container_class' => 'better-custom-fonts-id',
	'section_class'   => 'full-with-both',
	'repeater_item'   => true
);
$custom_fonts['woff']   = array(
	'name'            => __( 'Font .woff', 'better-studio' ),
	'button_text'     => __( 'Upload .woff', 'better-studio' ),
	'id'              => 'woff',
	'std'             => '',
	'type'            => 'media',
	'container_class' => 'better-custom-fonts-woff',
	'section_class'   => 'full-with-both',
	'repeater_item'   => true
);
$custom_fonts['woff2']  = array(
	'name'            => __( 'Font .woff2', 'better-studio' ),
	'button_text'     => __( 'Upload .woff2', 'better-studio' ),
	'id'              => 'woff2',
	'std'             => '',
	'type'            => 'media',
	'container_class' => 'better-custom-fonts-woff2',
	'section_class'   => 'full-with-both',
	'repeater_item'   => true
);
$custom_fonts['ttf']    = array(
	'name'            => __( 'Font .ttf', 'better-studio' ),
	'button_text'     => __( 'Upload .ttf', 'better-studio' ),
	'id'              => 'ttf',
	'std'             => '',
	'type'            => 'media',
	'container_class' => 'better-custom-fonts-ttf',
	'section_class'   => 'full-with-both',
	'repeater_item'   => true
);
$custom_fonts['svg']    = array(
	'name'            => __( 'Font .svg', 'better-studio' ),
	'button_text'     => __( 'Upload .svg', 'better-studio' ),
	'id'              => 'svg',
	'std'             => '',
	'type'            => 'media',
	'container_class' => 'better-custom-fonts-svg',
	'section_class'   => 'full-with-both',
	'repeater_item'   => true
);
$custom_fonts['eot']    = array(
	'name'            => __( 'Font .eot', 'better-studio' ),
	'button_text'     => __( 'Upload .eot', 'better-studio' ),
	'id'              => 'eot',
	'std'             => '',
	'type'            => 'media',
	'container_class' => 'better-custom-fonts-eot',
	'section_class'   => 'full-with-both',
	'repeater_item'   => true
);
$custom_fonts['otf']    = array(
	'name'            => __( 'Font .otf', 'better-studio' ),
	'button_text'     => __( 'Upload .otf', 'better-studio' ),
	'id'              => 'otf',
	'std'             => '',
	'type'            => 'media',
	'container_class' => 'better-custom-fonts-otf',
	'section_class'   => 'full-with-both',
	'repeater_item'   => true
);
$fields['custom_fonts'] = array(
	'name'          => __( 'Upload Custom Fonts', 'better-studio' ),
	'id'            => 'custom_fonts',
	'type'          => 'repeater',
	'save-std'      => true,
	'delete_label'  => __( 'Delete Font', 'better-studio' ),
	'item_title'    => __( 'Custom Font', 'better-studio' ),
	'section_class' => 'full-with-both',
	'options'       => $custom_fonts
);


//
// TypeKit Fonts
//
$fields[]                = array(
	'name' => __( 'TypeKit Fonts', 'better-studio' ),
	'id'   => 'typekit_tab',
	'type' => 'tab',
	'icon' => 'bsai-typekit',
);
$fields[]                = array(
	'name'          => __( 'What is TypeKit?', 'better-studio' ),
	'id'            => '_typekit-help',
	'type'          => 'info',
	'std'           => __( 'TypeKit offer a service that allows you to select from a range of hundreds of high quality fonts for your WordPress website. The fonts are applied using the font-face standard, so they are standards compliant, fully licensed and accessible.', 'better-studio' ),
	'state'         => 'open',
	'info-type'     => 'warning',
	'section_class' => 'widefat',
);
$fields[]                = array(
	'name'          => __( 'How to setup TypeKit?', 'better-studio' ),
	'id'            => '_typekit-setup',
	'type'          => 'info',
	'std'           => __( '<ol>
                <li>Go To <a href="https://goo.gl/mKugDo" target="_blank">typekit.com</a> and register for an account</li>
                <li>Choose a few fonts to add to your account and Publish them.</li>
                <li>Go to the <strong>Kit Editor</strong> and get your <strong>Embed Code</strong> (link at the top right of the screen)</li>
                <li>Copy the whole 2 lines of your embed code into the following <strong>TypeKit Embed Code</strong> field.</li>
                <li>You have to add fonts of your TypeKit kit into following the <strong>Kit Fonts List</strong> field.</li>
                <li>Done, You can select TypeKit fonts from panels in typography field.</li>
            </ol>', 'better-studio' ),
	'state'         => 'open',
	'info-type'     => 'help',
	'section_class' => 'widefat',
);
$fields['typekit_code']  = array(
	'name' => __( 'TypeKit Embed Code', 'better-studio' ),
	'desc' => __( 'Enter the whole 2 lines of your kit embed code into this field. Create new item for each font.', 'better-studio' ),
	'id'   => 'typekit_code',
	'type' => 'textarea',
);
$tk_font['name']         = array(
	'name'            => __( 'Font Name', 'better-studio' ),
	'desc'            => __( 'Name that will be shown in panel fields', 'better-studio' ),
	'id'              => 'id',
	'std'             => '',
	'type'            => 'text',
	'container_class' => 'better-font-stack-name',
	'section_class'   => 'full-with-both',
	'repeater_item'   => true
);
$tk_font['id']           = array(
	'name'            => __( 'Font Family ID', 'better-studio' ),
	'desc'            => __( 'Font family ID of selected font in TypeKit. Ex: fair-sans', 'better-studio' ),
	'id'              => 'id',
	'std'             => '',
	'type'            => 'text',
	'container_class' => 'better-font-stack-stack',
	'section_class'   => 'full-with-both',
	'repeater_item'   => true
);
$fields['typekit_fonts'] = array(
	'name'          => __( 'Kit Fonts List', 'better-studio' ),
	'desc'          => __( 'Enter fonts of your kit into following fields to can select it from fonts selector popup in panels.', 'better-studio' ),
	'id'            => 'typekit_fonts',
	'type'          => 'repeater',
	'save-std'      => true,
	'add_label'     => '<i class="fa fa-plus"></i> ' . __( 'Add New TypeKit Font', 'better-studio' ),
	'delete_label'  => __( 'Delete Font', 'better-studio' ),
	'item_title'    => __( 'TypeKit Fonts', 'better-studio' ),
	'section_class' => 'full-with-both',
	'options'       => $tk_font
);


//
// Fonts Stacks
//
$fields[]              = array(
	'name' => __( 'Font Stacks', 'better-studio' ),
	'id'   => 'font_stacks_tab',
	'type' => 'tab',
	'icon' => 'bsai-font',
);
$font_stacks['id']     = array(
	'name'            => __( 'Font Name', 'better-studio' ),
	'id'              => 'id',
	'std'             => '',
	'type'            => 'text',
	'container_class' => 'better-font-stack-name',
	'section_class'   => 'full-with-both',
	'repeater_item'   => true
);
$font_stacks['stack']  = array(
	'name'            => __( 'Font Stack', 'better-studio' ),
	'id'              => 'stack',
	'std'             => '',
	'type'            => 'text',
	'container_class' => 'better-font-stack-stack',
	'section_class'   => 'full-with-both',
	'repeater_item'   => true
);
$fields['font_stacks'] = array(
	'name'          => __( 'Web Safe CSS Font Stacks', 'better-studio' ),
	'id'            => 'font_stacks',
	'type'          => 'repeater',
	'save-std'      => true,
	'add_label'     => '<i class="fa fa-plus"></i> ' . __( 'Add New Font Stack', 'better-studio' ),
	'delete_label'  => __( 'Delete Font Stack', 'better-studio' ),
	'item_title'    => __( 'CSS Font Stack', 'better-studio' ),
	'section_class' => 'full-with-both',
	'options'       => $font_stacks
);


//
// Advanced Options
//
$fields[] = array(
	'name' => __( 'Advanced', 'better-studio' ),
	'id'   => 'typo_opt_tab',
	'type' => 'tab',
	'icon' => 'bsai-gear',
);
$fields[] = array(
	'name'          => __( 'Google Fonts Protocol', 'better-studio' ),
	'id'            => 'google_fonts_protocol',
	'desc'          => __( 'Select protocol of fonts link for Google Fonts.', 'better-studio' ),
	'std'           => 'http',
	'type'          => 'select',
	'section_class' => 'style-floated-left',
	'options'       => array(
		'http'     => __( 'HTTP', 'better-studio' ),
		'https'    => __( 'HTTPs', 'better-studio' ),
		'relative' => __( 'Relative to Site', 'better-studio' ),
	),
);
$fields[] = array(
	'name'  => __( 'Typography Field Preview Texts', 'better-studio' ),
	'type'  => 'group',
	'state' => 'not',
);
$fields[] = array(
	'name' => __( 'Font modal preview text', 'better-studio' ),
	'id'   => 'typo_text_font_manager',
	'type' => 'text',
);
$fields[] = array(
	'name' => __( 'Heading Text', 'better-studio' ),
	'id'   => 'typo_text_heading',
	'type' => 'text',
);
$fields[] = array(
	'name' => __( 'Paragraph Text', 'better-studio' ),
	'id'   => 'typo_text_paragraph',
	'type' => 'textarea',
);
$fields[] = array(
	'name' => __( 'Divided Text', 'better-studio' ),
	'id'   => 'typo_text_divided',
	'type' => 'textarea',
);


//
// Backup & restore
//
$fields[] = array(
	'name'       => __( 'Backup & Restore', 'better-studio' ),
	'id'         => 'backup_restore',
	'type'       => 'tab',
	'icon'       => 'bsai-export-import',
	'margin-top' => '30',
);
$fields[] = array(
	'name'      => __( 'Backup / Export', 'better-studio' ),
	'id'        => 'backup_export_options',
	'type'      => 'export',
	'file_name' => 'custom-fonts-backup',
	'panel_id'  => $this->option_panel_id,
	'desc'      => __( 'This allows you to create a backup of your translation. Please note, it will not backup anything else.', 'better-studio' )
);
$fields[] = array(
	'name'     => __( 'Restore / Import', 'better-studio' ),
	'id'       => 'import_restore_options',
	'type'     => 'import',
	'panel_id' => $this->option_panel_id,
	'desc'     => __( '<strong>It will override your current translation!</strong> Please make sure to select a valid translation file.', 'better-studio' ),
);

libs/better-framework/core/fonts-manager/class-bf-fm-typekit-fonts-helper.php000064400000010526151214002430023340 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Used For retrieving TypeKit Fonts.
 */
class BF_FM_Typekit_Fonts_Helper {


	/**
	 * Contain array of all TypeKit Fonts
	 *
	 * @var array
	 */
	private static $fonts_list = null;


	/**
	 * Used for Retrieving list of all TypeKit Fonts
	 */
	public static function get_all_fonts() {

		if ( self::$fonts_list != null ) {
			return self::$fonts_list;
		}

		$typekit_code = bf_get_option( 'typekit_code', Better_Framework::fonts_manager()->option_panel_id );

		self::$fonts_list = array();

		if ( ! empty( $typekit_code ) ) {

			// load option
			$typekit_fonts = bf_get_option( 'typekit_fonts', Better_Framework::fonts_manager()->option_panel_id );

			foreach ( (array) $typekit_fonts as $font ) {

				if ( empty( $font['id'] ) ) {
					continue;
				}

				// set ID to name
				if ( empty( $font['name'] ) ) {
					$font['name'] = ucfirst( $font['id'] );
				}

				self::$fonts_list[ $font['id'] ]['id']   = $font['id'];
				self::$fonts_list[ $font['id'] ]['type'] = 'typekit-font';
			}
		}


		// save to cache
		return self::$fonts_list;
	}


	/**
	 * Used for retrieving single font info
	 *
	 * @param $font_name
	 *
	 * @return bool
	 */
	public static function get_font( $font_name ) {

		$fonts = self::get_all_fonts();

		if ( isset( $fonts[ $font_name ] ) ) {
			return $fonts[ $font_name ];
		} else {
			return false;
		}
	}


	/**
	 * Generate and return Option elements of all font for select element
	 *
	 * @param   string $active_font  Family name of selected font in options
	 * @param   bool   $option_group Active or selected font
	 *
	 * @return  string
	 */
	public static function get_fonts_family_option_elements( $active_font = '', $option_group = true ) {

		$output = '';

		if ( $option_group ) {
			$output .= '<optgroup label="' . __( 'TypeKit Fonts', 'better-studio' ) . '">';
		}

		foreach ( self::get_all_fonts() as $key => $font ) {
			$output .= '<option value="' . esc_attr( $key ) . '" ' . ( $key == $active_font ? 'selected' : '' ) . '>' . esc_html( $key ) . '</option>';
		}

		if ( $option_group ) {
			$output .= '</optgroup>';
		}

		return $output;
	}


	/**
	 * Generate and return Option elements of font variants
	 *
	 * @param   string $font_variant Active or selected variant
	 *
	 * @return string
	 */
	public static function get_font_variants_option_elements( $font_variant = '' ) {

		if ( empty( $font_variant ) ) {

			$font_variant = '400';

		}

		$output = '';

		$variants = array(
			'100'       => __( 'Ultra-Light 100', 'better-studio' ),
			'300'       => __( 'Book 300', 'better-studio' ),
			'400'       => __( 'Normal 400', 'better-studio' ),
			'500'       => __( 'Medium 500', 'better-studio' ),
			'700'       => __( 'Bold 700', 'better-studio' ),
			'900'       => __( 'Ultra-Bold 900', 'better-studio' ),
			'100italic' => __( 'Ultra-Light 100 Italic', 'better-studio' ),
			'300italic' => __( 'Book 300 Italic', 'better-studio' ),
			'400italic' => __( 'Normal 400 Italic', 'better-studio' ),
			'500italic' => __( 'Medium 500 Italic', 'better-studio' ),
			'700italic' => __( 'Bold 700 Italic', 'better-studio' ),
			'900italic' => __( 'Ultra-Bold 900 Italic', 'better-studio' ),
		);

		foreach ( $variants as $variant_id => $variant_name ) {
			$output .= '<option value="' . $variant_id /* escaped before */ . '" ' . ( $variant_id == $font_variant ? 'selected' : '' ) . '>' . esc_html( $variant_name ) . '</option>';
		}

		return $output;
	}


	/**
	 * Generate and return Option elements of font subsets
	 *
	 * @return string
	 */
	public static function get_font_subset_option_elements() {

		return '<option value="unknown">' . esc_html__( 'Unknown', 'better-studio' ) . '</option>';
	}

}
libs/better-framework/core/fonts-manager/fonts-google.php000064400000727221151214002430017565 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

/**
 * Google Fonts List.
 * Created By: BetterStudio
 * Updated: 17 Marc 2019
 * Fonts: 915
 */

return json_decode(
	'{"ABeeZee":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Abel":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Abhaya Libre":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"}],"subsets":[{"name":"sinhala","id":"sinhala"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Abril Fatface":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Aclonica":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Acme":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Actor":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Adamina":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Advent Pro":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Greek","id":"greek"}],"category":"sans-serif"},"Aguafina Script":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Akronim":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Aladin":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Aldrich":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Alef":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Hebrew","id":"hebrew"}],"category":"sans-serif"},"Alegreya":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"Alegreya SC":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"Alegreya Sans":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Alegreya Sans SC":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Aleo":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Alex Brush":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Alfa Slab One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Alice":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"Alike":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Alike Angular":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Allan":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Allerta":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Allerta Stencil":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Allura":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Almendra":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Almendra Display":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Almendra SC":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Amarante":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Amaranth":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Amatic SC":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Hebrew","id":"hebrew"}],"category":"handwriting"},"Amethysta":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Amiko":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Amiri":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Arabic","id":"arabic"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Amita":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Anaheim":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Andada":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Andika":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Angkor":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Khmer","id":"khmer"}],"category":"display"},"Annie Use Your Telescope":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Anonymous Pro":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"}],"category":"monospace"},"Antic":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Antic Didone":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Antic Slab":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Anton":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Arapey":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Arbutus":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Arbutus Slab":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Architects Daughter":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Archivo":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Archivo Black":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Archivo Narrow":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Aref Ruqaa":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Arabic","id":"arabic"},{"name":"Latin","id":"latin"}],"category":"serif"},"Arima Madurai":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Tamil","id":"tamil"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Arimo":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Hebrew","id":"hebrew"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Arizonia":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Armata":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Arsenal":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Artifika":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Arvo":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Arya":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Asap":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Asap Condensed":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Asar":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Asset":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Assistant":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Hebrew","id":"hebrew"}],"category":"sans-serif"},"Astloch":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Asul":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Athiti":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"sans-serif"},"Atma":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Bengali","id":"bengali"}],"category":"display"},"Atomic Age":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Aubrey":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Audiowide":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Autour One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Average":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Average Sans":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Averia Gruesa Libre":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Averia Libre":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Averia Sans Libre":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Averia Serif Libre":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"B612":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"B612 Mono":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"monospace"},"Bad Script":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Cyrillic","id":"cyrillic"}],"category":"handwriting"},"Bahiana":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Bai Jamjuree":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"sans-serif"},"Baloo":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Baloo Bhai":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Gujarati","id":"gujarati"}],"category":"display"},"Baloo Bhaijaan":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Arabic","id":"arabic"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Baloo Bhaina":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"oriya","id":"oriya"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Baloo Chettan":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"malayalam","id":"malayalam"}],"category":"display"},"Baloo Da":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Bengali","id":"bengali"}],"category":"display"},"Baloo Paaji":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"gurmukhi","id":"gurmukhi"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Baloo Tamma":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"kannada","id":"kannada"}],"category":"display"},"Baloo Tammudu":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Telugu","id":"telugu"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Baloo Thambi":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Tamil","id":"tamil"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Balthazar":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Bangers":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Barlow":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Barlow Condensed":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Barlow Semi Condensed":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Barrio":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Basic":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Battambang":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Khmer","id":"khmer"}],"category":"display"},"Baumans":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Bayon":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Khmer","id":"khmer"}],"category":"display"},"Belgrano":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Bellefair":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Hebrew","id":"hebrew"}],"category":"serif"},"Belleza":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"BenchNine":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Bentham":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Berkshire Swash":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Bevan":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Bigelow Rules":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Bigshot One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Bilbo":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Bilbo Swash Caps":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"BioRhyme":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"BioRhyme Expanded":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Biryani":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Bitter":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Black And White Picture":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Black Han Sans":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Black Ops One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Bokor":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Khmer","id":"khmer"}],"category":"display"},"Bonbon":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Boogaloo":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Bowlby One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Bowlby One SC":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Brawler":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Bree Serif":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Bubblegum Sans":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Bubbler One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Buda":{"type":"google-font","variants":[{"name":"Light 300","id":"300"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Buenard":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Bungee":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Bungee Hairline":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Bungee Inline":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Bungee Outline":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Bungee Shade":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Butcherman":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Butterfly Kids":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Cabin":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Cabin Condensed":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Cabin Sketch":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Caesar Dressing":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Cagliostro":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Cairo":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Arabic","id":"arabic"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Calligraffitti":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Cambay":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Cambo":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Candal":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Cantarell":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Cantata One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Cantora One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Capriola":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Cardo":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Greek","id":"greek"}],"category":"serif"},"Carme":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Carrois Gothic":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Carrois Gothic SC":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Carter One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Catamaran":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Tamil","id":"tamil"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Caudex":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Greek","id":"greek"}],"category":"serif"},"Caveat":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"}],"category":"handwriting"},"Caveat Brush":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Cedarville Cursive":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Ceviche One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Chakra Petch":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"sans-serif"},"Changa":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"}],"subsets":[{"name":"Arabic","id":"arabic"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Changa One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Chango":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Charm":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"handwriting"},"Charmonman":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"handwriting"},"Chathura":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"}],"subsets":[{"name":"Telugu","id":"telugu"},{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Chau Philomene One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Chela One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Chelsea Market":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Chenla":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Khmer","id":"khmer"}],"category":"display"},"Cherry Cream Soda":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Cherry Swash":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Chewy":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Chicle":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Chivo":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Chonburi":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"display"},"Cinzel":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Cinzel Decorative":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Clicker Script":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Coda":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Extra-Bold 800","id":"800"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Coda Caption":{"type":"google-font","variants":[{"name":"Extra-Bold 800","id":"800"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Codystar":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Coiny":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Tamil","id":"tamil"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Combo":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Comfortaa":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"display"},"Coming Soon":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Concert One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Condiment":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Content":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Khmer","id":"khmer"}],"category":"display"},"Contrail One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Convergence":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Cookie":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Copse":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Corben":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Cormorant":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"Cormorant Garamond":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"Cormorant Infant":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"Cormorant SC":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"Cormorant Unicase":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"Cormorant Upright":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Courgette":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Cousine":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Hebrew","id":"hebrew"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"monospace"},"Coustard":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Covered By Your Grace":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Crafty Girls":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Creepster":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Crete Round":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Crimson Text":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Croissant One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Crushed":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Cuprum":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Cute Font":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"display"},"Cutive":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Cutive Mono":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"monospace"},"Damion":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Dancing Script":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Dangrek":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Khmer","id":"khmer"}],"category":"display"},"David Libre":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Hebrew","id":"hebrew"}],"category":"serif"},"Dawning of a New Day":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Days One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Dekko":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Delius":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Delius Swash Caps":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Delius Unicase":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Della Respira":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Denk One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Devonshire":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Dhurjati":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Telugu","id":"telugu"},{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Didact Gothic":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Diplomata":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Diplomata SC":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Do Hyeon":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Dokdo":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"handwriting"},"Domine":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Donegal One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Doppio One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Dorsa":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Dosis":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Dr Sugiyama":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Duru Sans":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Dynalight":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"EB Garamond":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"Eagle Lake":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"East Sea Dokdo":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"handwriting"},"Eater":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Economica":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Eczar":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"El Messiri":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Arabic","id":"arabic"},{"name":"Latin","id":"latin"},{"name":"Cyrillic","id":"cyrillic"}],"category":"sans-serif"},"Electrolize":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Elsie":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Elsie Swash Caps":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Emblema One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Emilys Candy":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Encode Sans":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Encode Sans Condensed":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Encode Sans Expanded":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Encode Sans Semi Condensed":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Encode Sans Semi Expanded":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Engagement":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Englebert":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Enriqueta":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Erica One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Esteban":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Euphoria Script":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Ewert":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Exo":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Exo 2":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"}],"category":"sans-serif"},"Expletus Sans":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Fahkwang":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"sans-serif"},"Fanwood Text":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Farsan":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Gujarati","id":"gujarati"}],"category":"display"},"Fascinate":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Fascinate Inline":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Faster One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Fasthand":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Khmer","id":"khmer"}],"category":"serif"},"Fauna One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Faustina":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Federant":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Federo":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Felipa":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Fenix":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Finger Paint":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Fira Mono":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"monospace"},"Fira Sans":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Fira Sans Condensed":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Fira Sans Extra Condensed":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Fjalla One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Fjord One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Flamenco":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Flavors":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Fondamento":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Fontdiner Swanky":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Forum":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"display"},"Francois One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Frank Ruhl Libre":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Bold 700","id":"700"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Hebrew","id":"hebrew"}],"category":"serif"},"Freckle Face":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Fredericka the Great":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Fredoka One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Freehand":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Khmer","id":"khmer"}],"category":"display"},"Fresca":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Frijole":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Fruktur":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Fugaz One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"GFS Didot":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Greek","id":"greek"}],"category":"serif"},"GFS Neohellenic":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Greek","id":"greek"}],"category":"sans-serif"},"Gabriela":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"Gaegu":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"handwriting"},"Gafata":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Galada":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Bengali","id":"bengali"}],"category":"display"},"Galdeano":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Galindo":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Gamja Flower":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"handwriting"},"Gentium Basic":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Gentium Book Basic":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Geo":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Geostar":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Geostar Fill":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Germania One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Gidugu":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Telugu","id":"telugu"},{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Gilda Display":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Give You Glory":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Glass Antiqua":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Glegoo":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Gloria Hallelujah":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Goblin One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Gochi Hand":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Gorditas":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Gothic A1":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Goudy Bookletter 1911":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Graduate":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Grand Hotel":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Gravitas One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Great Vibes":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Griffy":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Gruppo":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Gudea":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Gugi":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"display"},"Gurajada":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Telugu","id":"telugu"},{"name":"Latin","id":"latin"}],"category":"serif"},"Habibi":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Halant":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Hammersmith One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Hanalei":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Hanalei Fill":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Handlee":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Hanuman":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Khmer","id":"khmer"}],"category":"serif"},"Happy Monkey":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Harmattan":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Arabic","id":"arabic"},{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Headland One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Heebo":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Hebrew","id":"hebrew"}],"category":"sans-serif"},"Henny Penny":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Herr Von Muellerhoff":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Hi Melody":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"handwriting"},"Hind":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Hind Guntur":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Telugu","id":"telugu"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Hind Madurai":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Tamil","id":"tamil"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Hind Siliguri":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Bengali","id":"bengali"}],"category":"sans-serif"},"Hind Vadodara":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Gujarati","id":"gujarati"}],"category":"sans-serif"},"Holtwood One SC":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Homemade Apple":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Homenaje":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"IBM Plex Mono":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"monospace"},"IBM Plex Sans":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"IBM Plex Sans Condensed":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"IBM Plex Serif":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"IM Fell DW Pica":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"IM Fell DW Pica SC":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"IM Fell Double Pica":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"IM Fell Double Pica SC":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"IM Fell English":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"IM Fell English SC":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"IM Fell French Canon":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"IM Fell French Canon SC":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"IM Fell Great Primer":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"IM Fell Great Primer SC":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Iceberg":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Iceland":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Imprima":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Inconsolata":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"monospace"},"Inder":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Indie Flower":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Inika":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Inknut Antiqua":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Irish Grover":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Istok Web":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Italiana":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Italianno":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Itim":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"handwriting"},"Jacques Francois":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Jacques Francois Shadow":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Jaldi":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Jim Nightshade":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Jockey One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Jolly Lodger":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Jomhuria":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Arabic","id":"arabic"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Josefin Sans":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Josefin Slab":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Joti One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Jua":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Judson":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Julee":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Julius Sans One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Junge":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Jura":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Just Another Hand":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Just Me Again Down Here":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"K2D":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"sans-serif"},"Kadwa":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"}],"category":"serif"},"Kalam":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Kameron":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Kanit":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"sans-serif"},"Kantumruy":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Khmer","id":"khmer"}],"category":"sans-serif"},"Karla":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Karma":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Katibeh":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Arabic","id":"arabic"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Kaushan Script":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Kavivanar":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Tamil","id":"tamil"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Kavoon":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Kdam Thmor":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Khmer","id":"khmer"}],"category":"display"},"Keania One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Kelly Slab":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"}],"category":"display"},"Kenia":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Khand":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Khmer":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Khmer","id":"khmer"}],"category":"display"},"Khula":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Kirang Haerang":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"display"},"Kite One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Knewave":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"KoHo":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"sans-serif"},"Kodchasan":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"sans-serif"},"Kosugi":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"japanese","id":"japanese"},{"name":"Cyrillic","id":"cyrillic"}],"category":"sans-serif"},"Kosugi Maru":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"japanese","id":"japanese"},{"name":"Cyrillic","id":"cyrillic"}],"category":"sans-serif"},"Kotta One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Koulen":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Khmer","id":"khmer"}],"category":"display"},"Kranky":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Kreon":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Kristi":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Krona One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Krub":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"sans-serif"},"Kumar One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Gujarati","id":"gujarati"}],"category":"display"},"Kumar One Outline":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Gujarati","id":"gujarati"}],"category":"display"},"Kurale":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"La Belle Aurore":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Laila":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Lakki Reddy":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Telugu","id":"telugu"},{"name":"Latin","id":"latin"}],"category":"handwriting"},"Lalezar":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Arabic","id":"arabic"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Lancelot":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Lateef":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Arabic","id":"arabic"},{"name":"Latin","id":"latin"}],"category":"handwriting"},"Lato":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"League Script":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Leckerli One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Ledger":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"}],"category":"serif"},"Lekton":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Lemon":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Lemonada":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Arabic","id":"arabic"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Libre Barcode 128":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Libre Barcode 128 Text":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Libre Barcode 39":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Libre Barcode 39 Extended":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Libre Barcode 39 Extended Text":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Libre Barcode 39 Text":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Libre Baskerville":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Libre Franklin":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Life Savers":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Lilita One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Lily Script One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Limelight":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Linden Hill":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Lobster":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"display"},"Lobster Two":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Londrina Outline":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Londrina Shadow":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Londrina Sketch":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Londrina Solid":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Lora":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"Love Ya Like A Sister":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Loved by the King":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Lovers Quarrel":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Luckiest Guy":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Lusitana":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Lustria":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"M PLUS 1p":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"japanese","id":"japanese"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Hebrew","id":"hebrew"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"M PLUS Rounded 1c":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"japanese","id":"japanese"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Hebrew","id":"hebrew"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Macondo":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Macondo Swash Caps":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Mada":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Arabic","id":"arabic"},{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Magra":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Maiden Orange":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Maitree":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"serif"},"Major Mono Display":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"monospace"},"Mako":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Mali":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"handwriting"},"Mallanna":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Telugu","id":"telugu"},{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Mandali":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Telugu","id":"telugu"},{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Manuale":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Marcellus":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Marcellus SC":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Marck Script":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"}],"category":"handwriting"},"Margarine":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Markazi Text":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Arabic","id":"arabic"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Marko One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Marmelad":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"}],"category":"sans-serif"},"Martel":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Martel Sans":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Marvel":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Mate":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Mate SC":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Maven Pro":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Bold 700","id":"700"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"McLaren":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Meddon":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"MedievalSharp":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Medula One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Meera Inimai":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Tamil","id":"tamil"},{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Megrim":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Meie Script":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Merienda":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Merienda One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Merriweather":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"Merriweather Sans":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Metal":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Khmer","id":"khmer"}],"category":"display"},"Metal Mania":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Metamorphous":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Metrophobic":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Michroma":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Milonga":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Miltonian":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Miltonian Tattoo":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Mina":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Bengali","id":"bengali"}],"category":"sans-serif"},"Miniver":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Miriam Libre":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Hebrew","id":"hebrew"}],"category":"sans-serif"},"Mirza":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Arabic","id":"arabic"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Miss Fajardose":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Mitr":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"sans-serif"},"Modak":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Modern Antiqua":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Mogra":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Gujarati","id":"gujarati"}],"category":"display"},"Molengo":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Molle":{"type":"google-font","variants":[{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Monda":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Monofett":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Monoton":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Monsieur La Doulaise":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Montaga":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Montez":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Montserrat":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Montserrat Alternates":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Montserrat Subrayada":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Moul":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Khmer","id":"khmer"}],"category":"display"},"Moulpali":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Khmer","id":"khmer"}],"category":"display"},"Mountains of Christmas":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Mouse Memoirs":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Mr Bedfort":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Mr Dafoe":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Mr De Haviland":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Mrs Saint Delafield":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Mrs Sheppards":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Mukta":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Mukta Mahee":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"}],"subsets":[{"name":"gurmukhi","id":"gurmukhi"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Mukta Malar":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"}],"subsets":[{"name":"Tamil","id":"tamil"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Mukta Vaani":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Gujarati","id":"gujarati"}],"category":"sans-serif"},"Muli":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Mystery Quest":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"NTR":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Telugu","id":"telugu"},{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Nanum Brush Script":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"handwriting"},"Nanum Gothic":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Nanum Gothic Coding":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"monospace"},"Nanum Myeongjo":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"serif"},"Nanum Pen Script":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"handwriting"},"Neucha":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Cyrillic","id":"cyrillic"}],"category":"handwriting"},"Neuton":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"New Rocker":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"News Cycle":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Niconne":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Niramit":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"sans-serif"},"Nixie One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Nobile":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Nokora":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Khmer","id":"khmer"}],"category":"serif"},"Norican":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Nosifer":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Notable":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Nothing You Could Do":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Noticia Text":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Noto Sans":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Noto Sans JP":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Bold 700","id":"700"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"japanese","id":"japanese"}],"category":"sans-serif"},"Noto Sans KR":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Bold 700","id":"700"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Noto Sans SC":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Bold 700","id":"700"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"chinese-simplified","id":"chinese-simplified"},{"name":"Latin","id":"latin"},{"name":"japanese","id":"japanese"},{"name":"Cyrillic","id":"cyrillic"}],"category":"sans-serif"},"Noto Sans TC":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Bold 700","id":"700"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"japanese","id":"japanese"},{"name":"chinese-traditional","id":"chinese-traditional"}],"category":"sans-serif"},"Noto Serif":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"Noto Serif JP":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"japanese","id":"japanese"}],"category":"serif"},"Noto Serif KR":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"serif"},"Noto Serif SC":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"chinese-simplified","id":"chinese-simplified"},{"name":"Latin","id":"latin"},{"name":"japanese","id":"japanese"},{"name":"Cyrillic","id":"cyrillic"}],"category":"serif"},"Noto Serif TC":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"japanese","id":"japanese"},{"name":"Cyrillic","id":"cyrillic"},{"name":"chinese-traditional","id":"chinese-traditional"}],"category":"serif"},"Nova Cut":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Nova Flat":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Nova Mono":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Greek","id":"greek"}],"category":"monospace"},"Nova Oval":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Nova Round":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Nova Script":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Nova Slim":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Nova Square":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Numans":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Nunito":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Nunito Sans":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Odor Mean Chey":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Khmer","id":"khmer"}],"category":"display"},"Offside":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Old Standard TT":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"Oldenburg":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Oleo Script":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Oleo Script Swash Caps":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Open Sans":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Open Sans Condensed":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Oranienbaum":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"Orbitron":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Bold 700","id":"700"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Oregano":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Orienta":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Original Surfer":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Oswald":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"}],"category":"sans-serif"},"Over the Rainbow":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Overlock":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Overlock SC":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Overpass":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Overpass Mono":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"monospace"},"Ovo":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Oxygen":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Oxygen Mono":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"monospace"},"PT Mono":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"monospace"},"PT Sans":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"PT Sans Caption":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"PT Sans Narrow":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"PT Serif":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"PT Serif Caption":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"Pacifico":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"}],"category":"handwriting"},"Padauk":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"myanmar","id":"myanmar"}],"category":"sans-serif"},"Palanquin":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Palanquin Dark":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Pangolin":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"handwriting"},"Paprika":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Parisienne":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Passero One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Passion One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Pathway Gothic One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Patrick Hand":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Patrick Hand SC":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Pattaya":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Thai","id":"thai"}],"category":"sans-serif"},"Patua One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Pavanam":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Tamil","id":"tamil"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Paytone One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Peddana":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Telugu","id":"telugu"},{"name":"Latin","id":"latin"}],"category":"serif"},"Peralta":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Permanent Marker":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Petit Formal Script":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Petrona":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Philosopher":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Piedra":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Pinyon Script":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Pirata One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Plaster":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Play":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Playball":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Playfair Display":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"}],"category":"serif"},"Playfair Display SC":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"}],"category":"serif"},"Podkova":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"Poiret One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"}],"category":"display"},"Poller One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Poly":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Pompiere":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Pontano Sans":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Poor Story":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"display"},"Poppins":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Port Lligat Sans":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Port Lligat Slab":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Pragati Narrow":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Prata":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"Preahvihear":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Khmer","id":"khmer"}],"category":"display"},"Press Start 2P":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"display"},"Pridi":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"serif"},"Princess Sofia":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Prociono":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Prompt":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"sans-serif"},"Prosto One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"}],"category":"display"},"Proza Libre":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Puritan":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Purple Purse":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Quando":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Quantico":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Quattrocento":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Quattrocento Sans":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Questrial":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Quicksand":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Quintessential":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Qwigley":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Racing Sans One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Radley":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Rajdhani":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Rakkas":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Arabic","id":"arabic"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Raleway":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Raleway Dots":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Ramabhadra":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Telugu","id":"telugu"},{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Ramaraja":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Telugu","id":"telugu"},{"name":"Latin","id":"latin"}],"category":"serif"},"Rambla":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Rammetto One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Ranchers":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Rancho":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Ranga":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Rasa":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Gujarati","id":"gujarati"}],"category":"serif"},"Rationale":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Ravi Prakash":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Telugu","id":"telugu"},{"name":"Latin","id":"latin"}],"category":"display"},"Redressed":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Reem Kufi":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Arabic","id":"arabic"},{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Reenie Beanie":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Revalia":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Rhodium Libre":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Ribeye":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Ribeye Marrow":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Righteous":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Risque":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Roboto":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Roboto Condensed":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Roboto Mono":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"monospace"},"Roboto Slab":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"Rochester":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Rock Salt":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Rokkitt":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Romanesco":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Ropa Sans":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Rosario":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Rosarivo":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Rouge Script":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Rozha One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Rubik":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Hebrew","id":"hebrew"}],"category":"sans-serif"},"Rubik Mono One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"}],"category":"sans-serif"},"Ruda":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Rufina":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Ruge Boogie":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Ruluko":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Rum Raisin":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Ruslan Display":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"}],"category":"display"},"Russo One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"}],"category":"sans-serif"},"Ruthie":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Rye":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Sacramento":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Sahitya":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"}],"category":"serif"},"Sail":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Saira":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Saira Condensed":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Saira Extra Condensed":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Saira Semi Condensed":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Salsa":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Sanchez":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Sancreek":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Sansita":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Sarabun":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"sans-serif"},"Sarala":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Sarina":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Sarpanch":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Satisfy":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Sawarabi Gothic":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"japanese","id":"japanese"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"}],"category":"sans-serif"},"Sawarabi Mincho":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"japanese","id":"japanese"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Scada":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Scheherazade":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Arabic","id":"arabic"},{"name":"Latin","id":"latin"}],"category":"serif"},"Schoolbell":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Scope One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Seaweed Script":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Secular One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Hebrew","id":"hebrew"}],"category":"sans-serif"},"Sedgwick Ave":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Sedgwick Ave Display":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Sevillana":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Seymour One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"}],"category":"sans-serif"},"Shadows Into Light":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Shadows Into Light Two":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Shanti":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Share":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Share Tech":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Share Tech Mono":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"monospace"},"Shojumaru":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Short Stack":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Shrikhand":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Gujarati","id":"gujarati"}],"category":"display"},"Siemreap":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Khmer","id":"khmer"}],"category":"display"},"Sigmar One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Signika":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Signika Negative":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Simonetta":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Sintony":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Sirin Stencil":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Six Caps":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Skranji":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Slabo 13px":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Slabo 27px":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Slackey":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Smokum":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Smythe":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Sniglet":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Extra-Bold 800","id":"800"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Snippet":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Snowburst One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Sofadi One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Sofia":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Song Myung":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"serif"},"Sonsie One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Sorts Mill Goudy":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Source Code Pro":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"monospace"},"Source Sans Pro":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Source Serif Pro":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Space Mono":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"monospace"},"Special Elite":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Spectral":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"}],"category":"serif"},"Spectral SC":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"}],"category":"serif"},"Spicy Rice":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Spinnaker":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Spirax":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Squada One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Sree Krushnadevaraya":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Telugu","id":"telugu"},{"name":"Latin","id":"latin"}],"category":"serif"},"Sriracha":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"handwriting"},"Srisakdi":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"display"},"Staatliches":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Stalemate":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Stalinist One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"}],"category":"display"},"Stardos Stencil":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Stint Ultra Condensed":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Stint Ultra Expanded":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Stoke":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Strait":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Stylish":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Sue Ellen Francisco":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Suez One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Hebrew","id":"hebrew"}],"category":"serif"},"Sumana":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Sunflower":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Medium 500","id":"500"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Sunshiney":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Supermercado One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Sura":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Suranna":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Telugu","id":"telugu"},{"name":"Latin","id":"latin"}],"category":"serif"},"Suravaram":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Telugu","id":"telugu"},{"name":"Latin","id":"latin"}],"category":"serif"},"Suwannaphum":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Khmer","id":"khmer"}],"category":"display"},"Swanky and Moo Moo":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Syncopate":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Tajawal":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Arabic","id":"arabic"},{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Tangerine":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Taprom":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Khmer","id":"khmer"}],"category":"display"},"Tauri":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Taviraj":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"serif"},"Teko":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Telex":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Tenali Ramakrishna":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Telugu","id":"telugu"},{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Tenor Sans":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"}],"category":"sans-serif"},"Text Me One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Thasadith":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"sans-serif"},"The Girl Next Door":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Tienne":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Tillana":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"handwriting"},"Timmana":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Telugu","id":"telugu"},{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Tinos":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Hebrew","id":"hebrew"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"Titan One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Titillium Web":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Trade Winds":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Trirong":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Thin 100 Italic","id":"100italic"},{"name":"Extra-Light 200","id":"200"},{"name":"Extra-Light 200 Italic","id":"200italic"},{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Extra-Bold 800","id":"800"},{"name":"Extra-Bold 800 Italic","id":"800italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Thai","id":"thai"}],"category":"serif"},"Trocchi":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Trochut":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Trykker":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Tulpen One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Ubuntu":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Ubuntu Condensed":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"sans-serif"},"Ubuntu Mono":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Greek Extended","id":"greek-ext"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"monospace"},"Ultra":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Uncial Antiqua":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Underdog":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"}],"category":"display"},"Unica One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"UnifrakturCook":{"type":"google-font","variants":[{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"UnifrakturMaguntia":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Unkempt":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Unlock":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Unna":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"VT323":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"monospace"},"Vampiro One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Varela":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Varela Round":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Hebrew","id":"hebrew"}],"category":"sans-serif"},"Vast Shadow":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Vesper Libre":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Bold 700","id":"700"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Vibur":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Vidaloka":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Viga":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Voces":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Volkhov":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"serif"},"Vollkorn":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"},{"name":"Ultra-Bold 900","id":"900"},{"name":"Ultra-Bold 900 Italic","id":"900italic"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Greek","id":"greek"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"Vollkorn SC":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"serif"},"Voltaire":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Waiting for the Sunrise":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Wallpoet":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"display"},"Walter Turncoat":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Warnes":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Wellfleet":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Wendy One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Wire One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"sans-serif"},"Work Sans":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"},{"name":"Extra-Bold 800","id":"800"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Yanone Kaffeesatz":{"type":"google-font","variants":[{"name":"Extra-Light 200","id":"200"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"}],"category":"sans-serif"},"Yantramanav":{"type":"google-font","variants":[{"name":"Thin 100","id":"100"},{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Bold 700","id":"700"},{"name":"Ultra-Bold 900","id":"900"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"sans-serif"},"Yatra One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Devanagari","id":"devanagari"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"},"Yellowtail":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Yeon Sung":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"korean","id":"korean"},{"name":"Latin","id":"latin"}],"category":"display"},"Yeseva One":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Vietnamese","id":"vietnamese"},{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"},{"name":"Cyrillic","id":"cyrillic"},{"name":"Cyrillic Extended","id":"cyrillic-ext"}],"category":"display"},"Yesteryear":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Yrsa":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Regular","id":"regular"},{"name":"Medium 500","id":"500"},{"name":"Semi-Bold 600","id":"600"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"ZCOOL KuaiLe":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"chinese-simplified","id":"chinese-simplified"},{"name":"Latin","id":"latin"}],"category":"display"},"ZCOOL QingKe HuangYou":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"chinese-simplified","id":"chinese-simplified"},{"name":"Latin","id":"latin"}],"category":"display"},"ZCOOL XiaoWei":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"chinese-simplified","id":"chinese-simplified"},{"name":"Latin","id":"latin"}],"category":"serif"},"Zeyada":{"type":"google-font","variants":[{"name":"Regular","id":"regular"}],"subsets":[{"name":"Latin","id":"latin"}],"category":"handwriting"},"Zilla Slab":{"type":"google-font","variants":[{"name":"Light 300","id":"300"},{"name":"Light 300 Italic","id":"300italic"},{"name":"Regular","id":"regular"},{"name":"Italic","id":"italic"},{"name":"Medium 500","id":"500"},{"name":"Medium 500 Italic","id":"500italic"},{"name":"Semi-Bold 600","id":"600"},{"name":"Semi-Bold 600 Italic","id":"600italic"},{"name":"Bold 700","id":"700"},{"name":"Bold 700 Italic","id":"700italic"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"serif"},"Zilla Slab Highlight":{"type":"google-font","variants":[{"name":"Regular","id":"regular"},{"name":"Bold 700","id":"700"}],"subsets":[{"name":"Latin","id":"latin"},{"name":"Latin Extended","id":"latin-ext"}],"category":"display"}}',
	true
);
libs/better-framework/core/fonts-manager/fonts-google-ea.php000064400000146761151214002430020154 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

/**
 * Google Early Access Fonts List.
 * Created By: BetterStudio
 * Updated: 17 Mar 2019
 * Fonts: 144
 */

return json_decode(
	'{
  "Alef Hebrew": {
    "name": "Alef Hebrew (Hebrew)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/alefhebrew.css",
    "type": "google-ea-font",
    "id": "Alef Hebrew",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "serif"
  },
  "Amstelvar Alpha": {
    "name": "Amstelvar Alpha (Latin)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/amstelvaralpha.css",
    "type": "google-ea-font",
    "id": "Amstelvar Alpha",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "serif"
  },
  "Cabin VF Beta": {
    "name": "Cabin VF Beta (Latin)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/cabinvfbeta.css",
    "type": "google-ea-font",
    "id": "Cabin VF Beta",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Dhyana": {
    "name": "Dhyana (Lao)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/dhyana.css",
    "type": "google-ea-font",
    "id": "Dhyana",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Hanna": {
    "name": "Hanna (Korean)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/hanna.css",
    "type": "google-ea-font",
    "id": "Hanna",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Hannari": {
    "name": "Hannari (Japanese)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/hannari.css",
    "type": "google-ea-font",
    "id": "Hannari",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "serif"
  },
  "Jeju Gothic": {
    "name": "Jeju Gothic (Korean)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/jejugothic.css",
    "type": "google-ea-font",
    "id": "Jeju Gothic",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Jeju Hallasan": {
    "name": "Jeju Hallasan (Korean)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/jejuhallasan.css",
    "type": "google-ea-font",
    "id": "Jeju Hallasan",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "serif"
  },
  "Jeju Myeongjo": {
    "name": "Jeju Myeongjo (Korean)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/jejumyeongjo.css",
    "type": "google-ea-font",
    "id": "Jeju Myeongjo",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "serif"
  },
  "Karla Tamil Inclined": {
    "name": "Karla Tamil Inclined (Tamil)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/karlatamilinclined.css",
    "type": "google-ea-font",
    "id": "Karla Tamil Inclined",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Karla Tamil Upright": {
    "name": "Karla Tamil Upright (Tamil)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/karlatamilupright.css",
    "type": "google-ea-font",
    "id": "Karla Tamil Upright",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Khyay": {
    "name": "Khyay (Myanmar)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/khyay.css",
    "type": "google-ea-font",
    "id": "Khyay",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Kokoro": {
    "name": "Kokoro (Japanese)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/kokoro.css",
    "type": "google-ea-font",
    "id": "Kokoro",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "serif"
  },
  "KoPub Batang": {
    "name": "KoPub Batang (Korean)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/kopubbatang.css",
    "type": "google-ea-font",
    "id": "KoPub Batang",
    "variants": {
      "300": {
        "name": "Book 300",
        "id": 300
      },
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "serif"
  },
  "Lao Muang Don": {
    "name": "Lao Muang Don (Lao)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/laomuangdon.css",
    "type": "google-ea-font",
    "id": "Lao Muang Don",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Lao Muang Khong": {
    "name": "Lao Muang Khong (Lao)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/laomuangkhong.css",
    "type": "google-ea-font",
    "id": "Lao Muang Khong",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Lao Sans Pro": {
    "name": "Lao Sans Pro (Lao)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/laosanspro.css",
    "type": "google-ea-font",
    "id": "Lao Sans Pro",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Lohit Bengali": {
    "name": "Lohit Bengali (Bengali)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/lohitbengali.css",
    "type": "google-ea-font",
    "id": "Lohit Bengali",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Lohit Devanagari": {
    "name": "Lohit Devanagari (Devanagari)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/lohitdevanagari.css",
    "type": "google-ea-font",
    "id": "Lohit Devanagari",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Lohit Tamil": {
    "name": "Lohit Tamil (Tamil)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/lohittamil.css",
    "type": "google-ea-font",
    "id": "Lohit Tamil",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Myanmar Sans Pro": {
    "name": "Myanmar Sans Pro (Myanmar)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/myanmarsanspro.css",
    "type": "google-ea-font",
    "id": "Myanmar Sans Pro",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "NATS": {
    "name": "NATS (Telugu)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/nats.css",
    "type": "google-ea-font",
    "id": "NATS",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Nico Moji": {
    "name": "Nico Moji (Japanese)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/nicomoji.css",
    "type": "google-ea-font",
    "id": "Nico Moji",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "serif"
  },
  "Nikukyu": {
    "name": "Nikukyu (Japanese)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/nikukyu.css",
    "type": "google-ea-font",
    "id": "Nikukyu",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "serif"
  },
  "Noto Kufi Arabic": {
    "name": "Noto Kufi Arabic (Arabic)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notokufiarabic.css",
    "type": "google-ea-font",
    "id": "Noto Kufi Arabic",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Naskh Arabic": {
    "name": "Noto Naskh Arabic (Arabic)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notonaskharabic.css",
    "type": "google-ea-font",
    "id": "Noto Naskh Arabic",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "serif"
  },
  "Noto Naskh Arabic UI": {
    "name": "Noto Naskh Arabic UI (Arabic)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notonaskharabicui.css",
    "type": "google-ea-font",
    "id": "Noto Naskh Arabic UI",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "serif"
  },
  "Noto Nastaliq Urdu": {
    "name": "Noto Nastaliq Urdu (Arabic)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notonastaliqurdu.css",
    "type": "google-ea-font",
    "id": "Noto Nastaliq Urdu",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "serif"
  },
  "Noto Nastaliq Urdu Draft": {
    "name": "Noto Nastaliq Urdu Draft (Arabic)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notonastaliqurdudraft.css",
    "type": "google-ea-font",
    "id": "Noto Nastaliq Urdu Draft",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "serif"
  },
  "Noto Sans Armenian": {
    "name": "Noto Sans Armenian (Armenian)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansarmenian.css",
    "type": "google-ea-font",
    "id": "Noto Sans Armenian",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Armenian": {
    "name": "Noto Sans Armenian (Armenian)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansarmenian.css",
    "type": "google-ea-font",
    "id": "Noto Sans Armenian",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Avestan": {
    "name": "Noto Sans Avestan (Avestan)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansavestan.css",
    "type": "google-ea-font",
    "id": "Noto Sans Avestan",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Balinese": {
    "name": "Noto Sans Balinese (Balinese)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansbalinese.css",
    "type": "google-ea-font",
    "id": "Noto Sans Balinese",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Bamum": {
    "name": "Noto Sans Bamum (Bamum)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansbamum.css",
    "type": "google-ea-font",
    "id": "Noto Sans Bamum",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Batak": {
    "name": "Noto Sans Batak (Batak)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansbatak.css",
    "type": "google-ea-font",
    "id": "Noto Sans Batak",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Bengali": {
    "name": "Noto Sans Bengali (Bengali)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansbengali.css",
    "type": "google-ea-font",
    "id": "Noto Sans Bengali",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Bengali UI": {
    "name": "Noto Sans Bengali UI (Bengali)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansbengaliui.css",
    "type": "google-ea-font",
    "id": "Noto Sans Bengali UI",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Brahmi": {
    "name": "Noto Sans Brahmi (Brahmi)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansbrahmi.css",
    "type": "google-ea-font",
    "id": "Noto Sans Brahmi",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Buginese": {
    "name": "Noto Sans Buginese (Buginese)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansbuginese.css",
    "type": "google-ea-font",
    "id": "Noto Sans Buginese",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Buhid": {
    "name": "Noto Sans Buhid (Buhid)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansbuhid.css",
    "type": "google-ea-font",
    "id": "Noto Sans Buhid",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Canadian Aboriginal": {
    "name": "Noto Sans Canadian Aboriginal (Canadian Aboriginal)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanscanadianaboriginal.css",
    "type": "google-ea-font",
    "id": "Noto Sans Canadian Aboriginal",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Carian": {
    "name": "Noto Sans Carian (Carian)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanscarian.css",
    "type": "google-ea-font",
    "id": "Noto Sans Carian",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Cham": {
    "name": "Noto Sans Cham (Cham)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanscham.css",
    "type": "google-ea-font",
    "id": "Noto Sans Cham",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Cherokee": {
    "name": "Noto Sans Cherokee (Cherokee)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanscherokee.css",
    "type": "google-ea-font",
    "id": "Noto Sans Cherokee",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Coptic": {
    "name": "Noto Sans Coptic (Coptic)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanscoptic.css",
    "type": "google-ea-font",
    "id": "Noto Sans Coptic",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Cuneiform": {
    "name": "Noto Sans Cuneiform (Cuneiform)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanscuneiform.css",
    "type": "google-ea-font",
    "id": "Noto Sans Cuneiform",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Cypriot": {
    "name": "Noto Sans Cypriot (Cypriot)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanscypriot.css",
    "type": "google-ea-font",
    "id": "Noto Sans Cypriot",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Deseret": {
    "name": "Noto Sans Deseret (Deseret)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansdeseret.css",
    "type": "google-ea-font",
    "id": "Noto Sans Deseret",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Devanagari": {
    "name": "Noto Sans Devanagari (Devanagari)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansdevanagari.css",
    "type": "google-ea-font",
    "id": "Noto Sans Devanagari",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Devanagari UI": {
    "name": "Noto Sans Devanagari UI (Devanagari)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansdevanagariui.css",
    "type": "google-ea-font",
    "id": "Noto Sans Devanagari UI",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Egyptian Hieroglyphs": {
    "name": "Noto Sans Egyptian Hieroglyphs (Egyptian Hieroglyphs)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansegyptianhieroglyphs.css",
    "type": "google-ea-font",
    "id": "Noto Sans Egyptian Hieroglyphs",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Ethiopic": {
    "name": "Noto Sans Ethiopic (Ethiopic)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansethiopic.css",
    "type": "google-ea-font",
    "id": "Noto Sans Ethiopic",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Georgian": {
    "name": "Noto Sans Georgian (Georgian)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansgeorgian.css",
    "type": "google-ea-font",
    "id": "Noto Sans Georgian",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Gothic": {
    "name": "Noto Sans Gothic (Gothic)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansgothic.css",
    "type": "google-ea-font",
    "id": "Noto Sans Gothic",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Gujarati": {
    "name": "Noto Sans Gujarati (Gujarati)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansgujarati.css",
    "type": "google-ea-font",
    "id": "Noto Sans Gujarati",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Gujarati UI": {
    "name": "Noto Sans Gujarati UI (Gujarati)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansgujaratiui.css",
    "type": "google-ea-font",
    "id": "Noto Sans Gujarati UI",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Gurmukhi": {
    "name": "Noto Sans Gurmukhi (Gurmukhi)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansgurmukhi.css",
    "type": "google-ea-font",
    "id": "Noto Sans Gurmukhi",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Gurmukhi UI": {
    "name": "Noto Sans Gurmukhi UI (Gurmukhi)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansgurmukhiui.css",
    "type": "google-ea-font",
    "id": "Noto Sans Gurmukhi UI",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Hanunoo": {
    "name": "Noto Sans Hanunoo (Hanunoo)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanshanunoo.css",
    "type": "google-ea-font",
    "id": "Noto Sans Hanunoo",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Imperial Aramaic": {
    "name": "Noto Sans Imperial Aramaic (Imperial Aramaic)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansimperialaramaic.css",
    "type": "google-ea-font",
    "id": "Noto Sans Imperial Aramaic",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Imperial Aramaic": {
    "name": "Noto Sans Imperial Aramaic (Imperial Aramaic)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansimperialaramaic.css",
    "type": "google-ea-font",
    "id": "Noto Sans Imperial Aramaic",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Inscriptional Pahlavi": {
    "name": "Noto Sans Inscriptional Pahlavi (Inscriptional Pahlavi)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansinscriptionalpahlavi.css",
    "type": "google-ea-font",
    "id": "Noto Sans Inscriptional Pahlavi",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Inscriptional Parthian": {
    "name": "Noto Sans Inscriptional Parthian (Inscriptional Parthian)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansinscriptionalparthian.css",
    "type": "google-ea-font",
    "id": "Noto Sans Inscriptional Parthian",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Japanese": {
    "name": "Noto Sans Japanese (Japanese)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansjapanese.css",
    "type": "google-ea-font",
    "id": "Noto Sans Japanese",
    "variants": {
      "100": {
        "name": "Ultra-Light 100",
        "id": 100
      },
      "300": {
        "name": "Book 300",
        "id": 300
      },
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "500": {
        "name": "Medium 500",
        "id": 500
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      },
      "900": {
        "name": "Ultra-Bold 900",
        "id": 900
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Javanese": {
    "name": "Noto Sans Javanese (Javanese)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansjavanese.css",
    "type": "google-ea-font",
    "id": "Noto Sans Javanese",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Kaithi": {
    "name": "Noto Sans Kaithi (Kaithi)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanskaithi.css",
    "type": "google-ea-font",
    "id": "Noto Sans Kaithi",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Kannada": {
    "name": "Noto Sans Kannada (Kannada)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanskannada.css",
    "type": "google-ea-font",
    "id": "Noto Sans Kannada",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Kannada UI": {
    "name": "Noto Sans Kannada UI (Kannada)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanskannadaui.css",
    "type": "google-ea-font",
    "id": "Noto Sans Kannada UI",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Kayah Li": {
    "name": "Noto Sans Kayah Li (Kayah Li)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanskayahli.css",
    "type": "google-ea-font",
    "id": "Noto Sans Kayah Li",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Kharoshthi": {
    "name": "Noto Sans Kharoshthi (Kharoshthi)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanskharoshthi.css",
    "type": "google-ea-font",
    "id": "Noto Sans Kharoshthi",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Khmer": {
    "name": "Noto Sans Khmer (Khmer)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanskhmer.css",
    "type": "google-ea-font",
    "id": "Noto Sans Khmer",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Khmer UI": {
    "name": "Noto Sans Khmer UI (Khmer)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanskhmerui.css",
    "type": "google-ea-font",
    "id": "Noto Sans Khmer UI",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Kufi Arabic": {
    "name": "Noto Sans Kufi Arabic (Arabic)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanskufiarabic.css",
    "type": "google-ea-font",
    "id": "Noto Sans Kufi Arabic",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Lao": {
    "name": "Noto Sans Lao (Lao)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanslao.css",
    "type": "google-ea-font",
    "id": "Noto Sans Lao",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Lao UI": {
    "name": "Noto Sans Lao UI (Lao)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanslaoui.css",
    "type": "google-ea-font",
    "id": "Noto Sans Lao UI",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Lepcha": {
    "name": "Noto Sans Lepcha (Lepcha)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanslepcha.css",
    "type": "google-ea-font",
    "id": "Noto Sans Lepcha",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Limbu": {
    "name": "Noto Sans Limbu (Limbu)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanslimbu.css",
    "type": "google-ea-font",
    "id": "Noto Sans Limbu",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Linear B": {
    "name": "Noto Sans Linear B (Linear B)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanslinearb.css",
    "type": "google-ea-font",
    "id": "Noto Sans Linear B",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Lisu": {
    "name": "Noto Sans Lisu (Lisu)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanslisu.css",
    "type": "google-ea-font",
    "id": "Noto Sans Lisu",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Lycian": {
    "name": "Noto Sans Lycian (Lycian)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanslycian.css",
    "type": "google-ea-font",
    "id": "Noto Sans Lycian",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Lydian": {
    "name": "Noto Sans Lydian (Lydian)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanslydian.css",
    "type": "google-ea-font",
    "id": "Noto Sans Lydian",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Malayalam": {
    "name": "Noto Sans Malayalam (Malayalam)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansmalayalam.css",
    "type": "google-ea-font",
    "id": "Noto Sans Malayalam",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Malayalam UI": {
    "name": "Noto Sans Malayalam UI (Malayalam)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansmalayalamui.css",
    "type": "google-ea-font",
    "id": "Noto Sans Malayalam UI",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Mandaic": {
    "name": "Noto Sans Mandaic (Mandaic)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansmandaic.css",
    "type": "google-ea-font",
    "id": "Noto Sans Mandaic",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Meetei Mayek": {
    "name": "Noto Sans Meetei Mayek (Meetei Mayek)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansmeeteimayek.css",
    "type": "google-ea-font",
    "id": "Noto Sans Meetei Mayek",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Mongolian": {
    "name": "Noto Sans Mongolian (Mongolian)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansmongolian.css",
    "type": "google-ea-font",
    "id": "Noto Sans Mongolian",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Myanmar": {
    "name": "Noto Sans Myanmar (Myanmar)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansmyanmar.css",
    "type": "google-ea-font",
    "id": "Noto Sans Myanmar",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Myanmar UI": {
    "name": "Noto Sans Myanmar UI (Myanmar)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansmyanmarui.css",
    "type": "google-ea-font",
    "id": "Noto Sans Myanmar UI",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans New Tai Lue": {
    "name": "Noto Sans New Tai Lue (New Tai Lue)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansnewtailue.css",
    "type": "google-ea-font",
    "id": "Noto Sans New Tai Lue",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Ogham": {
    "name": "Noto Sans Ogham (Ogham)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansogham.css",
    "type": "google-ea-font",
    "id": "Noto Sans Ogham",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Ol Chiki": {
    "name": "Noto Sans Ol Chiki (Ol Chiki)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansolchiki.css",
    "type": "google-ea-font",
    "id": "Noto Sans Ol Chiki",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Ol Chiki": {
    "name": "Noto Sans Ol Chiki (Ol Chiki)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansolchiki.css",
    "type": "google-ea-font",
    "id": "Noto Sans Ol Chiki",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Old Italic": {
    "name": "Noto Sans Old Italic (Old Italic)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansolditalic.css",
    "type": "google-ea-font",
    "id": "Noto Sans Old Italic",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Old Persian": {
    "name": "Noto Sans Old Persian (Old Persian)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansoldpersian.css",
    "type": "google-ea-font",
    "id": "Noto Sans Old Persian",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Old South Arabian": {
    "name": "Noto Sans Old South Arabian (Old South Arabian)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansoldsoutharabian.css",
    "type": "google-ea-font",
    "id": "Noto Sans Old South Arabian",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Old Turkic": {
    "name": "Noto Sans Old Turkic (Old Turkic)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansoldturkic.css",
    "type": "google-ea-font",
    "id": "Noto Sans Old Turkic",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Oriya": {
    "name": "Noto Sans Oriya (Oriya)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansoriya.css",
    "type": "google-ea-font",
    "id": "Noto Sans Oriya",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Oriya UI": {
    "name": "Noto Sans Oriya UI (Oriya)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansoriyaui.css",
    "type": "google-ea-font",
    "id": "Noto Sans Oriya UI",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Osmanya": {
    "name": "Noto Sans Osmanya (Osmanya)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansosmanya.css",
    "type": "google-ea-font",
    "id": "Noto Sans Osmanya",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Phags Pa": {
    "name": "Noto Sans Phags Pa (Phags-pa)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansphagspa.css",
    "type": "google-ea-font",
    "id": "Noto Sans Phags Pa",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Phoenician": {
    "name": "Noto Sans Phoenician (Phoenician)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansphoenician.css",
    "type": "google-ea-font",
    "id": "Noto Sans Phoenician",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Rejang": {
    "name": "Noto Sans Rejang (Rejang)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansrejang.css",
    "type": "google-ea-font",
    "id": "Noto Sans Rejang",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Runic": {
    "name": "Noto Sans Runic (Runic)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansrunic.css",
    "type": "google-ea-font",
    "id": "Noto Sans Runic",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Samaritan": {
    "name": "Noto Sans Samaritan (Samaritan)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanssamaritan.css",
    "type": "google-ea-font",
    "id": "Noto Sans Samaritan",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Saurashtra": {
    "name": "Noto Sans Saurashtra (Saurashtra)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanssaurashtra.css",
    "type": "google-ea-font",
    "id": "Noto Sans Saurashtra",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "": {
    "name": "Noto Sans SC Sliced (Chinese Simplified)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansscsliced.css",
    "type": "google-ea-font",
    "id": "",
    "variants": [],
    "category": "sans-serif"
  },
  "Noto Sans Shavian": {
    "name": "Noto Sans Shavian (Shavian)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansshavian.css",
    "type": "google-ea-font",
    "id": "Noto Sans Shavian",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Sinhala": {
    "name": "Noto Sans Sinhala (Sinhala)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanssinhala.css",
    "type": "google-ea-font",
    "id": "Noto Sans Sinhala",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Sundanese": {
    "name": "Noto Sans Sundanese (Sundanese)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanssundanese.css",
    "type": "google-ea-font",
    "id": "Noto Sans Sundanese",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Syloti Nagri": {
    "name": "Noto Sans Syloti Nagri (Syloti Nagri)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanssylotinagri.css",
    "type": "google-ea-font",
    "id": "Noto Sans Syloti Nagri",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Syriac Eastern": {
    "name": "Noto Sans Syriac Eastern (Syriac Eastern)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanssyriaceastern.css",
    "type": "google-ea-font",
    "id": "Noto Sans Syriac Eastern",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Syriac Estrangela": {
    "name": "Noto Sans Syriac Estrangela (Syriac Estrangela)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanssyriacestrangela.css",
    "type": "google-ea-font",
    "id": "Noto Sans Syriac Estrangela",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Syriac Western": {
    "name": "Noto Sans Syriac Western (Syriac Western)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanssyriacwestern.css",
    "type": "google-ea-font",
    "id": "Noto Sans Syriac Western",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Tagalog": {
    "name": "Noto Sans Tagalog (Tagalog)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanstagalog.css",
    "type": "google-ea-font",
    "id": "Noto Sans Tagalog",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Tagbanwa": {
    "name": "Noto Sans Tagbanwa (Tagbanwa)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanstagbanwa.css",
    "type": "google-ea-font",
    "id": "Noto Sans Tagbanwa",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Tai Le": {
    "name": "Noto Sans Tai Le (Tai Le)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanstaile.css",
    "type": "google-ea-font",
    "id": "Noto Sans Tai Le",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Tai Tham": {
    "name": "Noto Sans Tai Tham (Tai Tham)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanstaitham.css",
    "type": "google-ea-font",
    "id": "Noto Sans Tai Tham",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Tai Viet": {
    "name": "Noto Sans Tai Viet (Tai Viet)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanstaiviet.css",
    "type": "google-ea-font",
    "id": "Noto Sans Tai Viet",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Tamil": {
    "name": "Noto Sans Tamil (Tamil)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanstamil.css",
    "type": "google-ea-font",
    "id": "Noto Sans Tamil",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Tamil UI": {
    "name": "Noto Sans Tamil UI (Tamil)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanstamilui.css",
    "type": "google-ea-font",
    "id": "Noto Sans Tamil UI",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Tamil UI": {
    "name": "Noto Sans Tamil UI (Tamil)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanstamilui.css",
    "type": "google-ea-font",
    "id": "Noto Sans Tamil UI",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Telugu": {
    "name": "Noto Sans Telugu (Telugu)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanstelugu.css",
    "type": "google-ea-font",
    "id": "Noto Sans Telugu",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Telugu UI": {
    "name": "Noto Sans Telugu UI (Telugu)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansteluguui.css",
    "type": "google-ea-font",
    "id": "Noto Sans Telugu UI",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Thaana": {
    "name": "Noto Sans Thaana (Thaana)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansthaana.css",
    "type": "google-ea-font",
    "id": "Noto Sans Thaana",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Thai": {
    "name": "Noto Sans Thai (Thai)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansthai.css",
    "type": "google-ea-font",
    "id": "Noto Sans Thai",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Thai UI": {
    "name": "Noto Sans Thai UI (Thai)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansthaiui.css",
    "type": "google-ea-font",
    "id": "Noto Sans Thai UI",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Tibetan": {
    "name": "Noto Sans Tibetan (Tibetan)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanstibetan.css",
    "type": "google-ea-font",
    "id": "Noto Sans Tibetan",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Tifinagh": {
    "name": "Noto Sans Tifinagh (Tifinagh)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanstifinagh.css",
    "type": "google-ea-font",
    "id": "Noto Sans Tifinagh",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Ugaritic": {
    "name": "Noto Sans Ugaritic (Ugaritic)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansugaritic.css",
    "type": "google-ea-font",
    "id": "Noto Sans Ugaritic",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Vai": {
    "name": "Noto Sans Vai (Vai)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansvai.css",
    "type": "google-ea-font",
    "id": "Noto Sans Vai",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans Yi": {
    "name": "Noto Sans Yi (Yi)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansyi.css",
    "type": "google-ea-font",
    "id": "Noto Sans Yi",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Noto Serif Armenian": {
    "name": "Noto Serif Armenian (Armenian)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notoserifarmenian.css",
    "type": "google-ea-font",
    "id": "Noto Serif Armenian",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "serif"
  },
  "Noto Serif Georgian": {
    "name": "Noto Serif Georgian (Georgian)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notoserifgeorgian.css",
    "type": "google-ea-font",
    "id": "Noto Serif Georgian",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "serif"
  },
  "Noto Serif Khmer": {
    "name": "Noto Serif Khmer (Khmer)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notoserifkhmer.css",
    "type": "google-ea-font",
    "id": "Noto Serif Khmer",
    "variants": {
      "300": {
        "name": "Book 300",
        "id": 300
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "serif"
  },
  "Noto Serif Lao": {
    "name": "Noto Serif Lao (Lao)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notoseriflao.css",
    "type": "google-ea-font",
    "id": "Noto Serif Lao",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "serif"
  },
  "Noto Serif Thai": {
    "name": "Noto Serif Thai (Thai)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notoserifthai.css",
    "type": "google-ea-font",
    "id": "Noto Serif Thai",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "serif"
  },
  "Nunito VF Beta": {
    "name": "Nunito VF Beta (Latin)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/nunitovfbeta.css",
    "type": "google-ea-font",
    "id": "Nunito VF Beta",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Open Sans Hebrew": {
    "name": "Open Sans Hebrew (Hebrew)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/opensanshebrew.css",
    "type": "google-ea-font",
    "id": "Open Sans Hebrew",
    "variants": {
      "300": {
        "name": "Book 300",
        "id": 300
      },
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Open Sans Hebrew Condensed": {
    "name": "Open Sans Hebrew Condensed (Hebrew)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/opensanshebrewcondensed.css",
    "type": "google-ea-font",
    "id": "Open Sans Hebrew Condensed",
    "variants": {
      "300": {
        "name": "Book 300",
        "id": 300
      },
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Phetsarath": {
    "name": "Phetsarath (Lao)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/phetsarath.css",
    "type": "google-ea-font",
    "id": "Phetsarath",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Ponnala": {
    "name": "Ponnala (Telugu)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/ponnala.css",
    "type": "google-ea-font",
    "id": "Ponnala",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "serif"
  },
  "Souliyo": {
    "name": "Souliyo (Lao)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/souliyo.css",
    "type": "google-ea-font",
    "id": "Souliyo",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Thabit": {
    "name": "Thabit (Arabic)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/thabit.css",
    "type": "google-ea-font",
    "id": "Thabit",
    "variants": {
      "500": {
        "name": "Medium 500",
        "id": 500
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "monospace"
  },
  "Tharlon": {
    "name": "Tharlon (Myanmar)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/tharlon.css",
    "type": "google-ea-font",
    "id": "Tharlon",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  }
}',
	true
);
libs/better-framework/core/fonts-manager/class-bf-fm-theme-fonts-helper.php000064400000010025151214002430022743 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Used For retrieving Font Stacks.
 */
class BF_FM_Theme_Fonts_Helper {


	/**
	 * Contain array of all font stacks
	 *
	 * @var array
	 */
	private static $fonts_list = array();


	public static function load_fonts() {

		static $font_loaded;

		if ( $font_loaded ) {
			return;
		}

		/**
		 * Use this filter to add theme specified inside font manager!
		 *
		 * @since 2.0
		 *
		 * @param string $fonts_list Contains all fonts list
		 */
		self::$fonts_list = apply_filters( 'better-fonts-manager/theme-fonts', self::$fonts_list );
	}


	/**
	 * Used for Retrieving list of all Google Fonts
	 *
	 * @return array
	 */
	public static function get_all_fonts() {

		// Load all fonts one time
		self::load_fonts();

		return self::$fonts_list;
	}


	/**
	 * Used for retrieving single font info
	 *
	 * @param $font_name
	 *
	 * @return bool
	 */
	public static function get_font( $font_name ) {

		$fonts = self::get_all_fonts();

		if ( isset( $fonts[ $font_name ] ) ) {
			return $fonts[ $font_name ];
		} else {
			return false;
		}
	}


	/**
	 * Generate and return Option elements of all font for select element
	 *
	 * @param   string $active_font  Family name of selected font in options
	 * @param   bool   $option_group Active or selected font
	 *
	 * @return  string
	 */
	public static function get_fonts_family_option_elements( $active_font = '', $option_group = true ) {

		$output = '';

		if ( $option_group ) {
			$output .= '<optgroup label="' . __( 'Theme Fonts', 'better-studio' ) . '">';
		}

		foreach ( self::get_all_fonts() as $key => $font ) {
			$output .= '<option value="' . esc_attr( $key ) . '" ' . ( $key == $active_font ? 'selected' : '' ) . '>' . esc_html( $key ) . '</option>';
		}

		if ( $option_group ) {
			$output .= '</optgroup>';
		}

		return $output;
	}


	/**
	 * Generate and return Option elements of font variants
	 *
	 * @param   string $font_variant Active or selected variant
	 *
	 * @return string
	 */
	public static function get_font_variants_option_elements( $font_variant = '' ) {

		if ( empty( $font_variant ) ) {
			$font_variant = '400';
		}

		$output = '';

		$variants = array(
			'100'       => __( 'Ultra-Light 100', 'better-studio' ),
			'300'       => __( 'Book 300', 'better-studio' ),
			'400'       => __( 'Normal 400', 'better-studio' ),
			'500'       => __( 'Medium 500', 'better-studio' ),
			'700'       => __( 'Bold 700', 'better-studio' ),
			'900'       => __( 'Ultra-Bold 900', 'better-studio' ),
			'100italic' => __( 'Ultra-Light 100 Italic', 'better-studio' ),
			'300italic' => __( 'Book 300 Italic', 'better-studio' ),
			'400italic' => __( 'Normal 400 Italic', 'better-studio' ),
			'500italic' => __( 'Medium 500 Italic', 'better-studio' ),
			'700italic' => __( 'Bold 700 Italic', 'better-studio' ),
			'900italic' => __( 'Ultra-Bold 900 Italic', 'better-studio' ),
		);

		foreach ( $variants as $variant_id => $variant_name ) {
			$output .= '<option value="' . esc_attr( $variant_id ) . '" ' . ( $variant_id == $font_variant ? 'selected' : '' ) . '>' . esc_html( $variant_name ) . '</option>';
		}

		return $output;
	}


	/**
	 * Generate and return Option elements of font subsets
	 *
	 * @return string
	 */
	public static function get_font_subset_option_elements() {

		return '<option value="unknown">' . esc_html__( 'Unknown', 'better-studio' ) . '</option>';
	}

}libs/better-framework/core/fonts-manager/class-bf-fm-google-fonts-helper.php000064400000010073151214002430023120 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Used For retrieving Google fonts list.
 * Also contain some helper functions for general usage
 */
class BF_FM_Google_Fonts_Helper {


	/**
	 * Contain array of all Google Fonts List
	 *
	 * @var array
	 */
	private static $fonts_list = null;


	/**
	 * Used for Retrieving list of all Google Fonts
	 */
	public static function get_all_fonts() {

		if ( self::$fonts_list != null ) {
			return self::$fonts_list;
		}

		return self::$fonts_list = include BF_PATH . 'core/fonts-manager/fonts-google.php';
	}


	/**
	 * Used for retrieving single font info
	 *
	 * @param   $font_name      string      Font name
	 *
	 * @return  bool
	 */
	public static function get_font( $font_name ) {

		$fonts = self::get_all_fonts();

		if ( isset( $fonts[ $font_name ] ) ) {
			return $fonts[ $font_name ];
		}

		return false;
	}


	/**
	 * Generate and return Option elements of all font for select element
	 *
	 * @param   string $active_font  Family name of selected font in options
	 * @param   bool   $option_group Add options into option group?
	 *
	 * @return string
	 */
	public static function get_fonts_family_option_elements( $active_font = '', $option_group = true ) {

		$output = '';

		if ( $option_group ) {
			$output .= '<optgroup label="' . __( 'Google Fonts', 'better-studio' ) . '">';
		}

		foreach ( self::get_all_fonts() as $key => $font ) {
			$output .= '<option value="' . esc_attr( $key ) . '"' . ( $key == $active_font ? 'selected' : '' ) . '>' . esc_html( $key ) . '</option>';
		}

		if ( $option_group ) {
			$output .= '</optgroup>';
		}

		return $output;
	}


	/**
	 * Generate and return Option elements of font variants
	 *
	 * @param   $font               string|array        Font array or ID
	 * @param   $font_variant       string              Active or selected variant
	 *
	 * @return  string
	 */
	public static function get_font_variants_option_elements( $font, $font_variant ) {

		$output = '';

		if ( ! is_array( $font ) ) {
			$font_info = self::get_font( $font );
		} else {
			$font_info = $font;
		}

		if ( $font_variant == '400' || $font_variant == '400italic' ) {
			foreach ( $font_info['variants'] as $variant ) {
				if ( $font_variant == '400' && $variant['id'] == 'regular' ) {
					$font_variant = 'regular';
					break;
				} elseif ( $font_variant == '400italic' && $variant['id'] == 'italic' ) {
					$font_variant = 'italic';
					break;
				}
			}
		}

		foreach ( $font_info['variants'] as $variant ) {
			$output .= '<option value="' . esc_html( $variant['id'] ) . '"' . ( $variant['id'] == $font_variant ? ' selected="selected" ' : '' ) . '>' . esc_html( $variant['name'] ) . '</option>';
		}

		return $output;

	}


	/**
	 * Generate and return Option elements of font subsets
	 *
	 * @param   $font               string|array        Font array or ID
	 * @param   $active_subset      string              Active or selected subset
	 *
	 * @return  string
	 */
	public static function get_font_subset_option_elements( $font, $active_subset ) {

		$output = '';

		if ( ! is_array( $font ) ) {
			$font_info = self::get_font( $font );
		} else {
			$font_info = $font;
		}

		foreach ( $font_info['subsets'] as $variant ) {
			$output .= '<option value="' . esc_attr( $variant['id'] ) . '"' . ( $variant['id'] == $active_subset ? ' selected="selected" ' : '' ) . '>' . esc_html( $variant['name'] ) . '</option>';
		}

		return $output;
	}

}libs/better-framework/core/fonts-manager/class-bf-fm-font-stacks-helper.php000064400000010045151214002430022750 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Used For retrieving Font Stacks.
 */
class BF_FM_Font_Stacks_Helper {


	/**
	 * Contain array of all font stacks
	 *
	 * @var array
	 */
	private static $fonts_list = null;


	/**
	 * Used for Retrieving list of all Google Fonts
	 */
	public static function get_all_fonts() {

		if ( self::$fonts_list != null ) {
			return self::$fonts_list;
		}

		// load option
		$font_stacks = bf_get_option( 'font_stacks', Better_Framework::fonts_manager()->option_panel_id );

		// create array
		$_font_stacks = array();
		foreach ( (array) $font_stacks as $stack ) {

			$_font_stacks[ $stack['id'] ]['stack'] = $stack['stack'];
			$_font_stacks[ $stack['id'] ]['type']  = 'font-stack';

		}

		// save to cache
		return self::$fonts_list = $_font_stacks;
	}


	/**
	 * Used for retrieving single font info
	 *
	 * @param $font_name
	 *
	 * @return bool
	 */
	public static function get_font( $font_name ) {

		$fonts = self::get_all_fonts();

		if ( isset( $fonts[ $font_name ] ) ) {
			return $fonts[ $font_name ];
		} else {
			return false;
		}
	}


	/**
	 * Generate and return Option elements of all font for select element
	 *
	 * @param   string $active_font  Family name of selected font in options
	 * @param   bool   $option_group Active or selected font
	 *
	 * @return  string
	 */
	public static function get_fonts_family_option_elements( $active_font = '', $option_group = true ) {

		$output = '';

		if ( $option_group ) {
			$output .= '<optgroup label="' . __( 'Font Stacks', 'better-studio' ) . '">';
		}

		foreach ( self::get_all_fonts() as $key => $font ) {
			$output .= '<option value="' . esc_attr( $key ) . '" ' . ( $key == $active_font ? 'selected' : '' ) . '>' . esc_html( $key ) . '</option>';
		}

		if ( $option_group ) {
			$output .= '</optgroup>';
		}

		return $output;
	}


	/**
	 * Generate and return Option elements of font variants
	 *
	 * @param   string $font_variant Active or selected variant
	 *
	 * @return string
	 */
	public static function get_font_variants_option_elements( $font_variant = '' ) {

		if ( empty( $font_variant ) ) {

			$font_variant = '400';

		}

		$output = '';

		$variants = array(
			'100'       => __( 'Ultra-Light 100', 'better-studio' ),
			'300'       => __( 'Book 300', 'better-studio' ),
			'400'       => __( 'Normal 400', 'better-studio' ),
			'500'       => __( 'Medium 500', 'better-studio' ),
			'700'       => __( 'Bold 700', 'better-studio' ),
			'900'       => __( 'Ultra-Bold 900', 'better-studio' ),
			'100italic' => __( 'Ultra-Light 100 Italic', 'better-studio' ),
			'300italic' => __( 'Book 300 Italic', 'better-studio' ),
			'400italic' => __( 'Normal 400 Italic', 'better-studio' ),
			'500italic' => __( 'Medium 500 Italic', 'better-studio' ),
			'700italic' => __( 'Bold 700 Italic', 'better-studio' ),
			'900italic' => __( 'Ultra-Bold 900 Italic', 'better-studio' ),
		);

		foreach ( $variants as $variant_id => $variant_name ) {
			$output .= '<option value="' . $variant_id /* escaped before */ . '" ' . ( $variant_id == $font_variant ? 'selected' : '' ) . '>' . esc_html( $variant_name ) . '</option>';
		}

		return $output;
	}


	/**
	 * Generate and return Option elements of font subsets
	 *
	 * @return string
	 */
	public static function get_font_subset_option_elements() {

		return '<option value="unknown">' . esc_html__( 'Unknown', 'better-studio' ) . '</option>';
	}

}libs/better-framework/core/fonts-manager/fonts-google-ea-old.php000064400000030351151214002430020713 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

/**
 * Google Early Access Fonts List.
 * Created By: BetterStudio
 * Updated: 17 Mar 2019
 * Fonts: 144
 */

return json_decode(
	'{
	 "cwTeXFangSong": {
    "name": "cwTeXFangSong (Chinese Traditional)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/cwtexfangsong.css",
    "type": "google-ea-font",
    "id": "cwTeXFangSong",
    "variants": {
      "500": {
        "name": "Medium 500",
        "id": 500
      }
    },
    "category": "serif"
  },
   "Droid Sans Thai": {
    "name": "Droid Sans Thai (Thai)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/droidsansthai.css",
    "type": "google-ea-font",
    "id": "Droid Sans Thai",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Sawarabi Mincho": {
    "name": "Sawarabi Mincho (Japanese)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/sawarabimincho.css",
    "type": "google-ea-font",
    "id": "Sawarabi Mincho",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "serif"
  },
   "Rounded Mplus 1c": {
    "name": "Rounded Mplus 1c (Japanese)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/roundedmplus1c.css",
    "type": "google-ea-font",
    "id": "Rounded Mplus 1c",
    "variants": {
      "100": {
        "name": "Ultra-Light 100",
        "id": 100
      },
      "300": {
        "name": "Book 300",
        "id": 300
      },
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "500": {
        "name": "Medium 500",
        "id": 500
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      },
      "900": {
        "name": "Ultra-Bold 900",
        "id": 900
      }
    },
    "category": "sans-serif"
  },
  "Sawarabi Gothic": {
    "name": "Sawarabi Gothic (Japanese)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/sawarabigothic.css",
    "type": "google-ea-font",
    "id": "Sawarabi Gothic",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "sans-serif"
  },
  "Padauk": {
    "name": "Padauk (Myanmar)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/padauk.css",
    "type": "google-ea-font",
    "id": "Padauk",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "cwTeXHei": {
    "name": "cwTeXHei (Chinese-traditional)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/cwtexhei.css",
    "type": "google-ea-font",
    "id": "cwTeXHei",
    "variants": {
      "500": {
        "name": "Medium 500",
        "id": 500
      }
    },
    "category": "sans-serif"
  },
  "cwTeXKai": {
    "name": "cwTeXKai (Chinese Traditional)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/cwtexkai.css",
    "type": "google-ea-font",
    "id": "cwTeXKai",
    "variants": {
      "500": {
        "name": "Medium 500",
        "id": 500
      }
    },
    "category": "serif"
  },
  "cwTeXMing": {
    "name": "cwTeXMing (Chinese Traditional)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/cwtexming.css",
    "type": "google-ea-font",
    "id": "cwTeXMing",
    "variants": {
      "500": {
        "name": "Medium 500",
        "id": 500
      }
    },
    "category": "serif"
  },
  "cwTeXYen": {
    "name": "cwTeXYen (Chinese Traditional)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/cwtexyen.css",
    "type": "google-ea-font",
    "id": "cwTeXYen",
    "variants": {
      "500": {
        "name": "Medium 500",
        "id": 500
      }
    },
    "category": "sans-serif"
  },
  "Dhyana": {
    "name": "Dhyana (Lao)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/dhyana.css",
    "type": "google-ea-font",
    "id": "Dhyana",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Droid Arabic Kufi": {
    "name": "Droid Arabic Kufi (Arabic)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/droidarabickufi.css",
    "type": "google-ea-font",
    "id": "Droid Arabic Kufi",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Droid Arabic Naskh": {
    "name": "Droid Arabic Naskh (Arabic)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/droidarabicnaskh.css",
    "type": "google-ea-font",
    "id": "Droid Arabic Naskh",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "serif"
  },
  "Mplus 1p": {
    "name": "Mplus 1p (Japanese)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/mplus1p.css",
    "type": "google-ea-font",
    "id": "Mplus 1p",
    "variants": {
      "100": {
        "name": "Ultra-Light 100",
        "id": 100
      },
      "300": {
        "name": "Book 300",
        "id": 300
      },
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "500": {
        "name": "Medium 500",
        "id": 500
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      },
      "900": {
        "name": "Ultra-Bold 900",
        "id": 900
      }
    },
    "category": "sans-serif"
  },
  "Droid Serif Thai": {
    "name": "Droid Serif Thai (Thai)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/droidserifthai.css",
    "type": "google-ea-font",
    "id": "Droid Serif Thai",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "serif"
  },
  "Nanum Brush Script": {
    "name": "Nanum Brush Script (Korean)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/nanumbrushscript.css",
    "type": "google-ea-font",
    "id": "Nanum Brush Script",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "serif"
  },
  "Nanum Gothic": {
    "name": "Nanum Gothic (Korean)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/nanumgothic.css",
    "type": "google-ea-font",
    "id": "Nanum Gothic",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Nanum Gothic Coding": {
    "name": "Nanum Gothic Coding (Korean)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/nanumgothiccoding.css",
    "type": "google-ea-font",
    "id": "Nanum Gothic Coding",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "monospace"
  },
  "Nanum Myeongjo": {
    "name": "Nanum Myeongjo (Korean)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/nanummyeongjo.css",
    "type": "google-ea-font",
    "id": "Nanum Myeongjo",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "serif"
  },
  "Nanum Pen Script": {
    "name": "Nanum Pen Script (Korean)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/nanumpenscript.css",
    "type": "google-ea-font",
    "id": "Nanum Pen Script",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      }
    },
    "category": "serif"
  },
  "Noto Sans Hebrew": {
    "name": "Noto Sans Hebrew (Hebrew)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanshebrew.css",
    "type": "google-ea-font",
    "id": "Noto Sans Hebrew",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans JP": {
    "name": "Noto Sans JP (Japanese)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosansjp.css",
    "type": "google-ea-font",
    "id": "Noto Sans JP",
    "variants": {
      "100": {
        "name": "Ultra-Light 100",
        "id": 100
      },
      "300": {
        "name": "Book 300",
        "id": 300
      },
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "500": {
        "name": "Medium 500",
        "id": 500
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      },
      "900": {
        "name": "Ultra-Bold 900",
        "id": 900
      }
    },
    "category": "sans-serif"
  },
   "Noto Sans KR": {
    "name": "Noto Sans KR (Korean)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanskr.css",
    "type": "google-ea-font",
    "id": "Noto Sans KR",
    "variants": {
      "100": {
        "name": "Ultra-Light 100",
        "id": 100
      },
      "300": {
        "name": "Book 300",
        "id": 300
      },
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "500": {
        "name": "Medium 500",
        "id": 500
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      },
      "900": {
        "name": "Ultra-Bold 900",
        "id": 900
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans SC": {
    "name": "Noto Sans SC (Chinese Simplified)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanssc.css",
    "type": "google-ea-font",
    "id": "Noto Sans SC",
    "variants": {
      "100": {
        "name": "Ultra-Light 100",
        "id": 100
      },
      "300": {
        "name": "Book 300",
        "id": 300
      },
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "500": {
        "name": "Medium 500",
        "id": 500
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      },
      "900": {
        "name": "Ultra-Bold 900",
        "id": 900
      }
    },
    "category": "sans-serif"
  },
  "Noto Sans TC": {
    "name": "Noto Sans TC (Chinese Traditional)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/notosanstc.css",
    "type": "google-ea-font",
    "id": "Noto Sans TC",
    "variants": {
      "100": {
        "name": "Ultra-Light 100",
        "id": 100
      },
      "300": {
        "name": "Book 300",
        "id": 300
      },
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "500": {
        "name": "Medium 500",
        "id": 500
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      },
      "900": {
        "name": "Ultra-Bold 900",
        "id": 900
      }
    },
    "category": "sans-serif"
  },
 "Droid Sans Ethiopic": {
    "name": "Droid Sans Ethiopic (Ethiopic)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/droidsansethiopic.css",
    "type": "google-ea-font",
    "id": "Droid Sans Ethiopic",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  },
 "Droid Sans Tamil": {
    "name": "Droid Sans Tamil (Tamil)",
    "url": "\/\/fonts.googleapis.com\/earlyaccess\/droidsanstamil.css",
    "type": "google-ea-font",
    "id": "Droid Sans Tamil",
    "variants": {
      "400": {
        "name": "Normal 400",
        "id": 400
      },
      "700": {
        "name": "Bold 700",
        "id": 700
      }
    },
    "category": "sans-serif"
  }
  }',
	true
);
libs/better-framework/core/class-bf-query.php000064400000006607151214002430015254 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

if ( class_exists( 'BF_Query' ) ) {
	return;
}


/**
 *
 * Deprecated!
 *
 * Functions of this file was moved to BF/functions/query.php
 *
 */
class BF_Query {

	/**
	 * Deprecated!
	 *
	 * @return array
	 */
	public static function get_pages( $extra = array() ) {

		return bf_get_pages( $extra );
	}


	/**
	 * Deprecated!
	 *
	 * @return array
	 */
	public static function get_posts( $extra = array() ) {

		return bf_get_posts( $extra );
	}


	/**
	 * Deprecated!
	 *
	 * @return bool|string
	 */
	static function get_random_post_link( $echo = true ) {

		if ( $echo ) {
			echo bf_get_random_post_link( $echo ); // escaped before in generating
		} else {
			return bf_get_random_post_link( $echo );
		}
	}


	/**
	 * Deprecated!
	 *
	 * @return array
	 */
	public static function get_categories( $extra = array() ) {

		return bf_get_categories( $extra );
	}


	/**
	 * Deprecated!
	 *
	 * @return array
	 */
	public static function get_categories_by_slug( $extra = array() ) {

		return bf_get_categories_by_slug( $extra );
	}


	/**
	 * Deprecated!
	 *
	 * @return mixed
	 */
	public static function get_tags( $extra = array() ) {

		return bf_get_tags( $extra );
	}


	/**
	 * Deprecated!
	 *
	 * @return array
	 */
	public static function get_users( $extra = array(), $advanced_ouput = false ) {

		return bf_get_users( $extra, $advanced_ouput );
	}


	/**
	 * Deprecated!
	 *
	 * @return array
	 */
	public static function get_post_types( $extra = array() ) {

		return bf_get_post_types( $extra );
	}


	/**
	 * Deprecated!
	 *
	 * @return mixed
	 */
	public static function get_page_templates( $extra = array() ) {

		return bf_get_page_templates( $extra );
	}


	/**
	 * Deprecated!
	 *
	 * @return array
	 */
	public static function get_taxonomies( $extra = array() ) {

		return bf_get_taxonomies( $extra );
	}


	/**
	 * Deprecated!
	 *
	 * @return array
	 */
	public static function get_terms( $tax = 'category', $extra = array() ) {

		return bf_get_terms( $tax, $extra );
	}


	/**
	 * Deprecated!
	 *
	 * @return array
	 */
	public static function get_roles( $extra = array() ) {

		return bf_get_roles( $extra );
	}


	/**
	 * Deprecated!
	 *
	 * @return array
	 */
	public static function get_menus( $hide_empty = false ) {

		return bf_get_menus( $hide_empty );
	}


	/**
	 * Deprecated!
	 *
	 * @return bool|mixed
	 */
	public static function is_a_category( $id = null ) {

		return bf_is_a_category( $id );
	}


	/**
	 * Deprecated!
	 *
	 * @return bool|mixed
	 */
	public static function is_a_tag( $id = null ) {

		return bf_is_a_tag( $id );
	}


	/**
	 * Deprecated!
	 *
	 * @return array
	 */
	public static function get_rev_sliders() {

		return bf_get_rev_sliders();
	}
} // BF_Querylibs/better-framework/core/class-bf-block-generator.php000064400000011344151214002430017157 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Used for generating listing, blocks and other display related things
 */
class BF_Block_Generator {


	/**
	 * Contains data that used in listings
	 *
	 * @var array
	 */
	static protected $block_atts = array();


	/**
	 * Getter for block atts
	 *
	 * @param string $key
	 * @param string $default
	 *
	 * @return array
	 */
	public static function get_attr( $key = '', $default = '' ) {

		if ( empty( $key ) || ! isset( self::$block_atts[ $key ] ) ) {
			return $default;
		}

		return self::$block_atts[ $key ];
	}


	/**
	 * Setter for block_atts
	 *
	 * @param string $key
	 * @param string $value
	 */
	public static function set_attr( $key = '', $value = '' ) {

		if ( empty( $key ) ) {
			return;
		}

		self::$block_atts[ $key ] = $value;

	}


	/**
	 * Used For Removing Attr
	 *
	 * @param string $key
	 */
	public static function unset_attr( $key = '' ) {

		if ( empty( $key ) ) {
			return;
		}

		unset( self::$block_atts[ $key ] );

	}


	/**
	 * Clears all attributes that saved in $block_atts
	 */
	public static function clear_atts() {

		self::$block_atts = array();

	}


	/**
	 * Used For Finding Best Count For Multiple columns
	 *
	 * @param int $count_all
	 * @param int $columns
	 * @param int $current_column
	 */
	public static function set_attr_count_multi_column( $count_all = 0, $columns = 1, $current_column = 1 ) {

		if ( $count_all == 0 ) {
			return;
		}

		$count = floor( $count_all / $columns );

		$reminder = $count_all % $columns;

		if ( $reminder >= $current_column ) {
			$count ++;
		}

		self::set_attr( "count", $count );
	}


	/**
	 * Used For Specifying Count
	 */
	public static function set_attr_count( $count ) {

		self::set_attr( "count", $count );

	}


	/**
	 * Used for adding class to block
	 *
	 * @param $value
	 */
	public static function set_attr_class( $value ) {

		if ( isset( self::$block_atts['block-class'] ) ) {
			self::$block_atts['block-class'] .= ' ' . $value;
		} else {
			self::$block_atts['block-class'] = $value;
		}

	}


	/**
	 * Used for retrieving block class attr
	 *
	 * @param $add_this
	 *
	 * @return array|string
	 */
	public static function get_attr_class( $add_this = '' ) {

		if ( $add_this ) {
			return self::get_attr( 'block-class' ) . ' ' . $add_this;
		} else {
			return self::get_attr( 'block-class' );
		}

	}


	/**
	 * Used for specifying thumbnail size
	 *
	 * @param $value
	 */
	public static function set_attr_thumbnail_size( $value ) {

		self::$block_atts['thumbnail-size'] = $value;

	}


	/**
	 * Used for retrieving block class attr
	 *
	 * @param $default
	 *
	 * @return array|string
	 */
	public static function get_attr_thumbnail_size( $default = '' ) {

		return self::get_attr( 'thumbnail-size', $default );

	}


	/**
	 * Used for including block elements
	 *
	 * @param string $block
	 * @param bool   $echo
	 * @param bool   $load
	 *
	 * @return string
	 */
	public static function get_block( $block = '', $echo = true, $load = true ) {

		if ( empty( $block ) ) {
			return '';
		}

		$template = 'blocks/' . $block . '.php';

		if ( $echo ) {
			locate_template( $template, $load, false );
		} else {
			ob_start();
			locate_template( $template, $load, false );

			return ob_get_clean();
		}

	}


	/**
	 * Used for including menus
	 *
	 * @param       string $menu menu file id
	 * @param       bool   $echo
	 * @param       bool   $load
	 *
	 * @return      string
	 */
	public static function get_menu( $menu = '', $echo = true, $load = true ) {

		if ( empty( $menu ) ) {
			return '';
		}

		$template = 'blocks/menu/' . $menu . '.php';

		if ( $echo ) {
			locate_template( $template, $load, false );
		} else {
			ob_start();
			locate_template( $template, $load, false );

			return ob_get_clean();
		}

	}


	/**
	 * Generates bread crumb with BF Breadcrumb
	 *
	 * @param bool $echo
	 *
	 * @return bool|string
	 */
	public static function breadcrumb( $echo = true ) {

		$output = Better_Framework::breadcrumb()->generate( false );

		if ( $echo ) {
			echo $output; // escaped before in generating
		} else {
			return $output;
		}

	}

}
libs/better-framework/core/class-bf-admin-notices.php000064400000021621151214002430016632 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Handles all message showing in admin panel
 */
class BF_Admin_Notices {

	/**
	 * Store notice data to save in the database
	 * todo check and add custom location for pages
	 *
	 * @var array
	 */
	protected $notices_hook = array(
		'post-new.php' => 'edit_form_top',
		'post.php'     => 'edit_form_top',
	);


	/**
	 * @var mixed|void
	 */
	protected $notice_data;


	/**
	 * Flag to detect it should be save or not
	 *
	 * @var bool
	 */
	protected $should_save = false;


	function __construct() {

		$this->apply_notice_hook();

		add_action( 'shutdown', array( $this, 'save_notices' ), 999 );
		add_action( 'wp_ajax_bf-notice-dismiss', array( $this, 'ajax_dismiss_handler' ) );

		$this->notice_data = $this->get_notices();
	}


	protected function apply_notice_hook() {

		global $pagenow;

		$hook = isset( $this->notices_hook[ $pagenow ] ) ? $this->notices_hook[ $pagenow ] : 'admin_notices';
		add_action( $hook, array( $this, 'show_notice' ) );
	}


	/**
	 * Adds notice to showing queue
	 *
	 * @param array          $notice      array {
	 *
	 * @type string|callable $mg          Message Text
	 * @type string          $id          optional. for deferred type.notice unique id
	 * @type string          $product     optional. unique id to detect notice is belong to which product
	 * @type string          $state       optional. success|warning|danger - default:success
	 * @type string          $thumbnail   optional. thumbnail image url
	 * @type array           $class       optional. notice custom classes
	 * @type string          $type        optional. Notice type is one of the deferred|fixed. - default: deferred.
	 * @type array           $page        optional. display notice on specific page. its an array of $pagenow values
	 * @type bool            $dismissible optional. display close notice button - default:true
	 * }
	 *
	 * @return bool true on success or false on error.
	 */
	function add_notice( $notice ) {

		$notice = bf_merge_args( $notice, array(
			'type'        => 'deferred',
			'dismissible' => true,
			'id'          => false,
			'product'     => false,
			'state'       => 'success',
		) );

		if ( empty( $notice['msg'] ) ) {
			return false;
		}

		/**
		 * Empty id just allowed for deferred type.
		 */
		if ( $notice['type'] !== 'deferred' && empty( $notice['id'] ) ) {
			return false;
		}

		if ( empty( $notice['id'] ) ) {
			$notice['id'] = $this->generate_ID();
		}


		$this->notice_data[ $notice['id'] ] = apply_filters( 'better-framework/admin-notices/new', $notice );

		if ( $this->immediately_save() ) {
			return $this->update_notices( $this->notice_data );
		}

		$this->should_save = true;

		return true;
	}


	/**
	 * Remove a notice
	 *
	 * @param string|int|array $id notice unique id
	 *
	 * @return bool true on success or false on error
	 */
	function remove_notice( $id = null ) {

		if ( is_array( $id ) ) {
			$id = isset( $id['id'] ) ? $id['id'] : false;
		}
		if ( ! $id ) {
			return false;
		}

		$nt = &$this->notice_data;;

		if ( isset( $nt[ $id ] ) ) {

			unset( $nt[ $id ] );

			if ( $this->immediately_save() ) {
				return $this->update_notices( $nt );
			} else {

				unset( $this->notice_data[ $id ] );
				$this->should_save = true;

				return true;
			}
		}

		return false;
	} // remove_notice


	protected function immediately_save() {

		return did_action( 'admin_footer' ) ||
		       ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ||
		       ( defined( 'DOING_CRON' ) && DOING_CRON );
	}


	protected function generate_ID() {

		do {
			$id = mt_rand();
		} while( isset( $this->notice_data[ $id ] ) );

		return $id;
	}


	/**
	 * Callback: Shows notice
	 * Action  : admin_notices
	 */
	function show_notice() {

		if ( $notices = apply_filters( 'better-framework/admin-notices/show', $this->notice_data ) ) {

			foreach ( $notices as $notice ) {

				if ( ! bf_item_can_shown( $notice ) ) {
					continue;
				}

				if ( is_callable( $notice['msg'] ) ) {
					$message = call_user_func( $notice['msg'], $notice, $this );
				} elseif ( ! is_array( $notice['msg'] ) ) {
					$message = wpautop( $notice['msg'] );
				} else {
					$message = '';
				}

				if ( ! $message ) {
					continue;
				}

				$dismissible   = ! empty( $notice['dismissible'] );
				$has_thumbnail = ! empty( $notice['thumbnail'] ) && filter_var( $notice['thumbnail'], FILTER_VALIDATE_URL );

				$filter_class = str_replace( '.php', '', current_filter() );
				if ( ! isset( $notice['class'] ) || ! is_array( $notice['class'] ) ) {
					$notice['class'] = array();
				}
				$notice['class'][] = 'bf-notice';
				$notice['class'][] = 'bf-notice-' . sanitize_html_class( $filter_class );
				$notice['class'][] = sprintf( 'bf-notice-%s', $notice['type'] );

				if ( ! isset( $notice['class'] ) ) {
					$notice['class'] = array();
				}
				if ( $dismissible ) {
					$notice['class'][] = 'bf-notice-dismissible';
				}
				$notice['class'][] = $has_thumbnail ? 'bf-notice-has-thumbnail' : 'bf-notice-no-thumbnail';

				$notice['class'][] = 'bf-notice-' . $notice['state'];

				$attrs = '';

				if ( ! empty( $notice['show_all_label'] ) ) {
					$attrs .= sprintf( ' data-show-all="%s"', esc_attr( $notice['show_all_label'] ) );
				}

				if ( isset( $notice['show-all'] ) && ! $notice['show-all'] ) {
					$attrs .= ' data-show-all-enable="false"';
				}
				?>
				<div
						class="bf-notice-wrapper bf-notice-<?php echo esc_attr( $notice['id'] ) ?> wrap"<?php echo $attrs ?>>
					<div
							class="<?php echo esc_attr( implode( ' ', array_map( 'sanitize_html_class', $notice['class'] ) ) ); ?>">

						<div class="bf-notice-container">
							<?php
							if ( $has_thumbnail ) {
								printf( '<div class="bf-notice-thumbnail"><img src="%s" class="bf-notice-thumbnail-img"></div>', esc_html( $notice['thumbnail'] ) );
							}
							?>
							<div class="bf-notice-text-container">
								<div class="bf-notice-text">
									<?php
									echo $message;
									?>
								</div>
							</div>

							<button type="button" class="bf-notice-dismiss"
								<?php if ( $notice['type'] !== 'deferred' ) { ?>
									data-notice-token="<?php echo esc_attr( wp_create_nonce( 'notice-dismiss-' . $notice['id'] ) ) ?>"
									data-notice-id="<?php echo esc_attr( $notice['id'] ) ?>"
								<?php } ?>
							>
								<span
										class="screen-reader-text"><?php esc_html_e( 'Dismiss this notice.', 'better-studio' ); ?></span>
								<?php
								if ( isset( $notice['dismiss_label'] ) ) {
									echo $notice['dismiss_label'];
								}
								?>
							</button>
						</div>
					</div>
					<?php

					if ( $notice['type'] === 'deferred' ) {
						$this->remove_notice( $notice );
					}

					?>
				</div>
				<?php
			}
		}
	} // show_notice


	/**
	 * Set notices info in db
	 *
	 * @param array $notices
	 *
	 * @return bool true on success or false on failure.
	 */
	protected function update_notices( $notices ) {

		return update_option( 'bf_notices', $notices );
	}


	/**
	 * Get all notices
	 *
	 * @return array
	 */
	public function get_notices() {

		return get_option( 'bf_notices', array() );
	}


	/**
	 * Update notices storage  with given data
	 *
	 * @param array $notices
	 *
	 * @return bool true on success or false on failure
	 */
	public function set_notices( $notices ) {

		if ( is_array( $notices ) && $notices ) {
			return update_option( 'bf_notices', $notices );
		} elseif ( ! $notices ) {
			return delete_option( 'bf_notices' );
		}

		return false;
	}


	/**
	 * Callback: Save added notices in db
	 * Action  : admin_footer
	 */
	function save_notices() {

		if ( ! $this->should_save ) {
			return;
		}

		if ( is_array( $this->notice_data ) ) {
			update_option( 'bf_notices', $this->notice_data );
		} elseif ( $this->notice_data === false ) {
			delete_option( 'bf_notices' );
		}
	}


	/**
	 * Callback: close notice ajax request handler
	 * Action  : wp_ajax_bf-notice-dismiss
	 */
	public function ajax_dismiss_handler() {

		$required_params = array(
			'noticeId'    => '',
			'noticeToken' => '',
		);
		if ( array_diff_key( $required_params, $_REQUEST ) ) {

			return;
		}

		$id = &$_REQUEST['noticeId'];
		if ( ! wp_verify_nonce( $_REQUEST['noticeToken'], 'notice-dismiss-' . $id ) ) {
			wp_die( __( 'Security error occurred', 'better-studio' ) );
		}

		$this->remove_notice( $id );
	}
}
libs/better-framework/core/utilities/index.php000064400000000050151214002440015524 0ustar00<?php

// Let's show them we are better
libs/better-framework/core/utilities/IO/index.php000064400000000050151214002440016033 0ustar00<?php

// Let's show them we are better
libs/better-framework/core/utilities/IO/class-bf-htaccess-editor.php000064400000007032151214002440021504 0ustar00<?php

/**
 * Class BF_Htaccess_Editor
 *
 * @since 3.9.1
 */


/**
 * Class BF_Htaccess_Editor
 *
 * @package core/utilites/IO
 *
 * @since   3.9.1
 */
final class BF_Htaccess_Editor {

	const VERSION = '1.0.0';

	/**
	 * @var array
	 *
	 * @since 3.9.1
	 */
	protected $pointers = array();


	/**
	 * @var string
	 *
	 * @since 3.9.1
	 */
	protected $buffer;


	/**
	 * @var string
	 *
	 * @since 3.9.1
	 */
	protected $content;


	/**
	 * Initialize props
	 *
	 * @param string $content
	 * @param string $head_pointer
	 * @param string $tail_pointer
	 */
	public function init( $content, $head_pointer, $tail_pointer ) {

		$this->content  = $content;
		$this->pointers = array( $head_pointer, $tail_pointer );

		///
		/// Read content between pointers
		///

		if ( preg_match( $this->pointer_pattern(), $this->content, $match ) ) {

			$this->buffer = $match[2];

		} else {

			$this->buffer  = '';
			$this->content = sprintf( "%s\n%s\n\n%s\n", $this->content, $this->pointers[0], $this->pointers[1] );
		}
	}


	/**
	 * Remove everything between pointers.
	 *
	 * @since 3.9.1
	 */
	public function remove_context() {

		$this->content = preg_replace( $this->pointer_pattern(), '', $this->content );
	}


	/**
	 * Look for custom string.
	 *
	 * @param string $string
	 * @param bool   $limit_context search only in pointed context or whole content
	 *
	 * @since 3.9.1
	 * @return bool true whether found or false on failure.
	 */
	public function exists( $string, $limit_context = true ) {

		$regex = preg_quote( $string, '/' );
		$regex = preg_replace( '/\s+/', '\s+', trim( $regex ) );
		$regex = '\s*' . $regex . '(?:\b|\n+)';

		return (bool) preg_match( "/$regex/i", $limit_context ? $this->buffer : $this->content );
	}


	/**
	 * @param string $string
	 *
	 * @since 1.0.0
	 */
	public function remove( $string ) {

		$config = preg_quote( $string, '/' );
		$config = preg_replace( '/\s+/', '\s+', $config );
		$regex  = '\b' . $config . '(?:\b|\n+)';

		$this->buffer = preg_replace( "/$regex/i", '', $this->buffer );
	}


	/**
	 * @param string $string
	 *
	 * @since 3.9.1
	 */
	public function append( $string ) {

		$this->buffer .= "\n$string";
	}


	/**
	 * Wrap string between IfModule mod_rewrite condition.
	 *
	 * @param string $string
	 */
	public function append_inside_condition( $string ) {


		if ( preg_match( '/(\<\s*IfModule\s+mod_rewrite.c\s*\>.*?)\s*(\<\s*\/\s*IfModule\s*\>)(.*?)/is', $this->buffer, $matches ) ) {

			$this->buffer = $matches[1] . "\n$string\n" . $matches[2];

		} else {

			$this->buffer .= "\n<IfModule mod_rewrite.c>\n$string\n</IfModule>";
		}
	}


	/**
	 * Apply changes to htaccess contents.
	 *
	 * @since 3.9.1
	 * @return string changed string on success.
	 */
	public function apply() {

		$replacement = sprintf( "\$1\n %s \n\$3", $this->buffer );

		$this->content = preg_replace( $this->pointer_pattern(), $replacement, $this->content );

		return $this->content;
	}


	/**
	 * @param string $string
	 * @param string $regex_quote
	 *
	 * @since 3.9.1
	 * @return string
	 */
	public static function normalize_string( $string, $regex_quote = '/' ) {

		if ( $regex_quote ) {
			$string = preg_quote( $string, $regex_quote );
		}

		$string = preg_replace( '/\s+/', '\s+', $string );

		return $string;
	}


	/**
	 * @access private
	 *
	 * @since  3.9.1
	 * @return string
	 */
	protected function pointer_pattern() {

		$pattern = sprintf( '(%s)', self::normalize_string( $this->pointers[0] ) );
		$pattern .= '\s*(.*?)\s*';
		$pattern .= sprintf( '(%s)', self::normalize_string( $this->pointers[1] ) );

		return "/$pattern/si";
	}
}
libs/better-framework/core/custom-css/class-bf-back-end-css.php000064400000005637151214002440020444 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * BF automatic custom css generator
 */
class BF_Back_End_CSS extends BF_Custom_CSS {

	/**
	 * prepare functionality
	 */
	function __construct() {

		if ( is_admin() ) {
			add_action( 'admin_footer', array( $this, 'display' ) );
		}

		add_action( 'profile_update', array( $this, 'clear_cache' ) );

	}


	/**
	 * clear cache (transient)
	 */
	public static function clear_cache() {

		delete_transient( '__better_framework__backend_css' );

	}


	/**
	 * Load all fields
	 */
	function load_all_fields() {

		// Load from cache if available
		if ( true == ( $cached_fields = get_transient( '__better_framework__backend_css' ) ) ) {
			$this->fields = array_merge( $this->fields, $cached_fields );

			return;
		} else {
			// Filter custom css code
			$cached_fields = apply_filters( 'better-framework/css/backend', $this->fields );
		}

		Better_Framework::factory( 'color' );

		foreach ( $cached_fields as $key => $field ) {

			if ( preg_match( '/(?=\d.*)-*\d*/', $cached_fields[ $key ]['value'], $chanage ) ) {
				$color = $chanage[0];
			}
			if ( preg_match( '/(?<=-\d)[-|+]\d*/', $cached_fields[ $key ]['value'], $chanage ) ) {
				$color_change = $chanage[0];
			}


			if ( ! isset( $color ) && ! isset( $color_change ) ) {
				continue;
			}

			if ( isset( $color ) && ! isset( $color_change ) ) {
				$cached_fields[ $key ]['value'] = BF_Color::get_user_profile_color( 'color-' . $color );
			}

			if ( isset( $color ) && isset( $color_change ) ) {
				$cached_fields[ $key ]['value'] = BF_Color::change_color( BF_Color::get_user_profile_color( 'color-' . $color ), intval( $color_change ) );
			}

			unset( $color );
			unset( $color_change );
		}

		if ( bf_count( $cached_fields ) ) {
			array_unshift( $cached_fields,
				array(
					'value' => 'c',
					'type'  => 'comment',
					array(
						'comment' => " BetterFramework Custom CSS For Admin "
					)
				) );
			$this->fields = array_merge( $this->fields, $cached_fields );

		}
		set_transient( '__better_framework__backend_css', $cached_fields );

	}


	/**
	 * display css
	 */
	function display() {

		$this->load_all_fields();

		$final_css = $this->render_css();

		bf_add_css( $this->render_fonts() . $final_css, true, true );

	}

}libs/better-framework/core/custom-css/class-bf-front-end-css.php000064400000064524151214002440020674 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * BF automatic custom css generator
 */
class BF_Front_End_CSS extends BF_Custom_CSS {


	/**
	 * Temp
	 *
	 * @var
	 */
	var $final_css;

	/**
	 * a Marker to determinate a is field value empty
	 *
	 * @example
	 *
	 *
	 *  $fields['footer_line_top_color'] = array(
	 *   'css'                  => array(
	 *     'callback'            => function() {
	 *       if ( $value === BF_Front_End_CSS::$empty_value_marker || empty( $value )  ) {
	 *            // VALUE IS EMPTY
	 *       } else {
	 *           // VALUE IS NOT EMPTY
	 *       }
	 *      },
	 *     'force-callback-call' => true,
	 *     ),
	 *  );
	 *
	 * @var string
	 */
	static $empty_value_marker = 'EMPTY-VALUE';


	/**
	 * prepare functionality
	 */
	function __construct() {

		// register custom css
		add_action( 'wp_enqueue_scripts', array( $this, 'wp_enqueue_scripts' ), 99 );
		add_action( 'wp_enqueue_scripts', array( $this, 'append_custom_css' ), 99 );

		add_action( 'enqueue_block_editor_assets', array( $this, 'wp_enqueue_scripts' ), 99 );
		add_action( 'enqueue_block_editor_assets', array( $this, 'append_custom_css' ), 99 );

		// Callbacks function for clearing cache when widgets changed
		add_filter( 'widget_update_callback', array( $this, 'clear_widgets_cache_on_update' ), 10, 3 );
		add_action( 'sidebar_admin_setup', array( $this, 'clear_widgets_cache_on_add_delete' ) );

		// Callbacks functions for clearing cache when terms changed
		add_filter( 'create_term', array( $this, 'clear_terms_cache_on_update' ) );
		add_filter( 'edit_term', array( $this, 'clear_terms_cache_on_update' ) );
		add_filter( 'delete_term', array( $this, 'clear_terms_cache_on_update' ) );

		// Callback function for clearing cache when Menus updated
		add_action( 'wp_update_nav_menu', array( $this, 'clear_menus_cache_on_update' ) );

	}


	/**
	 * Callback: Register BF custom css codes for theme specified fields
	 *
	 * action: wp_enqueue_scripts
	 */
	function wp_enqueue_scripts() {

		$this->final_css = $this->prepare_final_css();

		// Adds fonts to page
		if ( isset( $this->final_css['fonts'] ) && ! empty( $this->final_css['fonts'] ) ) {
			foreach ( (array) $this->final_css['fonts'] as $key => $font ) {
				if ( $key == 0 ) {
					wp_enqueue_style( 'better-framework-main-fonts', $font, array(), null );
				} else {
					wp_enqueue_style( 'better-framework-font-' . $key, $font, array(), null );
				}
			}
		}

	}


	/**
	 * Callback: Print auto generated css in header
	 *
	 * Action: wp_head
	 */
	function append_custom_css() {

		bf_add_style_file( self::get_css_version(), array( $this, 'get_final_css' ) );

		if ( bf_is_doing_ajax( 'fetch-mce-view-shortcode' ) ) {
			bf_enqueue_tinymce_style( 'extra', self::get_css_version() );
		}

		// clear memory
		$this->final_css = '';
	}


	/**
	 * Action callback: Output Custom CSS
	 */
	public function global_custom_css() {

		// just when custom css requested
		if ( empty( $_GET['better_framework_css'] ) OR intval( $_GET['better_framework_css'] ) != 1 ) {
			return;
		}

		$this->display();

		exit;
	}


	/**
	 * clear cache (transient)
	 *
	 * @param string $type
	 */
	public static function clear_cache( $type = 'all' ) {

		global $wpdb;

		switch ( $type ) {

			case 'widgets':
				delete_transient( '__better_framework__widgets_css' );
				self::clear_cache( 'final' );
				break;

			case 'panel':
				$wpdb->query( $wpdb->prepare( "
                      DELETE
                      FROM $wpdb->options
                      WHERE option_name LIKE %s
                  ", '_transient___better_framework__panel_css%' ) );
				self::clear_cache( 'final' );
				break;

			case 'menu':
				delete_transient( '__better_framework__menu_css' );
				self::clear_cache( 'final' );
				break;

			case 'terms':
				delete_transient( '__better_framework__terms_css' );
				self::clear_cache( 'final' );
				break;

			case 'final':
				$wpdb->query( $wpdb->prepare( "
                      DELETE
                      FROM $wpdb->options
                      WHERE option_name LIKE %s
                  ", '_transient___better_framework__final_fe_css%' ) );
				$wpdb->query( $wpdb->prepare( "
                      DELETE
                      FROM $wpdb->options
                      WHERE option_name LIKE %s
                  ", '_transient___better_framework__final_fe_css_version%' ) );

				break;


			case 'all':
				delete_transient( '__better_framework__widgets_css' );
				self::clear_cache( 'panel' );
				delete_transient( '__better_framework__menu_css' );
				delete_transient( '__better_framework__terms_css' );
				self::clear_cache( 'final' );

		}

	}


	/**
	 * Clear terms cache when 1 term added, updated or deleted
	 */
	function clear_terms_cache_on_update() {

		$this->clear_cache( 'terms' );

	}


	/**
	 * Clear menu cache when 1 menu updated
	 *
	 * @param $nav_menu_selected_id
	 */
	function clear_menus_cache_on_update( $nav_menu_selected_id ) {

		$this->clear_cache( 'menu' );

	}


	/**
	 * Clear widgets cache when update changed
	 *
	 * @param   $instance
	 * @param   $new_instance
	 * @param   $old_instance
	 *
	 * @return  mixed
	 */
	function clear_widgets_cache_on_update( $instance, $new_instance, $old_instance ) {

		self::clear_cache( 'widgets' );

		return $instance;
	}


	/**
	 * Clear widgets cache when add new or delete widget
	 */
	function clear_widgets_cache_on_add_delete() {

		if ( 'post' == strtolower( $_SERVER['REQUEST_METHOD'] ) ) {

			if ( isset( $_POST['delete_widget'] ) && ( 1 === (int) $_POST['delete_widget'] ) ) {
				if ( 1 === (int) $_POST['delete_widget'] ) {
					self::clear_cache( 'widgets' );
				}
			} elseif ( isset( $_POST['add_new'] ) && ( 1 === (int) $_POST['add_new'] ) ) {
				if ( 1 === (int) $_POST['add_new'] ) {
					self::clear_cache( 'widgets' );
				}
			}

		}
	}


	/**
	 * display css
	 */
	function display() {

		status_header( 200 );
		header( "Content-type: text/css; charset: utf-8" );

		echo $this->get_final_css();
	}


	public function get_final_css() {

		$final_fe_css = $this->prepare_final_css();

		return $final_fe_css['css']; // escaped before in generating
	}


	/**
	 * Load all fields
	 */
	function load_all_fields() {

		/**
		 * Filter custom css code
		 *
		 * @since 1.0.0
		 *
		 * @param array $fields All active fields that should be rendered
		 */
		$this->fields = apply_filters( 'better-framework/css/main/fields', $this->fields );

		// load and prepare panel css
		$this->load_panel_fields();

		// Load and prepare widgets css
		$this->load_widget_fields();

		// Load and prepare menus css
		$this->load_menus_css();

		// Load and prepare taxonomies css
		$this->load_terms_css();

	}


	/**
	 * Get  frontend css version number
	 *
	 * @return mixed none empty string on success, mixed otherwise
	 */
	public static function get_css_version() {

		$lang = bf_get_current_language_option_code();

		return get_transient( '__better_framework__final_fe_css_version' . $lang );
	}


	/**
	 * Set frontend css version number
	 *
	 * @param string $version version number
	 *
	 * @return bool False if value was not set and true if value was set.
	 */
	public function set_css_version( $version ) {

		$lang = bf_get_current_language_option_code();

		return set_transient( '__better_framework__final_fe_css_version' . $lang, $version );
	}


	/**
	 * Prepare final CSS
	 */
	function prepare_final_css() {

		$lang = bf_get_current_language_option_code();

		// Checks both theme version number and last update date for loading again fields
		if ( ( $final_css_version = self::get_css_version() ) !== false ) {

			$final_css_version = substr( $final_css_version, 0, strrpos( $final_css_version, '-' ) );

			if ( $final_css_version != Better_Framework::theme()->get( 'Version' ) ) {
				$final_css_version = true;
			} else {
				$final_css_version = false;
			}
		} else {
			$final_css_version = true;
		}

		if ( $final_css_version || ( false == ( $final_css = get_transient( '__better_framework__final_fe_css' . $lang ) ) ) ) {
			$this->load_all_fields();

			$final_css        = array();
			$final_css['css'] = $this->render_css();

			// Include theme Fonts to top
			$theme_fonts = $this->render_fonts( 'theme-fonts' );
			if ( ! empty( $theme_fonts ) ) {
				$theme_fonts      = '/* ' . __( 'Theme Fonts', 'better-studio' ) . ' */' . $theme_fonts . "\n";
				$final_css['css'] = $theme_fonts . $final_css['css'];
			}

			// Include custom Fonts to top
			$custom_fonts = $this->render_fonts( 'custom-fonts' );
			if ( ! empty( $custom_fonts ) ) {
				$custom_fonts     = '/* ' . __( 'Custom Fonts', 'better-studio' ) . ' */' . $custom_fonts . "\n";
				$final_css['css'] = $custom_fonts . $final_css['css'];
			}

			$final_css['fonts'] = (array) $this->render_fonts( 'google-fonts' );

			$final_css['fonts'] = array_merge( $final_css['fonts'], (array) $this->render_fonts( 'google-ea-fonts' ) );

			$final_css['fonts'] = array_filter( $final_css['fonts'] );

			$final_css = apply_filters( 'better-framework/css/final', $final_css );

			set_transient( '__better_framework__final_fe_css' . $lang, $final_css );

			$this->set_css_version( Better_Framework::theme()->get( 'Version' ) . '-' . time() );
		}

		return $final_css;
	}


	/**
	 * Load all taxonomies custom css and add them to queue
	 */
	function load_terms_css() {

		$lang = bf_get_current_language_option_code();

		//load from cache if available
		if ( true == ( $cached_fields = get_transient( '__better_framework__terms_css' . $lang ) ) ) {
			$this->fields = array_merge( $this->fields, $cached_fields );

			return;
		} else {
			$cached_fields = array();
		}

		// init
		if ( ! class_exists( 'BF_Taxonomy_Core' ) ) {
			Better_Framework()->taxonomy_meta();
		}

		// Find taxonomies that have field
		foreach ( BF_Taxonomy_Core::$metabox as $metabox_id => $metabox ) {

			if ( ! isset( $metabox['css'] ) || ! $metabox['css'] ) {
				continue;
			}

			$metabox_css = BF_Taxonomy_Core::get_metabox_css( $metabox_id );

			if ( empty( $metabox_css ) || ! is_array( $metabox_css ) ) {
				continue;
			}

			if ( isset( $metabox['panel-id'] ) ) {
				$std_id = Better_Framework::options()->get_panel_std_id( $metabox['panel-id'] );
				$css_id = $this->get_css_id( $metabox['panel-id'] );
			} else {
				$std_id = 'std';
				$css_id = 'css';
			}

			$metabox_config = BF_Taxonomy_Core::get_metabox_config( $metabox_id );

			// Iterate each taxonomy in css fields
			foreach ( (array) $metabox_config['taxonomies'] as $tax_key ) {

				// load all terms of taxonomy
				$all_tax_terms = get_terms( $tax_key, array( 'fields' => 'all' ) );

				// each term of taxonomy
				foreach ( $all_tax_terms as $term ) {

					if ( ! is_a( $term, 'WP_Term' ) ) {
						continue;
					}

					// each taxonomy custom field
					foreach ( $metabox_css as $field_option_key => $field_option_value ) {

						// continue when haven't css field
						if ( ! isset( $field_option_value[ $css_id ] ) ) {
							if ( ! isset( $field_option_value['css'] ) ) {
								continue;
							}
						}

						// continue if haven't saved value for this field
						if ( ! ( $term_value = bf_get_term_meta( $field_option_key, $term->term_id ) ) ) {
							continue;
						}

						// if value saved and is difference than default value
						if ( isset( $field_option_value[ $std_id ] ) && $term_value == $field_option_value[ $std_id ] ) {
							continue;
						} elseif ( isset( $field_option_value['std'] ) && $term_value == $field_option_value['std'] ) {
							continue;
						}

						if ( isset( $field_option_value[ $css_id ] ) ) {
							$_temp_css_field = $field_option_value[ $css_id ];
						} elseif ( isset( $field_option_value['css'] ) ) {
							$_temp_css_field = $field_option_value['css'];
						} else {
							continue;
						}

						// prepare selectors
						foreach ( $_temp_css_field as $_temp_css_field_key => $_temp_css_field_value ) {

							// prepare selectors
							if ( isset( $_temp_css_field[ $_temp_css_field_key ]['selector'] ) && is_array( $_temp_css_field[ $_temp_css_field_key ]['selector'] ) ) {

								foreach ( $_temp_css_field[ $_temp_css_field_key ]['selector'] as $selector_key => $selector ) {
									$_temp_css_field[ $_temp_css_field_key ]['selector'][ $selector_key ] = str_replace(
										array( '%%id%%', '%%slug%%' ),
										array( $term->term_id, $term->slug ),
										$_temp_css_field[ $_temp_css_field_key ]['selector'][ $selector_key ]
									);
								}

							} elseif ( isset( $_temp_css_field[ $_temp_css_field_key ]['selector'] ) ) {
								$_temp_css_field[ $_temp_css_field_key ]['selector'] = str_replace(
									array( '%%id%%', '%%slug%%' ),
									array( $term->term_id, $term->slug ),
									$_temp_css_field[ $_temp_css_field_key ]['selector']
								);
							}

						}

						// Ads current term ID to list
						$_temp_css_field['_TERM_ID'] = $term->term_id;

						if ( is_array( $term_value ) ) {
							$_temp_css_field['value'] = $term_value;
						} else {
							$_temp_css_field['value'] = stripcslashes( $term_value );
						}

						$cached_fields[] = $_temp_css_field;

					}

				}

			}

		}

		if ( $cached_fields ) {
			array_unshift( $cached_fields, array(
				'value' => 'c',
				'type'  => 'comment',
				array(
					'comment' => ' ' . __( 'Terms Custom CSS', 'better-studio' ) . ' '
				)
			) );
			array_unshift( $cached_fields, array( 'newline' => true ) );
			array_unshift( $cached_fields, array( 'newline' => true ) );
			$this->fields = array_merge( $this->fields, $cached_fields );
		}
		set_transient( '__better_framework__terms_css' . $lang, $cached_fields );
	}


	/**
	 * Load Menus fields and add theme to queue
	 */
	function load_menus_css() {

		$lang = bf_get_current_language_option_code();

		// Load from cache if available
		if ( true == ( $cached_fields = get_transient( '__better_framework__menu_css' . $lang ) ) ) {
			$this->fields = array_merge( $this->fields, $cached_fields );

			return;
		} else {
			$cached_fields = array();
		}

		if ( ! class_exists( 'BF_Menus' ) ) {
			Better_Framework::factory( 'better-menu' );
		}

		$menu_fields = BF_Menus::get_fields();

		// each registered navigation menu locations that a menu assigned to it
		// TODO menus that have not assigned to location but used in widgets not included in this! fix this
		foreach ( ( (array) get_nav_menu_locations() ) as $menu_id => $menu_slug ) {

			if ( is_null( $menu_slug ) ) {
				continue;
			}

			// each item of menu
			foreach ( (array) wp_get_nav_menu_items( $menu_slug ) as $menu_item ) {

				// all fields that registered to menus
				foreach ( (array) $menu_fields as $field_id => $field ) {

					// prepare std and css id
					if ( isset( $field['panel-id'] ) && isset( BF_Options::$panels[ $field['panel-id'] ]['style'] ) ) {

						$current_style_of_panel = get_option( $field['panel-id'] . '_current_style' );

						if ( $current_style_of_panel == 'default' ) {
							$std_id = 'std';
							$css_id = 'css';
						} else {
							$std_id = 'std-' . $current_style_of_panel;
							$css_id = 'css-' . $current_style_of_panel;
						}
					} else {

						$std_id = 'std';
						$css_id = 'css';

					}

					// just fields with css
					if ( ! isset( $field[ $css_id ] ) ) {
						if ( ! isset( $field['css'] ) ) {
							continue;
						}
					}

					if ( ! isset( $menu_item->{$field_id} ) ) {
						continue;
					}

					// if item has key and value is difference than default color
					if ( isset( $field[ $std_id ] ) && $menu_item->{$field_id} == $field[ $std_id ] ) {
						continue;
					} elseif ( isset( $field['std'] ) && $menu_item->{$field_id} == $field['std'] ) {
						continue;
					}

					if ( empty( $menu_item->{$field_id} ) ) {
						continue;
					}

					if ( isset( $field[ $css_id ] ) ) {
						$_temp_css_field = $field[ $css_id ];
					} else {
						$_temp_css_field = $field['css'];
					}

					// prepare selectors
					foreach ( $_temp_css_field as $_temp_css_field_key => $_temp_css_field_value ) {

						// prepare selectors
						if ( is_array( $_temp_css_field[ $_temp_css_field_key ]['selector'] ) ) {
							foreach ( $_temp_css_field[ $_temp_css_field_key ]['selector'] as $selector_key => $selector ) {

								if ( strpos( $selector, '%%id%%' ) !== false ) {
									$_temp_css_field[ $_temp_css_field_key ]['selector'][ $selector_key ] = str_replace( '%%id%%', '#menu-item-' . $menu_item->ID, $_temp_css_field[ $_temp_css_field_key ]['selector'][ $selector_key ] );
								}

								if ( strpos( $selector, '%%class%%' ) !== false ) {
									$_temp_css_field[ $_temp_css_field_key ]['selector'][ $selector_key ] = str_replace( '%%class%%', '.menu-item-' . $menu_item->ID, $_temp_css_field[ $_temp_css_field_key ]['selector'][ $selector_key ] );
								}

							}

						} else {
							$_temp_css_field[ $_temp_css_field_key ]['selector'] = str_replace( '%%class%%', '.menu-item-' . $menu_item->ID, $_temp_css_field[ $_temp_css_field_key ]['selector'] );
							$_temp_css_field[ $_temp_css_field_key ]['selector'] = str_replace( '%%id%%', '#menu-item-' . $menu_item->ID, $_temp_css_field[ $_temp_css_field_key ]['selector'] );
						}

					}

					$_temp_css_field['value'] = $menu_item->{$field_id};

					$cached_fields[] = $_temp_css_field;

				}
			}
		}

		if ( $cached_fields ) {
			array_unshift( $cached_fields, array(
				'value' => 'c',
				'type'  => 'comment',
				array(
					'comment' => ' ' . __( 'Menus Custom CSS', 'better-studio' ) . ' '
				)
			) );
			array_unshift( $cached_fields, array( 'newline' => true ) );
			array_unshift( $cached_fields, array( 'newline' => true ) );
			$this->fields = array_merge( $this->fields, $cached_fields );
		}
		set_transient( '__better_framework__menu_css' . $lang, $cached_fields );

	}


	/**
	 * Load Panel options fields and add them to queue
	 *
	 */
	function load_panel_fields() {

		$_lang = bf_get_current_language_option_code();

		//load from cache if available
		if ( true == ( $cached_fields = get_transient( '__better_framework__panel_css' . $_lang ) ) ) {
			$this->fields = array_merge( $this->fields, $cached_fields );

			return;
		} else {
			$cached_fields = array();
		}


		// iterates all panels for css and adds them to css render list
		foreach ( BF_Options::$panels as $panel_id => $panel_value ) {

			// Prepare std id
			$std_id    = BF_Options::get_panel_std_id( $panel_id );
			$css_id    = $this->get_css_id( $panel_id );
			$panel_std = BF_Options::get_panel_std( $panel_id );

			// check each option field
			foreach ( (array) BF_Options::load_panel_css( $panel_id ) as $field_id => $field ) {

				// must have css field
				if ( ! isset( $field[ $css_id ] ) ) {
					if ( ! isset( $field['css'] ) ) {
						continue;
					}
				}

				$value             = bf_get_option( $field_id, $panel_id );
				$is_callback_force = ! empty( $field['css']['force-callback-call'] );

				// if field hasn't value

				if ( $value === false || $value == '' ) {
					if ( ! $is_callback_force ) {
						continue;
					}
				}

				if ( $is_callback_force && empty( $value ) ) {
					$value = self::$empty_value_marker;
				}

				if ( isset( $panel_std[ $field_id ][ $std_id ] ) ) {
					if ( $value == $panel_std[ $field_id ][ $std_id ] ) {
						if ( ! isset( $field['css-echo-default'] ) || ! $field['css-echo-default'] ) {
							continue;
						}
					}
				} elseif ( isset( $panel_std[ $field_id ]['std'] ) ) {
					if ( $value == $panel_std[ $field_id ]['std'] ) {
						if ( ! isset( $field['css-echo-default'] ) || ! $field['css-echo-default'] ) {
							continue;
						}
					}
				}

				if ( isset( $field[ $css_id ] ) ) {
					$_field = $field[ $css_id ];
				} else {
					$_field = $field['css'];
				}

				$_field['value'] = $value;

				$cached_fields[] = $_field;

			}
		}

		if ( $cached_fields ) {
			array_unshift( $cached_fields, array(
				'value' => 'c',
				'type'  => 'comment',
				array(
					'comment' => ' ' . __( 'Panel Options Custom CSS', 'better-studio' ) . ' '
				)
			) );
			$this->fields = array_merge( $this->fields, $cached_fields );

		}
		set_transient( '__better_framework__panel_css' . $_lang, $cached_fields );
	}


	/**
	 *  Load widget fields and add to queue
	 */
	function load_widget_fields() {

		$lang = bf_get_current_language_option_code();

		// load from cache if available
		if ( true == ( $cached_widgets_fields = get_transient( '__better_framework__widgets_css' . $lang ) ) ) {
			$this->fields = array_merge( $this->fields, $cached_widgets_fields );

			return;
		} else {
			$cached_widgets_fields = array();
		}

		// TODO: Refactor this code to better if you can :D

		// filter widgets css fields
		$fields = apply_filters( 'better-framework/css/widgets', array() );

		// if fields set
		if ( ! is_array( $fields ) || bf_count( $fields ) < 1 ) {
			return;
		}

		// load all active sidebars
		if ( ! $sidebars = get_option( 'sidebars_widgets' ) ) {

			$sidebars = array();
		}

		// remove inactive sidebar from all sidebars list
		unset( $sidebars['wp_inactive_widgets'] );
		unset( $sidebars['array_version'] );


		foreach ( (array) $sidebars as $sidebar_key => $sidebar_value ) {

			if ( strpos( $sidebar_key, 'orphaned_widgets' ) !== false ) {
				continue;
			}

			// is sidebar or active sidebar
			if ( ! is_active_sidebar( $sidebar_key ) ) {
				continue;
			}

			foreach ( (array) $sidebar_value as $widget ) {

				// remove widget number from id
				if ( preg_match( '/\-\d+$/i', $widget ) ) {
					$widget_name = preg_replace( '/\-\d+$/i', '', $widget );
				} else {
					$widget_name = $widget;
				}

				preg_match( '/\-(\d+)$/i', $widget, $widget_id );

				if ( empty( $widget_id ) ) {
					continue;
				}

				$widget_id = $widget_id[1];

				// get active instances of this widget
				$sidebar_widgets = get_option( 'widget_' . $widget_name );

				if ( ! isset( $sidebar_widgets[ $widget_id ] ) ) {
					continue;
				}
				// if widget just is in use but "not active"
				$_is_widget_active = @is_active_widget( false, $widget, $widget_name ) == '';
				if ( $_is_widget_active || strpos( $_is_widget_active, 'orphaned_widgets' ) !== false ) {
					continue;
				}

				// check each field for css fields
				foreach ( (array) $sidebar_widgets[ $widget_id ] as $widget_field_key => $widget_field_value ) {

					// check each filtered css fields
					foreach ( (array) $fields as $css_field ) {

						// if is a css field then prepare field and add to final fields list
						if ( $widget_field_key == $css_field['field'] ) {

							// print default or not
							if ( empty( $css_field['css-echo-default'] ) ) {

								// skip when value is equal to default!
								if ( BF_Widgets_General_Fields::is_valid_field( $widget_field_key ) ) {
									if ( BF_Widgets_General_Fields::get_default_value( $widget_field_key ) == $widget_field_value ) {
										continue;
									}
								} elseif ( isset( $css_field['default_value'] ) && $css_field['default_value'] == $widget_field_value ) {
									continue;
								}
							}


							$_temp_css_field = $css_field;

							// move callback needed field t block level
							if ( ! empty( $_temp_css_field['callback']['_NEEDED_WIDGET_FIELDS'] ) ) {
								$_temp_css_field['_NEEDED_WIDGET_FIELDS'] = $_temp_css_field['callback']['_NEEDED_WIDGET_FIELDS'];
							}

							// prepare selectors: replace "%%widget-id%%" with widget id
							foreach ( (array) $_temp_css_field as $_temp_field_key => $temp_field_val ) {

								//
								// Used to say value of a field to another field in CSS
								// Use Case: using it in CSS callbacks to generate smaller CSS only for 1 widget title style!
								//
								if ( ! empty( $_temp_css_field['_NEEDED_WIDGET_FIELDS'] ) ) {

									foreach ( (array) $_temp_css_field['_NEEDED_WIDGET_FIELDS'] as $_field ) {

										$value = isset( $sidebar_widgets[ $widget_id ][ $_field ] ) ? $sidebar_widgets[ $widget_id ][ $_field ] : '';

										$_temp_css_field['_NEEDED_WIDGET_VALUE'][ $_field ] = $value;

										// add value to callback level if needed
										if ( isset( $_temp_css_field['callback'] ) ) {
											$_temp_css_field['callback']['_NEEDED_WIDGET_VALUE'][ $_field ] = $value;
										}
									}
								}


								// skip "value" and "field" fields
								if ( ! is_int( $_temp_field_key ) ) {
									continue;
								}

								foreach ( (array) $_temp_css_field[ $_temp_field_key ] as $_t_key => $_t_value ) {

									// if is selector field in array
									if ( $_t_key != 'selector' ) {
										continue;
									}

									if ( ! isset( $_temp_css_field[ $_temp_field_key ]['selector'] ) ) {
										continue;
									}

									if ( is_array( $_temp_css_field[ $_temp_field_key ]['selector'] ) ) {
										foreach ( $_temp_css_field[ $_temp_field_key ]['selector'] as $selector_key => $selector ) {
											if ( strpos( $selector, '%%widget-id%%' ) !== false ) {
												$_temp_css_field[ $_temp_field_key ]['selector'][ $selector_key ] = str_replace( '%%widget-id%%', '#' . $widget, $_temp_css_field[ $_temp_field_key ]['selector'][ $selector_key ] );
											}
										}

									} else {
										$_temp_css_field[ $_temp_field_key ]['selector'] = str_replace( '%%widget-id%%', '#' . $widget, $_temp_css_field[ $_temp_field_key ]['selector'] );
									}

								}

							}


							$_temp_css_field['value'] = $widget_field_value;

							// Ads current widget ID to list
							$_temp_css_field['_WIDGET_ID']   = '#' . $widget;
							$_temp_css_field['_SIDEBAR_ID_'] = $sidebar_key;

							$cached_widgets_fields[] = $_temp_css_field;
						}
					}
				}
			}
		}

		if ( $cached_widgets_fields ) {
			array_unshift( $cached_widgets_fields, array(
				'value' => 'c',
				'type'  => 'comment',
				array(
					'comment' => ' ' . __( 'Widgets Custom CSS', 'better-studio' ) . ' '
				)
			) );
			array_unshift( $cached_widgets_fields, array( 'newline' => true ) );
			array_unshift( $cached_widgets_fields, array( 'newline' => true ) );
			$this->fields = array_merge( $this->fields, $cached_widgets_fields );
		}

		set_transient( '__better_framework__widgets_css' . $lang, $cached_widgets_fields );
	}

}
libs/better-framework/core/custom-css/class-bf-pages-css.php000064400000012025151214002440020064 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * BF automatic custom css generator
 */
class BF_Pages_CSS extends BF_Custom_CSS {

	/**
	 * Contains Current Page or Post ID
	 *
	 * @var int
	 */
	public $post_id = 0;


	/**
	 * prepare functionality
	 */
	function __construct() {

		// Clear Cache Callbacks
		add_action( 'delete_post', array( $this, 'clear_cache' ) );
		add_action( 'untrash_post', array( $this, 'clear_cache' ) );
		add_action( 'save_post', array( $this, 'clear_cache' ) );

		// Print Page Custom CSS
		add_action( 'wp_head', array( $this, 'wp_head' ), 99 );

	}


	/**
	 * Callback: Print auto generated css in header
	 *
	 * Action: wp_head
	 */
	function wp_head() {

		// Only in Post Types Single Page and Pages
		if ( ! is_singular() ) {
			return;
		}

		$this->load_post_fields( get_the_ID() );

		if ( ! empty( $this->fields ) ) {
			bf_add_css( $this->render_css(), true, true );
		}

	} // wp_head


	/**
	 * Clear cache (transient)
	 *
	 * - Action Callback
	 */
	public function clear_cache( $post_ID ) {

		delete_post_meta( $post_ID, '_bf_post_css_' . $post_ID );
		delete_post_meta( $post_ID, '_bf_post_css_cached_' . $post_ID );
	}


	/**
	 * Load all fields
	 */
	function load_all_fields() {

		// Filter Custom CSS Code For Pages
		if ( is_page() ) {

			$this->fields = apply_filters( 'better-framework/css/pages', $this->fields );
			$this->load_post_fields();

		} elseif ( is_singular() ) {

			$this->fields = apply_filters( 'better-framework/css/posts', $this->fields );
			$this->load_post_fields();

		}

	} // load_all_fields


	/**
	 * Loads Fields For Posts And Pages
	 *
	 * @param bool $post_id
	 */
	function load_post_fields( $post_id = false ) {

		if ( $post_id == false ) {
			$post_id = $this->post_id;
		}

		// load from cache if available
		$css_meta_cached = get_post_meta( $post_id, '_bf_post_css_cached_' . $post_id, true );
		if ( $css_meta_cached !== '' ) {

			$css_meta = get_post_meta( $post_id, '_bf_post_css_' . $post_id );

			if ( $css_meta === false ) {
				return;
			} else {
				foreach ( $css_meta as $post_meta ) {
					$this->fields = array_merge( $this->fields, $post_meta );
				}

				return;
			}

		}

		// save current time to page cached time
		add_post_meta( $post_id, '_bf_post_css_cached_' . $post_id, time() );


		// initialize base BF metabox
		if ( ! class_exists( 'BF_Metabox_Core' ) ) {
			Better_Framework()->post_meta();
		}

		// Iterate All Meta Box's
		foreach ( BF_Metabox_Core::$metabox as $metabox_id => $metabox ) {

			if ( ! isset( $metabox['css'] ) || ! $metabox['css'] ) {
				continue;
			}

			if ( isset( $metabox['panel-id'] ) ) {
				$css_id = $this->get_css_id( $metabox['panel-id'] );
			} else {
				$css_id = 'css';
			}

			$metabox_config = BF_Metabox_Core::get_metabox_config( $metabox_id );

			// If meta box have config
			if ( empty( $metabox_config ) ) {
				continue;
			}

			$metabox_css = array();


			// If Meta Box is Valid for Current Page
			if ( ! Better_Framework::factory( 'meta-box' )->can_output( $metabox_config ) ) {
				continue;
			}

			$metabox_fields = BF_Metabox_Core::get_metabox_css( $metabox_id );

			// If have meta box have fields
			if ( empty( $metabox_fields ) || ! is_array( $metabox_fields ) ) {
				continue;
			}


			// Each field of Metabox
			foreach ( $metabox_fields as $field_key => $field_value ) {

				// continue when haven't css field
				if ( ! isset( $field_value[ $css_id ] ) ) {
					if ( ! isset( $field_value['css'] ) ) {
						continue;
					}
				}

				// If Field Value Saved
				if ( false == ( $field_saved_value = get_post_meta( $post_id, $field_key, true ) ) ) {
					continue;
				}

				if ( isset( $field_value[ $css_id ] ) ) {
					$field_value[ $css_id ]['value'] = $field_saved_value;
					$metabox_css[]                   = $field_value[ $css_id ];
				} else {
					$field_value['css']['value'] = $field_saved_value;
					$metabox_css[]               = $field_value['css'];
				}

			}

			// remove without data background image fields
			foreach ( $metabox_css as $key => $meta_css ) {
				if ( isset( $meta_css['value']['img'] ) && empty( $meta_css['value']['img'] ) ) {
					unset( $metabox_css[ $key ] );
				}
			}

			if ( $metabox_css ) {
				add_post_meta( $post_id, '_bf_post_css_' . $post_id, $metabox_css );
				$this->fields = array_merge( $this->fields, $metabox_css );
			}

		}

	} // load_post_fields

} // BF_Pages_CSS
libs/better-framework/core/custom-css/class-bf-users-css.php000064400000014460151214002440020133 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * BF users custom css generator
 */
class BF_Users_CSS extends BF_Custom_CSS {

	/**
	 * Contains Current User ID
	 *
	 * @var int
	 */
	public $user_id = 0;


	/**
	 * prepare functionality
	 */
	function __construct() {

		// Clear Cache Callbacks
		add_action( 'delete_user', array( $this, 'clear_cache' ) );
		add_action( 'user_register', array( $this, 'clear_cache' ) );
		add_action( 'profile_update', array( $this, 'clear_cache' ) );

		// Register Custom CSS
		add_action( 'wp_enqueue_scripts', array( $this, 'register_custom_css' ), 100 );

		// Output Custom CSS Codes
		add_action( 'template_redirect', array( $this, 'global_custom_css' ), 1 );

	}


	/**
	 * Register BF Custom CSS Codes For Theme Specified Fields
	 *
	 * - Action Callback
	 */
	function register_custom_css() {

		// Only in user archive pages
		if ( ! is_author() ) {
			return;
		}

		$current_user = bf_get_author_archive_user();

		if ( ! $current_user ) {
			return;
		}

		// get last cached time
		$css_meta_cached_time = get_user_meta( $current_user->ID, '_bf_user_css_cached' );

		// if not cached then generate css and cache it
		if ( ! $css_meta_cached_time ) {
			$this->load_user_fields( $current_user->ID );
			$css_meta_cached_time = get_user_meta( $current_user->ID, '_bf_user_css_cached' );
		}

		// load main css
		$css_meta = get_user_meta( $current_user->ID, '_bf_user_css' );

		// if any css is cached before then enqueue it
		if ( $css_meta ) {
			wp_enqueue_style( 'better-framework-user-custom', get_site_url() . '/?bf_user_custom_css=1&user_id=' . $current_user->ID . '&ver=' . current( $css_meta_cached_time ), array(), null );
		}

	}


	/**
	 * Output Custom CSS
	 *
	 * - Action Callback
	 */
	public function global_custom_css() {

		// just when custom css requested
		if (
			empty( $_GET['bf_user_custom_css'] ) OR
			intval( $_GET['bf_user_custom_css'] ) != 1 OR
			! isset( $_GET['user_id'] ) OR
			empty( $_GET['user_id'] )

		) {
			return;
		}

		$this->user_id = intval( $_GET["user_id"] );
		$this->display();
		exit;
	}


	/**
	 * Callback: Clear Cached CSS
	 *
	 * Action: delete_user
	 * Action: user_register
	 */
	public function clear_cache( $user_ID ) {

		delete_user_meta( $user_ID, '_bf_user_css' );
		delete_user_meta( $user_ID, '_bf_user_css_cached' );

	}


	/**
	 * Load all fields
	 */
	function load_all_fields() {

		$this->fields = apply_filters( 'better-framework/css/users', $this->fields );
		$this->load_user_fields( $this->user_id );

	}


	/**
	 * Loads Fields For User
	 *
	 * @param bool $user_id
	 */
	function load_user_fields( $user_id = false ) {

		if ( $user_id == false ) {
			$user_id = bf_get_author_archive_user();
			$user_id = $user_id->ID;
		}

		// load from cache if available
		$css_meta_cached_time = get_user_meta( $user_id, '_bf_user_css_cached', true );
		if ( $css_meta_cached_time !== '' ) {

			$css_meta = get_user_meta( $user_id, '_bf_user_css' );

			if ( ! $css_meta ) {
				return;
			} else {
				foreach ( $css_meta as $user_meta ) {
					$this->fields = array_merge( $this->fields, $user_meta );
				}

				return;
			}

		}

		// save current time to user cached time
		add_user_meta( $user_id, '_bf_user_css_cached', time() );

		// initialize base BF metabox
		if ( ! class_exists( 'BF_Metabox_Core' ) ) {
			Better_Framework()->user_meta();
		}

		$css_cache = array();

		// Iterate All Meta Box's
		foreach ( BF_User_Metabox_Core::$metabox as $metabox_id => $metabox ) {

			if ( ! isset( $metabox['css'] ) || ! $metabox['css'] ) {
				continue;
			}

			if ( isset( $metabox['panel-id'] ) ) {
				$css_id = $this->get_css_id( $metabox['panel-id'] );
			} else {
				$css_id = 'css';
			}

			$metabox_css = BF_User_Metabox_Core::get_metabox_css( $metabox_id );

			if ( empty( $metabox_css ) || ! is_array( $metabox_css ) ) {
				continue;
			}

			$css_cache = array();

			// Each field of Metabox
			foreach ( $metabox_css as $field_key => $field ) {

				// continue when haven't css field
				if ( ! isset( $field[ $css_id ] ) ) {
					if ( ! isset( $field['css'] ) ) {
						continue;
					}
				}

				// If Field Value Saved
				if ( false == ( $field_saved_value = get_user_meta( $user_id, $field['id'], true ) ) ) {
					continue;
				}


				if ( isset( $field[ $css_id ] ) ) {
					$_temp_css_field = $field[ $css_id ];
				} elseif ( isset( $field['css'] ) ) {
					$_temp_css_field = $field['css'];
				} else {
					continue;
				}

				// prepare selectors
				foreach ( $_temp_css_field as $_temp_css_field_key => $_temp_css_field_value ) {

					// prepare selectors
					if ( is_array( $_temp_css_field[ $_temp_css_field_key ]['selector'] ) ) {

						foreach ( $_temp_css_field[ $_temp_css_field_key ]['selector'] as $selector_key => $selector ) {
							if ( strpos( $selector, '%%user-id%%' ) !== false ) {
								$_temp_css_field[ $_temp_css_field_key ]['selector'][ $selector_key ] = str_replace( '%%user-id%%', $user_id, $_temp_css_field[ $_temp_css_field_key ]['selector'][ $selector_key ] );
							}
						}

					} else {
						$_temp_css_field[ $_temp_css_field_key ]['selector'] = str_replace( '%%user-id%%', $user_id, $_temp_css_field[ $_temp_css_field_key ]['selector'] );
					}

				}

				$_temp_css_field['value'] = $field_saved_value;

				$css_cache[] = $_temp_css_field;
			}

			// remove without data background image fields
			foreach ( $css_cache as $key => $meta_css ) {
				if ( isset( $meta_css['value']['img'] ) && $meta_css['value']['img'] == '' ) {
					unset( $css_cache[ $key ] );
				}
			}

			if ( ! $css_cache ) {
				add_user_meta( $user_id, '_bf_user_css', $css_cache );
				$this->fields = array_merge( $this->fields, $css_cache );
			}
		}
	}
}libs/better-framework/core/custom-css/class-bf-custom-css.php000064400000023034151214002440020301 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Handle Base Custom CSS Functionality in BetterFramework
 */
class BF_Custom_CSS {

	/**
	 * Contain all css's that must be generated
	 *
	 * @var array
	 */
	protected $fields = array();


	/**
	 * Contain final css that rendered.
	 *
	 * @var string
	 */
	protected $final_css = '';


	/**
	 * Contain Fonts That Must Be Import In Top Of CSS
	 *
	 * @var array
	 */
	protected $fonts = array();


	/**
	 * Used For Adding New Font To Fonts Queue
	 *
	 * @param string $family
	 * @param string $variants
	 * @param string $subsets
	 */
	public function set_fonts( $family = '', $variants = '', $subsets = '' ) {


		// If Font Currently is in Queue Then Add New Variant Or Subset
		if ( isset( $this->fonts[ $family ] ) ) {

			if ( ! in_array( $variants, $this->fonts[ $family ]['variants'] ) ) {
				$this->fonts[ $family ]['variants'][] = $variants;
			}

			if ( ! in_array( $subsets, $this->fonts[ $family ]['subsets'] ) ) {
				$this->fonts[ $family ]['subsets'][] = $subsets;
			}

		} // Add New Font to Queue
		else {

			$this->fonts[ $family ] = array(
				'variants' => array( $variants ),
				'subsets'  => array( $subsets ),
			);

		}

	}


	/**
	 * Used For Generating Fonts
	 *
	 * @param string $type
	 *
	 * @param string $protocol custom protocol
	 *
	 * @return array|string
	 */
	public function render_fonts( $type = 'google-fonts', $protocol = 'default' ) {

		if ( ! bf_count( $this->fonts ) ) {
			return '';
		}

		$output = ''; // Final Out Put CSS

		$out_fonts = array(); // Array of Fonts, Each inner element separately

		// Collect all fonts in one url for better performance
		if ( $type == 'google-fonts' ) {
			$out_fonts['main'] = array();
		}

		// Create Each Font CSS
		foreach ( $this->fonts as $font_id => $font_information ) {

			//
			// Google Font
			//
			if ( $type == 'google-fonts' ) {

				$_font_have_subset = false;

				$font_data = Better_Framework::fonts_manager()->google_fonts()->get_font( $font_id );

				if ( $font_data == false ) {
					continue;
				} // font id is not valid google font

				$_font = str_replace( ' ', '+', $font_id );

				if ( in_array( 'italic', $font_information['variants'] ) ) {
					unset( $font_information['variants'][ array_search( 'italic', $font_information['variants'] ) ] );
					$font_information['variants'][] = '400italic';
				}

				if ( implode( ',', $font_information['variants'] ) != '' ) {
					$_font .= ':' . implode( ',', $font_information['variants'] );
				}

				// Remove Latin Subset because default subset is latin!
				// and if font have other subset then we make separate @import.
				foreach ( $font_information['subsets'] as $key => $value ) {
					if ( $value == 'latin' ) {
						unset( $font_information['subsets'][ $key ] );
					}
				}

				if ( implode( ',', $font_information['subsets'] ) != '' ) {
					$_font_have_subset = true;
					$_font             .= '&subset=' . implode( ',', $font_information['subsets'] );
				}

				// no subset
				if ( ! $_font_have_subset ) {
					array_push( $out_fonts['main'], $_font );
				} else {
					$out_fonts[][] = $_font;
				}
			}

			//
			// Custom Font
			//
			elseif ( $type == 'custom-fonts' || $type == 'theme-fonts' ) {

				if ( $type == 'custom-fonts' ) {
					$font = Better_Framework::fonts_manager()->custom_fonts()->get_font( $font_id );
				} else {
					$font = Better_Framework::fonts_manager()->theme_fonts()->get_font( $font_id );
				}

				if ( $font === false ) {
					continue;
				} // font id is not valid or removed

				$main_src_printed = false;

				$custom_output = '';
				$src           = array(
					'main'  => array(),
					'extra' => array(),
				);
				$custom_output .= " 
@font-face { 
	font-family: '" . $font_id . "';";


				// .EOT
				if ( ! empty( $font['eot'] ) ) {
					$src['extra'][] = "url('" . $font['eot'] . "')";
					$src['extra'][] = "url('" . $font['eot'] . "?#iefix') format('embedded-opentype')";
				}

				// .WOFF2
				if ( ! empty( $font['woff2'] ) ) {
					$src['main'][] = "url('" . $font['woff2'] . "') format('woff2')";
				}

				// .WOFF
				if ( ! empty( $font['woff'] ) ) {
					$src['main'][] = "url('" . $font['woff'] . "') format('woff')";
				}

				// .TTF
				if ( ! empty( $font['ttf'] ) ) {
					$src['main'][] = "url('" . $font['ttf'] . "') format('truetype')";
				}

				// .SVG
				if ( ! empty( $font['svg'] ) ) {
					$src['main'][] = "url('" . $font['svg'] . "#" . $font_id . "') format('svg')";
				}

				// .OTF
				if ( ! empty( $font['otf'] ) ) {
					$src['main'][] = "url('" . $font['otf'] . "#" . $font_id . "') format('opentype')";
				}

				//
				// Generate SRC attrs
				//
				{
					if ( ! empty( $src['extra'] ) ) {
						foreach ( $src['extra'] as $_src ) {
							$custom_output .= "src: $_src;";
						}
					}

					if ( ! empty( $src['main'] ) ) {
						$custom_output .= 'src: ' . implode( ',', $src['main'] ) . ';';
					}
				}

				$custom_output .= "
    font-weight: normal;
    font-style: normal;
}";

				$out_fonts[] = $custom_output;

			} // Google EA Fonts
			elseif ( $type == 'google-ea-fonts' ) {

				$font_data = Better_Framework::fonts_manager()->google_ea_fonts()->get_font( $font_id );

				if ( $font_data === false ) {
					continue;
				} // font id is not valid or removed

				$out_fonts[] = $font_data['url'];
			}
		}


		//
		// Google Fonts final array of links
		//
		if ( $type == 'google-fonts' ) {

			$final_fonts = array();
			foreach ( $out_fonts as $key => $out_font ) {
				if ( $out_font ) {
					$final_fonts[] = Better_Framework::fonts_manager()->get_protocol( $protocol ) . 'fonts.googleapis.com/css?family=' . implode( '%7C', $out_font );
				}
			}

			return $final_fonts;
		}

		//
		// Google EA Fonts final array of links
		//
		if ( $type == 'google-ea-fonts' ) {
			return $out_fonts;
		}

		//
		// Custom Fonts final string of font-face
		//
		elseif ( $type == 'custom-fonts' || $type == 'theme-fonts' ) {

			foreach ( $out_fonts as $out_font ) {
				$output .= $out_font;
			}

			if ( ! empty( $output ) ) {
				$output .= "\n";
			}
		}

		return $output;
	}


	/**
	 * Add new line to active fields
	 */
	private function add_new_line() {

		$this->fields[] = array( 'newline' => true );

	}


	/**
	 * Render a block array to css code
	 *
	 * @param   array  $block
	 * @param   string $value
	 * @param   bool   $add_to_final
	 *
	 * @return string
	 */
	private function render_block( $block, $value = '', $add_to_final = true ) {

		$css = bf_render_css_block_array( $block, $value );

		if ( $add_to_final ) {
			$this->final_css .= $css['code'];
		}

		//
		// Adds font into current font stacks
		//
		if ( ! empty( $css['font']['family'] ) ) {

			if ( ! isset( $css['font']['variant'] ) ) {
				$css['font']['variant'] = '';
			}

			if ( ! isset( $css['font']['subset'] ) ) {
				$css['font']['subset'] = '';
			}

			$this->set_fonts( $css['font']['family'], $css['font']['variant'], $css['font']['subset'] );
		}

		return $css['code'];
	}


	/**
	 * Render all fields css
	 *
	 * @return string
	 */
	function render_css() {

		foreach ( (array) $this->fields as $field ) {

			// new line field
			if ( isset( $field['newline'] ) ) {
				$this->render_block( $field, '' );
				continue;
			}


			// Continue when value in empty
			if ( ! isset( $field['value'] ) || $field['value'] === false || $field['value'] == '' ) {
				if ( empty( $field['force-callback-call'] ) ) {
					continue;
				}
			}

			$value = $field['value'];

			unset( $field['value'] );

			// Custom callbacks for generating CSS
			if ( isset( $field['callback'] ) ) {

				if ( is_string( $field['callback'] ) & is_callable( $field['callback'] ) ) {
					call_user_func_array( $field['callback'], array( &$field, &$value ) );
				} elseif ( isset( $field['callback']['fun'] ) && is_callable( $field['callback']['fun'] ) ) {

					$args = array( &$field, &$value );

					if ( ! empty( $field['callback']['args'] ) ) {
						$args[] = $field['callback']['args'];
					}

					call_user_func_array( $field['callback']['fun'], $args );
				}

			}

			foreach ( (array) $field as $block ) {
				if ( is_array( $block ) ) {
					$this->render_block( $block, $value );
				}
			}
		}


		return $this->final_css;
	}


	/**
	 * display css
	 */
	function display() {

		status_header( 200 );
		header( "Content-type: text/css; charset: utf-8" );

		$this->load_all_fields();

		$final_css = $this->render_css();

		echo $this->render_fonts(); // escaped before in generating

		echo $final_css; // escaped before in generating

	}


	/**
	 * Returns current css field id that integrated with style system
	 *
	 * @param   string $panel_id
	 *
	 * @return  string
	 */
	function get_css_id( $panel_id ) {

		// If panel haven't style feature
		if ( ! isset( BF_Options::$panels[ $panel_id ]['style'] ) ) {
			return 'css';
		}

		$style = get_option( $panel_id . '_current_style' );

		if ( $style == 'default' ) {
			return 'css';
		} else {
			return 'css-' . $style;
		}

	}
}libs/better-framework/core/field-generator/class-bf-term-select.php000064400000011436151214002450021400 0ustar00<?php

if ( ! class_exists( 'Walker_Category' ) ) {

	require ABSPATH . WPINC . '/class-walker-category.php';
}


class BF_Term_Select extends Walker_Category {

	public $primary_term_id;

	public static $status;


	function __destruct() {

		self::$status = null;
	}


	public function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0 ) {


		if ( is_null( self::$status ) ) {
			self::$status = array();
			if ( isset( $args['selected_terms'] ) ) {
				$terms_id = explode( ',', $args['selected_terms'] );
				foreach ( $terms_id as $term_id ) {
					if ( $term_id ) {

						if ( $term_id[0] === '-' ) {
							$term_id     = substr( $term_id, 1 );
							$term_status = 'deactivate';
						} elseif ( $term_id[0] === '+' ) {
							$term_id               = substr( $term_id, 1 );
							$term_status           = 'active';
							$this->primary_term_id = $term_id;
						} else {
							$term_status = 'active';
						}

						self::$status[ $term_id ] = $term_status;
					}
				}
			}
		}

		$term_status = isset( self::$status[ $category->term_id ] ) ? self::$status[ $category->term_id ] : '';

		/** This filter is documented in wp-includes/category-template.php */
		$cat_name = apply_filters(
			'list_cats',
			esc_attr( $category->name ),
			$category
		);

		// Don't generate an element if the category name is empty.
		if ( ! $cat_name ) {
			return;
		}

		$el = '<span class="label" data-status="' . $term_status . '">' . $cat_name;

		if ( ! empty( $args['show_count'] ) ) {
			$el .= ' (' . number_format_i18n( $category->count ) . ')';
		}
		$output      .= "\t<li";
		$css_classes = array(
			'cat-item',
			'cat-item-' . $category->term_id,
		);

		if ( ! empty( $args['current_category'] ) ) {
			// 'current_category' can be an array, so we use `get_terms()`.
			$_current_terms = get_terms( $category->taxonomy, array(
				'include'    => $args['current_category'],
				'hide_empty' => false,
			) );

			foreach ( $_current_terms as $_current_term ) {
				if ( $category->term_id == $_current_term->term_id ) {
					$css_classes[] = 'current-cat';
				} elseif ( $category->term_id == $_current_term->parent ) {
					$css_classes[] = 'current-cat-parent';
				}
				while( $_current_term->parent ) {
					if ( $category->term_id == $_current_term->parent ) {
						$css_classes[] = 'current-cat-ancestor';
						break;
					}
					$_current_term = get_term( $_current_term->parent, $category->taxonomy );
				}
			}
		}

		/**
		 * Filter the list of CSS classes to include with each category in the list.
		 *
		 * @since 4.2.0
		 *
		 * @see   wp_list_categories()
		 *
		 * @param array  $css_classes An array of CSS classes to be applied to each list item.
		 * @param object $category    Category data object.
		 * @param int    $depth       Depth of page, used for padding.
		 * @param array  $args        An array of wp_list_categories() arguments.
		 */
		$css_classes = implode( ' ', apply_filters( 'category_css_class', $css_classes, $category, $depth, $args ) );

		$output .= ' class="' . $css_classes . '"';
		$output .= ">";
		$output .= $this->checkbox_field( $category, $args['input_name'] );
		$output .= "$el\n";
		if ( $category->term_id == $this->primary_term_id ) {
			$output .= '<em class="bf-make-term-primary bf-is-term-primary">Primary</em>';
		} elseif ( empty( $category->parent ) && $term_status === 'active' ) {
			$output .= '<em class="bf-make-term-primary"><a href="#" data-term-id="' . intval( $category->term_id ) . '">Make Primary</a></em>';
		}
		$output .= '</span>';
	}


	protected function checkbox_field( $term, $input_name ) {

		ob_start();
		$status = 'none';
		if ( isset( self::$status[ $term->term_id ] ) ) {
			$status = self::$status[ $term->term_id ];
		} elseif ( ! empty( $term->parent ) ) {
			if ( isset( self::$status[ $term->parent ] ) ) {
				$_status = self::$status[ $term->parent ];
				if ( $_status === 'active' ) {
					$status = $_status;

					self::$status[ $term->term_id ] = $status;
				}
			}
		}
		$status = esc_attr( $status );
		?>
		<!-- Start checkbox input -->
		<div
				class="bf-checkbox-multi-state <?php echo $term->term_id == $this->primary_term_id ? 'bf-checkbox-primary-term' : '' ?>"
				data-current-state="<?php echo $status ?>"
		>
			<input type="hidden"
			       name="<?php echo esc_attr( $input_name ) ?>[<?php echo intval( $term->term_id ) ?>]"
			       class="bf-checkbox-status"
			       value="<?php echo $status ?>">

			<span data-state="none"></span>
			<span data-state="active" class="bf-checkbox-active">
                        <i class="fa fa-check" aria-hidden="true"></i>
                    </span>
			<span data-state="deactivate" class="bf-checkbox-active">
                         <i class="fa fa-times" aria-hidden="true"></i>
                    </span>
		</div>
		<!-- END checkbox input -->
		<?php

		return ob_get_clean();
	}
}
libs/better-framework/core/field-generator/fields/hr.php000064400000000022151214002450017330 0ustar00<hr class="bf-hr">libs/better-framework/core/field-generator/fields/heading.php000064400000001354151214002450020327 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */
libs/better-framework/core/field-generator/fields/ajax_select.php000064400000004513151214002450021212 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

echo '<div class="bf-ajax_select-field-container">';

$search_input = Better_Framework::html()->add( 'input' )->type( 'text' )->class( 'bf-ajax-suggest-input' );

if ( isset( $options['placeholder'] ) && ! empty( $options['placeholder'] ) ) {
	$search_input->attr( "placeholder", $options['placeholder'] );
}

echo $search_input->display(); // escaped before

echo Better_Framework::html()->add( 'span' )->class( 'bf-search-loader' )->text( '<i class="fa fa-search"></i>' )->display();

$input = Better_Framework::html()->add( 'input' )->type( 'hidden' )->name( $options['input_name'] );

if ( ! empty( $options['value'] ) ) {
	$input->val( $options['value'] );
}

if ( isset( $options['input_class'] ) ) {
	$input->class( $options['input_class'] );
}


$input->data( 'callback', $options['callback'] );
$input->data( 'token', Better_Framework::callback_token( $options['callback'] ) );

echo $input->display(); // escaped before

echo Better_Framework::html()->add( 'ul' )->class( 'bf-ajax-suggest-search-results' )->display();

$controls = Better_Framework::html()->add( 'ul' )->class( 'bf-ajax-suggest-controls' );

if ( ! empty( $options['value'] ) ) {
	foreach ( explode( ',', $options['value'] ) as $val ) {
		$name = isset( $options['get_name'] ) && is_callable( $options['get_name'] ) ? call_user_func( $options['get_name'], $val ) : $val;
		$sub  = Better_Framework::html()->add( 'li' )->data( 'id', $val )->text( $name )->text( '<i class="del fa fa-remove"></i>' );
		$controls->text( $sub );
	}
}

echo $controls->display(); // escaped before

echo '</div>';libs/better-framework/core/field-generator/fields/switch.php000064400000003437151214002450020235 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$hidden = Better_Framework::html()->add( 'input' )->type( 'hidden' )->name( $options['input_name'] )->val( '0' )->class( 'checkbox' );

// On Label
$on_label = __( 'On', 'better-studio' );
if ( isset( $options['on-label'] ) ) {
	$on_label = $options['on-label'];
}

// On Label
$off_label = __( 'Off', 'better-studio' );
if ( isset( $options['off-label'] ) ) {
	$off_label = $options['off-label'];
}

if ( $options['value'] ) {
	$on_checked  = 'selected';
	$off_checked = '';
	$hidden->attr( 'value', '1' );

} else {
	$on_checked  = '';
	$off_checked = 'selected';
}

if ( isset( $options['input_class'] ) ) {
	$hidden->class( $options['input_class'] );
}

?>
<div class="bf-switch bf-clearfix">

	<label
			class="cb-enable <?php echo esc_attr( $on_checked ); ?>"><span><?php echo esc_html( $on_label ); ?></span></label>
	<label class="cb-disable <?php echo esc_attr( $off_checked ); ?>"><span><?php echo esc_html( $off_label ); ?></span></label>
	<?php

	echo $hidden->display();  // escaped before

	?>
</div>libs/better-framework/core/field-generator/fields/radio.php000064400000002551151214002450020026 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( empty( $options['options'] ) ) {
	return;
}

foreach ( $options['options'] as $id => $val ) {
	$container = Better_Framework::html()->add( 'div' )->class( 'bf-radio-button-option' );
	$label     = Better_Framework::html()->add( 'label' );

	$input = Better_Framework::html()->add( 'input' )->type( 'radio' )->name( $options['input_name'] )->val( $id );
	if ( ! empty( $options['value'] ) && $options['value'] == $id ) {
		$input->attr( 'checked', 'checked' );
	}

	$label->text( $input );
	$label->text( $val );

	$container->text( $label );

	echo $container->display(); // escaped before
}libs/better-framework/core/field-generator/fields/select.php000064400000012602151214002450020205 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

// set options from deferred callback
if ( isset( $options['deferred-options'] ) ) {
	if ( is_string( $options['deferred-options'] ) && is_callable( $options['deferred-options'] ) ) {
		$options['options'] = call_user_func( $options['deferred-options'] );
	} elseif ( is_array( $options['deferred-options'] ) && ! empty( $options['deferred-options']['callback'] ) && is_callable( $options['deferred-options']['callback'] ) ) {
		if ( isset( $options['deferred-options']['args'] ) ) {
			$options['options'] = call_user_func_array( $options['deferred-options']['callback'], $options['deferred-options']['args'] );
		} else {
			$options['options'] = call_user_func( $options['deferred-options']['callback'] );
		}
	}
}


if ( empty( $options['options'] ) ) {
	$options['options'] = array();
}

$container_class = '';

$select = Better_Framework::html()->add( 'select' )->name( $options['input_name'] );

if ( isset( $options['input_class'] ) ) {
	$select->class( $options['input_class'] );
}

if ( isset( $options['multiple'] ) && $options['multiple'] ) {
	$select->attr( 'multiple', 'multiple' );
	$container_class .= 'multiple ';
}


if ( empty( $options['value'] ) ) {
	$val = array();;
} elseif ( is_array( $options['value'] ) ) {
	$val = $options['value'];
} else {
	$val = explode( ',', $options['value'] );
}

foreach ( $options['options'] as $option_id => $option_val ) {

	if ( $option_id === 'category_walker' ) {

		if ( is_array( $option_val ) && ! empty( $option_val['taxonomy'] ) ) {
			$tax = $option_val['taxonomy'];
		} else {
			$tax = 'category';
		}

		$r = array(
			'walker'       => new Walker_Better_CategoryDropdown,
			'orderby'      => 'name',
			'multiple'     => isset( $options['multiple'] ) ? $options['multiple'] : false,
			'hierarchical' => 1,
			'selected'     => $val,
			'show_count'   => 0
		);

		$cats_list = walk_category_dropdown_tree( get_terms( $tax, $r ), 0, $r );

		$select->text( $cats_list );

		continue;

	}

	if ( is_array( $option_val ) && isset( $option_val['disabled'] ) ) {

		$selected = false;
		if ( empty( $val ) && empty( $option_id ) ) {
			$selected = true;
		} elseif ( in_array( $option_id, $val ) ) {
			$selected = true;
		}

		$select->text( '<option value="' . esc_attr( $option_id ) . '" ' . ( $selected ? 'selected="selected"' : '' ) . ' ' . ( $option_val['disabled'] ? 'disabled="disabled"' : '' ) . '>' . wp_kses( $option_val['label'], bf_trans_allowed_html() ) . '</option>' );

	} elseif ( is_array( $option_val ) ) {

		if ( ! isset( $option_val['options'] ) && ! isset( $option_val['label'] ) ) {
			continue;
		}

		$select->text( '<optgroup label="' . $option_val['label'] . '">' );

		foreach ( $option_val['options'] as $_option_id => $_option_val ) {

			if ( $_option_id === 'category_walker' ) {

				if ( is_array( $_option_val ) && ! empty( $_option_val['taxonomy'] ) ) {
					$tax = $_option_val['taxonomy'];
				} else {
					$tax = 'category';
				}

				$r = array(
					'walker'       => new Walker_Better_CategoryDropdown,
					'orderby'      => 'name',
					'multiple'     => isset( $options['multiple'] ) ? $options['multiple'] : false,
					'hierarchical' => 1,
					'selected'     => $val,
					'show_count'   => 0
				);

				$terms_list = walk_category_dropdown_tree( get_terms( $tax, $r ), 0, $r );

				$select->text( $terms_list );
				continue;

			} else {

				if ( is_array( $_option_val ) ) {
					$select->text( '<option value="' . esc_attr( $_option_id ) . '" ' . ( in_array( $_option_id, $val ) ? 'selected="selected"' : '' ) . ' ' . ( $_option_val['disabled'] ? 'disabled="disabled"' : '' ) . '>' . wp_kses( $_option_val['label'], bf_trans_allowed_html() ) . '</option>' );
				} else {
					$select->text( '<option value="' . esc_attr( $_option_id ) . '" ' . ( in_array( $_option_id, $val ) ? 'selected="selected"' : '' ) . '>' . wp_kses( $_option_val, bf_trans_allowed_html() ) . '</option>' );
				}
			}
		}

		$select->text( '</optgroup>' );

	} else {
		// only for when default item id is empty and no any other selected!
		$selected = false;
		if ( empty( $val ) && empty( $option_id ) ) {
			$selected = true;
		} elseif ( in_array( $option_id, $val ) ) {
			$selected = true;
		}

		$select->text( '<option value="' . esc_attr( $option_id ) . '" ' . ( $selected ? 'selected="selected"' : '' ) . '>' . wp_kses( $option_val, bf_trans_allowed_html() ) . '</option>' );
	}

}

echo '<div class="bf-select-option-container ' . esc_attr( $container_class ) . '">';
echo $select->display(); // escaped before
echo '</div>';
echo $this->get_filed_input_desc( $options ); // escaped beforelibs/better-framework/core/field-generator/fields/image_checkbox.php000064400000004674151214002450021670 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// set options from deferred callback
if ( isset( $options['deferred-options'] ) ) {
	if ( is_string( $options['deferred-options'] ) && is_callable( $options['deferred-options'] ) ) {
		$options['options'] = call_user_func( $options['deferred-options'] );
	} elseif ( is_array( $options['deferred-options'] ) && ! empty( $options['deferred-options']['callback'] ) && is_callable( $options['deferred-options']['callback'] ) ) {
		if ( isset( $options['deferred-options']['args'] ) ) {
			$options['options'] = call_user_func_array( $options['deferred-options']['callback'], $options['deferred-options']['args'] );
		} else {
			$options['options'] = call_user_func( $options['deferred-options']['callback'] );
		}
	}
}

if ( empty( $options['options'] ) ) {
	$options['options'] = array();
}

$value = isset( $options['value'] ) ? $options['value'] : array();

$field_options = bf_sort_array_by_array( $options['options'], $value );

foreach ( $field_options as $key => $item ) {
	$is_checked = ! empty( $value[ $key ] ) && $value[ $key ] != 0;
	$input      = Better_Framework::html()->add( 'input' )->type( 'checkbox' )->name( sprintf( $options['input_name'], $key ) );

	if ( $is_checked ) {
		$input->attr( 'checked', 'checked' );
	}

	$image = Better_Framework::html()->add( 'img' )->src( $item['img'] )->alt( $item['label'] )->title( $item['label'] );
	$label = Better_Framework::html()->add( 'label' );

	$label->text( $input );
	$label->text( $image );

	$object = Honar::html()->add( 'div' )->class( 'bf-image-checkbox-option' );

	if ( $is_checked ) {
		$object->class( 'checked' );
	}

	$object->text( $label->display() );

	echo $object->display(); // escaped before
}libs/better-framework/core/field-generator/fields/textarea.php000064400000003235151214002450020545 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$object = Better_Framework::html()->add( 'textarea' );

if ( $options['value'] !== false ) {
	if ( ! empty( $options['special-chars'] ) && $options['special-chars'] == true ) {
		$object->val( htmlspecialchars_decode( $options['value'] ) );
	} else {
		$object->val( $options['value'] );
	}
}

if ( isset( $options['rtl'] ) && $options['rtl'] !== false ) {
	$object->class( 'rtl' );
}

if ( isset( $options['ltr'] ) && $options['ltr'] !== false ) {
	$object->class( 'ltr' );
}

if ( isset( $options['placeholder'] ) && $options['placeholder'] !== '' ) {
	$object->attr( 'placeholder', $options['placeholder'] );
}

if ( isset( $options['input_class'] ) ) {
	$object->class( $options['input_class'] );
}

$object->name( $options['input_name'] );

$output = '';

$output .= $object->display();

echo $output;  // escaped before
echo $this->get_filed_input_desc( $options );  // escaped beforelibs/better-framework/core/field-generator/fields/editor.php000064400000003012151214002450020207 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

$options = bf_merge_args( $options, array(
	'lang' => 'plain_text'
) );

$max_lines = ! empty( $options['max-lines'] ) ? $options['max-lines'] : 15;

$min_lines = ! empty( $options['min-lines'] ) ? $options['min-lines'] : 10;

?>
	<div class="bf-editor-wrapper">
		<pre class="bf-editor" data-lang="<?php echo esc_attr( $options['lang'] ); ?>"
		     data-max-lines="<?php echo esc_attr( $max_lines ); ?>"
		     data-min-lines="<?php echo esc_attr( $min_lines ); ?>"></pre>

		<textarea name="<?php echo esc_attr( $options['input_name'] ) ?>"
		          class="bf-editor-field"><?php echo $options['value']; // escaped before in function that passes value to this ?></textarea>
	</div>
<?php

echo $this->get_filed_input_desc( $options ); // escaped before in function that passes value to this
libs/better-framework/core/field-generator/fields/term_select.php000064400000004737151214002450021246 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div class="bf-field-term-select-wrapper">
	<ul>
		<?php

		if ( ! class_exists( 'BF_Term_Select' ) ) {
			require BF_PATH . '/core/field-generator/class-bf-term-select.php';
		}

		wp_list_categories( array(
			'style'          => 'list',
			'title_li'       => false,
			'taxonomy'       => isset( $options['taxonomy'] ) ? $options['taxonomy'] : 'category',
			'walker'         => new BF_Term_Select,
			'selected_terms' => $options['value'],
			'input_name'     => 'bf-term-select', //$options['input_name'],
			'hide_empty'     => false,

		) );

		?>
	</ul>
</div>
<div class="bf-field-term-select-help">
	<label><?php _e( 'Help: Click on check box to', 'better-studio' ); ?></label>

	<div class="bf-checkbox-multi-state disabled none-state">
		<span data-state="none"></span>
	</div>
	<label><?php _e( 'Not Selected', 'better-studio' ) ?></label>

	<div class="bf-checkbox-multi-state disabled active-state">
        <span class="bf-checkbox-active" style="display: inline-block;">
            <i class="fa fa-check" aria-hidden="true"></i>
        </span>
	</div>
	<label><?php _e( 'Selected', 'better-studio' ) ?></label>

	<div class="bf-checkbox-multi-state disabled deactivate-state">
        <span class="bf-checkbox-active" style="display: inline-block;">
           <i class="fa fa-times" aria-hidden="true"></i>
        </span>
	</div>
	<label><?php _e( 'Excluded', 'better-studio' ) ?></label>

	<?php echo $this->get_filed_input_desc( $options ); // escaped before ?>

</div>

<input type="hidden"
       name="<?php echo esc_attr( $options['input_name'] ) ?>"
       value="<?php echo esc_attr( $options['value'] ) ?>"
       class="bf-term-select-value <?php echo isset( $options['input_class'] ) ? esc_attr( $options['input_class'] ) : ''; ?> kc-param"
>libs/better-framework/core/field-generator/fields/partial-border.php000064400000006227151214002450021643 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div class="single-border border-<?php echo esc_attr( $border['type'] ); ?>"><?php

	if ( isset( $border['label'] ) ) {
		echo '<span class="border-label">' . wp_kses( $border['label'], bf_trans_allowed_html() ) . '</span>';
	}

	if ( in_array( 'width', $border ) ) {
		?>
		<span class="bf-field-with-suffix bf-field-with-prefix border-width">
        <span class='bf-prefix-suffix bf-prefix'><?php esc_html_e( 'Width:', 'better-studio' ); ?> </span><input
					type="text"
					name="<?php echo esc_attr( $options['input_name'] ); ?>[<?php echo esc_attr( $border['type'] ); ?>][width]"
					value="<?php echo esc_attr( $options['value'][ $border['type'] ]['width'] ); ?>"
					class="border-width"/><span
					class='bf-prefix-suffix bf-suffix'>px</span>
    </span>
		<?php
	}// width


	if ( in_array( 'style', $border ) ) {
		?>

		<span class="border-style-container"><?php
			$styles = array(
				'dotted' => __( 'Dotted', 'better-studio' ),
				'dashed' => __( 'Dashed', 'better-studio' ),
				'solid'  => __( 'Solid', 'better-studio' ),
				'double' => __( 'Double', 'better-studio' ),
				'groove' => __( 'Groove', 'better-studio' ),
				'ridge'  => __( 'Ridge', 'better-studio' ),
				'inset'  => __( 'Inset', 'better-studio' ),
				'outset' => __( 'Outset', 'better-studio' ),
			);

			?>
			<select
					name="<?php echo esc_attr( $options['input_name'] ); ?>[<?php echo esc_attr( $border['type'] ); ?>][style]"
					class="border-style">
				<?php foreach ( $styles as $key => $style ) {
					echo '<option value="' . esc_attr( $key ) . '" ' . ( $key == $options['value'][ $border['type'] ]['style'] ? 'selected' : '' ) . '>' . esc_html( $style ) . '</option>';
				} ?>
			</select>
        </span>

		<?php
	} //style

	if ( in_array( 'color', $border ) ) {

		echo '<span>';

		$input = Better_Framework::html()->add( 'input' )->type( 'text' )->name( $options['input_name'] . '[' . $border['type'] . '][color]' )->class( 'bf-color-picker' );

		$preview = Better_Framework::html()->add( 'div' )->class( 'bf-color-picker-preview' );

		if ( ! empty( $options['value'][ $border['type'] ]['color'] ) ) {
			$input->value( $options['value'][ $border['type'] ]['color'] )->css( 'border-color', $options['value'][ $border['type'] ]['color'] );
			$preview->css( 'background-color', $options['value'][ $border['type'] ]['color'] );
		}

		echo $input->display(); // escaped before
		echo $preview->display(); // escaped before
		echo '</span>';

	}

	?>
</div>libs/better-framework/core/field-generator/fields/icon_select.php000064400000013133151214002450021215 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// Default selected
$current = array(
	'key'       => '',
	'title'     => __( 'Chose an Icon', 'better-studio' ),
	'width'     => '',
	'height'    => '',
	'type'      => '',
	'font_code' => '',
);

if ( isset( $options['value'] ) ) {

	if ( is_array( $options['value'] ) ) {

		$current['font_code'] = isset( $options['value']['font_code'] ) ? $options['value']['font_code'] : '';

		if ( in_array( $options['value']['type'], array( 'custom-icon', 'custom' ) ) ) {
			$current['key']    = isset( $options['value']['icon'] ) ? $options['value']['icon'] : '';
			$current['title']  = bf_get_icon_tag( isset( $options['value'] ) ? $options['value'] : '' ) . ' ' . __( 'Custom icon', 'better-studio' );
			$current['width']  = isset( $options['value']['width'] ) ? $options['value']['width'] : '';
			$current['height'] = isset( $options['value']['height'] ) ? $options['value']['height'] : '';
			$current['type']   = 'custom-icon';
		} else {

			// Fontawesome icon
			if ( substr( $options['value']['icon'], 0, 3 ) == 'fa-' ) {

				Better_Framework::factory( 'icon-factory' );

				$fontawesome = BF_Icons_Factory::getInstance( 'fontawesome' );

				if ( isset( $fontawesome->icons[ $options['value']['icon'] ] ) ) {
					$current['key']    = $options['value']['icon'];
					$current['title']  = bf_get_icon_tag( $options['value'] ) . $fontawesome->icons[ $options['value']['icon'] ]['label'];
					$current['width']  = ! empty( $options['value']['width'] ) ? $options['value']['width'] : '';
					$current['height'] = ! empty( $options['value']['height'] ) ? $options['value']['height'] : '';
					$current['type']   = 'fontawesome';
				}

			} // BetterStudio Font Icon
			elseif ( substr( $options['value']['icon'], 0, 5 ) == 'bsfi-' ) {

				Better_Framework::factory( 'icon-factory' );

				$bs_icons = BF_Icons_Factory::getInstance( 'bs-icons' );


				if ( isset( $bs_icons->icons[ $options['value']['icon'] ] ) ) {
					$current['key']    = $options['value']['icon'];
					$current['title']  = bf_get_icon_tag( $options['value'] ) . $bs_icons->icons[ $options['value']['icon'] ]['label'];
					$current['width']  = ! empty( $options['value']['width'] ) ? $options['value']['width'] : '';
					$current['height'] = ! empty( $options['value']['height'] ) ? $options['value']['height'] : '';
					$current['type']   = 'bs-icons';
				}

			}


		}

	} elseif ( ! empty( $options['value'] ) ) {

		// Fontawesome icon
		if ( substr( $options['value'], 0, 3 ) == 'fa-' ) {

			Better_Framework::factory( 'icon-factory' );

			$fontawesome = BF_Icons_Factory::getInstance( 'fontawesome' );

			if ( isset( $fontawesome->icons[ $options['value'] ] ) ) {
				$current['key']    = $options['value'];
				$current['title']  = bf_get_icon_tag( $options['value'] ) . $fontawesome->icons[ $options['value'] ]['label'];
				$current['width']  = '';
				$current['height'] = '';
				$current['type']   = 'fontawesome';
			}

		} // BetterStudio Font Icon
		elseif ( substr( $options['value'], 0, 5 ) == 'bsfi-' ) {

			Better_Framework::factory( 'icon-factory' );

			$bs_icons = BF_Icons_Factory::getInstance( 'bs-icons' );

			if ( isset( $bs_icons->icons[ $options['value'] ] ) ) {
				$current['key']    = $options['value'];
				$current['title']  = bf_get_icon_tag( $options['value'] ) . $bs_icons->icons[ $options['value'] ]['label'];
				$current['width']  = ! empty( $options['value']['width'] ) ? $options['value']['width'] : '';
				$current['height'] = ! empty( $options['value']['height'] ) ? $options['value']['height'] : '';
				$current['type']   = 'bs-icons';
			}

		}

	}

}

$icon_handler = 'bf-icon-modal-handler-' . mt_rand();

?>
	<div class="bf-icon-modal-handler" id="<?php echo esc_attr( $icon_handler ); ?>">

		<div class="select-options">
			<span
					class="selected-option"><?php echo $current['title']; // escaped before in function that passes value to this ?></span>
		</div>

		<input type="hidden" class="icon-input" data-label=""
		       name="<?php echo esc_attr( $options['input_name'] ); ?>[icon]"
		       value="<?php echo esc_attr( $current['key'] ); ?>"/>
		<input type="hidden" class="icon-input-type" name="<?php echo esc_attr( $options['input_name'] ); ?>[type]"
		       value="<?php echo esc_attr( $current['type'] ); ?>"/>
		<input type="hidden" class="icon-input-height" name="<?php echo esc_attr( $options['input_name'] ); ?>[height]"
		       value="<?php echo esc_attr( $current['height'] ); ?>"/>
		<input type="hidden" class="icon-input-width" name="<?php echo esc_attr( $options['input_name'] ); ?>[width]"
		       value="<?php echo esc_attr( $current['width'] ); ?>"/>
		<input type="hidden" class="icon-input-font-code"
		       name="<?php echo esc_attr( $options['input_name'] ); ?>[font_code]"
		       value="<?php echo esc_attr( $current['font_code'] ); ?>"/>

		<?php echo $this->get_filed_input_desc( $options ); // escaped before ?>
	</div><!-- modal handler container -->
<?php


bf_enqueue_modal( 'icon' );
libs/better-framework/core/field-generator/fields/slider.php000064400000003525151214002450020214 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$dimension = empty( $options['dimension'] ) ? '' : $options['dimension'];
$min       = isset( $options['min'] ) && is_numeric( $options['min'] ) ? $options['min'] : 0;
$max       = isset( $options['max'] ) && is_numeric( $options['max'] ) ? $options['max'] : 100;
$step      = isset( $options['step'] ) && is_numeric( $options['step'] ) ? $options['step'] : 1;
$animation = isset( $options['animation'] ) && ! $options['animation'] ? 'disable' : 'enable';
$value     = empty( $options['value'] ) ? '0' : $options['value'];

$slider = Better_Framework::html()->add( 'div' )->class( 'bf-slider-slider' )->
data( 'dimension', $dimension )->
data( 'animation', $animation )->
data( 'val', $value )->
data( 'min', $min )->
data( 'max', $max )->
data( 'step', $step );

echo $slider->display(); // escaped before

$input = Better_Framework::html()->add( 'input' )->type( 'hidden' )->class( 'bf-slider-input' )->name( $options['input_name'] )->val( $value );

if ( isset( $options['input_class'] ) ) {
	$input->class( $options['input_class'] );
}

echo $input->display(); // escaped before
libs/better-framework/core/field-generator/fields/info.php000064400000001531151214002450017660 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div class="info-value">
	<?php echo $options['value']; // escaped before ?>
</div>libs/better-framework/core/field-generator/fields/sorter.php000064400000006733151214002450020254 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// set options from deferred callback
if ( isset( $options['deferred-options'] ) ) {
	if ( is_string( $options['deferred-options'] ) && is_callable( $options['deferred-options'] ) ) {
		$options['options'] = call_user_func( $options['deferred-options'] );
	} elseif ( is_array( $options['deferred-options'] ) && ! empty( $options['deferred-options']['callback'] ) && is_callable( $options['deferred-options']['callback'] ) ) {
		if ( isset( $options['deferred-options']['args'] ) ) {
			$options['options'] = call_user_func_array( $options['deferred-options']['callback'], $options['deferred-options']['args'] );
		} else {
			$options['options'] = call_user_func( $options['deferred-options']['callback'] );
		}
	}
}

if ( empty( $options['options'] ) ) {
	$options['options'] = array();
}

$value      = isset( $options['value'] ) && is_array( $options['value'] ) ? $options['value'] : array();
$groups_ids = array();

?>
<div class="bf-sorter-groups-container">
	<ul id="bf-sorter-group-<?php echo esc_attr( $options['id'] ); ?>"
	    class="bf-sorter-list bf-sorter-<?php echo esc_attr( $options['id'] ); ?>">
		<?php
		if ( is_array( $value ) && count( $value ) > 0 ) {

			foreach ( $value as $item_id => $item ) { ?>
				<li id="bf-sorter-group-item-<?php echo esc_attr( $options['id'] ); ?>-<?php echo esc_attr( $item_id ); ?>"
				    class="<?php echo isset( $options['options'][ $item_id ]['css-class'] ) ? esc_attr( $options['options'][ $item_id ]['css-class'] ) : ''; ?>"
				    style="<?php echo isset( $options['options'][ $item_id ]['css'] ) ? esc_attr( $options['options'][ $item_id ]['css'] ) : ''; ?>">
					<?php echo wp_kses( ( is_array( $item ) ? $item['label'] : $item ), bf_trans_allowed_html() ) ?>
					<input name="<?php echo esc_attr( $options['input_name'] ) ?>[<?php echo esc_attr( $item_id ); ?>]"
					       value="<?php echo is_array( $item ) ? esc_attr( $item['label'] ) : esc_attr( $item ); ?>"
					       type="hidden"/>
				</li>
			<?php }
		} else {
			foreach ( $options['options'] as $item_id => $item ) { ?>
				<li id="bf-sorter-group-item-<?php echo esc_attr( $options['id'] ); ?>-<?php echo esc_attr( $item_id ); ?>"
				    class="<?php echo isset( $item['css-class'] ) ? esc_attr( $item['css-class'] ) : ''; ?>"
				    style="<?php echo isset( $item['css'] ) ? esc_attr( $item['css'] ) : ''; ?>">
					<?php echo wp_kses( is_array( $item ) ? $item['label'] : $item, bf_trans_allowed_html() ) ?>
					<input name="<?php echo esc_attr( $options['input_name'] ) ?>[<?php echo esc_attr( $item_id ); ?>]"
					       value="<?php echo is_array( $item ) ? esc_attr( $item['label'] ) : esc_attr( $item ); ?>"
					       type="hidden"/>
				</li>
			<?php }
		}
		?>
	</ul>
</div>
libs/better-framework/core/field-generator/fields/custom.php000064400000003231151214002450020236 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

if ( isset( $options['input_callback'] ) ) {

	if ( is_string( $options['input_callback'] ) ) {

		$callback = $options['input_callback'];

		$callback_args = array( array( 'field_options' => $options ) );

	} else {
		$callback = $options['input_callback']['callback'];

		if ( isset( $options['input_callback']['args'][0] ) ) {

			$callback_args                     = $options['input_callback']['args'];
			$callback_args[0]['field_options'] = $options;
		} else {

			$callback_args = array( array( 'field_options' => $options ) );
		}
	}

	$options['options'] = call_user_func_array( $callback, $callback_args );
}

if ( isset( $options['input'] ) ) {
	echo $options['input'];  // escaped before
}


if ( isset( $options['js-code'] ) ) {
	Better_Framework()->assets_manager()->add_admin_js( $options['js-code'] );
}

if ( isset( $options['css-code'] ) ) {
	Better_Framework()->assets_manager()->add_admin_css( $options['css-code'] );
}libs/better-framework/core/field-generator/fields/select_popup.php000064400000010522151214002450021427 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// set options from deferred callback
if ( isset( $options['deferred-options'] ) ) {
	if ( is_string( $options['deferred-options'] ) && is_callable( $options['deferred-options'] ) ) {
		$options['options'] = call_user_func( $options['deferred-options'] );
	} elseif ( is_array( $options['deferred-options'] ) && ! empty( $options['deferred-options']['callback'] ) && is_callable( $options['deferred-options']['callback'] ) ) {
		if ( isset( $options['deferred-options']['args'] ) ) {
			$options['options'] = call_user_func_array( $options['deferred-options']['callback'], $options['deferred-options']['args'] );
		} else {
			$options['options'] = call_user_func( $options['deferred-options']['callback'] );
		}
	}
}

if ( empty( $options['options'] ) ) {
	$options['options'] = array();
}

$list_style = 'grid-2-column';
if ( isset( $options['list_style'] ) && ! empty( $options['list_style'] ) ) {
	$list_style = $options['list_style'];
}

// default selected
$current = array(
	'key'   => '',
	'label' => isset( $options['default_text'] ) && ! empty( $options['default_text'] ) ? wp_kses( $options['default_text'], bf_trans_allowed_html() ) : esc_html__( 'chose one...', 'better-studio' ),
	'img'   => ''
);

if ( isset( $options['value'] ) && ! empty( $options['value'] ) ) {
	if ( isset( $options['options'][ $options['value'] ] ) ) {
		$current        = $options['options'][ $options['value'] ];
		$current['key'] = $options['value'];
	}
}

$data2print = wp_array_slice_assoc( $options, bf_field_extra_options('select_popup') );

foreach ( (array) $options['options'] as $key => $option ) {
	if ( empty( $option['info'] ) ) {
		$option['info'] = array();
	}
	$option['info']['img']   = $option['img'];
	$option['info']['label'] = $option['label'];

	if(isset($option['badges'])) {
		$option['info']['badges'] = $option['badges'];
	}
	if(isset($option['class'])) {
		$option['info']['class'] = $option['class'];
	}
	if(!empty($option['current_img'])){
		$option['info']['current_img']   = $option['current_img'];
	}

	$data2print['options'][ $key ] = bf_map_deep( $option['info'], 'sanitize_text_field' );
}

$input_name = esc_attr( $options['input_name'] );

$select_style = empty( $options['select_style'] ) ? 'creative' : 'regular-select';

if ( $select_style === 'regular-select' ) {
	echo '
<div class="better-select-style better-select-popup ', $input_name, '">
	<span class="active-item-label">' . $current['label'] . '</span>
';
} else {
	?>

	<div class="select-popup-field bf-clearfix <?php echo $input_name ?>">
		<div class="select-popup-selected-image">
			<img src="<?php
			if(empty($current['current_img'])) {
				echo $current['img'];
			} else {
				echo $current['current_img'];
			}
			?>" alt="">
		</div>
		<div class="select-popup-selected-info">
			<div class="active-item-text"><?php
				if(isset($options['texts']['box_pre_title'])) {

					echo $options['texts']['box_pre_title'];
				} else{

					_e('Active item', 'better-studio');
				}
			 ?></div>
			<div class="active-item-label"><?php echo $current['label'] ?></div>

			<a href="#" class="button"><?php
				if(isset($options['texts']['box_button'])) {

					echo $options['texts']['box_button'];
				} else{

					_e('Change', 'better-studio');
				}

			 ?></a>
		</div>
	<?php
}


if ( $data2print ) {
	?>
	<script id="<?php echo str_replace( '-', '_', sanitize_html_class( $input_name ) ) ?>" class="select-popup-data"
	        type="application/json"><?php echo json_encode( $data2print ) ?></script>
	<?php
}

echo '<input type="hidden" name="' . $input_name . '" value="' . esc_attr( $current['key'] ) . '" class="select-value wpb_vc_param_value mce-field kc-param"/>';

echo '</div>';libs/better-framework/core/field-generator/fields/border.php000064400000004212151214002450020201 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// border param must be set
if ( ! isset( $options['border'] ) ) {
	return '';
}

// All Borders
if ( isset( $options['border']['all'] ) ) {

	$border         = $options['border']['all'];
	$border['type'] = 'all';

	include BF_PATH . 'core/field-generator/fields/partial-border.php';

} // Specified borders
else {

	// Top Border
	if ( isset( $options['border']['top'] ) ) {

		$border          = $options['border']['top'];
		$border['type']  = 'top';
		$border['label'] = __( 'Top Border:', 'better-studio' );

		include BF_PATH . 'core/field-generator/fields/partial-border.php';

	}

	// Right Border
	if ( isset( $options['border']['right'] ) ) {

		$border          = $options['border']['right'];
		$border['type']  = 'right';
		$border['label'] = __( 'Right Border:', 'better-studio' );

		include BF_PATH . 'core/field-generator/fields/partial-border.php';

	}

	// Bottom Border
	if ( isset( $options['border']['bottom'] ) ) {

		$border          = $options['border']['bottom'];
		$border['type']  = 'bottom';
		$border['label'] = __( 'Bottom Border:', 'better-studio' );

		include BF_PATH . 'core/field-generator/fields/partial-border.php';

	}

	// Left Border
	if ( isset( $options['border']['left'] ) ) {

		$border          = $options['border']['left'];
		$border['type']  = 'left';
		$border['label'] = __( 'Left Border:', 'better-studio' );

		include BF_PATH . 'core/field-generator/fields/partial-border.php';

	}

}
libs/better-framework/core/field-generator/fields/wp_editor.php000064400000002055151214002450020723 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$value = empty( $options['value'] ) ? '' : $options['value'];

$settings = empty( $options['settings'] ) ? array() : $options['settings'];

if ( ! isset( $settings['textarea_name'] ) ) {
	$settings['textarea_name'] = $options['input_name'];
}

wp_editor( $value, $options['id'], $settings );libs/better-framework/core/field-generator/fields/image_select.php000064400000006376151214002450021362 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// set options from deferred callback
if ( isset( $options['deferred-options'] ) ) {
	if ( is_string( $options['deferred-options'] ) && is_callable( $options['deferred-options'] ) ) {
		$options['options'] = call_user_func( $options['deferred-options'] );
	} elseif ( is_array( $options['deferred-options'] ) && ! empty( $options['deferred-options']['callback'] ) && is_callable( $options['deferred-options']['callback'] ) ) {
		if ( isset( $options['deferred-options']['args'] ) ) {
			$options['options'] = call_user_func_array( $options['deferred-options']['callback'], $options['deferred-options']['args'] );
		} else {
			$options['options'] = call_user_func( $options['deferred-options']['callback'] );
		}
	}
}

if ( empty( $options['options'] ) ) {
	$options['options'] = array();
}

$list_style = 'grid-2-column';
if ( isset( $options['list_style'] ) && ! empty( $options['list_style'] ) ) {
	$list_style = $options['list_style'];
}

// default selected
$current = array(
	'key'   => '',
	'label' => isset( $options['default_text'] ) && ! empty( $options['default_text'] ) ? wp_kses( $options['default_text'], bf_trans_allowed_html() ) : esc_html__( 'chose one...', 'better-studio' ),
	'img'   => ''
);

if ( isset( $options['value'] ) && ! empty( $options['value'] ) ) {
	if ( isset( $options['options'][ $options['value'] ] ) ) {
		$current        = $options['options'][ $options['value'] ];
		$current['key'] = $options['value'];
	}
}

$select_options = '';
foreach ( (array) $options['options'] as $key => $option ) {
	$select_options .= '<li data-value="' . esc_attr( $key ) . '" data-label="' . esc_attr( $option['label'] ) . '" class="image-select-option ' . ( $key == $current['key'] ? 'selected' : '' ) . '">
        <img src="' . esc_attr( $option['img'] ) . '" alt="' . esc_attr( $option['label'] ) . '"/><p>' . wp_kses( $option['label'], bf_trans_allowed_html() ) . '</p>
    </li>';

	if ( ! empty( $option['info'] ) ) {
		$option['info']['img']   = $option['img'];
		$option['info']['label'] = $option['label'];
	}
}

$input_name = esc_attr( $options['input_name'] );

echo '<div class="better-select-image ', sanitize_html_class( $input_name ), '">
<div class="select-options">
	<span class="selected-option">' . $current['label'] . '</span>
    <div class="better-select-image-options"><ul class="options-list ' . esc_attr( $list_style ) . ' bf-clearfix">' . $select_options /* escaped before */ . '</ul>
    </div>
</div>
<input type="hidden" name="' . $input_name . '" id="' . $input_name . '" value="' . esc_attr( $current['key'] ) . '"/>
</div>';
libs/better-framework/core/field-generator/fields/code.php000064400000004407151214002460017645 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$default_lang = 'text/html';
if ( empty( $options['language'] ) ) {
	$lang = $default_lang;
} else {
	switch ( $options['language'] ) {
		case ( 'xml' ):
		case ( 'html' ):
			$lang = 'text/html';
			break;

		case ( 'javascript' ):
		case ( 'json' ):
		case ( 'js' ):
			$lang = 'text/javascript';
			break;

		case ( 'php' ):
			$lang = 'application/x-httpd-php';
			break;

		case ( 'css' ):
			$lang = 'text/css';
			break;

		case ( 'sql' ):
			$lang = 'text/x-sql';
			break;

		default:
			$lang = $default_lang;
			break;
	}
}

$textarea = Better_Framework::html()->add( 'textarea' )->class( 'bf-code-editor' )->name( $options['input_name'] );

$line_numbers        = ! empty( $options['line_numbers'] ) ? 'enable' : 'disable';
$auto_close_brackets = ! empty( $options['auto_close_brackets'] ) ? 'enable' : 'disable';
$auto_close_tags     = ! empty( $options['auto_close_tags'] ) ? 'enable' : 'disable';

// Set editor language
$textarea->data( 'lang', $lang );

// Set editor line number feature
$textarea->data( 'line-numbers', $line_numbers );

// Set editor auto close brackets feature
$textarea->data( 'auto-close-brackets', $auto_close_brackets );

// Set editor auto close tags feature
$textarea->data( 'auto-close-tags', $auto_close_tags );

if ( ! empty( $options['placeholder'] ) ) {
	$textarea->placeholder( $options['placeholder'] );
}

if ( ! empty( $options['value'] ) ) {
	$textarea->val( $options['value'] );
}

echo $textarea->display();  // escaped beforelibs/better-framework/core/field-generator/fields/export.php000064400000002605151214002460020252 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( isset( $options['file_name'] ) && ! empty( $options['file_name'] ) ) {
	$file_name = 'data-file_name="' . esc_attr( $options['file_name'] ) . '"';
} else {
	$file_name = '';
}


if ( isset( $options['panel_id'] ) && ! empty( $options['panel_id'] ) ) {
	$panel_id = 'data-panel_id="' . esc_attr( $options['panel_id'] ) . '"';
} else {
	return '';
}


?>
<div>
	<a class="bf-button bf-main-button"
	   id="bf-download-export-btn" <?php echo $file_name; // escaped before ?> <?php echo $panel_id; // escaped before ?>><i
				class="fa fa-download"></i> <?php esc_html_e( 'Download Backup', 'better-studio' ); ?></a>
</div>libs/better-framework/core/field-generator/fields/background_image.php000064400000016435151214002460022220 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// stripcslashes for when json is splashed!
if ( ! empty( $options['value'] ) ) {
	$value = $options['value'];
} else {
	$value = array(
		'img'  => '',
		'type' => 'cover'
	);
}

$media_title = empty( $options['media_title'] ) ? __( 'Upload', 'better-studio' ) : $options['media_title'];
$button_text = empty( $options['button_text'] ) ? __( 'Upload', 'better-studio' ) : $options['button_text'];

// Upload Button
$upload_button = Better_Framework::html()
                                 ->add( 'a' )
                                 ->class( 'bf-button bf-main-button bf-background-image-upload-btn' )
                                 ->data( 'mediatitle', $media_title )
                                 ->data( 'buttontext', $button_text )
                                 ->text( '<i class="fa fa-upload"></i>' );

if ( isset( $options['upload_label'] ) ) {
	$upload_button->text( $options['upload_label'] );
} else {
	$upload_button->text( __( 'Upload', 'better-studio' ) );
}

// Remove Button
$remove_button = Better_Framework::html()
                                 ->add( 'a' )
                                 ->class( 'bf-button bf-background-image-remove-btn' )
                                 ->text( '<i class="fa fa-remove"></i>' );

if ( isset( $options['remove_label'] ) ) {
	$remove_button->text( $options['remove_label'] );
} else {
	$remove_button->text( __( 'Remove', 'better-studio' ) );
}

if ( $value['img'] == "" ) {
	$remove_button->css( 'display', 'none' );
}

// version < 2 compatibility
if ( $value['type'] == 'no-repeat' ) {
	$value['type'] = 'top-left';
}

// Select
$select = Better_Framework::html()
                          ->add( 'select' )
                          ->attr( 'id', $options['id'] . '-select' )
                          ->class( 'bf-background-image-uploader-select' )
                          ->name( $options['input_name'] . '[type]' );


//
// Fully Background Image
//
$cover_group = Better_Framework::html()
                               ->add( 'optgroup' )->attr( 'label', __( 'Full Background Image', 'better-studio' ) );

$cover_group->text( '<option value="cover" ' . ( $value['type'] == 'cover' ? 'selected="selected"' : '' ) . '>' . __( 'Full Cover', 'better-studio' ) . '</option>' );
$cover_group->text( '<option value="fit-cover" ' . ( $value['type'] == 'fit-cover' ? 'selected="selected"' : '' ) . '>' . __( 'Fit Cover', 'better-studio' ) . '</option>' );
$cover_group->text( '<option value="parallax" ' . ( $value['type'] == 'parallax' ? 'selected="selected"' : '' ) . '>' . __( 'Parallax', 'better-studio' ) . '</option>' );

$select->text( $cover_group->display() );


//
// Repeated Background Image
//
$repeat_group = Better_Framework::html()
                                ->add( 'optgroup' )->attr( 'label', __( 'Repeated Background Image', 'better-studio' ) );

$repeat_group->text( '<option value="repeat" ' . ( $value['type'] == 'repeat' ? 'selected="selected"' : '' ) . '>' . __( 'Repeat Horizontal and Vertical - Pattern', 'better-studio' ) . '</option>' );
$repeat_group->text( '<option value="repeat-y" ' . ( $value['type'] == 'repeat-y' ? 'selected="selected"' : '' ) . '>' . __( 'Repeat Horizontal', 'better-studio' ) . '</option>' );
$repeat_group->text( '<option value="repeat-x" ' . ( $value['type'] == 'repeat-x' ? 'selected="selected"' : '' ) . '>' . __( 'Repeat Vertical', 'better-studio' ) . '</option>' );
$repeat_group->text( '<option value="no-repeat" ' . ( $value['type'] == 'no-repeat' ? 'selected="selected"' : '' ) . '>' . __( 'No Repeat', 'better-studio' ) . '</option>' );

$select->text( $repeat_group->display() );


//
// Static Background Image Position
//
$position_group = Better_Framework()->html()->add( 'optgroup' )->attr( 'label', __( 'Static Background Image Position', 'better-studio' ) );

$position_group->text( '<option value="top-left" ' . ( $value['type'] == 'top-left' ? 'selected="selected"' : '' ) . '>' . __( 'Top Left', 'better-studio' ) . '</option>' );
$position_group->text( '<option value="top-center" ' . ( $value['type'] == 'top-center' ? 'selected="selected"' : '' ) . '>' . __( 'Top Center', 'better-studio' ) . '</option>' );
$position_group->text( '<option value="top-right" ' . ( $value['type'] == 'top-right' ? 'selected="selected"' : '' ) . '>' . __( 'Top Right', 'better-studio' ) . '</option>' );
$position_group->text( '<option value="left-center" ' . ( $value['type'] == 'left-center' ? 'selected="selected"' : '' ) . '>' . __( 'Left Center', 'better-studio' ) . '</option>' );
$position_group->text( '<option value="center-center" ' . ( $value['type'] == 'center-center' ? 'selected="selected"' : '' ) . '>' . __( 'Center Center', 'better-studio' ) . '</option>' );
$position_group->text( '<option value="right-center" ' . ( $value['type'] == 'right-center' ? 'selected="selected"' : '' ) . '>' . __( 'Right Center', 'better-studio' ) . '</option>' );
$position_group->text( '<option value="bottom-left" ' . ( $value['type'] == 'bottom-left' ? 'selected="selected"' : '' ) . '>' . __( 'Bottom Left', 'better-studio' ) . '</option>' );
$position_group->text( '<option value="bottom-center" ' . ( $value['type'] == 'bottom-center' ? 'selected="selected"' : '' ) . '>' . __( 'Bottom Center', 'better-studio' ) . '</option>' );
$position_group->text( '<option value="bottom-right" ' . ( $value['type'] == 'bottom-right' ? 'selected="selected"' : '' ) . '>' . __( 'Bottom Right', 'better-studio' ) . '</option>' );

$select->text( $position_group->display() );


// Main Input
$input = Better_Framework::html()
                         ->add( 'input' )
                         ->type( 'hidden' )
                         ->class( 'bf-background-image-input' )
                         ->name( $options['input_name'] . '[img]' )
                         ->val( $value['img'] );

if ( isset( $options['input_class'] ) ) {
	$input->class( $options['input_class'] );
}

echo $upload_button->display(); // escaped before
echo $remove_button->display(); // escaped before
echo '<br>';

if ( $value['img'] == "" ) {
	$class = 'hidden';
} else {
	$class = '';
}
echo '<div class="bf-background-image-uploader-select-container bf-select-option-container ' . $class . '">';
echo $select->display();  // escaped before
echo '</div>';

echo $input->display();  // escaped before

if ( $value['img'] != "" ) {
	echo '<div class="bf-background-image-preview">';
} else {
	echo '<div class="bf-background-image-preview" style="display: none">';
}

echo '<img src="' . esc_url( $value['img'] ) . '" />';
echo '</div>';
libs/better-framework/core/field-generator/fields/repeater.php000064400000013531151214002460020540 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( empty( $options['options'] ) ) {
	return;
}

if ( empty( $options['default'] ) ) {
	$options['default'] = array();
}

$is_close = isset( $options['state'] ) && 'close' === $options['state'];

if ( empty( $options['default'] ) ) {
	if ( isset( $panel_id ) ) {

		$default            = BF_Options::get_panel_std( $panel_id );
		$options['default'] = $default[ $options['id'] ]['default'];
	}
}

$name_format = empty( $options['input_name'] ) ? '%s[%d][%s]' : $options['input_name'];

// Add New Item Label
if ( isset( $options['add_label'] ) && ! empty( $options['add_label'] ) ) {
	$add_label = $options['add_label'];
} else {
	$add_label = __( 'Add', 'better-studio' );
}

// Delete Item Label
if ( isset( $options['delete_label'] ) && ! empty( $options['delete_label'] ) ) {
	$delete_label = $options['delete_label'];
} else {
	$delete_label = __( 'Delete', 'better-studio' );
}

// Item title
if ( isset( $options['item_title'] ) && ! empty( $options['item_title'] ) ) {
	$item_title = $options['item_title'];
} else {
	$item_title = __( 'Item', 'better-studio' );
}


echo '<!-- Repeater Container --><div class="bf-repeater-items-container bf-clearfix">';


$repeater_item_start = '<!-- Repeater Item --><div class="bf-repeater-item"><div class="bf-repeater-item-title"><h5><span class="handle-repeater-title-label">' . wp_kses( $item_title, bf_trans_allowed_html() ) . '</span><span class="handle-repeater-item' . ( $is_close ? ' closed' : '' ) . '"></span><span class="bf-remove-repeater-item-btn"><span class="dashicons dashicons-trash"></span>' . wp_kses( $delete_label, bf_trans_allowed_html() ) . '</span></div><div class="repeater-item-container bf-clearfix"';

if ( $is_close ) {
	$repeater_item_start .= ' style="display:none"';
}

$repeater_item_start .= '>';

$repeater_item_end = '</div></div><!-- /Repeater Item -->';

// Lst saved values
if ( ! empty( $options['value'] ) ) {

	$counter = 0;

	foreach ( (array) $options['value'] as $saved_key => $saved_val ) {

		echo $repeater_item_start; // escaped before

		foreach ( (array) $options['options'] as $field_id => $field_options ) {

			$this->generate_repeater_field( $options, $field_options, $saved_val, $name_format, $counter );

		}

		echo $repeater_item_end; // escaped before

		$counter ++;
	}

} else { // Default value

	// multiple default value
	if ( bf_count( $options['default'] ) > 1 ) {

		$counter = 0;

		foreach ( (array) $options['default'] as $saved_key => $saved_val ) {

			echo $repeater_item_start; // escaped before

			foreach ( (array) $options['options'] as $field_id => $field_options ) {

				$this->generate_repeater_field( $options, $field_options, $saved_val, $name_format, $counter );

			}

			$counter ++;

			echo $repeater_item_end; // escaped before

		}
	} else { // single default value

		$default = current( $options['default'] );

		echo $repeater_item_start; // escaped before

		foreach ( (array) $options['options'] as $field_id => $field_options ) {

			$this->generate_repeater_field( $options, $field_options, $default, $name_format, 0 );

		}

		echo $repeater_item_end; // escaped before
	}
}

echo '</div><!-- / Repeater Container -->';

// HTML Stuff for when user is adding new item to repeater
$script = Better_Framework::html()->add( 'script' )->type( 'text/html' );
ob_start();
echo '<!-- Repeater Item --><div class="bf-repeater-item"><div class="bf-repeater-item-title"><h5><span class="handle-repeater-title-label">' . wp_kses( $item_title, bf_trans_allowed_html() ) . '</span><span class="handle-repeater-item"></span><span class="bf-remove-repeater-item-btn"><span class="dashicons dashicons-trash"></span>' . wp_kses( $delete_label, bf_trans_allowed_html() ) . '</span></div><div class="repeater-item-container bf-clearfix">';

$default = current( $options['default'] );

foreach ( $options['options'] as $script_option ) {

	$this->generate_repeater_field_script( $options, $script_option, $default );

}

echo '</div></div><!-- /Repeater Item -->';

$item_html = ob_get_clean();

// FIX nested script tag
$item_html = preg_replace( '/<\s*script([^>]+)>/', '<!-- SCRIPT TAG START --><div $1 style="display:none;">', $item_html );
$item_html = preg_replace( '#<\s*/\s*script\s*>#', '</div><!-- SCRIPT TAG END -->', $item_html );

$script->text( $item_html );
echo $script->display(); // escaped before


// Add new item to repeater button
$new_btn = Better_Framework::html()->add( 'button' )->class( 'bf-clone-repeater-item bf-button bf-main-button' )->text( $add_label );

// Repeater in widgets
if ( isset( $options['widget_field'] ) ) {
	$new_btn = Better_Framework::html()->add( 'button' )->class( 'bf-widget-clone-repeater-item bf-button bf-main-button' )->text( $add_label );
} // General Repeater
else {
	$new_btn = Better_Framework::html()->add( 'button' )->class( 'bf-clone-repeater-item bf-button bf-main-button' )->text( $add_label );
}

if ( ! empty( $options['clone-name-format'] ) ) {
	$new_btn->data( 'name-format', $options['clone-name-format'] );
}

echo $new_btn->display(); // escaped beforelibs/better-framework/core/field-generator/fields/date.php000064400000002202151214002460017637 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

$date_format = empty( $options['date_format'] ) ? 'mm/dd/yy' : $options['date_format'];

$input = Better_Framework::html()->add( 'input' )->type( 'text' )->class( 'bf-date-picker-input' )->name( $options['input_name'] )->data( 'date-format', $date_format );
if ( ! empty( $options['value'] ) ) {
	$input->val( $options['value'] );
}

echo $input->display(); // escaped before

libs/better-framework/core/field-generator/fields/ajax_action.php000064400000002622151214002460021210 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div class="bf-ajax_action-field-container"><?php

	if ( isset( $options['confirm'] ) ) {
		$confirm = ' data-confirm="' . esc_attr( $options['confirm'] ) . '" ';
	} else {
		$confirm = '';
	}

	?>
	<a class="bf-action-button bf-button bf-main-button" data-callback="<?php echo esc_attr( $options['callback'] ); ?>"
		<?php if ( ! empty( $options['js-event'] ) ) printf( 'data-event="%s"', esc_attr( $options['js-event'] ) ) ?>
       data-token="<?php echo esc_attr( Better_Framework::callback_token( $options['callback'] ) ) ?>" <?php echo $confirm; // escaped before ?>><?php echo $options['button-name']; // escaped before ?></a>
</div>
libs/better-framework/core/field-generator/fields/color.php000064400000002104151214002460020041 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>

<div class="bs-color-picker-wrapper">

	<input type="text" name="<?php
	echo esc_attr( $options['input_name'] )
	?>" value="<?php
	if ( ! empty( $options['value'] ) )
		echo esc_attr( $options['value'] )
	?>" class="bs-color-picker-value color-picker wpb_vc_param_value mce-field" data-alpha="true">

</div>
libs/better-framework/core/field-generator/fields/typography.php000064400000025667151214002460021154 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! isset( $options['value']['family'] ) ) {

	$options['value']['family']  = 'Lato';
	$options['value']['variant'] = '';

}

$default = BF_Options::get_panel_std( $panel_id );
$default = isset( $default[ $options['id'] ] ) ? $default[ $options['id'] ] : '';

// prepare std id
if ( isset( $panel_id ) ) {
	$std_id = Better_Framework::options()->get_panel_std_id( $panel_id );
} else {
	$std_id = 'css';
}

$enabled = false;

if ( isset( $default[ $std_id ] ) ) {
	if ( isset( $default[ $std_id ]['enable'] ) ) {
		$enabled = true;
	}
} elseif ( isset( $default['std'] ) ) {
	if ( isset( $default['std']['enable'] ) ) {
		$enabled = true;
	}
}

if ( $enabled && ! isset( $options['value']['enable'] ) ) {
	$options['value']['enable'] = $default['std']['enable'];
}

// Get current font
$font = Better_Framework()->fonts_manager()->get_font( $options['value']['family'] );

if ( $enabled ) { ?>
	<div class="typo-fields-container bf-clearfix">
		<div class="typo-field-container">
			<div class="typo-enable-container"><?php

				$hidden = Better_Framework::html()->add( 'input' )->type( 'hidden' )->name( $options['input_name'] . '[enable]' )->val( $options['value']['enable'] ? '1' : 0 )->class( 'checkbox' );

				?>
				<div class="bf-switch bf-clearfix">
					<label
							class="cb-enable <?php echo esc_attr( $options['value']['enable'] ) ? 'selected' : ''; ?>"><span><?php esc_html_e( 'Enable', 'better-studio' ); ?></span></label>
					<label
							class="cb-disable <?php echo ! $options['value']['enable'] ? 'selected' : ''; ?>"><span><?php esc_html_e( 'Disable', 'better-studio' ); ?></span></label>
					<?php

					echo $hidden->display();  // escaped before

					?>
				</div>
			</div>
		</div>
	</div>
	<?php
}
?>
	<div class="typo-fields-container bf-clearfix">
		<span class="enable-disable"></span>
		<div class="typo-field-container font-family-container bf-select-option-container">
			<label><?php esc_html_e( 'Font Family:', 'better-studio' ); ?></label>
			<div class="select-placeholder bf-font-selector">
				<?php echo isset( $options['value']['family'] ) ? esc_attr( $options['value']['family'] ) : ' - ' ?>
			</div>
			<input type="hidden" name="<?php echo esc_attr( $options['input_name'] ); ?>[family]"
			       value="<?php echo isset( $options['value']['family'] ) ? esc_attr( $options['value']['family'] ) : '' ?>"
			       class="bf-font-family">
		</div>

		<div class="bf-select-option-container typo-field-container">
			<label
					for="<?php echo esc_attr( $options['input_name'] ); ?>[variant]"><?php esc_html_e( 'Font Weight:', 'better-studio' ); ?></label>
			<select name="<?php echo esc_attr( $options['input_name'] ); ?>[variant]"
			        id="<?php echo esc_attr( $options['input_name'] ); ?>-variants" class="font-variants">
				<?php

				Better_Framework()->fonts_manager()->get_font_variants_option_elements( $font, $options['value']['variant'] );

				?>
			</select>
		</div>

		<div class="bf-select-option-container typo-field-container">
			<label
					for="<?php echo esc_attr( $options['input_name'] ); ?>[subset]"><?php esc_html_e( 'Font Character Set:', 'better-studio' ); ?></label>
			<select name="<?php echo esc_attr( $options['input_name'] ); ?>[subset]"
			        id="<?php echo esc_attr( $options['input_name'] ); ?>-subset" class="font-subsets">
				<?php

				Better_Framework()->fonts_manager()->get_font_subset_option_elements( $font, $options['value']['subset'] );

				?>
			</select>
		</div>

		<?php

		$align = false;

		if ( isset( $default[ $std_id ] ) ) {
			if ( isset( $default[ $std_id ]['align'] ) ) {
				$align = true;
			}
		} elseif ( isset( $default['std'] ) ) {
			if ( isset( $default['std']['align'] ) ) {
				$align = true;
			}
		}

		if ( $align && ! isset( $options['value']['align'] ) ) {
			$options['value']['align'] = $default['std']['align'];
		}

		if ( $align ) { ?>
			<div class="bf-select-option-container  typo-field-container text-align-container">
				<label
						for="<?php echo esc_attr( $options['input_name'] ); ?>[align]"><?php esc_html_e( 'Text Align:', 'better-studio' ); ?></label>
				<?php
				$aligns = array(
					'inherit' => 'Inherit',
					'left'    => 'Left',
					'center'  => 'Center',
					'right'   => 'Right',
					'justify' => 'Justify',
					'initial' => 'Initial',
				);
				?>
				<select name="<?php echo esc_attr( $options['input_name'] ); ?>[align]"
				        id="<?php echo esc_attr( $options['input_name'] ); ?>-align">
					<?php foreach ( $aligns as $key => $align ) {
						echo '<option value="' . esc_attr( $key ) . '" ' . ( $key == $options['value']['align'] ? 'selected' : '' ) . '>' . esc_html( $align ) . '</option>';
					} ?>
				</select>
			</div>
		<?php } ?>

		<?php

		$transform = false;

		if ( isset( $default[ $std_id ] ) ) {
			if ( isset( $default[ $std_id ]['transform'] ) ) {
				$transform = true;
			}
		} elseif ( isset( $default['std'] ) ) {
			if ( isset( $default['std']['transform'] ) ) {
				$transform = true;
			}
		}

		if ( $transform && ! isset( $options['value']['transform'] ) ) {
			$options['value']['transform'] = $default['std']['transform'];
		}

		if ( $transform ) { ?>
			<div class="bf-select-option-container typo-field-container text-transform-container">
				<label
						for="<?php echo esc_attr( $options['input_name'] ); ?>[transform]"><?php esc_html_e( 'Text Transform:', 'better-studio' ); ?></label>
				<?php
				$transforms = array(
					'none'       => 'None',
					'capitalize' => 'Capitalize',
					'lowercase'  => 'Lowercase',
					'uppercase'  => 'Uppercase',
					'initial'    => 'Initial',
					'inherit'    => 'Inherit',
				);
				?>
				<select name="<?php echo esc_attr( $options['input_name'] ); ?>[transform]"
				        id="<?php echo esc_attr( $options['input_name'] ); ?>-transform" class="text-transform">
					<?php foreach ( $transforms as $key => $transform ) {
						echo '<option value="' . esc_attr( $key ) . '" ' . ( $key == $options['value']['transform'] ? 'selected' : '' ) . '>' . esc_html( $transform ) . '</option>';
					} ?>
				</select>
			</div>
		<?php } ?>


		<?php


		$size = false;

		if ( isset( $default[ $std_id ] ) ) {
			if ( isset( $default[ $std_id ]['size'] ) ) {
				$size = true;
			}
		} elseif ( isset( $default['std'] ) ) {
			if ( isset( $default['std']['size'] ) ) {
				$size = true;
			}
		}

		if ( $size && ! isset( $options['value']['size'] ) ) {
			$options['value']['size'] = $default['std']['size'];
		}

		if ( $size ) { ?>
			<div class="typo-field-container text-size-container">
				<label
						for="<?php echo esc_attr( $options['input_name'] ); ?>[size]"><?php esc_html_e( 'Font Size:', 'better-studio' ); ?></label>
				<div class="bf-field-with-suffix">
					<input type="text" name="<?php echo esc_attr( $options['input_name'] ); ?>[size]"
					       value="<?php echo esc_attr( $options['value']['size'] ); ?>" class="font-size"/><span
							class='bf-prefix-suffix bf-suffix'><?php esc_html_e( 'Pixel', 'better-studio' ); ?></span>
				</div>
			</div>
		<?php }

		//
		// Line Height
		//
		$line_height = false;

		if ( isset( $default[ $std_id ] ) ) {
			if ( isset( $default[ $std_id ]['line-height'] ) ) {
				$line_height_id = 'line-height';
				$line_height    = true;
			} elseif ( isset( $default[ $std_id ]['line_height'] ) ) {
				$line_height_id = 'line_height';
				$line_height    = true;
			}
		} elseif ( isset( $default['std'] ) ) {
			if ( isset( $default['std']['line-height'] ) ) {
				$line_height_id = 'line-height';
				$line_height    = true;
			} elseif ( isset( $default['std']['line_height'] ) ) {
				$line_height_id = 'line_height';
				$line_height    = true;
			}
		}

		if ( $line_height && ! isset( $options['value'][ $line_height_id ] ) ) {
			$options['value'][ $line_height_id ] = $default['std'][ $line_height_id ];
		}

		if ( $line_height ) { ?>
			<div class="typo-field-container text-height-container">
				<label><?php esc_html_e( 'Line Height:', 'better-studio' ); ?></label>
				<div class="bf-field-with-suffix ">
					<input type="text"
					       name="<?php echo esc_attr( $options['input_name'] ); ?>[<?php echo esc_attr( $line_height_id ); ?>]"
					       value="<?php echo esc_attr( $options['value'][ $line_height_id ] ); ?>" class="line-height"/><span
							class='bf-prefix-suffix bf-suffix'><?php esc_html_e( 'Pixel', 'better-studio' ); ?></span>
				</div>
			</div>
		<?php }


		//
		// Letter Spacing
		//
		$letter_spacing = false;

		if ( isset( $default[ $std_id ] ) ) {
			if ( isset( $default[ $std_id ]['letter-spacing'] ) ) {
				$letter_spacing = true;
			}
		} elseif ( isset( $default['std'] ) ) {
			if ( isset( $default['std']['letter-spacing'] ) ) {
				$letter_spacing = true;
			}
		}

		if ( $letter_spacing && ! isset( $options['value']['letter-spacing'] ) ) {
			$options['value']['letter-spacing'] = $default['std']['letter-spacing'];
		}

		if ( $letter_spacing ) { ?>
			<div class="typo-field-container text-height-container">
				<label><?php esc_html_e( 'Letter Spacing:', 'better-studio' ); ?></label>
				<input type="text" name="<?php echo esc_attr( $options['input_name'] ); ?>[letter-spacing]"
				       value="<?php echo esc_attr( $options['value']['letter-spacing'] ); ?>"
				       class="letter-spacing" placeholder="<?php _e('Use unite px, em...') ?>"/>
			</div>
			<?php
		}


		//
		// Color field
		//
		$color = false;

		if ( isset( $default[ $std_id ] ) ) {
			if ( isset( $default[ $std_id ]['color'] ) ) {
				$color = true;
			}
		} elseif ( isset( $default['std'] ) ) {
			if ( isset( $default['std']['color'] ) ) {
				$color = true;
			}
		}

		if ( $color && ! isset( $options['value']['color'] ) ) {
			$options['value']['color'] = $default['std']['color'];
		}

		if ( $color ) {
			?>
			<div class="typo-field-container text-color-container">
				<label><?php esc_html_e( 'Color:', 'better-studio' ); ?></label>
				<div class="bs-color-picker-wrapper">
					<div class="bs-color-picker-stripe">
						<a class="wp-color-result" title="Select Color" data-current="Current Color"
						   style="background-color: <?php echo esc_attr( $options['value']['color'] ); ?>"></a>
					</div>

					<input type="text" name="<?php echo esc_attr( $options['input_name'] ) ?>[color]" value="<?php
					echo esc_attr( $options['value']['color'] )
					?>" class="bs-color-picker-value">
				</div>
			</div>

			<?php
		}
		?>

	</div>
<?php
libs/better-framework/core/field-generator/fields/media.php000064400000002766151214002460020020 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$input = Better_Framework::html()->add( 'input' )->type( 'text' )->name( $options['input_name'] );

if ( ! $options['value'] == false ) {
	$input->val( $options['value'] );
}

$media_title = empty( $options['media_title'] ) ? __( 'Upload', 'better-studio' ) : $options['media_title'];
$button_text = empty( $options['button_text'] ) ? __( 'Upload', 'better-studio' ) : $options['button_text'];

$a = Better_Framework::html()->add( 'a' )->class( 'bf-button' )->class( 'bf-main-button bf-button bf-media-upload-btn' )->data( 'mediatitle', $media_title )->data( 'buttontext', esc_attr( $button_text ) );

$a->text( '<i class="fa fa-upload"></i> ' . $button_text );

echo $input->display(); // escaped before
echo $a->display(); // escaped beforelibs/better-framework/core/field-generator/fields/text.php000064400000004507151214002460017720 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$field_object = Better_Framework::html()->add( 'input' )->type( 'text' );

$field_object->name( $options['input_name'] );

if ( $options['value'] !== false ) {
	$field_object->val( esc_attr( $options['value'] ) );
}

if ( isset( $options['input_class'] ) ) {
	$field_object->class( $options['input_class'] );
}

if ( isset( $options['rtl'] ) && $options['rtl'] !== false ) {
	$field_object->class( 'rtl' );
}

if ( isset( $options['ltr'] ) && $options['ltr'] !== false ) {
	$field_object->class( 'ltr' );
}

if ( isset( $options['placeholder'] ) && $options['placeholder'] !== '' ) {
	$field_object->attr( 'placeholder', $options['placeholder'] );
}

$has_prefix_or_suffix          = ! empty( $options['prefix'] ) || ! empty( $options['suffix'] );
$prefix_suffix_wrapper_classes = array();
if ( ! empty( $options['prefix'] ) ) {
	$prefix_suffix_wrapper_classes[] = 'bf-field-with-prefix';
}
if ( ! empty( $options['suffix'] ) ) {
	$prefix_suffix_wrapper_classes[] = 'bf-field-with-suffix';
}

$output = '';

if ( $has_prefix_or_suffix ) {

	$output .= '<div class="' . implode( ' ',$prefix_suffix_wrapper_classes ) . '">';
}

if ( ! empty( $options['prefix'] ) ) {
	$output .= "<span class='bf-prefix-suffix'>{$options['prefix']}</span>";
}

$output .= $field_object->display();

if ( ! empty( $options['suffix'] ) ) {
	$output .= "<span class='bf-prefix-suffix'>{$options['suffix']}</span>";
}

if ( $has_prefix_or_suffix ) {
	$output .= '</div>';
}

echo $output;  // escaped before

echo $this->get_filed_input_desc( $options ); // escaped beforelibs/better-framework/core/field-generator/fields/import.php000064400000002304151214002460020237 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( isset( $options['panel_id'] ) && ! empty( $options['panel_id'] ) ) {
	$panel_id = 'data-panel_id="' . esc_attr( $options['panel_id'] ) . '"';
} else {
	return '';
}

?>

<input type="file" <?php echo $panel_id; // escaped before ?> name="bf-import-file-input" id="bf-import-file-input"
       class="bf-import-file-input">

<a class="bf-import-upload-btn bf-button bf-main-button"><i
			class="fa fa-upload"></i><?php esc_html_e( 'Import', 'better-studio' ); ?></a>libs/better-framework/core/field-generator/fields/checkbox.php000064400000002360151214002460020515 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$hidden = Better_Framework::html()->add( 'input' )->type( 'hidden' )->name( $options['input_name'] )->val( '0' );

$checkbox = Better_Framework::html()->add( 'input' )->type( 'checkbox' )->name( $options['input_name'] )->val( '1' );
if ( ! empty( $options['value'] ) ) {
	if ( $options['value'] == 'on' || $options['value'] == 'checked' || $options['value'] == '1' ) {
		$checkbox->attr( 'checked', 'checked' );
	}
}

echo $hidden->display(), $checkbox->display();  // escaped before
libs/better-framework/core/field-generator/fields/media_image.php000064400000006765151214002460021165 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

$input_type = ! empty( $options['show_input'] ) ? 'text' : 'hidden';

$input = Better_Framework::html()->add( 'input' )->type( $input_type )->name( $options['input_name'] )->class( 'bf-media-image-input' )->class( 'ltr' );

if ( ! $options['value'] == false ) {
	$input->val( $options['value'] );
}

if ( isset( $options['input_class'] ) ) {
	$input->class( $options['input_class'] );
}

if ( $input_type === 'text' ) {
	if ( ! empty( $options['input_placeholder'] ) ) {
		$input->placeholder( $options['input_placeholder'] );
	} else {
		$input->placeholder( __( 'Image external link...', 'better-studio' ) );
	}
}

if ( empty( $options['hide_buttons'] ) ) {

	$media_title = empty( $options['media_title'] ) ? __( 'Upload', 'better-studio' ) : $options['media_title'];
	$button_text = empty( $options['media_button'] ) ? __( 'Upload', 'better-studio' ) : $options['media_button'];

	$upload_label = empty( $options['upload_label'] ) ? __( 'Upload', 'better-studio' ) : $options['upload_label'];
	$remove_label = empty( $options['remove_label'] ) ? __( 'Remove', 'better-studio' ) : $options['remove_label'];

	$upload_button = Better_Framework::html()->add( 'a' )->class( 'bf-button bf-main-button bf-media-image-upload-btn' )->data( 'media-title', $media_title )->data( 'button-text', $button_text );
	$upload_button->text( '<i class="fa fa-upload"></i> ' . $upload_label );

	$remove_button = Better_Framework::html()->add( 'a' )->class( 'bf-button bf-media-image-remove-btn' );
	$remove_button->text( '<i class="fa fa-remove"></i> ' . $remove_label );


	if ( isset( $options['data-type'] ) && $options['data-type'] == 'id' ) {

		if ( ! isset( $options['preview-size'] ) ) {
			$options['preview-size'] = 'thumbnail';
		}

		$upload_button->class( 'bf-media-type-id' )->data( 'size', $options['preview-size'] );
	}

	if ( $options['value'] == false ) {
		$remove_button->css( 'display:none' );
	}

	echo $upload_button->display(); // escaped before
	echo $remove_button->display(); // escaped before
}

echo $input->display(); // escaped before


if ( empty( $options['hide_preview'] ) ) {
	if ( $options['value'] != false ) {
		echo '<div class="bf-media-image-preview">';
	} else {
		echo '<div class="bf-media-image-preview" style="display: none">';
	}

	if ( ! empty( $options['value'] ) ) {

		if ( $attachment_id = filter_var( $options['value'], FILTER_VALIDATE_INT ) ) {
			$options['value'] = wp_get_attachment_image_src( $attachment_id, isset( $options['preview-size'] ) ? $options['preview-size'] : 'thumbnail' );
			$options['value'] = $options['value'][0];
		}
	}

	echo '<img src="' . esc_url( $options['value'] ) . '" />';

	echo '</div>';
}


echo $this->get_filed_input_desc( $options ); // escaped before
libs/better-framework/core/field-generator/fields/image_preview.php000064400000002574151214002460021561 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$class = '';
$align = 'center';

if ( ! empty( $options['align'] ) ) {
	$align = $options['align'];
}

if ( ! empty( $options['class'] ) ) {
	$class = $options['class'];
}

if ( ( ! isset( $options['value'] ) || ! $options['value'] ) && isset( $options['std'] ) ) {
	$options['value'] = $options['std'];
}

?>
<div class="info-value <?php echo $class; // escaped before ?>"
     style="text-align: <?php echo $align; // escaped before ?>;">
	<?php foreach ( (array) $options['value'] as $k => $image ) { ?>
		<img class="image-<?php echo $k; ?>" src="<?php echo $image; // escaped before ?>">
	<?php } ?>
</div>
libs/better-framework/core/field-generator/fields/image_radio.php000064400000005263151214002460021174 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// set options from deferred callback
if ( isset( $options['deferred-options'] ) ) {
	if ( is_string( $options['deferred-options'] ) && is_callable( $options['deferred-options'] ) ) {
		$options['options'] = call_user_func( $options['deferred-options'] );
	} elseif ( is_array( $options['deferred-options'] ) && ! empty( $options['deferred-options']['callback'] ) && is_callable( $options['deferred-options']['callback'] ) ) {
		if ( isset( $options['deferred-options']['args'] ) ) {
			$options['options'] = call_user_func_array( $options['deferred-options']['callback'], $options['deferred-options']['args'] );
		} else {
			$options['options'] = call_user_func( $options['deferred-options']['callback'] );
		}
	}
}

if ( empty( $options['options'] ) ) {
	$options['options'] = array();
}

$value = ! empty( $options['value'] ) ? $options['value'] : '';

foreach ( $options['options'] as $key => $item ) {
	$is_checked = ! empty( $value ) && ( $key == $value );

	$input = Better_Framework::html()->add( 'input' )->type( 'radio' )->name( $options['input_name'] )->value( $key );

	if ( isset( $options['input_class'] ) ) {
		$input->class( $options['input_class'] );
	}

	if ( $is_checked ) {
		$input->attr( 'checked', 'checked' );
	}

	$image = Better_Framework::html()->add( 'img' )->src( $item['img'] )->alt( $item['label'] )->title( $item['label'] );

	if ( isset( $item['class'] ) ) {
		$image->class( $item['class'] );
	}

	$label = Better_Framework::html()->add( 'label' );

	$label->text( $input );
	$label->text( $image );
	if ( isset( $item['label'] ) ) {
		$p = Better_Framework::html()->add( 'p' )->text( $item['label'] )->class( 'item-label' );
		$label->text( $p );
	}

	$object = Better_Framework::html()->add( 'div' )->class( 'bf-image-radio-option' );

	if ( $is_checked ) {
		$object->class( 'checked' );
	}

	$object->text( $label->display() );

	echo $object->display(); // escaped before
}libs/better-framework/core/field-generator/fields/sorter_checkbox.php000064400000011654151214002460022121 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// todo add option to disable sorter items and male iot wimple multi checkbox
// todo add std support for this field

// set options from deferred callback
if ( isset( $options['deferred-options'] ) ) {
	if ( is_string( $options['deferred-options'] ) && is_callable( $options['deferred-options'] ) ) {
		$options['options'] = call_user_func( $options['deferred-options'] );
	} elseif ( is_array( $options['deferred-options'] ) && ! empty( $options['deferred-options']['callback'] ) && is_callable( $options['deferred-options']['callback'] ) ) {
		if ( isset( $options['deferred-options']['args'] ) ) {
			$options['options'] = call_user_func_array( $options['deferred-options']['callback'], $options['deferred-options']['args'] );
		} else {
			$options['options'] = call_user_func( $options['deferred-options']['callback'] );
		}
	}
}

if ( empty( $options['options'] ) ) {
	return;
}

$value     = isset( $options['value'] ) && is_array( $options['value'] ) ? $options['value'] : array();
$check_all = ( ! isset( $options['check_all'] ) || $options['check_all'] ) && ! bf_count( $value ) ? true : false;

$groups_ids = array();

?>

<div class="bf-sorter-groups-container">
	<ul id="bf-sorter-group-<?php echo esc_attr( $options['id'] ); ?>"
	    class="bf-sorter-list bf-sorter-<?php echo esc_attr( $options['id'] ); ?>">
		<?php
		// Options That Saved Before
		foreach ( $value as $item_id => $item ) {
			if ( ! $item ) {
				continue;
			}
			if ( ! isset( $options['options'][ $item_id ] ) ) {
				continue;
			}
			?>
			<li id="bf-sorter-group-item-<?php echo esc_attr( $options['id'] ); ?>-<?php echo esc_attr( $item_id ); ?>"
			    class="<?php echo isset( $options['options'][ $item_id ]['css-class'] ) ? esc_attr( $options['options'][ $item_id ]['css-class'] ) : ''; ?> item-<?php echo esc_attr( $item_id ); ?> checked-item"
			    style="<?php echo isset( $options['options'][ $item_id ]['css'] ) ? esc_attr( $options['options'][ $item_id ]['css'] ) : ''; ?>">
				<label>
					<input name="<?php echo esc_attr( $options['input_name'] ) ?>[<?php echo esc_attr( $item_id ); ?>]"
					       value="1" type="checkbox" checked="checked"/>
					<?php echo $options['options'][ $item_id ]['label']; // escaped before ?>
				</label>
			</li>
			<?php

			unset( $options['options'][ $item_id ] );

		}

		// Options That Not Saved but are Active
		foreach ( $options['options'] as $item_id => $item ) {

			// Skip Disabled Items
			if ( isset( $item['css-class'] ) && strpos( $item['css-class'], 'active-item' ) === false ) {
				continue;
			}
			?>
			<li id="bf-sorter-group-item-<?php echo esc_attr( $options['id'] ); ?>-<?php echo esc_attr( $item_id ); ?>"
			    class="<?php echo isset( $item['css-class'] ) ? esc_attr( $item['css-class'] ) : ''; ?> item-<?php echo esc_attr( $item_id ); ?> <?php echo $check_all ? ' checked-item' : ''; ?>" <?php echo $check_all ? ' checked="checked" ' : ''; ?>
			    style="<?php echo isset( $item['css'] ) ? esc_attr( $item['css'] ) : ''; ?>">
				<label>
					<input name="<?php echo esc_attr( $options['input_name'] ) ?>[<?php echo esc_attr( $item_id ); ?>]"
					       value="1" type="checkbox" <?php echo $check_all ? ' checked="checked" ' : ''; ?>/>
					<?php echo is_array( $item ) ? $item['label'] : $item; // escaped before ?>
				</label>
			</li>
			<?php

			unset( $options['options'][ $item_id ] );
		}

		// Disable Items
		foreach ( $options['options'] as $item_id => $item ) { ?>
			<li id="bf-sorter-group-item-<?php echo esc_attr( $options['id'] ); ?>-<?php echo esc_attr( $item_id ); ?>"
			    class="<?php echo isset( $item['css-class'] ) ? esc_attr( $item['css-class'] ) : ''; ?> item-<?php echo esc_attr( $item_id ); ?>"
			    style="<?php echo isset( $item['css'] ) ? esc_attr( $item['css'] ) : ''; ?>">
				<label>
					<input name="<?php echo esc_attr( $options['input_name'] ) ?>[<?php echo esc_attr( $item_id ); ?>]"
					       value="0" type="checkbox" disabled/>
					<?php echo is_array( $item ) ? $item['label'] : $item; // escaped before ?>
				</label>
			</li>
			<?php
		}

		?>
	</ul>
	<?php

	echo $this->get_filed_input_desc( $options ); // escaped before

	?>
</div>
libs/better-framework/core/field-generator/fields/image_upload.php000064400000003706151214002460021362 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// TODO: change style for showing demo of uploaded image
$is_img = ! empty( $options['value'] ) && preg_match( '/(gif)|(jpg)|(png)(jpeg)/i', pathinfo( $options['value'], PATHINFO_EXTENSION ) );

// Text Input
$input_text = Better_Framework::html()->add( 'input' )->type( 'text' );
$input_text->name( $options['input_name'] );
if ( $options['value'] !== false ) {
	$input_text->value( $options['value'] );
}
echo $input_text->display(); // escaped before

// Upload Button
$btn = Better_Framework::html()->add( 'label' )->class( 'bf-button' );
$btn->add( __( 'Upload', 'better-studio' ) );
$btn->add( Better_Framework::html()->add( 'input' )->name( 'bf_image_upload_' . $options['id'] )->class( 'bf-image-upload-choose-file hidden bf-button bf-main-button' )->type( 'file' ) );
echo $btn->display(); // escaped before


// Progress Bar
$bar = Better_Framework::html()->add( 'div' )->class( 'bf-image-upload-progress-bar' )->add( '<div class="bar"></div>' );
echo $bar->display(); // escaped before

// Image Preview
if ( $is_img ) {
	echo Honar::html()->add( 'div' )->class( 'bf-image-upload-preview' )->add( Better_Framework::html()->add( 'img' )->src( $options['value'] ) ); // escaped before
}libs/better-framework/core/field-generator/class-bf-ajax-select-callbacks.php000064400000012447151214002460023275 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

if ( class_exists( 'BF_Ajax_Select_Callbacks' ) ) {
	return;
}


/**
 * Contain General callbacks that used in BF Ajax Select field
 */
class BF_Ajax_Select_Callbacks {


	/**
	 * Used for finding post name from ID
	 *
	 * @param $id
	 *
	 * @return string
	 */
	static function post_name( $id ) {

		return get_the_title( $id );

	}


	/**
	 * Used to retrieving posts from an keyword
	 *
	 * @param $keyword
	 * @param $exclude
	 *
	 * @return array
	 */
	static function posts_callback( $keyword, $exclude ) {

		$exclude = explode( ',', $exclude );

		$q = new WP_Query( array(
			'post_type'      => array( 'post' ),
			'posts_per_page' => 10,
			's'              => $keyword,
			'post__not_in'   => $exclude
		) );

		$results = array();

		while( $q->have_posts() ) {

			$q->the_post();

			$results[ get_the_ID() ] = get_the_title();

		}

		return $results;
	}


	/**
	 * Used for finding page name from ID
	 *
	 * @param $id
	 *
	 * @return string
	 */
	static function page_name( $id ) {

		return get_the_title( $id );

	}


	/**
	 * Used to retrieving pages from an keyword
	 *
	 * @param $keyword
	 * @param $exclude
	 *
	 * @return array
	 */
	static function pages_callback( $keyword, $exclude ) {

		$exclude = explode( ',', $exclude );

		$q = new WP_Query( array(
			'post_type'      => array( 'page' ),
			'posts_per_page' => 10,
			's'              => $keyword,
			'post__not_in'   => $exclude
		) );

		$results = array();

		while( $q->have_posts() ) {

			$q->the_post();

			$results[ get_the_ID() ] = get_the_title();

		}

		return $results;
	}


	/**
	 * Used for finding Category Name from ID
	 *
	 * @param $id
	 *
	 * @return string
	 */
	static function cat_name( $id ) {

		$cat = get_term( $id, 'category' );

		return $cat->name;
	}


	/**
	 * Used for finding Category Name from slug
	 *
	 * @param $id
	 *
	 * @return string
	 */
	static function cat_by_slug_name( $id ) {

		$cat = get_term_by( 'slug', $id, 'category' );

		return $cat->name;
	}


	/**
	 * Used to retrieving Categories from an keyword
	 *
	 * @param $keyword
	 * @param $exclude
	 *
	 * @return array
	 */
	static function cats_callback( $keyword, $exclude ) {

		$results = array();

		$exclude = explode( ',', $exclude );

		$args = array(
			'search'  => $keyword,
			'exclude' => $exclude
		);

		$terms = get_terms( "category", $args );

		if ( ! empty( $terms ) && ! is_wp_error( $terms ) ) {

			foreach ( $terms as $term ) {
				$results[ $term->term_id ] = $term->name;
			}

		}

		return $results;
	}


	/**
	 * Used to retrieving Categories from an keyword ( cat slug as id )
	 *
	 * @param $keyword
	 * @param $exclude
	 *
	 * @return array
	 */
	static function cats_slug_callback( $keyword, $exclude ) {

		$results = array();

		$exclude = explode( ',', $exclude );

		$args = array(
			'search'  => $keyword,
			'exclude' => $exclude
		);

		$terms = get_terms( "category", $args );

		if ( ! empty( $terms ) && ! is_wp_error( $terms ) ) {

			foreach ( $terms as $term ) {
				$results[ $term->slug ] = $term->name;
			}
		}

		return $results;
	}


	/**
	 * Used for finding Category Name from ID
	 *
	 * @param $id
	 *
	 * @return string|void string on success or null on failure.
	 */
	static function tag_name( $id ) {

		$cat = get_term( $id, 'post_tag' );

		if ( $cat && ! is_wp_error( $cat ) ) {
			return $cat->name;
		}
	}


	/**
	 * Used for finding Category Name from slug
	 *
	 * @param $id
	 *
	 * @return string
	 */
	static function tag_by_slug_name( $id ) {

		$cat = get_term_by( 'slug', $id, 'post_tag' );

		return $cat->name;
	}


	/**
	 * Used to retrieving Tags from an keyword
	 *
	 * @param $keyword
	 * @param $exclude
	 *
	 * @return array
	 */
	static function tags_callback( $keyword, $exclude ) {

		$results = array();

		$exclude = explode( ',', $exclude );

		$args = array(
			'search'     => $keyword,
			'exclude'    => $exclude,
			'hide_empty' => false
		);

		$terms = get_terms( "post_tag", $args );

		if ( ! empty( $terms ) && ! is_wp_error( $terms ) ) {

			foreach ( $terms as $term ) {
				$results[ $term->term_id ] = $term->name;
			}
		}

		return $results;
	}


	/**
	 * Used to retrieving Tags from an keyword
	 *
	 * @param $keyword
	 * @param $exclude
	 *
	 * @return array
	 */
	static function tags_slug_callback( $keyword, $exclude ) {

		$results = array();

		$exclude = explode( ',', $exclude );

		$args = array(
			'search'  => $keyword,
			'exclude' => $exclude
		);

		$terms = get_terms( "post_tag", $args );

		if ( ! empty( $terms ) && ! is_wp_error( $terms ) ) {

			foreach ( $terms as $term ) {
				$results[ $term->slug ] = $term->name;
			}
		}

		return $results;
	}

}libs/better-framework/core/field-generator/modals/icon.php000064400000020563151214002460017675 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// Fire up icon factory
Better_Framework::factory( 'icon-factory' );

// Get fontawesome instance
$fontawesome = BF_Icons_Factory::getInstance( 'fontawesome' );

// BS Icons
$bs_icons = BF_Icons_Factory::getInstance( 'bs-icons' );

// Default selected
$current = array(
	'key'   => '',
	'title' => '',
);

?>
<div id="better-icon-modal" class="better-modal icon-modal" data-remodal-id="better-icon-modal" role="dialog">
	<div class="modal-inner">

		<div class="modal-header">
			<span><?php esc_html_e( 'Chose an Icon', 'better-studio' ); ?></span>
			<div class="better-icons-search bf-clearfix">
				<input type="text" class="better-icons-search-input"
				       placeholder="<?php esc_html_e( 'Search...', 'better-studio' ); ?>"/>
				<i class="clean fa fa-search"></i>
			</div>
		</div><!-- modal header -->

		<div class="modal-body bf-clearfix">

			<div class="icons-container bf-clearfix">

				<div class="icons-inner bf-clearfix">
					<?php

					$custom_icons = get_option( Better_Framework::factory( 'icon-factory' )->get_custom_icons_id() );

					?>
					<h2 class="font-type-header">
						<span class="title"><?php esc_html_e( 'Custom Icons', 'better-studio' ); ?></span>
						<span data-button-text="<?php esc_html_e( 'Select Icon', 'better-studio' ); ?>"
						      data-media-title="<?php esc_html_e( 'Select Icon', 'better-studio' ); ?>"
						      class="upload-custom-icon"><i
									class="bf-icon fa fa-upload "></i> <?php esc_html_e( 'Upload Custom Icon', 'better-studio' ); ?></span>
					</h2>
					<ul class="icons-list custom-icons-list bf-clearfix">
						<?php

						if ( $custom_icons ) {
							foreach ( (array) $custom_icons as $icon ) {

								if ( ! isset( $icon['width'] ) ) {
									$icon['width'] = '';
								}

								if ( ! isset( $icon['height'] ) ) {
									$icon['height'] = '';
								}

								?>
								<li data-id="<?php echo esc_attr( $icon['id'] ); ?>"
								    class="icon-select-option custom-icon"
								    data-custom-icon="<?php echo esc_attr( $icon['icon'] ); ?>"
								    data-width="<?php echo esc_attr( $icon['width'] ); ?>"
								    data-height="<?php echo esc_attr( $icon['height'] ); ?>" data-type="custom-icon">
									<?php echo bf_get_icon_tag( $icon ); ?>
									<i class="fa fa-close delete-icon"></i>
								</li>
								<?php
							}
						}

						?>
					</ul><!-- icons list -->

					<p class="no-custom-icon <?php echo $custom_icons ? 'hidden' : ''; ?>"><?php esc_html_e( 'No custom icon created!.', 'better-studio' ); ?></p>

					<!-- FontAwesome Icons -->
					<h2 class="font-type-header"><span
								class="title"><?php esc_html_e( 'Fontawesome Icons', 'better-studio' ); ?></span></h2>
					<ul class="icons-list font-icons bf-clearfix">
						<li data-value="" data-label="<?php esc_html_e( 'Chose an Icon', 'better-studio' ); ?>"
						    class="icon-select-option default-option">
							<p><?php esc_html_e( 'No Icon', 'better-studio' ); ?></p>
						</li>
						<?php

						foreach ( (array) $fontawesome->icons as $key => $icon ) {
							$_cats = '';

							if ( isset( $icon['category'] ) ) {
								foreach ( $icon['category'] as $category ) {
									$_cats .= ' cat-' . $category;
								}
							}
							?>

							<li data-value="<?php echo esc_attr( $key ); ?>"
							    data-label="<?php echo esc_attr( $icon['label'] ); ?>"
							    data-font-code="<?php echo esc_attr( $icon['font_code'] ); ?>"
							    data-categories="<?php echo esc_attr( $_cats ); ?>"
							    class="icon-select-option <?php echo ( $key === $current['key'] ? 'selected' : '' ) . esc_attr( $_cats ); ?>"
							    data-type="fontawesome">
								<?php echo $fontawesome->getIconTag( $key ); // escaped before in function ?> <span
										class="label"><?php echo esc_html( $icon['label'] ); ?></span>
							</li>

							<?php
						}

						?>
					</ul><!-- icons list -->

					<!-- /FontAwesome Icons -->

					<!-- BS Icons -->
					<h2 class="font-type-header"><span
								class="title"><?php esc_html_e( 'BetterStudio Icons', 'better-studio' ); ?></span></h2>
					<ul class="icons-list font-icons bf-clearfix">
						<?php

						foreach ( (array) $bs_icons->icons as $key => $icon ) {
							$_cats = '';

							if ( isset( $icon['category'] ) ) {
								foreach ( $icon['category'] as $category ) {
									$_cats .= ' cat-' . $category;
								}
							}
							?>

							<li data-value="<?php echo esc_attr( $key ); ?>"
							    data-label="<?php echo esc_attr( $icon['label'] ); ?>"
							    data-categories="<?php echo esc_attr( $_cats ); ?>"
							    data-font-code="<?php echo esc_attr( isset( $icon['font_code'] ) ? $icon['font_code'] : '' ); ?>"
							    class="icon-select-option <?php echo ( $key === $current['key'] ? 'selected' : '' ) . esc_attr( $_cats ); ?>"
							    data-type="bs-icons">
								<?php echo $bs_icons->getIconTag( $key ); // escaped before in function ?> <span
										class="label"><?php echo esc_html( $icon['label'] ); ?></span>
							</li>

							<?php
						}

						?>
					</ul><!-- icons list -->
					<!-- /BS Icons -->

				</div><!-- /icons inner -->
			</div><!-- /icons container -->

			<div class="cats-container bf-clearfix">

				<ul class="better-icons-category-list bf-clearfix">
					<li class="icon-category selected" id="cat-all">
						<span data-cat="#cat-all"><?php esc_html_e( 'All ', 'better-studio' ); ?></span> <span
								class="text-muted">(<?php echo bf_count( $fontawesome->icons ) + bf_count( $bs_icons->icons ); ?>
							)</span>
					</li>
					<?php

					foreach ( (array) $fontawesome->categories as $key => $category ) {

						?>
						<li class="icon-category" id="cat-<?php echo esc_attr( $category['id'] ); ?>">
							<span
									data-cat="#cat-<?php echo esc_attr( $category['id'] ); ?>"><?php echo esc_html( $category['label'] ); ?></span>
							<span class="text-muted">(<?php echo esc_html( $category['counts'] ); ?>)</span>
						</li>
						<?php
					}

					foreach ( (array) $bs_icons->categories as $key => $category ) {

						?>
						<li class="icon-category" id="cat-<?php echo esc_attr( $category['id'] ); ?>">
							<span
									data-cat="#cat-<?php echo esc_attr( $category['id'] ); ?>"><?php echo esc_html( $category['label'] ); ?></span>
							<span class="text-muted">(<?php echo esc_html( $category['counts'] ); ?>)</span>
						</li>
						<?php
					}

					?>
				</ul><!-- categories list -->

			</div><!-- /cats container -->

			<div class="upload-custom-icon-container">
				<div class="upload-custom-icon-inner">
					<div class="custom-icon-fields">

						<div class="section-header">
							<span><?php esc_html_e( 'Inset Custom Icon', 'better-studio' ); ?></span>
						</div>

						<div class="section-body">
							<span class="icon-helper"></span>
							<img src="" class="icon-preview">
						</div>

						<div class="icon-fields">
							<?php esc_html_e( 'Width:', 'better-studio' ); ?> <input type="text" name="icon-width"
							                                                         placeholder="<?php esc_html_e( 'Auto', 'better-studio' ); ?>">
							<?php esc_html_e( 'Height:', 'better-studio' ); ?> <input type="text" name="icon-height"
							                                                          placeholder="<?php esc_html_e( 'Auto', 'better-studio' ); ?>">
						</div>

						<div class="section-footer">
							<a href="#"
							   class="bf-button bf-main-button"><?php esc_html_e( 'Insert Icon', 'better-studio' ); ?></a>
						</div>
					</div>
					<div class="icon-uploader-loading">
						<i class="fa fa-refresh fa-spin"></i>
					</div>

					<i class="close-custom-icon fa fa-close"></i>
				</div>
			</div>
		</div><!-- /modal body -->
	</div><!-- /modal inner -->
</div><!-- /modal -->libs/better-framework/core/field-generator/functions.php000064400000003774151214002460017503 0ustar00<?php

if ( ! function_exists( 'bf_show_on_attributes' ) ) {

	/**
	 * Generate required attributes for fields wrapper to handle 'show_on' feature
	 *
	 * @param array $options
	 *
	 * @since 2.8.7
	 *
	 * @return string
	 */
	function bf_show_on_attributes( $options ) {

		bf_convert_filter_field_to_show_on( $options );

		$attributes = '';

		$attributes .= ' data-param-name="';
		$attributes .= isset( $options['id'] ) ? esc_attr( $options['id'] ) : '';
		$attributes .= '"';

		if ( $settings = bf_show_on_settings( $options ) ) {
			$attributes .= ' data-param-settings="';
			$attributes .= esc_attr( json_encode( $settings ) );
			$attributes .= '"';
		}

		return $attributes;
	}
}

if ( ! function_exists( 'bf_show_on_settings' ) ) {

	/**
	 * @param array $options
	 *
	 * @return array
	 */
	function bf_show_on_settings( $options ) {

		if ( ! class_exists( 'BF_Admin_Fields' ) ) {
			require BF_PATH . 'core/field-generator/class-bf-admin-fields.php';
		}

		return array_intersect_key( $options, BF_Admin_Fields::$public_options );
	}
}

if ( ! function_exists( 'bf_convert_filter_field_to_show_on' ) ) {

	/**
	 * filter-field attribute backward compatibility
	 *
	 * @param array $options
	 *
	 * @since 2.8.7
	 */
	function bf_convert_filter_field_to_show_on( &$options ) {

		if ( ! empty( $options['filter-field'] ) && isset( $options['filter-field-value'] ) ) {

			$options['show_on'] = array(
				array( sprintf( '%s=%s', $options['filter-field'], $options['filter-field-value'] ) )
			);

			unset( $options['filter-field'] );
			unset( $options['filter-field-value'] );
		}
	}
}

if ( ! function_exists( 'bf_field_extra_options' ) ) {

	/**
	 * Get extra options name available for field
	 *
	 * @param string $field_type
	 *
	 * @since 3.0.0
	 * @return array
	 */
	function bf_field_extra_options( $field_type ) {

		$options = array();

		switch ( $field_type ) {
			case 'select_popup':

				$options = array( 'texts', 'confirm_texts', 'column_class', 'confirm_changes' );
				break;
		}

		return $options;
	}
}
libs/better-framework/core/field-generator/class-bf-admin-fields.php000064400000053367151214002460021522 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * todo refactor this
 */
abstract class BF_Admin_Fields {

	/**
	 * Holds All Field Generator Options
	 *
	 * @since  1.0
	 * @access private
	 * @var array
	 */
	protected $options = array();


	/**
	 * Holds all fields
	 *
	 * @since  1.0
	 * @access private
	 * @var array
	 */
	protected $items = array();


	/**
	 * Panel ID
	 *
	 * @since  1.0
	 * @access public
	 * @var string
	 */
	protected $id;


	/**
	 * Panel Values
	 *
	 * @since  1.0
	 * @access public
	 * @var array
	 */
	protected $values;


	/**
	 * Store options keys which will be print in html source
	 *
	 * @since BF 2.8.4
	 * @var array
	 */
	public static $public_options = array( 'show_on' => '' );

	/**
	 * Holds All Supported Fields
	 *
	 * @since  1.0
	 * @access public
	 * @var array
	 */
	public $supported_fields = array(
		'text',
		'textarea',
		'wp_editor',
		'code',
		'color',
		'date',
		'slider',
		'radio',
		'checkbox',
		'switch',
		'repeater',
		'select',
		'ajax_select',
		'ajax_action',
		'sorter',
		'sorter_checkbox',
		'heading',
		'media',
		'background_image',
		'media_image',
		'image_upload',
		'image_checkbox',
		'image_radio',
		'image_select',
		'icon_select',
		'typography',
		'border',
		'export',
		'import',
		'info',
		'custom',
		'hr',
		'group_close',
		'editor',
		'term_select',
		'image_preview',
		'select_popup',
	);


	/**
	 * Holds All Supported Fields in Repeater Field
	 *
	 * @since  1.4
	 * @access public
	 * @var array
	 */
	public $supported_fields_in_repeater = array(
		'text',
		'textarea',
		'ajax_select',
		'image_radio',
		'image_upload',
		'color',
		'date',
		'select',
		'icon_select',
		'media',
		'checkbox',
		'media_image',
		'image_select',
		'switch',
		'sorter_checkbox',
		'select_popup',
		'heading',
		'term_select',
	);


	/**
	 * PHP Constructor Function
	 *
	 * defining class options with constructor function
	 *
	 * @param array $items
	 *
	 * @since  1.0
	 * @access public
	 * @return \BF_Admin_Fields
	 */
	public function __construct( $items = array() ) {

		bf_require_once( 'core/field-generator/class-bf-ajax-select-callbacks.php' );

		$default_options = array(
			'fields_dir'    => BF_PATH . 'core/field-generator/fields/',
			'modals_dir'    => BF_PATH . 'core/modals/',
			'templates_dir' => BF_PATH . 'core/templates/',
			'section-file'  => BF_PATH . 'core/templates/default-fileld-template.php'
		);

		$this->options = array_merge( $default_options, $items );

	}


	/**
	 * Setting object settings
	 *
	 * This class is for setting options
	 *
	 * @param  (string)               $option_name    Name of option
	 * @param  (array|sting|bool)   $option_value    Value of option
	 *
	 * @since  1.0
	 * @access public
	 * @return object
	 */
	public function set( $option_name, $option_value ) {

		$this->options[ $option_name ] = $option_value;

		return $this;
	}


	/**
	 * Check if the panel has specific field
	 *
	 * @param  (string) $type Field Type
	 *
	 * @since  1.0
	 * @access public
	 * @return bool
	 */
	public function has_field( $field ) {

		$has = false;
		foreach ( $this->items as $item ) {
			if ( isset( $item['type'] ) && $item['type'] == $field ) {
				return true;
			}
		}

		return (bool) $has;
	}


	/**
	 * Used for checking meta box have tab or not
	 *
	 * @return bool
	 */
	public function has_tab() {

		foreach ( $this->items['fields'] as $field ) {
			if ( $field['type'] == 'tab' ) {
				return true;
			}
		}

		return false;

	}


	/**
	 * Wrap the input in a section
	 *
	 * This class is for setting options
	 *
	 * @param  (string)    $input   The string value of input (<input />))
	 * @param  (array)   $option     Field options (like name, id etc)
	 *
	 * @since  1.0
	 * @access public
	 * @return string
	 */
	public function section( $input, $options ) {

		$template_file = $this->options['templates_dir'] . $options['type'] . '.php';
		ob_start();

		if ( ! file_exists( $template_file ) ) {
			require $this->options['templates_dir'] . 'default.php';
		} else {
			require $template_file;
		}

		return ob_get_clean();

	}


	/**
	 * Make input name from options variable
	 *
	 * @param  (array) $options Options array
	 *
	 * @since  1.0
	 * @access public
	 * @return string
	 */
	public function input_name( &$options ) {

		$id   = isset( $options['id'] ) ? $options['id'] : '';
		$type = isset( $options['type'] ) ? $options['type'] : '';

		switch ( $type ) {

			case( 'image_checkbox' ):
				return "{$id}[%s]";
				break;

			default:
				return $id;
				break;

		}

	}


	/**
	 * Get classes - @Vahid WTF!!!
	 *
	 * get element classes array
	 *
	 * @param  (type) about this param
	 *
	 * @since  1.0
	 * @access public
	 * @return array
	 */
	public function get_classes( &$options ) {

		$is_repeater = isset( $options['repeater_item'] ) && $options['repeater_item'] === true;
		$classes     = array();

		$classes['section'] = apply_filters( 'better-framework/field-generator/class/section', 'bf-section' );
		$classes['section'] .= ! isset( $options['section_class'] ) ? '' : ' ' . $options['section_class'];

		$classes['container'] = apply_filters( 'better-framework/field-generator/class/container', 'bf-section-container' );
		$classes['container'] .= ! isset( $options['container_class'] ) ? '' : ' ' . $options['container_class'];

		if ( isset( $options['direction'] ) ) {
			$classes['container'] .= ! isset( $options['container_class'] ) ? ' dir-' . $options['direction'] : ' ' . $options['container_class'] . ' dir-' . $options['direction'];
		}

		$classes['repeater-section']                        = apply_filters( 'better-framework/field-generator/class/section/repeater', 'bf-repeater-section-option' );
		$classes['nonrepeater-section']                     = apply_filters( 'better-framework/field-generator/class/section/nonrepeater', 'bf-nonrepeater-section' );
		$classes['section-class-by-filed-type']             = apply_filters( 'better-framework/field-generator/class/section/by/type', 'bf-section-' . $options['type'] . '-option', $options['type'] );
		$classes['nonrepeater-section-class-by-filed-type'] = apply_filters( 'better-framework/field-generator/class/section/nonrepeater/by/type', 'bf-nonrepeater-' . $options['type'] . '-section', $options['type'] );
		$classes['repeater-section-class-by-filed-type']    = apply_filters( 'better-framework/field-generator/class/section/repeater/by/type', 'bf-repeater-' . $options['type'] . '-section', $options['type'] );

		$classes['heading']                                 = apply_filters( 'better-framework/field-generator/class/heading', 'bf-heading' );
		$classes['repeater-heading']                        = apply_filters( 'better-framework/field-generator/class/heading/repeater', 'bf-repeater-heading-option' );
		$classes['nonrepeater-heading']                     = apply_filters( 'better-framework/field-generator/class/heading/nonrepeater', 'bf-nonrepeater-heading' );
		$classes['heading-class-by-filed-type']             = apply_filters( 'better-framework/field-generator/class/heading/by/type', 'bf-heading-' . $options['type'] . '-option', $options['type'] );
		$classes['nonrepeater-heading-class-by-filed-type'] = apply_filters( 'better-framework/field-generator/class/heading/nonrepeater/by/type', 'bf-nonrepeater-' . $options['type'] . '-heading', $options['type'] );
		$classes['repeater-heading-class-by-filed-type']    = apply_filters( 'better-framework/field-generator/class/heading/repeater/by/type', 'bf-repeater-' . $options['type'] . '-heading', $options['type'] );

		$classes['controls']                                 = apply_filters( 'better-framework/field-generator/class/controls', 'bf-controls' );
		$classes['repeater-controls']                        = apply_filters( 'better-framework/field-generator/class/heading/repeater', 'bf-repeater-controls-option' );
		$classes['nonrepeater-controls']                     = apply_filters( 'better-framework/field-generator/class/heading/nonrepeater', 'bf-nonrepeater-controls' );
		$classes['controls-class-by-filed-type']             = apply_filters( 'better-framework/field-generator/class/heading/by/type', 'bf-controls-' . $options['type'] . '-option', $options['type'] );
		$classes['nonrepeater-controls-class-by-filed-type'] = apply_filters( 'better-framework/field-generator/class/heading/nonrepeater/by/type', 'bf-nonrepeater-' . $options['type'] . '-controls', $options['type'] );
		$classes['repeater-controls-class-by-filed-type']    = apply_filters( 'better-framework/field-generator/class/heading/repeater/by/type', 'bf-repeater-' . $options['type'] . '-controls', $options['type'] );

		$classes['explain']                                 = apply_filters( 'better-framework/field-generator/class/explain', 'bf-explain' );
		$classes['repeater-explain']                        = apply_filters( 'better-framework/field-generator/class/explain/repeater', 'bf-repeater-explain-option' );
		$classes['nonrepeater-explain']                     = apply_filters( 'better-framework/field-generator/class/explain/nonrepeater', 'bf-nonrepeater-explain' );
		$classes['explain-class-by-filed-type']             = apply_filters( 'better-framework/field-generator/class/explain/by/type', 'bf-explain-' . $options['type'] . '-option', $options['type'] );
		$classes['nonrepeater-explain-class-by-filed-type'] = apply_filters( 'better-framework/field-generator/class/explain/nonrepeater/by/type', 'bf-nonrepeater-' . $options['type'] . '-explain', $options['type'] );
		$classes['repeater-explain-class-by-filed-type']    = apply_filters( 'better-framework/field-generator/class/explain/repeater/by/type', 'bf-repeater-' . $options['type'] . '-explain', $options['type'] );

		return $classes;

	}


	/**
	 * Used for generating start tag of fields group
	 *
	 * @param $group
	 *
	 * @return string
	 */
	function get_fields_group_start( $group ) {

		$group_container_class = 'fields-group bf-clearfix';
		if ( isset( $group['container-class'] ) ) {
			$group_container_class .= ' ' . $group['container-class'];
		}

		$group_title_class = 'fields-group-title-container';
		if ( isset( $group['title-class'] ) ) {
			$group_title_class .= ' ' . $group['title-class'];
		}

		if ( ! empty( $group['ajax-section'] ) ) {
			$group_container_class .= ' bf-ajax-section ' . sanitize_html_class( $group['ajax-section'] );
		}

		if ( ! empty( $group['ajax-tab'] ) ) { // Backward compatibility
			$group_container_class .= ' bf-ajax-tab';
		}


		if ( ! isset( $group['id'] ) ) {
			$group['id'] = time();
		}

		if ( isset( $group['color'] ) ) {
			$color = $group['color'];
		} else {
			$color = '';
		}

		// Collapsible feature
		if ( isset( $group['state'] ) ) {
			$state = $group['state'];
		} else {
			$state = 'open';
		}
		if ( $state == 'close' ) {

			$group_container_class .= ' collapsible close';
			$collapse_button       = '<span class="collapse-button"><i class="fa fa-plus"></i></span>';


		} elseif ( $state == 'open' ) {

			$group_container_class .= ' collapsible open';
			$collapse_button       = '<span class="collapse-button"><i class="fa fa-minus"></i></span>';


		} else {

			$group_container_class .= ' not-collapsible';
			$collapse_button       = '';

		}


		// Desc
		if ( ! empty( $group['desc'] ) ) {
			$desc = "<div class='bf-group-desc'>{$group['desc']}</div>";
		} else {
			$desc = "";
		}

		$output = "\n\n<!-- Fields Group -->\n<div class='{$group_container_class} {$color}' id='fields-group-{$group['id']}'\n";

		$output .= bf_show_on_attributes( $group );
		$output .= '>';

		$output .= "<div class='{$group_title_class}'><span class='fields-group-title'>{$group['name']}</span>{$collapse_button}</div>";
		$output .= "<div class='bf-group-inner bf-clearfix' style='" . ( $state == 'close' ? 'display:none;' : '' ) . "'>$desc";

		return $output;
	}


	/**
	 * Used for generating close tag of fields group
	 *
	 * @param $group
	 *
	 * @return string
	 */
	function get_fields_group_close( $group = '' ) {

		return '</div></div>';

	}


	/**
	 * Used for generating repeater field
	 *
	 * @param $panel_or_metabox          array           Repeater field information's
	 * @param $field                     array           Field information's
	 * @param $defaults                  string|int|bool Field Value
	 * @param $name_format               string          Field name
	 * @param $number                    int             Field id in repeater values
	 *
	 * @return string
	 */
	function generate_repeater_field( $panel_or_metabox, $field, $defaults, $name_format, $number ) {

		if (
			empty( $field['id'] )
			|| empty( $field['type'] )
			|| ! in_array( $field['type'], $this->supported_fields_in_repeater )
		) {
			return;
		}

		// Repeater in metabox
		if ( isset( $panel_or_metabox['metabox-field'] ) && $panel_or_metabox['metabox-field'] ) {
			$field['input_name'] = sprintf( $name_format, $panel_or_metabox['metabox-id'], $panel_or_metabox['id'], $number, $field['id'] );
		} // Repeater in widgets
		elseif ( isset( $panel_or_metabox['widget_field'] ) ) {
			$field['input_name'] = sprintf( $field['input_name'], $number );
		} // General Repeater
		else {
			$field['input_name'] = sprintf( $name_format, $panel_or_metabox['id'], $number, $field['id'] );
		}

		if ( isset( $field['filter-field'] ) && $field['filter-field-value'] ) {

			if ( isset( $defaults[ $field['filter-field'] ] ) && $field['filter-field-value'] !== $defaults[ $field['filter-field'] ] ) {

				$field['section-css']['display'] = "none";

			}

		}

		$field['value'] = isset( $defaults[ $field['id'] ] ) ? $defaults[ $field['id'] ] : '';

		echo call_user_func(
			array( $this, 'section' ),
			call_user_func(
				array( $this, $field['type'] ),
				$field
			),
			$field
		);

	}


	/**
	 * Used for generating repeater field script tags
	 * that will be used adding more items in front end
	 *
	 * @param $panel_or_metabox          array           Repeater field information's
	 * @param $field                     array           Field Information's
	 * @param $defaults                  string|int|bool Field value
	 *
	 * @return string
	 */
	function generate_repeater_field_script( $panel_or_metabox, $field, $defaults ) {

		if ( ! isset( $field['type'] ) || ! in_array( $field['type'], $this->supported_fields_in_repeater ) ) {
			return;
		}

		// Repeater in metabox
		if ( isset( $panel_or_metabox['metabox-field'] ) && $panel_or_metabox['metabox-field'] ) {
			$field['input_name'] = "|_to_clone_{$panel_or_metabox['metabox-id']}-child-{$panel_or_metabox['id']}-num-{$field['id']}|";
		} // Repeater in widgets
		elseif ( isset( $panel_or_metabox['widget_field'] ) ) {
			$field['input_name'] = "|_to_clone_{$panel_or_metabox['id']}-num-{$field['id']}|";
		} // General Repeater
		else {
			$field['input_name'] = "|_to_clone_{$panel_or_metabox['id']}-num-{$field['id']}|";
		}

		if ( isset( $field['filter-field'] ) && $field['filter-field-value'] ) {

			if ( isset( $defaults[ $field['filter-field'] ] ) && $field['filter-field-value'] !== $defaults[ $field['filter-field'] ] ) {

				$field['section-css']['display'] = "none";

			}
		}

		if ( isset( $field['id'] ) && isset( $defaults[ $field['id'] ] ) ) {
			$field['value'] = $defaults[ $field['id'] ];
		} else {
			$field['value'] = '';
		}

		echo call_user_func(
			array( $this, 'section' ),
			call_user_func(
				array( $this, $field['type'] ),
				$field
			),
			$field
		);

	}


	/**
	 * PHP __call Magic Function
	 *
	 * @param $name
	 * @param $arguments
	 *
	 * @throws Exception
	 * @internal param $ (string) $name      name of requested method
	 * @internal param $ (array)  $arguments arguments of requested method
	 *
	 * @since    1.0
	 * @access   public
	 * @return mixed
	 */
	public function __call( $name, $arguments ) {

		$file = $this->options['fields_dir'] . $name . '.php';

		// Check if requested field (method) does exist!
		if ( ! file_exists( $file ) ) {
			throw new Exception( sprintf( __( '%s does not exist!', 'better-studio' ), $name ) );
		}

		$options = $arguments[0];

		// Capture output
		ob_start();
		require $file;

		$data = ob_get_clean();

		return $data;
	}


	//
	//
	// Handy functions
	//
	//


	/**
	 * Used for generating section css attr from field array
	 *
	 * @since 2.0
	 *
	 * @param $field
	 *
	 * @return string
	 */
	function get_section_css_attr( $field ) {

		$attr = '';

		if ( isset( $field['section-css'] ) ) {

			$attr = 'style="';

			foreach ( (array) $field['section-css'] as $css_id => $css_code ) {

				$attr .= $css_id . ':' . $css_code . ';';

			}

			$attr .= '"';
		}


		return $attr;
	}


	/**
	 * Used for generating section field attr from field array
	 *
	 * @since 2.0
	 *
	 * @param $field
	 *
	 * @return string
	 */
	function get_section_filter_attr( $field ) {

		return bf_show_on_attributes( $field );
	}


	/**
	 * Used for creating field input desc
	 *
	 * @since 2.0
	 *
	 * @param $field
	 *
	 * @return string
	 */
	function get_filed_input_desc( $field ) {

		if ( isset( $field['input-desc'] ) ) {
			return '<div class="input-desc">' . $field['input-desc'] . '</div>'; // escaped before
		} else {
			return '';
		}

	}


	/**
	 * Return The HTML Output of Tabs
	 *
	 * @since 1.0
	 * @return string
	 */
	public function get_tabs() {

		// Generate Tabs Array
		$tabs_array   = array();
		$prev_tab_key = 0;
		$menu_items   = array();

		foreach ( (array) $this->items['fields'] as $field ) {

			if ( ! isset( $field['type'] ) ) {
				continue;
			}

			if ( isset( $field['type'] ) && $field['type'] == 'tab' || $field['type'] == 'subtab' ) {
				$tabs_array[] = $field;
			}
		}

		foreach ( $tabs_array as $k => $v ) {
			$token = $v['id'];
			// Capture the token.
			$v['token'] = $token;
			if ( $v['type'] == 'tab' ) {
				$menu_items[ $token ] = $v;
				$prev_tab_key         = $token;
			}
			if ( $v['type'] == 'subtab' ) {
				$menu_items[ $prev_tab_key ]['children'][] = $v;
			}
		}


		if ( ! $menu_items ) {
			return '';
		}

		$output = '';
		$output .= '<ul>';

		foreach ( $menu_items as $tab_id => $tab ) {
			$hasChildren = isset( $tab['children'] ) && bf_count( $tab['children'] ) > 0;
			$class       = $hasChildren ? 'has-children' : '';

			if ( isset( $tab['margin-top'] ) ) {
				$class .= ' margin-top-' . $tab['margin-top'];
			}

			if ( isset( $tab['margin-bottom'] ) ) {
				$class .= ' margin-bottom-' . $tab['margin-bottom'];
			}
			if ( isset( $tab['ajax-tab'] ) ) {
				$class .= ' bf-ajax-tab';
			}

			if ( ! empty( $tab['ajax-section'] ) ) {
				$class .= ' bf-ajax-section ' . sanitize_html_class( $tab['ajax-section'] );
			}

			$output .= '<li class="' . $class . '" data-go="' . $tab_id . '">';
			$output .= '<a href="#" class="bf-tab-item-a" data-go="' . $tab['id'] . '">';


			// Icon
			if ( isset( $tab['icon'] ) && ! empty( $tab['icon'] ) ) {

				$output .= bf_get_icon_tag( $tab['icon'] ) . ' ';

			}

			$output .= $tab['name'];


			// Adds badge to tab
			if ( isset( $tab['badge'] ) && isset( $tab['badge']['text'] ) ) {

				$badge_style = '';

				if ( isset( $tab['badge']['color'] ) ) {
					$badge_style = "style='background-color:{$tab['badge']['color']};border-color:{$tab['badge']['color']}'";
				}

				$output .= "<span class='bf-tab-badge' {$badge_style}>{$tab['badge']['text']}</span>";
			}


			$output .= '</a>';

			if ( $hasChildren ) {

				$output .= '<ul class="sub-nav">';

				foreach ( $tab['children'] as $child ) {

					$output .= '<li>';
					$output .= '<a href="#" class="bf-tab-subitem-a" data-go="' . $child['id'] . '">' . $child['name'] . '</a>'; // escaped before
					$output .= '</li>';
				}

				$output .= '</ul>';

			}

			$output .= '</li>';
		}

		$output .= '</ul>';

		return $output;

	}


	/**
	 * @return array
	 */
	public function get_items() {

		return $this->items;
	}


	/**
	 * @param array $items
	 */
	public function set_items( $items ) {

		$this->items = $items;
	}


	/**
	 * @return array
	 */
	public function get_fields() {

		return $this->items['fields'];
	}


	/**
	 * @param array $fields
	 */
	public function set_fields( $fields ) {

		$this->items['fields'] = $fields;
	}


	/**
	 * Converts field to global standard field
	 *
	 * @param array  $field Field array
	 * @param string $type  Generator type
	 *
	 * @return mixed
	 */
	public function standardize_field( $field, $type = 'all' ) {

		//
		// Group fix
		//
		{
			// group level fix types
			$_group_level_fix = array(
				'group'       => '',
				'group_close' => '',
			);


			if ( isset( $_group_level_fix[ $field['type'] ] ) && ! isset( $field['level'] ) ) {
				$field['level'] = 0;
			}

		}

		return $field;
	}

} // BF_Admin_Fieldslibs/better-framework/core/field-generator/templates/default.php000064400000006052151214002460021105 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes = $classes['section'];

$heading_classes  = $classes['heading'];
$controls_classes = $classes['controls'];
$explain_classes  = $classes['explain'];

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];

if ( ! isset( $options['desc'] ) || empty( $options['desc'] ) ) {
	$controls_classes .= ' ' . 'no-desc';
}

$section_css = '';

if ( isset( $options['section-css'] ) ) {

	$_css = '';
	foreach ( (array) $options['section-css'] as $css_id => $css_code ) {
		$_css .= $css_id . ':' . $css_code . ';';
	}

	$section_css = 'style="' . esc_attr( $_css ) . '"';
}

?>
<div class="bf-section-container bf-clearfix" <?php echo $section_css; // escaped before ?>>
	<div class="<?php echo esc_attr( $section_classes ); ?> bf-clearfix"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>">

		<div class="<?php echo esc_attr( $heading_classes ); ?> bf-clearfix">
			<h3><label
						for="<?php echo esc_attr( $options['id'] ); ?>"><?php echo esc_attr( $options['name'] ); ?></label>
			</h3>
		</div>

		<div class="<?php echo esc_attr( $controls_classes ); ?> bf-clearfix">
			<?php echo $input; // escaped before in generator ?>
		</div>

		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div
					class="<?php echo esc_attr( $explain_classes ); ?> bf-clearfix"><?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?></div>
		<?php } ?>

	</div>
</div>libs/better-framework/core/field-generator/templates/hr.php000064400000001600151214002460020064 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div class="bf-section-container bf-clearfix">
	<div class="bf-section-hr bf-clearfix">
		<?php echo $input; // escaped before ?>
	</div>
</div>libs/better-framework/core/field-generator/templates/heading.php000064400000002362151214002460021060 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

$style = ! empty( $options['layout'] ) ? $options['layout'] : 'style-1';

?>
<div class="bf-section-container bf-clearfix">
	<div class="bf-section-heading bf-clearfix <?php echo $style; ?>">
		<div class="bf-section-heading-title bf-clearfix">
			<h3><?php echo esc_html( $options['name'] ); ?></h3>
		</div>
		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div
					class="bf-section-heading-desc bf-clearfix"><?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?></div>
		<?php } ?>
	</div>
</div>
libs/better-framework/core/field-generator/templates/info.php000064400000002243151214002470020413 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div class="bf-section-container bf-clearfix">
	<div
			class="bf-section-info <?php echo esc_attr( $options['info-type'] ) . ' ' . esc_attr( $options['state'] ); ?> bf-clearfix">
		<div class="bf-section-info-title bf-clearfix">
			<h3><?php echo esc_html( $options['name'] ); ?></h3>
		</div>
		<div class="<?php echo esc_attr( $controls_classes ); ?>  bf-clearfix">
			<?php echo $input; // escaped before ?>
		</div>
	</div>
</div>libs/better-framework/core/field-generator/templates/border.php000064400000005345151214002470020743 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes = $classes['section'];

$heading_classes  = $classes['heading'];
$controls_classes = $classes['controls'];
$explain_classes  = $classes['explain'];

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];

?>
<div class="bf-section-container bf-clearfix">
	<div class="<?php echo esc_attr( $section_classes ); ?> bf-clearfix"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>">

		<div class="<?php echo esc_attr( $heading_classes ); ?> bf-clearfix">
			<h3><label><?php echo esc_html( $options['name'] ); ?></label></h3>
		</div>

		<div class="<?php echo esc_attr( $controls_classes ); ?> bf-clearfix">
			<?php echo $input; // escaped before ?>
		</div>

		<?php if ( ! empty( $options['desc'] ) ||
		           ( isset( $options['preview'] ) && $options['preview'] )
		) { ?>
			<div class="<?php echo esc_attr( $explain_classes ); ?> bf-clearfix">
				<?php if ( isset( $options['preview'] ) && $options['preview'] ) { ?>

					<?php esc_html_e( 'Preview', 'better-studio' ); ?>

					<hr/>

				<?php } ?>

				<?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?>
			</div>
		<?php } ?>

	</div>
</div>libs/better-framework/core/field-generator/templates/typography.php000064400000005755151214002470021701 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes = $classes['section'];

$heading_classes  = $classes['heading'];
$controls_classes = $classes['controls'];
$explain_classes  = $classes['explain'];

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];

?>
<div class="bf-section-container bf-clearfix">
	<div class="<?php echo esc_attr( $section_classes ); ?> bf-clearfix"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>">

		<div class="<?php echo esc_attr( $heading_classes ); ?> bf-clearfix">
			<h3><label><?php echo esc_html( $options['name'] ); ?></label></h3>
		</div>

		<div class="<?php echo esc_attr( $controls_classes ); ?> bf-clearfix">
			<?php echo $input; // escaped before ?>
		</div>

		<?php if ( ! empty( $options['desc'] ) ||
		           ( isset( $options['preview'] ) && $options['preview'] )
		) { ?>
			<div class="<?php echo esc_attr( $explain_classes ); ?> bf-clearfix">
				<?php if ( isset( $options['preview'] ) && $options['preview'] ) { ?>

					<div class="typography-preview">
						<p class="preview-text">
							<?php if ( isset( $options['preview_text'] ) && ! empty( $options['preview_text'] ) ) {
								echo esc_html( $options['preview_text'] );
							} else {
								esc_html_e( 'ABCDEF...123', 'better-studio' );
							} ?>
						</p>
					</div>

					<hr/>
				<?php } ?>

				<?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?>
			</div>
		<?php } ?>

	</div>
</div>libs/better-framework/core/field-generator/templates/image_preview.php000064400000002241151214002470022301 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div class="bf-section-container bf-clearfix">
	<div
			class="bf-section bf-section-image-preview bf-clearfix">
		<?php if ( ! empty( $options['name'] ) ) { ?>
			<div class="bf-section-info-title bf-clearfix">
				<h3><?php echo esc_html( $options['name'] ); ?></h3>
			</div>
		<?php } ?>
		<div class="<?php echo esc_attr( $controls_classes ); ?>  bf-clearfix">
			<?php echo $input; // escaped before ?>
		</div>
	</div>
</div>
libs/better-framework/core/walkers/class-walker-better-categorydropdown.php000064400000004522151214002470023330 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * BF Category Walker
 */
class Walker_Better_CategoryDropdown extends Walker_CategoryDropdown {

	/**
	 * Start the element output.
	 *
	 * @see   Walker::start_el()
	 * @since 2.1.0
	 *
	 * @param string $output   Passed by reference. Used to append additional content.
	 * @param object $category Category data object.
	 * @param int    $depth    Depth of category. Used for padding.
	 * @param array  $args     Uses 'selected', 'show_count', and 'value_field' keys, if they exist.
	 *                         See {@see wp_dropdown_categories()}.
	 */
	public function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0 ) {

		$pad = str_repeat( '&nbsp;', $depth * 3 );

		/** This filter is documented in wp-includes/category-template.php */
		$cat_name = apply_filters( 'list_cats', $category->name, $category );

		if ( isset( $args['value_field'] ) && isset( $category->{$args['value_field']} ) ) {
			$value_field = $args['value_field'];
		} else {
			$value_field = 'term_id';
		}

		$output .= "\t<option class=\"level-$depth\" value=\"" . esc_attr( $category->{$value_field} ) . "\"";

		//
		// Changed to support multiple
		//
		if ( is_array( $args['selected'] ) ) {
			if ( in_array( $category->{$value_field}, $args['selected'] ) ) {
				$output .= ' selected="selected"';
			}
		} elseif ( (string) $category->{$value_field} === (string) $args['selected'] ) {
			$output .= ' selected="selected"';
		}


		$output .= '>';
		$output .= $pad . $cat_name;
		if ( $args['show_count'] ) {
			$output .= '&nbsp;&nbsp;(' . number_format_i18n( $category->count ) . ')';
		}
		$output .= "</option>\n";
	}
}libs/better-framework/core/class-bf-posts.php000064400000003511151214002470015252 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Contain Functionality Related To Posts and Pages That Used In Themes
 */
class BF_Posts {


	/**
	 * Deprecated!
	 *
	 * Custom excerpt
	 *
	 * @param  integer     $length
	 * @param  string|null $text
	 * @param bool         $echo
	 *
	 * @return string
	 */
	public static function excerpt( $length = 24, $text = null, $echo = true ) {

		// If text not defined get excerpt
		if ( ! $text ) {

			// have a manual excerpt?
			if ( has_excerpt( get_the_ID() ) ) {

				if ( $echo ) {
					echo apply_filters( 'the_excerpt', get_the_excerpt() );

					return;
				} else {
					return apply_filters( 'the_excerpt', get_the_excerpt() );
				}

			} else {

				$text = get_the_content( '' );

			}

		}

		$text = strip_shortcodes( $text );
		$text = str_replace( ']]>', ']]&gt;', $text );

		// get plaintext excerpt trimmed to right length
		$excerpt = wp_trim_words( $text, $length, '&hellip;' );

		// fix extra spaces
		$excerpt = trim( str_replace( '&nbsp;', ' ', $excerpt ) );


		if ( $echo ) {
			echo $excerpt; // escaped before in generating inside WP Core
		} else {
			return $excerpt;
		}
	}


}libs/better-framework/menu/class-bf-menu-walker.php000064400000033023151214002470016346 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Front Site Walker
 */
class BF_Menu_Walker extends Walker_Nav_Menu {

	/**
	 * Contain mega menu IDs
	 *
	 * @var array
	 */
	public $mega_menus = array();


	/**
	 * Capture children elements
	 *
	 * @var int
	 */
	public $capture_childs = 0;

	/**
	 * Store children items in mega menu as html
	 *
	 * @var string
	 */
	public $captured_children;

	/**
	 * Contains list of field ID's that should be behave as mega menu
	 *
	 * @var array
	 */
	public static $mega_menu_field_ids = array(
		'mega_menu' => array(
			'default' => 'disabled',
			'depth'   => 0,
		),
	);


	/**
	 * Sub menu animations
	 */
	public $animations = array(
		'fade',
		'slide-fade',
		'bounce',
		'tada',
		'shake',
		'swing',
		'wobble',
		'buzz',
		'slide-top-in',
		'slide-bottom-in',
		'slide-left-in',
		'slide-right-in',
		'filip-in-x',
		'filip-in-y',
	);

	/**
	 * Show parent items description
	 */
	public $show_desc_parent = false;


	function __construct() {

		$this->show_desc_parent = apply_filters( 'better-framework/menu/show-parent-desc', $this->show_desc_parent );

		do_action_ref_array( 'better-framework/menu/walker/init', array( &$this ) );
	}


	/**
	 * Prepare properties to start capturing
	 */
	public function turn_capturing_mode_on() {

		$this->capture_childs    = 1;
		$this->captured_children = '';
	}


	/**
	 * Reset capture temp variables
	 */
	public function turn_capturing_mode_off() {

		$this->capture_childs = 0;
	}


	/**
	 * Increase capture pointer number
	 */
	public function start_capture_children() {

		$this->capture_childs ++;
	}


	/**
	 * decrease capture pointer number
	 */
	public function stop_capture_children() {

		$this->capture_childs --;
	}


	/**
	 * Whether to check is capturing mode turn on
	 *
	 * @return int
	 */
	public function is_capturing_mode_enable() {

		return $this->capture_childs;
	}


	/**
	 * Whether to check is capturing started
	 *
	 * @return bool true on success
	 */
	public function is_capture_childs_started() {

		return $this->capture_childs > 1;
	}


	/**
	 * Handy function to check mega menu status
	 *
	 * @param string $id
	 * @param array  $args
	 * @param null   $item
	 * @param bool   $default
	 *
	 * @return array|bool
	 */
	public function get_status( $id = '', $args = array(), $item = null, $default = false ) {

		$_id = 'bf_' . $id;

		if ( is_object( $args ) ) {
			$args = (array) $args;
		}

		if ( isset( $args[ $_id ] ) ) {
			return $args[ $_id ];
		}

		if ( is_null( $item ) ) {
			return $default;
		}

		if ( isset( $item->$id ) ) {
			return $item->$id;
		}

		return $default;
	}


	/**
	 * Starts the list before the elements are added.
	 *
	 * @see Walker_Nav_Menu::start_lvl()
	 * @see Walker::start_lvl()
	 *
	 * @param string $output Passed by reference. Used to append additional content.
	 * @param int    $depth  Depth of menu item. Used for padding.
	 * @param array  $args   An array of arguments. @see wp_nav_menu()
	 */
	public function start_lvl( &$output, $depth = 0, $args = array() ) {

		$active_mega_menu = $this->get_status( 'mega_menu', $args, null, true ) && $this->mega_menus;

		/**
		 * Capture mega menu children items
		 *
		 * Ex:
		 *  item: mega-menu
		 *         - Child 1
		 *         - Child 2
		 *
		 * will capture child 1, child 2 otherwise print <ul>
		 */
		if ( $active_mega_menu && ! $this->is_capture_childs_started() ) {
			$this->turn_capturing_mode_on();
		}

		$item_output = '';
		parent::start_lvl( $item_output, $depth, $args );

		if ( $active_mega_menu && $this->is_capturing_mode_enable() ) {
			$this->start_capture_children();

			if ( $this->capture_childs > 2 ) { // ignore first <ul ..> tag
				$this->captured_children .= $item_output;
			}
		} else {
			$output .= $item_output;
		}
	}


	/**
	 * Ends the list of after the elements are added.
	 *
	 * @see Walker_Nav_Menu::end_lvl()
	 * @see Walker::end_lvl()
	 *
	 * @param string $output Passed by reference. Used to append additional content.
	 * @param int    $depth  Depth of menu item. Used for padding.
	 * @param array  $args   An array of arguments. @see wp_nav_menu()
	 */
	public function end_lvl( &$output, $depth = 0, $args = array() ) {

		$active_mega_menu = $this->get_status( 'mega_menu', $args, null, true ) && $this->mega_menus;

		if ( $active_mega_menu ) {

			$turned_off = false;
			if ( $this->is_capturing_mode_enable() ) {
				$this->stop_capture_children();
				$turned_off = ! $this->is_capture_childs_started();
			}

			if ( $turned_off ) {
				$current_item = array_pop( $this->mega_menus );

				$mega_menu = apply_filters( 'better-framework/menu/mega/end_lvl', array(
						'depth'        => $depth,
						'this'         => &$this,
						'sub-menu'     => $this->captured_children,
						'current-item' => &$current_item,
						'output'       => '',
					)
				);

				$this->captured_children = ''; // Clear captured childs to prevent duplicate print in next mega menu!
				$this->append_comment( $output, $depth, __( 'Mega Menu Start', 'better-studio' ) );
				$output .= $mega_menu['output'];
				$this->append_comment( $output, $depth, __( 'Mega Menu End', 'better-studio' ) );
			}

		}

		$item_output = '';
		parent::end_lvl( $item_output, $depth, $args );

		if ( $active_mega_menu ) {
			if ( $this->is_capturing_mode_enable() ) {
				$this->captured_children .= $item_output;
			} else {
				$output .= $item_output;
			}
		} else {
			$output .= $item_output;
		}

	}


	/**
	 * @param int|array $valid_range
	 * @param int       $item_depth
	 *
	 * @return bool
	 */
	protected function is_valid_depth( $valid_range, $item_depth ) {

		if ( $valid_range === $item_depth ) {
			return true;
		}

		if ( $valid_range === - 1 ) {
			return true;
		}


		return $valid_range[0] <= $item_depth &&
		       $valid_range[1] >= $item_depth;
	}


	/**
	 * Detect the item have mega menu
	 *
	 * @param object $item
	 * @param int    $depth item depth
	 *
	 * @return bool true on success
	 */
	protected function is_item_mega_menu( $item, $depth = 0 ) {

		foreach ( self::$mega_menu_field_ids as $mega_id => $mega_value ) {
			if ( ! empty( $item->{$mega_id} ) && $item->{$mega_id} != $mega_value['default'] ) {

				$mega_menu_id = $item->{$mega_id};

				if ( isset( $mega_value['options'][ $mega_menu_id ] ) ) {

					if ( $this->is_valid_depth( $mega_value['options'][ $mega_menu_id ]['depth'], $depth ) ) {

						return true;
					}

				} elseif ( $this->is_valid_depth( $mega_value['depth'], $depth ) ) {

					return true;
				}

			}
		}

		return false;
	}


	/**
	 * Set list of field ID's that should be behave as mega menu
	 *
	 * @param array $value
	 *
	 * @since BF 2.8.4
	 */
	public function set_mega_menu_fields_id( $value ) {

		self::$mega_menu_field_ids = $value;
	}


	/**
	 * Get list of field ID's that should be behave as mega menu
	 *
	 * @since BF 2.8.4
	 * @return array
	 */
	public function get_mega_menu_fields_id() {

		return self::$mega_menu_field_ids;
	}


	/**
	 * Start the element output.
	 *
	 * @see Walker_Nav_Menu::start_el()
	 * @see Walker::start_el()
	 *
	 * @param string $output Passed by reference. Used to append additional content.
	 * @param object $item   Menu item data object.
	 * @param int    $depth  Depth of menu item. Used for padding.
	 * @param array  $args   An array of arguments. @see wp_nav_menu()
	 * @param int    $id     Current item ID.
	 */
	public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {

		$_class = array();

		//
		// Responsive Options
		//
		if ( $this->get_status( 'resp_desktop', $args, $item ) === 'hide' ) {
			$_class[] = 'hidden-lg'; // Hide On Desktop
		}

		if ( $this->get_status( 'resp_tablet', $args, $item ) === 'hide' ) {
			$_class[] = 'hidden-md'; // Hide On Desktop
		}

		if ( $this->get_status( 'resp_mobile', $args, $item ) === 'hide' ) {
			$_class[] = 'hidden-sm'; // Hide On Mobile
			$_class[] = 'hidden-xs';
		}

		// add specific class for identical usages for categories
		if ( $item->object == 'category' ) {
			$_class[] = 'menu-term-' . $item->object_id;
		}

		// Delete item title when hiding title set
		if ( $this->get_status( 'hide_menu_title', $args, $item ) == 1 ) {
			$_class[]    = 'menu-title-hide';
			$item->title = '<span class="hidden">' . $item->title /* escaped before */ . '</span>';
		}


		//
		// Menu Animations
		//
		$anim = $this->get_status( 'drop_menu_anim', $args, $item );
		if ( $anim && $anim !== 'default' ) {
			if ( $item->drop_menu_anim === 'random' ) {
				$_class[] = 'better-anim-' . $this->animations[ array_rand( $this->animations ) ];
			} else {
				$_class[] = 'better-anim-' . $anim;
			}
		} else {
			$_class[] = 'better-anim-' . $this->get_status( 'default_anim', $args, $item, 'fade' );
		}


		//
		// Generate Badges html
		//
		$badge_label = $this->get_status( 'badge_label', $args, $item );
		if ( $badge_label ) {

			if ( ! isset( $_temp_args ) ) {
				$_temp_args = (object) $args;
				$_temp_args = clone $_temp_args;
			}

			if ( ! empty( $item->badge_position ) ) {
				$badge_position = $item->badge_position;
				$_class[]       = 'menu-badge-' . $item->badge_position;
			} else {
				$badge_position = 'right';
				$_class[]       = 'menu-badge-right';
			}

			if ( $badge_position == 'right' ) {
				$_temp_args->link_after = $this->generate_badge_HTML( $badge_label ) . $_temp_args->link_after;
			} else {
				$_temp_args->link_before = $this->generate_badge_HTML( $badge_label ) . $_temp_args->link_before;
			}

			$_class[] = 'menu-have-badge';
		}


		//
		// Add description to parent items
		//
		if ( $depth == 0 && $this->show_desc_parent && isset( $item->description ) && ! empty( $item->description ) ) {

			if ( ! isset( $_temp_args ) ) {
				$_temp_args = (object) $args;
				$_temp_args = clone $_temp_args;
			}

			$_temp_args->link_after .= '<span class="description">' . $item->description /* escaped before */ . '</span>';
			$_class[]               = 'menu-have-description';
		}

		// Prepare params for mega menu
		if ( $this->get_status( 'mega_menu', $args, $item ) && $this->is_item_mega_menu( $item, $depth ) ) {
			// Mega menu classes
			$mega_item_obj            = clone( $item );
			$mega_item_obj->item_id   = $item->ID;
			$mega_item_obj->mega_menu = $item->mega_menu;

			$this->mega_menus[ $item->ID ] = $mega_item_obj;

			$_class[] = 'menu-item-has-children menu-item-has-mega menu-item-mega-' . $item->mega_menu;
		}

		// Merge menu classes
		$item->classes = array_merge( (array) $item->classes, $_class );
		unset( $_class );

		// continue with new args that changed
		$item_output = '';
		if ( isset( $_temp_args ) ) {
			parent::start_el( $item_output, $item, $depth, $_temp_args, $id );
		} else {
			parent::start_el( $item_output, $item, $depth, $args, $id );
		}

		if ( $this->is_capture_childs_started() ) {
			$this->captured_children .= $item_output;
		} else {
			$output .= $item_output;
		}
	}


	/**
	 * Ends the element output, if needed.
	 *
	 * @see Walker_Nav_Menu::end_el()
	 * @see Walker::end_el()
	 *
	 * @param string $output Passed by reference. Used to append additional content.
	 * @param object $item   Page data object. Not used.
	 * @param int    $depth  Depth of page. Not Used.
	 * @param array  $args   An array of arguments. @see wp_nav_menu()
	 */
	function end_el( &$output, $item, $depth = 0, $args = array() ) {

		// Mega menu items without child
		if ( $this->get_status( 'mega_menu', $args, $item ) && $this->mega_menus && ! $this->is_capture_childs_started() ) {
			$current_item = array_pop( $this->mega_menus );
			$mega_menu    = apply_filters( 'better-framework/menu/mega/end_lvl', array(
					'depth'        => $depth,
					'this'         => &$this,
					'sub-menu'     => $this->captured_children,
					'current-item' => &$current_item,
					'output'       => '',
				)
			);

			$this->append_comment( $output, $depth, __( 'Mega Menu Start', 'better-studio' ) );
			$output .= $mega_menu['output'];
			$this->append_comment( $output, $depth, __( 'Mega Menu End', 'better-studio' ) );

			parent::end_el( $output, $item, $depth, $args );
		} else {

			$item_output = '';
			parent::end_el( $item_output, $item, $depth, $args );


			if ( $this->is_capturing_mode_enable() ) {
				$this->captured_children .= $item_output;
				if ( ! $this->is_capture_childs_started() ) {
					$output .= $item_output;
				}
			} else {
				$output .= $item_output;
			}
		}
	}


	/**
	 * Append HTML comment inside menu items. it's formatted and easy to read!
	 *
	 * @param string $output
	 * @param int    $depth
	 * @param string $comment
	 */
	protected function append_comment( &$output, $depth, $comment = '' ) {

		$output .= "\n";
		$output .= str_repeat( "\t", $depth );
		if ( $comment ) {
			$output .= sprintf( '<!-- %s -->', $comment );
		}
		$output .= "\n";
	}


	/**
	 * Used for generating custom badge html
	 *
	 * @param $badge_label
	 *
	 * @return string
	 */
	public function generate_badge_HTML( $badge_label ) {

		return '<span class="better-custom-badge">' . $badge_label /* escaped before */ . '</span>';
	}

} // BF_Menu_Walker
libs/better-framework/menu/class-bf-menu-field-generator.php000064400000007126151214002470020135 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * BF Menu Field Generator
 *
 * @since 1.0
 */
class BF_Menu_Field_Generator extends BF_Admin_Fields {

	/**
	 * Menu item that contains values
	 *
	 * @since  1.0
	 * @access public
	 * @var array
	 */
	public $menu_item;


	/**
	 * Constructor Function
	 *
	 * @param array  $items
	 * @param object $menu_item
	 *
	 * @since  1.0
	 * @access public
	 * @return \BF_Menu_Field_Generator
	 */
	public function __construct( array $items, &$menu_item = null ) {

		$items['templates_dir'] = BF_PATH . 'menu/templates/';

		// Parent Constructor
		parent::__construct( $items );

		$this->menu_item = &$menu_item;
	}


	/**
	 * Display HTML output of fields
	 *
	 * @since  1.0
	 * @access public
	 * @return string
	 */
	public function get_fields() {

		$output        = '';
		$group_counter = 0;

		$all_std = BF_Menus::get_std();

		foreach ( BF_Menus::get_fields() as $key => $field ) {

			if ( isset( $field['panel-id'] ) ) {
				$std = Better_Framework::options()->get_panel_std_id( $field['panel-id'] );
			} else {
				$std = 'std';
			}

			if ( empty( $field['id'] ) ) {
				$field['value'] = false;
			} else {
				$field['value'] = isset( $this->menu_item->{$field['id']} ) ? $this->menu_item->{$field['id']} : false;
			}

			if ( $field['value'] == false ) {
				if ( isset( $all_std[ $std ] ) ) {
					$field['value'] = $all_std[ $std ];
				} elseif ( $std != 'std' && isset( $all_std['std'] ) ) {
					$field['value'] = $all_std['std'];
				}
			}

			if ( $field['type'] == 'group_close' ) {

				// close tag for latest group in tab
				if ( $group_counter != 0 ) {
					$group_counter = 0;
					$output        .= $this->get_fields_group_close( $field );
				}
				continue;
			}

			if ( $field['type'] == 'group' ) {

				// close tag for latest group in tab
				if ( $group_counter != 0 ) {
					$group_counter = 0;
					$output        .= $this->get_fields_group_close( $field );
				}

				$output .= $this->get_fields_group_start( $field );

				$group_counter ++;
			}

			if ( ! in_array( $field['type'], $this->supported_fields ) ) {
				continue;
			}

			// for image checkbox sortable option
			if ( isset( $field['is_sortable'] ) && ( $field['is_sortable'] == '1' ) ) {
				$field['section_class'] .= ' is-sortable';
			}

			$field['input_name'] = $this->generate_field_ID( $key, $this->menu_item->ID );

			$output .= $this->section(
				call_user_func(
					array( $this, $field['type'] ),
					$field
				),
				$field
			);

		} // foreach


		// close tag for latest group in tab
		if ( $group_counter != 0 ) {
			$output .= $this->get_fields_group_close( $field );
		}

		unset( $std );
		unset( $group_counter );

		return $output;
	}


	/**
	 * Generate valid names for fields
	 *
	 * @param $key
	 * @param $parent_id
	 *
	 * @return string
	 */
	public function generate_field_ID( $key, $parent_id ) {

		return 'bf-m-i[' . esc_attr( $key ) . '][' . $parent_id . ']';
	}

}libs/better-framework/menu/class-bf-menus.php000064400000021767151214002470015262 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * BetterFramework core menu manager.
 */
class BF_Menus {


	/**
	 * Active Fields
	 *
	 * @var array
	 */
	public static $fields = array();


	/**
	 * STD value for all fields
	 *
	 * @var array
	 */
	public static $std = array();

	/**
	 * BF Menu Field generator
	 *
	 * @var
	 */
	public $field_generator;


	/**
	 * Default walker for all menus
	 *
	 * @var string
	 */
	private static $default_walker = 'BF_Menu_Walker';


	/**
	 * BF_Menus constructor.
	 */
	public function __construct() {

		// low priority init, give theme a chance to register hooks
		add_action( 'init', array( $this, 'init' ), 50 );

		// Icons Factory
		Better_Framework::factory( 'icon-factory' );
	}


	/**
	 * Loads all fields
	 *
	 * @return array
	 */
	public static function get_fields() {

		static $loaded;

		if ( $loaded ) {
			return self::$fields;
		}

		$loaded = true;

		return self::$fields = apply_filters( 'better-framework/menu/options', self::$fields );
	}


	/**
	 * Loads all default values for fields
	 *
	 * @return array
	 */
	public static function get_std() {

		static $loaded;

		if ( $loaded ) {
			return self::$std;
		}

		$loaded = true;

		return self::$std = apply_filters( 'better-framework/menu/std', self::$std );
	}


	/**
	 * Filters and returns walker
	 */
	public static function get_walker() {

		static $filtered;

		if ( $filtered ) {
			return self::$default_walker;
		}

		$filtered = true;

		return self::$default_walker = apply_filters( 'better-framework/menu/walker', self::$default_walker );
	}


	/**
	 * Initializes
	 */
	public function init() {

		add_filter( 'wp_setup_nav_menu_item', array( $this, 'setup_menu_fields' ) );

		// Save and Walker filter only needed for admin
		if ( is_admin() ) {
			add_action( 'wp_update_nav_menu_item', array( $this, 'save_menu_fields' ), 10, 3 );
			add_filter( 'wp_edit_nav_menu_walker', array( $this, 'walker_menu_fields' ), PHP_INT_MAX );

			// Bug fix: when create a new menu, menu walker not fire so bf_enqueue_modal()
			// not fire and user cannot set icon for the menu items

			if ( $GLOBALS['pagenow'] === 'nav-menus.php' ) {
				bf_enqueue_modal( 'icon' );
			}
		}

		// Front Site Walker
		add_filter( 'wp_nav_menu_args', array( $this, 'walker_front' ) );

		if ( ! has_action( 'nav_menu_item_args', array( $this, 'append_icon_html' ) ) ) {

			add_filter( 'nav_menu_item_title', array( $this, 'append_icon_html' ), 20, 2 );
			add_filter( 'wp_setup_nav_menu_item', array( $this, 'append_icon_classes' ), 11 );
		}
	}


	/**
	 * Setup custom walker for editing the menu
	 */
	public function walker_menu_fields( $walker, $menu_id = null ) {

		if ( ! class_exists( 'BF_Menu_Edit_Walker' ) ) {
			include BF_PATH . 'menu/class-bf-menu-edit-walker.php';
		}

		return 'BF_Menu_Edit_Walker';
	}


	/**
	 * Load the correct walker on demand when needed for the frontend menu
	 *
	 * @param array $args
	 *
	 * @return array
	 */
	public function walker_front( $args ) {

		if ( ! empty( $args['bf_menu_walker'] ) && ! $args['bf_menu_walker'] ) {
			return $args;
		}

		$_walker = self::get_walker();

		// fix for when location have no any menu!
		// We change the walker and empty the theme location to stop WP from showing errors
		if ( ! empty( $args['theme_location'] ) && ! has_nav_menu( $args['theme_location'] ) ) {
			$args['fallback_cb']    = $_walker;
			$args['theme_location'] = '';
		}

		if ( has_nav_menu( $args['theme_location'] ) ) {

			if ( $_walker == self::$default_walker ) {

				if ( ! class_exists( 'BF_Menu_Walker' ) ) {
					require BF_PATH . 'menu/class-bf-menu-walker.php';
				}

				$args['walker'] = new BF_Menu_Walker;
			} else {

				$_walker        = "Class" . $_walker;
				$args['walker'] = new $_walker;

			}
		}


		return $args;
	}


	/**
	 * @param string  $title The menu item's title.
	 * @param WP_Post $item  The current menu item.
	 *
	 * @since 3.10.13
	 *
	 * @return stdClass
	 */
	public function append_icon_html( $title, $item ) {

		if ( empty( $item->menu_icon ) ) {

			return $title;
		}

		$menu_icon = $item->menu_icon;

		if ( is_array( $menu_icon ) && ! empty( $menu_icon['icon'] ) ) {

			$title = bf_get_icon_tag( $menu_icon ) . $title;

		} elseif ( is_string( $menu_icon ) && $menu_icon != 'none' ) {

			$title = bf_get_icon_tag( $menu_icon ) . $title;
		}

		return $title;
	}

	/**
	 * @param object $menu_item The menu item object.
	 *
	 * @return object
	 */
	public function append_icon_classes( $menu_item ) {

		if ( empty( $menu_item->menu_icon ) ) {

			return $menu_item;
		}

		$menu_icon = $menu_item->menu_icon;

		if ( is_array( $menu_icon ) && ! empty( $menu_icon['icon'] ) ) {

			$menu_item->classes[] = 'menu-have-icon';
			$menu_item->classes[] = 'menu-icon-type-' . $menu_icon['type'];

		} elseif ( is_string( $menu_icon ) && $menu_icon != 'none' ) {

			$menu_item->classes[] = 'menu-have-icon';
		}


		return $menu_item;
	}


	/**
	 * Load custom fields to the menu
	 *
	 * @param $menu_item
	 *
	 * @return WP_Post
	 */
	public function setup_menu_fields( $menu_item ) {

		foreach ( self::get_std() as $key => $field ) {

			// load values
			$value = get_post_meta( $menu_item->ID, '_menu_item_' . $key, true );

			if ( ! empty( $value ) ) {
				$menu_item->{$key} = $value;
				continue;
			}

			if ( isset( $field['panel-id'] ) ) {
				$std_id = Better_Framework::options()->get_panel_std_id( $field['panel-id'] );
			} else {
				$std_id = 'std';
			}

			if ( ! isset( $field[ $std_id ] ) ) {
				$std_id = 'std';
			}

			// load default value when it's not available!
			if ( isset( $field[ $std_id ] ) ) {
				$menu_item->{$key} = $field[ $std_id ];
			}
		}

		return $menu_item;
	}


	/**
	 * Save menu custom fields
	 *
	 * @global $wp_version WordPress version number
	 */
	public function save_menu_fields( $menu_id, $menu_item_db_id, $args ) {

		global $wp_version;

		$is_data_array = false;


		if ( isset( $_POST['bf-m-i'] ) ) {

			// Parse JSON and convert it to array
			// Parse this one time for better performance
			if ( is_string( $_POST['bf-m-i'] ) ) {
				$_POST['bf-m-i'] = json_decode( urldecode( $_POST['bf-m-i'] ), true );
			} else {
				$is_data_array = is_array( $_POST['bf-m-i'] );
			}

		} else {
			return; // continue if there is not better-menu-field!
		}


		/**
		 * Convert menu array style to new
		 */
		include ABSPATH . WPINC . '/version.php'; // include an unmodified $wp_version

		//check WordPress version and make sure $_POST modified by WordPress
		if ( ! $is_data_array && version_compare( $wp_version, '4.5.3', '<' ) ) {
			$this->convert_data_array();
		}


		foreach ( self::get_std() as $key => $field ) {

			$value = null;

			// default value type
			if ( isset( $_POST['bf-m-i'][ $key ][ $menu_item_db_id ] ) ) {
				$value = $_POST['bf-m-i'][ $key ][ $menu_item_db_id ];
			} // Some plugins like advanced custom fields are reversing the way that WP stores data in menu section
			elseif ( isset( $_POST['bf-m-i'][ $menu_item_db_id ][ $key ] ) ) {
				$value = $_POST['bf-m-i'][ $menu_item_db_id ][ $key ];
			}

			if ( is_null( $value ) ) {
				continue;
			}

			// add / update meta

			if ( isset( $field['panel-id'] ) ) {
				$std_id = Better_Framework::options()->get_panel_std_id( $field['panel-id'] );
			} else {
				$std_id = 'std';
			}

			if ( ! isset( $field[ $std_id ] ) ) {
				$std_id = 'std';
			}

			// check for saving default or not!?
			if ( isset( $field['save-std'] ) && ! $field['save-std'] ) {
				if ( $value != $field[ $std_id ] ) {
					update_post_meta( $menu_item_db_id, '_menu_item_' . $key, $value );
				} else {
					delete_post_meta( $menu_item_db_id, '_menu_item_' . $key );
				}
			} // save anyway ( save-std not defined or is true )
			else {
				update_post_meta( $menu_item_db_id, '_menu_item_' . $key, $value );
			}

		}

	} // save_menu_fields


	/**
	 * Convert menu array to new WP version style
	 *
	 * @since 4.5.3 in menu array data, item key and menu item ID postion fliped
	 *
	 *
	 *
	 * @see   _wp_expand_nav_menu_post_data()
	 */
	protected function convert_data_array() {

		if ( ! is_array( $_POST['bf-m-i'] ) ) {
			return;
		}

		$new_structure = array();
		foreach ( $_POST['bf-m-i'] as $post_ID => $data_array ) {

			if ( ! is_array( $data_array ) ) {
				continue;
			}

			foreach ( $data_array as $item_type => $item_value ) {
				$new_structure[ $item_type ][ $post_ID ] = $item_value;
			}
		}

		$_POST['bf-m-i'] = $new_structure;
	}

}libs/better-framework/menu/class-bf-menu-edit-walker.php000064400000005407151214002470017276 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Walker for back-end adding and saving menus custom fields
 */
class BF_Menu_Edit_Walker extends Walker_Nav_Menu_Edit {

	/**
	 * Contains all locations. (used for filtering fields just for one location)
	 *
	 * @var array
	 */
	public $locations = array();

	/**
	 * current menu location
	 *
	 * @var
	 */
	public $current_menu;


	public function __construct() {

		// load all registered menu locations
		// todo commented and needs test because of WPML incompatibility
		// $this->locations = array_flip( (array) get_nav_menu_locations() );

	}


	/**
	 * Used for appending admin fields
	 *
	 * @param string $output
	 * @param object $item
	 * @param int    $depth
	 * @param array  $args
	 * @param int    $id
	 */
	public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {

		// get current menu id
		if ( ! $this->current_menu ) {

			$menu = wp_get_post_terms( $item->ID, 'nav_menu' );

			if ( isset( $menu[0] ) && $menu[0]->term_id ) {
				$this->current_menu = $menu[0]->term_id;
			}

			if ( ! $this->current_menu && $_REQUEST['menu'] ) {
				$this->current_menu = $_REQUEST['menu'];
			}

		}

		$item_output = '';

		parent::start_el( $item_output, $item, $depth, $args, $id );

		// add new fields before <div class="menu-item-actions description-wide submitbox">
		$fields = $this->get_custom_fields( $item, $depth );

		ob_start();

		do_action( 'wp_nav_menu_item_custom_fields', $item->ID, $item, $depth, $args );
		$fields .= ob_get_clean();

		$item_output = preg_replace( '/(?=<div[^>]+class="[^"]*submitbox)/', $fields, $item_output );

		$output .= $item_output;
	}


	/**
	 * Load and save active custom fields for menus
	 *
	 * TODO: Add option for showing fields expander
	 *
	 * @param     $item
	 * @param int $depth
	 *
	 * @return string
	 */
	public function get_custom_fields( $item, $depth = 0 ) {

		require_once BF_PATH . 'menu/class-bf-menu-field-generator.php';

		$field_generator = new BF_Menu_Field_Generator( array(), $item );

		$output = $field_generator->get_fields();

		return $output;
	}
}
libs/better-framework/menu/templates/default.php000064400000003445151214002470016056 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

$parent_only = isset( $option['parent_only'] ) ? ' data-parent_only="true"' : '';

// Block width
$block_class = array();
if ( isset( $options['width'] ) && ! empty( $options['width'] ) ) {
	$block_class[] = 'description-' . $options['width'];
} else {
	$block_class[] = 'description-wide';
}

$block_class[] = 'bf-field-' . $options['id'];

// Block Classes
if ( isset( $options['class'] ) && ! empty( $options['class'] ) ) {
	$block_class[] = $options['class'];
}

$block_class = apply_filters( 'better-framework/menu/fields-class', $block_class );

?>
<div class="bf-menu-custom-field better-custom-field-<?php echo esc_attr( $options['type'] ); ?> description <?php echo esc_attr( implode( ' ', $block_class ) ); ?>" <?php $parent_only; ?> <?php echo bf_show_on_attributes( $options ); ?> >
	<label for="<?php echo esc_attr( $options['input_name'] ); ?>">
		<span class="better-custom-field-label"><?php echo esc_html( $options['name'] ); ?></span>
		<br/>
		<div class="bf-section-container bf-menus bf-clearfix"><?php echo $input; // escaped before ?></div>
	</label>
</div>libs/better-framework/menu/templates/hr.php000064400000001600151214002470015032 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div class="bf-section-container bf-clearfix">
	<div class="bf-section-hr bf-clearfix">
		<?php echo $input; // escaped before ?>
	</div>
</div>libs/better-framework/menu/templates/heading.php000064400000004131151214002470016022 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

if ( ! isset( $options['id'] ) ) {
	$options['id'] = '';
}
$style = ! empty( $options['layout'] ) ? $options['layout'] : 'style-1';

$parent_only = isset( $option['parent_only'] ) ? ' data-parent_only="true"' : '';

// Block Classes
$block_class = array();
if ( isset( $options['width'] ) && ! empty( $options['width'] ) ) {
	$block_class[] = 'description-' . $options['width'];
} else {
	$block_class[] = 'description-wide';
}

if ( isset( $options['class'] ) && ! empty( $options['class'] ) ) {
	$block_class[] = $options['class'];
}

$block_class[] = 'bf-field-' . $options['id'];

$block_class = apply_filters( 'better-framework/menu/fields-class', $block_class );


?>
<div
		class="bf-section-container bf-menus bf-clearfix <?php echo esc_attr( implode( ' ', $block_class ) ); ?>" <?php echo $parent_only;  // escaped before ?> <?php echo bf_show_on_attributes( $options ); ?>>
	<div class="bf-section-heading bf-clearfix <?php echo $style; ?>"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>"
	     id="<?php echo esc_attr( $options['id'] ); ?>">
		<div class="bf-section-heading-title bf-clearfix">
			<h3><?php echo esc_html( $options['name'] ); ?></h3>
		</div>
		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div
					class="bf-section-heading-desc bf-clearfix"><?php echo wp_kses( $options['desc'], bf_trans_allowed_html() ); ?></div>
		<?php } ?>
	</div>
</div>
libs/better-framework/menu/templates/select_popup.php000064400000013346151214002470017135 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! isset( $options['id'] ) ) {
	$options['id'] = '';
}
$style = ! empty( $options['layout'] ) ? $options['layout'] : 'style-1';

$parent_only = isset( $option['parent_only'] ) ? ' data-parent_only="true"' : '';

// Block Classes
$block_class = array();
if ( isset( $options['width'] ) && ! empty( $options['width'] ) ) {
	$block_class[] = 'description-' . $options['width'];
} else {
	$block_class[] = 'description-wide';
}

if ( isset( $options['class'] ) && ! empty( $options['class'] ) ) {
	$block_class[] = $options['class'];
}

$block_class[] = 'bf-field-' . $options['id'];

$block_class = apply_filters( 'better-framework/menu/fields-class', $block_class );


?>

<div class="bf-menu-custom-field better-custom-field-<?php echo esc_attr( $options['type'] ); ?> description <?php echo esc_attr( implode( ' ', $block_class ) ); ?>" <?php $parent_only; ?> <?php echo bf_show_on_attributes( $options ); ?> >

<?php
// set options from deferred callback
if ( isset( $options['deferred-options'] ) ) {
	if ( is_string( $options['deferred-options'] ) && is_callable( $options['deferred-options'] ) ) {
		$options['options'] = call_user_func( $options['deferred-options'] );
	} elseif ( is_array( $options['deferred-options'] ) && ! empty( $options['deferred-options']['callback'] ) && is_callable( $options['deferred-options']['callback'] ) ) {
		if ( isset( $options['deferred-options']['args'] ) ) {
			$options['options'] = call_user_func_array( $options['deferred-options']['callback'], $options['deferred-options']['args'] );
		} else {
			$options['options'] = call_user_func( $options['deferred-options']['callback'] );
		}
	}
}
if ( empty( $options['options'] ) ) {
	$options['options'] = array();
}

$list_style = 'grid-2-column';
if ( isset( $options['list_style'] ) && ! empty( $options['list_style'] ) ) {
	$list_style = $options['list_style'];
}

// default selected
$current = array(
	'key'   => '',
	'label' => isset( $options['default_text'] ) && ! empty( $options['default_text'] ) ? wp_kses( $options['default_text'], bf_trans_allowed_html() ) : esc_html__( 'chose one...', 'better-studio' ),
	'img'   => ''
);

if ( isset( $options['value'] ) && ! empty( $options['value'] ) ) {
	if ( isset( $options['options'][ $options['value'] ] ) ) {
		$current        = $options['options'][ $options['value'] ];
		$current['key'] = $options['value'];
	}
}

$is_mega_menu_field = false;

$data2print = wp_array_slice_assoc( $options, array( 'texts', 'confirm_texts', 'column_class', 'confirm_changes' ) );

foreach ( (array) $options['options'] as $key => $option ) {
	if ( empty( $option['info'] ) ) {
		$option['info'] = array();
	}
	$option['info']['img']   = $option['img'];
	$option['info']['label'] = $option['label'];

	if ( isset( $option['badges'] ) ) {
		$option['info']['badges'] = $option['badges'];
	}
	if ( isset( $option['class'] ) ) {
		$option['info']['class'] = $option['class'];
	}
	if ( isset( $option['depth'] ) ) {
		$is_mega_menu_field          = true;
		$data2print[ $key ]['depth'] = $option['depth'];
	}

	$data2print['options'][ $key ] = bf_map_deep( $option['info'], 'sanitize_text_field' );
}

$input_name = esc_attr( $options['input_name'] );

$select_style = empty( $options['select_style'] ) ? 'creative' : 'regular-select';

$extra_classes = $is_mega_menu_field ? 'better-select-popup-mega-menu' : '';

if ( $select_style === 'regular-select' ) {
	echo '<div class="better-select-style better-select-popup ', $input_name, ' ', $extra_classes, '">
	<span class="active-item-label">' . $current['label'] . '</span>
';
} else {
	?>

	<div class="select-popup-field bf-clearfix <?php echo $extra_classes ?> <?php echo $input_name ?>">
	<div class="select-popup-selected-image">
		<img src="<?php echo $current['img'] ?>" alt="">
	</div>
	<div class="select-popup-selected-info">
		<div class="active-item-text"><?php
			if ( isset( $options['texts']['box_pre_title'] ) ) {

				echo $options['texts']['box_pre_title'];
			} else {

				_e( 'Active item', 'better-studio' );
			}
			?></div>
		<div class="active-item-label"><?php echo $current['label'] ?></div>

		<a href="#" class="button"><?php
			if ( isset( $options['texts']['box_button'] ) ) {

				echo $options['texts']['box_button'];
			} else {
				_e( 'Change', 'better-studio' );
			}

			?></a>
	</div>
	<?php
}

if ( $data2print ) {
	?>
	<script id="<?php echo str_replace( '-', '_', sanitize_html_class( $input_name ) ) ?>" class="select-popup-data"
	        type="application/json"><?php echo json_encode( $data2print ) ?></script>
	<?php
}

echo '<input type="hidden" name="' . $input_name . '" id="' . $input_name . '" value="' . esc_attr( $current['key'] ) . '" class="select-value"/>';

echo '</div>';

?>

	<div class="bf-section-info bf-clearfix mega-menu-depth-notice" style="display: none;">
		<div class="bf-section-info-title">
			<h3><i class="fa fa-warning"></i> Please Note</h3>

		</div>
		<div class="bf-section-info-message">
			<?php
			_e( 'Mega menu does not work on this particular location', 'better-studio' )
			?>
		</div>
	</div>
<?php

echo '</div>'; // END .bf-menu-custom-field
libs/better-framework/menu/templates/checkbox.php000064400000003504151214002470016214 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$parent_only = isset( $option['parent_only'] ) ? ' data-parent_only="true"' : '';

// Block width
$block_class = array();
if ( isset( $options['width'] ) && ! empty( $options['width'] ) ) {
	$block_class[] = 'description-' . $options['width'];
} else {
	$block_class[] = 'description-wide';
}

$block_class[] = 'bf-field-' . $options['id'];

// Block Classes
if ( isset( $options['class'] ) && ! empty( $options['class'] ) ) {
	$block_class[] = $options['class'];
}

$block_class = apply_filters( 'better-framework/menu/fields-class', $block_class );

?>
<div
		class="bf-menu-custom-field better-custom-field-<?php echo esc_attr( $options['type'] ); ?> description <?php echo esc_attr( implode( ' ', $block_class ) ); ?>" <?php echo $parent_only; // escaped before
echo bf_show_on_attributes( $options ); ?> >
	<label for="<?php echo esc_attr( $options['input_name'] ); ?>">
		<div class="bf-section-container bf-menus bf-clearfix"><label><?php echo $input; // escaped before ?> <span
						class="better-custom-field-label"><?php echo esc_html( $options['name'] ); ?></span></label>
		</div>
	</label>
</div>libs/better-framework/json-ld/class-bf-json-ld-generator.php000064400000032502151214002470020054 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/***
 * Library for json-ld support
 *
 * @since 2.10.0
 */
class BF_Json_LD_Generator {


	/**
	 * Configurations
	 *
	 * @var array
	 */
	protected static $config = array(
		'active'         => true,
		'media_field_id' => '_featured_embed_code', // BS Media Meta ID
		'logo'           => '',                     // Logo for organization
		'posts_type'     => 'BlogPosting',          // Default posts schema type
	);


	/**
	 * Store json-LD Generator Callback
	 *
	 * @var array
	 */
	protected static $generators = array();


	/**
	 * Global json-ld properties that is need in every data types
	 *
	 * @var array
	 *
	 * @since 2.10.0
	 */
	protected static $global_params = array(
		'@context' => 'http://schema.org',
	);


	/**
	 * Initialize library
	 *
	 * @since 2.10.0
	 */
	public static function init() {

		// Prepare data
		add_action( 'template_redirect', 'BF_Json_LD_Generator::prepare_data' );

		// Remove YoastSEO JSON-LD to prevent plugin conflict
		add_action( 'wpseo_json_ld', 'BF_Json_LD_Generator::plugins_conflict', 1 );
	}


	/**
	 * callback: Print json-ld output
	 *
	 * action: wp_head
	 *
	 * @since 2.10.0
	 */
	public static function print_output() {

		foreach ( self::$generators as $generator ) {

			if ( empty( $generator['type'] ) || empty( $generator['callback'] ) || ! is_callable( $generator['callback'] ) ) {
				continue;
			}

			$filter = sprintf( 'better-framework/json-ld/%s', $generator['type'] );

			if ( ! $data = apply_filters( $filter, call_user_func( $generator['callback'] ) ) ) {
				continue;
			}

			echo '<script type="application/ld+json">', wp_json_encode( $data, JSON_PRETTY_PRINT ), '</script>', PHP_EOL;
		}
	}


	/**
	 * remove YoastSEO JSON-LD to prevent plugin conflict
	 *
	 * @since 2.10.0
	 */
	public static function plugins_conflict() {

		bf_remove_class_action( 'wpseo_json_ld', 'WPSEO_JSON_LD', 'website', 10 );
	}


	/**
	 * Generate JSON-LD Information
	 *
	 * @since 2.10.0
	 */
	public static function prepare_data() {

		self::$config = apply_filters( 'better-framework/json-ld/config', self::$config );

		if ( empty( self::$config['active'] ) ) {
			return;
		}


		//
		// Organization
		//
		self::$generators[] = array(
			'type'     => 'organization',
			'callback' => array( 'BF_Json_LD_Generator', 'generate_organization_schema' ),
		);


		//
		// Homepage
		//
		self::$generators[] = array(
			'type'     => 'website',
			'callback' => array( 'BF_Json_LD_Generator', 'generate_website_schema' ),
		);


		//
		// Single Items
		//
		if ( is_singular() && ! is_front_page() ) {

			$type = 'single';

			if ( function_exists( 'is_product' ) && is_product() ) {
				$type = 'product';
			} elseif ( is_page() ) {
				$type = 'page';
			}

			$callback = array( 'BF_Json_LD_Generator', sprintf( 'generate_%s_schema', $type ) );

			if ( $type != 'single' && ! is_callable( $callback ) ) {
				$callback = array( 'BF_Json_LD_Generator', sprintf( 'generate_single_schema', $type ) );
			}

			self::$generators[] = array(
				'type'     => 'single',
				'callback' => $callback,
			);
		}


		// Print data
		if ( ! empty( self::$generators ) ) {
			add_action( 'wp_head', 'BF_Json_LD_Generator::print_output' );
			add_action( 'better-amp/template/head', 'BF_Json_LD_Generator::print_output' );
		}

	}


	/**
	 *  Check current single post have review ?
	 *
	 * @since 2.10.0
	 *
	 * @return bool
	 */
	public static function is_review_active() {

		if ( ! class_exists( 'Better_Reviews' ) ||
		     ! function_exists( 'better_reviews_is_review_active' ) ||
		     ! function_exists( 'better_reviews_get_total_rate' )
		) {
			return false;
		}

		return better_reviews_is_review_active();
	}


	/**
	 * Get the Post Author
	 *
	 * @since 2.10.0
	 * @return string
	 */
	public static function get_the_author() {

		return get_the_author();
	}


	/**
	 * Escape shortcodes and tags of text
	 *
	 * @param string $text
	 * @param int    $limit
	 *
	 * @return string $text
	 */
	private static function esc_text( $text, $limit = 0 ) {

		$text = strip_tags( $text );

		$text = strip_shortcodes( $text );

		$text = str_replace( array( "\r", "\n" ), '', $text );

		if ( $limit ) {
			return self::substr_text( $text, $limit );
		} else {
			return $text;
		}
	}


	/**
	 * Return a pice of text
	 *
	 * @param string $text
	 * @param int    $length
	 *
	 * @return string $text
	 */
	private static function substr_text( $text = '', $length = 110 ) {

		if ( empty( $text ) ) {
			return $text;
		}

		return mb_substr( $text, 0, $length, 'UTF-8' );
	}


	/**
	 * Generate Organization Schema
	 *
	 * @since 2.10.0
	 * @return array
	 */
	public static function generate_organization_schema() {

		$data = array(
			"@context" => "http://schema.org/",
			'@type'    => 'Organization',
			'@id'      => '#organization',
		);

		if ( ! empty( self::$config['logo'] ) ) {
			$data['logo'] = array(
				'@type' => 'ImageObject',
				'url'   => self::$config['logo'],
			);
		}

		$data['url']         = home_url( '/' );
		$data['name']        = get_bloginfo( 'name' );
		$data['description'] = self::esc_text( get_bloginfo( 'description' ) );

		return $data;
	}


	/**
	 * Generate WebSite Schema
	 *
	 * @since 2.10.0
	 * @return array
	 */
	public static function generate_website_schema() {

		$data = array(
			"@context"      => "http://schema.org/",
			'@type'         => 'WebSite',
			//
			'name'          => get_bloginfo( 'name' ),
			'alternateName' => self::esc_text( get_bloginfo( 'description' ) ),
			'url'           => home_url( '/' ),
		);

		if ( is_home() || is_front_page() ) {
			$data['potentialAction'] = array(
				'@type'       => 'SearchAction',
				'target'      => get_search_link() . '{search_term}',
				'query-input' => 'required name=search_term'
			);
		}

		return $data;
	}


	/**
	 * Generate WebPage Schema
	 *
	 * @since 2.10.0
	 * @return array
	 */
	public static function generate_page_schema() {

		return self::get_singular_schema( 'WebPage', array( 'add_date' => false ) );
	}


	/**
	 * Generate WooCommerce Schema
	 *
	 * @since 2.10.0
	 * @return array
	 *
	 *
	 * @check http://jsonld.com/product/
	 */
	public static function generate_product_schema() {

		$product = wc_get_product();
		$schema  = self::get_singular_schema( 'Product', false );

		//
		// Change to product to be valid!
		//
		$schema['@type']          = 'Product';
		$schema['name']           = $schema['headline'];
		$schema['brand']          = $schema['publisher'];
		$schema['productionDate'] = $schema['datePublished'];
		unset(
			$schema['headline'],
			$schema['publisher'],
			$schema['dateModified'],
			$schema['datePublished'],
			$schema['author']
		);


		if ( $rating_count = (int) $product->get_rating_count() ) {

			$schema['aggregateRating'] = array(
				'@type'       => 'AggregateRating',
				'ratingValue' => wc_format_decimal( $product->get_average_rating(), 2 ),
				'reviewCount' => $rating_count,
			);
		}

		$schema['offers'] = array(
			'@type'         => 'Offer',
			'priceCurrency' => get_woocommerce_currency(),
			'price'         => $product->get_price(),
			'availability'  => 'http://schema.org/' . ( $product->is_in_stock() ? 'InStock' : 'OutOfStock' ),
		);


		return $schema;
	}


	/**
	 * Generate  Single Post Schema
	 *
	 * @since 2.10.0
	 * @return array
	 */
	public static function generate_single_schema() {

		return self::get_singular_schema( self::$config['posts_type'] );
	}


	/**
	 * Get Singular Post Schema
	 *
	 * @param string $type
	 * @param array  $args
	 *
	 * @since 2.10.0
	 *
	 * @return array
	 */
	public static function get_singular_schema( $type = '', $args = array() ) {

		global $post;

		if ( empty( $type ) ) {
			$type = self::$config['posts_type'];
		}

		if ( ! isset( $args['add_search'] ) ) {
			$args['add_search'] = true;
		}

		if ( ! isset( $args['add_date'] ) ) {
			$args['add_date'] = true;
		}

		if ( ! isset( $args['add_image'] ) ) {
			$args['add_image'] = true;
		}

		$permalink = get_permalink( $post->ID );

		$schema = array(
			"@context" => "http://schema.org/",
			'@type'    => ucfirst( $type ),
			'headline' => $post->post_title,
		);


		//
		// Post excerpt or content
		//
		if ( $post->post_excerpt ) {
			$schema['description'] = $post->post_excerpt;
		} else {
			$schema['description'] = self::esc_text( $post->post_content, 250 );
		}


		//
		// Add date
		//
		if ( $args['add_date'] ) {
			$schema['datePublished'] = get_post_time( 'Y-m-d', false, $post, false );
			$schema['dateModified']  = get_post_modified_time( 'Y-m-d' );
		}


		//
		// Author
		//
		$author = get_the_author_meta( 'display_name', $post->post_author );

		$schema['author'] = array(
			'@type' => 'Person',
			'@id'   => '#person-' . $author,
			'name'  => $author,
		);

		$author = sanitize_html_class( $author );

		$schema['author']['@id'] = '#person-' . $author;


		//
		// Add thumbnail
		//
		if ( $args['add_image'] ) {

			$featured_image = wp_get_attachment_image_src( get_post_thumbnail_id(), 'full' );

			if ( ! empty( $featured_image[0] ) ) {

				$schema['image'] = array(
					'@type' => 'ImageObject',
					'url'   => $featured_image[0],
				);

				// Add width and height
				if ( ! empty( $featured_image[1] ) && ! empty( $featured_image[2] ) ) {
					$schema['image']['width']  = $featured_image[1];
					$schema['image']['height'] = $featured_image[2];
				}
			}
		}


		//
		// Change type to advanced format
		//
		if ( 'post' === $post->post_type ) {

			$format = get_post_format();

			switch ( $format ) {

				//
				// Audio type
				//
				case 'audio':
					$schema['@type'] = 'AudioObject';

					// Add media
					if ( $media = get_post_meta( $post->ID, self::$config['media_field_id'], true ) ) {
						$schema['contentUrl'] = $media;
					}

					break;

				//
				// Video type
				//
				case 'video':

					$schema['@type'] = 'VideoObject';

					// Add media
					if ( $media = get_post_meta( $post->ID, self::$config['media_field_id'], true ) ) {
						$schema['contentUrl'] = $media;
					}

					//
					// Change to product to be valid!
					//
					$schema['name']         = $schema['headline'];
					$schema['thumbnailUrl'] = empty( $schema['image']['url'] ) ? '' : $schema['image']['url'];
					$schema['uploadDate']   = $schema['datePublished'];
					unset(
						$schema['headline'],
						$schema['datePublished'],
						$schema['dateModified'],
						$schema['image']
					);

					break;

				//
				// Image & Gallery type
				//
				case 'image':
				case 'gallery':
					$schema['@type'] = 'ImageObject';
					break;

			}

		} // Image attachment
		elseif ( 'attachment' === $post->post_type && wp_attachment_is_image() ) {
			$schema['@type'] = 'ImageObject';
		} // Audio attachment
		elseif ( 'attachment' === $post->post_type && wp_attachment_is( 'audio' ) ) {
			$schema['@type']      = 'AudioObject';
			$schema['contentUrl'] = wp_get_attachment_url();
		} // Video attachment
		elseif ( 'attachment' === $post->post_type && wp_attachment_is( 'video' ) ) {
			$schema['@type']      = 'VideoObject';
			$schema['contentUrl'] = wp_get_attachment_url();
		}


		//
		// Review
		// todo add more review plugin support
		//
		if ( self::is_review_active() ) {

			$rating_value = better_reviews_get_total_rate();
			$criteria     = get_post_meta( $post->ID, '_bs_review_criteria', true );

			if ( $rating_value && $criteria ) {

				$worst                  = 0;
				$best                   = 100;
				$schema['itemReviewed'] = array(
					'@type' => 'Thing',
					'name'  => bf_get_post_meta( '_bs_review_heading' ) ? bf_get_post_meta( '_bs_review_heading' ) : get_the_title(),
				);
				$schema['reviewRating'] = array(
					'@type'       => 'Rating',
					'ratingValue' => $rating_value,
					'worstRating' => $worst,
					'bestRating'  => $best,
				);
				$schema['@type']        = 'Product';
			}
		}


		//
		// Comments count
		//
		if ( $post->post_type != 'product' && $post->post_type != 'page' && post_type_supports( $post->post_type, 'comments' ) ) {

			$schema['interactionStatistic'][] = array(
				'@type'                => 'InteractionCounter',
				'interactionType'      => 'http://schema.org/CommentAction',
				'userInteractionCount' => get_comments_number( $post ),
			);
		}


		//
		// Publisher
		//
		$schema['publisher'] = array(
			'@id' => '#organization',
		);


		//
		// Current Web Page
		//
		$schema['mainEntityOfPage'] = $permalink;


		//
		// Add search for pages
		//
		if ( $type === 'WebPage' ) {

			$search_link = get_search_link();
			if ( ! strstr( $search_link, '?' ) ) {
				$search_link = trailingslashit( $search_link );
			}

			$schema['potentialAction'] = array(
				'@type'       => 'SearchAction',
				'target'      => $search_link . '{search_term}',
				'query-input' => 'required name=search_term'
			);
		}

		return array_filter( $schema );
	}
}


BF_Json_LD_Generator::init();
libs/better-framework/json-ld/index.php000064400000000034151214002470014134 0ustar00<?php
// Silence is golden.
libs/better-framework/content-injector/bf-content-inject.php000064400000031330151214002470020260 0ustar00<?php

BF_Content_Inject::init();


/**
 * Class BF_Content_Inject
 *
 * Inject custom code into post content in single page
 *
 * @since 2.10.0
 */
class BF_Content_Inject {

	/**
	 * a Flag to turn injector on/off.
	 *
	 * @var bool
	 */
	static $working = true;

	/**
	 * Store injections list
	 *
	 * @var array
	 *
	 * @since 2.10.0
	 */
	static $injections = array();


	/**
	 * Store Custom configurations
	 *
	 * @var array
	 *
	 * @since 2.14.0
	 */
	static $config = array();


	/**
	 * Inject custom config
	 *
	 * @param array   $item        array {
	 *
	 * @type int      $priority    action priority.optional. default 10
	 * @type string   $position    top|middle|bottom|{Paragraph Number}
	 * @type string   $content     content to inject. optional if $content_cb set
	 * @type callable $content_cb  deferred content callback name. optional if $content set
	 *
	 * @type string   $user_status user sign-in status which is logged-in|guest. optional.
	 * @type callable $filter_cb   custom filter callback. optional.
	 * @type string   $post_type   post type filter. optional.
	 * @type array    $author      authors ID. optional.
	 * @type array    $taxonomies  terms ID. optional. array {
	 *
	 * @type string   $taxonomy    => @type array terms ID
	 *
	 * ...
	 * }
	 * }
	 *
	 * @since 2.10.0
	 */
	public static function inject( $item = array() ) {

		self::$injections[] = $item;
	}


	/**
	 * Injector custom configuration
	 *
	 * @param string $config_name
	 * @param array  $configuration   array {
	 *
	 * @type array   $blocks_elements block level html elements
	 *
	 * }
	 *
	 * @since 2.14.0
	 */
	public static function config( $config_name, $configuration ) {

		self::$config[ $config_name ] = $configuration;
	}


	/**
	 * Initialize library
	 *
	 * @since 2.10.0
	 */
	public static function init() {

		add_filter( 'the_content', 'BF_Content_Inject::the_content', 999 );
	}


	/**
	 * Handy function to get final content of injections.
	 *
	 * @param $injection
	 *
	 * @return mixed|string
	 */
	public static function get_injection_content( $injection ) {

		if ( isset( $injection['content_cb'] ) ) {
			return call_user_func( $injection['content_cb'], $injection );
		} elseif ( isset( $injection['content'] ) ) {
			return $injection['content'];
		}

		return '';
	}


	/**
	 * Modify post content and append custom codes
	 *
	 * @param string $content
	 *
	 * @since 2.10.0
	 * @return string
	 */
	public static function the_content( $content ) {

		if ( ! self::$working ) {
			return $content;
		}

		$before = $after = '';

		$paragraph_changed = false;

		usort( self::$injections, 'BF_Content_Inject::priority_sort' );
		usort( self::$injections, 'BF_Content_Inject::sort_config' );

		foreach ( self::$injections as $_inject ) {

			if ( ! self::can_inject( $_inject ) ) {
				continue;
			}


			if ( $_inject['position'] === 'top' ) {

				$before .= self::get_injection_content( $_inject );

			} elseif ( $_inject['position'] === 'bottom' ) {

				$after .= self::get_injection_content( $_inject );

			} else {

				if ( ! isset( $html_blocks ) ) {
					$html_blocks       = self::get_html_blocks( $content );
					$html_blocks_count = bf_count( $html_blocks );
				}

				if ( $_inject['position'] === 'middle' ) {

					$position = floor( $html_blocks_count / 2 );
					self::inject_after( $html_blocks, $_inject, $position );
					$paragraph_changed = true;

				} elseif ( $position = absint( $_inject['position'] ) ) {

					$config_id    = empty( $_inject['config'] ) ? 'default' : $_inject['config'];
					$allowed_tags = isset( self::$config[ $config_id ]['blocks_elements'] ) ? self::$config[ $config_id ]['blocks_elements'] : array();

					if ( ! $after || ( $position !== $html_blocks_count ) ) {

						self::inject_after( $html_blocks, $_inject, $_inject['position'], $allowed_tags );
						$paragraph_changed = true;
					}
				}
			}
		}

		if ( $paragraph_changed ) {
			$content = '';

			foreach ( $html_blocks as $block ) {
				$content .= $block['content'];
				$content .= ' ';
			}
		}

		return $before . $content . $after;

	} // the_content


	/**
	 * Whether to check can inject custom code or not
	 *
	 * @param array    $conf
	 *
	 * @global WP_Post $post Wordpress active post object
	 *
	 * @since 2.10.0
	 * @return bool true if possible
	 */
	public static function can_inject( $conf ) {

		global $post;

		$return = true;


		//
		// Filter callback
		//
		if ( ! empty( $conf['filter_cb'] ) ) {
			$return = call_user_func( $conf['filter_cb'], $post->ID, $conf, $post );

			if ( ! $return ) {
				return $return;
			}
		}


		//
		// Post type filter
		//
		if ( ! empty( $conf['post_type'] ) ) {

			if ( is_string( $conf['post_type'] ) ) {
				if ( $conf['post_type'] !== $post->post_type ) {
					$return = false;
				}
			} elseif ( is_array( $conf['post_type'] ) ) {
				if ( ! in_array( $post->post_type, $conf['post_type'] ) ) {
					$return = false;
				}
			}

			if ( ! $return ) {
				return $return;
			}
		}


		//
		// User status
		//
		if ( ! empty( $conf['user_status'] ) ) {

			$return = is_user_logged_in() ? 'logged-in' === $conf['user_status'] : 'guest' === $conf['user_status'];

			if ( ! $return ) {
				return $return;
			}
		}


		//
		// Post Author
		//
		if ( ! empty( $conf['author'] ) ) {

			$return = in_array( $post->post_author, $conf['author'] );

			if ( ! $return ) {
				return $return;
			}
		}


		//
		// Taxonomy
		//
		if ( ! empty( $conf['taxonomies'] ) ) {

			foreach ( $conf['taxonomies'] as $taxonomy => $IDs ) {

				$terms_id = wp_get_post_terms( $post->ID, $taxonomy, array( 'fields' => 'ids' ) );

				if ( is_wp_error( $terms_id ) || array_diff( $IDs, $terms_id ) ) {

					$return = false;
					break;
				}
			}

		}


		return $return;

	} // can_inject


	/**
	 * Divide html into several block
	 *
	 * @param string $html
	 * @param string $block_level_elements list of blocks level elements separated by pipe (Vertical bar)
	 *
	 * @return array|bool false on failure or array on success
	 * @since 2.10.0
	 */
	public static function get_html_blocks( $html, $block_level_elements = '' ) {

		if ( ! $block_level_elements ) {
			$block_level_elements = 'address|article|aside|blockquote|canvas|dd|div|dl|fieldset|figcaption|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|li|main|nav|ol|output|p|pre|section|table|tfoot|ul|video';
		}

		preg_match_all( '/
			( # Capture Whole HTML or Text
				\s* ( < \s* (' . $block_level_elements . ')  (?=.*\>) )? # Select HTML Open Tag

				(?(2)  # IF Open Tag Exists
					(.*?)  # accept innerHTML
		             <\s*\/\s*(?:\\3) \s* > \s* # Select HTML Close Tag
				|  # Else
				[^\n]+  # Capture pain text
				)  #END Condition
			)
		 /six', trim( $html ), $match );

		if ( empty( $match ) ) {
			return false;
		}

		$empty_check = array(
			'<p>&amp;nbsp;</p>' => '',
			'&nbsp;'            => '',
			'<p>&nbsp;</p>'     => '',
		);


		$block_valid_html = array();

		if ( array_filter( $match[3] ) ) { // html tag exits

			/**
			 * Fix Nested HTML Tag
			 */
			$html_blocks = array( 0 => array( 'content' => '' ) );
			$last_index  = - 1;

			$mark_plain_text_as_new_block = true;

			foreach ( $match[3] as $index => $tag ) {

				if ( ! trim( $match[1][ $index ] ) ) {
					continue;
				}

				if ( $tag ) {

					$ttext = trim( $match[1][ $index ] );

					if ( ! isset( $block_valid_html[ $index ] ) ) {
						$block_valid_html[ $index ] = self::is_valid_html( $match[0][ $index ] );
					}


					if (
						isset( $empty_check[ $ttext ] )

						|| (
							isset( $html_blocks[ $last_index ]['content'] ) &&
							! self::is_valid_html( $html_blocks[ $last_index ]['content'] )
						)

						|| (
							isset( $block_valid_html[ $index - 1 ] ) && ! $block_valid_html[ $index - 1 ]
						)
					) {

						if ( $last_index === - 1 ) {
							$last_index ++;
						}

						$html_blocks[ $last_index ]['content'] .= $match[0][ $index ];
					} else {

						$last_index ++;
						$html_blocks[ $last_index ]['content'] = $match[0][ $index ];
						$html_blocks[ $last_index ]['tag']     = $tag;

						$mark_plain_text_as_new_block = true;
					}

				} else {

					$is_plain_text = ! strstr( $match[1][ $index ], '<' );

					if ( $is_plain_text && $mark_plain_text_as_new_block ) {

						$last_index ++;
						$mark_plain_text_as_new_block = false;

						$html_blocks[ $last_index ]['content'] = $match[0][ $index ];
						$html_blocks[ $last_index ]['tag']     = $tag;

					} else {

						if ( $last_index === - 1 ) {
							$last_index ++;
						}

						$html_blocks[ $last_index ]['content'] .= $match[0][ $index ];
					}

				}
			}
		} else { // there is no html tag

			$html_blocks = array();

			$i = 0;
			foreach ( $match[0] as $text ) {

				if ( trim( $text ) === '' ) {
					$i ++;
					continue;
				}

				if ( ! isset( $html_blocks[ $i ]['content'] ) ) {
					$html_blocks[ $i ]['content'] = '';
					$html_blocks[ $i ]['tag']     = '';
				}

				$html_blocks[ $i ]['content'] .= "\n";
				$html_blocks[ $i ]['content'] .= $text;

			}
		}

		return $html_blocks;
	} // get_html_blocks


	/**
	 * Inject custom code after a paragraph
	 *
	 * @param array  $blocks    All blocks
	 * @param string $injection Content for injecting it
	 * @param int    $position  Position of injection in blocks
	 * @param array  $tags      todo:doc
	 *
	 * @return string content
	 *
	 * @since 2.10.0
	 */
	public static function inject_after( &$blocks, $injection, $position, $tags = array() ) {

		$inject_position = $position > 0 ? 'after' : 'before';

		if ( $tags ) {

			$tags     = array_flip( $tags );
			$position = absint( $position );

			$i = 0;

			foreach ( $blocks as $idx => $info ) {

				$tag = $info['tag'];

				if ( isset( $tags[ $tag ] ) ) {
					$i ++;
				}

				if ( $i === $position ) {


					if ( 'after' === $inject_position ) {

						$blocks[ $idx ]['content'] .= self::get_injection_content( $injection );

					} else {

						$blocks[ $idx ]['content'] = self::get_injection_content( $injection ) . $blocks[ $idx ]['content'];
					}

					break;
				}
			}

		} else {

			$position --;

			if ( isset( $blocks[ $position ]['content'] ) ) {

				if ( 'after' === $inject_position ) {

					$blocks[ $position ]['content'] .= self::get_injection_content( $injection );
				} else {

					$blocks[ $position ]['content'] = self::get_injection_content( $injection ) . $blocks[ $position ]['content'];
				}
			}
		}
	}


	/**
	 * Partial Check have html valid structure
	 *
	 * @param string $string
	 *
	 * @access private
	 *
	 * @return bool true|null true if valid html false not valid html and null for none-html strings
	 */
	public static function is_valid_html( $string ) {

		if ( preg_match_all( '@\<(/?[^<>&/\<\>\x00-\x20=]++)@', $string, $matches ) ) {
			$tags = array_count_values( $matches[1] );

			$self_close = array(
				'command' => '',
				'keygen'  => '',
				'source'  => '',
				'embed'   => '',
				'area'    => '',
				'base'    => '',
				'br'      => '',
				'col'     => '',
				'hr'      => '',
				'wbr'     => '',
				'img'     => '',
				'link'    => '',
				'meta'    => '',
				'input'   => '',
				'param'   => '',
				'track'   => '',
			);

			foreach ( array_diff_key( $tags, $self_close ) as $tag => $count ) {

				if ( $tag[0] === '/' || $tag[0] === '!' ) {
					continue;
				}

				$close_tag = '/' . $tag;

				if ( ! isset( $tags[ $close_tag ] ) || $tags[ $close_tag ] !== $count ) {
					return false;
				}
			}

			return true;
		}
	}


	/**
	 * Move bottom position indexes up
	 *
	 * @param array  $a
	 * @param  array $b
	 *
	 * @since 2.10.0
	 * @return int
	 */
	public static function sort_config( $a, $b ) {

		if ( $a['position'] === 'bottom' ) {
			return - 1;
		}
		if ( $b['position'] === 'bottom' ) {
			return 1;
		}

		return 0;
	}


	/**
	 * Sort config array by priority
	 *
	 * @param array  $a
	 * @param  array $b
	 *
	 * @since 2.10.0
	 * @return int
	 */
	public static function priority_sort( $a, $b ) {

		$a_priority = isset( $a['priority'] ) ? $a['priority'] : 10;
		$b_priority = isset( $b['priority'] ) ? $b['priority'] : 10;

		if ( $a_priority == $b_priority ) {
			return 0;
		} elseif ( $a_priority < $b_priority ) {
			return - 1;
		} elseif ( $a_priority > $b_priority ) {
			return 1;
		}
	}
}


if ( ! function_exists( 'bf_content_inject' ) ) {

	/**
	 * Inject custom config
	 *
	 * @param array $inject
	 *
	 * @see   BF_Content_Inject::inject
	 *
	 * @since 2.10.0
	 */
	function bf_content_inject( $inject = array() ) {

		BF_Content_Inject::inject( $inject );
	}
}


if ( ! function_exists( 'bf_content_inject_config' ) ) {

	/**
	 * Register custom settings/ configuration for injector
	 *
	 * @param string $config_name
	 * @param array  $configuration
	 *
	 * @see   BF_Content_Inject::config
	 *
	 * @since 2.14.0
	 */
	function bf_content_inject_config( $config_name, $configuration = array() ) {

		BF_Content_Inject::config( $config_name, $configuration );
	}
}
libs/better-framework/content-injector/index.php000064400000000034151214002470016053 0ustar00<?php
// Silence is golden.
libs/better-framework/editor-shortcodes/init.php000064400000032015151214002470016067 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


BF_Editor_Shortcodes::Run();


class BF_Editor_Shortcodes {

	/**
	 * Contains configuration's of shortcodes
	 *
	 * @var array
	 */
	public static $config = array();


	/**
	 * Contains alive instance of class
	 *
	 * @var  self
	 */
	protected static $instance;


	/**
	 * BF_Editor_Shortcodes instance
	 *
	 * @var BF_Editor_Shortcodes
	 */
	protected static $editor_instance;


	/**
	 * All registered shortcodes
	 *
	 * @var array
	 */
	private static $shortcodes = array();


	/**
	 * [ create and ] Returns life version
	 *
	 * @return \BF_Editor_Shortcodes
	 */
	public static function Run() {

		if ( ! self::$instance instanceof self ) {
			self::$instance = new self();
			self::$instance->init();
		}

		return self::$instance;
	}


	/**
	 * Handy function used to get custom value from config
	 *
	 * @param        $id
	 * @param string $default
	 *
	 * @return string
	 */
	public static function get_config( $id = null, $default = '' ) {

		if ( is_null( $id ) ) {
			return $default;
		}

		/**
		 * Calculates numbers of 2 column layout
		 */
		if ( $id === 'layout-2-col' ) {

			if ( ! isset( self::$config[ $id ] ) ) {
				return self::$config[ $id ] = array(
					'width'      => 1180,
					'content'    => 790.6,
					'primary'    => 389.4,
					'calculated' => true,
				);
			}

			if ( isset( self::$config[ $id ]['calculated'] ) ) {
				return self::$config[ $id ];
			}

			self::$config[ $id ]['content'] = ( self::$config[ $id ]['content'] * 0.01 ) * self::$config[ $id ]['width'];
			self::$config[ $id ]['primary'] = ( self::$config[ $id ]['primary'] * 0.01 ) * self::$config[ $id ]['width'];

			self::$config[ $id ]['calculated'] = true;

			return self::$config[ $id ];
		}


		/**
		 * Calculates numbers of 3 column layout
		 */
		if ( $id === 'layout-3-col' ) {

			if ( ! isset( self::$config[ $id ] ) ) {
				return self::$config[ $id ] = array(
					'width'      => 1300,
					'content'    => 754,
					'primary'    => 325,
					'secondary'  => 221,
					'calculated' => true,
				);
			}

			if ( isset( self::$config[ $id ]['calculated'] ) ) {
				return self::$config[ $id ];
			}

			self::$config[ $id ]['content']   = ( self::$config[ $id ]['content'] * 0.01 ) * self::$config[ $id ]['width'];
			self::$config[ $id ]['primary']   = ( self::$config[ $id ]['primary'] * 0.01 ) * self::$config[ $id ]['width'];
			self::$config[ $id ]['secondary'] = ( self::$config[ $id ]['secondary'] * 0.01 ) * self::$config[ $id ]['width'];

			self::$config[ $id ]['calculated'] = true;

			return self::$config[ $id ];
		}

		return isset( self::$config[ $id ] ) ? self::$config[ $id ] : $default;
	}


	/**
	 * @return array
	 */
	public static function get_shortcodes() {

		return self::$shortcodes;
	}


	/**
	 * @param array $shortcodes
	 */
	public static function set_shortcodes( $shortcodes ) {

		self::$shortcodes = $shortcodes;
	}


	/**
	 * Get BF url
	 *
	 * @param string $append optional.
	 *
	 * @return string
	 */
	public static function url( $append = '' ) {

		return bf_get_uri( 'editor-shortcodes/' . ltrim( $append, '/' ) );
	}


	/**
	 * Get library path
	 *
	 * @param string $append optional.
	 *
	 * @return string
	 */
	public static function path( $append = '' ) {

		return bf_get_dir( 'editor-shortcodes/' . ltrim( $append, '/' ) );
	}


	/**
	 * Register Hooks
	 */
	public function init() {

		add_action( 'better-framework/after_setup', array( $this, 'setup_shortcodes' ) );
	}


	/**
	 * Print dynamic editor css
	 */
	public function load_editor_css() {

		if ( isset( $_GET['bf-editor-shortcodes'] ) ) {

			@header( 'Content-Type: text/css; charset=UTF-8' );

			ob_start();

			// IF post ID was bigger than 0 == valid post
			if ( intval( $_GET['bf-editor-shortcodes'] ) > 0 ) {
				if ( ! empty( self::$config['editor-style'] ) ) {
					@include self::$config['editor-style'];
				} else {
					include self::path( '/assets/css/editor-style.php' );
				}

				// Injects dynamics generated CSS codes from PHP files outside of library
				if ( ! empty( self::$config['editor-dynamic-style'] ) ) {

					if ( is_array( self::$config['editor-dynamic-style'] ) ) {

						foreach ( self::$config['editor-dynamic-style'] as $_file ) {
							@include $_file;
						}

					} else {
						@include self::$config['editor-dynamic-style'];
					}
				}
			}


			$output = ob_get_clean();
			$fonts  = '';

			// Move all @import to the beginning of generated CSS
			{
				preg_match_all( '/@import .*/', $output, $matched );

				if ( ! empty( $matched[0] ) ) {
					foreach ( $matched[0] as $item ) {
						$fonts .= $item . "\n\n";

						$output = str_replace( $item, '', $output );
					}
				}
			}

			echo $fonts;
			echo $output;

			exit;
		}

	}


	/**
	 * Adds custom dynamic editor css
	 *
	 * @param  array $stylesheets list of stylesheets uri
	 *
	 * @return array
	 */
	public function prepare_editor_style_uri( $stylesheets = array() ) {

		// Detect current active editor
		{
			$editor = 'tinymce';

			if ( function_exists( 'is_gutenberg_page' ) && is_gutenberg_page() ) {
				$editor = 'gutenberg';
			}
		}

		$url = home_url( '?bf-editor-shortcodes=' . bf_get_admin_current_post_id() . '&editor=' . $editor );
		$url = set_url_scheme( $url );

		// Add dynamic css file
		$stylesheets[] = $url;

		// Enqueue font awesome library from better framework
		$stylesheets[] = BF_URI . 'assets/css/font-awesome.min.css';

		return $stylesheets;
	}


	/**
	 * Add custom editor script
	 */
	public function append_editor_script() {

		wp_enqueue_script( 'bf-editor-script', $this->url( 'assets/js/edit-post-script.js' ), '', Better_Framework()->version );
	}


	/**
	 * Used for retrieving instance
	 *
	 * @param $fresh
	 *
	 * @return mixed
	 */
	public static function editor_instance( $fresh = false ) {

		if ( self::$editor_instance != null && ! $fresh ) {
			return self::$editor_instance;
		}

		if ( ! class_exists( 'BF_Editor_Shortcodes_TinyMCE' ) ) {
			require self::path( 'includes/class-bf-editor-shortcodes-tinymce.php' );
		}

		return self::$editor_instance = new BF_Editor_Shortcodes_TinyMCE();
	}


	/**
	 *
	 */
	public function setup_shortcodes() {

		/**
		 * Retrieves configurations
		 *
		 * @since 1.0.0
		 *
		 * @param string $args reset panel data
		 */
		self::$config = apply_filters( 'better-framework/editor-shortcodes/config', self::$config );

		// injects all our custom styles to TinyMCE
		add_filter( 'editor_stylesheets', array( $this, 'prepare_editor_style_uri' ), 100 );

		// Register style for the Gutenberg
		add_action( 'enqueue_block_editor_assets', array( $this, 'gutenberg_styles' ) );

		// Prints dynamic custom css if needed
		add_action( 'template_redirect', array( $this, 'load_editor_css' ), 1 );
		add_action( 'admin_init', array( $this, 'load_editor_css' ), 1 );

		$this->load_all_shortcodes();

		// registers shortcodes
		add_action( 'init', array( $this, 'register_all_shortcodes' ), 50 );

		global $pagenow;
		// Initiate custom shortcodes only in post edit editor
		if ( is_admin() && ( bf_is_doing_ajax() || in_array( $pagenow, array( 'post-new.php', 'post.php' ) ) ) ) {
			add_action( 'load-post.php', array( $this, 'append_editor_script' ) );
			add_action( 'load-post-new.php', array( $this, 'append_editor_script' ) );

			self::editor_instance();
		}
	}


	/**
	 * Loads all active shortcodes
	 */
	public function load_all_shortcodes() {

		self::set_shortcodes( apply_filters( 'better-framework/editor-shortcodes/shortcodes-array', array() ) );

	}


	/**
	 * Register shortcode from nested array
	 *
	 * @param $shortcode_key
	 * @param $shortcode
	 */
	public function register_shortcode( $shortcode_key, $shortcode ) {

		// Menu
		if ( isset( $shortcode['type'] ) && $shortcode['type'] == 'menu' ) {

			foreach ( (array) $shortcode['items'] as $_shortcode_key => $_shortcode_value ) {

				$this->register_shortcode( $_shortcode_key, $_shortcode_value );

			}

			return;
		}

		// Do not register shortcode
		if ( isset( $shortcode['register'] ) && $shortcode['register'] === false ) {
			return;
		}

		// External callback
		if ( isset( $shortcode['external-callback'] ) && $shortcode['external-callback'] ) {
			call_user_func( 'add' . '_' . 'shortcode', $shortcode_key, $shortcode['external-callback'] );
		} elseif ( isset( $shortcode['callback'] ) ) {
			call_user_func( 'add' . '_' . 'shortcode', $shortcode_key, array( $this, $shortcode['callback'] ) );
		}

	}


	/**
	 * Registers all active shortcodes
	 */
	public function register_all_shortcodes() {

		foreach ( (array) self::get_shortcodes() as $shortcode_key => $shortcode ) {

			$this->register_shortcode( $shortcode_key, $shortcode );

		}
	}


	/**
	 * Enqueue WordPress theme styles within Gutenberg
	 */
	function gutenberg_styles() {

		$list = $this->prepare_editor_style_uri();

		foreach ( $list as $k => $style ) {
			wp_enqueue_style( "bf-gutenberg-$k", $style, false, Better_Framework()->version, 'all' );
		}
	}


	/**
	 * Shortcode: Columns
	 */
	public function columns( $atts, $content = null ) {

		extract( shortcode_atts( array( 'class' => '' ), $atts ) );

		$classes = array( 'row', 'bs-row-shortcode' );

		if ( $class ) {
			$classes = array_merge( $classes, explode( ' ', $class ) );
		}

		$output = '<div class="' . implode( ' ', $classes ) . '">';

		$this->temp['columns'] = array();

		// parse nested shortcodes and collect data
		do_shortcode( $content );

		foreach ( $this->temp['columns'] as $column ) {
			$output .= $column;
		}

		unset( $this->temp['columns'] );

		return $output . '</div>';
	}


	/**
	 * Shortcode Helper: Column
	 */
	public function column( $atts, $content = null ) {

		extract(
			shortcode_atts( array(
				'size'       => '1/1',
				'class'      => '',
				'text_align' => ''
			),
				$atts
			),
			EXTR_SKIP
		);

		$classes = array( 'column' );

		if ( $class ) {
			$classes = array_merge( $classes, explode( ' ', $class ) );
		}

		if ( stristr( $size, '/' ) ) {

			$size = str_replace(
				array(
					'1/1',
					'1/2',
					'1/3',
					'1/4',
				),
				array(
					'col-lg-12',
					'col-lg-6',
					'col-lg-4',
					'col-lg-3',
				),
				$size
			);

		} else {
			$size = 'col-lg-6';
		}

		// Add size to column classes
		array_push( $classes, $size );

		// Add style such as text-align
		$style = '';
		if ( in_array( $text_align, array( 'left', 'center', 'right' ) ) ) {
			array_push( $classes, esc_attr( strip_tags( $text_align ) ) );
		}

		$this->temp['columns'][] = $column = '<div class="' . implode( ' ', $classes ) . '"' . $style . '>' . do_shortcode( $content ) . '</div>';

		return $column;
	}


	/**
	 * Shortcode: List
	 */
	public function list_shortcode( $atts, $content = null ) {

		extract( shortcode_atts( array( 'style' => 'check', 'class' => '' ), $atts ), EXTR_SKIP );

		$this->temp['list_style'] = $style;

		// parse nested shortcodes and collect data
		$content = do_shortcode( $content );
		$content = preg_replace( '#^<\/p>|<div>|<\/div>|<p>$#', '', $content );
		$content = preg_replace( '#<\/li><br \/>#', '</li>', $content );
		// no list?
		if ( ! preg_match( '#<(ul|ol)[^<]*>#i', $content ) ) {

			$content = '<ul>' . $content . '</ul>'; // escaped before

		}

		$content = preg_replace( '#<ul><br \/>#', '<ul>', $content );

		return '<div class="bs-shortcode-list list-style-' . esc_attr( $style ) . $class . '">' . $content . '</div>';
	}


	/**
	 * Shortcode Helper: List item
	 */
	public function list_item( $atts, $content = null ) {

		$icon = '<i class="fa fa-' . $this->temp['list_style'] . '"></i>';

		return '<li>' . $icon . do_shortcode( $content ) . '</li>';

	}


	/**
	 * Shortcode: Button
	 */
	public function button( $atts, $content = null ) {

		$atts = bf_merge_args( $atts, array(
			'style'      => 'default',
			'link'       => '#link',
			'size'       => 'medium',
			'target'     => '',
			'background' => '',
			'color'      => '',
		) );

		$atts['size'] = str_replace(
			array(
				'large',
				'medium',
				'small',
			),
			array(
				'lg',
				'sm',
				'xs'
			),
			$atts['size']
		);

		$style = '';

		if ( ! empty( $atts['background'] ) ) {
			$style .= 'background:#' . ltrim( $atts['background'], '#' ) . ' !important;';
		}

		if ( ! empty( $atts['color'] ) ) {
			$style .= 'color:#' . ltrim( $atts['color'], '#' ) . ' !important;';
		}

		return '<a class="btn btn-' . $atts['style'] . ' btn-' . $atts['size'] . ' btn-shortcode" href="' . $atts['link'] . '" target="' . $atts['target'] . '" ' . ( $style ? 'style="' . $style . '"' : '' ) . '>' . do_shortcode( $content ) . '</a>';
	}

}
libs/better-framework/editor-shortcodes/index.php000064400000000034151214002470016227 0ustar00<?php
// Silence is golden.
libs/better-framework/editor-shortcodes/assets/js/editor-scripts.js000064400000077122151214002470021652 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */

/**
 *
 * @constructor
 */
function BetterStudio_ShortCodes() {

    this.events = {};

    this.init();
}
BetterStudio_ShortCodes.prototype = {

    _getFormatterName: function (obj) {
        if (typeof obj === 'object') {
            return obj.formatter || obj.command;
        }
    },
    _getFormatterValue: function (obj) {
        if (typeof obj === 'object') {
            return obj.formatterValues;
        }
    },

    _isset: function (variable) {
        return typeof variable === 'undefined' || variable === null ? false : true;
    },

    /**
     * Inserts a p element after the reference element.
     *
     * @param {Element/String/Array} referenceNode Reference element, element id or array of elements to insert after.
     * @private
     */
    _insertPAfter: function (referenceNode) {
        var p = tinyMCE.activeEditor.dom.insertAfter(tinyMCE.activeEditor.dom.create('p', {}, "&nbsp;"), referenceNode),
            rng = tinyMCE.activeEditor.dom.createRng();
        // create p element and move cursor to el
        rng.setStart(p, 0);
        rng.setEnd(p, 0);
        tinyMCE.activeEditor.selection.setRng(rng);
    },

    /**
     * Append an element to referenceNode
     *
     * @param {Element} referenceNode Reference element.
     * @param {Object}  Optional. newElAttr object name/value collection with element attributes.
     * @param {String}  Optional. newElHTML HTML string to set as inner HTML of the element.
     * @param {String}  Optional. newElName Name of new element. default p
     * @private
     */
    _appendElement: function (referenceNode, newElAttr, newElHTML, newElName) {
        if (!referenceNode || !referenceNode.appendChild) {
            return;
        }
        newElName = newElName || 'p';

        var p = referenceNode.appendChild(tinyMCE.activeEditor.dom.create(newElName, newElAttr, newElHTML)),
            rng = tinyMCE.activeEditor.dom.createRng();
        // create p element and move cursor to el
        rng.setStart(p, 0);
        rng.setEnd(p, 0);
        tinyMCE.activeEditor.selection.setRng(rng);
    },
    _runWithDelay: function (callback, delay) {
        setTimeout(callback, delay || 10);
    },

    /**
     * Binds an event listener to a specific internal event by name
     *
     * @param {String}   name     Event name or space separated list of events to bind.
     * @param {callback} callback Callback to be executed when the event occurs.
     */
    on: function (name, callback) {
        if (typeof this.events[name] === 'undefined')
            this.events[name] = [];
        this.events[name].push(callback);
    },

    /**
     * Fire an event
     *
     *  @param {String} name Event name.
     */
    dispatchEvent: function (name) {
        var args = Array.prototype.slice.call(arguments, 1),
            self = this;
        if (typeof this.events[name] === 'object') {
            this.events[name].forEach(function (callback) {
                callback.apply(self, args);
            });
        }
    },

    /**
     * initial Functions & Variables
     */
    init: function () {
        var self = this;

        if (!self._isset(tinyMCE) || !self._isset(tinyMCE.activeEditor) || !self._isset(tinyMCE.activeEditor.formatter)) {
            jQuery(document).on('tinymce-editor-init', function () {
                self.init();
            });
            return;
        }

        this.registerFormatters();
        this.addCommands();
        this.attachEventListeners();
        this.attachInternalEvent();
    },

    each: function (o, cb, s) {
        var n, l;

        if (!o) {
            return 0;
        }

        s = s || o;

        if (o.length !== undefined) {
            // Indexed arrays, needed for Safari
            for (n = 0, l = o.length; n < l; n++) {
                if (cb.call(s, o[n], n, o) === false) {
                    return 0;
                }
            }
        } else {
            // Hashtables
            for (n in o) {
                if (o.hasOwnProperty(n)) {
                    if (cb.call(s, o[n], n, o) === false) {
                        return 0;
                    }
                }
            }
        }

        return 1;
    },

    /**
     * Check user selected thing in editor
     *
     * @returns {boolean} true on success
     */
    isUserSelected: function () {
        var selectionNode = tinyMCE.activeEditor.selection.getNode();

        return !(
            tinyMCE.activeEditor.selection.getNode().parentNode.hasAttribute("data-mce-bogus") ||
            tinyMCE.activeEditor.dom.isEmpty(selectionNode) ||
            tinymce.trim(selectionNode.innerHTML) === '&nbsp;'
        );
    },
    getFormatters: function () {
        return {
            // pullquote
            BS_pullquote_Left: {
                block: 'blockquote',
                classes: 'bs-pullquote bs-pullquote-left'
            },
            BS_pullquote_Right: {
                block: 'blockquote',
                classes: 'bs-pullquote bs-pullquote-right'
            },

            //Dropcap
            BS_Dropcap_Simple: {
                inline: 'span',
                classes: 'dropcap dropcap-simple'
            },
            BS_Dropcap_Square: {
                inline: 'span',
                classes: 'dropcap dropcap-square'
            },
            BS_Dropcap_Square_Outline: {
                inline: 'span',
                classes: 'dropcap dropcap-square-outline'
            },
            BS_Dropcap_circle: {
                inline: 'span',
                classes: 'dropcap dropcap-circle'
            },
            BS_Dropcap_Circle_Outline: {
                inline: 'span',
                classes: 'dropcap dropcap-circle-outline'
            },

            // Highlight
            BS_Highlight: {
                inline: 'mark',
                classes: 'bs-highlight bs-highlight-default'
            },
            BS_Highlight_Red: {
                inline: 'mark',
                classes: 'bs-highlight bs-highlight-red'
            },

            //Alerts
            BS_Alert_Simple: {
                block: 'div',
                classes: 'bs-shortcode-alert alert alert-simple'
            },
            BS_Alert_Success: {
                block: 'div',
                classes: 'bs-shortcode-alert alert alert-success'
            },
            BS_Alert_Info: {
                block: 'div',
                classes: 'bs-shortcode-alert alert alert-info'
            },
            BS_Alert_Warning: {
                block: 'div',
                classes: 'bs-shortcode-alert alert alert-warning'
            },
            BS_Alert_Danger: {
                block: 'div',
                classes: 'bs-shortcode-alert alert alert-danger'
            },
        };
    },

    //TODO use mce native method: this.formatter.get()
    getFormatter: function (name) {
        var formatters = this.getFormatters();
        if (typeof formatters[name] === 'object')
            return formatters[name];
    },
    registerFormatters: function () {
        var self = this;

        self.each(this.getFormatters(), function (obj, id) {
            tinyMCE.activeEditor.formatter.register(id, obj);
        });
    },

    attachEventListeners: function () {
        var self = this;

        tinyMCE.activeEditor.on('NewBlock', function (e) {
            function returnTrue() {
                return true;
            }

            var prev_el = tinyMCE.activeEditor.selection.dom.getPrev(e.newBlock, returnTrue);
            if (!prev_el) {
                return;
            }

            if (e.newBlock.tagName != 'P' || /\bbs\-.+/.test(e.newBlock.className)) {
                if (tinyMCE.activeEditor.dom.isEmpty(prev_el)) {
                    self._insertPAfter(e.newBlock);
                    self.removeNode(prev_el);
                    self.removeNode(e.newBlock);
                }
                /**
                 * inert p element when pressing enter in columns
                 */
                else if (tinyMCE.activeEditor.dom.hasClass(prev_el, 'bs-shortcode-col')) {
                    /**
                     * keep text when press enter between paragraph
                     */
                    if (tinyMCE.activeEditor.dom.isEmpty(e.newBlock)) {
                        self._appendElement(prev_el);
                    } else {
                        self._appendElement(prev_el);
                        self._appendElement(prev_el, {}, e.newBlock.innerHTML);
                    }

                    self.removeNode(e.newBlock);
                }
            }

            /**
             * exit column shortcode when pressing enter in columns
             */
            else if (self.findParentByClass(e.newBlock, 'bs-shortcode-col')) {
                if (prev_el.tagName === 'P' && tinyMCE.activeEditor.dom.isEmpty(prev_el)) {
                    var parent = self.findParentByClass(e.newBlock, 'bs-shortcode-row');
                    //ignore coming out the block while press enter between elements (not bottom)
                    if (!tinyMCE.activeEditor.selection.dom.getNext(e.newBlock, returnTrue)) {
                        self._insertPAfter(parent);
                        self.removeNode(e.newBlock);
                    }
                }
            }

            /**
             * Stop duplicate element when pressed enter key for the following element classes
             */
            var preventDuplicateTag = [
                /\bbs-intro/,
                /\bbs-shortcode-alert/,
            ];
            var i, regex;
            for (i = 0; i < preventDuplicateTag.length; i++) {
                regex = preventDuplicateTag[i];
                if (regex.test(e.newBlock.className)) {
                    self._insertPAfter(e.newBlock);
                    self.removeNode(e.newBlock);
                    break;
                }
            }
        });
    },

    attachInternalEvent: function () {
        var self = this;

        function ins(txt) {
            tinyMCE.activeEditor.insertContent(txt);
        }

        /**
         * Append 'A' character when add dropcap on empty area
         */
        self.on('after-formatter', function (fmt) {
            if (/^\bBS_Dropcap.+/i.test(fmt)) {
                if (!self.isUserSelected()) {
                    ins("A");
                }
            }
        });

        /**
         * Append default text when insert highlight on empty area
         */
        self.on('after-formatter', function (fmt) {
            if (/^\bBS_Highlight.*/i.test(fmt)) {
                if (!self.isUserSelected()) {
                    ins("this is a highlighted text");
                }
            }
        });

        /**
         * Append default text when insert alert on empty area
         */
        self.on('after-formatter', function (fmt) {
            if (!self.isUserSelected()) {
                var matched = /^BS_Alert_(.*?)$/i.exec(fmt);
                if (matched) {
                    switch (matched[1].toLowerCase()) {
                        case 'simple':
                            ins("<p><strong>Simple!</strong> This is an alert message.</p>");
                            break;
                        case 'success':
                            ins("<p><strong>Well done!</strong> You successfully read this important alert message.</p>");
                            break;
                        case 'info':
                            ins("<p><strong>Heads up!</strong> This alert needs your attention, but it&#x2019;s not super important.</p>");
                            break;
                        case 'warning':
                            ins("<p><strong>Warning!</strong> Better check yourself, you&#x2019;re not looking too good.</p>");
                            break;
                        case 'danger':
                            ins("<p><strong>Oh snap!</strong> Change a few things up and try submitting again.</p>");
                            break;
                    }
                }
            }
        });
    },

    /**
     * Remove specified node
     *
     * @param   {Element}  node
     */
    removeNode: function (node) {
        // Make sure that the body node isn't removed

        if (!this.isNodeRoot(node)) {
            tinyMCE.activeEditor.dom.remove(node);
        }
    },

    /**
     * Check is node Root<body> element
     *
     * @returns {boolean}
     */
    isNodeRoot: function (node) {
        return node === tinyMCE.activeEditor.getBody();
    },

    addCommands: function () {
        var self = this,
        edit = tinyMCE.activeEditor;

        edit.addCommand('bs-formatter', function (_, value) {
            edit.formatter.toggle(self._getFormatterName(value), self._getFormatterValue(value));
            edit.fire(value.command);
        });
        /**
         * Custom List Commands
         *
         * todo: InsertUnorderedList command sometime add nested ul
         * <ul>
         *  <ul>
         *   <li>...</li>
         *   ...
         *  </ul>
         * </ul>
         */
        edit.addCommand('BS_CheckList', function () {
            edit.execCommand("InsertUnorderedList", false)
            self._runWithDelay(function () {

                var $list = jQuery(edit.dom.getParent(edit.selection.getNode(), "ul")),
                    listClass = 'bs-shortcode-list',
                    currentListType = 'list-style-check';

                if ($list.hasClass(listClass) && $list.hasClass(currentListType)) {
                    $list.removeClass(listClass).removeClass(currentListType);
                } else if ($list.hasClass(listClass) && !$list.hasClass(currentListType)) {
                    $list[0].className = $list[0].className.replace(/list\-.*/ig, '').trim();
                    $list.addClass(currentListType);
                } else {
                    $list.addClass(listClass).addClass(currentListType);
                }
            });
        });
        edit.addCommand('BS_StarList', function () {
            edit.execCommand("InsertUnorderedList", false)
            self._runWithDelay(function () {

                var $list = jQuery(edit.dom.getParent(edit.selection.getNode(), "ul")),
                    listClass = 'bs-shortcode-list',
                    currentListType = 'list-style-star';

                if ($list.hasClass(listClass) && $list.hasClass(currentListType)) {
                    $list.removeClass(listClass).removeClass(currentListType);
                } else if ($list.hasClass(listClass) && !$list.hasClass(currentListType)) {
                    $list[0].className = $list[0].className.replace(/list\-.*/ig, "").trim();
                    $list.addClass(currentListType);
                } else {
                    $list.addClass(listClass).addClass(currentListType);
                }
            });
        });
        edit.addCommand('BS_EditList', function () {
            edit.execCommand("InsertUnorderedList", false)
            self._runWithDelay(function () {

                var $list = jQuery(edit.dom.getParent(edit.selection.getNode(), "ul")),
                    listClass = 'bs-shortcode-list',
                    currentListType = 'list-style-edit';

                if ($list.hasClass(listClass) && $list.hasClass(currentListType)) {
                    $list.removeClass(listClass).removeClass(currentListType);
                } else if ($list.hasClass(listClass) && !$list.hasClass(currentListType)) {
                    $list[0].className = $list[0].className.replace(/list\-.*/ig, "").trim();
                    $list.addClass(currentListType);
                } else {
                    $list.addClass(listClass).addClass(currentListType);
                }
            });
        });
        edit.addCommand('BS_FolderList', function () {
            edit.execCommand("InsertUnorderedList", false)
            self._runWithDelay(function () {

                var $list = jQuery(edit.dom.getParent(edit.selection.getNode(), "ul")),
                    listClass = 'bs-shortcode-list',
                    currentListType = 'list-style-folder';

                if ($list.hasClass(listClass) && $list.hasClass(currentListType)) {
                    $list.removeClass(listClass).removeClass(currentListType);
                } else if ($list.hasClass(listClass) && !$list.hasClass(currentListType)) {
                    $list[0].className = $list[0].className.replace(/list\-.*/ig, "").trim();
                    $list.addClass(currentListType);
                } else {
                    $list.addClass(listClass).addClass(currentListType);
                }
            });
        });
        edit.addCommand('BS_FileList', function () {
            edit.execCommand("InsertUnorderedList", false)
            self._runWithDelay(function () {

                var $list = jQuery(edit.dom.getParent(edit.selection.getNode(), "ul")),
                    listClass = 'bs-shortcode-list',
                    currentListType = 'list-style-file';

                if ($list.hasClass(listClass) && $list.hasClass(currentListType)) {
                    $list.removeClass(listClass).removeClass(currentListType);
                } else if ($list.hasClass(listClass) && !$list.hasClass(currentListType)) {
                    $list[0].className = $list[0].className.replace(/list\-.*/ig, "").trim();
                    $list.addClass(currentListType);
                } else {
                    $list.addClass(listClass).addClass(currentListType);
                }
            });
        });
        edit.addCommand('BS_HeartList', function () {
            edit.execCommand("InsertUnorderedList", false)
            self._runWithDelay(function () {

                var $list = jQuery(edit.dom.getParent(edit.selection.getNode(), "ul")),
                    listClass = 'bs-shortcode-list',
                    currentListType = 'list-style-heart';

                if ($list.hasClass(listClass) && $list.hasClass(currentListType)) {
                    $list.removeClass(listClass).removeClass(currentListType);
                } else if ($list.hasClass(listClass) && !$list.hasClass(currentListType)) {
                    $list[0].className = $list[0].className.replace(/list\-.*/ig, "").trim();
                    $list.addClass(currentListType);
                } else {
                    $list.addClass(listClass).addClass(currentListType);
                }
            });
        });
        edit.addCommand('BS_AsteriskList', function () {
            edit.execCommand("InsertUnorderedList", false)
            self._runWithDelay(function () {

                var $list = jQuery(edit.dom.getParent(edit.selection.getNode(), "ul")),
                    listClass = 'bs-shortcode-list',
                    currentListType = 'list-style-asterisk';

                if ($list.hasClass(listClass) && $list.hasClass(currentListType)) {
                    $list.removeClass(listClass).removeClass(currentListType);
                } else if ($list.hasClass(listClass) && !$list.hasClass(currentListType)) {
                    $list[0].className = $list[0].className.replace(/list\-.*/ig, "").trim();
                    $list.addClass(currentListType);
                } else {
                    $list.addClass(listClass).addClass(currentListType);
                }
            });
        });

        /**
         * Column commands
         */
        (function () {
            var lorem = '<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt</p>';

            function getRow() {
                var maybeRow, row,
                    rowClass = "bs-shortcode-row";

                maybeRow = edit.selection.getNode();
                if (edit.dom.hasClass(maybeRow, rowClass)) {
                    row = maybeRow;
                } else {
                    row = self.findParentByClass(maybeRow, rowClass)
                }

                return row;
            }

            function appendDefaultText(row) {
                var firstCol = edit.dom.select('.bs-shortcode-col:first', row)[0];
                self._appendElement(firstCol, {}, lorem);
            }

            function moveCaretToFirstColumn(row) {
                self._runWithDelay(function () {
                    if (row) {
                        var rng = edit.dom.createRng();
                        rng.setStart(row, 0);
                        rng.setEnd(row, 0);
                        edit.selection.setRng(rng);
                    }
                });
            }

            /**
             * Prevent insert anything, inside row tag out of a column
             */
            function setContentEditableAttribute(row) {
                //Mark row as none editable element

                //Mark columns as editable element
                var cols = edit.dom.select('.bs-shortcode-col', row);
                self.each(cols, function (col) {
                    col.setAttribute('data-mce-contenteditable', 'true');
                });
            }

            function handleColumn(beforeHTML, afterHTML) {
                //grab selected node and remove it. it will copy to first column
                var selectedNode = edit.selection.getNode(),
                    isNodeBody = self.isNodeRoot(selectedNode),
                    row;

                if (isNodeBody) {
                    var text = edit.selection.getContent();

                    edit.selection.setContent(
                        beforeHTML
                        + text
                        + afterHTML
                    );

                    //row = edit.selection.dom.getPrev(edit.selection.getNode(), function () {
                    //    return true;
                    //});


                } else {
                    self.removeNode(selectedNode);

                    edit.insertContent(
                        beforeHTML
                        + selectedNode.outerHTML
                        + afterHTML
                    );
                    row = getRow();
                }


                self._runWithDelay(function () {
                    row = getRow();

                    moveCaretToFirstColumn(row);
                    setContentEditableAttribute(row);

                    //append default lorem text if needed
                    if (edit.dom.isEmpty(selectedNode)) {
                        appendDefaultText(row);
                    }
                });
            }


            edit.addCommand('BS_Column_2', function () {
                handleColumn('<div class="row bs-shortcode-row bs-shortcode-row-2-column"><div class="col-xs-6 bs-shortcode-col">', '</div><div class="col-xs-6 bs-shortcode-col">' + lorem + '</div></div>');
            });
            edit.addCommand('BS_Column_3', function () {
                handleColumn(
                    '<div class="row bs-shortcode-row bs-shortcode-row-3-column"><div class="col-xs-4 bs-shortcode-col">',
                    '</div><div class="col-xs-4 bs-shortcode-col">' + lorem + '</div><div class="col-xs-4 bs-shortcode-col">' + lorem + '</div></div>'
                );
            });
            edit.addCommand('BS_Column_4', function () {
                handleColumn(
                    '<div class="row bs-shortcode-row bs-shortcode-row-4-column"><div class="col-xs-3 bs-shortcode-col">',
                    '</div><div class="col-xs-3 bs-shortcode-col">' + lorem + '</div><div class="col-xs-3 bs-shortcode-col">' + lorem +
                    '</div><div class="col-xs-3 bs-shortcode-col">' + lorem + '</div></div>'
                );
            });
        })();
    },
    /**
     * Find parent class of referenceNode with specified classes
     *
     * @param   {Element}   referenceNode Reference element.
     * @param   {String}    className
     * @returns {Element}   parent Node
     * @private
     */
    findParentByClass: function (referenceNode, className) {
        var root = tinyMCE.activeEditor.dom.getRoot(),
            parent = referenceNode,
            breaked = false;

        while (parent && parent.parentNode && parent.parentNode != root) {
            parent = parent.parentNode;

            if (className && tinyMCE.activeEditor.dom.hasClass(parent, className)) {
                breaked = true;
                break;
            }
        }
        if (!className || breaked)
            return parent;
    },

    /**
     * Get parent element of node
     *
     * @param   {Element}  node
     * @param   {String}   parentTagName optional.
     * @returns {Element}  parent Node
     */
    getParentNode: function (node, parentTagName) {
        var root = tinyMCE.activeEditor.dom.getRoot(),
            parent,
            editableRoot,
            breaked = false;
        parent = node;

        if (parentTagName) {
            parentTagName = parentTagName.toString().toUpperCase();
        }
        while (parent && parent.parentNode && parent.parentNode != root) {
            parent = parent.parentNode;

            if (parentTagName && parent.tagName === parentTagName) {
                breaked = true;
                break;
            }
        }


        if (!parentTagName || breaked)
            return parent;
    },
    /**
     * Replaces variables in the value. The variable format is %var.
     *
     * @private
     * @param {String} value Value to replace variables in.
     * @param {Object} vars Name/value array with variables to replace.
     * @return {String} New value with replaced variables.
     */
    replaceVars: function (value, vars) {
        if (typeof value != "string") {
            value = value(vars);
        } else if (vars) {
            value = value.replace(/%(\w+)/g, function (str, name) {
                return vars[name] || str;
            });
        }

        return value;
    },

    /**
     * @param {Object} condition
     */
    applyActiveConditions: function (condition) {
        if (!condition)
            return false;

        var active = 1,
            node = tinyMCE.activeEditor.selection.getNode(),
            parent = condition.tagName && !tinyMCE.activeEditor.dom.isBlock(condition.tagName)
                ? node : this.getParentNode(node, condition.parent);

        if (!parent)
            return false;

        if (condition.tagName) {
            active &= condition.tagName.toUpperCase() === parent.tagName;
        }
        if (condition.classes) {
            active &= tinyMCE.activeEditor.dom.hasClass(parent, condition.classes);
        }

        return Boolean(active);
    },

    BS_PostRenderEvent: function (util_Class) {
        var self = this, fmt, values,
            opt = util_Class.settings;

        tinyMCE.activeEditor.on(opt.command, function () {
            var cond;

            fmt = self.getFormatter(self._getFormatterName(opt));
            if (fmt) {
                values = self._getFormatterValue(opt);
                cond = {tagName: fmt.block || fmt.inline, classes: self.replaceVars(fmt.classes, values)};
            } else if (opt.activeConditions) {
                cond = opt.activeConditions;
            } else {
                return;
            }

            var isActive = self.applyActiveConditions(cond);
            util_Class.active(isActive);
        });
    },

    /**
     * Fire Tinymce event
     *
     * @param {String} name Event name.
     */
    fireEvent: function (event) {
        if (event) {
            tinyMCE.activeEditor.fire(event);
        }
    },

    BS_TriggerSubMenu: function (menu_object) {
        var self = this;

        self.each(menu_object, function (obj) {
            self.fireEvent(obj.command);
        })
    },

    BS_CommandClickEvent: function (util_Class) {
        var currentCmd = util_Class.settings.command;
        if (!currentCmd) {
            return;
        }
        var self = this,
            cmd2remove = {name: ''};

        self.each(util_Class.parent().settings.items, function (settings) {
            cmd2remove.name = settings.command;

            if (cmd2remove.name !== currentCmd) {
                if (self.applyActiveConditions(settings.activeConditions)) {
                    tinyMCE.activeEditor.execCommand(cmd2remove.name, false);
                }
            }
        });

        tinyMCE.activeEditor.execCommand(currentCmd, false);
    },
    /**
     * Click event handler
     */
    BS_FormatterClickEvent: function (util_Class) {
        var self = this,
            currentFmt, fmt,
            fmt2remove = {
                name: '',
                value: ''
            };
        //remove another formatters
        currentFmt = self._getFormatterName(util_Class.settings);
        this.each(util_Class.parent().settings.items, function (settings) {
            fmt2remove.name = self._getFormatterName(settings);
            fmt2remove.value = self._getFormatterValue(settings);
            if (fmt2remove.name !== currentFmt) {
                var fmt = tinyMCE.activeEditor.formatter.get(fmt2remove.name);
                if (tinyMCE.activeEditor.formatter.match(fmt2remove.name, fmt2remove.name) &&
                    (!('toggle' in fmt[0]) || fmt[0].toggle)) {
                    tinyMCE.activeEditor.formatter.remove(fmt2remove.name, fmt2remove.name);
                }
            }
        });

        this.dispatchEvent('before-formatter', currentFmt, util_Class);
        tinyMCE.activeEditor.execCommand('bs-formatter', false, util_Class.settings);
        this.dispatchEvent('after-formatter', currentFmt, util_Class);
    },

    BS_RawJsBeforeClickEvent: function (util_Class) {
        this.dispatchEvent('before-raw-js-click', util_Class.settings, util_Class);
    },
    BS_RawJsAfterClickEvent: function (util_Class) {
        this.dispatchEvent('after-raw-js-click', util_Class.settings, util_Class);
    },
    /**
     * Toggle classes and remove another classes
     *
     * @param {String} classes list of classes separated by comma
     * @param {RegExp} removeClassPattern remove all classes with this pattern on node
     * @param {Node}   node optional, default current selection
     */
    toggleClass: function (classes, removeClassPattern, node) {
        var self = this,
            currentClasses,
            nodes = node ? [node] : tinyMCE.activeEditor.selection.getSelectedBlocks();

        self.each(nodes, function (node) {
            currentClasses = tinyMCE.activeEditor.dom.getAttrib(node, 'class', false);
            if (currentClasses) {
                self.each(currentClasses.split(' '), function (removeClass) {
                    self.each(classes.split(' '), function (toggledClass) {
                        if (toggledClass !== removeClass && removeClassPattern.test(removeClass)) {
                            tinyMCE.activeEditor.dom.toggleClass(node, removeClass);
                        }
                    });
                });
            }
            tinyMCE.activeEditor.dom.toggleClass(node, classes);
        });
    },

    /**
     * Insert a Button
     *
     * @param {String} btnType
     */
    insertButton: function (btnType) {

        tinyMCE.activeEditor.execCommand("WP_Link", false, {});
        jQuery(tinyMCE.activeEditor.selection.getNode()).addClass("btn btn-default btn-" + btnType);
        tinyMCE.activeEditor.buttons.wp_link_advanced.onclick();
    }
};
libs/better-framework/editor-shortcodes/assets/js/index.php000064400000000034151214002470020145 0ustar00<?php
// Silence is golden.
libs/better-framework/editor-shortcodes/assets/js/edit-post-script.js000064400000002457151214002470022110 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */

jQuery(function ($) {
    var $document = jQuery(document);

    $document.on('tinymce-editor-init', function () {

        $document.on("change", ".affect-editor-on-change :input", function () {
            var input_match = this.name.match(/\[([^\]]+)\]$/);
            if (!input_match)
                return false;
            var input_name = input_match[1];

            jQuery("#content_ifr").contents().find("body").attr("data-" + input_name, this.value);
        }).find(".affect-editor-on-change")
            .find(':checked,:selected')
            .change();
    });
});
libs/better-framework/editor-shortcodes/assets/img/betterstudio-shortcodes.png000064400000002564151214002470024075 0ustar00�PNG


IHDR��
tEXtSoftwareAdobe ImageReadyq�e<#iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.5-c014 79.151481, 2013/03/13-12:09:15        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CC (Macintosh)" xmpMM:InstanceID="xmp.iid:46AE898701A611E4BC59DBD97E61D249" xmpMM:DocumentID="xmp.did:46AE898801A611E4BC59DBD97E61D249"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:46AE898501A611E4BC59DBD97E61D249" stRef:documentID="xmp.did:46AE898601A611E4BC59DBD97E61D249"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>�6�IDATx�b���?�{��8�9V�y9 ^��(n|�����[�����,�o��F��͝������r����?��'�@\?���;��?!v�Sf�Z�"
9�E
ӻ�
�|���_�g��EQ,�r��J�b��Wr}��=אl �c?�OI�Bjb�,����@��=�60@�WF����CĞ���h���x��7��_a�}���a��o�^�`")�A���?��a�bc���?��w?�~��?��2���,�b����|b`z��ὰ�O���?�B���w?�b�,?�_}b`��APZ���_FF�
|���?~���"���?�/��0q|d`�f�Al�s�w��ba�*��w!ѱ|���|�L2�,K�i�L��������ln^���N )�}�J3�
��?����)����)�ճ/Ȋx��S e��҆�
�0r/��'��IEND�B`�libs/better-framework/editor-shortcodes/assets/css/style-tinymce-layout.css000064400000016510151214002470023342 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */

/**
** ->Sidebars
**/
.mce-content-body.mceContentBody.mceContentBody {
    max-width: inherit /* layout-2column-content */;
    padding-right: 25px !important;
    padding-left: 15px !important;
    border-right: 1px solid #eee;
    position: relative;
}

.mce-content-body.mceContentBody.mceContentBody.rtl {
    padding-right: 15px !important;
    padding-left: 25px !important;
    border-right: none;
    border-left: 1px solid #eee;
}

.mce-content-body.mceContentBody[data-page_layout^="3-col-"]:before,
.mce-content-body.mceContentBody::after {
    content: 'Sidebar';
    display: block;
    position: absolute;
    top: 0;
    left: 102%;
    width: 10px;
    -ms-word-break: break-all;
    word-break: break-all;
    font-size: 14px;
    color: #d8d8d8;
    text-align: center;
    height: 100%;
    max-width: 330px;
    z-index: 1;
    text-transform: uppercase;
    font-family: sans-serif;
    font-weight: 600;
    line-height: 26px;
    pointer-events: none;
}

.rtl.mce-content-body.mceContentBody[data-page_layout^="3-col-"]:before,
.rtl.mce-content-body.mceContentBody:after {
    left: auto;
    right: 102%;
}

.mce-content-body.mceContentBody[data-page_layout="1-col"] {
    max-width: inherit /* layout-2column-width */;
}

.mce-content-body.mceContentBody[data-page_layout="1-col"]::after {
    display: none;
}

.mce-content-body.mceContentBody[data-page_layout="2-col-left"] {
    margin-left: 50px !important;
    border-left: 1px solid #eee;
    border-right: none;
}

.mce-content-body.mceContentBody.rtl[data-page_layout="2-col-left"] {
    margin-left: auto !important;
    margin-right: 50px !important;
    border-left: none;
    border-right: 1px solid #eee;
}

.mce-content-body.mceContentBody[data-page_layout="2-col-left"]::after {
    left: -25px;
    right: auto;
}

.mce-content-body.mceContentBody.rtl[data-page_layout="2-col-left"]::after {
    right: -25px;
    left: auto;
}

.mce-content-body.mceContentBody[data-page_layout="1-col"] {
    border: none;
    padding-left: 15px;
    padding-right: 15px;
}

@media (max-width: 1px /* layout-2column-content */
) {
    .mce-content-body.mceContentBody[data-page_layout="2-col-left"] {
        margin-left: 38px !important;
    }

    .mce-content-body.mceContentBody.rtl[data-page_layout="2-col-left"] {
        margin-left: auto !important;
        margin-right: 38px !important;
    }
}

@media (max-width: 1px /* layout-2column-content */
) {
    .mce-content-body.mceContentBody::after {
        display: none;
    }

    .mce-content-body.mceContentBody[data-page_layout="1-col"],
    .mce-content-body.mceContentBody[data-page_layout="2-col-left"],
    .mce-content-body.mceContentBody {
        border: none !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        padding-left: 15px !important;
        padding-right: 15px !important;
    }
}

.mce-content-body.mceContentBody[data-page_layout^="3-col-"]:after {
    content: 'Primary';
    color: #c2cad2;
}

.mce-content-body.mceContentBody[data-page_layout^="3-col-"]:before {
    content: 'Secondary';
    color: #d3d4d6;
}

.mce-content-body.mceContentBody[data-page_layout^="3-col-"] {
    max-width: inherit /* layout-3column-content */;
}

.mce-content-body.mceContentBody[data-page_layout="3-col-0"]:before,
.mce-content-body.mceContentBody[data-page_layout="3-col-0"]:after {
    display: none;
}

.mce-content-body.mceContentBody[data-page_layout="3-col-0"] {
    max-width: inherit /* layout-3column-width */;
    border-right: none;
}

.rtl.mce-content-body.mceContentBody[data-page_layout="3-col-0"] {
    border-left: none;
}

.mce-content-body.mceContentBody[data-page_layout="3-col-1"]:before,
.mce-content-body.mceContentBody[data-page_layout="3-col-2"]:after {
    left: 106%;
    border-left: 1px solid #eee;
    padding-left: 22px;
    width: 35px;
}

.rtl.mce-content-body.mceContentBody[data-page_layout="3-col-1"]:before,
.rtl.mce-content-body.mceContentBody[data-page_layout="3-col-2"]:after {
    left: inherit;
    right: 106%;
    border-left: none;
    border-right: 1px solid #eee;
    padding-left: 0;
    padding-right: 22px;
}

.mce-content-body.mceContentBody[data-page_layout="3-col-4"],
.mce-content-body.mceContentBody[data-page_layout="3-col-3"] {
    margin-left: 40px;
}

.rtl.mce-content-body.mceContentBody[data-page_layout="3-col-4"],
.rtl.mce-content-body.mceContentBody[data-page_layout="3-col-3"] {
    margin-left: 0;
    margin-right: 40px;
}

.mce-content-body.mceContentBody[data-page_layout="3-col-4"]:before,
.mce-content-body.mceContentBody[data-page_layout="3-col-3"]:after {
    left: -3%;
    border-right: 1px solid #eee;
    padding-right: 10px;
    width: 21px;
}

.rtl.mce-content-body.mceContentBody[data-page_layout="3-col-4"]:before,
.rtl.mce-content-body.mceContentBody[data-page_layout="3-col-3"]:after {
    left: inherit;
    right: -3%;
    border-right: none;
    border-left: 1px solid #eee;
    padding-right: 0;
    padding-left: 10px;
}

.mce-content-body.mceContentBody[data-page_layout="3-col-6"],
.mce-content-body.mceContentBody[data-page_layout="3-col-5"] {
    margin-left: 70px !important;
    border-right: none;
    border-left: 1px solid #eee;
}

.rtl.mce-content-body.mceContentBody[data-page_layout="3-col-6"],
.rtl.mce-content-body.mceContentBody[data-page_layout="3-col-5"] {
    margin-left: inherit !important;
    margin-right: 70px !important;
    border-left: none;
    border-right: 1px solid #eee;
}

.mce-content-body.mceContentBody[data-page_layout="3-col-6"]:before,
.mce-content-body.mceContentBody[data-page_layout="3-col-5"]:after {
    left: -7.5%;
    border-right: 1px solid #eee;
    padding-right: 10px;
    width: 21px;
}

.rtl.mce-content-body.mceContentBody[data-page_layout="3-col-6"]:before,
.rtl.mce-content-body.mceContentBody[data-page_layout="3-col-5"]:after {
    right: -7.5%;
    border-right: none;
    border-left: 1px solid #eee;
    padding-right: 0;
    padding-left: 10px;
}

.mce-content-body.mceContentBody[data-page_layout="3-col-6"]:after,
.mce-content-body.mceContentBody[data-page_layout="3-col-5"]:before {
    left: -3%;
}

.rtl.mce-content-body.mceContentBody[data-page_layout="3-col-6"]:after,
.rtl.mce-content-body.mceContentBody[data-page_layout="3-col-5"]:before {
    left: inherit;
    right: -3%;
}

@media (max-width: 1px /* layout-3column-content */
) {
    .mce-content-body.mceContentBody[data-page_layout^="3-col-"] {
        border: none !important;
        margin-left: 0 !important;
        margin-right: 0 !important;
        padding-left: 15px !important;
        padding-right: 15px !important;
    }

    .mce-content-body.mceContentBody[data-page_layout^="3-col-"]:before {
        display: none !important;
    }
}
libs/better-framework/editor-shortcodes/assets/css/style-bootstrap.css000064400000234624151214002500022376 0ustar00/*!
 * Generated using the Bootstrap Customizer (http://getbootstrap.com/customize/?id=923cac3803e6fb383ccb)
 * Config saved to config.json and https://gist.github.com/923cac3803e6fb383ccb
 */
*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box} .img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#777}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}mark,.mark{background-color:#fcf8e3;padding:.2em}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#e44e4f}a.text-primary:hover{color:#dd2223}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#e44e4f}a.bg-primary:hover{background-color:#dd2223}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25)}kbd kbd{padding:0;font-size:100%;font-weight:bold;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}.table-responsive{overflow-x:auto;min-height:0.01%}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}input[type="date"],input[type="time"],input[type="datetime-local"],input[type="month"]{line-height:34px;line-height:1.42857143 \0}input[type="date"].input-sm,input[type="time"].input-sm,input[type="datetime-local"].input-sm,input[type="month"].input-sm{line-height:30px;line-height:1.5 \0}input[type="date"].input-lg,input[type="time"].input-lg,input[type="datetime-local"].input-lg,input[type="month"].input-lg{line-height:46px;line-height:1.33 \0}_:-ms-fullscreen,:root input[type="date"],_:-ms-fullscreen,:root input[type="time"],_:-ms-fullscreen,:root input[type="datetime-local"],_:-ms-fullscreen,:root input[type="month"]{line-height:1.42857143}_:-ms-fullscreen.input-sm,:root input[type="date"].input-sm,_:-ms-fullscreen.input-sm,:root input[type="time"].input-sm,_:-ms-fullscreen.input-sm,:root input[type="datetime-local"].input-sm,_:-ms-fullscreen.input-sm,:root input[type="month"].input-sm{line-height:1.5}_:-ms-fullscreen.input-lg,:root input[type="date"].input-lg,_:-ms-fullscreen.input-lg,:root input[type="time"].input-lg,_:-ms-fullscreen.input-lg,:root input[type="datetime-local"].input-lg,_:-ms-fullscreen.input-lg,:root input[type="month"].input-lg{line-height:1.33}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{position:absolute;margin-left:-20px;margin-top:4px \9}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"].disabled,input[type="checkbox"].disabled,fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"]{cursor:not-allowed}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-left:0;padding-right:0}.input-sm,.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm,select.form-group-sm .form-control{height:30px;line-height:30px}textarea.input-sm,textarea.form-group-sm .form-control,select[multiple].input-sm,select[multiple].form-group-sm .form-control{height:auto}.input-lg,.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg,select.form-group-lg .form-control{height:46px;line-height:46px}textarea.input-lg,textarea.form-group-lg .form-control,select[multiple].input-lg,select[multiple].form-group-lg .form-control{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}@media (min-width:768px){.form-horizontal .control-label{text-align:right;margin-bottom:0;padding-top:7px}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.3px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px}}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default.focus,.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#e44e4f;border-color:#e13839}.btn-primary:hover,.btn-primary:focus,.btn-primary.focus,.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#dd2223;border-color:#be1d1e}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#e44e4f;border-color:#e13839}.btn-primary .badge{color:#e44e4f;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success.focus,.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info.focus,.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning.focus,.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger.focus,.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#444;font-weight:normal;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#e44e4f;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#777;text-decoration:none}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none;visibility:hidden}.collapse.in{display:block;visibility:visible}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height, visibility;transition-property:height, visibility;-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;text-align:left;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#262626;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;outline:0;background-color:#e44e4f}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#777}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#777;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#444}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#e44e4f}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none;visibility:hidden}.tab-content>.active{display:block;visibility:visible}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block !important;visibility:visible !important;height:auto !important;padding-bottom:0;overflow:visible !important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px;height:50px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);margin-top:8px;margin-bottom:8px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}}@media (min-width:768px){.navbar-left{float:left !important}.navbar-right{float:right !important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#e7e7e7;color:#555}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#333}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#080808;color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#fff}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#444}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:hover,.label-default[href]:focus{background-color:#5e5e5e}.label-primary{background-color:#e44e4f}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#dd2223}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0%;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#e44e4f;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar,.progress-bar-striped{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table caption,.panel>.table-responsive>.table caption,.panel>.panel-collapse>.table caption{padding-left:15px;padding-right:15px}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body,.panel-group .panel-heading+.panel-collapse>.list-group{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#e44e4f}.panel-primary>.panel-heading{color:#fff;background-color:#e44e4f;border-color:#e44e4f}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#e44e4f}.panel-primary>.panel-heading .badge{color:#e44e4f;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#e44e4f}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;left:0;bottom:0;height:100%;width:100%;border:0}.embed-responsive.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.modal-open{overflow:hidden}.modal{display:none;overflow:hidden;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0, -25%);-ms-transform:translate(0, -25%);-o-transform:translate(0, -25%);transform:translate(0, -25%);-webkit-transition:-webkit-transform 0.3s ease-out;-moz-transition:-moz-transform 0.3s ease-out;-o-transition:-o-transform 0.3s ease-out;transition:transform 0.3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0, 0);-ms-transform:translate(0, 0);-o-transform:translate(0, 0);transform:translate(0, 0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;min-height:16.42857143px}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;visibility:visible;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;right:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-size:14px;font-weight:normal;line-height:1.42857143;text-align:left;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);white-space:normal}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{border-width:10px;content:""}.popover.top>.arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);bottom:-11px}.popover.top>.arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,0.25)}.popover.right>.arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff}.popover.bottom>.arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);top:-11px}.popover.bottom>.arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,0.25)}.popover.left>.arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.panel-body:before,.panel-body:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.panel-body:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important;visibility:hidden !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (max-width:767px){.visible-xs-block{display:block !important}}@media (max-width:767px){.visible-xs-inline{display:inline !important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (min-width:1200px){.visible-lg-block{display:block !important}}@media (min-width:1200px){.visible-lg-inline{display:inline !important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}.visible-print-block{display:none !important}@media print{.visible-print-block{display:block !important}}.visible-print-inline{display:none !important}@media print{.visible-print-inline{display:inline !important}}.visible-print-inline-block{display:none !important}@media print{.visible-print-inline-block{display:inline-block !important}}@media print{.hidden-print{display:none !important}}libs/better-framework/editor-shortcodes/assets/css/bs-shortcodes-editor.css000064400000014741151214002500023262 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */


/*

    1. =>Global

    2. =>Elements

*/


/**
 * 1. =>Global
 **/
i.mce-ico.mce-i-betterstudio_shortcodes:before {
    font-family: 'Better Studio Admin Icons';
    color: #3272a0;
    display: inline-block;
}

/**
 * 2. =>Elements
 **/
.mce-menu-item.mce-highlight-red .mce-text,
.mce-menu-item.mce-highlight .mce-text{
    padding: 0 3px;
}
.mce-menu-item.mce-highlight:hover,
.mce-menu-item.mce-highlight .mce-text{
    background-color: #FF9 !important;
    color: #333 !important;
}
.mce-menu-item.mce-highlight.mce-selected .mce-caret,
.mce-menu-item.mce-highlight:focus .mce-caret,
.mce-menu-item.mce-highlight:hover .mce-caret {
    border-left-color: #333 !important;
}
.mce-menu-item.mce-highlight-red:hover,
.mce-menu-item.mce-highlight-red .mce-text{
    background-color: #FFB6B6 !important;
    color: #333 !important;
}
.mce-menu-item.mce-highlight-red.mce-selected .mce-caret,
.mce-menu-item.mce-highlight-red:focus .mce-caret,
.mce-menu-item.mce-highlight-red:hover .mce-caret {
    border-left-color: #333 !important;
}

.mce-review-percentage.mce-menu-item .mce-text:before,
.mce-review-points.mce-menu-item .mce-text:before,
.mce-review-stars.mce-menu-item .mce-text:before,
.mce-list-asterisk.mce-menu-item .mce-text:before,
.mce-list-heart.mce-menu-item .mce-text:before,
.mce-list-file.mce-menu-item .mce-text:before,
.mce-list-folder.mce-menu-item .mce-text:before,
.mce-list-edit.mce-menu-item .mce-text:before,
.mce-list-star.mce-menu-item .mce-text:before,
.mce-list.mce-menu-item .mce-text:before{
    display: inline-block;
    font-family: FontAwesome;
    font-style: normal;
    font-weight: normal;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    content: '\f00c';
    margin: 0 10px 0 0;
}
.mce-rtl .mce-review-percentage.mce-menu-item .mce-text:before,
.mce-rtl .mce-review-points.mce-menu-item .mce-text:before,
.mce-rtl .mce-review-stars.mce-menu-item .mce-text:before,
.mce-rtl .mce-list-asterisk.mce-menu-item .mce-text:before,
.mce-rtl .mce-list-heart.mce-menu-item .mce-text:before,
.mce-rtl .mce-list-file.mce-menu-item .mce-text:before,
.mce-rtl .mce-list-folder.mce-menu-item .mce-text:before,
.mce-rtl .mce-list-edit.mce-menu-item .mce-text:before,
.mce-rtl .mce-list-star.mce-menu-item .mce-text:before,
.mce-rtl .mce-list.mce-menu-item .mce-text:before{
    margin: 0 0 0 10px;
}
.mce-review-percentage.mce-menu-item:hover .mce-text:before,
.mce-review-points.mce-menu-item:hover .mce-text:before,
.mce-review-stars.mce-menu-item:hover .mce-text:before,
.mce-list-asterisk.mce-menu-item:hover .mce-text:before,
.mce-list-heart.mce-menu-item:hover .mce-text:before,
.mce-list-file.mce-menu-item:hover .mce-text:before,
.mce-list-folder.mce-menu-item:hover .mce-text:before,
.mce-list-edit.mce-menu-item:hover .mce-text:before,
.mce-list-star.mce-menu-item:hover .mce-text:before,
.mce-list.mce-menu-item:hover .mce-text:before{
    font-size: 17px;
    margin-left: -2px;
}
.mce-rtl .mce-review-percentage.mce-menu-item:hover .mce-text:before,
.mce-rtl .mce-review-points.mce-menu-item:hover .mce-text:before,
.mce-rtl .mce-review-stars.mce-menu-item:hover .mce-text:before,
.mce-rtl .mce-list-asterisk.mce-menu-item:hover .mce-text:before,
.mce-rtl .mce-list-heart.mce-menu-item:hover .mce-text:before,
.mce-rtl .mce-list-file.mce-menu-item:hover .mce-text:before,
.mce-rtl .mce-list-folder.mce-menu-item:hover .mce-text:before,
.mce-rtl .mce-list-edit.mce-menu-item:hover .mce-text:before,
.mce-rtl .mce-list-star.mce-menu-item:hover .mce-text:before,
.mce-rtl .mce-list.mce-menu-item:hover .mce-text:before{
    margin-left: 5px;
    margin-right: -2px;
}
.mce-review-stars.mce-menu-item .mce-text:before,
.mce-list-star.mce-menu-item .mce-text:before{
    content: '\f005';
}
.mce-list-edit.mce-menu-item .mce-text:before{
    content: '\f044';
}
.mce-list-folder.mce-menu-item .mce-text:before{
    content: '\f07b';
}
.mce-list-file.mce-menu-item .mce-text:before{
    content: '\f15b';
}
.mce-list-heart.mce-menu-item .mce-text:before{
    content: '\f004';
}
.mce-list-asterisk.mce-menu-item .mce-text:before{
    content: '\f069';
}
.mce-review-points.mce-menu-item .mce-text:before{
    content: '\f0ae';
}
.mce-review-percentage.mce-menu-item .mce-text:before{
    content: '%';
}
.mce-menu-item.mce-alert-warning .mce-text,
.mce-menu-item.mce-alert-info .mce-text,
.mce-menu-item.mce-alert-success .mce-text,
.mce-menu-item.mce-alert-danger .mce-text{
    padding: 0 3px;
}
.mce-menu-item.mce-alert-success.mce-active,
.mce-menu-item.mce-alert-success:hover,
.mce-menu-item.mce-alert-success .mce-text{
    background-color: #dff0d8 !important;
    color: #333 !important;
}
.mce-menu-item.mce-alert-info.mce-active,
.mce-menu-item.mce-alert-info:hover,
.mce-menu-item.mce-alert-info .mce-text{
    background-color: #d9edf7 !important;
    color: #333 !important;
}
.mce-menu-item.mce-alert-warning.mce-active,
.mce-menu-item.mce-alert-warning:hover,
.mce-menu-item.mce-alert-warning .mce-text{
    background-color: #fcf8e3 !important;
    color: #333 !important;
}
.mce-menu-item.mce-alert-danger.mce-active,
.mce-menu-item.mce-alert-danger:hover,
.mce-menu-item.mce-alert-danger .mce-text{
    background-color: #f2dede !important;
    color: #333 !important;
}
.mce-menu-item.mce-bs-separator{
    cursor: default;
    padding: 0 6px;
    position: relative;
    height: 8px;
}
.mce-menu-item.mce-bs-separator:hover{
    background-color: #fff !important;
}
.mce-menu-item.mce-bs-separator .mce-text{
    text-indent: -9999px;
    overflow: hidden;
    display: inline-block;
}
.mce-menu-item.mce-bs-separator .mce-text:before{
    width: 100%;
    height: 1px;
    position: absolute;
    top: 50%;
    left: 0;
    background-color: #eee;
    display: inline-block;
    content: '';
}
.mce-rtl .mce-menu-item.mce-bs-separator .mce-text:before{
    left: auto;
    right: 0;
}
libs/better-framework/editor-shortcodes/assets/css/style-tinymce.css000064400000014405151214002500022022 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */

iframe {
    max-width: 100%;
    height: auto;
}

.entry-content h6:first-child,
.entry-content h5:first-child,
.entry-content h4:first-child,
.entry-content h3:first-child,
.entry-content h2:first-child,
.entry-content h1:first-child {
    margin-top: 0;
}

.mce-content-body img.mce-wp-nextpage {
    height: 25px !important;
}

/**
** ->Padding arrows
**/
.bs-padding-1-1,
.bs-padding-1-0,
.bs-padding-0-1,
.bs-padding-2-2,
.bs-padding-0-2,
.bs-padding-2-0,
.bs-padding-2-1,
.bs-padding-1-2,
.bs-padding-3-3 {
    position: relative;
}

.bs-padding-1-1:after,
.bs-padding-1-0:after,
.bs-padding-0-1:after,
.bs-padding-2-2:after,
.bs-padding-0-2:after,
.bs-padding-2-0:after,
.bs-padding-2-1:after,
.bs-padding-1-2:after,
.bs-padding-3-3:after,
.bs-padding-1-1:before,
.bs-padding-0-1:before,
.bs-padding-1-0:before,
.bs-padding-2-2:before,
.bs-padding-0-2:before,
.bs-padding-2-0:before,
.bs-padding-2-1:before,
.bs-padding-1-2:before,
.bs-padding-3-3:before {
    position: absolute;
    top: 50%;
    -webkit-transform: translateY(-50%);
    -moz-transform: translateY(-50%);
    -ms-transform: translateY(-50%);
    -o-transform: translateY(-50%);
    transform: translateY(-50%);
    color: #dadada;
    font-size: 20px;
    font-weight: bold;
    opacity: 0;
    -webkit-transition: all .6s ease;
    -moz-transition: all .6s ease;
    -o-transition: all .6s ease;
    transition: all .6s ease;
}

.bs-padding-1-0:before,
.bs-padding-1-1:before,
.bs-padding-1-2:before {
    left: -6%;
    content: '\21E5';
}

.rtl .bs-padding-1-0:before,
.rtl .bs-padding-1-1:before,
.rtl .bs-padding-1-2:before {
    left: auto;
    right: -6%;
}

.bs-padding-0-1:after,
.bs-padding-1-1:after,
.bs-padding-2-1:after {
    right: -6%;
    content: '\21E4';
}

.rtl .bs-padding-0-1:after,
.rtl .bs-padding-1-1:after,
.rtl .bs-padding-2-1:after {
    right: auto;
    left: -6%;
}

.bs-padding-2-2:before,
.bs-padding-2-1:before {
    content: '\21E5\21E5';
    left: -12%;
}

.rtl .bs-padding-2-2:before,
.rtl .bs-padding-2-1:before {
    left: auto;
    right: -12%;
}

.bs-padding-2-2:after,
.bs-padding-1-2:after {
    content: '\21E4\21E4';
    right: -12%;
}

.rtl .bs-padding-2-2:after,
.rtl .bs-padding-1-2:after {
    right: auto;
    left: -12%;
}

.bs-padding-3-3:before {
    content: '\21E5\21E5\21E5';
    left: -22%
}

.rtl .bs-padding-3-3:before {
    left: auto;
    right: -22%
}

.bs-padding-3-3:after {
    content: '\21E4\21E4\21E4';
    right: -22%
}

.rtl .bs-padding-3-3:after {
    right: auto;
    left: -22%
}

.mceContentBody.mceContentBody:hover .bs-padding-1-1:after,
.mceContentBody.mceContentBody:hover .bs-padding-1-0:after,
.mceContentBody.mceContentBody:hover .bs-padding-0-1:after,
.mceContentBody.mceContentBody:hover .bs-padding-2-2:after,
.mceContentBody.mceContentBody:hover .bs-padding-0-2:after,
.mceContentBody.mceContentBody:hover .bs-padding-2-0:after,
.mceContentBody.mceContentBody:hover .bs-padding-2-1:after,
.mceContentBody.mceContentBody:hover .bs-padding-1-2:after,
.mceContentBody.mceContentBody:hover .bs-padding-3-3:after,
.mceContentBody.mceContentBody:hover .bs-padding-1-1:before,
.mceContentBody.mceContentBody:hover .bs-padding-0-1:before,
.mceContentBody.mceContentBody:hover .bs-padding-1-0:before,
.mceContentBody.mceContentBody:hover .bs-padding-2-2:before,
.mceContentBody.mceContentBody:hover .bs-padding-0-2:before,
.mceContentBody.mceContentBody:hover .bs-padding-2-0:before,
.mceContentBody.mceContentBody:hover .bs-padding-2-1:before,
.mceContentBody.mceContentBody:hover .bs-padding-1-2:before,
.mceContentBody.mceContentBody:hover .bs-padding-3-3:before {
    opacity: 1;
}

.bs-shortcode-col:before {
    content: '' !important;
    position: absolute !important;
    display: block !important;
    top: -5px !important;
    left: 5px !important;
    right: 5px !important;
    bottom: -5px !important;
    background: #f5f5f5 !important;
    z-index: -1 !important;
    opacity: 0 !important;
    -webkit-transition: all .6s ease;
    -moz-transition: all .6s ease;
    -o-transition: all .6s ease;
    transition: all .6s ease !important;
    transform: none !important;
}

.mceContentBody.mceContentBody:hover .bs-shortcode-col:before {
    opacity: 1 !important;
}

.bs-shortcode-row {
    margin-bottom: 20px;
}

@media (max-width: 700px) {
    .bs-shortcode-row-4-column.bs-shortcode-row-4-column .bs-shortcode-col {
        width: 33.3333% !important;
        margin-bottom: 15px;
    }

    .bs-shortcode-row-4-column.bs-shortcode-row-4-column .bs-shortcode-col:last-child {
        margin-bottom: 0;
    }
}

@media (max-width: 600px) {
    .bs-shortcode-row-4-column.bs-shortcode-row-4-column .bs-shortcode-col,
    .bs-shortcode-row-3-column.bs-shortcode-row-3-column .bs-shortcode-col {
        width: 50% !important;
        margin-bottom: 15px;
    }

    .bs-shortcode-row-4-column.bs-shortcode-row-4-column .bs-shortcode-col:last-child,
    .bs-shortcode-row-3-column.bs-shortcode-row-3-column .bs-shortcode-col:last-child {
        margin-bottom: 0;
    }
}

@media (max-width: 450px) {
    .bs-shortcode-row-4-column.bs-shortcode-row-3-column .bs-shortcode-col,
    .bs-shortcode-row-3-column.bs-shortcode-row-3-column .bs-shortcode-col,
    .bs-shortcode-row-2-column.bs-shortcode-row-2-column .bs-shortcode-col {
        width: 100% !important;
        margin-bottom: 15px;
    }

    .bs-shortcode-row-4-column.bs-shortcode-row-3-column .bs-shortcode-col:last-child,
    .bs-shortcode-row-3-column.bs-shortcode-row-3-column .bs-shortcode-col:last-child,
    .bs-shortcode-row-2-column.bs-shortcode-row-2-column .bs-shortcode-col:last-child {
        margin-bottom: 0;
    }
}
libs/better-framework/editor-shortcodes/assets/css/style-gutenberg.css000064400000013640151214002500022334 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */

iframe {
    max-width: 100%;
    height: auto;
}

/**
** ->Padding arrows
**/
.bs-padding-1-1,
.bs-padding-1-0,
.bs-padding-0-1,
.bs-padding-2-2,
.bs-padding-0-2,
.bs-padding-2-0,
.bs-padding-2-1,
.bs-padding-1-2,
.bs-padding-3-3 {
    position: relative;
}

.bs-padding-1-1:after,
.bs-padding-1-0:after,
.bs-padding-0-1:after,
.bs-padding-2-2:after,
.bs-padding-0-2:after,
.bs-padding-2-0:after,
.bs-padding-2-1:after,
.bs-padding-1-2:after,
.bs-padding-3-3:after,
.bs-padding-1-1:before,
.bs-padding-0-1:before,
.bs-padding-1-0:before,
.bs-padding-2-2:before,
.bs-padding-0-2:before,
.bs-padding-2-0:before,
.bs-padding-2-1:before,
.bs-padding-1-2:before,
.bs-padding-3-3:before {
    position: absolute;
    top: 50%;
    -webkit-transform: translateY(-50%);
    -moz-transform: translateY(-50%);
    -ms-transform: translateY(-50%);
    -o-transform: translateY(-50%);
    transform: translateY(-50%);
    color: #dadada;
    font-size: 20px;
    font-weight: bold;
    opacity: 0;
    -webkit-transition: all .6s ease;
    -moz-transition: all .6s ease;
    -o-transition: all .6s ease;
    transition: all .6s ease;
}

.bs-padding-1-0:before,
.bs-padding-1-1:before,
.bs-padding-1-2:before {
    left: -6%;
    content: '\21E5';
}

.rtl .bs-padding-1-0:before,
.rtl .bs-padding-1-1:before,
.rtl .bs-padding-1-2:before {
    left: auto;
    right: -6%;
}

.bs-padding-0-1:after,
.bs-padding-1-1:after,
.bs-padding-2-1:after {
    right: -6%;
    content: '\21E4';
}

.rtl .bs-padding-0-1:after,
.rtl .bs-padding-1-1:after,
.rtl .bs-padding-2-1:after {
    right: auto;
    left: -6%;
}

.bs-padding-2-2:before,
.bs-padding-2-1:before {
    content: '\21E5\21E5';
    left: -12%;
}

.rtl .bs-padding-2-2:before,
.rtl .bs-padding-2-1:before {
    left: auto;
    right: -12%;
}

.bs-padding-2-2:after,
.bs-padding-1-2:after {
    content: '\21E4\21E4';
    right: -12%;
}

.rtl .bs-padding-2-2:after,
.rtl .bs-padding-1-2:after {
    right: auto;
    left: -12%;
}

.bs-padding-3-3:before {
    content: '\21E5\21E5\21E5';
    left: -22%
}

.rtl .bs-padding-3-3:before {
    left: auto;
    right: -22%
}

.bs-padding-3-3:after {
    content: '\21E4\21E4\21E4';
    right: -22%
}

.rtl .bs-padding-3-3:after {
    right: auto;
    left: -22%
}

.editor-post-visual-editor:hover .bs-padding-1-1:after,
.editor-post-visual-editor:hover .bs-padding-1-0:after,
.editor-post-visual-editor:hover .bs-padding-0-1:after,
.editor-post-visual-editor:hover .bs-padding-2-2:after,
.editor-post-visual-editor:hover .bs-padding-0-2:after,
.editor-post-visual-editor:hover .bs-padding-2-0:after,
.editor-post-visual-editor:hover .bs-padding-2-1:after,
.editor-post-visual-editor:hover .bs-padding-1-2:after,
.editor-post-visual-editor:hover .bs-padding-3-3:after,
.editor-post-visual-editor:hover .bs-padding-1-1:before,
.editor-post-visual-editor:hover .bs-padding-0-1:before,
.editor-post-visual-editor:hover .bs-padding-1-0:before,
.editor-post-visual-editor:hover .bs-padding-2-2:before,
.editor-post-visual-editor:hover .bs-padding-0-2:before,
.editor-post-visual-editor:hover .bs-padding-2-0:before,
.editor-post-visual-editor:hover .bs-padding-2-1:before,
.editor-post-visual-editor:hover .bs-padding-1-2:before,
.editor-post-visual-editor:hover .bs-padding-3-3:before {
    opacity: 1;
}

.bs-shortcode-col:before {
    content: '' !important;
    position: absolute !important;
    display: block !important;
    top: -5px !important;
    left: 5px !important;
    right: 5px !important;
    bottom: -5px !important;
    background: #f5f5f5 !important;
    z-index: -1 !important;
    opacity: 0 !important;
    -webkit-transition: all .6s ease;
    -moz-transition: all .6s ease;
    -o-transition: all .6s ease;
    transition: all .6s ease !important;
    transform: none !important;
}

.editor-post-visual-editor:hover .bs-shortcode-col:before {
    opacity: 1 !important;
}

.bs-shortcode-row {
    margin-bottom: 20px;
}

@media (max-width: 700px) {
    .bs-shortcode-row-4-column.bs-shortcode-row-4-column .bs-shortcode-col {
        width: 33.3333% !important;
        margin-bottom: 15px;
    }

    .bs-shortcode-row-4-column.bs-shortcode-row-4-column .bs-shortcode-col:last-child {
        margin-bottom: 0;
    }
}

@media (max-width: 600px) {
    .bs-shortcode-row-4-column.bs-shortcode-row-4-column .bs-shortcode-col,
    .bs-shortcode-row-3-column.bs-shortcode-row-3-column .bs-shortcode-col {
        width: 50% !important;
        margin-bottom: 15px;
    }

    .bs-shortcode-row-4-column.bs-shortcode-row-4-column .bs-shortcode-col:last-child,
    .bs-shortcode-row-3-column.bs-shortcode-row-3-column .bs-shortcode-col:last-child {
        margin-bottom: 0;
    }
}

@media (max-width: 450px) {
    .bs-shortcode-row-4-column.bs-shortcode-row-3-column .bs-shortcode-col,
    .bs-shortcode-row-3-column.bs-shortcode-row-3-column .bs-shortcode-col,
    .bs-shortcode-row-2-column.bs-shortcode-row-2-column .bs-shortcode-col {
        width: 100% !important;
        margin-bottom: 15px;
    }

    .bs-shortcode-row-4-column.bs-shortcode-row-3-column .bs-shortcode-col:last-child,
    .bs-shortcode-row-3-column.bs-shortcode-row-3-column .bs-shortcode-col:last-child,
    .bs-shortcode-row-2-column.bs-shortcode-row-2-column .bs-shortcode-col:last-child {
        margin-bottom: 0;
    }
}
libs/better-framework/editor-shortcodes/assets/css/bs-shortcodes.css000064400000001346151214002500021773 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */
libs/better-framework/editor-shortcodes/assets/css/editor-style.php000064400000004251151214002500021635 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! empty( $_GET['editor'] ) && $_GET['editor'] == 'gutenberg' ) {
	$editor = 'gutenberg';
} else {
	$editor = 'tinymce';
}

$show_layouts   = BF_Editor_Shortcodes::get_config( 'layouts', true );
$layout_2column = BF_Editor_Shortcodes::get_config( 'layout-2-col' );
$layout_3column = BF_Editor_Shortcodes::get_config( 'layout-3-col' );
$code           = '';

//
// Bootstrap Base style
//
{
	ob_start();
	include 'style-bootstrap.css';
	$code .= ob_get_clean() . "\n\n";
}


//
// Show Sidebar Layouts
//
if ( BF_Editor_Shortcodes::get_config( 'layouts', true ) ) {
	ob_start();
	include 'style-' . $editor . '-layout.css';
	$code .= ob_get_clean() . "\n\n";
}


//
// The editor specific style (TinyMCE or Gutenberg)
//
{
	ob_start();
	include 'style-' . $editor . '.css';
	$code .= ob_get_clean() . "\n\n";
}


//
// Replace Dynamic Constants
//
{
	$replaces = array(
		'inherit /* layout-2column-content */' => $layout_2column['content'] . 'px',
		'1px /* layout-2column-content */'     => $layout_2column['content'] . 'px',
		'inherit /* layout-2column-width */'   => $layout_2column['width'] . 'px',
		//
		'inherit /* layout-3column-content */' => $layout_3column['content'] . 'px',
		'inherit /* layout-3column-width */'   => $layout_3column['width'] . 'px',
		'1px /* layout-3column-content */'     => $layout_3column['content'] . 'px',
	);

	foreach ( $replaces as $k => $v ) {
		$code = str_replace( $k, $v, $code );
	}
}

// Print final CSS
echo $code;
libs/better-framework/editor-shortcodes/assets/css/index.php000064400000000034151214002500020313 0ustar00<?php
// Silence is golden.
libs/better-framework/editor-shortcodes/assets/css/style-gutenberg-layout.css000064400000002056151214002500023646 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */

body.block-editor-page .editor-post-title__block,
body.block-editor-page .editor-default-block-appender,
body.block-editor-page .editor-block-list__block {
    max-width: inherit /* layout-2column-content */ !important;
}

.edit-post-visual-editor .editor-block-list__block[data-align=full] {
    max-width: none !important;
}
libs/better-framework/editor-shortcodes/assets/index.php000064400000000034151214002500017523 0ustar00<?php
// Silence is golden.
libs/better-framework/editor-shortcodes/includes/class-bf-editor-shortcodes-tinymce.php000064400000025201151214002500025522 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Handles admin functionality of shortcodes
 */
class BF_Editor_Shortcodes_TinyMCE {

	function __construct() {

		if ( ! current_user_can( 'edit_pages' ) && ! current_user_can( 'edit_posts' ) ) {
			return;
		}

		$shortcodes = BF_Editor_Shortcodes::get_shortcodes();

		// Check if WYSIWYG is enabled
		if ( 'true' == get_user_option( 'rich_editing' ) && ! empty( $shortcodes ) ) {

			add_filter( 'mce_buttons', array( $this, 'editor_button' ) );

			add_filter( 'mce_external_plugins', array( $this, 'editor_plugin' ) );

			add_action( 'wp_ajax_betterstudio_editor_shortcode_plugin', array( $this, 'render_plugin_js' ) );

		}

		add_action( 'admin_enqueue_scripts', array( $this, 'editor_static_files' ) );
		add_action( 'admin_print_styles', array( $this, 'enqueue_dynamic_css' ) );
	}


	/**
	 * Filter Callback: Adds style
	 */
	public function editor_static_files() {

		bf_enqueue_script( 'bs-shortcode-editor-dep',
			BF_Editor_Shortcodes::url( 'assets/js/editor-scripts.js' ),
			array( 'bf-modal' ),
			BF_Editor_Shortcodes::path( 'assets/js/editor-scripts.js' )
		);

		bf_enqueue_style( 'bf-modal' );

		wp_localize_script( 'bs-shortcode-editor-dep', 'BS_Shortcode_loc', array(
			'save'  => __( 'Save', 'better-studio' ),
			'close' => __( 'Close', 'better-studio' ),
		) );


		wp_enqueue_style( 'betterstudio-editor-shortcodes', BF_Editor_Shortcodes::url( 'assets/css/bs-shortcodes-editor.css' ) );

	}


	public function enqueue_dynamic_css() {

		$icon = BF_Editor_Shortcodes::Run()->get_config( 'icon', array(
			'icon'      => 'bsfi-publisher',
			'type'      => 'bs-icons',
			'height'    => '',
			'width'     => '',
			'font_code' => '\b023',
			'font_name' => 'bs-icons',
		) );

		if ( is_string( $icon ) ) {

			$icon = array(
				'icon'      => 'bsfi-publisher',
				'type'      => 'bs-icons',
				'height'    => '',
				'width'     => '',
				'font_code' => $icon,
				'font_name' => 'Better Studio Admin Icons',
			);
		} else {

			$_check = array(
				'bs-icons'    => 'bs-icons',
				'fontawesome' => 'FontAwesome',
			);

			if ( isset( $_check[ $icon['type'] ] ) ) {
				$icon['font_name'] = $_check[ $icon['type'] ];
			} else {
				$icon['font_name'] = 'Better Studio Admin Icons';
			}
		}

		?>
		<style type="text/css">
			i.mce-ico.mce-i-betterstudio_shortcodes:before {
				content: '<?php echo $icon['font_code']; ?>' !important;
				font-family: '<?php echo $icon['font_name']; ?>' !important;
				color: <?php echo BF_Editor_Shortcodes::Run()->get_config( 'icon-color', '#3272a0' );?> !important;
			}
		</style>
		<?php
	}


	/**
	 * Filter Callback: Adds shortcode list button to TinyMCE
	 *
	 * @param array $buttons
	 *
	 * @return array
	 */
	public function editor_button( $buttons ) {

		array_unshift( $buttons, 'betterstudio_shortcodes', 'separator' );

		return $buttons;
	}


	/**
	 * Filter Callback: Registers js file for shortcode button
	 *
	 * @param $plugin_array
	 *
	 * @return array
	 */
	public function editor_plugin( $plugin_array ) {

		$plugin_array['betterstudio_shortcodes'] = admin_url( 'admin-ajax.php' ) . '?action=betterstudio_editor_shortcode_plugin';

		return $plugin_array;
	}


	/**
	 * Render item and all nested items ( unlimited child )
	 *
	 * @param      $item_key
	 * @param      $item
	 * @param bool $echo
	 *
	 * @return string
	 */
	public function render_item( $item_key, $item, $echo = true ) {

		$output = '';

		// Renders simple buttons
		if ( isset( $item['type'] ) && $item['type'] == 'button' ) {

			$output .= $this->render_single_button( $item_key, $item, false );

		}
		// Renders Separator
		if ( isset( $item['type'] ) && $item['type'] == 'separator' ) {

			$output .= $this->render_separator( false );

		} // Renders drop down menu items
		elseif ( isset( $item['type'] ) && $item['type'] == 'menu' ) {

			if ( isset( $item['items'] ) ) {

				$output .= $this->render_menu( $item_key, $item, false );

			}

		}

		if ( $echo ) {
			echo $output; // escaped before
		} else {
			return $output;
		}

	}


	/**
	 * Renders Separator
	 *
	 * @param bool $echo
	 *
	 * @return string
	 */
	public function render_separator( $echo = true ) {

		$output = "{
                    text: 'separator',";

		if ( isset( $item['classes'] ) ) {
			$output .= "classes: '" . $item['classes'] . ' ' . "bs-separator',";
		} else {
			$output .= "classes: 'bs-separator',";
		}

		$output .= "},";

		if ( $echo ) {
			echo $output; // escaped before
		} else {
			return $output;
		}

	}


	/**
	 * Renders menu element
	 *
	 * @param      $item_key
	 * @param      $item
	 * @param bool $echo
	 *
	 * @return string
	 */
	public function render_menu( $item_key, $item, $echo = true ) {

		$output = "{
                    text: '" . $item['label'] . "',";

		if ( isset( $item['classes'] ) ) {
			$output .= "classes: '" . $item['classes'] . ' ' . $item_key . "',";
		} else {
			$output .= "classes: '" . $item_key . "',";
		}

		if ( isset( $item['icon'] ) ) {
			$output .= "icon: '" . $item['icon'] . "',";
		}

		$output .= ' onshow: onShow, ';
		$output .= "menu: [";

		foreach ( (array) $item['items'] as $_item_key => $_item_value ) {
			$output .= $this->render_item( $_item_key, $_item_value, false );
		}

		$output .= "]},";

		if ( $echo ) {
			echo $output; // escaped before
		} else {
			return $output;
		}
	}


	/**
	 * Used for rendering single button
	 *
	 * @param      $item_key
	 * @param      $item
	 * @param bool $echo
	 *
	 * @return string
	 */
	public function render_single_button( $item_key, $item, $echo = true ) {

		$output = "
            {
                text: '" . $item['label'] . "',";

		if ( isset( $item['classes'] ) ) {
			$output .= "classes: '" . $item['classes'] . ' ' . $item_key . "',";
		} else {
			$output .= "classes: '" . $item_key . "',";
		}

		if ( isset( $item['icon'] ) ) {
			$output .= "icon: '" . $item['icon'] . "',";
		}

		$have_command = false;
		if ( ! empty( $item['formatter'] ) ) {
			$have_command = true;
			$output       .= "
                command: '" . $item['formatter'] . "',
                onPostRender: PostRenderEvent,
			";
		} elseif ( ! empty( $item['command'] ) ) {
			$have_command = true;
			$output       .= "
                command: '" . $item['command'] . "',
                onPostRender: PostRenderEvent,
			";
		}

		if ( ! empty( $item['active_conditions'] ) ) {
			$output .= '
            onPostRender: PostRenderEvent,
			activeConditions: ' . json_encode( $item['active_conditions'] );
			$output .= ',
			';
		}

		if ( ! $have_command ) {
			$output .= '
			command: "' . $item_key . '-active",
		';
		}
		$output .= 'onclick: function() {
			';

		$append_rawjs_event = false;
		if ( ! empty( $item['formatter'] ) ) {
			$output .= 'formatterClickEvent.call(this);
			';
		} elseif ( ! empty( $item['command'] ) ) {
			$output .= 'commandClickEvent.call(this);
			';
		} else {
			$append_rawjs_event = true;
			$output             .= 'rawJsBeforeClickEvent.call(this);
			';
		}

		if ( ! empty( $item['onclick_raw_js'] ) ) {
			$output .= $item['onclick_raw_js'];
		}

		if ( ! empty( $item['wrap_before'] ) && ! empty( $item['wrap_after'] ) ) {
			$output .= "
                    var content = editor.selection.getContent({'format':'html'});
                    editor.insertContent( '" . $item['wrap_before'] . "' + content + '" . $item['wrap_after'] . "' );
                ";
		} elseif ( ! empty( $item['content'] ) ) {
			$output .= "editor.insertContent('" . $item['content'] . "');";
		}
		if ( $append_rawjs_event ) {
			$output .= 'rawJsAfterClickEvent.call(this);
			';

		}

		$output .= "
                }
            },
        ";

		if ( $echo ) {
			echo $output; // escaped before
		} else {
			return $output;
		}

	}


	protected function _js_functions() {

		echo '
        var bs = new BetterStudio_ShortCodes();

        function PostRenderEvent() {
            bs.BS_PostRenderEvent(this);
        }

        function commandClickEvent() {
            bs.BS_CommandClickEvent(this);
        }

        function rawJsBeforeClickEvent() {
            bs.BS_RawJsBeforeClickEvent(this);
        }
        function rawJsAfterClickEvent() {
            bs.BS_RawJsAfterClickEvent(this);
        }

        function formatterClickEvent() {
            bs.BS_FormatterClickEvent(this);
        }

        function onShow() {
            bs.BS_TriggerSubMenu(this.settings.menu);
        }

        function move_caret_first_col(editor) {
            bs.columnMoveCaretFirst(editor, "bs-shortcode-row");
        }

        function toggleClass(classes, removeClassPattern,node) {
            bs.toggleClass(classes, removeClassPattern,node);
        }

		function newButton(btnType) {
            bs.insertButton(btnType);
		}
		var textPaddingPattern = /^bs\-padding\-\d+\-\d+$/,
			introClassPattern  = /\bbs\-intro\-?.*\b/;
		';
	}


	/**
	 * Renders editor plugin js
	 *
	 * TODO Add support versions before 3.9
	 */
	public function render_plugin_js() {

		// Check auth
		if ( ! is_user_logged_in() || ! current_user_can( 'edit_posts' ) ) {
			die( esc_html( __( 'You do not have the right type of authorization. You must be logged in and be able to edit pages and posts.', 'better-studio' ) ) );
		}

		// javascript will be output
		header( 'Content-type: application/x-javascript' );

		echo "(function() {\n";
		$this->_js_functions();

		echo "        tinymce.PluginManager.add( 'betterstudio_shortcodes', function( editor, url ) {
                    editor.addButton( 'betterstudio_shortcodes', {
                        text: '" . BF_Editor_Shortcodes::Run()->get_config( 'name', __( 'Shortcodes', 'better-studio' ) ) . "',
                        icon: 'betterstudio_shortcodes',
                        type: 'menubutton',

                        menu: [";

		foreach ( (array) BF_Editor_Shortcodes::get_shortcodes() as $item_key => $item_value ) {
			echo $this->render_item( $item_key, $item_value, false ); // escaped before inside generator
		}

		echo "
                    ]

                    });
                });";
		echo "\n    })();";

		die(); // end ajax request

	}
}
libs/better-framework/editor-shortcodes/includes/index.php000064400000000034151214002500020027 0ustar00<?php
// Silence is golden.
libs/better-framework/composer.json000064400000000617151214002500013471 0ustar00{
  "require-dev": {
    "phpcompatibility/php-compatibility": "*"
  },
  "scripts": {
    "phpcheck": "./vendor/bin/phpcs -p .",

    "post-install-cmd": "\"vendor/bin/phpcs\" --config-set installed_paths vendor/phpcompatibility/php-compatibility",
    "post-update-cmd" : "\"vendor/bin/phpcs\" --config-set installed_paths vendor/phpcompatibility/php-compatibility"
  },
  "prefer-stable" : true
}libs/better-framework/product-pages/support/class-bf-product-support.php000064400000003122151214002500022625 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Class BF_Product_Support
 */
class BF_Product_Support extends BF_Product_Item {

	public $id = 'support';


	protected function before_render() {

		?>

		<style>
			.bf-btn-primary {
				padding: 3px 13px;
			}

			.bs-pages-secondary-btn {
				background: none;
				border: none;
				color: #a9a9a9;
			}
		</style>
		<?php
	}


	public function render_content( $options ) {

		//todo: hide support links when product was not resisted
		if ( $support_list = apply_filters( 'better-framework/product-pages/support/config', array() ) ) :

			?>
			<div class="bs-product-pages-box-container bf-clearfix">

				<?php
				foreach ( $support_list as $support_data ) {

					$support_data['classes'] = array( 'fix-height-1' );
					bf_product_box( $support_data );
				}
				?>
			</div>

			<?php
		else:

			$this->error( 'no support registered' );
		endif;
	}
}
libs/better-framework/product-pages/support/assets/js/index.php000064400000000006151214002500020766 0ustar00<?php
libs/better-framework/product-pages/support/assets/css/index.php000064400000000006151214002500021142 0ustar00<?php
libs/better-framework/product-pages/support/assets/index.php000064400000000006151214002500020352 0ustar00<?php
libs/better-framework/product-pages/core/class-bf-product-pages-base.php000064400000006155151214002500022345 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Class BS_Theme_Pages_Base
 */
abstract class BF_Product_Pages_Base {

	public static $config = array();


	public function __construct() {

		self::init_config();
	}


	public function error( $error_message ) {

		//todo: print error message

		printf( '<div class="update-nag">%s</div>', $error_message );
	}


	public static function init_config() {

		if ( ! self::$config ) {

			self::$config         = apply_filters( 'better-framework/product-pages/config', array() );
			self::$config['URI']  = BF_PRODUCT_PAGES_URI;
			self::$config['path'] = BF_PRODUCT_PAGES_PATH;
		}

	}


	public static function get_config() {

		self::init_config();

		return self::$config;
	}


	public static function get_product_info( $index, $default = false ) {

		if ( isset( self::$config[ $index ] ) ) {
			return self::$config[ $index ];
		}

		return $default;
	}


	/**
	 * handle api request
	 *
	 * @see \BetterFramework_Oculus::request
	 *
	 * @param string $action
	 * @param array  $data
	 * @param array  $auth
	 * @param bool   $use_wp_error
	 *
	 * @return array|bool|object|WP_Error
	 */
	protected function api_request( $action, $data = array(), $auth = array(), $use_wp_error = true ) {

		if ( ! class_exists( 'BetterFramework_Oculus' ) ) {
			return false;
		}

		$results = BetterFramework_Oculus::request( $action, compact( 'auth', 'data', 'use_wp_error' ) );

		if ( isset( $results->result ) && 'error' === $results->result ) {

			return new WP_Error( $results->{'error-code'}, $results->{'error-message'} );
		}

		return $results;
	} //api_request


	/**
	 * Throw exception when argument is WP_Error
	 *
	 * @param mixed $maybe_wp_error
	 *
	 * @throws BF_Exception
	 */
	protected static function throw_if_is_wp_error( $maybe_wp_error ) {

		if ( is_wp_error( $maybe_wp_error ) ) {
			/**
			 * @var WP_Error $maybe_wp_error
			 */
			$message = '';

			foreach ( $maybe_wp_error->get_error_codes() as $code ) {
				$message .= "\n";
				$message .= $code . ': ';
				$message .= $maybe_wp_error->get_error_message( $code );
				$message .= "\n";
				$message .= print_r( $maybe_wp_error->get_error_data( $code ), true );
				$message .= "\n";
			}

			$message .= " ----- \n";

			$args = func_get_args();
			foreach ( array_slice( $args, 1 ) as $param ) {
				$message .= "\n";
				$message .= print_r( $param, true );
			}

			throw new BF_Exception( $message, $maybe_wp_error->get_error_code() );
		}
	}
}
libs/better-framework/product-pages/core/class-bf-product-item.php000064400000010260151214002500021264 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Class BF_Product_Item
 */
abstract class BF_Product_Item extends BF_Product_Pages_Base {

	public $data;

	public $id;


	abstract public function render_content( $item_data );


	protected function before_render() {

	}


	public function ajax_request( $params ) {

	}


	/**
	 * Display module main content
	 */
	public function render() {


		$page_elements = apply_filters( 'better-framework/product-pages/page/' . $this->id . '/config', array() );

		echo '<div class="wrap bs-product-item">';

		$this->header();

		$this->before_render();

		//call render_content method of children class
		call_user_func( array( $this, 'render_content' ), $page_elements );

		$this->append_hidden_fields();

		$this->after_render();

		do_action( 'better-framework/product-pages/page/' . $this->id . '/loaded', $this->id );

		echo '</div>';

	}


	protected function after_render() {

	}


	/**
	 * append hidden fields for ajax request
	 */
	protected function append_hidden_fields() {

		?>

		<form style="display: none;" id="bs-pages-hidden-params">

			<input type="hidden" name="active-page" id="bs-pages-current-id"
			       value="<?php echo esc_attr( $this->id ) ?>">

			<?php
			wp_nonce_field( 'bs-pages-' . $this->id, 'token', false );

			?>
			<input type="hidden" name="action" value="bs_pages_ajax">

		</form>

		<?php
	}


	protected function get_tabs() {

		global $plugin_page;

		$settings = $this->get_config();

		$results = array();

		if ( isset( $settings['pages'] ) ) {

			foreach ( $settings['pages'] as $id => $menu ) {

				if ( empty( $menu['hide_tab'] ) ) {

					$page_slug = BF_Product_Pages::$menu_slug . "-$id";
					$active    = $page_slug === $plugin_page;

					if ( isset( $menu['type'] ) && $menu['type'] == 'tab_link' ) {
						$url = isset( $menu['tab_link'] ) ? $menu['tab_link'] : '';
					} else {
						$url = admin_url( 'admin.php?page=' . $page_slug );
					}

					$results[ $id ] = array(
						'url'     => $url,
						'active'  => $active,
						'label'   => isset( $menu['tab']['label'] ) ? $menu['tab']['label'] : $menu['name'],
						'classes' => isset( $menu['tab']['classes'] ) ? $menu['tab']['classes'] : '',
						'header'  => isset( $menu['tab']['header'] ) ? $menu['tab']['header'] : '',
					);
				}
			}

		}

		return $results;
	}


	protected function header() {

		?>
		<div class="bs-product-pages-tabs-wrapper">
			<ul class="bs-product-pages-tabs">
				<?php

				$tab_header = '';

				foreach ( $this->get_tabs() as $id => $tab ) {

					if ( empty( $tab['url'] ) ) {
						continue;
					}

					//generate classes
					$classes = array( 'tab' );

					if ( isset( $tab['classes'] ) ) {

						$classes = array_merge( $classes, (array) $tab['classes'] );
					}

					if ( empty( $tab['active'] ) ) {

						$classes = implode( ' ', array_map( 'sanitize_html_class', $classes ) );
						printf( '<li  class="%s"><a href="%s">%s</a></li>', $classes, esc_attr( $tab['url'] ), $tab['label'] );
					} else {

						$classes[] = 'bs-tab-active';

						if ( isset( $tab['header'] ) ) {
							$tab_header = $tab['header'];
						}
						$classes = implode( ' ', array_map( 'sanitize_html_class', $classes ) );
						printf( '<li  class="%s"><span>%s</span></li>', $classes, $tab['label'] );
					}
				}
				?>
			</ul>
			<div class="clear-fix"></div>
		</div>
		<?php if ( $tab_header ) : ?>
			<div class="description-bottom">
				<?php echo $tab_header; // escaped before ?>
			</div>
			<?php
		endif;

	} // header

} // BF_Product_Pages_Baselibs/better-framework/product-pages/core/class-bf-product-pages.php000064400000017024151214002500021432 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Class BF_Product_Pages
 */
class BF_Product_Pages extends BF_Product_Pages_Base {

	/**
	 * Current version number of BS Product Pages
	 *
	 * todo move this to better location
	 *
	 * @var string
	 */
	public static $version = '1.0.0';


	/**
	 * Base menu slug
	 *
	 * @var string
	 */
	public static $menu_slug = 'bs-product-pages';


	/**
	 * Used to get current version number
	 *
	 * @return string
	 */
	public static function get_version() {

		return self::$version;
	}


	/**
	 * @var array
	 */
	protected $instances = array();


	/**
	 * Initialize
	 */
	public static function Run() {

		global $bs_theme_pages;

		if ( $bs_theme_pages === false ) {
			return;
		}

		if ( ! $bs_theme_pages instanceof self ) {
			$bs_theme_pages = new self();
			$bs_theme_pages->init();
		}

		return $bs_theme_pages;
	}


	public static function get_asset_url( $file_path ) {

		return self::$config['URI'] . "/assets/$file_path";
	}


	public static function get_asset_path( $file_path ) {

		return self::$config['path'] . "/assets/$file_path";
	}


	/**
	 * Use to get URL of BS Theme Pages
	 *
	 * @param string $append
	 *
	 * @return string
	 */
	public static function get_url( $append = '' ) {

		return self::$config['URI'] . '/' . $append;
	}


	/**
	 * Use to get path of BS Theme Pages
	 *
	 * @param string $append
	 *
	 * @return string
	 */
	public static function get_path( $append = '' ) {

		return trailingslashit( self::$config['path'] ) . ltrim( $append, '/' );
	}


	public function init() {

		add_action( 'wp_ajax_bs_pages_ajax', array( $this, 'ajax_response' ) );

		add_action( 'after_switch_theme', array( $this, 'show_welcome_page' ), 999 );

		$this->load_modules_function_file();
	}


	/**
	 * handle ajax requests
	 */

	public function ajax_response() {

		$required_fields = array(
			'active-page' => '',
			'token'       => '',
		);

		if ( array_diff_key( $required_fields, $_REQUEST ) ) {
			return;
		}

		try {

			$sub_page_id = &$_REQUEST['active-page'];

			//validate request
			if ( $_REQUEST['token'] !== wp_create_nonce( 'bs-pages-' . $sub_page_id ) ) {
				throw new Exception( 'Security Error' );
			}

			$settings    = $this->get_config();
			$item_params = &$settings['pages'][ $sub_page_id ];
			$item_params = array_merge( $_REQUEST, $item_params );

			$instance = $this->get_instance( $sub_page_id );
			//call ajax_request method of children class
			$response = $instance->ajax_request( $item_params );

			if ( ! $response ) {

				wp_send_json( array(
					'success' => 0,
					'error'   => 'invalid request'
				) );
			} else {

				wp_send_json( array(
					'success' => empty( $response['is_error'] ),
					'result'  => $response
				) );
			}

			$instance = null;

		} catch( Exception $e ) {

			wp_send_json( array(
				'status' => 'error',
				'error'  => $e->getMessage()
			) );

		}

		exit;
	}


	public function plugins_menu_instance() {

		require_once $this->get_path( 'install-plugin/class-bf-product-plugin-manager.php' );

		return new BF_Product_Plugin_Manager();
	}


	public function install_demo_menu_instance() {

		require_once $this->get_path( 'install-demo/class-bf-product-demo-manager.php' );
		require_once $this->get_path( 'install-demo/functions.php' );

		return new BF_Product_Demo_Manager();
	}


	public function support_menu_instance() {

		require_once $this->get_path( 'support/class-bf-product-support.php' );

		return new BF_Product_Support();
	}


	public function welcome_menu_instance() {

		require_once $this->get_path( 'welcome/class-bf-product-welcome.php' );

		return new BF_Product_Welcome();
	}


	public function report_menu_instance() {

		require_once $this->get_path( 'report/class-bf-product-report.php' );

		return new BF_Product_Report();
	}


	/**
	 *
	 * @return array list of modules  array {
	 *
	 *  module name (directory name)
	 *  ...
	 * }
	 */
	protected function get_modules_list() {

		return array(

			'install-plugin',
			'install-demo',
			'support',
			'report',
			'welcome'
		);
	}


	/**
	 * callback: load modules functions.php file
	 * action: admin_init
	 */

	public function load_modules_function_file() {

		foreach ( $this->get_modules_list() as $dir ) {

			$functions_file = $this->get_path( "$dir/functions.php" );

			if ( file_exists( $functions_file ) ) {
				require_once $functions_file;
			}
		}
	}


	/**
	 *
	 * @param string $handler_name
	 *
	 * @return bool|string
	 */
	public function get_item_handler_instance( $handler_name ) {

		$suffix   = '_menu_instance';
		$method   = str_replace( '-', '_', $handler_name ) . $suffix;
		$callback = array( $this, $method );

		if ( is_callable( $callback ) ) {

			return call_user_func( $callback );
		}
	}


	/**
	 * return item object instance
	 *
	 * @param $sub_page_id
	 *
	 * @return BF_Product_Item
	 * @throws Exception
	 */
	public function get_instance( $sub_page_id ) {

		if ( isset( $this->instances[ $sub_page_id ] ) ) {
			return $this->instances[ $sub_page_id ];
		}

		$settings = $this->get_config();

		if ( ! isset( $settings['pages'][ $sub_page_id ] ) ) {
			throw new Exception( 'cannot process your request' );
		}

		$item     = &$settings['pages'][ $sub_page_id ];
		$instance = $this->get_item_handler_instance( $item['type'] );

		if ( ! $instance instanceof BF_Product_Item ) {
			throw new Exception( 'Manager Class is not instance of BS_Theme_Pages_Menu Class' );
		}

		$this->instances[ $sub_page_id ] = $instance;

		return $instance;
	}


	/**
	 * @param string $page_slug
	 *
	 * @return string
	 * @throws Exception
	 */

	public function the_sub_page_id( $page_slug ) {

		$prefix = preg_quote( self::$menu_slug );

		if ( preg_match( "/$prefix\-*(.+)$/i", $page_slug, $match ) ) {

			return $match[1];
		}

		return '';
	}


	/**
	 * Callback function for menus & sub menus
	 */
	public function menu_callback() {

		global $page_hook;

		try {

			if ( ! $sub_page_id = $this->the_sub_page_id( $page_hook ) ) {

				throw new Exception( 'cannot process your request' );
			}

			$settings    = $this->get_config();
			$item_params = &$settings['pages'][ $sub_page_id ];

			$instance = $this->get_instance( $sub_page_id );

			//display html result to admin user
			$instance->render( $item_params );

			$instance = null;

		} catch( Exception $e ) {

			$this->error( $e->getMessage() );
		}

	}


	/**
	 * callback: Redirect user to welcome if welcome page is available after actived BS Theme
	 *
	 * action: after_switch_theme
	 *
	 */
	public function show_welcome_page() {

		global $pagenow;
		if ( $pagenow == 'admin.php' ) {
			return;
		}

		$settings = $this->get_config();
		if ( isset( $settings['pages'] ) && is_array( $settings['pages'] ) ) {

			foreach ( $settings['pages'] as $id => $menu ) {

				if ( $menu['type'] === 'welcome' ) {


					wp_safe_redirect( admin_url( 'admin.php?page=' . self::$menu_slug . "-$id" ) );
					exit;
				}
			}
		}
	}
}


BF_Product_Pages::Run();
libs/better-framework/product-pages/core/functions.php000064400000022133151214002500017172 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_is_product_page' ) ) {

	/**
	 * Determinate is current page a part of product pages
	 *
	 * @param string $page_slug
	 *
	 * @return bool
	 */
	function bf_is_product_page( $page_slug = '' ) {

		global $pagenow;

		if ( $pagenow === 'admin.php' && ! empty( $_GET['page'] ) ) {
			if ( $page_slug ) {
				return BF_Product_Pages::$menu_slug . '-' . $page_slug === $_GET['page'];
			}

			$length = strlen( BF_Product_Pages::$menu_slug );

			return substr( $_GET['page'], 0, $length ) === BF_Product_Pages::$menu_slug;
		}

		return false;
	}
}

add_filter( 'better-framework/admin-notices/show', 'bf_product_notice_thumbnail' );

if ( ! function_exists( 'bf_product_notice_thumbnail' ) ) {

	/**
	 * Append thumbnail image to notice array
	 *
	 * @param array $notices
	 *
	 * @hooked better-framework/admin-notices/show
	 *
	 * @return null|array array on success
	 */
	function bf_product_notice_thumbnail( $notices ) {

		if ( ! bf_is_product_page() ) {
			return;
		}

		static $thumbnail;

		if ( is_null( $thumbnail ) ) {
			$settings  = BF_Product_Pages::get_config();
			$thumbnail = isset( $settings['notice-icon'] ) ? $settings['notice-icon'] : false;
		}

		if ( ! $thumbnail ) {
			return;
		}

		foreach ( $notices as $index => $notice ) {
			if ( empty( $notice['thumbnail'] ) || ! filter_var( $notice['thumbnail'], FILTER_VALIDATE_URL ) ) {
				$notices[ $index ]['thumbnail'] = $thumbnail;
			}
		}

		return $notices;
	}
}

add_action( 'admin_enqueue_scripts', 'bf_product_enqueue_scripts' );

if ( ! function_exists( 'bf_product_enqueue_scripts' ) ) {

	/**
	 * Enqueue static assets
	 *
	 * @hooked admin_enqueue_scripts
	 */
	function bf_product_enqueue_scripts() {

		bf_enqueue_style( 'fontawesome' );
		wp_enqueue_style( 'bs-product-pages-styles', BF_Product_Pages::get_asset_url( 'css/bs-product-pages.css' ), array(), BF_Product_Pages::Run()->get_version() );
	}
}


if ( ! function_exists( 'bf_product_box' ) ) {

	/**
	 * Generate Product Box
	 *
	 *
	 * @param array $box_data    array {
	 *
	 * @type array  $classes     wrapper extra class
	 * @type string $icon        icon   class {@see bf_get_icon_tag}
	 * @type string $header      box header label
	 * @type string $description box container text
	 * @type array buttons array{
	 *  array{
	 * @type string $url         button url
	 * @type string $target      button url
	 * @type string $class       button classes
	 * @type string $label       button label
	 *  }
	 * }
	 *
	 * }
	 */
	function bf_product_box( $box_data ) {

		$box_data = bf_merge_args( $box_data, array(
			'classes'     => array(),
			'has_loading' => false
		) );

		//class bs-pages-box-wrapper is required
		$box_data['classes'][] = 'bs-pages-box-wrapper';
		$box_data['classes']   = array_unique( $box_data['classes'] );
		?>

		<div class="<?php echo implode( ' ', array_map( 'sanitize_html_class', $box_data['classes'] ) ) ?>">
			<?php if ( $box_data['has_loading'] ) : ?>
				<div class="bs-loading-overlay" stlye="display:none;">
					<div class="la-line-scale-pulse-out-rapid la-2x">
						<div></div>
						<div></div>
						<div></div>
						<div></div>
						<div></div>
					</div>
				</div>
			<?php endif ?>
			<div class="bs-pages-box-container">
		<span class="bs-pages-box-header">
			<?php echo ! empty( $box_data['icon'] ) ? bf_get_icon_tag( $box_data['icon'] ) : ''; // escaped before in function ?>
			<?php echo $box_data['header']; // escaped before ?>
		</span>

				<div class="bs-pages-box-description">
					<?php echo $box_data['description']; // escaped before ?>
				</div>

				<?php if ( isset( $box_data['buttons'] ) && bf_count( $box_data['buttons'] ) > 0 ) { ?>
					<div class="bs-pages-buttons">
						<?php foreach ( $box_data['buttons'] as $btn ) { ?>
							<a href="<?php echo ! empty( $btn['url'] ) ? esc_url( $btn['url'] ) : ''; ?>"
							   target="<?php echo ! empty( $btn['target'] ) ? esc_attr( $btn['target'] ) : '_self'; ?>"
							   class="<?php echo ! empty( $btn['class'] ) ? esc_attr( $btn['class'] ) : ''; ?>">
								<?php echo ! empty( $btn['label'] ) ? $btn['label'] : ''; ?>
							</a>
						<?php } ?>
					</div>
				<?php } ?>
			</div>
		</div>
		<?php
	}
}


if ( is_user_logged_in() ) {
	add_action( 'better-framework/admin-menus/admin-menu/before', 'bf_product_register_menus' );
}

if ( ! function_exists( 'bf_product_register_menus' ) ) {

	/**
	 * register admin menu and sub menus
	 *
	 * @hooked better-framework/admin-menus/admin-menu/before
	 */
	function bf_product_register_menus() {

		global $pagenow;

		$settings = BF_Product_Pages::get_config();

		if ( ! isset( $settings['pages'] ) || ! is_array( $settings['pages'] ) ) {
			return;
		}

		$settings = BF_Product_Pages::get_config();

		if ( ! isset( $settings['pages'] ) || ! is_array( $settings['pages'] ) ) {
			return;
		}

		bf_enqueue_style( 'better-studio-admin-icon' );

		$parent_slug = false;

		// todo: check capability of each page, for example check install_plugins capability for plugins page
		$default_capability = 'edit_theme_options';
		$instance           = BF_Product_Pages::Run();

		if ( $pagenow === 'admin.php' && ! empty( $_REQUEST['page'] ) ) {

			$page_slug   = $_REQUEST['page'];
			$active_menu = 'admin_page_' . $page_slug;
		} else {

			$page_slug   = '';
			$active_menu = '';
		}

		foreach ( $settings['pages'] as $id => $menu ) {

			// don't register menu for tab_link type
			if ( isset( $menu['type'] ) && $menu['type'] == 'tab_link' ) {
				continue;
			}

			if ( ! isset( $menu['menu_title'] ) ) {
				$menu['menu_title'] = $menu['name'];
			}

			$_menu_slug = BF_Product_Pages::$menu_slug . "-$id";

			if ( $early_init = $active_menu === get_plugin_page_hookname( plugin_basename( $_menu_slug ), '' ) ) {

				// for active page, fire constructor earlier
				$instance->get_instance( $instance->the_sub_page_id( $page_slug ) );
			}

			// change position from config
			// parent item position should be 3
			if ( $parent_slug === false ) {
				if ( ! empty( $settings['menu_position'] ) ) {
					$default_position = $settings['menu_position'];
				} else {
					$default_position = 3;
				}
			} elseif ( empty( $menu['menu_position'] ) ) {
				$default_position = 50;
			} else {
				$default_position = $menu['menu_position'];
			}

			// Create menu item config
			$menu_config = array(
				'id'           => $_menu_slug,
				'parent'       => $parent_slug ? $parent_slug : false,
				'slug'         => $_menu_slug,
				'name'         => $menu['name'],
				'menu_title'   => isset( $menu['menu_title'] ) ? $menu['menu_title'] : $menu['name'],
				'page_title'   => $menu['name'],
				'parent_title' => $settings['menu_title'],
				'icon'         => isset( $settings['menu_icon'] ) ? $settings['menu_icon'] : '\E000',
				'callback'     => array( $instance, 'menu_callback' ),
				'position'     => $default_position,
				'capability'   => isset( $menu['capability'] ) ? $menu['capability'] : $default_capability,
				'on_admin_bar' => is_admin(),
			);

			Better_Framework()->admin_menus()->add_menupage(
				apply_filters( 'better-framework/product-pages/register-menu/params', $menu_config )
			);

			// cache parent slug for next menu items
			if ( $parent_slug === false ) {
				$parent_slug = $_menu_slug;
			}
		}


		if ( ! defined( 'BF_PRODUCT_PAGES_MAIN_MENU' ) ) {
			define( 'BF_PRODUCT_PAGES_MAIN_MENU', $parent_slug );
		}
	}
} // bf_product_register_menus


if ( ! function_exists( 'bf_product_view' ) ) {

	/**
	 * Load view file
	 *
	 * @param string $view_file view file path
	 * @param array  $vars      pass variables to view
	 * @param array  $options   options
	 *
	 * @return string|WP_Error string on success or WP_Error on failure.
	 */
	function bf_product_view( $view_file, $vars = array(), $options = array() ) {

		$options = wp_parse_args( $options, array(
			'root' => BF_Product_Pages::get_path(),
			'echo' => true,
		) );


		try {

			if ( ! is_string( $view_file ) ) {
				throw new BF_Exception( 'Invalid file name passed!', 'invalid_file_name' );
			}

			$view_full_path = trailingslashit( $options['root'] ) . $view_file . '.php';

			if ( ! is_readable( $view_full_path ) ) {
				throw new BF_Exception( "Cannot read the view file $view_file", 'file_not_found' );
			}

			if ( ! $options['echo'] ) {
				ob_start();
			}

			extract( $vars );

			include $view_full_path;

			if ( ! $options['echo'] ) {
				return ob_get_clean();
			}

		} catch( BF_Exception $e ) {

			return new WP_Error( $e->getCode(), $e->getMessage() );
		}
	}
}libs/better-framework/product-pages/core/class-bf-product-multi-step-item.php000064400000004614151214002500023373 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Class BF_Product_Multi_Step_Item
 */
abstract class BF_Product_Multi_Step_Item extends BF_Product_Item {

	/**
	 *
	 * @param strint|int $key
	 *
	 * @return string
	 */

	protected function get_steps_data_option_name( $key ) {

		return sprintf( 'bs_%s_data_%s', $this->id, $key );
	}


	/**
	 * save item process temporary data
	 *
	 * @param string $item_id
	 * @param mixed  $data
	 *
	 * @return bool
	 */
	protected function set_steps_data( $item_id, $data ) {


		return update_option( $this->get_steps_data_option_name( $item_id ), $data, 'no' );
	}


	/**
	 * delete item process temporary data
	 *
	 * @param string $item_id
	 *
	 * @return bool true if successful, false otherwise
	 */
	protected function delete_steps_data( $item_id ) {

		return delete_option( $this->get_steps_data_option_name( $item_id ) );
	}


	/**
	 * get item process temporary data
	 *
	 * @param string $item_id
	 *
	 * @return bool true if successful, false otherwise
	 */
	protected function get_steps_data( $item_id ) {

		return get_option( $this->get_steps_data_option_name( $item_id ) );
	}


	/**
	 * determinate is final step of import/rollback process
	 *
	 * @param string     $item_id
	 * @param string     $type
	 * @param string|int $step
	 *
	 * @return bool
	 */
	protected function is_final_step( $item_id, $type, $step ) {

		if ( $data = $this->get_steps_data( $item_id ) ) {

			if ( isset( $data['steps'] ) && is_array( $data['steps'] ) ) {

				end( $data['steps'] );

				$final_step_type  = key( $data['steps'] );
				$final_step_count = $data['steps'] [ $final_step_type ];

				return $type === $final_step_type && $step == $final_step_count;
			}
		}

		return false;
	}

}libs/better-framework/product-pages/install-plugin/plugins/index.php000064400000000006151214002500021757 0ustar00<?php
libs/better-framework/product-pages/install-plugin/class-bf-product-plugin-list-table.php000064400000037447151214002500025714 0ustar00<?php

if ( ! class_exists( 'WP_Plugins_List_Table' ) ) {
	_get_list_table( 'WP_Plugins_List_Table' );
}


class BF_Product_Plugin_List_Table extends WP_Plugins_List_Table {


	public function prepare_items() {

		global $page, $s;

		$plugins = $this->get_plugins_list();

		if ( ! empty( $_REQUEST['s'] ) ) {
			$s       = wp_unslash( $_REQUEST['s'] );
			$plugins = $this->filter_plugins( $plugins );
		}

		$total_items = bf_count( $plugins );

		$plugins_per_page = 50;
		$this->items      = $plugins;
		$start            = ( $page - 1 ) * $plugins_per_page;

		if ( $total_items > $plugins_per_page ) {
			$this->items = array_slice( $this->items, $start, $plugins_per_page );
		}

		$this->set_pagination_args( array(
			'total_items' => $total_items,
			'per_page'    => $plugins_per_page,
		) );
	}


	protected function filter_plugins( $plugins ) {

		return array_filter( $plugins, array( $this, 'filter_by_title' ) );
	}


	protected function filter_by_title( $plugin ) {

		global $s;

		return isset( $plugin['name'] ) && mb_strpos( strtolower( $plugin['name'] ), strtolower( $s ) ) !== false;
	}


	protected function badge_classes( $plugin_info ) {

		$classes = array();

		if ( ! empty( $plugin_info['is_premium'] ) ) {

			$classes[] = 'premium';
		}

		if ( ! empty( $plugin_info['is_exclusive'] ) ) {

			$classes[] = 'exclusive';
		}

		if ( ! empty( $plugin_info['is_compatible'] ) ) {

			$classes[] = 'compatible';
		}


		return $classes;
	}


	public function single_row( $item ) {

		global $s, $page;

		list( $plugin_ID, $plugin_info ) = $item;

		$actions          = array();
		$status           = $this->active_status();
		$plugin_file      = BF_Product_Plugin_Installer::the_plugin_file( $plugin_ID );
		$plugin_installed = BF_Product_Plugin_Installer::is_plugin_installed( $plugin_ID );
		$plugin_activated = $plugin_installed && BF_Product_Plugin_Installer::is_plugin_active( $plugin_ID );

		if ( $plugin_data = get_plugins( "/$plugin_ID" ) ) {

			$plugin_data = array_shift( $plugin_data );
		}

		// Plugin Update Available
		$update_available = $plugin_activated && $this->is_update_available( $plugin_ID, $plugin_file, $plugin_data );
		$page_slug        = isset( $_GET['page'] ) ? $_GET['page'] : '';
		$classes          = $this->badge_classes( $plugin_info );

		if ( empty( $plugin_info['have_access'] ) ) {
			$classes[] = 'plugin-not-available';
			$classes[] = 'plugin-not-installed';
		}


		if ( $update_available ) {
			$classes[] = 'plugin-update-available';
		}

		if ( $plugin_installed ) {

			$classes[] = 'plugin-installed';

		} elseif ( ! empty( $plugin_info['have_access'] ) ) {

			$actions['install'] = '<a href="' . wp_nonce_url( 'admin.php?page=' . $page_slug . '&action=install&amp;plugin=' . urlencode( $plugin_ID ) . '&amp;plugin_status=' . $status . '&amp;paged=' . $page . '&amp;s=' . $s, 'install-plugin_' . $plugin_ID ) . '" aria-label="' . esc_attr( sprintf( _x( 'Download & Activate %s', 'better-studio' ), $plugin_info['name'] ) ) . '">' . __( 'Download & Activate', 'better-studio' ) . '</a>';

			$classes[] = 'plugin-not-installed';
		}

		if ( $plugin_activated ) {

			$actions['deactivate'] = '<a href="' . wp_nonce_url( 'admin.php?page=' . $page_slug . '&action=deactivate&amp;plugin=' . urlencode( $plugin_ID ) . '&amp;plugin_status=' . $status . '&amp;paged=' . $page . '&amp;s=' . $s, 'deactivate-plugin_' . $plugin_ID ) . '" aria-label="' . esc_attr( sprintf( _x( 'Deactivate %s', 'better-studio' ), $plugin_info['name'] ) ) . '">' . __( 'Deactivate', 'better-studio' ) . '</a>';
			$classes[]             = 'active';

		} elseif ( $plugin_installed ) {

			$actions['activate'] = '<a href="' . wp_nonce_url( 'admin.php?page=' . $page_slug . '&action=activate&amp;plugin=' . urlencode( $plugin_ID ) . '&amp;plugin_status=' . $status . '&amp;paged=' . $page . '&amp;s=' . $s, 'activate-plugin_' . $plugin_ID ) . '" class="edit" aria-label="' . esc_attr( sprintf( _x( 'Activate %s', 'better-studio' ), $plugin_info['name'] ) ) . '">' . __( 'Activate', 'better-studio' ) . '</a>';
			$actions['delete']   = '<a href="' . wp_nonce_url( 'admin.php?page=' . $page_slug . '&action=delete&amp;plugin=' . urlencode( $plugin_ID ) . '&amp;plugin_status=' . $status . '&amp;paged=' . $page . '&amp;s=' . $s, 'delete-plugin_' . $plugin_ID ) . '" aria-label="' . esc_attr( sprintf( _x( 'Delete %s', 'better-studio' ), $plugin_info['name'] ) ) . '">' . __( 'Delete', 'better-studio' ) . '</a>';
			$classes[]           = 'inactive';
		}

		$plugin_desc_actions = array();

		if ( ! empty( $plugin_data['Version'] ) ) {

			$plugin_desc_actions[] = sprintf(
				__( 'Version %s', 'better-studio' ),
				$plugin_data['Version']
			);
		}

		$plugin_desc_actions[] = sprintf(
			__( 'By %s', 'better-studio' ),
			'<a href="' . $plugin_info['author_uri'] . '">' . $plugin_info['author'] . '</a>'
		);
		?>

		<tr class="<?php echo implode( ' ', $classes ) ?>" data-slug="<?php echo $plugin_ID ?>">

			<?php if ( bf_is_product_registered() ) { ?>
				<th scope="row" class="check-column"
				    rowspan="<?php echo $update_available ? 2 : 1 ?>">
					<label class="screen-reader-text"><?php echo $plugin_info['name'] ?></label>
					<input type="checkbox" name="checked[]" value="<?php echo $plugin_ID ?>">
				</th>

			<?php } ?>

			<td class="plugin-thumbnail"
			    rowspan="<?php echo $update_available ? 2 : 1 ?>">
				<img src="<?php echo $plugin_info['thumbnail'] ?>" width="94" height="94"
				     class="plugin-table-screenshot">
			</td>

			<td class="plugin-title column-primary">

				<strong><?php
					echo $plugin_info['name'];

					if ( ! empty( $plugin_info['is_new'] ) ) {
						echo '<span class="bs-pages-badge bs-pages-badge-new">', __( 'New', 'better-studio' ), '</span>';
					}

					?></strong>

				<?php

				if ( empty( $plugin_info['have_access'] ) && empty( $actions ) ) {
					?>
					<span class="bs-upgrade-notice">

					<?php

					if ( bf_is_product_registered() ) {

						if ( ! empty( $plugin_info['plans'] ) ) {
							$plans_list = implode( __( ' or ', 'better-studio' ), $plugin_info['plans'] );
						} else {

							$plans_list = __( 'higher', 'better-studio' );
						}

						printf(
							__( '<strong>This plugin is not available for your license.</strong> <a href="%s" target="_blank">Upgrade to %s plan</a> for accessing this plugin.', 'better-studio' ),
							'http://betterstudio.com/account/license-manager/',
							$plans_list
						);
					}
					?>
					</span>

				<?php } ?>
				<?php

				if ( bf_is_product_registered() ) {

					echo $this->row_actions( $actions, true );

				} else {

					echo '<div class="bs-upgrade-notice">';
					_e( '<strong>Please register your theme.</strong>', 'better-studio' );
					echo '</div>';
				}

				?>

				<button type="button" class="toggle-row">
					<span class="screen-reader-text"><?php _e( 'Show more details', 'better-studio' ) ?></span>
				</button>
			</td>
			<td class="column-description desc">
				<div class="plugin-description">
					<p><?php echo $plugin_info['description'] ?></p>
				</div>
				<div class="second plugin-version-author-uri">
					<?php

					if ( ! empty( $plugin_info['is_premium'] ) ) {

						echo '<span class="bs-pages-badge bs-pages-badge-premium">', __( 'Premium', 'better-studio' ), '</span>';
					}
					if ( ! empty( $plugin_info['is_exclusive'] ) ) {

						echo '<span class="bs-pages-badge bs-pages-badge-exclusive">', __( 'Exclusive', 'better-studio' ), '</span>';
					}
					if ( ! empty( $plugin_info['is_compatible'] ) ) {

						echo '<span class="bs-pages-badge bs-pages-badge-compatible">', __( 'Compatible', 'better-studio' ), '</span>';
					}
					?>
					<?php echo implode( ' | ', $plugin_desc_actions ); ?>
				</div>
			</td>
		</tr>
		<?php

		if ( $plugin_file && $plugin_activated && $update_available ) {

			$this->wp_plugin_update_row( $plugin_ID, $plugin_file, $plugin_data );
		}
	}


	/**
	 * Check if plugin update is available.
	 *
	 * @param string $plugin_ID
	 * @param string $plugin_file
	 * @param array  $plugin_data
	 *
	 * @return bool true if available.
	 */
	protected function is_update_available( $plugin_ID, $plugin_file, $plugin_data ) {

		if ( BF_Product_Plugin_Installer::is_plugin_latest_version( $plugin_ID ) ) {
			return false;
		}

		// Check local plugin version with remote one version.
		if ( ! empty( $plugin_data['Version'] ) ) {

			$status = get_option( 'bs-product-plugins-status' );

			if ( isset( $status->remote_plugins[ $plugin_file ]['new_version'] ) ) {

				return version_compare(
					$status->remote_plugins[ $plugin_file ]['new_version'], // remote version
					$plugin_data['Version'], // local version
					'>'
				);
			}
		}

		return true;
	}

	/**
	 *
	 * @global string $status
	 * @return array
	 */
	protected function get_views() {

		$page_slug    = isset( $_GET['page'] ) ? $_GET['page'] : '';
		$status_links = array();

		$status = $this->active_status();

		foreach ( $this->get_plugins_stat() as $type => $count ) {
			if ( ! $count ) {
				continue;
			}

			switch ( $type ) {
				case 'all':
					$text = _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $count, 'better-studio' );
					break;

				case 'active':
					$text = _n( 'Active <span class="count">(%s)</span>', 'Active <span class="count">(%s)</span>', $count, 'better-studio' );
					break;

				case 'inactive':
					$text = _n( 'Inactive <span class="count">(%s)</span>', 'Inactive <span class="count">(%s)</span>', $count, 'better-studio' );
					break;

				case 'premium':
					$text = _n( 'Inactive <span class="count">(%s)</span>', 'Premium <span class="count">(%s)</span>', $count, 'better-studio' );
					break;

				case 'exclusive':
					$text = _n( 'Inactive <span class="count">(%s)</span>', 'Exclusive <span class="count">(%s)</span>', $count, 'better-studio' );
					break;

				case 'compatible':
					$text = _n( 'Inactive <span class="count">(%s)</span>', 'Compatible <span class="count">(%s)</span>', $count, 'better-studio' );
					break;
			}

			if ( 'search' !== $type ) {

				$status_links[ $type ] = sprintf( "<a href='%s' %s>%s</a>",
					add_query_arg( 'plugin_status', $type, 'admin.php?page=' . $page_slug ),
					( $type === $status ) ? ' class="current"' : '',
					sprintf( $text, number_format_i18n( $count ) )
				);
			}
		}

		return $status_links;
	}


	/**
	 * @param array $plugin
	 *
	 * @access internal
	 *
	 * @return bool
	 */
	protected function is_plugin_active( $plugin ) {

		return BF_Product_Plugin_Installer::is_plugin_installed( $plugin['slug'] )
		       &&
		       BF_Product_Plugin_Installer::is_plugin_active( $plugin['slug'] );
	}


	/**
	 * @param array $plugin
	 *
	 * @access internal
	 *
	 * @return bool
	 */
	protected function is_plugin_inactive( $plugin ) {

		return ! BF_Product_Plugin_Installer::is_plugin_installed( $plugin['slug'] )
		       ||
		       ! BF_Product_Plugin_Installer::is_plugin_active( $plugin['slug'] );
	}


	/**
	 * Prepare plugins list to view
	 *
	 * @access internal usage
	 * @return array
	 */
	protected function get_plugins_list() {

		$status  = $this->active_status();
		$plugins = bf_get_plugins_config();

		if ( 'active' === $status ) {

			$plugins = array_filter( $plugins, array( $this, 'is_plugin_active' ) );

		} elseif ( 'inactive' === $status ) {

			$plugins = array_filter( $plugins, array( $this, 'is_plugin_inactive' ) );

		} elseif ( 'premium' === $status ) {

			$plugins = array_filter( $plugins, array( $this, 'is_plugin_premium' ) );

		} elseif ( 'exclusive' === $status ) {

			$plugins = array_filter( $plugins, array( $this, 'is_plugin_exclusive' ) );

		} elseif ( 'compatible' === $status ) {

			$plugins = array_filter( $plugins, array( $this, 'is_plugin_compatible' ) );
		}

		return $plugins;
	}


	/**
	 * @param string $file
	 *
	 * @return bool
	 */
	protected function is_wp_plugin_update_available( $file ) {

		static $current;

		if ( ! isset( $current ) ) {
			$current = get_site_transient( 'update_plugins' );
		}

		return isset( $current->response[ $file ] );
	}


	/**
	 * @param string $plugin_slug
	 * @param string $file
	 * @param array  $plugin_data
	 *
	 * @return bool
	 */
	function wp_plugin_update_row( $plugin_slug, $file, $plugin_data ) {

		$plugins_allowedtags = array(
			'a'       => array( 'href' => array(), 'title' => array() ),
			'abbr'    => array( 'title' => array() ),
			'acronym' => array( 'title' => array() ),
			'code'    => array(),
			'em'      => array(),
			'strong'  => array(),
		);

		$page_slug   = isset( $_GET['page'] ) ? $_GET['page'] : '';
		$plugin_name = wp_kses( $plugin_data['Name'], $plugins_allowedtags );
		$details_url = '';

		if ( 'betterstudio' !== strtolower( $plugin_data['Author'] ) ) {
			$details_url = self_admin_url( 'plugin-install.php?tab=plugin-information&plugin=' . $plugin_slug . '&section=changelog&TB_iframe=true&width=600&height=800' );
		}

		//		if ( ! is_network_admin() && is_multisite() ) {
		//			return;
		//		}

		if ( is_network_admin() ) {
			$active_class = is_plugin_active_for_network( $file ) ? ' active' : '';
		} else {
			$active_class = is_plugin_active( $file ) ? ' active' : '';
		}

		echo '<tr class="plugin-update-tr' . $active_class . '" id="' . esc_attr( $plugin_slug . '-update' ) . '" data-slug="' . esc_attr( $plugin_slug ) . '" data-plugin="' . esc_attr( $file ) . '"><td colspan="2" class="plugin-update colspanchange"><div class="update-message notice inline notice-warning notice-alt"><p>';

		if ( ! current_user_can( 'update_plugins' ) ) {

			_e( 'There is a new version available.', 'better-studio' );

		} else {


			printf( __( 'There is a new version available. <a href="%1$s" %2$s>update now</a>.', 'better-studio' ),
				wp_nonce_url( self_admin_url( 'admin.php?page=' . $page_slug . '&action=upgrade&plugin=' ) . $plugin_slug, 'upgrade-plugin_' . $plugin_slug ),
				sprintf( 'class="update-link" aria-label="%s"',
					/* translators: %s: plugin name */
					esc_attr( sprintf( __( 'Update %s now', 'better-studio' ), $plugin_name ) )
				)
			);
		}

		echo '</p></div></td></tr>';
	}


	public function print_column_headers( $with_id = true ) {

		ob_start();
		parent::print_column_headers( $with_id );
		$html = ob_get_clean();

		echo str_replace(
			"class='manage-column column-name",
			"colspan='2' class='manage-column column-name",
			$html
		);
	}


	protected function get_bulk_actions() {

		return bf_is_product_registered() ? parent::get_bulk_actions() : array();
	}


	protected function is_plugin_premium( $plugin ) {

		return ! empty( $plugin['is_premium'] );
	}


	protected function is_plugin_exclusive( $plugin ) {

		return ! empty( $plugin['is_exclusive'] );
	}


	protected function is_plugin_compatible( $plugin ) {

		return ! empty( $plugin['is_compatible'] );
	}


	public function get_plugins_stat() {

		$all_plugins = bf_get_plugins_config();

		return array(
			'all'        => bf_count( $all_plugins ),
			'active'     => bf_count( array_filter( $all_plugins, array( $this, 'is_plugin_active' ) ) ),
			'premium'    => bf_count( array_filter( $all_plugins, array( $this, 'is_plugin_premium' ) ) ),
			'inactive'   => bf_count( array_filter( $all_plugins, array( $this, 'is_plugin_inactive' ) ) ),
			'exclusive'  => bf_count( array_filter( $all_plugins, array( $this, 'is_plugin_exclusive' ) ) ),
			'compatible' => bf_count( array_filter( $all_plugins, array( $this, 'is_plugin_compatible' ) ) ),
		);
	}


	public function active_status() {

		if ( isset( $_REQUEST['plugin_status'] )
		     && in_array( $_REQUEST['plugin_status'], array(
				'active',
				'premium',
				'inactive',
				'exclusive',
				'compatible'
			) )
		) {

			return $_REQUEST['plugin_status'];
		}

		return 'all';
	}


	public function get_columns() {

		$columns = parent::get_columns();

		if ( ! bf_is_product_registered() ) {
			unset( $columns['cb'] );
		}

		return $columns;
	}


	protected function get_table_classes() {

		$classes = parent::get_table_classes();

		if ( ! bf_is_product_registered() ) {
			$classes[] = 'bf-product-inactive';
		}

		return $classes;
	}
}
libs/better-framework/product-pages/install-plugin/class-bf-product-plugin-installer.php000064400000055130151214002500025636 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * plugin installer/ updater handler
 *
 * Class BF_Product_Plugin_Factory
 */
class BF_Product_Plugin_Installer extends BF_Product_Pages_Base {

	/**
	 * store data while installing plugin. at last save data into an option
	 *
	 * @var array
	 */
	private $process_data;

	/**
	 * installing plugin data, option key
	 *
	 * @var string
	 */
	private $data_option_name;

	/**
	 * store list of plugin file array {
	 *  plugin_directory => plugin_directory/plugin_file.php
	 * }
	 *
	 * @var array
	 */
	static $plugins_file;

	/**
	 * store list of plugins need update array {
	 *  plugin_directory => plugin_directory/plugin_file.php
	 * }
	 *
	 * @var array
	 */
	static $plugins_update;

	/**
	 * temporary data option name pattern
	 *
	 * %s replace with plugin name
	 *
	 * @var string
	 */
	private $option_name_pattern = 'bs_plugin_%s';


	/**
	 * @var array
	 */
	private $messages = array();


	/**
	 * BF_Product_Plugin_Factory constructor.
	 *
	 */
	public function __construct() {

		if ( ! class_exists( 'Plugin_Upgrader' ) ) {

			require_once ABSPATH . '/wp-admin/includes/class-wp-upgrader.php';
		}
	}


	/**
	 * get list of plugins and cache
	 *
	 * @see $plugins_file
	 *
	 * @return array array of plugins on success.
	 */
	public static function get_plugins_basename() {

		if ( ! is_array( self::$plugins_file ) ) {

			self::$plugins_file = array();

			if ( function_exists( 'get_plugins' ) ) { // fix for when there is no any active plugin!
				foreach ( get_plugins() as $file => $info ) {
					self::$plugins_file[ dirname( $file ) ] = $file;
				}
			}
		}

		return self::$plugins_file;
	}


	/**
	 * check a plugin in already installed
	 *
	 * @param string $plugin_directory plugin directory name
	 *
	 * @return bool return true if plugin installed
	 */

	public static function is_plugin_installed( $plugin_directory ) {

		self::get_plugins_basename();

		return ! empty( self::$plugins_file[ $plugin_directory ] );
	}


	/**
	 * Get the plugin file relative path
	 *
	 * @param string $plugin_directory plugin directory name
	 *
	 * @return string
	 */
	public static function the_plugin_file( $plugin_directory ) {

		self::get_plugins_basename();

		if ( isset( self::$plugins_file[ $plugin_directory ] ) ) {

			return self::$plugins_file[ $plugin_directory ];
		}

		return '';
	}


	/**
	 * check a plugin in already activated
	 *
	 * @param string $plugin_directory plugin directory name
	 *
	 * @return bool return true if plugin was activated.
	 */
	public static function is_plugin_active( $plugin_directory ) {

		self::get_plugins_basename();

		return isset( self::$plugins_file[ $plugin_directory ] ) &&
		       is_plugin_active( self::$plugins_file[ $plugin_directory ] );
	}


	/**
	 * check a plugin is deactivated
	 *
	 * @param string $plugin_directory plugin directory name
	 *
	 * @return bool return true if plugin was activated.
	 */
	public static function is_plugin_deactivate( $plugin_directory ) {

		return ! self::is_plugin_active( $plugin_directory );
	}


	/**
	 * get list of plugins need update and cache
	 *
	 * @see \BF_Product_Plugin_Manager::update_plugins
	 */
	private static function get_updates() {

		if ( is_array( self::$plugins_update ) ) {
			return;
		}

		self::$plugins_update = array();
		//
		$updates = get_option( 'bs-product-plugins-status' );

		if ( ! is_object( $updates ) ) {
			return;
		}

		// append remote plugins data
		if ( ! empty( $updates->remote_plugins ) && is_array( $updates->remote_plugins ) ) {

			foreach ( $updates->remote_plugins as $file => $info ) {

				$slug = empty( $info['slug'] ) ? dirname( $file ) : $info['slug'];

				self::$plugins_update[ $slug ] = $file;
			}
		}

		// append local plugins data
		if ( ! empty( $updates->local_plugins ) && is_array( $updates->local_plugins ) ) {

			foreach ( $updates->local_plugins as $file => $info ) {

				$slug = empty( $info['slug'] ) ? dirname( $file ) : $info['slug'];

				self::$plugins_update[ $slug ] = $file;
			}
		}
	}


	/**
	 * TODO: check update for local plugins
	 *
	 * check is plugin in latest version
	 *
	 * @param string $plugin_directory plugin directory name
	 *
	 * @return bool false if update available
	 */
	public static function is_plugin_latest_version( $plugin_directory ) {

		self::get_updates();

		return empty( self::$plugins_update[ $plugin_directory ] );
	}


	/**
	 * Active a plugin
	 *
	 * @param string $plugin_directory plugin folder name
	 *
	 * @return bool true on success.
	 * @throws BF_Exception
	 */
	public static function active_plugin( $plugin_directory ) {

		if ( ! function_exists( 'activate_plugin' ) ) {

			require_once ABSPATH . '/wp-admin/includes/plugin.php';
		}

		$plugin_directory = trim( $plugin_directory, '/' . DIRECTORY_SEPARATOR );

		if ( $plugin_data = get_plugins( '/' . $plugin_directory ) ) {

			wp_cache_delete( 'plugins', 'plugins' ); // FIX: 'The plugin does not have a valid header' error

			$plugin_file = trailingslashit( $plugin_directory ) . key( $plugin_data );
			$activated   = activate_plugin( $plugin_file, false, false );
			self::throw_if_is_wp_error( $activated, $plugin_file );

			return true;
		}

		return false;
	}


	/**
	 * Flush cache
	 */
	public static function flush_cache() {

		self::$plugins_file = null;
	}


	/**
	 * deactivate a plugin
	 *
	 * @param string $plugin_directory plugin directory name
	 *
	 * @return bool true on success.
	 */
	public function deactivate_plugin( $plugin_directory ) {

		if ( ! function_exists( 'activate_plugin' ) ) {

			require_once ABSPATH . '/wp-admin/includes/plugin.php';
		}

		$plugin_directory = trim( $plugin_directory, '/' . DIRECTORY_SEPARATOR );

		if ( $plugin_data = get_plugins( '/' . $plugin_directory ) ) {

			deactivate_plugins( trailingslashit( $plugin_directory ) . key( $plugin_data ), false, false );

			/**
			 * Deactivate plugin in multisite if plugin was network activated
			 */
			if ( is_multisite() ) {
				deactivate_plugins( trailingslashit( $plugin_directory ) . key( $plugin_data ), false, true );
			}

			return true;
		}

		return false;
	}


	/**
	 * Fetch bundled plugin download link
	 *
	 * @param string $plugin_slug
	 * @param string $action
	 * @param bool   $mirror
	 *
	 * @return bool|string|\WP_Error url string on success bool|WP_Error otherwise
	 */
	public function get_bundled_plugin_download_link( $plugin_slug, $action = '', $mirror = false ) {

		$plugin_data = $this->api_request( 'download-plugin', compact( 'plugin_slug', 'action', 'mirror' ) );

		if ( is_wp_error( $plugin_data ) ) {
			return $plugin_data;
		}

		if ( ! empty( $plugin_data->success ) && ! empty( $plugin_data->download_link ) ) {
			return $plugin_data->download_link;
		}

		return false;
	}


	public function install_finished() {

		//delete temporary option data
		delete_option( $this->data_option_name );

		//delete downloaded package file
		if ( ! empty( $this->process_data['downloaded_package_path'] ) ) {

			@unlink( $this->process_data['downloaded_package_path'] );
		}

		/**
		 * update update cache status for to prevent display update message after updated plugin!
		 *
		 * @see \BF_Product_Plugin_Manager::update_plugins
		 */
		if ( isset( $this->process_data['slug'] ) ) {

			$prev_status = get_option( 'bs-product-plugins-status' );
			if ( is_object( $prev_status ) ) {
				$slug = &$this->process_data['slug'];

				if ( $this->process_data['is_remote'] ) {
					$plugins_list = &$prev_status->remote_plugins;

				} else {
					$plugins_list = &$prev_status->local_plugins;
				}

				$need_update = false;
				if ( $plugins_list && is_array( $plugins_list ) ) {

					foreach ( $plugins_list as $plugin_basename => $new_plugin_data ) {

						//remove plugin from update list
						if ( $slug === $new_plugin_data['slug'] ) {

							//check version again to make sure plugin was updated successfully
							if ( isset( $new_plugin_data['new_version'] ) ) {

								$plugin_file = trailingslashit( WP_PLUGIN_DIR ) . $plugin_basename;
								$plugin_data = get_plugin_data( $plugin_file );

								if ( isset( $plugin_data['Version'] ) &&
								     $plugin_data['Version'] === $new_plugin_data['new_version']
								) {
									unset( $plugins_list[ $plugin_basename ] );
									$need_update = true;
								}
							}

							break;
						}
					}
				}

				if ( $need_update ) {
					update_option( 'bs-product-plugins-status', $prev_status, 'no' );
				}
			}
		}

		do_action( 'better-framework/product-pages/install-plugin/install-finished', $this->process_data );
	}


	/**
	 * delete temporary data generated while installing plugin
	 *
	 * @param string $plugin_slug
	 *
	 * @return boll always true
	 */
	public function rollback( $plugin_slug ) {

		$data_option_name = sprintf( $this->option_name_pattern, $plugin_slug );
		$process_data     = get_option( $data_option_name, array() );


		//delete downloaded package file
		if ( ! empty( $process_data['downloaded_package_path'] ) ) {

			@unlink( $process_data['downloaded_package_path'] );
		}

		//delete extracted files & folders
		if ( ! empty( $process_data['unpacked_path'] ) ) {
			bf_file_system_instance()->rmdir( $process_data['unpacked_path'], true );
		}

		//delete temporary option data
		delete_option( $data_option_name );

		return true;
	}


	function __destruct() {

		if ( ! headers_sent() ) {
			// prevent redirect page
			if ( function_exists( 'header_remove' ) ) {
				header_remove( 'Location' );
			}
			status_header( 200 );
		}
	}


	/**
	 * Get plugin upgrader/ installer object instance.
	 *
	 * @param bool   $is_upgrade
	 * @param array  $args
	 * @param string $plugin_slug
	 *
	 * @return Plugin_Upgrader
	 */
	protected function get_upgrader_instance( $plugin_slug, $args = array(), $is_upgrade = false ) {

		$prefix = $is_upgrade ? 'upgrade' : 'install';

		$skin_args = array(
			'type'       => 'web',
			'url'        => esc_url_raw( add_query_arg(
				array(
					'action' => "$prefix-plugin",
					'plugin' => urlencode( $plugin_slug ),
				),
				'update.php'
			) ),
			'nonce'      => "$prefix-plugin_$plugin_slug", // check  admin referrer
			'plugin'     => '',
			'extra'      => array(),
			'is_upgrade' => $is_upgrade,
		);

		$skin_args = array_merge( $skin_args, $args );


		if ( $is_upgrade ) {

			$skin = new Plugin_Upgrader_Skin( $skin_args );
		} else {

			$skin = new BF_Plugin_Install_Skin( $skin_args );
		}

		return new Plugin_Upgrader( $skin );
	}


	/**
	 * Download & install remote path plugins
	 *
	 * @param array $plugins_slug plugins slug list
	 * @param bool  $upgrade      upgrade or install
	 *
	 * @throws BF_Exception
	 */
	public function download_plugins( $plugins_slug, $upgrade = false ) {

		if ( empty( $plugins_slug ) ) {
			return;
		}

		if ( ! function_exists( 'plugins_api' ) ) {
			require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
		}

		if ( ! class_exists( 'Plugin_Upgrader' ) ) {
			require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
		}

		if ( ! class_exists( 'BF_Plugin_Install_Skin' ) ) {
			require BF_Product_Pages::get_path( 'install-plugin/class-bf-plugin-install-skin.php' );
		}

		if ( ! class_exists( 'BF_Plugin_Bulk_Install_Skin' ) ) {
			require BF_Product_Pages::get_path( 'install-plugin/class-bf-plugin-bulk-install-skin.php' );
		}

		if ( $upgrade ) {

			$this->bulk_upgrade( $plugins_slug );

		} else {

			$this->bulk_install( $plugins_slug );
		}
	}


	protected function bulk_install( $plugins_slug ) {

		$plugins = array_intersect_key( // Filter valid plugins
			bf_get_plugins_config(),
			array_flip( (array) $plugins_slug )
		);

		end( $plugins );
		$last_plugin = key( $plugins );

		add_filter( 'upgrader_post_install', array( $this, 'active_after_install' ), 999, 3 );

		foreach ( $plugins as $slug => $plugin ) {

			$return_link = $last_plugin === $slug;
			$upgrader    = $this->get_upgrader_instance( $slug, compact( 'return_link' ) );
			$installed   = $upgrader->install(
				$this->get_plugin_package_url( $plugin )
			);
		}
	}


	/**
	 * Active plugin immediately after installed
	 *
	 * @hooked upgrader_post_install
	 *
	 * @param bool|WP_Error $response   Installation response.
	 * @param array         $hook_extra Extra arguments passed to hooked filters.
	 * @param array         $result     Installation result data.
	 *
	 * @return bool|WP_Error
	 */
	public function active_after_install( $response, $hook_extra, $result ) {

		if ( ! $response || is_wp_error( $response ) ) {
			return $response;
		}

		try {

			$this->active_plugin( plugin_basename( $result['destination'] ) );

		} catch( BF_Exception $e ) {

			$response = new WP_Error( $e->getCode(), $e->getMessage() );
		}

		return $response;
	}


	/**
	 * Upgrade plugins
	 *
	 * @param $plugins_slug
	 *
	 * @return bool
	 */
	protected function bulk_upgrade( $plugins_slug ) {

		if ( ! $bf_states = get_option( 'bs-product-plugins-status' ) ) {

			return false;
		}

		$current  = get_site_transient( 'update_plugins' );
		$skin     = new BF_Plugin_Bulk_Install_Skin();
		$upgrader = new Plugin_Upgrader( $skin );
		$plugins  = array_intersect_key( // Filter valid plugins
			bf_get_plugins_config(),
			array_flip( (array) $plugins_slug )
		);


		$plugins_slug = array();

		foreach ( $plugins as $slug => $plugin ) {

			if ( ! $this->is_plugin_active( $slug ) ) {
				continue;
			}

			$plugin_file = $this->the_plugin_file( $slug );

			if ( ! empty( $plugin['local_path'] ) ) { # local plugin

				$current->response[ $plugin_file ] = (object) array(

					'id'          => $plugin['slug'],
					'slug'        => $plugin['slug'],
					'plugin'      => $plugin_file,
					'package'     => $this->get_plugin_package_url( $plugin ),
					'new_version' => $plugin['version'],
				);

			} else { # Plugin with remote source


				if ( ! isset( $bf_states->remote_plugins[ $plugin_file ] ) ) {
					continue;
				}

				$plugin_info = $bf_states->remote_plugins[ $plugin_file ];

				$current->response[ $plugin_file ] = (object) array(

					'id'          => $plugin_info['id'],
					'slug'        => $plugin_info['id'],
					'plugin'      => $plugin_file,
					'package'     => $this->get_plugin_package_url( $plugin ),
					'new_version' => $plugin_info['new_version'],
				);
			}

			//
			$plugins_slug[] = $plugin_file;
		}

		bf_update_plugin_schedule_status( 'disable' );

		set_site_transient( 'update_plugins', $current );

		if ( $upgraded = $upgrader->bulk_upgrade( $plugins_slug ) ) {

			$status = get_option( 'bs-product-plugins-status' );

			foreach ( $upgraded as $plugin_file ) {

				$plugin_rel_path = $plugin_file['destination_name'];
				$plugin_rel_path .= '/' . $plugin_file['source_files'][0];

				unset( $status->remote_plugins[ $plugin_rel_path ] );
			}


			update_option( 'bs-product-plugins-status', $status );
		}
	}


	/**
	 * Get requested action
	 *
	 * @return string
	 */
	protected function current_action() {

		$action = '';

		if ( isset( $_REQUEST['action'] ) && '-1' !== $_REQUEST['action'] ) {

			$action = $_REQUEST['action'];

		} elseif ( ! empty( $_REQUEST['action2'] ) ) {

			$action = $_REQUEST['action2'];
		}

		return $action;
	}


	/**
	 * Handle Plugin Table Single/Bulk Actions
	 *
	 * @return string handled action
	 * @throws BF_Exception
	 */
	public function handle_early_action() {

		$handled_action = '';

		switch ( $this->current_action() ) {

			case 'activate-selected':

				check_admin_referer( 'bulk-plugins' );

				$download_and_active = array();
				$active_only         = array();

				foreach ( $_REQUEST['checked'] as $slug ) {

					if ( $this->the_plugin_file( $slug ) ) {

						$active_only[] = $slug;

					} else {

						$download_and_active[] = $slug;
					}
				}

				if ( empty( $download_and_active ) && $active_only ) {

					$this->download_plugins( $download_and_active, false );

					$handled_action = 'activate';
					$plugins_file   = array_map( array( $this, 'the_plugin_file' ), $active_only );

					activate_plugins( $plugins_file );
				}

				break;

			case 'deactivate':

				check_admin_referer( 'deactivate-plugin_' . $_REQUEST['plugin'] );

				deactivate_plugins( $this->the_plugin_file( $_REQUEST['plugin'] ) );

				$handled_action = 'deactivate';

				break;

			case 'activate':

				check_admin_referer( 'activate-plugin_' . $_REQUEST['plugin'] );

				$active = activate_plugin( $this->the_plugin_file( $_REQUEST['plugin'] ) );

				if ( ! is_wp_error( $active ) && ! $active ) {
					$handled_action = 'activate';
				}

				break;

			case 'deactivate-selected':

				check_admin_referer( 'bulk-plugins' );

				$plugins = array();

				if ( ! empty( $_REQUEST['checked'] ) ) {

					$plugins = $_REQUEST['checked'];

				} elseif ( ! empty( $_REQUEST['plugin'] ) ) {

					$plugins = array( $_REQUEST['plugin'] );
				}

				$handled_action = 'deactivate';
				$plugins_file   = array_map( array( $this, 'the_plugin_file' ), $plugins );

				deactivate_plugins( $plugins_file );

				break;

			case 'delete':
			case 'delete-selected':

				if ( $this->current_action() === 'delete' ) {

					check_admin_referer( 'delete-plugin_' . $_REQUEST['plugin'] );

					$plugins = (array) $_REQUEST['plugin'];

				} else {

					check_admin_referer( 'bulk-plugins' );

					$plugins = $_REQUEST['checked'];
				}

				$plugins = array_filter( $plugins, array( $this, 'is_plugin_installed' ) );
				$plugins = array_filter( $plugins, array( $this, 'is_plugin_deactivate' ) );

				if ( empty( $plugins ) ) {
					return;
				}

				if ( empty( $_REQUEST['verify-delete'] ) ) {

					$this->ask_verify_delete( $plugins );

					$handled_action = 'delete-confirm';

				} else {

					if ( delete_plugins( array_map( array( $this, 'the_plugin_file' ), $plugins ) ) ) {

						if ( bf_count( $plugins ) === 1 ) {

							$handled_action = 'delete';

						} else {

							$handled_action = 'delete-multi';
						}
					}
				}

				break;
		}

		return $handled_action;
	}


	/**
	 * Handle Plugin Table Single/Bulk Actions
	 *
	 * @return string handled action
	 * @throws BF_Exception
	 */
	public function handle_action() {

		$handled_action = '';

		switch ( $this->current_action() ) {

			case 'install':

				// Download, install and activate single plugin

				check_admin_referer( 'install-plugin_' . $_REQUEST['plugin'] );

				$this->download_plugins( $_REQUEST['plugin'] );

				$handled_action = 'install';

				break;


			case 'activate-selected':

				check_admin_referer( 'bulk-plugins' );

				$download_and_active = array();
				$active_only         = array();

				foreach ( $_REQUEST['checked'] as $slug ) {

					if ( $this->the_plugin_file( $slug ) ) {

						$active_only[] = $slug;

					} else {

						$download_and_active[] = $slug;
					}
				}

				if ( $download_and_active ) {

					$this->download_plugins( $download_and_active, false );

					$handled_action   = 'install';
					$this->messages[] = __( 'Selected plugins <strong>activated</strong>.', 'better-studio' );
				}

				break;

			case 'update-selected':

				check_admin_referer( 'bulk-plugins' );

				$this->download_plugins( $_REQUEST['checked'], true );

				$handled_action = 'upgrade';

				break;


			case 'upgrade':

				check_admin_referer( 'upgrade-plugin_' . $_REQUEST['plugin'] );

				$this->download_plugins( $_REQUEST['plugin'], true );

				$handled_action = 'upgrade';

				break;

		}

		return $handled_action;
	}


	public function defined_message( $id ) {

		$messages = array(
			'deactivate'   => __( 'Plugin <strong>deactivated</strong>.', 'better-studio' ),
			'activate'     => __( 'Selected plugins <strong>activated</strong>.', 'better-studio' ),
			'delete'       => __( 'The selected plugin has been <strong>deleted</strong>.', 'better-studio' ),
			'delete-multi' => __( 'The selected plugins have been < strong>deleted </strong >.', 'better-studio' ),
		);

		if ( isset( $messages[ $id ] ) ) {
			return $messages[ $id ];
		}
	}


	/**
	 * Get admin messages list
	 *
	 * @return array
	 */
	public function get_messages() {

		return $this->messages;
	}


	/**
	 * Get plugin download url
	 *
	 * @param array $plugin plugin info array
	 *
	 * @return string
	 */
	protected function get_plugin_package_url( $plugin ) {

		if ( empty( $plugin['slug'] ) ) {
			return '';
		}

		$plugin_type = isset( $plugin['type'] ) ? $plugin['type'] : 'bundled';

		if ( 'global' === $plugin_type ) {

			$api = plugins_api( 'plugin_information', array(
				'slug'   => $plugin['slug'],
				'fields' => array( 'sections' => false )
			) );

			if ( isset( $api->download_link ) ) {
				$source = $api->download_link;
			}

		} elseif ( 'local' === $plugin_type ) {

			$source = isset( $plugin['local_path'] ) ? $plugin['local_path'] : '';

		} else {

			$source = bf_bundle_plugin_package_url( $plugin['slug'] );
		}

		return $source;
	}


	protected function ask_verify_delete( $plugins ) {

		$plugins = array_intersect_key( // Filter valid plugins
			bf_get_plugins_config(),
			array_flip( (array) $plugins )
		);

		_e( 'Are you sure you wish to delete these files ? ', 'better-studio' );

		?>
		<ul class="ul-disc">
			<?php
			foreach ( $plugins as $plugin ) {

				if ( is_uninstallable_plugin( $this->the_plugin_file( $plugin['slug'] ) ) ) {
					/* translators: 1: plugin name, 2: plugin author */
					echo ' < li>', sprintf( __( ' % 1$s by % 2$s ( will also <strong>delete its data </strong >)', 'better-studio' ), ' <strong>' . $plugin['name'] . ' </strong > ', '<em > ' . $plugin['author'] . ' </em > ' ), '</li> ';
				} else {
					/* translators: 1: plugin name, 2: plugin author */
					echo '<li > ', sprintf( _x( ' % 1$s by % 2$s', 'plugin', 'better-studio' ), ' <strong>' . $plugin['name'] . ' </strong > ', '<em > ' . $plugin['author'] ) . ' </em > ', '</li > ';
				}
			}
			?>
		</ul>
		<form method="post" action="<?php echo esc_url( $_SERVER['REQUEST_URI'] ); ?>" style="display:inline;">
			<input type="hidden" name="verify-delete" value="1"/>
			<input type="hidden" name="action" value="delete-selected"/>
			<?php

			foreach ( (array) $plugins as $slug => $plugin ) {
				echo ' < input type = "hidden" name = "checked[]" value = "' . esc_attr( $slug ) . '" />';
			}

			wp_nonce_field( 'bulk-plugins' );

			submit_button( __( 'Yes, delete these files', 'better-studio' ), '', 'submit', false ); ?>
		</form>
		<?php

	}
}libs/better-framework/product-pages/install-plugin/class-bf-product-plugin-manager.php000064400000024016151214002500025252 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! class_exists( 'BF_Product_Multi_Step_Item' ) ) {
	require_once BF_PRODUCT_PAGES_PATH . 'init.php';
}


/**
 * Class BS_Product_Plugins
 */
class BF_Product_Plugin_Manager extends BF_Product_Multi_Step_Item {

	public $handled_action;

	public $id = 'install-plugin';

	public $check_update_duration;

	/**
	 * Store custom messages
	 *
	 * @var array
	 */
	public $messages = array();

	/**
	 * @var BF_Product_Plugin_Installer
	 */
	protected $installer;


	/**
	 * BF_Product_Plugin_Manager constructor.
	 */
	public function __construct() {

		if ( ! class_exists( 'BF_Product_Plugin_Installer' ) ) {
			require_once BF_Product_Pages::get_path( 'install-plugin/class-bf-product-plugin-installer.php' );
		}

		$this->messages  = array();
		$this->installer = new BF_Product_Plugin_Installer();

		parent::__construct();

		$this->check_update_duration = MINUTE_IN_SECONDS * 15; //check plugin update every 15 minutes;
		//
		$this->handle_early_actions();
	}


	protected function before_render() {

		$this->handled_action = $this->handle_actions();

		$this->update_plugins();

		$this->display_messages();
	}


	/**
	 *
	 */
	protected function handle_early_actions() {

		// Important: WP plugins list table deactivation bug fix.
		if ( ! bf_is_product_page( 'install-plugin' ) ) {

			return;
		}

		if ( $action = $this->installer->handle_early_action() ) {

			$url = remove_query_arg( array( 'action', '_wpnonce', 'plugin' ), $_SERVER['REQUEST_URI'] );
			$url = add_query_arg( 'msg', $action, $url );

			wp_redirect( $url );

			die( "#" );
		}

		if ( isset( $_GET['msg'] ) ) {

			if ( $message = $this->installer->defined_message( $_GET['msg'] ) ) {

				$this->messages[] = $message;
			}
		}
	}


	protected function handle_actions() {

		$handled = $this->installer->handle_action();

		if ( $messages = $this->installer->get_messages() ) {
			$this->messages = array_merge( $messages, $this->messages );
		}

		return $handled;
	}


	/**
	 * Check plugins for update
	 *
	 * @uses $wp_version Used to notify the WordPress version.
	 *
	 * @param bool $force Whether to force check plugins for update. Defaults to false.
	 *
	 * @return stdClass|bool false on failure.
	 */
	public function update_plugins( $force = false ) {

		global $wp_version, $pagenow;

		include ABSPATH . WPINC . '/version.php';

		// Don't check update while updating another item!

		if (
			( isset( $_REQUEST['action'] ) && 'do-theme-upgrade' === $_REQUEST['action'] )
			||
			( bf_is_product_page( 'install-plugin' ) && ! empty( $_REQUEST['action'] ) )
			||
			(
				isset( $_REQUEST['action'] ) &&
				in_array( $pagenow, array( 'admin-ajax.php', 'update.php' ) ) &&
				in_array( $_REQUEST['action'], array(
					'upgrade-theme',
					'update-selected-themes',
					'update-theme',
				) )
			)
		) {
			return false;
		}

		$plugins_basename = BF_Product_Plugin_Installer::get_plugins_basename();
		$all_plugins_data = get_plugins();
		$remote_plugins   = array();
		$active_plugins   = array();

		$update_status                 = new stdClass();
		$update_status->last_checked   = time();
		$update_status->no_update      = array();
		$update_status->remote_plugins = array(); // wordpress repo plugins need update
		$update_status->translations   = array();
		$update_status->local_plugins  = array(); // list of local plugins need update

		if ( ! $force ) {

			$prev_status = get_option( 'bs-product-plugins-status' );

			if ( ! is_object( $prev_status ) ) {
				$prev_status               = new stdClass();
				$prev_status->last_checked = time();
				$skip_update               = false;
			} else {
				$skip_update = $this->check_update_duration > ( time() - $prev_status->last_checked );
			}

			if ( $skip_update ) {

				return $prev_status;
			}
		}

		$bundled_plugins      = array();
		$bundled_plugins_data = array();
		if ( $plugins_data = $this->get_plugins_data() ) {
			foreach ( $plugins_data as $ID => $plugin_data ) {
				if ( empty( $plugin_data['slug'] ) ) {
					continue;
				}

				/**
				 * skip process if plugin was not installed!
				 */
				$slug = &$plugin_data['slug'];
				if ( ! isset( $plugins_basename[ $slug ] ) ) {
					continue;
				}
				$plugin_basename = &$plugins_basename[ $slug ];
				/**
				 * get plugin basename path EX: pluginDirectory/pluginFile.php
				 *
				 * @see plugin_basename
				 * @var string $plugin_basename
				 */
				if ( ! isset( $all_plugins_data[ $plugin_basename ] ) ) {
					continue;
				}
				// End plugin installation check block

				$active_plugins[] = $plugin_basename;
				$data             = &$all_plugins_data[ $plugin_basename ];
				$is_local_plugin  = ! empty( $plugin_data['local_path'] );

				if ( $is_local_plugin ) {
					//compare local plugin version with installed plugin
					if (
						isset( $data['Version'] ) && isset( $plugin_data['version'] )
						&& version_compare( $plugin_data['version'], $data['Version'], '>' )
					) {

						$update_status->local_plugins[ $plugin_basename ] = array(
							'id'          => $ID,
							'slug'        => $slug,
							'new_version' => $plugin_data['version']
						);
					}

				} elseif ( isset( $plugin_data['type'] ) && $plugin_data['type'] === 'bundled' ) {
					// bundled plugin

					$bundled_plugins[ $slug ]      = $data['Version'];
					$bundled_plugins_data[ $slug ] = compact( 'plugin_basename', 'ID' );
				} else {
					//wordpress repository plugin
					$remote_plugins[ $plugin_basename ] = $data;
				}
			}
		}

		/**
		 * check wp repo plugins update
		 */

		// Three seconds, plus one extra second for every 10 plugins
		$timeout      = 3 + (int) ( bf_count( $plugins_basename ) / 10 );
		$to_send      = array(
			'plugins' => $remote_plugins,
			'active'  => $active_plugins
		);
		$translations = wp_get_installed_translations( 'plugins' );
		$locales      = array( get_locale() );
		/**
		 * Filter the locales requested for plugin translations.
		 *
		 * @see wp_update_plugins
		 *
		 * @param array $locales Plugin locale. Default is current locale of the site.
		 */
		$locales = apply_filters( 'plugins_update_check_locales', $locales );


		$options = array(
			'timeout'    => $timeout,
			'body'       => array(
				'plugins'      => wp_json_encode( $to_send ),
				'translations' => wp_json_encode( $translations ),
				'locale'       => wp_json_encode( $locales ),
				'all'          => wp_json_encode( true ),
			),
			'user-agent' => 'WordPress/' . $wp_version . '; ' . esc_url( home_url( '/' ) )
		);
		$api_url = 'http://api.wordpress.org/plugins/update-check/1.1/';

		$raw_response = wp_remote_post( $api_url, $options );
		if ( ! is_wp_error( $raw_response ) && 200 == wp_remote_retrieve_response_code( $raw_response ) ) {

			$response = json_decode( wp_remote_retrieve_body( $raw_response ), true );

			if ( is_array( $response ) ) {
				$update_status->remote_plugins = $response['plugins']; //list of plugins need update
				$update_status->translations   = $response['translations'];
				$update_status->no_update      = $response['no_update'];
			}
		}

		/**
		 * check bundled plugins update
		 */

		if ( $bundled_plugins ) {

			$check_update = $this->api_request( 'check-plugin-update', array( 'plugins_list' => $bundled_plugins ) );
			if ( ! is_wp_error( $check_update ) && ! empty( $check_update->success ) && ! empty( $check_update->plugins ) ) {
				foreach ( $check_update->plugins as $slug => $version ) {
					if ( $version !== 'latest' ) {
						$plugin_basename                                   = $bundled_plugins_data[ $slug ]['plugin_basename'];
						$update_status->remote_plugins[ $plugin_basename ] = array(
							'id'          => $bundled_plugins_data[ $slug ]['ID'],
							'slug'        => $slug,
							'new_version' => $version
						);
					}
				}
			}
		}

		if ( isset( $response ) ) {
			do_action( 'better-framework/product-pages/plugin-update-check', $update_status, $response );
		}

		update_option( 'bs-product-plugins-status', $update_status, 'no' );

		return $update_status;
	}


	/**
	 * get list of plugins
	 *
	 * @return array
	 * @see \BF_Product_Plugin_Factory::install_start $plugin_data param
	 */
	public function get_plugins_data() {

		return bf_get_plugins_config();
	}


	/**
	 * @param $options
	 */
	public function render_content( $options ) {

		global $status, $page;

		if ( $this->handled_action ) {

			if ( 'deactivate' !== $this->handled_action &&
			     'activate' !== $this->handled_action &&
			     'delete' !== $this->handled_action
			) {
				return;
			}
		}

		$list_table = $this->list_table();

		bf_product_view( 'install-plugin/templates/main-page', compact( 'list_table', 'status', 'page' ) );
	}


	/**
	 * Get an instance of the plugins list table class
	 *
	 * @return BF_Product_Plugin_List_Table
	 */
	protected function list_table() {

		if ( ! class_exists( 'BF_Product_Plugin_List_Table' ) ) {

			require BF_Product_Pages::get_path( 'install-plugin/class-bf-product-plugin-list-table.php' );
		}

		return new BF_Product_Plugin_List_Table( array( 'screen' => __CLASS__ ) );
	}


	/**
	 *
	 */
	public function display_messages() {

		if ( empty( $this->messages ) ) {
			return;
		}

		?>
		<div id="message" class="updated notice is-dismissible">
			<?php
			foreach ( $this->messages as $message ) {

				printf( '<p>%s%s</p>', $message, "\n" );
			}
			?>
			<button type="button" class="notice-dismiss">
				<span class="screen-reader-text">Dismiss this notice.</span>
			</button>
		</div>
		<?php
	}

}libs/better-framework/product-pages/install-plugin/class-bf-plugin-install-skin.php000064400000001263151214002510024572 0ustar00<?php

if ( ! class_exists( 'Plugin_Installer_Skin' ) ) {

	require ABSPATH . '/wp-admin/includes/class-wp-upgrader-skins.php';
}


class BF_Plugin_Install_Skin extends Plugin_Installer_Skin {


	public function __construct( $args = array() ) {

		$args['url'] = add_query_arg( $_GET );

		parent::__construct( $args );
	}


	public function after() {

		if ( ! empty( $this->options['return_link'] ) ) {

			$install_actions['plugins_page'] = '<a href="admin.php?page=' . esc_attr( $_REQUEST['page'] ) . '">' . __( 'Return to Plugin Installer', 'better-studio' ) . '</a>';
		}

		if ( ! empty( $install_actions ) ) {
			$this->feedback( implode( ' ', (array) $install_actions ) );
		}
	}
}
libs/better-framework/product-pages/install-plugin/functions.php000064400000044336151214002510021216 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * enqueue static files.
 */

add_action( 'admin_enqueue_scripts', 'bf_install_plugins_enqueue_scripts' );

if ( ! function_exists( 'bf_install_plugins_enqueue_scripts' ) ) {

	/**
	 * Enqueue plugin page styles & scripts
	 *
	 * @hooked admin_enqueue_scripts
	 */
	function bf_install_plugins_enqueue_scripts() {

		if ( ! bf_is_product_page( 'install-plugin' ) ) {
			return;
		}

		bf_enqueue_script( 'bf-modal' );
		bf_enqueue_style( 'bf-modal' );

		$ver = BF_Product_Pages::Run()->get_version();

		wp_enqueue_style(
			'bs-product-plugin-styles',
			BF_Product_Pages::get_url( 'install-plugin/assets/css/bs-plugin-install.css' ),
			array(),
			$ver
		);

		wp_enqueue_script(
			'bs-product-plugin-scripts',
			BF_Product_Pages::get_url( 'install-plugin/assets/js/bs-plugin-install.js' ),
			array(),
			$ver
		);

		wp_localize_script( 'bs-product-plugin-scripts', 'bs_plugin_install_loc', array(
			'search_failed' => __( 'No plugins found for %s', 'better-studio' ),
			'item_count'    => __( '%s item', 'better-studio' ),
			'items_count'   => __( '%s item', 'better-studio' ),


			'delete_confirm' => array(
				'icon'       => 'fa-trash',
				'header'     => __( 'Delete Selected Plugin(s)', 'better-studio' ),
				'title'      => '',
				'body'       => __( 'Are you sure you want to delete the selected plugins and their data? %list%', 'better-studio' ),
				'button_yes' => __( 'Yes, Delete', 'better-studio' ),
				'button_no'  => __( 'No', 'better-studio' ),
			),
			'confirm_delete' => __( '', 'better-studio' ),
			'menu_slug'      => BF_PRODUCT_PAGES_MAIN_MENU
		) );
	}
}


if ( ! function_exists( 'bf_get_plugins_config' ) ) {

	/**
	 * get plugins config array
	 *
	 * @return array  {
	 *
	 *  Plugin_ID => array {
	 *
	 * @type string  $name        plugin name
	 * @type string  $slug        plugin slug( plugin directory )
	 * @type boolean $required    is plugin required?
	 * @type string  $version     plugin version number
	 * @type string  $description plugin description
	 * @type string  $thumbnail   plugin image  URI
	 * @type string  $local_path  path to zip file if plugin not exists in wordpress.org plugin repository
	 *
	 * }
	 *
	 * ...
	 * }
	 */
	function bf_get_plugins_config() {

		$result = array();


		foreach ( bf_plugins_config_array() as $id => $plugin ) {

			if ( ! isset( $plugin['type'] ) ) {
				$plugin['type'] = empty( $plugin['local_path'] ) ? 'global' : 'local';
			}

			$result[ $id ] = $plugin;
		}

		return $result;
	}
}

if ( ! function_exists( 'bf_plugins_config_array' ) ) {

	/**
	 * Retrieve plugins configuration array.
	 *
	 * @since 3.9.0
	 * @return array
	 */
	function bf_plugins_config_array() {

		list( $data, $is_expired ) = bf_get_transient( 'bf-plugins-config', array() );

		if ( ! $is_expired ) {

			return $data;
		}

		if ( $config = bf_plugins_config_fetch() ) {

			$data = $config;
		}

		bf_set_transient( 'bf-plugins-config', $data, 60 * 60 * 5 /* 5 Hour */ );

		return $data;
	}
}


if ( ! function_exists( 'bf_plugins_config_fetch' ) ) {

	/**
	 * Fetch list of bundled products from server.
	 *
	 * @since 3.9.0
	 * @return array
	 */
	function bf_plugins_config_fetch() {

		$results = BetterFramework_Oculus::request( 'bundled-products-list', array( 'json_assoc' => true ) );

		if ( is_wp_error( $results ) ) {
			return array();
		}

		return ! empty( $results['bundled_products'] ) ? $results['bundled_products'] : array();
	}
}

add_action( 'in_admin_header', 'bf_required_plugin_notice', 17 );

if ( ! function_exists( 'bf_required_plugin_notice' ) ) {

	/**
	 * Display notice if required plugins was not installed
	 *
	 * @hooked in_admin_header
	 */
	function bf_required_plugin_notice() {

		if ( ! $plugins = bf_get_plugins_config() ) {
			return;
		}

		$add_notice            = false;
		$last_required_plugins = get_option( 'bs-require-plugin-install' );
		$required_plugins      = array();

		if ( ! class_exists( 'BS_Product_Plugin_Factor' ) ) {
			require_once BF_Product_Pages::get_path( 'install-plugin/class-bf-product-plugin-installer.php' );
		}

		foreach ( $plugins as $plugin_ID => $plugin ) {

			if ( ! empty( $plugin['required'] ) && $plugin['required'] ) {

				if ( ! BF_Product_Plugin_Installer::is_plugin_installed( $plugin_ID )
				     ||
				     ! BF_Product_Plugin_Installer::is_plugin_active( $plugin_ID )
				) {
					$required_plugins[] = $plugin['name'];
				}
			}
		}

		if ( $last_required_plugins === false ) {
			$add_notice = true;
		} else {
			sort( $required_plugins );
			if ( $required_plugins != $last_required_plugins ) {
				$add_notice = true;
			}
		}

		if ( ! $add_notice ) {
			return;
		}

		if ( empty( $required_plugins ) ) {
			delete_option( 'bs-require-plugin-install' );
			Better_Framework::admin_notices()->remove_notice( 'bs-product-required-plugins' );

		} else {

			update_option( 'bs-require-plugin-install', $required_plugins );

			$link = admin_url( 'admin.php?page=' . BF_Product_Pages::$menu_slug . '-install-plugin' );

			if ( bf_count( $required_plugins ) > 1 ) {

				if ( bf_count( $required_plugins ) === 2 ) {
					$msg = wp_kses( sprintf(
						__( 'The <strong>%s</strong> and <strong>%s</strong> plugins are required for %s to work properly. Install and activate them from <a href="%s">Plugin Installer</a>.', 'better-studio' ),
						isset( $required_plugins['0'] ) ? $required_plugins['0'] : '',
						isset( $required_plugins['1'] ) ? $required_plugins['1'] : '',
						BF_Product_Pages::get_product_info( 'product_name', '' ),
						$link
					), bf_trans_allowed_html() );
				} else {
					$msg = wp_kses( sprintf( __( 'Some required plugins was not installed currently. Install and activate them from <a href="%s">Plugin Installer</a>.', 'better-studio' ), $link ), bf_trans_allowed_html() );
				}

			} else {
				$msg = wp_kses( sprintf(
					__( 'The <strong>%s</strong> plugin is required for %s to work properly. Install and activate it from <a href="%s">Plugin Installer</a>.', 'better-studio' ),
					isset( $required_plugins['0'] ) ? $required_plugins['0'] : '',
					BF_Product_Pages::get_product_info( 'product_name', '' ),
					$link
				), bf_trans_allowed_html() );
			}

			Better_Framework::admin_notices()->add_notice( array(
				'msg'       => $msg,
				'id'        => 'bs-product-required-plugins',
				'type'      => 'fixed',
				'state'     => 'danger',
				'thumbnail' => BF_Product_Pages::get_product_info( 'notice-icon', '' ),
			) );
		}
	}
}

add_filter( 'pre_set_site_transient_update_plugins', 'bf_update_plugin_schedule', 9999 );


if ( ! function_exists( 'bf_update_plugin_schedule' ) ) {

	/**
	 * @hooked pre_set_site_transient_update_plugins
	 *
	 * @param mixed $value
	 *
	 * @return mixed
	 */
	function bf_update_plugin_schedule( $value ) {

		if ( ! class_exists( 'BF_Product_Plugin_Installer' ) ) {
			require_once BF_Product_Pages::get_path( 'install-plugin/class-bf-product-plugin-installer.php' );
		}

		if ( ! class_exists( 'BF_Product_Plugin_Manager' ) ) {
			require_once BF_Product_Pages::get_path( 'install-plugin/class-bf-product-plugin-manager.php' );
		}

		$obj    = new BF_Product_Plugin_Manager();
		$status = $obj->update_plugins( true );

		$plugins_config = bf_get_plugins_config();

		if ( ! empty( $status->remote_plugins ) && is_array( $status->remote_plugins ) ) {

			if ( empty( $value->response ) ) {

				if ( ! is_object( $value ) ) {
					$value = new stdClass();
				}

				$value->response = array();
			}

			$r = &$value->response;

			foreach ( $status->remote_plugins as $p_file => $plugin_data ) {

				$slug = $plugin_data['slug'];

				if ( ! isset( $plugins_config[ $slug ]['type'] ) ||
				     'bundled' !== $plugins_config[ $slug ]['type']
				) {

					continue;
				}

				$r[ $p_file ]          = (object) $plugin_data;
				$r[ $p_file ]->plugin  = $p_file;
				$r[ $p_file ]->package = 'FETCH_FROM_BETTER_STUDIO/' . $slug;
			}
		}

		return $value;
	}
}


if ( ! function_exists( 'bf_update_plugin_schedule_status' ) ) {

	/**
	 * @param string $status enable or disable
	 *
	 * @since 3.9.1
	 */
	function bf_update_plugin_schedule_status( $status ) {

		global $bf_update_plugin_schedule_disabled;

		$bf_update_plugin_schedule_disabled = $status === 'disable';
	}
}


add_action( 'site_transient_update_plugins', 'bf_update_plugins_list' );

if ( ! function_exists( 'bf_update_plugins_list' ) ) {

	/**
	 *
	 * @param mixed $value
	 *
	 * @hooked site_transient_update_plugins
	 *
	 * @return mixed
	 */
	function bf_update_plugins_list( $value ) {

		if ( ! bf_is_doing_ajax( 'update-plugin' ) ) { // when updating plugin in plugins.php page

			return $value;
		}

		if ( empty( $value->response ) || ! is_array( $value->response ) ) {

			return $value;
		}

		if ( ! class_exists( 'BF_Product_Plugin_Installer' ) ) {
			require_once BF_Product_Pages::get_path( 'install-plugin/class-bf-product-plugin-installer.php' );
		}
		$installer = new BF_Product_Plugin_Installer();
		add_filter( 'http_request_args', 'bf_remove_reject_unsafe_urls', 99 );

		foreach ( $value->response as $p_file => $plugin_data ) {

			if ( isset( $plugin_data->package ) && preg_match( '/^FETCH_FROM_BETTER_STUDIO\/.+/i', $plugin_data->package ) ) {

				$action  = BF_Product_Plugin_Installer::is_plugin_installed( $plugin_data->slug ) ? 'update' : 'install';
				$dl_link = $installer->get_bundled_plugin_download_link( $plugin_data->slug, $action );

				if ( $dl_link && ! is_wp_error( $dl_link ) ) {
					$value->response[ $p_file ]->package = $dl_link;
				}
			}
		}

		return $value;
	}
}

add_filter( 'set_site_transient_update_plugins', 'bf_sync_plugin_update_information' );

if ( ! function_exists( 'bf_sync_plugin_update_information' ) ) {

	/**
	 *
	 * @param object $value
	 *
	 * @hooked set_site_transient_update_plugins
	 *
	 * @return object
	 */
	function bf_sync_plugin_update_information( $value ) {

		global $pagenow;

		// Make sure plugin update data is valid
		// we expect wordpress check plugin updates in plugin and updates page
		if ( ! in_array( $pagenow, array(
				'plugins.php',
				'update-core.php',
				'update.php'
			) ) && ! bf_is_doing_ajax( 'update-plugin' )
		) {
			return $value;
		}

		$current_plugin_stat = get_option( 'bs-product-plugins-status' );
		$update_plugin_stat  = false;

		//
		// Remove Updated Plugin From our List
		//
		if ( ! empty( $current_plugin_stat->remote_plugins ) ) {

			$plugins       = empty( $value->response ) ? array() : $value->response;
			$maybe_updated = array_diff_key( $current_plugin_stat->remote_plugins, $plugins );

			$plugin_dir = trailingslashit( WP_PLUGIN_DIR );
			foreach ( $maybe_updated as $plugin_path => $plugin_new_ver ) {

				$plugin_installed_data = get_plugin_data( $plugin_dir . $plugin_path );

				// check if plugin was really updated
				if ( version_compare( $plugin_installed_data['Version'], $plugin_new_ver['new_version'], '=' ) ) {
					unset( $current_plugin_stat->remote_plugins[ $plugin_path ] );
					$update_plugin_stat = true;
				}
			}
		}

		if ( $update_plugin_stat ) {
			update_option( 'bs-product-plugins-status', $current_plugin_stat );
		}

		return $value;
	}
}


if ( ! function_exists( 'bf_remove_reject_unsafe_urls' ) ) {

	/**
	 * @param array $args
	 *
	 * @return array
	 */
	function bf_remove_reject_unsafe_urls( $args ) {

		$args['reject_unsafe_urls'] = false;

		return $args;
	}
}

add_filter( 'upgrader_pre_download', 'bf_update_plugin_bulk', 999, 2 );

if ( ! function_exists( 'bf_update_plugin_bulk' ) ) {

	/**
	 * @param bool   $bool
	 * @param string $package
	 *
	 * @hooked upgrader_pre_download
	 *
	 * @return bool|string|WP_Error
	 */
	function bf_update_plugin_bulk( $bool, $package ) {

		if ( ! preg_match( '/^FETCH_FROM_BETTER_STUDIO\/(.+)/i', $package, $match ) ) {

			return $bool;
		}

		$plugin_slug = &$match[1];

		try {

			if ( ! class_exists( 'BF_Product_Plugin_Installer' ) ) {
				require_once BF_Product_Pages::get_path( 'install-plugin/class-bf-product-plugin-installer.php' );
			}

			if ( $url = bf_bundle_plugin_package_url( $plugin_slug ) ) {

				return download_url( $url );
			}

		} catch( Exception $e ) {

			return '';
		}

		return $bool;
	}
}


if ( ! function_exists( 'bf_bundle_plugin_package_url' ) ) {

	/**
	 * Get the plugin package download url
	 *
	 * @param string $plugin_slug
	 * @param bool   $mirror
	 *
	 * @return string
	 */
	function bf_bundle_plugin_package_url( $plugin_slug, $mirror = false ) {

		if ( ! class_exists( 'BF_Product_Plugin_Installer' ) ) {
			require_once BF_Product_Pages::get_path( 'install-plugin/class-bf-product-plugin-installer.php' );
		}

		$installer = new BF_Product_Plugin_Installer();
		$action    = BF_Product_Plugin_Installer::is_plugin_installed( $plugin_slug ) ? 'update' : 'install';
		$url       = $installer->get_bundled_plugin_download_link( $plugin_slug, $action, $mirror );

		if ( ! $url || is_wp_error( $url ) ) {

			return '';
		}

		return $url;
	}
}


add_action( 'vc_after_mapping', 'bf_remove_vc_register_notice' );

if ( ! function_exists( 'bf_remove_vc_register_notice' ) ) {

	/**
	 * callback: remove visual composer register admin notice
	 * action  : vc_after_mapping
	 *
	 * @hooked vc_after_mapping
	 */
	function bf_remove_vc_register_notice() {

		global $_bs_vc_access_changes;

		if ( ! function_exists( 'vc_user_access' ) ) {
			return;
		}

		$instance = vc_user_access();

		if ( is_callable( array( $instance, 'setValidAccess' ) ) ) {
			$instance->setValidAccess( false );
		}

		if ( is_callable( array( $instance, 'getValidAccess' ) ) ) {
			$_bs_vc_access_changes = vc_user_access()->getValidAccess();
		}
	}
}

add_action( 'better-framework/product-pages/install-plugin/install-finished', 'bf_remove_revslider_register_notice' );
add_action( 'better-framework/product-pages/install-plugin/active-finished', 'bf_remove_revslider_register_notice' );

if ( ! function_exists( 'bf_remove_revslider_register_notice' ) ) {

	/**
	 * callback: Hide register revolution slider admin notice
	 *
	 * @hooked better-framework/product-pages/install-plugin/install-finished,
	 * @hooked better-framework/product-pages/install-plugin/active-finished
	 *
	 * @param string|array $data
	 *
	 * @return bool
	 */
	function bf_remove_revslider_register_notice( $data ) {

		if ( is_string( $data ) ) {
			$slug = $data;
		} elseif ( isset( $data['slug'] ) ) {
			$slug = $data['slug'];
		} else {
			return false;
		}

		if ( $slug === 'revslider' ) {
			remove_filter( 'pre_update_option_revslider-valid-notice', '__return_false', PHP_INT_MAX );
			update_option( 'revslider-valid-notice', 'false' );
		}

		return true;
	}
}

add_action( 'delete_option_revslider-valid-notice', 'bf_hide_revslider_register_notice', PHP_INT_MAX );
add_filter( 'pre_update_option_revslider-valid-notice', '__return_false', PHP_INT_MAX );

if ( ! function_exists( 'bf_hide_revslider_register_notice' ) ) {

	/**
	 * Hide revolution slider registration notice
	 *
	 * @hooked delete_option_revslider-valid-notice
	 */
	function bf_hide_revslider_register_notice() {

		add_option( 'revslider-valid-notice', 'false' );
	}
}


add_action( 'vc_after_init', 'bf_undo_vc_access_changes' );

if ( ! function_exists( 'bf_undo_vc_access_changes' ) ) {

	/**
	 * callback: undo changes on visual composer user access
	 *
	 * @hooked vc_after_init
	 */
	function bf_undo_vc_access_changes() {

		global $_bs_vc_access_changes;

		if ( ! is_null( $_bs_vc_access_changes ) ) {
			vc_user_access()->setValidAccess( $_bs_vc_access_changes );
			unset( $_bs_vc_access_changes );
		}
	}
}

add_action( 'load-update.php', 'bf_force_check_plugins_update' );
add_action( 'load-update-core.php', 'bf_force_check_plugins_update' );

if ( ! function_exists( 'bf_force_check_plugins_update' ) ) {

	/**
	 * @hooked load-update.php
	 * @hooked load-update-core.php
	 */
	function bf_force_check_plugins_update() {

		BF_Product_Pages::Run()->plugins_menu_instance()->update_plugins( true );
	}
}

add_filter( 'better-framework/product-pages/register-menu/params', 'bf_append_plugins_update_badge' );

if ( ! function_exists( 'bf_append_plugins_update_badge' ) ) {

	/**
	 * @hooked better-framework/product-pages/register-menu/params
	 *
	 * @param array $menu
	 *
	 * @return array
	 */
	function bf_append_plugins_update_badge( $menu ) {

		if ( ! empty( $menu['parent'] ) && $menu['id'] !== BF_Product_Pages::$menu_slug . '-install-plugin' ) {

			return $menu;
		}

		if ( ! $update_status = get_option( 'bs-product-plugins-status' ) ) {

			return $menu;
		}

		$activated_plugins_updates = 0;

		if ( ! empty( $update_status->remote_plugins ) && is_array( $update_status->remote_plugins ) ) {

			/**
			 * Just display number of updates for activated plugins
			 *
			 * @see BF_Product_Plugin_Manager::render_content
			 */
			if ( ! class_exists( 'BS_Product_Plugin_Factor' ) ) {
				require_once BF_Product_Pages::get_path( 'install-plugin/class-bf-product-plugin-installer.php' );
			}

			foreach ( $update_status->remote_plugins as $plugin ) {

				if ( isset( $plugin['slug'] ) &&
				     BF_Product_Plugin_Installer::is_plugin_installed( $plugin['slug'] ) &&
				     BF_Product_Plugin_Installer::is_plugin_active( $plugin['slug'] )
				) {
					$activated_plugins_updates ++;
				}
			}

			if ( $activated_plugins_updates ) {

				$menu_title_index = $menu['parent'] ? 'menu_title' : 'parent_title';

				$menu[ $menu_title_index ] .= ' &nbsp;<span class="bs-admin-menu-badge"><span class="plugin-count">'
				                              . number_format_i18n( $activated_plugins_updates ) .
				                              '</span></span>';
			}
		}

		if ( ! isset( $update_status->number ) || $update_status->number !== $activated_plugins_updates ) {

			$update_status->number = $activated_plugins_updates;
			update_option( 'bs-product-plugins-status', $update_status );
		}

		return $menu;
	}
}
libs/better-framework/product-pages/install-plugin/index.php000064400000000006151214002510020277 0ustar00<?php
libs/better-framework/product-pages/install-plugin/class-bf-plugin-bulk-install-skin.php000064400000004560151214002510025530 0ustar00<?php

if ( ! class_exists( 'Plugin_Installer_Skin' ) ) {

	require ABSPATH . '/wp-admin/includes/class-wp-upgrader-skins.php';
}


class BF_Plugin_Bulk_Install_Skin extends Bulk_Plugin_Upgrader_Skin {

	public function __construct( $args = array() ) {

		$args['url'] = add_query_arg( $_GET );

		parent::__construct( $args );
	}


	/**
	 * @access public
	 */
	public function bulk_footer() {

		parent::bulk_footer();

		$update_actions = array(
			'plugins_page' => '<a href="admin.php?page=' . esc_attr( $_REQUEST['page'] ) . '" target="_parent">' . __( 'Return to Plugins page', 'better-studio' ) . '</a>',
		);

		if ( ! current_user_can( 'activate_plugins' ) ) {
			unset( $update_actions['plugins_page'] );
		}

		/**
		 * Filter the list of action links available following bulk plugin updates.
		 *
		 * @since 3.0.0
		 *
		 * @param array $update_actions Array of plugin action links.
		 * @param array $plugin_info    Array of information for the last-updated plugin.
		 */
		$update_actions = apply_filters( 'update_bulk_plugins_complete_actions', $update_actions, $this->plugin_info );

		if ( ! empty( $update_actions ) ) {
			$this->feedback( implode( ' | ', (array) $update_actions ) );
		}

		$this->filter_updated_plugins();
	}


	/**
	 * Iterate over the plugins update list to remove updated items if it's been already updated successfully.
	 *
	 * @since 3.10.2
	 * @return bool true if any change made.
	 */
	protected function filter_updated_plugins() {

		$update_plugins = get_site_transient( 'update_plugins' );

		if ( empty( $update_plugins->response ) ) {
			return false;
		}

		$current                  = count( $update_plugins->response );
		$update_plugins->response = array_filter( $update_plugins->response, array( $this, 'is_valid_item' ) );

		if ( $current !== count( $update_plugins->response ) ) {

			set_site_transient( 'update_plugins', $update_plugins );

			return true;
		}

		return false;
	}

	/**
	 * Whether to check if the plugin update info is valid.
	 *
	 * @param stdClass $item
	 *
	 * @since 3.10.2
	 * @return bool true if it's valid.
	 */
	protected function is_valid_item( $item ) {

		$plugin_installed_data = get_plugin_data(
			trailingslashit( WP_PLUGIN_DIR ) . $item->plugin
		);

		if ( empty( $plugin_installed_data['Version'] ) ) {
			return true;
		}

		return version_compare( $plugin_installed_data['Version'], $item->new_version, '<' );
	}
}
libs/better-framework/product-pages/install-plugin/assets/js/index.php000064400000000006151214002510022215 0ustar00<?php
libs/better-framework/product-pages/install-plugin/assets/js/bs-plugin-install.js000064400000014265151214002510024313 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */



jQuery(function ($) {
    "use strict";

    var $context = $("#wpbody-content"),
        $table = $("#the-list", $context);

    var $items = $table.children('tr');

    function updateDisplayingNum(num) {

        $(".displaying-num", $context).html(
            bs_plugin_install_loc[num > 1 ? 'items_count' : 'item_count'].replace('%s', num)
        );
    }

    function updateResults($foundItems, searchValue) {

        $(".no-items", $table).remove();

        var msg;
        //
        // Update Results
        //
        if ($foundItems.length === 0) {

            msg = bs_plugin_install_loc.search_failed.replace('%s', searchValue);

            $items.hide();
            $table.append(
                '<tr class="no-items"><td class="colspanchange" colspan="3">' + msg + '</td></tr>'
            );

        } else {

            $foundItems.show();
            $items.not($foundItems).hide();
        }

        // Update displaying number
        updateDisplayingNum($foundItems.length);
    }

    function showAll() {

        $(".no-items", $table).remove();
        var total = $items.show().length;

        updateDisplayingNum(total);
    }

    $("#plugin-search-input", $context).on('keyup', function () {

        if (document.getElementById('current-plugin-status').value !== 'all') {

            return true;
        }

        var value = this.value.trim().toLowerCase();

        if (value === '') {

            showAll();

            return;
        }

        var $foundItems = $items.filter(function () {

            if (this.classList.contains('plugin-update-tr')) {

                if (!this.previousElementSibling) {
                    return false;
                }

                return $('.plugin-title strong', this.previousElementSibling).text().toLowerCase().indexOf(value) > -1;
            }

            return $('.plugin-title strong', this).text().toLowerCase().indexOf(value) > -1;
        });

        updateResults($foundItems, value);
    });

    $(".subsubsub a", $context).on('click', function () {

        if (document.getElementById('current-plugin-status').value !== 'all') {

            return true;
        }

        var $this = $(this),
            state = $this.closest('li').attr('class');

        //
        // Add activated class
        //

        $(".subsubsub a", $context).removeClass('current');

        $this.addClass('current');

        if ('all' === state) {

            showAll();

            return false;
        }

        var $foundItems = $items.filter(function () {

            var $item = $(this);

            if ($item.hasClass('plugin-update-tr')) {

                if (!this.previousElementSibling) {
                    return false;
                }

                return $item.prev().hasClass(state);
            }

            return $item.hasClass(state);
        });

        updateResults($foundItems, $this.text().replace(/\s*\(.*?\)\s*/, ''));

        return false;
    });

    var _confirmDelete = function (confirm, names) {
        var loc = $.extend(bs_plugin_install_loc.delete_confirm, {});


        var list = '';
        if (names) {
            list = '<ol>';
            names.forEach(function (name) {
                list += "<li>" + name + "</li>";
                list += "\n\t";
            });
        }
        list += '</ol>';

        loc.body = loc.body.replace("%list%", list);

        $.bs_modal({
            modalId: 'delete-confirm',
            content: loc,

            buttons: {
                close_modal: {
                    label: loc.button_no,
                    type: 'primary',
                    action: 'close'
                },
                custom_event: {
                    label: loc.button_yes,
                    type: 'secondary',
                    clicked: confirm
                }
            },
            button_position: 'left',
            events: {},
            styles: {
                container: 'overflow:visible;max-width: 530px;'
            }
        });
    };
    $("#bulk-action-form").on('click', '[type="submit"]:not([name="clear-recent-list"])', function (event) {

        var bulkAction = $(event.target).siblings('select').val();

        if (bulkAction !== 'delete-selected') {
            return true;
        }

        var $form = $("#bulk-action-form");
        // $form.one('submit', function () { return false; });

        var names = [];

        $(".check-column :checkbox:checked", $form).each(function () {
            var $row = $(this).closest('tr');

            names.push($(".plugin-title strong", $row).html());

        }).promise().done(function () {

            _confirmDelete(function () {

                var self = this;
                self.change_skin({
                    skin: 'loading',
                    animations: {
                        body: 'bs-animate bs-fadeInLeft'
                    }
                });

                $("#verify-delete-input").val('1');
                $("#bulk-action-form").submit();

            }, names);
        });

        return false;
    });

    $(".row-actions .delete a").on('click', function (e) {

        e.preventDefault();

        var url = this.href;

        _confirmDelete(function () {

            var self = this;
            self.change_skin({
                skin: 'loading',
                animations: {
                    body: 'bs-animate bs-fadeInLeft'
                }
            });
            window.location = url + "&verify-delete=1";
        });

    });

});libs/better-framework/product-pages/install-plugin/assets/css/index.php000064400000000006151214002510022371 0ustar00<?php
libs/better-framework/product-pages/install-plugin/assets/css/bs-plugin-install.css000064400000004372151214002510024641 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */

.plugins .plugin-not-installed th,
.plugins .plugin-not-installed td {
    box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.1);
}

.plugins tr.plugin-update-available .plugin-title,
.plugins tr.plugin-update-available .column-description {

    box-shadow: none !important;
    padding-bottom: 0 !important;
}

.plugins td.plugin-thumbnail {
    width: 94px;
    padding: 12px 0;
    margin: 0;
}

.plugins .plugin-update-tr .notice, .plugins .plugin-update-tr div[class="update-message"] {
    margin-left: 10px;
}

body.rtl .plugins .plugin-update-tr .notice, .plugins .plugin-update-tr div[class="update-message"] {
    margin-right: 10px;
}

.plugins .plugin-update-tr td.plugin-update {
    border-left: none;
}

body.rtl .plugins .plugin-update-tr td.plugin-update {
    border-left: none;
}

.plugins .bs-pages-badge {
    background: #aaa;
    color: #fff;
    text-transform: uppercase;
    padding: 2px 4px;
    font-size: 10px;
    font-weight: 500;
}

.plugins .bs-pages-badge-compatible {
    background: #3e69b7;
}

.plugins .bs-pages-badge-premium {
    background: #cf5830;
}

.plugins .bs-pages-badge-exclusive {
    background: #46b450;
}

.plugins .bs-pages-badge-new {
    background: #ca4a1f;
    margin: 0 5px;
}

.plugins .deactivate a {
    color: #ca4a21;
}

.plugins .bs-upgrade-notice {
    padding-top: 20px;
    display: block;
    color: #dc3434;
}

.plugins.bf-product-inactive .plugin-thumbnail {
    padding-left: 15px;
}

body.rtl .plugins.bf-product-inactive .plugin-thumbnail {
    padding-right: 15px;
    padding-left: 0;
}libs/better-framework/product-pages/install-plugin/assets/index.php000064400000000006151214002510021601 0ustar00<?php
libs/better-framework/product-pages/install-plugin/templates/class-bf-plugin-upgrade-skin.php000064400000000616151214002510026552 0ustar00<?php

if ( ! class_exists( 'Plugin_Installer_Skin' ) ) {

	require ABSPATH . '/wp-admin/includes/class-wp-upgrader-skins.php';
}


class BF_Plugin_Upgrade_Skin extends Bulk_Plugin_Upgrader_Skin {

	public function after() {

		$install_actions['plugins_page'] = '<a href="admin.php?page=' . esc_attr( $_REQUEST['page'] ) . '">' . __( 'Return to Plugin Installer', 'better-studio' ) . '</a>';
	}
}
libs/better-framework/product-pages/install-plugin/templates/index.php000064400000000006151214002510022275 0ustar00<?php
libs/better-framework/product-pages/install-plugin/templates/main-page.php000064400000002270151214002510023031 0ustar00<?php

BF_Product_Plugin_Installer::flush_cache();

$list_table->prepare_items();
$list_table->views();
?>

	<form class="search-form search-plugins" method="get">
		<input type="hidden" name="plugin_status" value="<?php echo esc_attr( $status ) ?>"/>
		<input type="hidden" name="paged" value="<?php echo esc_attr( $page ) ?>"/>
		<input type="hidden" name="page"
		       value="<?php echo isset( $_REQUEST['page'] ) ? esc_attr( $_REQUEST['page'] ) : '' ?>"/>

		<?php $list_table->search_box( __( 'Search Installed Plugins', 'better-studio' ), 'plugin' ); ?>
	</form>

	<form method="post" id="bulk-action-form">

		<input type="hidden" name="verify-delete" value="0" id="verify-delete-input"/>
		<input type="hidden" name="plugin_status" value="<?php echo esc_attr( $status ) ?>"/>
		<input type="hidden" name="paged" value="<?php echo esc_attr( $page ) ?>"/>
		<input type="hidden" name="page"
		       value="<?php echo isset( $_REQUEST['page'] ) ? esc_attr( $_REQUEST['page'] ) : '' ?>"/>

		<?php $list_table->display(); ?>


		<input type="hidden" id="current-plugin-status"
		       value="<?php echo isset( $_GET['plugin_status'] ) ? esc_attr( $_GET['plugin_status'] ) : 'all' ?>">
	</form>
<?php
libs/better-framework/product-pages/inc/class-bf-product-pages-menu.php000064400000004452151214002510022217 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


die( 'Marked to remove' );


abstract class BF_Product_Pages_Menu extends BF_Product_Pages_Base {

	public $data;

	public $instaces = array();


	abstract public function fields();


	public function get_field_types() {

		return apply_filters( 'better-framework/product-pages/fields', array(
				'import_demo' => 'BS_Theme_Pages_Demo_Import_Manager'
			)
		);
	}


	public function render() {

		try {
			$fields = $this->fields();
			if ( ! $fields ) {
				throw new Exception( 'Fields is empty!' );
			}

			if ( ! is_array( $fields ) ) {
				throw new Exception( 'Fields is invalid!' );
			}

			$fields_required_keys = array(
				'type'    => '',
				'options' => ''
			);

			$available_types = $this->get_field_types();
			//handle fields

			foreach ( $fields as $field ) {

				if ( array_diff_key( $fields_required_keys, $field ) ) {
					continue;
				}
				$type    = &$field['type'];
				$options = &$field['options'];

				if ( ! isset( $available_types[ $type ] ) ) {
					throw new Exception( sprintf( 'invalid field type: %s', $type ) );
				}

				$instance = $this->get_instance( $available_types[ $type ] );

				$instance->setup();

				call_user_func( array( $instance, 'display_field' ), $field['options'] );

				$instance->tearDown();

			}

		} catch( Exception $e ) {

			$this->error( $e->getMessage() );
		}
	}


	protected function get_instance( &$class_name ) {

		if ( ! isset( $this->instaces[ $class_name ] ) ) {
			$this->instaces[ $class_name ] = new $class_name();
			$this->instaces[ $class_name ]->init();
		}

		return $this->instaces[ $class_name ];
	}
}libs/better-framework/product-pages/inc/class-bf-product-pages-plugins.php000064400000001703151214002510022730 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Class BF_Product_Pages_Plugin
 */
class BF_Product_Pages_Plugin extends BF_Product_Item {

	public $id = 'plugins';


	public function render_content( $item_data ) {
	}


	public function item_data() {
	}
}libs/better-framework/product-pages/inc/class-bf-product-pages-system-status.php000064400000001730151214002510024114 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Class BF_Product_Pages_System_Status
 */
class BF_Product_Pages_System_Status extends BF_Product_Item {

	public $id = 'system-status';


	public function render_content( $item_data ) {
	}


	public function item_data() {
	}
}
libs/better-framework/product-pages/inc/class-bf-product-pages-theme-panel.php000064400000001663151214002510023453 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Class BF_Product_Pages_Theme_Panel
 */
class BF_Product_Pages_Theme_Panel extends BF_Product_Item {

	public function render_content( $item_data ) {
	}


	public function item_data() {
	}
}
libs/better-framework/product-pages/inc/index.php000064400000000006151214002510016106 0ustar00<?php
libs/better-framework/product-pages/inc/class-bf-product-pages-register-theme.php000064400000001733151214002510024176 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Class BF_Product_Pages_Register_Theme
 */
class BF_Product_Pages_Register_Theme extends BF_Product_Item {

	public $id = 'register-theme';


	public function render_content( $item_data ) {
	}


	public function item_data() {
	}
}
libs/better-framework/product-pages/report/functions.php000064400000004163151214002510017561 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


function bf_system_report_enqueue_scripts() {

	if ( bf_is_product_page( 'report' ) ) {

		$ver = BF_Product_Pages::Run()->get_version();

		wp_enqueue_script( 'bs-product-report-scripts', BF_Product_Pages::get_url( 'report/assets/js/bs-system-report.js' ), array(), $ver );
	}

}

add_action( 'admin_enqueue_scripts', 'bf_system_report_enqueue_scripts' );


/**
 * callback: saved imported demo list in database
 * action: bs-product-pages/install-demo/import-finished
 *
 * @param string $demo_ID
 */
function bf_product_report_log_demo_install( $demo_ID ) {

	$history             = (array) get_option( 'bs-demo-install-log', array() );
	$history[ $demo_ID ] = time();

	update_option( 'bs-demo-install-log', $history, 'no' );
}

add_action( 'better-framework/product-pages/install-demo/import-finished', 'bf_product_report_log_demo_install' );


/**
 * callback: remove imported demo from database after demo uninstalled successfully
 * action: bs-product-pages/install-demo/rollback-finished
 *
 * @param string $demo_ID
 */
function bf_product_report_log_demo_uninstall( $demo_ID ) {

	$history = (array) get_option( 'bs-demo-install-log', array() );
	if ( isset( $history[ $demo_ID ] ) ) {
		unset( $history[ $demo_ID ] );
		update_option( 'bs-demo-install-log', $history, 'no' );
	}
}

add_action( 'better-framework/product-pages/install-demo/rollback-finished', 'bf_product_report_log_demo_uninstall' );
libs/better-framework/product-pages/report/class-bf-product-report.php000064400000055243151214002510022237 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Class BF_Product_Report
 */
class BF_Product_Report extends BF_Product_Item {

	public $id = 'report';

	public $check_remote_duration;

	/**
	 * store active item in loop
	 *
	 * @var array
	 */
	public $active_item = array();

	/**
	 * store item settings array if available
	 *
	 * @var array
	 */
	public $item_settings = array();

	/**
	 * Store theme headers data
	 *
	 * @var array
	 */
	public $theme_header = array();


	/**
	 * allow generate HTML?
	 *
	 * @var string
	 */
	public $render_context = 'html';


	/**
	 * BF_Product_Report constructor.
	 */
	public function __construct() {

		parent::__construct();

		$this->check_remote_duration = HOUR_IN_SECONDS;
	}


	protected function get_report_settings() {

		return apply_filters( 'better-framework/product-pages/system-report/config', array() );
	}


	protected function before_render() {

		parent::before_render();

		$this->test_http_remote();
	}


	/**
	 * Render HTML output
	 *
	 * @param array $item_data
	 */
	public function render_content( $item_data ) {

		if ( $boxes = $this->get_report_settings() ) :

			$this->sort_config( $boxes );

			foreach ( $boxes as $box ) :

				$this->prepare_box_params( $box );

				?>
				<div class="bs-product-pages-box-container bs-pages-row-one bf-clearfix">

					<div class="bs-pages-box-wrapper">
				<span class="bs-pages-box-header">
					<?php
					if ( isset( $box['box-settings']['icon'] ) ) {
						echo bf_get_icon_tag( $box['box-settings']['icon'] );
					}


					if ( isset( $box['box-settings']['header'] ) ) {
						echo $box['box-settings']['header']; // escaped before
					}

					?>
				</span>

						<div class="bs-pages-box-description bs-pages-box-description-fluid">
							<?php if ( ! empty( $box['items'] ) ) : ?>
							<div class="bs-pages-list-wrapper">
								<?php
								foreach ( $box['items'] as $item ) :
									$have_label = ! empty( $item['label'] );
									$this->item_settings = $this->get_item_settings( $item );

									?>
									<div class="bs-pages-list-item<?php
									if ( ! empty( $item['class'] ) ) {
										echo ' ', sanitize_html_class( $item['class'] ); // escaped before
									}
									?>">
										<?php

										if ( $have_label ) : ?>
											<div class="bs-pages-list-title">
												<?php

												if ( isset( $item['before_label'] ) ) {
													echo $item['before_label']; // escaped before
												}

												echo $item['label']; // escaped before

												if ( isset( $item['after_label'] ) ) {
													echo $item['after_label']; // escaped before
												}
												?>
											</div>
										<?php endif ?>
										<div class="bs-pages-list-data<?php if ( ! $have_label ) {
											echo ' no-label';
										} ?>">
											<?php
											if ( $data = $this->get_item_data( $item ) ) {

												$this->help_section_html( $data );
												$this->item_section_html( $data );
											}
											?>
										</div>
									</div>
								<?php endforeach; ?>
							</div>
						</div>
						<?php endif ?>
					</div>
				</div>
				<?php

			endforeach;
		else:
			$this->error( 'System report was not configured!' );
		endif;
	}


	/**
	 * Render simple text
	 *
	 */
	public function render_text() {

		ob_start();

		$this->render_context = 'debug';

		if ( $boxes = $this->get_report_settings() ) {

			$this->sort_config( $boxes );

			//remove system report html before export as text
			foreach ( $boxes as $box_id => $info ) {
				if ( isset( $info['box-settings']['operation'] ) && $info['box-settings']['operation'] === 'report-export' ) {

					unset( $boxes[ $box_id ] );
					break;
				}
			}

			foreach ( $boxes as $box ) :

				$this->prepare_box_params( $box );

				echo "\n";
				echo '### ';
				if ( isset( $box['box-settings']['header'] ) ) {
					echo $box['box-settings']['header']; // escaped before
				}
				echo ' ###', "\n";

				if ( ! empty( $box['items'] ) ) {
					foreach ( $box['items'] as $item ) {

						echo "\n", $item['label'], ' '; // escaped before

						if ( $data = $this->get_item_data( $item ) ) {
							echo $data[1]; // escaped before
						} else {
							esc_html_e( 'NOTHING!', 'better-studio' );
						}
					}
				}
				echo "\n";
			endforeach;

			echo '### ', __( 'Error Log', 'better-studio' ), ' ###', "\n";
			print_r( get_option( 'bs-backend-error-log' ) );

		} else {
			esc_html_e( 'System report was not configured!', 'better-studio' );
		}

		return ob_get_clean();
	}


	private function get_item_settings( $item ) {

		if ( ! isset( $item['settings'] ) || ! is_array( $item['settings'] ) ) {

			return array();
		}

		return wp_parse_args( $item['settings'], array(
			'standard_value' => 0,
			'minimum_value'  => 0,
			'default'        => 'enabled'
		) );
	}


	/**
	 * process item and retrieve data
	 *
	 * @param array $item
	 *
	 * @return array empty array on failed
	 *
	 *  success array:
	 *  array {
	 *    0 => raw value
	 *    1 => print ready content
	 *  }
	 */
	protected function get_item_data( $item ) {

		if ( empty( $item['type'] ) ) {
			return array();
		}

		$this->active_item = &$item;

		$type     = explode( '.', $item['type'] );
		$method   = 'get_' . $type[0] . '_data';
		$callback = array( $this, $method );

		if ( is_callable( $callback ) ) {
			$params     = array_slice( $type, 1 );
			$raw_result = call_user_func_array( $callback, $params );


			/**
			 * Todo: test $type[0] param
			 */
			return array(
				$this->sanitize_item( $raw_result, $type[0], 'raw' ),
				$this->sanitize_item( $raw_result, $type[0], 'display' )
			);
		}

		return array();
	}


	/**
	 * @param string $data_type
	 *
	 * @return string
	 */
	private function get_bs_pages_data( $data_type ) {

		$result = '';
		switch ( $data_type ) {

			case 'history':

				/**
				 * get demo installation history
				 *
				 * @see bf_product_report_log_demo_install
				 */
				if ( $imported_demos = get_option( 'bs-demo-install-log' ) ) {

					$result = sprintf( 'imported demo(s): %s', implode( ', ', array_keys( (array) $imported_demos ) ) );
				} else {

					$result = __( 'Nothing!', 'better-studio' );
				}

				break;
		}


		return $result;
	}


	/**
	 * append data to box item by checking box-settings array => operation index value
	 *
	 * @param array $box
	 *
	 * @return bool true on success or false on failure.
	 */
	protected function prepare_box_params( &$box ) {

		if ( empty( $box['box-settings']['operation'] ) ) {
			return false;
		}

		if ( ! isset( $box['items'] ) ) {
			$box['items'] = array();
		}


		switch ( $box['box-settings']['operation'] ) {

			case 'list-active-plugin':


				/** @noinspection SpellCheckingInspection */
				$plugins = array_merge(
					array_flip( (array) get_option( 'active_plugins', array() ) ),
					(array) get_site_option( 'active_sitewide_plugins', array() )
				);
				if ( $plugins = array_intersect_key( get_plugins(), $plugins ) ) {

					foreach ( $plugins as $plugin ) {

						$plugin_uri  = isset( $plugin['PluginURI'] ) ? esc_url( $plugin['PluginURI'] ) : '#';
						$plugin_name = isset( $plugin['Name'] ) ? $plugin['Name'] : __( 'unknown', 'better-studio' );

						$author_uri  = isset( $plugin['AuthorURI'] ) ? esc_url( $plugin['AuthorURI'] ) : '#';
						$author_name = isset( $plugin['Author'] ) ? $plugin['Author'] : __( 'unknown', 'better-studio' );

						if ( $this->render_context === 'html' ) {

							$box['items'][] = array(
								'type'        => 'raw',
								'label'       => wp_kses( sprintf( '<a href="%s" target="_blank">%s</a>', $plugin_uri, $plugin_name ), bf_trans_allowed_html() ),
								'description' => wp_kses( sprintf( __( 'by <a href="%s" target="_blank">%s</a>', 'better-studio' ), $author_uri, $author_name ), bf_trans_allowed_html() ),
							);
						} else {

							$plugin_version = isset( $plugin['Version'] ) ? $plugin['Version'] : 'unknown';

							$box['items'][] = array(
								'type'        => 'raw',
								'label'       => $plugin_name,
								'description' => sprintf( __( 'by %s (V %s)', 'better-studio' ), $author_name, $plugin_version ),
							);
						}
					}
				} else {
					$box['items'][] = array(
						'type'        => 'raw',
						'label'       => false,
						'count_calc'  => false,
						'description' => sprintf( '<div class="bs-product-notice bs-product-notice-warning">%s</div>', __( 'no active plugin was found!', 'better-studio' ) )
					);
				}

				break;

			case 'report-export':

				if ( $this->render_context === 'html' ) {

					$box['items'][] = array(
						'type'        => 'raw',
						'label'       => sprintf( '<a href="#" class="bf-btn-primary bs-pages-primary-btn bs-pages-success-btn" id="bs-get-system-report"><span class="loading" style="display: none;margin: 0 5px;"><i class="fa fa-refresh fa-spin"></i></span> %s</a>', __( 'Get Status Report', 'better-studio' ) ),
						'description' => __( 'Click the button to produce a report, then copy and paste into your support ticket.', 'better-studio' ),
					);
					$box['items'][] = array(
						'type'        => 'raw',
						'label'       => false,
						'class'       => 'bs-item-hide',
						'description' => '<div id="bs-system-container" style="display: none;"><textarea rows="20" style="width: 100%;color: #595959;" class="bs-output">' . $this->render_text() . '</textarea><a href="#" class="bf-btn-primary" id="bs-copy-system-report">' . __( 'Copy status report', 'better-studio' ) . '</a></div>'
					);
				}

				break;

			case 'template-compatibility':

				$config = apply_filters( 'better-framework/product-pages/system-report/theme-compatibility', array() );
				$label  = __( 'current version: %s - updated version: %s', 'better-studio' );

				if ( $outdated_files = BF_Template_Compatibility::do_compatibility( $config, false ) ) {
					foreach ( $outdated_files as $file ) {

						if ( empty( $file['override_version'] ) ) {
							$file['override_version'] = __( 'undefined', 'better-studio' );
						}

						$box['items'][] = array(
							'type'        => 'raw',
							'label'       => $file['path'],
							'description' => sprintf( $label, $file['override_version'], $file['parent_version'] ),
						);
					}
				} else {
					$box['items'][] = array(
						'type'  => 'raw',
						'label' => __( 'No outdated file was found in child-theme', 'better-studio' ),
					);
				}

				break;
			default:

				return false;
		}

		$box['box-settings']['header'] =
			str_replace(
				array( '%%count%%' ),
				array( number_format_i18n( $this->count( $box['items'] ) ) ),
				$box['box-settings']['header']
			);

		return true;
	}


	protected function count( $items ) {

		$count = 0;
		if ( is_array( $items ) ) {

			foreach ( $items as $item ) {

				if ( ! isset( $item['count_calc'] ) || $item['count_calc'] ) {

					$count ++;
				}
			}
		}

		return $count;
	}


	/**
	 * get current theme header data and cache
	 *
	 * @param string $data_type theme header index
	 *
	 * @see \WP_Theme::__isset $properties is valid value this var
	 *
	 * @return string|bool string on success otherwise false
	 */
	protected function get_wp_theme_data( $data_type ) {

		if ( ! $this->theme_header ) {
			$theme_data = wp_get_theme( get_template() );

			if ( $theme_data instanceof WP_Theme ) {
				$this->theme_header = $theme_data;
			}
		}

		if ( isset( $this->theme_header->$data_type ) ) {
			return $this->theme_header->$data_type;
		}

		return false;
	}


	/**
	 * Retrieve information about the blog
	 *
	 * @param string $data_type
	 *
	 * @see get_bloginfo
	 *
	 * @return string string values, might be empty
	 */
	protected function get_bloginfo_data( $data_type ) {

		return get_bloginfo( $data_type, 'display' );
	}


	/**
	 * Sort report config array boxes by position value
	 *
	 * @param $boxes
	 */
	protected function sort_config( &$boxes ) {

		uasort( $boxes, array( $this, '_sort_box_by_position' ) );
	}


	/**
	 * Retrieve information about the wordpress
	 *
	 * @param string $data_type
	 *
	 * @return string string values, might be empty
	 */
	protected function get_wp_data( $data_type ) {

		$result = null;

		switch ( $data_type ) {

			case 'version':
				include ABSPATH . WPINC . '/version.php'; // include an unmodified $wp_version
				$result = $GLOBALS['wp_version'];
				break;

			case 'memory_limit':

				$wp_memory_limit  = WP_MEMORY_LIMIT;
				$php_memory_limit = get_cfg_var( 'memory_limit' );

				if ( bf_is_ini_value_changeable( 'memory_limit' ) &&
				     wp_convert_hr_to_bytes( $wp_memory_limit ) < wp_convert_hr_to_bytes( $php_memory_limit )
				) {
					$wp_memory_limit = $php_memory_limit;
				}

				$result = $wp_memory_limit . ', ' . WP_MAX_MEMORY_LIMIT;
				break;

			case 'debug_mode':

				$result = WP_DEBUG;
				break;

			case 'cache_exists':

				$cache_plugins = array(
					'w3-total-cache/w3-total-cache.php'   => 'W3 Total Cache',
					'wp-super-cache/wp-cache.php'         => 'WP Super Cache',
					'wp-rocket/wp-rocket.php'             => 'WP Rocket',
					'wp-fastest-cache/wpFastestCache.php' => 'WP Fastest Cache',
					'cache-enabler/cache-enabler.php'     => 'Cache Enabler - WordPress Cache',
					'wp-ffpc/wp-ffpc.php'                 => 'WP FFPC',
				);

				/**
				 * TODO: read plugin name from plugin file
				 * TODO: check caching status of each plugin
				 * TODO: check object-cache.php file
				 */
				$active_cache_plugin = false;
				foreach ( $cache_plugins as $cache_plugin => $plugin_name ) {
					if ( is_plugin_active( $cache_plugin ) ) {
						$active_cache_plugin = $plugin_name;
						break;
					}
				}

				$result = $active_cache_plugin ? $active_cache_plugin : 'no cache plugin was found';
				break;
			default:
				$prefix   = 'wp_';
				$function = $prefix . $data_type;


				if ( is_callable( $function ) ) {

					$params = func_get_args();
					$result = call_user_func_array( $function, array_slice( $params, 1 ) );
				}
		}

		return $result;
	}


	/**
	 * Call custom function and return results
	 *
	 * @param string $function_name
	 *
	 * @return string|bool string on success
	 */
	protected function get_func_data( $function_name ) {

		if ( is_callable( $function_name ) ) {
			return call_user_func( $function_name );
		}

		return false;
	}


	/**
	 * Translate data to valid printable output string
	 *
	 * @param mixed  $result
	 * @param string $data_type
	 * @param string $context raw or display context is available
	 *
	 * @return string|null string on success
	 */
	private function sanitize_item( $result, $data_type, $context = 'raw' ) {

		static $format_size = array(
			'max_upload_size',
			'memory_limit',
			'post_max_size'
		);
		$return = null;

		switch ( $context ) {

			case 'display':

				if ( is_bool( $result ) ) {

					$return = $result ? __( 'Enabled', 'better-studio' ) : __( 'Disabled', 'better-studio' );
				} elseif ( is_string( $result ) || is_int( $result ) ) {

					if ( in_array( $data_type, $format_size ) ) {
						$return = size_format( is_string( $result ) ? $this->convert_hr_to_bytes( $result ) : $result );

					} elseif ( is_int( $result ) ) {
						$return = number_format_i18n( $result );
					} else {

						$return = $result;
					}
				}

				break;


			case 'raw':

			default:

				if ( is_bool( $result ) ) {

					return $result;
				} elseif ( is_string( $result ) || is_int( $result ) ) {

					if ( in_array( $data_type, $format_size ) ) {
						$result = is_string( $result ) ? $this->convert_hr_to_bytes( $result ) : $result;
					}

					return $result;
				}
		}


		return $return;
	}


	/***
	 * Get php.ini values
	 *
	 * @param string $data_type init_get input
	 *
	 * @return string|null string on success, empty string or null on failure or for null values.
	 */
	protected function get_ini_data( $data_type ) {

		$current_value = ini_get( $data_type );
		$org_value     = get_cfg_var( $data_type );

		if ( $org_value === false ) {
			return $current_value;
		}

		if ( $current_value === $org_value ) {
			return $current_value;
		}

		return $org_value . ', ' . $current_value;
	}


	/**
	 * return raw html stored in description index
	 *
	 * @return string
	 */
	protected function get_raw_data() {

		if ( isset( $this->active_item['description'] ) ) {
			return $this->active_item['description'];
		}

		return '';
	}


	/**
	 * Get information about serve software
	 *
	 * @param string $data_type
	 *
	 * @global wpdb  $wpdb
	 *
	 * @return string|void string on success
	 */
	protected function get_server_data( $data_type ) {

		global $wpdb;

		$result = null;

		switch ( $data_type ) {

			case 'web_server':
			case 'software':

				$result = $_SERVER['SERVER_SOFTWARE'];
				break;

			case 'php_version':

				$result = phpversion();
				break;

			case 'mysql_version':

				$result = $wpdb->db_version();
				break;

			case 'suhosin_installed':

				$result = extension_loaded( 'suhosin' );
				break;

			case 'zip_archive':

				/** @noinspection SpellCheckingInspection */
				$result = class_exists( 'ZipArchive' ) || function_exists( 'gzopen' );
				break;

			case 'remote_get':
			case 'remote_post':

				$test_result = get_transient( 'bs_remote_test' );
				$result      = ! empty( $test_result[ $data_type ] );
				break;
		}

		return $result;
	}


	/**
	 *
	 * compare  ['box-settings']['position'] index to sort
	 *
	 * @see sort_config
	 *
	 * @param array $box_a
	 * @param array $box_b
	 *
	 * @return int
	 */
	protected function _sort_box_by_position( $box_a, $box_b ) {

		$position_a = isset( $box_a['box-settings']['position'] ) ? (int) $box_a['box-settings']['position'] : 10;
		$position_b = isset( $box_b['box-settings']['position'] ) ? (int) $box_b['box-settings']['position'] : 10;

		return $position_a > $position_b;
	}


	/**
	 * Test remote request working
	 *
	 * @return array {
	 *
	 * @type int  $last_checked last time remote status checked (timestamp)
	 * @type bool $remote_get   is remote get active?
	 * @type bool $remote_post  is remote post active?
	 * }
	 */
	protected function test_http_remote() {

		$prev_status = get_transient( 'bs_remote_test' );
		if ( ! is_array( $prev_status ) ) {
			$prev_status                 = array();
			$prev_status['last_checked'] = time();
			$skip_test                   = false;
		} else {
			$skip_test = $this->check_remote_duration > ( time() - $prev_status['last_checked'] );
		}

		if ( $skip_test ) {
			return $prev_status;
		}

		$empty_array = wp_json_encode( array() );
		$api_url     = 'http://api.wordpress.org/plugins/update-check/1.1/';
		$options     = array(
			'body' => array(
				'plugins'      => $empty_array,
				'translations' => $empty_array,
				'locale'       => $empty_array,
				'all'          => wp_json_encode( true ),
			),
		);

		$new_status                 = array();
		$new_status['last_checked'] = time();

		$raw_response             = wp_remote_post( $api_url, $options );
		$new_status['remote_get'] = ! is_wp_error( $raw_response ) && wp_remote_retrieve_response_code( $raw_response ) == 200;

		$raw_response              = wp_remote_get( $api_url, $options );
		$new_status['remote_post'] = ! is_wp_error( $raw_response ) && wp_remote_retrieve_response_code( $raw_response ) == 200;


		set_transient( 'bs_remote_test', $new_status, $this->check_remote_duration );

		return $new_status;
	}


	protected function convert_hr_to_bytes( $string ) {

		$string = explode( ',', $string );
		$string = $string[0];

		return wp_convert_hr_to_bytes( $string );
	}


	/**
	 * Generate help section HTML
	 *
	 * @param array $data description array generated by {@see get_item_description}
	 */
	protected function help_section_html( &$data ) {

		$raw_data = &$data[0];
		if ( ! empty( $this->active_item['help'] ) ) { ?>
			<div class="bs-pages-help-wrapper">

				<?php

				$icon_classes         = array( 'fa' );
				$icon_wrapper_classes = array( 'bs-pages-help' );

				if ( ! empty( $this->item_settings['standard_value'] ) ) {

					$std_value     = $this->item_settings['standard_value'];
					$std_value     = is_string( $std_value ) ? $this->convert_hr_to_bytes( $std_value ) : (int) $std_value;
					$current_value = is_string( $raw_data ) ? $this->convert_hr_to_bytes( $raw_data ) : (int) $raw_data;
					$min_value     = 0;

					if ( isset( $this->item_settings['minimum_value'] ) ) {

						$min_value = $this->item_settings['minimum_value'];
						$min_value = is_string( $min_value ) ? $this->convert_hr_to_bytes( $min_value ) : (int) $min_value;
					}

					if ( $min_value && $current_value < $min_value ) {

						$icon_wrapper_classes[] = 'danger';
						$icon_classes[]         = 'fa-bolt';
					} elseif ( $current_value < $std_value ) {

						$icon_wrapper_classes[] = 'warning';
						$icon_classes[]         = 'fa-exclamation';
					} else {

						$icon_wrapper_classes[] = 'success';
						$icon_classes[]         = 'fa-check';
					}

				} elseif ( is_bool( $raw_data ) && empty( $this->item_settings['hide_mark'] ) ) {

					$success_status = isset( $this->item_settings['default'] ) ? $this->item_settings['default'] : 'enabled';
					if ( ( $success_status === 'enabled' && $raw_data )
					     ||
					     ( $success_status === 'disable' && ! $raw_data )
					) {

						$icon_classes[]         = 'fa-check';
						$icon_wrapper_classes[] = 'success';
					} else {

						$icon_wrapper_classes[] = 'warning';
						$icon_classes[]         = 'fa-exclamation';
					}

				} else {

					$icon_classes[] = 'fa-question';
				}

				?>


				<div class="<?php echo esc_attr( implode( ' ', $icon_wrapper_classes ) ); ?>">
					<i class="<?php echo esc_html( implode( ' ', $icon_classes ) ); ?>"></i>
				</div>

				<div class="bs-pages-help-description">
					<?php
					if ( is_string( $this->active_item['help'] ) )
						echo $this->active_item['help'] // escaped before
					?>
				</div>
			</div>
		<?php }
	}


	/**
	 * Generate help section HTML
	 *
	 * @param array $data description array generated by {@see get_item_description}
	 */
	protected function item_section_html( &$data ) {

		?>

		<span class="bs-item-description">
		<?php


		if ( isset( $this->active_item['before_description'] ) ) {
			echo $this->active_item['before_description']; // escaped before
		}

		echo $data[1]; // escaped before

		if ( isset( $this->active_item['after_description'] ) ) {
			echo $this->active_item['after_description']; // escaped before
		}
		?>
		</span>
		<?php
	}
}
libs/better-framework/product-pages/report/index.php000064400000000006151214002510016650 0ustar00<?php
libs/better-framework/product-pages/report/assets/js/index.php000064400000000006151214002510020566 0ustar00<?php
libs/better-framework/product-pages/report/assets/js/bs-system-report.js000064400000006017151214002510022553 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */


(function ($) {


    var BS_Product_System_Status = function () {

        this.init();
        this.copy();
        this.textarea_click();
    }


    BS_Product_System_Status.prototype = {

        init: function () {

            var self = this;

            $("#bs-get-system-report").on('click', function (e) {
                e.preventDefault();
                var animation_speed = 300,
                    $contianer = $("#bs-system-container");

                //hide get system report section
                $(this)
                    .closest('.bs-pages-list-item')
                    .slideUp(animation_speed);

                //remove hide class of parent element and display system report
                $contianer
                    .closest('.bs-pages-list-item')
                    .removeClass('bs-item-hide');
                $contianer
                    .slideDown(animation_speed);

                //automatic copy data to clipboard
                $contianer
                    .delay(animation_speed)
                    .queue(function (n) {
                        self._select_all();
                        n();
                    })
            });
        },

        copy: function () {

            var self = this;
            $("#bs-copy-system-report").on('click', function (e) {
                e.preventDefault();

                self._select_all();
                document.execCommand('copy');

            });
        },
        textarea_click: function () {
            var self = this;
            $("#bs-system-container ").on('click', '.bs-output', function () {
                self._select_all();
            });
        },
        _select_all: function () {

            $("#bs-system-container textarea").focus().select();
        },
        _get_ajax_params: function (params) {
            var default_obj = {},
                default_params = $("#bs-pages-hidden-params").serializeArray();

            if (default_params) {
                for (var i = 0; i < default_params.length; i++) {
                    default_obj[ default_params[ i ].name ] = default_params[ i ].value;
                }
            }

            return $.extend(default_obj, params);
        },
    }

    $(document).ready(function () {

        new BS_Product_System_Status();
    })
})(jQuery)libs/better-framework/product-pages/report/assets/css/index.php000064400000000006151214002510020742 0ustar00<?php
libs/better-framework/product-pages/report/assets/css/bs-system-report.css000064400000001346151214002510023103 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */
libs/better-framework/product-pages/report/assets/index.php000064400000000006151214002510020152 0ustar00<?php
libs/better-framework/product-pages/init.php000064400000002640151214002510015177 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

// todo add support for using product page in multiple product!
// Ex: welcome page url is admin.php?page=bs-product-pages-welcome
// and we cannot detect which product is active

// todo refactor product pages for new home

define( 'BF_PRODUCT_PAGES_URI', BF_URI . 'product-pages/' );
define( 'BF_PRODUCT_PAGES_PATH', BF_PATH . 'product-pages/' );

include BF_PRODUCT_PAGES_PATH . 'core/class-bf-product-pages-base.php';

include BF_PRODUCT_PAGES_PATH . 'core/class-bf-product-item.php';

include BF_PRODUCT_PAGES_PATH . 'core/class-bf-product-multi-step-item.php';

include BF_PRODUCT_PAGES_PATH . 'core/class-bf-product-pages.php';

include BF_PRODUCT_PAGES_PATH . 'core/functions.php';

libs/better-framework/product-pages/index.php000064400000000032151214002510015334 0ustar00<?php
// Silent is golden!libs/better-framework/product-pages/welcome/functions.php000064400000011236151214002510017700 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Callback: enqueue product registration static files in welcome page.
 * action  :  admin_enqueue_scripts
 */
function bf_welcome_admin_enqueue() {

	if ( bf_is_product_page( 'welcome' ) ) {

		bf_register_product_enqueue_scripts();
	}
}

add_action( 'admin_enqueue_scripts', 'bf_welcome_admin_enqueue' );


/**
 * Enqueue product registration static file dependencies.
 */
function bf_register_product_enqueue_scripts() {

	wp_enqueue_script( 'bs-register-product', BF_Product_Pages::get_url( 'welcome/assets/js/register-product.js' ), array(), Better_Framework()->version );

	wp_localize_script(
		'bs-register-product',
		'bs_register_product',
		array(
			'messages' => array(
				'success' => wp_kses( __( '<b>Congratulations, your license is now registered.</b>', 'better-studio' ), bf_trans_allowed_html() ),
			),
		)
	);
} // bf_register_product_enqueue_scripts


/**
 * Retrieve product registration information
 *
 * @return bool|array array of data on success or false on failure. array data always have this indexes {
 * @type int    $last_check    last time status was updated timestamp.
 * @type string $purchase_code envato marketplace product code
 * }
 * @see \bf_bs_register_product_params
 */
function bf_register_product_get_info() {

	/**
	 * @see \BetterFramework_Oculus::$auth
	 */
	$auth        = apply_filters( 'better-framework/product-pages/register-product/auth', array() );
	$option_name = sprintf( '%s-register-info', $auth['item_id'] );

	return array_merge( (array) $auth, (array) get_option( $option_name, array() ) );
} // bf_register_product_get_info

function bf_register_product_clear_info( $item_id = 0 ) {

	if ( ! $item_id ) {
		$auth    = apply_filters( 'better-framework/product-pages/register-product/auth', array() );
		$item_id = $auth['item_id'];
	}

	$option_name = sprintf( '%s-register-info', $item_id );

	return delete_option( $option_name );
}

/**
 * Array of data about product registration
 *
 * @param array $data
 *
 * @return bool true when data updated or false otherwise.
 */
function bf_register_product_set_info( $data ) {

	/**
	 * @see \BetterFramework_Oculus::$auth
	 */
	$auth        = apply_filters( 'better-framework/product-pages/register-product/auth', array() );
	$option_name = sprintf( '%s-register-info', $auth['item_id'] );
	$data        = bf_merge_args( $data, array(
		'last_check'    => time(),
		'purchase_code' => $auth['purchase_code'],
	) );

	// Clear plugins list cache
	delete_option( 'bf-plugins-config' );

	return update_option( $option_name, $data );
} // bf_register_product_set_info

/**
 * check product activated?
 *
 * @return bool
 */
function bf_is_product_registered() {

	$auth        = apply_filters( 'better-framework/product-pages/register-product/auth', array() );
	$option_name = sprintf( '%s-register-info', $auth['item_id'] );
	$options     = get_option( $option_name );

	return ! empty( $options['purchase_code'] );
}

if ( ! empty( $_GET['bs-clear-registered-product'] ) ) {
	if ( empty( $_GET['bs-reset-token'] ) ) {
		$link = add_query_arg( array(
			'bs-reset-token' => wp_create_nonce( 'bs-reset-registered-' . $_GET['bs-clear-registered-product'] )
		) );
		wp_die( sprintf( __( 'Are you sure to deregister product <strong>%s</strong> in this WordPress installation?<br/> This can disable auto update and other premium features of product.<br/><br/> <a href="%s" class="button" style="color: #fff;background-color: #0085ba;border-color:#0073aa #006799 #006799;">Yes, Deregister</a> &nbsp; <a href="%s" class="button">No</a> ', 'better-studio' ), $_GET['bs-clear-registered-product'], esc_url( $link ), esc_url( get_dashboard_url() ) ) );
	} else {
		if ( wp_verify_nonce( $_GET['bs-reset-token'], 'bs-reset-registered-' . $_GET['bs-clear-registered-product'] ) ) {
			bf_register_product_clear_info( $_GET['bs-clear-registered-product'] );

			wp_redirect( add_query_arg( array(
				'bs-reset-token'              => false,
				'bs-clear-registered-product' => false,
			) ) );
			exit;
		}
	}
}
libs/better-framework/product-pages/welcome/index.php000064400000000006151214002510016770 0ustar00<?php
libs/better-framework/product-pages/welcome/assets/js/register-product.js000064400000011700151214002510022731 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */

(function ($) {
    var bs_product_register = function () {
        this.init();
    }

    bs_product_register.prototype = {
        init: function () {
            var self = this;
            jQuery(document).ready(function ($) {
                self.attach_register_btn_event();
                self.attach_submit_event();
            });
        },
        attach_register_btn_event: function () {
            var self = this;
            $(document).on('click', '#bs-login-register-btn', function (e) {
                e.preventDefault();
                self.attach_auto_check_license_event();
                window.open(this.href);
            });
        },
        bind_input_mask: function () {
            if ($.fn.inputmask) {
                $("#bs-purchase-code").inputmask({
                    mask: "*{8}\-*{4}\-*{4}\-*{4}\-*{12}"
                });
            }
        },
        attach_submit_event: function () {

            var self = this;
            $("#bs-register-product-form").on('submit', function (e) {
                e.preventDefault();
                self.register_product();

                return false;
            });
        },
        ajax_params: function (params) {
            var default_obj = {},
                default_params = $("#bs-pages-hidden-params").serializeArray();

            if (default_params) {
                for (var i = 0; i < default_params.length; i++) {
                    default_obj[ default_params[ i ].name ] = default_params[ i ].value;
                }
            }

            return $.extend(default_obj, params);
        },

        ajax: function (params, success_callback, always_callback) {

            params = this.ajax_params(params);

            $.ajax({
                 url: ajaxurl,
                 type: 'POST',
                 dataType: 'json',
                 data: $.extend(
                     {page_id: $("#bs-pages-current-id").val()},
                     params
                 )
             })
             .done(success_callback)
             .always(function () {
                 if (always_callback)
                     always_callback()
             });
        },
        register_product: function () {
            var $form = $("#bs-register-product-form"),
                self = this,
                $wrapper = $form.closest('.bs-pages-box-wrapper'),
                data = $form.serializeArray(),
                loadingClass = 'bs-loading-wrapper',
                ajax_params = {bs_pages_action: 'register'};

            if ($wrapper.hasClass(loadingClass))
                return false;

            for (var i = 0; i < data.length; i++) {
                ajax_params[ data[ i ].name ] = data[ i ].value;
            }

            $wrapper.addClass(loadingClass);
            this.ajax(ajax_params, function (r) {
                var stat = r.status || r[ 'error-code' ], m = bs_register_product.messages;

                $form.closest('.bs-pages-box-description')
                     .find('.bs-product-desc')
                     .html('<p>' + (function () {
                             if (typeof m[ stat ] === 'string')
                                 return m[ stat ];

                             if (typeof r[ 'error-message' ] === 'string')
                                 return r[ 'error-message' ];
                             return '';
                         })()      + '</p>');

                if (stat === 'success' || stat === 'add-to-account')
                    $form.slideUp();

                if (stat === 'add-to-account') {
                    self.attach_auto_check_license_event();
                } else {
                    self.remove_auto_check_license_event();
                }
            }, function () {
                $wrapper.removeClass(loadingClass)
            });

            return true;
        },
        attach_auto_check_license_event: function () {
            var self = this;
            $(window).on('focus.bs-reg-product', function () {
                self.register_product();
            });
        },
        remove_auto_check_license_event: function () {
            $(window).off('focus.bs-reg-product');
            this.register_window = false;
        }
    };

    new bs_product_register();
})(jQuery);libs/better-framework/product-pages/welcome/assets/index.php000064400000000006151214002510020272 0ustar00<?php
libs/better-framework/product-pages/welcome/class-bf-product-welcome.php000064400000007712151214002510022475 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Class BF_Product_Welcome
 */
class BF_Product_Welcome extends BF_Product_Item {

	public $id = 'welcome';

	/**
	 * Store ajax params list.
	 *
	 * @var array
	 */
	protected $params;


	public function render_content( $item_data ) {

		if ( ! empty( $item_data['include_file'] ) && file_exists( $item_data['include_file'] ) ) {
			include $item_data['include_file'];
		}
	}


	public function ajax_request( $params ) {

		if ( empty( $params['bs_pages_action'] ) ) {
			return;
		}

		$this->params = $params;

		try {
			switch ( $params['bs_pages_action'] ) {

				case 'register':

					if ( isset( $params['bs-purchase-code'] ) && isset( $params['bs-register-token'] ) ) {

						//verify register product token

						if ( wp_create_nonce( 'bs-register-product' ) !== $params['bs-register-token'] ) {

							throw new Exception( 'invalid request.' );
						}

						$this->handle_reponse(
							$this->api_request( 'register-product', array(), array( 'purchase_code' => $this->params['bs-purchase-code'] ) )
						);
					}


					break;
			}
		} catch( Exception $e ) {

			wp_send_json( array( 'status' => 'error', 'error-message' => $e->getMessage() ) );

		}

	}


	/**
	 * @param array $response
	 *
	 * @throws Exception
	 */
	protected function handle_reponse( $response ) {

		if ( empty( $response ) ) {
			throw new Exception( __( 'unknown error occurred!', 'publisher' ) );
		}

		$purchase_code = $this->params['bs-purchase-code'];

		if ( is_wp_error( $response ) ) {

			$error_code = $response->get_error_code();

			if ( 'add-to-account' === $error_code || 'add-domain' == $error_code ) {

				$auth      = apply_filters( 'better-framework/product-pages/register-product/auth', array() );
				$uri       = site_url();
				$item_id   = $auth['item_id'];
				$bs_action = 'register-product';

				$link = add_query_arg( compact( 'purchase_code', 'uri', 'item_id', 'bs_action' ), 'http://betterstudio.com/account/apply-new-purchase' );

				if ( 'add-domain' == $error_code ) {

					$response = array(
						'error-message' => wp_kses( sprintf( __( 'Your current domain name was not added to this purchase code,<br/> <b>Please add this domain name to your license code</b> by clicking on the following button <br><br> <a href="%s" class="bf-btn-primary bs-pages-primary-btn" target="_blank" id="bs-login-register-btn">Add new domain</a>', 'publisher' ), $link ), bf_trans_allowed_html() ),
						'error-code'    => 'add-to-account',
						'result'        => 'error',
					);
				} else {

					$response = array(
						'error-message' => wp_kses( sprintf( __( 'This looks like <b>a new purchase code that hasn&#x2019;t been added to BetterStudio account yet</b>. Login to existing account or register new one to continue. <br><br> <a href="%s" class="bf-btn-primary bs-pages-primary-btn" target="_blank" id="bs-login-register-btn">Login or Register</a>', 'publisher' ), $link ), bf_trans_allowed_html() ),
						'error-code'    => 'add-to-account',
						'result'        => 'error',
					);
				}

			} else {

				throw new Exception( $response->get_error_message() );
			}
		}

		if ( isset( $response->status ) ) {

			$status = $response->status;
			bf_register_product_set_info( compact( 'purchase_code', 'status' ) );
		}

		wp_send_json( $response );
	}
}
libs/better-framework/product-pages/assets/js/mustache.js000064400000045654151214002510017624 0ustar00/*!
 * mustache.js - Logic-less {{mustache}} templates with JavaScript
 * http://github.com/janl/mustache.js
 */

/*global define: false Mustache: true*/

(function defineMustache (global, factory) {
  if (typeof exports === 'object' && exports && typeof exports.nodeName !== 'string') {
    factory(exports); // CommonJS
  } else if (typeof define === 'function' && define.amd) {
    define(['exports'], factory); // AMD
  } else {
    global.Mustache = {};
    factory(global.Mustache); // script, wsh, asp
  }
}(this, function mustacheFactory (mustache) {

  var objectToString = Object.prototype.toString;
  var isArray = Array.isArray || function isArrayPolyfill (object) {
    return objectToString.call(object) === '[object Array]';
  };

  function isFunction (object) {
    return typeof object === 'function';
  }

  /**
   * More correct typeof string handling array
   * which normally returns typeof 'object'
   */
  function typeStr (obj) {
    return isArray(obj) ? 'array' : typeof obj;
  }

  function escapeRegExp (string) {
    return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&');
  }

  /**
   * Null safe way of checking whether or not an object,
   * including its prototype, has a given property
   */
  function hasProperty (obj, propName) {
    return obj != null && typeof obj === 'object' && (propName in obj);
  }

  // Workaround for https://issues.apache.org/jira/browse/COUCHDB-577
  // See https://github.com/janl/mustache.js/issues/189
  var regExpTest = RegExp.prototype.test;
  function testRegExp (re, string) {
    return regExpTest.call(re, string);
  }

  var nonSpaceRe = /\S/;
  function isWhitespace (string) {
    return !testRegExp(nonSpaceRe, string);
  }

  var entityMap = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#39;',
    '/': '&#x2F;',
    '`': '&#x60;',
    '=': '&#x3D;'
  };

  function escapeHtml (string) {
    return String(string).replace(/[&<>"'`=\/]/g, function fromEntityMap (s) {
      return entityMap[s];
    });
  }

  var whiteRe = /\s*/;
  var spaceRe = /\s+/;
  var equalsRe = /\s*=/;
  var curlyRe = /\s*\}/;
  var tagRe = /#|\^|\/|>|\{|&|=|!/;

  /**
   * Breaks up the given `template` string into a tree of tokens. If the `tags`
   * argument is given here it must be an array with two string values: the
   * opening and closing tags used in the template (e.g. [ "<%", "%>" ]). Of
   * course, the default is to use mustaches (i.e. mustache.tags).
   *
   * A token is an array with at least 4 elements. The first element is the
   * mustache symbol that was used inside the tag, e.g. "#" or "&". If the tag
   * did not contain a symbol (i.e. {{myValue}}) this element is "name". For
   * all text that appears outside a symbol this element is "text".
   *
   * The second element of a token is its "value". For mustache tags this is
   * whatever else was inside the tag besides the opening symbol. For text tokens
   * this is the text itself.
   *
   * The third and fourth elements of the token are the start and end indices,
   * respectively, of the token in the original template.
   *
   * Tokens that are the root node of a subtree contain two more elements: 1) an
   * array of tokens in the subtree and 2) the index in the original template at
   * which the closing tag for that section begins.
   */
  function parseTemplate (template, tags) {
    if (!template)
      return [];

    var sections = [];     // Stack to hold section tokens
    var tokens = [];       // Buffer to hold the tokens
    var spaces = [];       // Indices of whitespace tokens on the current line
    var hasTag = false;    // Is there a {{tag}} on the current line?
    var nonSpace = false;  // Is there a non-space char on the current line?

    // Strips all whitespace tokens array for the current line
    // if there was a {{#tag}} on it and otherwise only space.
    function stripSpace () {
      if (hasTag && !nonSpace) {
        while (spaces.length)
          delete tokens[spaces.pop()];
      } else {
        spaces = [];
      }

      hasTag = false;
      nonSpace = false;
    }

    var openingTagRe, closingTagRe, closingCurlyRe;
    function compileTags (tagsToCompile) {
      if (typeof tagsToCompile === 'string')
        tagsToCompile = tagsToCompile.split(spaceRe, 2);

      if (!isArray(tagsToCompile) || tagsToCompile.length !== 2)
        throw new Error('Invalid tags: ' + tagsToCompile);

      openingTagRe = new RegExp(escapeRegExp(tagsToCompile[0]) + '\\s*');
      closingTagRe = new RegExp('\\s*' + escapeRegExp(tagsToCompile[1]));
      closingCurlyRe = new RegExp('\\s*' + escapeRegExp('}' + tagsToCompile[1]));
    }

    compileTags(tags || mustache.tags);

    var scanner = new Scanner(template);

    var start, type, value, chr, token, openSection;
    while (!scanner.eos()) {
      start = scanner.pos;

      // Match any text between tags.
      value = scanner.scanUntil(openingTagRe);

      if (value) {
        for (var i = 0, valueLength = value.length; i < valueLength; ++i) {
          chr = value.charAt(i);

          if (isWhitespace(chr)) {
            spaces.push(tokens.length);
          } else {
            nonSpace = true;
          }

          tokens.push([ 'text', chr, start, start + 1 ]);
          start += 1;

          // Check for whitespace on the current line.
          if (chr === '\n')
            stripSpace();
        }
      }

      // Match the opening tag.
      if (!scanner.scan(openingTagRe))
        break;

      hasTag = true;

      // Get the tag type.
      type = scanner.scan(tagRe) || 'name';
      scanner.scan(whiteRe);

      // Get the tag value.
      if (type === '=') {
        value = scanner.scanUntil(equalsRe);
        scanner.scan(equalsRe);
        scanner.scanUntil(closingTagRe);
      } else if (type === '{') {
        value = scanner.scanUntil(closingCurlyRe);
        scanner.scan(curlyRe);
        scanner.scanUntil(closingTagRe);
        type = '&';
      } else {
        value = scanner.scanUntil(closingTagRe);
      }

      // Match the closing tag.
      if (!scanner.scan(closingTagRe))
        throw new Error('Unclosed tag at ' + scanner.pos);

      token = [ type, value, start, scanner.pos ];
      tokens.push(token);

      if (type === '#' || type === '^') {
        sections.push(token);
      } else if (type === '/') {
        // Check section nesting.
        openSection = sections.pop();

        if (!openSection)
          throw new Error('Unopened section "' + value + '" at ' + start);

        if (openSection[1] !== value)
          throw new Error('Unclosed section "' + openSection[1] + '" at ' + start);
      } else if (type === 'name' || type === '{' || type === '&') {
        nonSpace = true;
      } else if (type === '=') {
        // Set the tags for the next time around.
        compileTags(value);
      }
    }

    // Make sure there are no open sections when we're done.
    openSection = sections.pop();

    if (openSection)
      throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos);

    return nestTokens(squashTokens(tokens));
  }

  /**
   * Combines the values of consecutive text tokens in the given `tokens` array
   * to a single token.
   */
  function squashTokens (tokens) {
    var squashedTokens = [];

    var token, lastToken;
    for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
      token = tokens[i];

      if (token) {
        if (token[0] === 'text' && lastToken && lastToken[0] === 'text') {
          lastToken[1] += token[1];
          lastToken[3] = token[3];
        } else {
          squashedTokens.push(token);
          lastToken = token;
        }
      }
    }

    return squashedTokens;
  }

  /**
   * Forms the given array of `tokens` into a nested tree structure where
   * tokens that represent a section have two additional items: 1) an array of
   * all tokens that appear in that section and 2) the index in the original
   * template that represents the end of that section.
   */
  function nestTokens (tokens) {
    var nestedTokens = [];
    var collector = nestedTokens;
    var sections = [];

    var token, section;
    for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
      token = tokens[i];

      switch (token[0]) {
        case '#':
        case '^':
          collector.push(token);
          sections.push(token);
          collector = token[4] = [];
          break;
        case '/':
          section = sections.pop();
          section[5] = token[2];
          collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens;
          break;
        default:
          collector.push(token);
      }
    }

    return nestedTokens;
  }

  /**
   * A simple string scanner that is used by the template parser to find
   * tokens in template strings.
   */
  function Scanner (string) {
    this.string = string;
    this.tail = string;
    this.pos = 0;
  }

  /**
   * Returns `true` if the tail is empty (end of string).
   */
  Scanner.prototype.eos = function eos () {
    return this.tail === '';
  };

  /**
   * Tries to match the given regular expression at the current position.
   * Returns the matched text if it can match, the empty string otherwise.
   */
  Scanner.prototype.scan = function scan (re) {
    var match = this.tail.match(re);

    if (!match || match.index !== 0)
      return '';

    var string = match[0];

    this.tail = this.tail.substring(string.length);
    this.pos += string.length;

    return string;
  };

  /**
   * Skips all text until the given regular expression can be matched. Returns
   * the skipped string, which is the entire tail if no match can be made.
   */
  Scanner.prototype.scanUntil = function scanUntil (re) {
    var index = this.tail.search(re), match;

    switch (index) {
      case -1:
        match = this.tail;
        this.tail = '';
        break;
      case 0:
        match = '';
        break;
      default:
        match = this.tail.substring(0, index);
        this.tail = this.tail.substring(index);
    }

    this.pos += match.length;

    return match;
  };

  /**
   * Represents a rendering context by wrapping a view object and
   * maintaining a reference to the parent context.
   */
  function Context (view, parentContext) {
    this.view = view;
    this.cache = { '.': this.view };
    this.parent = parentContext;
  }

  /**
   * Creates a new context using the given view with this context
   * as the parent.
   */
  Context.prototype.push = function push (view) {
    return new Context(view, this);
  };

  /**
   * Returns the value of the given name in this context, traversing
   * up the context hierarchy if the value is absent in this context's view.
   */
  Context.prototype.lookup = function lookup (name) {
    var cache = this.cache;

    var value;
    if (cache.hasOwnProperty(name)) {
      value = cache[name];
    } else {
      var context = this, names, index, lookupHit = false;

      while (context) {
        if (name.indexOf('.') > 0) {
          value = context.view;
          names = name.split('.');
          index = 0;

          /**
           * Using the dot notion path in `name`, we descend through the
           * nested objects.
           *
           * To be certain that the lookup has been successful, we have to
           * check if the last object in the path actually has the property
           * we are looking for. We store the result in `lookupHit`.
           *
           * This is specially necessary for when the value has been set to
           * `undefined` and we want to avoid looking up parent contexts.
           **/
          while (value != null && index < names.length) {
            if (index === names.length - 1)
              lookupHit = hasProperty(value, names[index]);

            value = value[names[index++]];
          }
        } else {
          value = context.view[name];
          lookupHit = hasProperty(context.view, name);
        }

        if (lookupHit)
          break;

        context = context.parent;
      }

      cache[name] = value;
    }

    if (isFunction(value))
      value = value.call(this.view);

    return value;
  };

  /**
   * A Writer knows how to take a stream of tokens and render them to a
   * string, given a context. It also maintains a cache of templates to
   * avoid the need to parse the same template twice.
   */
  function Writer () {
    this.cache = {};
  }

  /**
   * Clears all cached templates in this writer.
   */
  Writer.prototype.clearCache = function clearCache () {
    this.cache = {};
  };

  /**
   * Parses and caches the given `template` and returns the array of tokens
   * that is generated from the parse.
   */
  Writer.prototype.parse = function parse (template, tags) {
    var cache = this.cache;
    var tokens = cache[template];

    if (tokens == null)
      tokens = cache[template] = parseTemplate(template, tags);

    return tokens;
  };

  /**
   * High-level method that is used to render the given `template` with
   * the given `view`.
   *
   * The optional `partials` argument may be an object that contains the
   * names and templates of partials that are used in the template. It may
   * also be a function that is used to load partial templates on the fly
   * that takes a single argument: the name of the partial.
   */
  Writer.prototype.render = function render (template, view, partials) {
    var tokens = this.parse(template);
    var context = (view instanceof Context) ? view : new Context(view);
    return this.renderTokens(tokens, context, partials, template);
  };

  /**
   * Low-level method that renders the given array of `tokens` using
   * the given `context` and `partials`.
   *
   * Note: The `originalTemplate` is only ever used to extract the portion
   * of the original template that was contained in a higher-order section.
   * If the template doesn't use higher-order sections, this argument may
   * be omitted.
   */
  Writer.prototype.renderTokens = function renderTokens (tokens, context, partials, originalTemplate) {
    var buffer = '';

    var token, symbol, value;
    for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
      value = undefined;
      token = tokens[i];
      symbol = token[0];

      if (symbol === '#') value = this.renderSection(token, context, partials, originalTemplate);
      else if (symbol === '^') value = this.renderInverted(token, context, partials, originalTemplate);
      else if (symbol === '>') value = this.renderPartial(token, context, partials, originalTemplate);
      else if (symbol === '&') value = this.unescapedValue(token, context);
      else if (symbol === 'name') value = this.escapedValue(token, context);
      else if (symbol === 'text') value = this.rawValue(token);

      if (value !== undefined)
        buffer += value;
    }

    return buffer;
  };

  Writer.prototype.renderSection = function renderSection (token, context, partials, originalTemplate) {
    var self = this;
    var buffer = '';
    var value = context.lookup(token[1]);

    // This function is used to render an arbitrary template
    // in the current context by higher-order sections.
    function subRender (template) {
      return self.render(template, context, partials);
    }

    if (!value) return;

    if (isArray(value)) {
      for (var j = 0, valueLength = value.length; j < valueLength; ++j) {
        buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate);
      }
    } else if (typeof value === 'object' || typeof value === 'string' || typeof value === 'number') {
      buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate);
    } else if (isFunction(value)) {
      if (typeof originalTemplate !== 'string')
        throw new Error('Cannot use higher-order sections without the original template');

      // Extract the portion of the original template that the section contains.
      value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender);

      if (value != null)
        buffer += value;
    } else {
      buffer += this.renderTokens(token[4], context, partials, originalTemplate);
    }
    return buffer;
  };

  Writer.prototype.renderInverted = function renderInverted (token, context, partials, originalTemplate) {
    var value = context.lookup(token[1]);

    // Use JavaScript's definition of falsy. Include empty arrays.
    // See https://github.com/janl/mustache.js/issues/186
    if (!value || (isArray(value) && value.length === 0))
      return this.renderTokens(token[4], context, partials, originalTemplate);
  };

  Writer.prototype.renderPartial = function renderPartial (token, context, partials) {
    if (!partials) return;

    var value = isFunction(partials) ? partials(token[1]) : partials[token[1]];
    if (value != null)
      return this.renderTokens(this.parse(value), context, partials, value);
  };

  Writer.prototype.unescapedValue = function unescapedValue (token, context) {
    var value = context.lookup(token[1]);
    if (value != null)
      return value;
  };

  Writer.prototype.escapedValue = function escapedValue (token, context) {
    var value = context.lookup(token[1]);
    if (value != null)
      return mustache.escape(value);
  };

  Writer.prototype.rawValue = function rawValue (token) {
    return token[1];
  };

  mustache.name = 'mustache.js';
  mustache.version = '2.2.1';
  mustache.tags = [ '{{', '}}' ];

  // All high-level mustache.* functions use this writer.
  var defaultWriter = new Writer();

  /**
   * Clears all cached templates in the default writer.
   */
  mustache.clearCache = function clearCache () {
    return defaultWriter.clearCache();
  };

  /**
   * Parses and caches the given template in the default writer and returns the
   * array of tokens it contains. Doing this ahead of time avoids the need to
   * parse templates on the fly as they are rendered.
   */
  mustache.parse = function parse (template, tags) {
    return defaultWriter.parse(template, tags);
  };

  /**
   * Renders the `template` with the given `view` and `partials` using the
   * default writer.
   */
  mustache.render = function render (template, view, partials) {
    if (typeof template !== 'string') {
      throw new TypeError('Invalid template! Template should be a "string" ' +
                          'but "' + typeStr(template) + '" was given as the first ' +
                          'argument for mustache#render(template, view, partials)');
    }

    return defaultWriter.render(template, view, partials);
  };

  // This is here for backwards compatibility with 0.4.x.,
  /*eslint-disable */ // eslint wants camel cased function name
  mustache.to_html = function to_html (template, view, partials, send) {
    /*eslint-enable*/

    var result = mustache.render(template, view, partials);

    if (isFunction(send)) {
      send(result);
    } else {
      return result;
    }
  };

  // Export the escaping function so that the user may override it.
  // See https://github.com/janl/mustache.js/issues/244
  mustache.escape = escapeHtml;

  // Export these mainly for testing, but also for advanced usage.
  mustache.Scanner = Scanner;
  mustache.Context = Context;
  mustache.Writer = Writer;

}));
libs/better-framework/product-pages/assets/js/mustache.min.js000064400000022450151214002510020373 0ustar00(function defineMustache(global,factory){if(typeof exports==="object"&&exports&&typeof exports.nodeName!=="string"){factory(exports)}else if(typeof define==="function"&&define.amd){define(["exports"],factory)}else{global.Mustache={};factory(global.Mustache)}})(this,function mustacheFactory(mustache){var objectToString=Object.prototype.toString;var isArray=Array.isArray||function isArrayPolyfill(object){return objectToString.call(object)==="[object Array]"};function isFunction(object){return typeof object==="function"}function typeStr(obj){return isArray(obj)?"array":typeof obj}function escapeRegExp(string){return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}function hasProperty(obj,propName){return obj!=null&&typeof obj==="object"&&propName in obj}var regExpTest=RegExp.prototype.test;function testRegExp(re,string){return regExpTest.call(re,string)}var nonSpaceRe=/\S/;function isWhitespace(string){return!testRegExp(nonSpaceRe,string)}var entityMap={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};function escapeHtml(string){return String(string).replace(/[&<>"'`=\/]/g,function fromEntityMap(s){return entityMap[s]})}var whiteRe=/\s*/;var spaceRe=/\s+/;var equalsRe=/\s*=/;var curlyRe=/\s*\}/;var tagRe=/#|\^|\/|>|\{|&|=|!/;function parseTemplate(template,tags){if(!template)return[];var sections=[];var tokens=[];var spaces=[];var hasTag=false;var nonSpace=false;function stripSpace(){if(hasTag&&!nonSpace){while(spaces.length)delete tokens[spaces.pop()]}else{spaces=[]}hasTag=false;nonSpace=false}var openingTagRe,closingTagRe,closingCurlyRe;function compileTags(tagsToCompile){if(typeof tagsToCompile==="string")tagsToCompile=tagsToCompile.split(spaceRe,2);if(!isArray(tagsToCompile)||tagsToCompile.length!==2)throw new Error("Invalid tags: "+tagsToCompile);openingTagRe=new RegExp(escapeRegExp(tagsToCompile[0])+"\\s*");closingTagRe=new RegExp("\\s*"+escapeRegExp(tagsToCompile[1]));closingCurlyRe=new RegExp("\\s*"+escapeRegExp("}"+tagsToCompile[1]))}compileTags(tags||mustache.tags);var scanner=new Scanner(template);var start,type,value,chr,token,openSection;while(!scanner.eos()){start=scanner.pos;value=scanner.scanUntil(openingTagRe);if(value){for(var i=0,valueLength=value.length;i<valueLength;++i){chr=value.charAt(i);if(isWhitespace(chr)){spaces.push(tokens.length)}else{nonSpace=true}tokens.push(["text",chr,start,start+1]);start+=1;if(chr==="\n")stripSpace()}}if(!scanner.scan(openingTagRe))break;hasTag=true;type=scanner.scan(tagRe)||"name";scanner.scan(whiteRe);if(type==="="){value=scanner.scanUntil(equalsRe);scanner.scan(equalsRe);scanner.scanUntil(closingTagRe)}else if(type==="{"){value=scanner.scanUntil(closingCurlyRe);scanner.scan(curlyRe);scanner.scanUntil(closingTagRe);type="&"}else{value=scanner.scanUntil(closingTagRe)}if(!scanner.scan(closingTagRe))throw new Error("Unclosed tag at "+scanner.pos);token=[type,value,start,scanner.pos];tokens.push(token);if(type==="#"||type==="^"){sections.push(token)}else if(type==="/"){openSection=sections.pop();if(!openSection)throw new Error('Unopened section "'+value+'" at '+start);if(openSection[1]!==value)throw new Error('Unclosed section "'+openSection[1]+'" at '+start)}else if(type==="name"||type==="{"||type==="&"){nonSpace=true}else if(type==="="){compileTags(value)}}openSection=sections.pop();if(openSection)throw new Error('Unclosed section "'+openSection[1]+'" at '+scanner.pos);return nestTokens(squashTokens(tokens))}function squashTokens(tokens){var squashedTokens=[];var token,lastToken;for(var i=0,numTokens=tokens.length;i<numTokens;++i){token=tokens[i];if(token){if(token[0]==="text"&&lastToken&&lastToken[0]==="text"){lastToken[1]+=token[1];lastToken[3]=token[3]}else{squashedTokens.push(token);lastToken=token}}}return squashedTokens}function nestTokens(tokens){var nestedTokens=[];var collector=nestedTokens;var sections=[];var token,section;for(var i=0,numTokens=tokens.length;i<numTokens;++i){token=tokens[i];switch(token[0]){case"#":case"^":collector.push(token);sections.push(token);collector=token[4]=[];break;case"/":section=sections.pop();section[5]=token[2];collector=sections.length>0?sections[sections.length-1][4]:nestedTokens;break;default:collector.push(token)}}return nestedTokens}function Scanner(string){this.string=string;this.tail=string;this.pos=0}Scanner.prototype.eos=function eos(){return this.tail===""};Scanner.prototype.scan=function scan(re){var match=this.tail.match(re);if(!match||match.index!==0)return"";var string=match[0];this.tail=this.tail.substring(string.length);this.pos+=string.length;return string};Scanner.prototype.scanUntil=function scanUntil(re){var index=this.tail.search(re),match;switch(index){case-1:match=this.tail;this.tail="";break;case 0:match="";break;default:match=this.tail.substring(0,index);this.tail=this.tail.substring(index)}this.pos+=match.length;return match};function Context(view,parentContext){this.view=view;this.cache={".":this.view};this.parent=parentContext}Context.prototype.push=function push(view){return new Context(view,this)};Context.prototype.lookup=function lookup(name){var cache=this.cache;var value;if(cache.hasOwnProperty(name)){value=cache[name]}else{var context=this,names,index,lookupHit=false;while(context){if(name.indexOf(".")>0){value=context.view;names=name.split(".");index=0;while(value!=null&&index<names.length){if(index===names.length-1)lookupHit=hasProperty(value,names[index]);value=value[names[index++]]}}else{value=context.view[name];lookupHit=hasProperty(context.view,name)}if(lookupHit)break;context=context.parent}cache[name]=value}if(isFunction(value))value=value.call(this.view);return value};function Writer(){this.cache={}}Writer.prototype.clearCache=function clearCache(){this.cache={}};Writer.prototype.parse=function parse(template,tags){var cache=this.cache;var tokens=cache[template];if(tokens==null)tokens=cache[template]=parseTemplate(template,tags);return tokens};Writer.prototype.render=function render(template,view,partials){var tokens=this.parse(template);var context=view instanceof Context?view:new Context(view);return this.renderTokens(tokens,context,partials,template)};Writer.prototype.renderTokens=function renderTokens(tokens,context,partials,originalTemplate){var buffer="";var token,symbol,value;for(var i=0,numTokens=tokens.length;i<numTokens;++i){value=undefined;token=tokens[i];symbol=token[0];if(symbol==="#")value=this.renderSection(token,context,partials,originalTemplate);else if(symbol==="^")value=this.renderInverted(token,context,partials,originalTemplate);else if(symbol===">")value=this.renderPartial(token,context,partials,originalTemplate);else if(symbol==="&")value=this.unescapedValue(token,context);else if(symbol==="name")value=this.escapedValue(token,context);else if(symbol==="text")value=this.rawValue(token);if(value!==undefined)buffer+=value}return buffer};Writer.prototype.renderSection=function renderSection(token,context,partials,originalTemplate){var self=this;var buffer="";var value=context.lookup(token[1]);function subRender(template){return self.render(template,context,partials)}if(!value)return;if(isArray(value)){for(var j=0,valueLength=value.length;j<valueLength;++j){buffer+=this.renderTokens(token[4],context.push(value[j]),partials,originalTemplate)}}else if(typeof value==="object"||typeof value==="string"||typeof value==="number"){buffer+=this.renderTokens(token[4],context.push(value),partials,originalTemplate)}else if(isFunction(value)){if(typeof originalTemplate!=="string")throw new Error("Cannot use higher-order sections without the original template");value=value.call(context.view,originalTemplate.slice(token[3],token[5]),subRender);if(value!=null)buffer+=value}else{buffer+=this.renderTokens(token[4],context,partials,originalTemplate)}return buffer};Writer.prototype.renderInverted=function renderInverted(token,context,partials,originalTemplate){var value=context.lookup(token[1]);if(!value||isArray(value)&&value.length===0)return this.renderTokens(token[4],context,partials,originalTemplate)};Writer.prototype.renderPartial=function renderPartial(token,context,partials){if(!partials)return;var value=isFunction(partials)?partials(token[1]):partials[token[1]];if(value!=null)return this.renderTokens(this.parse(value),context,partials,value)};Writer.prototype.unescapedValue=function unescapedValue(token,context){var value=context.lookup(token[1]);if(value!=null)return value};Writer.prototype.escapedValue=function escapedValue(token,context){var value=context.lookup(token[1]);if(value!=null)return mustache.escape(value)};Writer.prototype.rawValue=function rawValue(token){return token[1]};mustache.name="mustache.js";mustache.version="2.2.1";mustache.tags=["{{","}}"];var defaultWriter=new Writer;mustache.clearCache=function clearCache(){return defaultWriter.clearCache()};mustache.parse=function parse(template,tags){return defaultWriter.parse(template,tags)};mustache.render=function render(template,view,partials){if(typeof template!=="string"){throw new TypeError('Invalid template! Template should be a "string" '+'but "'+typeStr(template)+'" was given as the first '+"argument for mustache#render(template, view, partials)")}return defaultWriter.render(template,view,partials)};mustache.to_html=function to_html(template,view,partials,send){var result=mustache.render(template,view,partials);if(isFunction(send)){send(result)}else{return result}};mustache.escape=escapeHtml;mustache.Scanner=Scanner;mustache.Context=Context;mustache.Writer=Writer});
libs/better-framework/product-pages/assets/js/index.php000064400000000006151214002520017254 0ustar00<?php
libs/better-framework/product-pages/assets/img/index.php000064400000000006151214002520017414 0ustar00<?php
libs/better-framework/product-pages/assets/css/bs-product-pages.css000064400000045257151214002520021522 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */


/**
  =>Animations
         -> Animation keyFrames
         -> Animation Classes
         -> load-awesome Loading

  =>global classes
        -> Buttons
        -> ProgressBar
  =>header

  =>tabs

  =>boxes

  =>lists

  =>help

  =>responsive
        -> @992: tabs responsive
        -> @992: boxes responsive
        
        -> @690: boxes responsive
        -> @690: list responsive
 **/

@-webkit-keyframes bs-fadeOutRight {
    from {
        opacity: 1;
    }

    to {
        opacity: 0;
        -webkit-transform: translate3d(10%, 0, 0);
        transform: translate3d(10%, 0, 0);
    }
}

@keyframes bs-fadeOutRight {
    from {
        opacity: 1;
    }

    to {
        opacity: 0;
        -webkit-transform: translate3d(10%, 0, 0);
        transform: translate3d(10%, 0, 0);
    }
}

@-webkit-keyframes bs-fadeInRight {
    from {
        opacity: 0;
        -webkit-transform: translate3d(100%, 0, 0);
        transform: translate3d(100%, 0, 0);
    }

    to {
        opacity: 1;
        -webkit-transform: none;
        transform: none;
    }
}

@keyframes bs-fadeInRight {
    from {
        opacity: 0;
        -webkit-transform: translate3d(100%, 0, 0);
        transform: translate3d(100%, 0, 0);
    }

    to {
        opacity: 1;
        -webkit-transform: none;
        transform: none;
    }
}

@-webkit-keyframes bs-animate-stripes {
    0% {
        background-position: 0 0
    }
    100% {
        background-position: 35px 35px
    }
}

@keyframes bs-animate-stripes {
    0% {
        background-position: 0 0
    }
    100% {
        background-position: 35px 35px
    }
}


.bs-fadeOutRight {
    -webkit-animation-name: bs-fadeOutRight;
    animation-name: bs-fadeOutRight;
}

.bs-fadeInRight {
    -webkit-animation-name: bs-fadeInRight;
    animation-name: bs-fadeInRight;
}

.bs-pages-animated {
    -webkit-animation-duration: 0.3s;
    animation-duration: 0.3s;
    -webkit-animation-fill-mode: both;
    animation-fill-mode: both;
}

/**
    -> load-awesome Loading
*/


.la-line-scale-pulse-out-rapid,
.la-line-scale-pulse-out-rapid > div {
    position: relative;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}

.la-line-scale-pulse-out-rapid {
    display: block;
    font-size: 0;
    color: #00a0d2;
    margin: 10px auto;
    text-align: center;
}

.la-line-scale-pulse-out-rapid.la-dark {
    color: #333;
}

.la-line-scale-pulse-out-rapid > div {
    display: inline-block;
    float: none;
    background-color: currentColor;
    border: 0 solid currentColor;
}

.la-line-scale-pulse-out-rapid {
    width: 40px;
    height: 32px;
}

.la-line-scale-pulse-out-rapid > div {
    width: 4px;
    height: 32px;
    margin: 2px;
    margin-top: 0;
    margin-bottom: 0;
    border-radius: 0;
    -webkit-animation: line-scale-pulse-out-rapid .9s infinite cubic-bezier(.11, .49, .38, .78);
    -moz-animation: line-scale-pulse-out-rapid .9s infinite cubic-bezier(.11, .49, .38, .78);
    -o-animation: line-scale-pulse-out-rapid .9s infinite cubic-bezier(.11, .49, .38, .78);
    animation: line-scale-pulse-out-rapid .9s infinite cubic-bezier(.11, .49, .38, .78);
}

.la-line-scale-pulse-out-rapid > div:nth-child(3) {
    -webkit-animation-delay: -.9s;
    -moz-animation-delay: -.9s;
    -o-animation-delay: -.9s;
    animation-delay: -.9s;
}

.la-line-scale-pulse-out-rapid > div:nth-child(2),
.la-line-scale-pulse-out-rapid > div:nth-child(4) {
    -webkit-animation-delay: -.65s;
    -moz-animation-delay: -.65s;
    -o-animation-delay: -.65s;
    animation-delay: -.65s;
}

.la-line-scale-pulse-out-rapid > div:nth-child(1),
.la-line-scale-pulse-out-rapid > div:nth-child(5) {
    -webkit-animation-delay: -.4s;
    -moz-animation-delay: -.4s;
    -o-animation-delay: -.4s;
    animation-delay: -.4s;
}

.la-line-scale-pulse-out-rapid.la-sm {
    width: 20px;
    height: 16px;
}

.la-line-scale-pulse-out-rapid.la-sm > div {
    width: 2px;
    height: 16px;
    margin: 1px;
    margin-top: 0;
    margin-bottom: 0;
}

.la-line-scale-pulse-out-rapid.la-2x {
    width: 80px;
    height: 64px;
}

.la-line-scale-pulse-out-rapid.la-2x > div {
    width: 8px;
    height: 64px;
    margin: 4px;
    margin-top: 0;
    margin-bottom: 0;
}

.la-line-scale-pulse-out-rapid.la-3x {
    width: 120px;
    height: 96px;
}

.la-line-scale-pulse-out-rapid.la-3x > div {
    width: 12px;
    height: 96px;
    margin: 6px;
    margin-top: 0;
    margin-bottom: 0;
}
/**
    =>global classes
*/
.bs-product-item hr {
    margin: 20px 0;
}

.clear-fix:after {
    content: ' ';
    display: block;
    height: 1px;
    clear: both;
    overflow: hidden;
}

.bs-disabled {
    opacity: 0.7;
    cursor: not-allowed;
}
/**
    -> Buttons
*/

.bs-product-item .bs-pages-success-btn {
    border-color: #06bb51;
    background: #04a647;
}
.bs-product-item .bs-pages-success-btn:hover {
    border-color: #06bb51;
    background: #01c552;
}

/**
    -> ProgressBar
*/
.bs-pages-progressbar {
    max-width: 100%;
    width: 0px;
    height: 5px;
    position: relative;
    visibility: hidden;
    position: absolute;
    top: 240px;
    z-index: 1;
    overflow: hidden;
    -webkit-transition: all .5s ease;
    -moz-transition: all .5s ease;
    -o-transition: all .5s ease;
    transition: all .5s ease;
}

.bs-pages-progressbar .bs-pages-progress {
    height: 5px;
    transition: width 400ms;
    -webkit-animation: bs-animate-stripes 2.4s linear infinite;
    -moz-animation: bs-animate-stripes 2.4s linear infinite;
    animation: bs-animate-stripes 2.4s linear infinite;
    background-color: #06a54e;
    background-image: -webkit-linear-gradient(135deg, rgba(255,255,255,0.3) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.3) 50%, rgba(255,255,255,0.3) 75%, transparent 75%, transparent);
    background-image: linear-gradient(-45deg, rgba(255,255,255,0.3) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.3) 50%, rgba(255,255,255,0.3) 75%, transparent 75%, transparent);
    background-size: 35px 35px;
}

.bs-pages-overlay {
    background: rgba(255, 255, 255, 0.5);
    height: 100%;
    position: absolute;
    width: 100%;
    z-index: 9999;
    display: none;
}

#adminmenuwrap.installing-demo,
.bs-product-pages-tabs-wrapper.installing-demo {
    opacity: 0.5;
    pointer-events: none;
}
/**
    =>header
*/

.bs-product-item {
    line-height: 1.7;
    color: #3b3b3b;
    font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
    font-size: 15px;
    color: #575757;
    max-width: 1065px;
}

.bs-product-item .heading {
    font-size: 28px;
    font-weight: 500;
    color: #3b3b3b;
    padding: 0;
    margin: 0 0 6px;
}

.bs-product-item h3.heading {
    font-size: 26px;
}

.bs-product-item .description-bottom {
    display: inline-block;
    margin-bottom: 10px;
    max-width: 1320px;
}

.bs-product-item .description-bottom p {
    font-size: 16px;
    margin-top: 0;
}

.bs-product-item .description-top {
    margin-bottom: 15px;
}

.bs-about-product {
    color: #575757;
    font-size: 15px;
}

.product-info-wrapper {
    display: table;
    width: 450px;
    max-width: 100%;
    margin: 20px 2px 0;
}

.product-info-wrapper ul.product-info {
    display: table-row;
}

.product-info-wrapper .product-info > li {
    display: table-cell;
    color: #7f7f7f;
}

.product-info-wrapper .bold {
    font-weight: bold;
    font-size: 14px;
    color: #3b3b3b !important;
}

/**
    =>tabs
*/
.bs-product-pages-tabs {
    margin: 20px 0 0;
    padding: 0;
    width: 100%;
    border-bottom: 1px solid #bfbfbf;
}

.bs-product-pages-tabs .tab {
    margin: 0 0 0 15px;
    padding: 0;
    position: relative;
    display: inline-block;
}

.bs-product-pages-tabs .tab a,
.bs-product-pages-tabs .tab span {
    background: #fff;
    color: #3b3b3b;
    border: 1px solid #bfbfbf;
    border-bottom-width: 0;
    text-decoration: none;
    padding: 6px 10px;
    font-weight: bold;
    white-space: nowrap;
    display: inline-block;
    position: relative;
    font-size: 13px;
}

.bs-product-pages-tabs .tab a:hover {
    background: #eee;
}

.bs-product-pages-tabs .tab.bs-tab-active span {
    background: #f1f1f1;
    border-color: #bfbfbf;
}

.bs-product-pages-tabs .tab.bs-tab-active span:after {
    content: '';
    position: absolute;
    bottom: -1px;
    left: 0;
    display: inline-block;
    width: 100%;
    height: 1px;
    background: #f1f1f1;
}

.bs-product-pages-tabs .tab:last-child {
    margin-right: 16px;
}

.bs-product-pages-tabs-wrapper {
    overflow: hidden;
    margin-bottom: 18px;
    max-width: 1320px;
}

/**
    =>boxes
**/

.bs-pages-row-one .bs-pages-box-wrapper {
    width: 100%;
    max-width: 100%;
}

.bs-product-pages-box-container{
    margin-left: -1.5%;
    margin-right: -1.5%;
}
.bs-pages-box-wrapper {
    width: 30.333%;
    float: left;
    background: #fff;
    -webkit-box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.13);
    -moz-box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.13);
    box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.13);
    font-family: "Open Sans", Helvetica, sans-serif;
    font-size: 15px;
    color: #3b3b3b;
    margin-left: 1.5%;
    margin-right: 1.5%;
    margin-bottom: 25px;
    position: relative;
}
.bs-pages-box-wrapper.fix-height-1 .bs-pages-box-description {
    min-height: 150px;
}

.bs-pages-box-wrapper.bs-fullwidth-box {
    width: 100%;
    max-width: 100%;
    margin: 0;
}
.bs-pages-box-wrapper a:not([class^=bf-btn]) {
    color: #00a0d2;
}
.bs-pages-box-wrapper .bs-loading-overlay {
    display: none;
    position: absolute;
    top: 0;
    left: 0;
    background: rgba(0,0,0,0.48);
    z-index: 99;
    width: 100%;
    height: 100%;
}
.bs-pages-box-wrapper.bs-loading-wrapper .bs-loading-overlay {
    display: block;
}
.bs-pages-box-wrapper.bs-loading-wrapper .la-line-scale-pulse-out-rapid {
    position: relative;
    top: 50%;
    -webkit-transform: translateY(-50%);
    -moz-transform: translateY(-50%);
    -ms-transform: translateY(-50%);
    -o-transform: translateY(-50%);
    transform: translateY(-50%);
}
.bs-loading-overlay>div {
    color: #fff;
}
.bs-pages-box-header {
    color: #3b3b3b;
    font-weight: bold;
    font-size: 16px;
    padding: 10px 18px;
    display: block;
}
.bs-pages-box-header .bf-icon {
    margin-right: 5px;
}
.bs-pages-box-description {
    line-height: 1.6;
    font-size: 14px;
    padding: 20px 18px;
    position: relative;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    min-height: 20px;
}

.bs-pages-box-description:before {
    background: linear-gradient(rgba(234, 234, 234, 1) 0%, rgba(255, 255, 255, 0) 100%);
    content: " ";
    display: block;
    height: 9px;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
}

.bs-pages-box-description.bs-pages-box-description-fluid {
    margin: 0;
    padding: 0;
}

.bs-pages-buttons {
    font-weight: normal;
    font-size: 14px;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}

.bs-pages-buttons a {
    margin: 0 10px 0 0;
    white-space: nowrap;
    display: inline-block;
}

.bs-pages-box-container .bs-pages-buttons{
    padding-left: 18px;
    padding-bottom: 20px;
}

/**
    =>lists
*/
.bs-pages-list-title,
.bs-pages-list-data {

    display: inline-block;
    width: 35%;
    padding: 0;
    margin: 10px 0;
    vertical-align: middle;
}

.bs-pages-list-data {
    width: 64%;
}
.bs-pages-list-data.no-label {
    width: 100%;
}

.bs-pages-list-wrapper {
    padding-top: 5px;
}

.bs-pages-list-item {
    padding: 3px 15px;
}
.bs-pages-list-item.bs-item-hide {
    display: none;
}
.bs-pages-list-wrapper > .bs-pages-list-item:nth-child(2n) {
    background: #f9f9f9;
    border-width: 1px 0 1px 0;
    border-color: #ededed;
    border-style: dashed;
}
.bs-pages-list-wrapper > .bs-pages-list-item:last-child {

    border-bottom-width: 0;
}
/**
    =>help
*/
.bs-pages-help-wrapper {
    position: relative;
    display: inline;
}
.bs-pages-help {
    background: #e1ebef;
    display: inline-block;
    width: 20px;
    height: 20px;
    line-height: 20px;
    color: #00a0d2;
    overflow: hidden;
    text-align: center;

    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    vertical-align: middle;

    -webkit-border-radius: 50%;
    -moz-border-radius: 50%;
    border-radius: 50%;

    margin: 0 5px;

}
.bs-pages-help.danger {
    background-color: #f44343;
}
.bs-pages-help.warning {
    background-color: #f2a20d;
}
.bs-pages-help.success {
    background-color: #06bb51;
}
.bs-pages-help .fa {
    color: #00a0d2;
    vertical-align: middle;
}

.bs-pages-help.danger .fa,
.bs-pages-help.warning .fa,
.bs-pages-help.success .fa {
    color: #fff;
}

.bs-pages-help-danger {
    background: #f44343;
}

.bs-pages-help-warning {
    background: #f2a20d;
}

.bs-pages-help-warning .fa,
.bs-pages-help-danger .fa {
    color: #fff;
    font-weight: bold;
}

.bs-pages-help:hover + .bs-pages-help-description,
.bs-pages-help:hover + .bs-pages-help-description:after {
    display: block;
}
.bs-pages-help-description {
    -webkit-border-radius: 3px 3px 0px 0px;
    -moz-border-radius: 3px 3px 0px 0px;
    border-radius: 3px 3px 0px 0px;

    -webkit-box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.3);
    -moz-box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.3);
    box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.3);
    position: absolute;
    background: rgba(0, 0, 0, 0.8);
    color: #fff;
    padding: 15px 13px;
    width: 200px;
    bottom: 100%;
    margin-left: -100px;
    margin-bottom: 15px;
    display: none;
    left: 0;
}
.bs-pages-help-description::after {
    content: ' ';
    display: block;
    border: 10px solid transparent;
    border-top-color: rgba(0, 0, 0, 0.8);
    position: absolute;
    bottom: 17px;
    left: 0;
    right: 0;
    margin: 0 auto;
    padding: 0;
    width: 0;
    bottom: -20px;
    display: none;
}

/*******
    =>Register Product
****/
.register-product-icon {
    margin-right: 54px;
    font-size: 30px;
}
.register-product-icon:last-child {
    margin-right: 0;
}
.register-product-icon.fa-key {
    color: #00bb38;
}
.bs-product-desc {
    text-align: center;
    padding: 20px;
    max-width: 665px;
    margin: 0 auto;
    color: #3b3b3b;
    font-size: 15px;
    line-height: 1.65;
}
.bs-purchase-code.bs-purchase-code {
    display: inline-block;
    width: 100%;
    border: 1px solid #d8d8d8;
    -webkit-border-radius: 0;
    -moz-border-radius: 0;
    border-radius: 0;
    -webkit-box-shadow: none;
    -moz-box-shadow: none;
    box-shadow: none;
    text-align: center;
    font-size: 18px;
}
.bs-pages-error-section {
    border: 1px solid #dadada;
    padding: 15px;
    background: #eee;
    border-radius: 5px;
    line-height: 1.6;
    position: relative;
    overflow: hidden;
}
.bs-pages-error-section textarea {
    width: 100%;
    display: block;
    background: none;
    box-shadow: none;
    border: none;
    overflow: scroll;
    min-height: 70px;
    margin-top: 0px;
    margin-bottom: 0px;
    height: 70px;
    /*max-height: 100px;*/
}
a.btn.bs-pages-error-copy {
    position: absolute;
    top: 0;
    right: 0;
    background: #fafafa;
    padding: 3px 10px;
    color: #707070;
    text-decoration: none;
    font-weight: bold;
    border: 1px solid #ddd;
    border-width: 0 0 1px 1px;
}
a.btn.bs-pages-error-copy:hover {
    background: #F5F5F5;
    color: #606060;
}
/**
    =>responsive
*/
@media only screen and (max-width: 992px) {

    /**
        -> @992: tabs responsive
    */
    .bs-product-pages-tabs {
        border-bottom: none;
        text-align: center;
    }

    .bs-product-pages-tabs .tab {
        margin-bottom: 10px;
    }

    .bs-product-pages-tabs .tab a {
        border-bottom-width: 1px;
    }

    .bs-product-pages-tabs .tab {
        margin-left: 5px;
    }

    .bs-product-pages-tabs .tab.bs-tab-active span {
        margin-bottom: 0;
        bottom: 1px;
        border-bottom-width: 2px;
    }

    /**
        -> @992: boxes responsive
    */
    .bs-pages-box-wrapper {
        width: 48%;
        margin-left: 2%;
        margin-right: 0;
    }

    .bs-product-pages-box-container {
        margin: 0 auto;
        display: block;
        width: 670px;
        max-width: 100%;
    }
}

@media only screen and (max-width: 690px) {
    /**
       -> @690: boxes responsive
   */
    .bs-pages-box-wrapper {
        width: 100%;
        margin-left: 0;
        margin-right: 0;
    }

    .bs-product-pages-box-container {
        margin: 0 auto;
        display: block;
        width: 310px;
        max-width: 100%;
    }

    /**
          -> @690: list responsive
      */
    .bs-pages-list-title,
    .bs-pages-list-data {
        width: 100%;
        display: block;
    }
}


/**
   RTL FIX
*/
.rtl .bs-product-pages-tabs .tab {
    margin: 0 15px 0 0;
}
.rtl .bs-product-pages-tabs .tab.bs-tab-active span:after {
    right: 0;
    left: auto;
}


/**
    =>boxes
**/
.rtl .bs-product-pages-box-container {
    margin-right: -1.5%;
    margin-left: -1.5%;
}
.rtl .bs-pages-box-wrapper {
    float: right;
    margin-right: 1.5%;
    margin-left: 1.5%;
}
.rtl .bs-pages-box-wrapper .bs-loading-overlay {
    right: 0;
    left: auto;
}
.rtl .bs-pages-box-header .bf-icon {
    margin-left: 5px;
    margin-right: auto;
}
.rtl .bs-pages-box-description:before {
    right: 0;
    left: auto;
}
.rtl .bs-pages-buttons a {
    margin: 0 0 0 10px;
}
.rtl .bs-pages-box-container .bs-pages-buttons {
    padding-right: 18px;
    padding-left: 0;
}


/**
    =>help
*/
.rtl .bs-pages-help-description {
    margin-right: -100px;
    right: 0;
    left: auto;
    margin-left: auto;
}
.rtl .bs-pages-help-description::after {
    right: 0;
    left: 0;
}

/*******
    =>Register Product
****/
.rtl .register-product-icon {
    margin-left: 54px;
    margin-right: auto;
}
.rtl .register-product-icon:last-child {
    margin-left: 0;
    margin-right: auto;
}
.rtl a.btn.bs-pages-error-copy {
    left: 0;
    right: auto;
}

/**
    =>responsive
*/
@media only screen and (max-width: 992px) {
    .rtl a.btn.bs-pages-error-copy {
        left: 0;
        right: auto;
    }
}
@media only screen and (max-width: 690px) {
    .rtl .bs-pages-box-wrapper {
        margin-right: 0;
        margin-left: 0;
    }
}
libs/better-framework/product-pages/assets/css/index.php000064400000000006151214002520017430 0ustar00<?php
libs/better-framework/product-pages/assets/index.php000064400000000006151214002520016640 0ustar00<?php
libs/better-framework/product-pages/install-demo/class-bf-demo-widget-manager.php000064400000020563151214002520024136 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Class BF_Demo_Widget_Manager
 */
class BF_Demo_Widget_Manager {

	public $sidebar_id = '';

	static $widgets_number = array();


	/**
	 * set active sidebar id
	 * uses by some methods
	 *
	 * @param string|int $sidebar_id The ID of the sidebar when it was registered.
	 *
	 * @return bool true on success or false on failure.
	 */
	public function set_sidebar_id( $sidebar_id ) {

		if ( $this->is_registered_sidebar( $sidebar_id ) ) {

			$this->sidebar_id = $sidebar_id;

			return true;
		} else {

			$this->sidebar_id = '';

			return false;
		}
	}


	/**
	 * Checks if a sidebar is registered.
	 *
	 * @param string|int $sidebar_id            The ID of the sidebar when it was registered.
	 *
	 * @global array     $wp_registered_sidebar Registered sidebars.
	 * @return bool true if the sidebar is registered, false otherwise.
	 */

	protected function is_registered_sidebar( $sidebar_id ) {

		global $wp_registered_sidebars;

		/**
		 * is_registered_sidebar() functoon become avaiable since wordpress 4.4.0
		 */
		if ( function_exists( 'is_registered_sidebar' ) ) {
			return is_registered_sidebar( $sidebar_id );
		}

		return isset( $wp_registered_sidebars[ $sidebar_id ] );
	}


	/**
	 * generate unique widget number to save widget option on unique array index number
	 *
	 * @param string $widget_id_base
	 *
	 * @return int widget id number
	 */
	protected function generate_widget_id_number( $widget_id_base ) {

		if ( ! function_exists( 'next_widget_id_number' ) ) {
			require_once ABSPATH . '/wp-admin/includes/widgets.php';// for next_widget_id_number()
		}

		if ( ! isset( self::$widgets_number[ $widget_id_base ] ) ) {
			self::$widgets_number[ $widget_id_base ] = next_widget_id_number( $widget_id_base );
		} else {
			self::$widgets_number[ $widget_id_base ] ++;
		}

		return self::$widgets_number[ $widget_id_base ];
	}


	/**
	 * add a widget to the sidebar
	 *
	 * @see set_sidebar_id()
	 *
	 * @param string $widget_id_base  base id of the widget
	 * @param array  $widget_settings widget settings
	 *
	 * @return bool true on success or false on failure.
	 */
	public function add_widget( $widget_id_base, $widget_settings = array() ) {

		global $wp_registered_widget_updates;

		if ( ! $this->is_registered_sidebar( $this->sidebar_id ) ) {
			return false;
		}

		if ( ! isset( $wp_registered_widget_updates[ $widget_id_base ] ) ) {
			return false;
		}

		//wp_get_sidebars_widgets() cache data and make a problem when trying to add multiple widget to sidebar
		$sidebars = get_option( 'sidebars_widgets' );


		$widget_number = $this->generate_widget_id_number( $widget_id_base );
		$widget_id     = $widget_id_base . '-' . $widget_number;

		$sidebars[ $this->sidebar_id ][] = $widget_id;

		wp_set_sidebars_widgets( $sidebars );

		$settings = get_option( 'widget_' . $widget_id_base, array() );

		/**
		 * ##  bug fixed    ##
		 *
		 * make sure $settings is an array
		 */
		if ( ! is_array( $settings ) ) {
			$settings = array();
		}

		$settings[ $widget_number ] = $widget_settings;

		update_option( 'widget_' . $widget_id_base, $settings );


		//save widget settings
		foreach ( (array) $wp_registered_widget_updates as $name => $control ) {

			if ( $name == $widget_id_base ) {
				if ( ! is_callable( $control['callback'] ) ) {
					continue;
				}

				ob_start();
				call_user_func_array( $control['callback'], $control['params'] );
				ob_end_clean();
			}
		}


		return true;
	}


	/**
	 * TODO: test function
	 *
	 * get all widgets exists in a sidebar
	 *
	 * @return array|bool array of data on success or false on failure.
	 *
	 * array {
	 * @type        string|int $sidebar_id sidebar id
	 * @widgets     array       list of widgets
	 * @settings    array       widgets settings based on option_name
	 *
	 * }
	 */
	public function get_all_widgets() {

		$sidebars = wp_get_sidebars_widgets();

		if ( ! isset( $sidebars[ $this->sidebar_id ] ) ) {
			return false;
		}

		$settings = array();

		foreach ( $sidebars[ $this->sidebar_id ] as $widget_numbers ) {
			if ( preg_match( "/^(.*?)\-(\d)+/i", $widget_numbers, $match ) ) {

				$widget_id_base = &$match[1];


				$option_name              = "widget_$widget_id_base";
				$option_value             = get_option( $option_name );
				$settings[ $option_name ] = $option_value;
			}
		}


		return array(
			'sidebar_id' => $this->sidebar_id,
			'widgets'    => $sidebars[ $this->sidebar_id ],
			'settings'   => $settings
		);
	}


	/**
	 * remove every widget exists in sidebar
	 *
	 * @return bool true on success or false on failure.
	 */

	public function remove_all_widgets() {

		$sidebars = wp_get_sidebars_widgets();

		if ( ! isset( $sidebars[ $this->sidebar_id ] ) ) {
			return false;
		}

		$widgets_in_sidebar = array();

		foreach ( $sidebars[ $this->sidebar_id ] as $widget_numbers ) {
			if ( preg_match( "/^(.*?)\-(\d)+/i", $widget_numbers, $match ) ) {

				$widget_id_base = &$match[1];
				$widget_number  = &$match[2];

				$widgets_in_sidebar[ $widget_id_base ][] = $widget_number;
			}
		}

		//delete widget settings form database.

		foreach ( $widgets_in_sidebar as $id_base => $widget_numbers ) {

			$option_name = "widget_$id_base";

			$option = get_option( $option_name );

			if ( $option && is_array( $option ) ) {

				foreach ( $widget_numbers as $widget_number ) {

					unset( $option[ $widget_number ] );
				}

				if ( $option ) {

					update_option( $option_name, $option );
				} else {

					delete_option( $option_name );
				}
			}
		}

		//remove all widgets in sidebar
		$sidebars[ $this->sidebar_id ] = array();

		//save changes
		wp_set_sidebars_widgets( $sidebars );

		return true;
	}


	/**
	 * @param string $widget_id_base
	 *
	 * @return array|bool. false on failure or array of information on success.
	 *
	 * array {
	 * @type string  $sidebar_id     active sidebar id.
	 * @type string  $widget_id_base widget id base
	 * @type array settings            widget settings array
	 *
	 * }
	 */
	public function get_widgets( $widget_id_base ) {

		$sidebars = wp_get_sidebars_widgets();

		if ( ! isset( $sidebars[ $this->sidebar_id ] ) ) {
			return false;
		}

		$_widget_id_base = preg_quote( $widget_id_base );
		$settings        = get_option( 'widget_' . $widget_id_base, array() );

		$save_widgets  = array();
		$save_settings = array();

		foreach ( $sidebars[ $this->sidebar_id ] as $index => $widget ) {
			if ( preg_match( "/^$_widget_id_base\-(\d+)/i", $widget, $match ) ) {

				$widget_number = &$match[1];

				$save_settings[] = $settings[ $widget_number ];
			}
		}


		return array(
			'sidebar_id'     => $this->sidebar_id,
			'widget_id_base' => $widget_id_base,
			'settings'       => $save_settings
		);
	}


	/**
	 * remove all widget which 'id bases' is equal to $widget_id_base
	 *
	 * @param string $widget_id_base
	 *
	 * @return bool true ob success or false on failure.
	 */
	public function remove_widgets( $widget_id_base ) {

		$sidebars = wp_get_sidebars_widgets();

		if ( ! isset( $sidebars[ $this->sidebar_id ] ) ) {
			return false;
		}

		$_widget_id_base = preg_quote( $widget_id_base );
		$settings        = get_option( 'widget_' . $widget_id_base, array() );

		foreach ( $sidebars[ $this->sidebar_id ] as $index => $widget ) {
			if ( preg_match( "/^$_widget_id_base\-(\d+)/i", $widget, $match ) ) {

				$widget_number = &$match[1];

				unset( $sidebars[ $this->sidebar_id ][ $index ] );
				unset( $settings[ $widget_number ] );
			}
		}

		wp_set_sidebars_widgets( $sidebars );
		update_option( 'widget_' . $widget_id_base, $settings );


		return true;
	}

}

/**
 * Example:
 *
 *
 * $import = new BF_Demo_Widget_Manager();
 *
 * $import->set_sidebarId( 'aside-logo' );
 *
 *
 * var_dump( $import->remove_widgets( 'search' ) );
 * var_dump( $import->add_widget( 'search' ) );
 */
libs/better-framework/product-pages/install-demo/class-bf-demo-option-manager.php000064400000017713151214002520024166 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Class BF_Demo_Option_Manager
 *
 * add, delete, update option and transient
 *
 */
class BF_Demo_Option_Manager {


	/**
	 * get option name stored in option array
	 *
	 * @param array $option_params
	 *
	 * @return bool|string option name as string on success or false on failure.
	 */
	public function get_option_name( $option_params ) {

		if ( isset( $option_params['option_name'] ) && is_string( $option_params['option_name'] ) ) {

			return $option_params['option_name'];
		}

		return false;
	}


	/**
	 * get option values stored in option array
	 *
	 * -external usage-
	 *
	 * @param array $option_params
	 *
	 * @return mixed null on failure another data type on success.
	 */
	public function get_option_value( $option_params = array() ) {

		if ( isset( $option_params['option_value'] ) ) {

			if ( is_array( $option_params['option_value'] ) ) {
				foreach ( $option_params['option_value'] as $id => $val ) {
					if ( is_array( $val ) ) {
						foreach ( $val as $_id => $_val ) {
							$option_params['option_value'][ $id ][ $_id ] = BF_Product_Demo_Installer::Run()->apply_pattern( $_val );
						}
					} else {
						$option_params['option_value'][ $id ] = BF_Product_Demo_Installer::Run()->apply_pattern( $val );
					}
				}
			} else {
				$option_params['option_value'] = BF_Product_Demo_Installer::Run()->apply_pattern( $option_params['option_value'] );
			}

			return $option_params['option_value'];
		}

		return BF_Product_Demo_Installer::Run()->apply_pattern( $option_params );
	}


	/**
	 * prepare a array with two index to pass add_option, update_option via call_user_func_array function.
	 *
	 * @param array $option_params
	 *
	 * @return array {
	 *
	 *     0 => option_name,
	 *     1 => option_value
	 *
	 * }
	 */
	protected function get_option_params( $option_params ) {

		if ( ! is_array( $option_params ) ) {
			return;
		}

		if ( isset( $option_params['option_value_file'] ) && is_readable( $option_params['option_value_file'] ) ) {
			$value = BF_Product_Demo_Installer::Run()->apply_pattern( bf_get_local_file_content( $option_params['option_value_file'] ) );

			// decode json value
			if ( $json_decode = bf_is_json( $value, true ) ) {
				$value = $json_decode;
			}

			$option_params['option_value'] = $value;
		}

		$required_params = array(
			'option_name'  => '',
			'option_value' => '',
		);

		if ( ! array_diff_key( $required_params, $option_params ) ) {

			return array(
				$option_params['option_name'],
				$this->get_option_value( $option_params )
			);
		}
	}


	/**
	 * prepare a array with three index to pass set_transient, get_transient via call_user_func_array function.
	 *
	 * @param array $transient_params
	 *
	 * @return array
	 */

	protected function get_transient_params( $transient_params ) {

		if ( ! is_array( $transient_params ) ) {
			return;
		}

		$required_params = array(
			'transient_name'  => '',
			'transient_value' => '',
			'expiration'      => '',
		);

		if ( ! array_diff_key( $required_params, $transient_params ) ) {

			return array(
				$transient_params['transient_name'],
				$transient_params['transient_value'],
				$transient_params['expiration']
			);
		}
	}


	/**
	 * @param Array $option_params
	 *                                 array {
	 *
	 * @type string $option_name       Name of option to add. Expected to not be SQL-escaped.
	 * @type mixed  $option_value      Optional if 'option_value_file' index exists .Option value. Must be serializable
	 *       if non-scalar. Expected to not be SQL-escaped
	 * @type string $option_value_file Optional if 'option_value' index exists . file path to option value.  long
	 *       option value can save on file.
	 *  }
	 *
	 *
	 * @return bool False if option was not added and true if option was added.
	 */
	public function add_option( $option_params ) {

		if ( $option_params = $this->get_option_params( $option_params ) ) {

			//turn off autoload
			$option_params[2] = '';
			$option_params[3] = 'no';

			return call_user_func_array( 'add_option', $option_params );
		}
	}


	/**
	 * @param $option_id option unique ID in database
	 *
	 * @return bool true on success or false on failure
	 */
	public function remove_option( $option_id ) {

		global $wpdb;


		return (bool) $wpdb->delete( $wpdb->options, array( 'option_id', $option_id ) );
	}


	/**
	 *
	 * update option
	 *
	 * @param Array $option_params
	 *
	 * @see update_option()
	 * @see get_option_params()
	 *
	 * @return bool False if value was not updated and true if value was updated
	 */
	public function update_option( $option_params ) {

		if ( $update_option_params = $this->get_option_params( $option_params ) ) {

			return call_user_func_array( 'update_option', $update_option_params );
		}

		return false;
	}


	/**
	 * combine new array value with previous option array
	 *
	 * @param Array $option_params
	 *
	 * @see update_option()
	 * @see get_option_params()
	 *
	 * @return bool False if value was not updated and true if value was updated
	 */
	public function merge_and_update_option( $option_params ) {

		if ( $update_option_params = $this->get_option_params( $option_params ) ) {

			//get previous option and make sure its array
			$prev_options = $this->get_option( $option_params );

			if ( empty( $prev_options ) ) {
				$prev_options = array();
			} else {
				$prev_options = (array) $prev_options;
			}

			//second index is option value
			$update_option_params[1] = array_merge( $prev_options, (array) $update_option_params[1] );

			return call_user_func_array( 'update_option', $update_option_params );
		}

		return false;
	}


	/**
	 *
	 * @param array|string $option_params
	 *
	 * @see get_option_params()
	 *
	 * @return bool False if value was not updated and true if value was updated
	 */
	public function get_option( $option_params ) {

		if ( is_array( $option_params ) ) {

			return get_option( $this->get_option_name( $option_params ) );
		} elseif ( is_string( $option_params ) ) {

			return get_option( $option_params );
		}
	}


	/**
	 * @param array|string $option_params of option to remove. Expected to not be SQL-escaped
	 *
	 * @return bool true, if option is successfully deleted. False on failure.
	 */
	public function delete_option( $option_params ) {

		if ( is_array( $option_params ) ) {

			return delete_option( $this->get_option_name( $option_params ) );
		} elseif ( is_string( $option_params ) ) {

			return delete_option( $option_params );
		}

	}


	/**
	 * @param Array $transient_params
	 *
	 * @see get_transient_params()
	 *
	 * @return bool False if value was not set and true if value was set.
	 */
	public function set_transient( $transient_params ) {

		if ( $transient_params = $this->get_transient_params( $transient_params ) ) {

			return call_user_func_array( 'set_transient', $transient_params );
		}
	}


	/**
	 * @param string $transient Transient name. Expected to not be SQL-escaped
	 *
	 * @return bool true if successful, false otherwise
	 */

	public function remove_transient( $transient ) {

		return delete_transient( $transient );
	}


	/**
	 * @param Array $transient_params
	 *
	 * @see get_option_params()
	 *
	 * @return mixed Value of transient.
	 */
	public function get_transient( $transient_params ) {

		if ( $transient_params = $this->get_transient_params( $transient_params ) ) {

			return get_transient( $transient_params[0] );
		}
	}
}
libs/better-framework/product-pages/install-demo/class-bf-demo-install-plugin-adapter.php000064400000006524151214002520025624 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Class BF_Demo_Install_Plugin_Adapter
 */
class BF_Demo_Install_Plugin_Adapter {

	/**
	 * @var BF_Product_Plugin_Installer
	 */
	private $_hanlder;

	/**
	 * @var BF_Product_Demo_Manager
	 */
	private $_demo_manager;


	/**
	 * BF_Demo_Install_Plugin_Adapter constructor.
	 */
	public function __construct() {

		$this->init();

		$this->_hanlder      = new BF_Product_Plugin_Installer();
		$this->_demo_manager = new BF_Product_Plugin_Manager();
	}


	/**
	 * include classes
	 */
	private function init() {

		if ( ! class_exists( 'BF_Product_Plugin_Installer' ) ) {

			$class_path = BF_Product_Pages::get_path( 'install-plugin/class-bf-product-plugin-installer.php' );

			if ( file_exists( $class_path ) ) {
				require_once $class_path;
			}
		}

		if ( ! class_exists( 'BF_Product_Plugin_Installer' ) ) {

			trigger_error( 'BF_Product_Plugin_Factory Was not found. BF_Demo_Install_Plugin_Adapter class need this class to handle plugin installation' );

			return;
		}

		if ( ! class_exists( 'BF_Product_Plugin_Manager' ) ) {

			$class_path = BF_Product_Pages::get_path( 'install-plugin/class-bf-product-plugin-manager.php' );

			if ( file_exists( $class_path ) ) {
				require_once $class_path;
			}
		}

		if ( ! class_exists( 'BF_Product_Plugin_Manager' ) ) {

			trigger_error( 'BF_Product_Plugin_Manager Was not found. BF_Demo_Install_Plugin_Adapter class need this class to handle plugin installation' );

			return;
		}
	}


	/**
	 * @see BF_Product_Plugin_Factory::install_start paranms
	 *
	 * @param array  $calculated_steps calculated plguin installation/update steps via
	 *
	 * @see \BF_Product_Plugin_Manager::calculate_process_steps
	 *
	 *
	 *
	 *
	 * @param int    $step
	 * @param string $plugin_ID
	 *
	 * @return bool true on success false otherwise
	 */
	public function install_start( $calculated_steps, $step, $plugin_ID ) {

		//validate $calculated_steps steps
		if ( ! isset( $calculated_steps['steps'] ) || ! is_array( $calculated_steps['steps'] ) ) {

			return false;
		}

		$plugins_list = $this->_demo_manager->get_plugins_data();
		if ( ! isset( $plugins_list[ $plugin_ID ] ) ) {

			return false;
		}


		//convert index number to plugin installation action
		$array_index    = $step - 1;
		$plugin_actions = array_keys( $calculated_steps['steps'] );

		if ( isset( $plugin_actions[ $array_index ] ) ) {
			$plugin_action = &$plugin_actions[ $array_index ];
		} else {

			return false;
		}


		$plugin_data = &$plugins_list[ $plugin_ID ];

		return $this->_hanlder->install_start( $plugin_data, $plugin_action, $step, $plugin_ID );
	}


	public function install_stop() {

		$this->_hanlder->install_stop();
	}
}libs/better-framework/product-pages/install-demo/class-bf-demo-taxonomy-manager.php000064400000016720151214002520024531 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Class BF_Demo_Taxonomy_Manager
 */
class BF_Demo_Taxonomy_Manager {


	/**
	 * prepare term params. add default indexes and filter some indexes.
	 *
	 * @param array $term_params
	 */
	protected function parse_term_params( &$term_params ) {

		$term_params = bf_merge_args( $term_params, array(
			'term_id'  => '',
			'name'     => '',
			'slug'     => '',
			'taxonomy' => 'category',
		) );

		BF_Product_Demo_Installer::data_params_filter( $term_params );
	}


	/**
	 * Add a new term to the database.
	 *
	 * @param array $term_params
	 *
	 * @return array|WP_Error WP_Error or empty array on failure or An array containing the `term_id` and
	 *                        `term_taxonomy_id` on success
	 *
	 */
	public function add_term( $term_params ) {

		$this->parse_term_params( $term_params );

		if ( ! $term_params['name'] ) {
			return new WP_Error( 'empty_term_name', 'term name could not be empty.' );
		}

		if ( empty( $term_params['slug'] ) ) {
			$term_params['slug'] = 'bs-' . sanitize_title( $term_params['name'] );
		}

		// Term Exists!? try to make unique copy!
		{
			$term_id = term_exists( $term_params['name'], $term_params['taxonomy'] );

			if ( $term_id !== 0 && $term_id !== null ) {
				$term_params['slug'] .= '-' . mt_rand( 1000, 100000 );
			}
		}

		$added_term = wp_insert_term( $term_params['name'], $term_params['taxonomy'], $term_params );

		if ( is_wp_error( $added_term ) ) {
			return $added_term;
		}

		if ( isset( $added_term['term_id'] ) ) {
			return $added_term['term_id'];
		}

		return array();
	}


	/**
	 * Removes a term from the database.
	 *
	 * @param array $term_params
	 *
	 * @return bool|int|WP_Error true on success, false if term does not exist. Zero on attempted
	 *                           deletion of default Category. WP_Error if the taxonomy does not exist.
	 */
	public function remove_term_by_params( $term_params ) {

		$this->parse_term_params( $term_params );

		return wp_delete_term( $term_params['term_id'], $term_params['taxonomy'], $term_params );
	}


	/**
	 * Removes a term from the database by unique term ID,
	 *
	 * @param int $term_id
	 *
	 * @return bool true on success or false on failure.
	 */
	public function remove_term( $term_id ) {

		settype( $term_id, 'integer' );


		$term = $this->get_term( $term_id );

		if ( $term && ! is_wp_error( $term ) ) {

			$deleted = wp_delete_term( intval( $term_id ), $term->taxonomy );

			return $deleted && ! is_wp_error( $deleted );
		}

		return false;
	}


	/**
	 * Get term just by term id
	 *
	 * get_term $taxonomy param become optional since version 4.4.0
	 * this function pass taxonomy param for version before 4.4.0
	 *
	 * @param int     $term_id    unique term id in database
	 *
	 * @global string $wp_version wordpress version number
	 *
	 * @return mixed|null|WP_Error
	 * @see get_term()
	 */
	public function get_term( $term_id ) {

		global $wp_version;


		$params = array( $term_id );
		if ( version_compare( '4.4.0', $wp_version, '>' ) ) {
			//its older version!
			$params[1] = $this->get_taxonomy_by_term_id( $term_id );
		}

		return call_user_func_array( 'get_term', $params );
	}


	/**
	 * get term taxonomy by term ID
	 *
	 * @param       $term_id
	 *
	 * @global wpdb $wpdb wordpress database object
	 *
	 * @return bool|string not a empty string on success empty string or false otherwise.
	 */
	protected function get_taxonomy_by_term_id( $term_id ) {

		global $wpdb;

		$taxonomy = wp_cache_get( $term_id, 'term-id-taxonomy' );

		if ( $taxonomy === false ) {
			$taxonomy = $wpdb->get_var( $wpdb->prepare( "SELECT taxonomy FROM $wpdb->term_taxonomy WHERE term_id = %d", $term_id ) );
			wp_cache_add( $term_id, $taxonomy, 'term-id-taxonomy' );
		}

		return $taxonomy;
	}


	/**
	 *
	 * prepare a array with three index to pass add,delete,update term meta function
	 *  via call_user_func_array function.
	 *
	 * @param array $term_meta_params
	 *
	 * @return array none empty array on success
	 */
	protected function get_meta_params( $term_meta_params ) {

		$required_params = array(
			'term_id'    => '',
			'meta_key'   => '',
			'meta_value' => '',
		);

		if ( ! array_diff_key( $required_params, $term_meta_params ) ) {

			return array(
				$term_meta_params['term_id'],
				$term_meta_params['meta_key'],
				$term_meta_params['meta_value']
			);
		}

		return array();
	}


	/**
	 *
	 * Adds metadata to a term.
	 *
	 * @param array $term_meta_params
	 *
	 * @return int|WP_Error|bool Meta ID on success. WP_Error when term_id is ambiguous between taxonomies.
	 *                           False on failure.
	 */
	public function add_term_meta( $term_meta_params ) {

		if ( $meta_params = $this->get_meta_params( $term_meta_params ) ) {
			return call_user_func_array( 'bf_add_term_meta', $meta_params );
		}

		return false;
	}


	/**
	 * Delete inserted term meta
	 *
	 * @param array $term_data  array {
	 *
	 * @type int    $term_id    term ID
	 * @type string $meta_key   Term meta key
	 * @type mixed  $meta_value Term value
	 * }
	 *
	 * @return bool true on successful delete, false on failure.
	 */

	public function remove_term_meta( $term_data ) {

		$required_params = array(
			'term_id'    => '',
			'meta_key'   => '',
			'meta_value' => '',
		);

		if ( ! array_diff_key( $required_params, $term_data ) ) {
			return bf_delete_term_meta( $term_data['term_id'], $term_data['meta_key'], $term_data['meta_value'] );
		}

		return false;
	}


	/**
	 * Delete term metadata from database.
	 *
	 * @param array $term_meta_params
	 *
	 * @return int|WP_Error|bool Meta ID on success. WP_Error when term_id is ambiguous between taxonomies.
	 *                           False on failure.
	 */
	public function delete_term_meta( $term_meta_params ) {

		if ( $meta_params = $this->get_meta_params( $term_meta_params ) ) {

			return call_user_func_array( 'bf_delete_term_meta', $meta_params );
		}

		return false;
	}


	/**
	 * update term meta data
	 *
	 * @param array $term_meta_params
	 *
	 * @return int|WP_Error|bool true on successful WP_Error|False on failure.
	 */
	public function update_term_meta( $term_meta_params ) {

		if ( $meta_params = $this->get_meta_params( $term_meta_params ) ) {
			$meta_params[3] = isset( $term_meta_params['prev_value'] ) ? $term_meta_params['prev_value'] : '';

			return call_user_func_array( 'bf_update_term_meta', $meta_params );
		}

		return false;
	}


	/**
	 * get term meta data.
	 *
	 * @param array $term_meta_params
	 *
	 * @return mixed meta value.
	 */
	public function get_term_meta( $term_meta_params ) {

		if ( $meta_params = $this->get_meta_params( $term_meta_params ) ) {
			$term_id   = &$meta_params[0];
			$meta_key  = &$meta_params[1];
			$is_single = isset( $term_meta_params['single'] ) ? $term_meta_params['single'] : false;

			return bf_get_term_meta( $meta_key, $term_id, '', $is_single );
		}

		return '';
	}
}
libs/better-framework/product-pages/install-demo/class-bf-product-demo-manager.php000064400000042401151214002520024326 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! class_exists( 'BF_Product_Multi_Step_Item' ) ) {
	if ( is_admin() ) {
		require_once BF_PRODUCT_PAGES_PATH . 'backend.php';
	} else {
		require_once BF_PRODUCT_PAGES_PATH . 'frontend.php';
	}
}


/**
 * Class BF_Product_Demo_Manager
 */
class BF_Product_Demo_Manager extends BF_Product_Multi_Step_Item {

	/**
	 * module id
	 *
	 * @var string
	 */
	public $id = 'install-demo';

	/**
	 * plugin installation step name have this prefix
	 *
	 * @var string
	 */
	public $plugin_installation_step_prefix = 'plugin_';

	/**
	 * demo import data context.  content or setting
	 *
	 * @var string
	 */
	public $data_context = 'content';


	protected function before_render() {

		if ( ! class_exists( 'BF_Product_Demo_Installer' ) ) {
			require_once BF_Product_Pages::get_path( 'install-demo/class-bf-product-demo-installer.php' );
		}
	}


	/**
	 * HTML output to display admin user.
	 *
	 * @param $options
	 */
	public function render_content( $options ) {

		if ( $demos_list = apply_filters( 'better-framework/product-pages/install-demo/config', array() ) ) :

			$is_active = bf_is_product_registered();

			?>
			<div class="bs-product-pages-install-demo">

				<?php

				foreach ( $demos_list as $demo_id => $demo_data ) :

					?>
					<div
							class="bf-item-container bs-pages-demo-item<?php if ( BF_Product_Demo_Installer::is_demo_installed( $demo_id ) ) {
								echo ' installed';
							}
							echo ! $is_active ? ' not-active' : ''; ?>">
						<div class="bs-pages-overlay "></div>

						<div class="bs-pages-ribbon-wrapper">
							<div class="bs-pages-ribbon">
							</div>
							<div class="bs-pages-ribbon-label">
								<i class="fa fa-check"></i>
							</div>
						</div>

						<figure>
							<img src="<?php echo esc_url( $demo_data['thumbnail'] ) ?>"
							     alt="<?php echo esc_attr( $demo_data['name'] ); ?>"
							     class="bs-demo-thumbnail">

							<?php if ( ! empty( $demo_data['badges'] ) ) { ?>
								<div class="demo-badges">
									<?php

									foreach ( (array) $demo_data['badges'] as $badge ) {
										echo '<span class="badge badge-', esc_attr( $badge ), '" >', $badge, '</span>';
									}

									?>
								</div>
							<?php } ?>
						</figure>
						<div class="bs-pages-progressbar">
							<div class="bs-pages-progress">

							</div>

						</div>

						<footer class="bf-item-footer bs-pages-demo-item-footer bf-clearfix">
							<span class="bf-item-title bs-pages-demo-name">
									<?php echo esc_html( $demo_data['name'] ); ?>
							</span>

							<?php if ( $is_active ) { ?>
								<div class="bf-item-buttons bs-pages-buttons"
								     data-demo-id="<?php echo esc_attr( $demo_id ) ?>">
									<?php #if ( has_filter( 'better-framework/product-pages/install-demo/' . $demo_id ) ) :
									?>
									<span class="install-demo highlight-section">
									<a href="#"
									   class="bf-btn-primary bs-pages-primary-btn"
									   disabled="disabled"><?php esc_html_e( 'Install', 'better-studio' ) ?></a>
								</span>
									<?php #endif;
									?>
									<span class="preview-demo">
									<a href="<?php echo esc_url( $demo_data['preview_url'] ); ?>" target="_blank"
									   class="bf-btn-secondary bs-pages-secondary-btn"><?php esc_html_e( 'Preview', 'better-studio' ) ?></a>
								</span>
									<span class="uninstall-demo highlight-section">
									<a href="#"
									   class="bf-btn-secondary bs-pages-secondary-btn"><?php esc_html_e( 'Uninstall', 'better-studio' ) ?></a>
								</span>
								</div>
								<div class="messages">
									<div class="installing highlight-section">
										<i class="fa fa-refresh fa-spin"></i>
										<?php esc_html_e( 'Installing...', 'better-studio' ) ?>
									</div>
									<div class="uninstalling highlight-section">
										<i class="fa fa-refresh fa-spin"></i>
										<?php esc_html_e( 'Uninstalling...', 'better-studio' ) ?>
									</div>
									<div class="installed highlight-section">
										<i class="fa fa-check"></i>
										<?php esc_html_e( 'Installed', 'better-studio' ) ?>
									</div>
									<div class="uninstalled highlight-section">
										<i class="fa fa-check"></i>
										<?php esc_html_e( 'Uninstalled', 'better-studio' ) ?>
									</div>
									<div class="failed">
										<?php esc_html_e( 'Process failed', 'better-studio' ) ?>
									</div>
								</div>
							<?php } else { ?>
								<span
										class="active-error"><?php _e( 'Please register your theme', 'better-studio' ); ?></span>
							<?php } ?>
						</footer>
					</div>
				<?php endforeach ?>

				<div class="clearfix"></div>
			</div>

			<?php

		else:

			//TODO: add alert class to this message
			echo 'no demo registered';

		endif;
	}


	/**
	 * @return null|BF_Product_Plugin_Manager object on success null otherwise
	 */
	protected function get_plugin_manager_instance() {

		$plugin_installer = BF_Product_Pages::Run()->get_item_handler_instance( 'plugins' );

		if ( $plugin_installer ) {

			return $plugin_installer;
		}
	}


	/**
	 * @return null|BF_Demo_Install_Plugin_Adapter object on success null otherwise
	 */
	protected function get_plugin_installer_adapter() {


		if ( ! class_exists( 'BF_Demo_Install_Plugin_Adapter' ) ) {

			$class_path = BF_Product_Pages::get_path( 'install-demo/class-bf-demo-install-plugin-adapter.php' );

			if ( file_exists( $class_path ) ) {
				require_once $class_path;
			}

			return new BF_Demo_Install_Plugin_Adapter();
		}
	}


	/**
	 * Calculate how many step needs to complete installation of demo.
	 *
	 * @param string $demo_id       Demo ID
	 * @param string $context       Demo process action( install|uninstall )
	 *
	 * @return array|bool boll on failure or array on success.
	 *
	 * array {
	 *
	 * @type         $total         integer number of total steps
	 * @type         $step          array    each data type, how many step need to complete.
	 * @type         $plugins       only plugin installation process. how many step needs to complete  install plugin.
	 *
	 * }
	 *
	 */
	protected function calculate_process_steps( $demo_id, $context = 'install' ) {

		$demo_data = $this->get_demo_data( $demo_id );

		if ( empty( $demo_data ) ) {
			return false;
		}

		$total = 0;
		$steps = $plugins = array();

		// calculate how many steps take to complete installation plugin process

		if ( ! empty( $demo_data['plugins'] ) && is_array( $demo_data['plugins'] ) ) {

			/**
			 * @var $plugin_manager BF_Product_Plugin_Manager
			 */
			$plugin_manager = $this->get_plugin_manager_instance();

			if ( $plugin_manager ) {

				$plugins_list = $plugin_manager->get_plugins_data();

				foreach ( $demo_data['plugins'] as $plugin_ID ) {

					if ( ! isset( $plugins_list[ $plugin_ID ] ) ) {
						continue;
					}

					$plugin_data          = &$plugins_list[ $plugin_ID ];
					$installation_process = $plugin_manager->calculate_process_steps( $plugin_data, 'install', true );

					if ( isset( $installation_process['steps'] ) ) {

						$total                                                        += $installation_process['total'];
						$steps[ $this->plugin_installation_step_prefix . $plugin_ID ] = $installation_process['total'];

						$plugins[ $plugin_ID ] = $installation_process;
					}

				}

			}
		}

		if ( ! class_exists( 'BF_Product_Demo_Installer' ) ) {
			require_once BF_Product_Pages::get_path( 'install-demo/class-bf-product-demo-installer.php' );
		}

		foreach ( BF_Product_Demo_Installer::import_data_sequence() as $type ) {

			if ( ! isset( $demo_data[ $type ] ) ) {
				continue;
			}

			$data = &$demo_data[ $type ];

			if ( ( $context === 'uninstall' && ( ! isset( $data['uninstall_multi_steps'] ) || ! $data['uninstall_multi_steps'] ) )
			     ||
			     ( $context !== 'uninstall' && ( ! isset( $data['multi_steps'] ) || ! $data['multi_steps'] ) )
			) {

				$steps[ $type ] = 1;
				$total ++;
			} else {

				unset( $data['multi_steps'] );
				unset( $data['uninstall_multi_steps'] );

				$current_type_steps = $this->calc_steps( $data, $type );
				$steps[ $type ]     = $current_type_steps;
				$total              += $current_type_steps;
			}
		}

		// uninstalling step have a extra step called clean, to make sure
		// all temporary data will deleted and uninstalling completed.
		if ( $context === 'uninstall' ) {
			$steps['clean'] = 1;
			$total ++;

		}

		return compact( 'total', 'steps', 'plugins' );
	}


	/**
	 * Calculate how many step needs to import data
	 *
	 * @param array  $data      array of data
	 * @param string $data_type {@see BF_Product_Demo_Factory::import_data_sequence}
	 *
	 * @return int number of steps
	 */
	public function calc_steps( $data, $data_type ) {

		$method   = sprintf( 'calc_%s_per_step', $data_type );
		$callback = array( $this, $method );

		if ( is_callable( $callback ) ) {
			$step = call_user_func( $callback, $data );

			return ceil(
				bf_count( $data ) /
				$step
			);
		}

		return bf_count( $data );
	}


	/**
	 * Calculate how many step needs to import media per each step
	 *
	 * @return int number of steps
	 */
	public function calc_media_per_step() {

		$is_memory_enough = bf_is_ini_value_changeable() || wp_convert_hr_to_bytes( WP_MEMORY_LIMIT ) < 67108864; // 64MB

		if ( ! $is_memory_enough ) {
			$import_per_step = 2;
		} elseif ( version_compare( '5.3', PHP_VERSION, '>' ) ) {
			$import_per_step = 2;
		} elseif ( version_compare( '5.5', PHP_VERSION, '>' ) ) {
			$import_per_step = 3;
		} elseif ( version_compare( '5.5', PHP_VERSION, '<=' ) ) {
			$import_per_step = 4;
		} else {
			$import_per_step = 2;
		}

		return apply_filters( 'better-framework/product-pages/install-demo/media-per-steps', $import_per_step, $is_memory_enough );
	}


	/**
	 * @param array  $demo_data
	 * @param string $context
	 *
	 * @return array
	 */
	public function prepare_data_before_import( $demo_data, $context = 'install' ) {

		foreach ( $demo_data as $data_type => $data ) {
			$method   = sprintf( 'calc_%s_per_step', $data_type );
			$callback = array( $this, $method );

			if ( is_callable( $callback ) ) {
				$step = call_user_func( $callback );

				if ( ( $context === 'uninstall' && ( ! isset( $data['uninstall_multi_steps'] ) || ! $data['uninstall_multi_steps'] ) )
				     ||
				     ( $context !== 'uninstall' && ( ! isset( $data['multi_steps'] ) || ! $data['multi_steps'] ) )
				) {
					$demo_data[ $data_type ] = array( $data );
				} else {
					$demo_data[ $data_type ] = $this->array_chunk( $data, $step );
				}
			}
		}

		return $demo_data;
	}


	/**
	 * @param array $array
	 * @param int   $size
	 *
	 * @return array
	 */
	protected function array_chunk( $array, $size ) {

		$array2merge = array();
		// list of keys to skip chunk action
		$ignore_chunk = array(
			'multi_steps',
			'uninstall_multi_steps'
		);
		foreach ( $ignore_chunk as $key ) {
			if ( isset( $array[ $key ] ) ) {
				$array2merge[ $key ] = $array[ $key ];

				unset( $array[ $key ] );
			}
		}

		$result = array_chunk( $array, $size );
		if ( $array2merge ) {
			$result = array_merge( $array2merge, $result );
		}

		return $result;
	}


	/**
	 * @param string $demo_id
	 *
	 * @return array
	 */
	protected function get_demo_data( $demo_id ) {

		return bf_get_demo_data( $demo_id, $this->data_context );
	}


	/**
	 * ajax handler for demo install/unInstall demo requests
	 *
	 * @param Array $params
	 *
	 * @return bool true on success or false on failure.
	 *
	 * @see BS_Theme_Pages_Item::append_hidden_fields()
	 */
	public function ajax_request( $params ) {

		$required_params = array(
			'bs_pages_action' => '',
			'demo_id'         => '',
			'context'         => '',
		);

		if ( array_diff_key( $required_params, $params ) ) {
			return false;
		}
		$demo_id = &$params['demo_id'];

		//set demo data context
		if ( $params['context'] === 'install' ) {

			$this->data_context = isset( $params['have_content'] ) && $params['have_content'] === 'no' ? 'setting' : 'content';
		} elseif ( $params['context'] === 'uninstall' ) {

			// read data context saved in database when demo installed
			$option_name  = sprintf( 'bs_demo_id_%s', $demo_id );
			$option_value = get_option( $option_name, array() );

			if ( ! empty( $option_value['_context'] ) ) {
				$this->data_context = $option_value['_context'];
			}

		}

		$response = array();
		try {
			switch ( $params['bs_pages_action'] ) {

				case 'get_steps':

					if ( $install_steps = $this->calculate_process_steps( $params['demo_id'], $params['context'] ) ) {

						$this->set_steps_data( $params['demo_id'], $install_steps );

						$response = array(
							'steps'       => array_values( $install_steps['steps'] ),
							'types'       => array_keys( $install_steps['steps'] ),
							'steps_count' => bf_count( $install_steps['steps'] ) - 1,
							'total'       => $install_steps['total'],
						);
					}

					//save demo data context to database, used to rollback demo
					if ( $params['context'] === 'install' ) {
						$option_name              = sprintf( 'bs_demo_id_%s', $demo_id );
						$option_value             = get_option( $option_name, array() );
						$option_value['_context'] = $this->data_context;
						update_option( $option_name, $option_value, 'no' );
					}

					break;


				case 'import':

					if ( isset( $params['current_type'] ) && isset( $params['current_step'] ) ) {

						$type  = &$params['current_type'];
						$step  = intval( $params['current_step'] );
						$index = $step - 1;


						$current_data = false;
						$demo_data    = $this->get_demo_data( $demo_id );
						$demo_data    = $this->prepare_data_before_import( $demo_data );

						//					$is_single_step = empty( $demo_data[ $type ]['multi_step'] );

						if ( isset( $demo_data[ $type ][ $index ] ) ) {

							$current_data = &$demo_data[ $type ][ $index ];

							if ( ! class_exists( 'BF_Product_Demo_Installer' ) ) {
								require_once BF_Product_Pages::get_path( 'install-demo/class-bf-product-demo-installer.php' );
							}

							$response = BF_Product_Demo_Installer::Run()->import_start( $current_data, $type, $index, $demo_id, $this->data_context );

							BF_Product_Demo_Installer::Run()->import_stop();

							if ( $this->is_final_step( $demo_id, $type, $step ) ) {

								$this->delete_steps_data( $demo_id );

								BF_Product_Demo_Installer::Run()->import_finished();
							}
						} else {

							//make sure its plugin installation step
							$pattern = preg_quote( $this->plugin_installation_step_prefix );
							if ( preg_match( "/^$pattern(.+)/i", $params['current_type'], $matched ) ) {

								$plugin_ID = &$matched[1];
								$step      = intval( $params['current_step'] );

								/**
								 * @var $plugin_installer BF_Demo_Install_Plugin_Adapter
								 * @var $plugin_manager   BF_Product_Plugin_Manager
								 */
								$plugin_installer = $this->get_plugin_installer_adapter();
								$plugin_manager   = $this->get_plugin_manager_instance();

								$steps_data = $this->get_steps_data( $demo_id );

								if ( $plugin_installer && $plugin_manager ) {

									$step_data = $this->get_steps_data( $demo_id );

									if ( isset( $step_data['plugins'][ $plugin_ID ] ) ) {

										$plugin_steps = &$step_data['plugins'][ $plugin_ID ];

										$plugin_installer->install_start( $plugin_steps, $step, $plugin_ID );
										$plugin_installer->install_stop();
									}
								}

								$response = true;
							}
						}
					}
					break;

				case 'rollback':

					if ( isset( $params['current_type'] ) && isset( $params['current_step'] ) ) {

						$type  = &$params['current_type'];
						$step  = intval( $params['current_step'] );
						$index = $step - 1;

						if ( ! class_exists( 'BF_Product_Demo_Installer' ) ) {
							require_once BF_Product_Pages::get_path( 'install-demo/class-bf-product-demo-installer.php' );
						}

						$response = BF_Product_Demo_Installer::Run()->rollback_start( $type, $index, $demo_id, $this->data_context );
						$response = is_wp_error( $response ) ? $response : true;

						BF_Product_Demo_Installer::Run()->rollback_stop();
					}
					break;

				case 'rollback_force':

					if ( ! class_exists( 'BF_Product_Demo_Installer' ) ) {
						require_once BF_Product_Pages::get_path( 'install-demo/class-bf-product-demo-installer.php' );
					}

					$response = true;
					BF_Product_Demo_Installer::Run()->rollback_force( $demo_id, $this->data_context );
					break;
			}
		} catch( Exception $e ) {
			$response = new WP_Error( $e->getCode(), $e->getMessage() );
		}

		if ( is_wp_error( $response ) ) {
			/**
			 * @var WP_Error $response
			 */
			$response = array(
				'is_error'      => true,
				'error_message' => $response->get_error_message(),
				'error_code'    => $response->get_error_code(),
			);
		}

		if ( $response ) {
			return $response;
		}

		return false;
	} // ajax_request
}libs/better-framework/product-pages/install-demo/class-bf-demo-menu-manager.php000064400000020640151214002520023613 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Class BF_Demo_Menu_Manager
 *
 * Create Nav Menu & Nav Menu Item
 */
//TODO: add better-framework menu options support
class BF_Demo_Menu_Manager {

	public $menu_id = 0;


	/**
	 * Get nav menu object
	 *
	 * @param string|int|object $menu Menu ID, slug, or name - or the menu object.
	 *
	 * @return object|bool menu object on success or false on error;
	 */
	protected function get_menu( $menu ) {

		$menu_object = wp_get_nav_menu_object( $menu );
		if ( is_object( $menu_object ) && isset( $menu_object->term_id ) ) {
			return $menu_object;
		}

		return false;
	}


	/**
	 * Try to Create new Menu if not already exists.
	 *
	 * @param string $menu_name name of the navigation menu
	 * @param string $location  navigation menu location registered by register_nav_menu() function.
	 * @param bool   $unique    optional. create unique menu if menu already exists, default true.
	 *
	 * @return array|int|WP_Error return false or WP_Error on failure or array on success.
	 *          array result contain {
	 * @type integer $menu_id   Navigation Menu ID in database
	 * @type bool    $exists    Navigation exists before
	 *          }
	 */
	function create_menu( $menu_name, $location, $unique = true ) {

		if ( $unique ) {
			$original_name = $menu_name;
			$suffix        = 2;
			while( $menu_object = $this->get_menu( $menu_name ) ) {
				$menu_name = $original_name . ' ' . $suffix;
				$suffix ++;
			}
		} else {
			$menu_object = $this->get_menu( $menu_name );
		}

		if ( ! is_object( $menu_object ) || ! isset( $menu_object->term_id ) ) {

			$maybe_menu_id = wp_create_nav_menu( $menu_name );

			if ( is_wp_error( $maybe_menu_id ) ) {

				return $maybe_menu_id;
			}
			$menu_id = &$maybe_menu_id;
			$exists  = false;

		} else {

			$exists  = true;
			$menu_id = &$menu_object->term_id;
		}


		$menu_locations = get_theme_mod( 'nav_menu_locations' );

		// activate the menu only if it's not already active
		if ( empty( $menu_locations[ $location ] ) || $menu_locations[ $location ] != $menu_id ) {
			$menu_locations[ $location ] = $menu_id;
			set_theme_mod( 'nav_menu_locations', $menu_locations );
		}

		$this->menu_id = $menu_id;

		return array( $menu_id, $exists );
	} // create_menu


	/**
	 * @param string $menu Menu ID, slug, or name.
	 *
	 * @return bool true on success or false on failure.
	 */
	public function remove_menu( $menu ) {

		$deleted = wp_delete_nav_menu( $menu );

		return $deleted && ! is_wp_error( $deleted );
	}


	/**
	 * Set active menu id
	 * uses by some methods
	 *
	 * @param int $menu_id
	 *
	 * @return bool true on success or false on failure.
	 */
	public function set_menu_id( $menu_id ) {

		$menu_object = wp_get_nav_menu_object( (int) $menu_id );

		if ( ! is_object( $menu_object ) || ! isset( $menu_object->term_id ) ) {
			return false;
		}

		$this->menu_id = $menu_id;

		return true;
	}


	/**
	 * @param array $menu_params The menu item's data.
	 *
	 * @see wp_update_nav_menu_item() $menu_item_data parameter
	 *
	 * @return int|WP_Error WP_ERROR on failure or item ID on success.
	 */
	public function create_link( $menu_params ) {

		$menu_item_data = bf_merge_args( $menu_params, array(
			'menu-item-object'    => '',
			'menu-item-title'     => '',
			'menu-item-url'       => '',
			'menu-item-type'      => 'custom',
			'menu-item-status'    => 'publish',
			'menu-item-parent-id' => 0
		) );

		if ( ! $menu_item_data['menu-item-title'] && $menu_item_data['menu-item-type'] == 'custom' ) {
			return new WP_Error( 'empty_menu_title', 'menu-item-title cannot be empty!' );
		}

		if ( $menu_item_data['menu-item-type'] === 'post_type' ) {

			//object-id is required param for post_type item type
			if ( empty( $menu_item_data['menu-item-object-id'] ) ) {
				return 0;
			}
			if ( ! $menu_item_data['menu-item-url'] ) {
				$menu_item_data['menu-item-url'] = get_permalink( $menu_item_data['menu-item-object-id'] );
			}

			if ( ! $menu_item_data['menu-item-title'] ) {
				$menu_item_data['menu-item-title'] = get_post_field( 'post_title', $menu_item_data['menu-item-object-id'] );
			}
		}

		$maybe_menu_item_id = wp_update_nav_menu_item( $this->menu_id, 0, $menu_item_data );

		if ( is_wp_error( $maybe_menu_item_id ) ) {
			return $maybe_menu_item_id;
		}

		$menu_item_id = &$maybe_menu_item_id;

		return $menu_item_id;
	} // create_link


	/**
	 * @param array $item_id menu item ID Generated by $this->create_link()
	 *
	 * @return bool true on success or false on failure
	 */
	public function remove_item( $item_id ) {

		//TODO: delete item from nav menu object

		return (bool) wp_delete_post( $item_id, true );
	}


	/**
	 * add "menu-item-" prefix to array indexes
	 *
	 * @param Array $params
	 */
	protected function prepare_menu_params( &$params ) {

		$new_params = array();


		BF_Product_Demo_Installer::data_params_filter( $params );

		foreach ( $params as $key => $value ) {
			$new_params[ 'menu-item-' . $key ] = $value;
		}


		$params = $new_params;
	}


	/**
	 * append custom link to menu
	 * array {
	 *
	 * @type string $title menu title
	 * @type string $url   menu url
	 * }
	 *
	 * @see create_link()
	 *
	 * @param Array $params
	 *
	 * @return int|WP_Error WP_ERROR on failure or item ID on success.
	 */
	public function append_link( $params ) {

		$this->prepare_menu_params( $params );

		return $this->create_link( $params );
	}


	/**
	 * @param int   $page_id page id in database
	 * @param array $params  additional setting
	 *
	 * @see create_menu()
	 *
	 * @return int|WP_Error WP_ERROR on failure or item ID on success.
	 */
	public function append_page_link( $page_id, $params = array() ) {

		$params = bf_merge_args( $params, array(
			'object'    => 'page',
			'type'      => 'post_type',
			'object-id' => $page_id
		) );

		$this->prepare_menu_params( $params );

		return $this->create_link( $params );
	}


	/**
	 * append custom post type link to menu
	 *
	 * @param int    $post_id   Post ID in Database
	 * @param string $post_type Post Type
	 * @param array  $params
	 *
	 * @see create_link()
	 *
	 * @return int|WP_Error WP_ERROR on failure or item ID on success.
	 */
	public function append_post_link( $post_id, $post_type = 'post', $params = array() ) {

		$params = bf_merge_args( $params, array(
			'object'    => $post_type,
			'type'      => 'post_type',
			'object-id' => $post_id
		) );

		$this->prepare_menu_params( $params );

		return $this->create_link( $params );
	}


	/**
	 * append taxonomy link to menu
	 *
	 * @param int    $term_id  Term ID in Database
	 * @param string $taxonomy The taxonomy name to use
	 * @param array  $params
	 *
	 * @return int|bool|WP_Error WP_ERROR or false on failure or item ID on success.
	 */
	public function append_taxonomy_link( $term_id, $taxonomy, $params = array() ) {

		if ( ! taxonomy_exists( $taxonomy ) ) {
			return false;
		}

		settype( $term_id, 'int' );

		if ( ! term_exists( $term_id, $taxonomy ) ) {
			return false;
		}

		$params = bf_merge_args( $params, array(
			'object-id' => $term_id,
			'type'      => 'taxonomy',
			'object'    => $taxonomy,
			'url'       => get_term_link( $term_id, $taxonomy )
		) );


		$this->prepare_menu_params( $params );

		return $this->create_link( $params );
	}


	/**
	 * append category item to menu
	 *
	 * @param int $category_id
	 *
	 * @see append_taxonomy_link()
	 *
	 * @return int|bool|WP_Error WP_ERROR or false on failure or item ID on success.
	 */

	public function append_category_link( $category_id ) {

		return $this->append_taxonomy_link( $category_id, 'category' );
	}


	/**
	 * append tag item to menu
	 *
	 * @param int $tag_id
	 *
	 * @see append_taxonomy_link()
	 *
	 * @return int|bool|WP_Error WP_ERROR or false on failure or item ID on success.
	 */
	public function append_tag_link( $tag_id ) {

		return $this->append_taxonomy_link( $tag_id, 'post_tag' );
	}

}
libs/better-framework/product-pages/install-demo/functions.php000064400000013204151214002520020633 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * get image URI by attachment ID
 *
 * @param        $attachment_id image attachment ID.
 * @param string $size          image size identifier
 *
 * @see add_image_size
 *
 * @return string image attachment url on success empty string otherwise.
 */
function bf_product_demo_media_url( $attachment_id, $size = 'thumbnail' ) {

	if ( $src = wp_get_attachment_image_src( $attachment_id, $size ) ) {

		return $src[0];
	}

	return '';
}

/**
 * enqueue static files
 */
function bf_install_demo_enqueue_scripts() {

	if ( bf_is_product_page( 'install-demo' ) ) {

		$ver = BF_Product_Pages::Run()->get_version();

		bf_enqueue_script( 'bf-modal' );
		bf_enqueue_style( 'bf-modal' );

		wp_enqueue_style( 'bs-product-demo-styles', BF_Product_Pages::get_url( 'install-demo/assets/css/bs-product-demo.css' ), array(), $ver );

		wp_enqueue_script( 'bs-product-demo-scripts', BF_Product_Pages::get_url( 'install-demo/assets/js/bs-product-demo.js' ), array(), $ver );

		wp_localize_script( 'bs-product-demo-scripts', 'bs_demo_install_loc', array(
			'checked_label'   => __( 'Include content', 'better-studio' ),
			'unchecked_label' => __( 'Only settings', 'better-studio' ),


			'install' => array(
				'title'      => __( 'Are you sure to install demo?', 'better-studio' ),
				'header'     => __( 'Import Demo', 'better-studio' ),
				'body'       => wp_kses( __( '<p>This will import our predefined settings for the demo (background, template layouts, fonts, colors etc...) and our sample content.</p>
				<p>The demo can be fully uninstalled via the uninstall button. Please backup your settings to be sure that you don\'t lose them by accident.</p>
				', 'better-studio' ), bf_trans_allowed_html() ),
				'button_yes' => __( 'Yes, Import', 'better-studio' ),
				'button_no'  => __( 'Cancel', 'better-studio' ),
			),

			'uninstall' => array(
				'title'      => __( 'Are your sure to uninstall this demo?', 'better-studio' ),
				'header'     => __( 'Confirm Uninstalling Demo', 'better-studio' ),
				'body'       => __( 'By uninstalling demo all configurations from widgets, options, menus and other settings that was comes from our demo content will be removed and your settings will be rollback to before demo installation.', 'better-studio' ),
				'button_yes' => __( 'Yes, Uninstall', 'better-studio' ),
				'button_no'  => __( 'No, do not', 'better-studio' ),
			),

			'on_error' => array(
				'button_ok'       => __( 'Ok', 'better-studio' ),
				'default_message' => __( 'Cannot install demo.', 'better-studio' ),
				'body'            => __( 'Please try again several minutes later or contact better studio team support.', 'better-studio' ),
				'header'          => __( 'Demo installation failed', 'better-studio' ),
				'title'           => __( 'An error occurred while installing demo', 'better-studio' ),
				'display_error'   => __( '<div class="bs-pages-error-section">
					<a href="#" class="btn bs-pages-error-copy" data-copied="' . esc_attr__( 'Copied !', 'better-studio' ) . '">
						<i class="fa fa-files-o" aria-hidden="true"></i> Copy</a>  <textarea> Error:  %ERROR_CODE% %ERROR_MSG% </textarea>
				</div>', 'better-studio' ),
			),

			'uninstall_error' => array(
				'button_ok'       => __( 'Ok', 'better-studio' ),
				'default_message' => __( 'Cannot uninstall demo.', 'better-studio' ),
				'body'            => __( 'Please try again several minutes later or contact better studio team support.', 'better-studio' ),
				'header'          => __( 'Demo uninstalling process failed', 'better-studio' ),
				'title'           => __( 'An error occurred while uninstalling demo', 'better-studio' ),
			),

			'uninstall_start_error' => array(
				'button_ok'       => __( 'Ok', 'better-studio' ),
				'default_message' => __( 'Cannot install demo.', 'better-studio' ),
				'body'            => __( 'Please click ok and try again', 'better-studio' ),
				'header'          => __( 'Demo uninstalling process failed', 'better-studio' ),
				'title'           => __( 'An error occurred while uninstalling demo', 'better-studio' ),
			),

			'install_start_error' => array(
				'button_ok'       => __( 'Ok', 'better-studio' ),
				'default_message' => __( 'Cannot install demo.', 'better-studio' ),
				'body'            => __( 'Please click ok and try again', 'better-studio' ),
				'header'          => __( 'Demo installing process failed', 'better-studio' ),
				'title'           => __( 'An error occurred while installing demo', 'better-studio' ),
			),
		) );
	}

}

add_action( 'admin_enqueue_scripts', 'bf_install_demo_enqueue_scripts' );

/**
 * Get demo data
 *
 * @param string $demo_id demo id
 * @param string $context demo context content or settings
 *
 * @return array
 */
function bf_get_demo_data( $demo_id, $context = 'content' ) {

	static $data = array();
	if ( ! isset( $data[ $demo_id ] ) ) {
		$data[ $demo_id ] = apply_filters( 'better-framework/product-pages/install-demo/' . $demo_id . '/' . $context, array(), $demo_id );
	}

	return $data[ $demo_id ];
}libs/better-framework/product-pages/install-demo/class-bf-product-demo-installer.php000064400000123321151214002520024712 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Class BF_Product_Demo_Factory
 *
 * Demo install & unInstaller handler
 */
class BF_Product_Demo_Installer extends BF_Product_Pages_Base {

	/**
	 * list of temporary IDs while insert data to database.
	 *
	 * @var array
	 */
	public $id_list = array();

	/**
	 * temporary rollback data.
	 *
	 * @var array
	 */
	public $rollback_data = array();

	/**
	 * active demo ID
	 *
	 * @var string
	 */
	public $demo_id;

	/**
	 * active demo context
	 *
	 * @see bf_get_demo_data
	 *
	 * @var string
	 */
	public $demo_context;

	/**
	 * active data type
	 *
	 * @var string
	 */
	public $active_data_type;

	/**
	 * active index step
	 *
	 * @var integer
	 */
	public $active_step_index;


	/**
	 * Pattern of ids of objects in string
	 *
	 * @var string
	 */
	public $id_pattern = '/%%(.*?)%%/';


	/**
	 * Pattern of custom functions in strings that supports params
	 *
	 * note: this should follow $id_pattern and should change it's inner value
	 *
	 * @var string
	 */
	public $function_pattern = '/%%(.*?)(:?\:.*?)%%/';


	/**
	 * store all demo data array
	 *
	 * @var array
	 */
	public $all_data = array();


	/**
	 * Initialize
	 */
	public static function Run() {

		global $bs_product_demo_factory;

		if ( $bs_product_demo_factory === false ) {
			return;
		}

		if ( ! $bs_product_demo_factory instanceof self ) {
			$bs_product_demo_factory = new self();
		}

		return $bs_product_demo_factory;
	}


	/**
	 * start import data to database.
	 *
	 * @param array   $import_data data to import
	 * @param string  $current_data_type
	 * @param integer $current_step
	 * @param string  $demo_id
	 * @param string  $demo_context
	 *
	 * @return bool true on success or false on failure.
	 */
	public function import_start( $import_data, $current_data_type, $current_step, $demo_id, $demo_context = 'content' ) {

		if ( ! is_array( $import_data ) ) {
			return false;
		}

		$this->set_demo_data( $demo_id, $demo_context );
		$this->handle_event( 'before_import', $import_data );

		$have_data              = ! empty( $import_data );
		$custom_function_result = $this->handle_custom_function( $import_data, 'on_import' );

		if ( $have_data && empty( $import_data ) ) {
			// all of the $import_data variable was custom_function, so return custom_function result

			return (bool) $custom_function_result;
		}

		//all import method have import_ prefix
		$callback_prefix = 'import_';
		$method          = strtolower( str_replace( '-', '_', $callback_prefix . $current_data_type ) );
		$callback        = array( $this, $method );


		if ( ! is_callable( $callback ) || $method === __FUNCTION__ ) {
			return false;
		}

		$this->active_data_type  = $current_data_type;
		$this->active_step_index = $current_step;

		unset( $import_data['multi_steps'], $import_data['uninstall_multi_steps'] );

		try {

			$return = call_user_func( $callback, $import_data );
			$this->handle_event( 'after_import', $import_data );

		} catch( BF_Exception $e ) {

			return new WP_Error( $e->getCode(), $e->getMessage() );
		}

		return $return;
	}


	protected function set_demo_data( $demo_id, $context = 'content' ) {

		if ( $this->demo_id !== $demo_id ) {
			$this->demo_id      = $demo_id;
			$this->demo_context = $context;
			$this->all_data     = bf_get_demo_data( $demo_id, $context );
		}
	}


	/**
	 * apply custom functions and remove it from $import_data
	 *
	 * @param array  $import_data array of data to import
	 * @param string $context     custom function context. call function on_import or on_rollback ?
	 *
	 * @return bool true on success or false otherwise
	 */
	protected function handle_custom_function( &$import_data, $context ) {

		$result = true;

		foreach ( $import_data as $index => $data ) {

			if ( isset( $data['type'] ) && $data['type'] === 'custom_function' ) {

				if ( ! empty( $data[ $context ] ) ) {

					if ( isset( $data['callback'] ) && is_callable( $data['callback'] ) ) {

						$params = isset( $data['params'] ) && is_array( $data['params'] ) ? $data['params'] : array();
						$result &= (bool) call_user_func_array( $data['callback'], $params );
					}
				}

				unset( $import_data[ $index ] );
			}
		}


		return $result;
	}


	/**
	 * receive absolute path to file in PS Product Pages Library
	 *
	 * @param string $path
	 *
	 * @return string
	 */
	protected function get_path( $path ) {

		return BF_Product_Pages::get_path( $path );
	}


	/**
	 * save ID and rollback information to database for future uses,
	 *
	 * fire this function after imported data.
	 *
	 * @return null
	 */
	public function import_stop() {

		//validate IDs
		if ( isset( $this->id_list[ $this->demo_id ] ) && is_array( $this->id_list[ $this->demo_id ] ) ) {

			$option_name  = sprintf( 'bs_demo_id_%s', $this->demo_id );
			$option_value = get_option( $option_name, array() );

			//save IDs
			update_option(
				$option_name,
				array_merge( $option_value, $this->id_list[ $this->demo_id ] ),
				'no'
			);
		}

		//validate rollback data
		if ( isset( $this->rollback_data[ $this->demo_id ] ) && is_array( $this->rollback_data[ $this->demo_id ] ) ) {

			$option_name  = sprintf( 'bs_demo_rollback_%s', $this->demo_id );
			$option_value = get_option( $option_name, array() );

			//save rollback data
			update_option(
				$option_name,
				array_merge( $option_value, $this->rollback_data[ $this->demo_id ] ),
				'no'
			);
		}

	}


	/**
	 * Import final step
	 *
	 * call import finished and clear BF css cache
	 */
	public function import_finished() {

		if ( is_callable( 'Better_Framework::factory' ) ) {
			// Clear CSS caches
			Better_Framework::factory( 'custom-css-fe' )->clear_cache( 'all' );
		}

		do_action( 'better-framework/product-pages/install-demo/import-finished', $this->demo_id, $this );
	}


	/**
	 * filter data array indexes
	 *
	 *
	 * @param Array $params
	 */
	public static function data_params_filter( &$params ) {

		if ( is_array( $params ) ) {

			unset( $params['the_id'] );

			$params = array_filter( $params );
		}
	}


	/**
	 *
	 * @return array
	 */
	public static function import_data_sequence() {

		return array(
			'taxonomy',
			'media',
			'posts',
			'options',
			'widgets',
			'menus',
		);
	}


	/**
	 * save imported data id or other information used to pass rollback data
	 *
	 * @param string $id
	 * @param mixed  $value
	 *
	 * @return bool true on success or false on failure.
	 * @throws BF_Exception
	 */
	protected function set_id( $id, $value ) {

		$this->throw_if_is_wp_error( $value );

		if ( ! isset( $this->id_list[ $this->demo_id ] ) ) {
			/**
			 * get previous data form database
			 *
			 * @see import_stop()
			 */
			$this->id_list[ $this->demo_id ] = get_option( sprintf( 'bs_demo_id_%s', $this->demo_id ) );
		}

		$id = trim( $id );

		$this->id_list[ $this->demo_id ][ $id ] = $value;

		return true;
	}


	/**
	 * save id of imported data if need
	 * this method will fire after each single import
	 *
	 * @param mixed $result
	 * @param array $data
	 *
	 * @throws BF_Exception
	 */
	protected function save_ID( $result, $data ) {

		if ( isset( $data['the_id'] ) ) {

			$this->set_id( $data['the_id'], $result );
		}
	}


	protected function prepare_item_string( &$value ) {

		$values = array_map( array( $this, 'apply_pattern' ), explode( ',', $value ) );
		$value  = implode( ',', $values );
	}


	/**
	 * @param array $params
	 * @param array $id_list
	 */
	protected function prepare_params( &$params, $id_list = array() ) {

		if ( $id_list && is_array( $id_list ) ) {
			$id_keys = array_flip( $id_list );

			foreach ( $params as $key => $param ) {

				if ( isset( $id_keys[ $key ] ) ) {

					if ( is_array( $params[ $key ] ) ) {
						array_walk_recursive( $params[ $key ], array( $this, 'prepare_item_string' ) );
					} else {
						$this->prepare_item_string( $params[ $key ] );
					}
				}
			}
		}
	}


	/**
	 * receive new instance of class
	 *
	 * @param $object_name name of object
	 *
	 * @return bool|object false on failure or object on success.
	 */
	protected function get_instance( $object_name ) {

		switch ( $object_name ) {

			case 'taxonomy':

				$class_name = 'BF_Demo_Taxonomy_Manager';

				if ( ! class_exists( $class_name ) ) {


					require_once $this->get_path( 'install-demo/class-bf-demo-taxonomy-manager.php' );
				}

				break;

			case 'media':

				$class_name = 'BF_Demo_Media_Manager';

				if ( ! class_exists( $class_name ) ) {

					require_once $this->get_path( 'install-demo/class-bf-demo-media-manager.php' );
				}


				break;

			case 'post':
			case 'posts':

				$class_name = 'BF_Demo_Posts_Manager';

				if ( ! class_exists( $class_name ) ) {

					$file = $this->get_path( 'install-demo/bs-demo-posts-manager.php' );

					require_once $this->get_path( 'install-demo/class-bf-demo-posts-manager.php' );
				}


				break;

			case 'option':
			case 'options':

				$class_name = 'BF_Demo_Option_Manager';

				if ( ! class_exists( $class_name ) ) {

					require_once $this->get_path( 'install-demo/class-bf-demo-option-manager.php' );
				}


				break;

			case 'widget':
			case 'widgets':

				$class_name = 'BF_Demo_Widget_Manager';

				if ( ! class_exists( $class_name ) ) {

					require_once $this->get_path( 'install-demo/class-bf-demo-widget-manager.php' );
				}


				break;

			case 'menu':
			case 'menus':

				$class_name = 'BF_Demo_Menu_Manager';

				if ( ! class_exists( $class_name ) ) {

					require_once $this->get_path( 'install-demo/class-bf-demo-menu-manager.php' );
				}


				break;

		}

		if ( ! empty( $class_name ) && class_exists( $class_name ) ) {
			return new $class_name();
		}

		return false;
	}


	/**
	 * @param Array $taxonomies
	 *
	 * @return bool true on success or false on failure
	 * @throws BF_Exception
	 */

	public function import_taxonomy( $taxonomies ) {

		/**
		 * @var $handler BF_Demo_Taxonomy_Manager
		 */
		if ( $handler = $this->get_instance( 'taxonomy' ) ) {

			foreach ( $taxonomies as $tax ) {

				$this->prepare_params( $tax, array( 'parent', 'term_id', 'meta_value' ) );

				$term_id = $handler->add_term( $tax );
				$this->throw_if_is_wp_error( $term_id, $tax );

				$this->save_ID( $term_id, $tax );

				$this->save_insert_state( $term_id, 'term' );

				if ( isset( $tax['term_meta'] ) && is_array( $tax['term_meta'] ) ) {

					foreach ( $tax['term_meta'] as $term_meta ) {

						$term_meta['term_id'] = $term_id;
						$this->prepare_params( $term_meta, array( 'meta_value' ) );

						if ( empty( $term_meta['update'] ) ) {
							$result = call_user_func( array( $handler, 'add_term_meta' ), $term_meta );
							$this->throw_if_is_wp_error( $result, $term_meta );

							$this->save_insert_state( $term_meta, 'term_meta' );
						} else {
							$term_meta['single'] = true;

							$prev_meta_data = call_user_func( array( $handler, 'get_term_meta' ), $term_meta );
							$result         = call_user_func( array( $handler, 'update_term_meta' ), $term_meta );
							$this->throw_if_is_wp_error( $result, $term_meta );

							$this->save_update_state( $term_meta, 'term_meta', $prev_meta_data );
						}
					}
				}
			}

			return true;
		}

		return false;
	}


	/**
	 * @param array $taxonomies
	 *
	 * @return bool true on success or false on failure
	 */
	public function rollback_taxonomy( $taxonomies ) {

		/**
		 * @var $handler BF_Demo_Taxonomy_Manager
		 */
		if ( $handler = $this->get_instance( 'taxonomy' ) ) {

			foreach ( $taxonomies as $tax ) {

				if ( ! isset( $tax['type'] ) ) {
					continue;
				}

				if ( $tax['type'] === 'term' ) {

					$handler->remove_term( $tax['id'] );

				} elseif ( $tax['type'] === 'term_meta' ) {

					if ( empty( $tax['prev_data'] ) ) {
						/**
						 * delete inserted data
						 *
						 * id index of $tax contain array of added meta array {
						 *
						 * @type string $meta_key
						 * @type mixed  $meta_value
						 * @type int    $term_id
						 * }
						 */
						$handler->remove_term_meta( $tax['id'] );
					} else {
						/**
						 * update term meta to previous value
						 *
						 * id index of $tax contain array of added meta array {
						 *
						 * @type string $meta_key
						 * @type mixed  $meta_value
						 * @type int    $term_id
						 * }
						 */
						$update_term               = $tax['id'];
						$update_term['prev_value'] = $tax['prev_data'];

						$handler->update_term_meta( $tax['id'], $update_term );
					}
				}
			}

			return true;
		}

		return false;
	}


	/**
	 * @param Array $media_list
	 *
	 * @return bool true on success or false on failure
	 * @throws BF_Exception
	 */
	public function import_media( $media_list ) {

		/**
		 * @var $handler BF_Demo_Media_Manager
		 */
		if ( $handler = $this->get_instance( 'media' ) ) {

			/**
			 * post handler need to add items post meta
			 *
			 * @var $handler BF_Demo_Posts_Manager
			 */
			$post_handler = $this->get_instance( 'post' );

			foreach ( $media_list as $media ) {

				if ( isset( $media['file'] ) ) {

					$image_id = $handler->add_image( $media['file'], $media );
					$this->throw_if_is_wp_error( $image_id, $media );

					if ( $image_id ) {

						$this->save_ID( $image_id, $media );

						$this->save_insert_state( $image_id, 'media' );

						//add post meta
						if ( isset( $media['media_meta'] ) && is_array( $media['media_meta'] ) ) {
							$this->handle_post_meta( $image_id, $media['media_meta'], $post_handler );
						}
					} else {
						$this->throw_if_is_wp_error( new WP_Error( 'add_image_error', 'cannot insert image' ), $media );
					}
				}
			}

			return true;
		}

		return false;
	}


	/**
	 * @param Array $media_list
	 *
	 * @return bool true on success or false on failure
	 */
	public function rollback_media( $media_list ) {

		/**
		 * @var $handler BF_Demo_Media_Manager
		 */
		if ( $handler = $this->get_instance( 'media' ) ) {

			foreach ( $media_list as $media ) {

				if ( isset( $media['type'] ) && $media['type'] === 'media' ) {

					$handler->remove_image( $media['id'] );
				}
			}

			return true;
		}

		return false;
	}


	/**
	 * insert/update post meta
	 *
	 * @param int                   $post_id        post id to add/update meta
	 * @param array                 $post_meta_list list of post meta
	 * @param BF_Demo_Posts_Manager $handler        object variable to prevent multiple instantiation
	 *
	 * @throws BF_Exception
	 */
	function handle_post_meta( $post_id, $post_meta_list, &$handler ) {

		foreach ( $post_meta_list as $post_meta ) {

			$post_meta['post_id'] = $post_id;

			$this->prepare_params( $post_meta, array( 'meta_value' ) );

			if ( empty( $post_meta['update'] ) ) {

				$post_meta_id = call_user_func( array( $handler, 'add_post_meta' ), $post_meta );

				$this->save_insert_state( $post_meta_id, 'post_meta' );
			} else {

				$prev_meta_data = call_user_func( array( $handler, 'get_post_meta' ), $post_meta );
				$post_meta_id   = call_user_func( array( $handler, 'update_post_meta' ), $post_meta );

				$this->save_update_state( $post_meta_id, 'post_meta', $prev_meta_data );
			}

			$this->save_ID( $post_meta_id, $post_meta );
		}
	}


	/**
	 * @param Array $posts_list
	 *
	 * @return bool true on success or false on failure
	 * @throws BF_Exception
	 */
	public function import_posts( $posts_list ) {

		static $remote_post_contents = array(); # Cache storage for remote post contents.

		/**
		 * @var $handler BF_Demo_Posts_Manager
		 */
		if ( $handler = $this->get_instance( 'post' ) ) {

			$post_date = new DateTime( '-30 minutes' );

			foreach ( array_reverse( $posts_list ) as $post ) {

				if ( ! empty( $post['remote_content'] ) ) { # Fetch remote post content from better studio core

					if ( empty( $remote_post_contents[ $this->demo_id ] ) ) {

						$remote_params            = $post['remote_content'];
						$remote_params['demo-id'] = $this->demo_id;

						$remote_response = $this->api_request( 'demo-content', $remote_params );

						// Validate remote response
						if ( ! is_wp_error( $remote_response ) && ! empty( $remote_response->success ) && ! empty( $remote_response->content ) ) {
							$post['post_content'] = $remote_response->content;

							$remote_post_contents[ $this->demo_id ] = $post['post_content']; # Cache it!
						}

					} else {

						$post['post_content'] = $remote_post_contents[ $this->demo_id ];
					}

					unset( $post['remote_content'] ); # it's better to unset new array index
				}


				$this->prepare_params( $post, array( 'thumbnail_id', 'post_id', 'post_terms' ) );

				if ( ! empty( $post['post_date'] ) ) {
					$post['post_date_gmt'] = strtotime( $post['post_date'] );
				} else {
					$post_date->modify( '+1 second' );
					$post['post_date_gmt'] = $post_date->format( 'Y-m-d H:i:s' );;
				}

				$post_id = $handler->add_post( $post );
				$this->throw_if_is_wp_error( $post_id, $post );

				$this->save_insert_state( $post_id, 'post' );

				$this->save_ID( $post_id, $post );

				if ( isset( $post['post_meta'] ) && is_array( $post['post_meta'] ) ) {

					$this->handle_post_meta( $post_id, $post['post_meta'], $handler );
				}
			}

			return true;
		}

		return false;
	}


	/**
	 * @param Array $posts_list
	 *
	 * @return bool true on success or false on failure
	 */
	public function rollback_posts( $posts_list ) {

		/**
		 * @var $handler BF_Demo_Posts_Manager
		 */
		if ( $handler = $this->get_instance( 'post' ) ) {

			foreach ( $posts_list as $post ) {

				if ( $post['type'] === 'post' ) {

					$handler->remove_post( $post['id'] );

				} elseif ( $post['type'] === 'post_meta' ) {

					if ( empty( $post['prev_data'] ) ) {

						//delete inserted data
						$handler->remove_post_meta( $post['id'] );
					} else {

						//update meta & set previous data

						//TODO: test this method
						$handler->update_post_meta( $post['prev_data'] );
					}
				}
			}

			return true;
		}

		return false;
	}


	/**
	 * @param Array $options_list
	 *
	 * @return bool true on success or false on failure
	 * @throws BF_Exception
	 */
	public function import_options( $options_list ) {

		/**
		 * @var $handler BF_Demo_Option_Manager
		 */
		if ( $handler = $this->get_instance( 'option' ) ) {

			foreach ( $options_list as $option ) {

				// replace recursively the_id in array of option value
				if ( isset( $option['option_value'] ) && is_array( $option['option_value'] ) ) {
					$this->prepare_params( $option, array_keys( $option['option_value'] ) );
				} else {
					$this->prepare_params( $option, array( 'option_value' ) );
				}

				if ( isset( $option['type'] ) && $option['type'] === 'transient' ) {
					// transient
					$transient = &$option;


					if ( ! isset( $transient['expiration'] ) ) {
						$transient['expiration'] = 0;
					}

					$prev_transient = $handler->get_transient( $transient );
					$handler->set_transient( $transient );

					$inserted_data = wp_array_slice_assoc(
						$transient,
						array(
							'transient_name',
							'expiration'
						)
					);
					$this->save_update_state( $inserted_data, 'transient', $prev_transient );

				} else {
					// option

					if ( empty( $option['delete'] ) ) {

						$this->insert_update_option( $option, $handler );
					} else {

						$prev_option = $handler->get_option( $option );

						$handler->delete_option( $option['option_name'] );
						$this->save_delete_state(
							array(
								'option_name'  => $handler->get_option_name( $option ),
								'option_value' => $prev_option
							),
							'delete_option'
						);
					}
				}
			}

			return true;
		}

		return false;
	}


	/**
	 * @param Array $options_list
	 *
	 * @return bool true on success or false on failure
	 */
	public function rollback_options( $options_list ) {

		/**
		 * @var $handler BF_Demo_Option_Manager
		 */
		if ( $handler = $this->get_instance( 'option' ) ) {

			foreach ( $options_list as $option ) {

				if ( ! isset( $option['type'] ) ) {
					continue;
				}

				switch ( $option['type'] ) {

					case 'merge_option':

						if ( isset( $option['prev_data'] ) ) {

							$handler->merge_and_update_option(
								array(
									'option_name'  => $option['id'],
									'option_value' => $option['prev_data']
								)
							);
						}
						break;

					case 'delete_option':

						$handler->add_option( $option['id'] );

						break;

					case 'add_option':

						$handler->delete_option( $option['id'] );

						break;

					case 'update_option':

						$handler->update_option( array(
							'option_name'  => $option['id'],
							'option_value' => isset( $option['prev_data'] ) ? $option['prev_data'] : ''
						) );

						break;

					case 'transient':

						if ( empty( $option['prev_data'] ) ) {

							if ( isset( $option['id']['transient_name'] ) ) {
								$handler->remove_transient( $option['id']['transient_name'] );
							}
						} else {

							$option['id']['transient_value'] = $option['prev_data'];
							$handler->set_transient( $option['id'] );
						}

						break;
				}
			}

			return true;
		}

		return false;
	}


	/**
	 * @param Array $widgets_list
	 *
	 * @return bool true on success or false on failure
	 * @throws BF_Exception
	 */

	public function import_widgets( $widgets_list ) {

		/**
		 * @var $handler BF_Demo_Widget_Manager
		 */
		if ( $handler = $this->get_instance( 'widget' ) ) {

			//save current widget status before start importing
			$this->save_widget_status();

			foreach ( $widgets_list as $sidebar_id => $sidebar_widgets ) {

				$handler->set_sidebar_id( $sidebar_id );

				if ( ! empty( $sidebar_widgets['remove_all_widgets'] ) ) {

					$handler->remove_all_widgets();

					unset( $sidebar_widgets['remove_all_widgets'] );

				} elseif ( ! empty( $sidebar_widgets['remove_widgets'] ) && is_array( $sidebar_widgets['remove_widgets'] ) ) {

					foreach ( $sidebar_widgets['remove_widgets'] as $widget_id_base ) {

						$handler->remove_widgets( $widget_id_base );
					}

					unset( $sidebar_widgets['remove_widgets'] );
				}


				foreach ( $sidebar_widgets as $widget_data ) {

					if ( ! isset( $widget_data['widget_id'] ) ) {
						continue;
					}

					$settings = isset( $widget_data['widget_settings'] ) ? $widget_data['widget_settings'] : array();

					$this->prepare_params( $settings, array_keys( $settings ) );

					$handler->add_widget( $widget_data['widget_id'], $settings );
				}

			}

			return true;
		}

		return false;
	}


	/**
	 * save sidebar widgets and widgets settings
	 *
	 * @see import_widgets
	 *
	 * @throws BF_Exception
	 * @global wpdb $wpdb
	 */
	protected function save_widget_status() {

		global $wpdb;

		//step 1) save widgets array
		$this->save_insert_state( get_option( 'sidebars_widgets' ), 'sidebars_widgets' );

		//step 2) save widget settings
		$widgets_settings = $wpdb->get_results(
			'SELECT option_name,option_value FROM ' . $wpdb->options . ' WHERE option_name LIKE \'widget_%\'',
			ARRAY_A
		);

		if ( is_array( $widgets_settings ) ) {
			$widgets_settings = array_map( array( $this, 'unserialize_option_value' ), $widgets_settings );
			$this->save_insert_state( $widgets_settings, 'widgets_settings' );
		}
	}


	/**
	 * @see save_widget_status
	 *
	 * @param array $option_array
	 *
	 * @return mixed
	 */
	protected function unserialize_option_value( $option_array ) {

		if ( isset( $option_array['option_value'] ) ) {
			$option_array['option_value'] = maybe_unserialize( $option_array['option_value'] );
		}

		return $option_array;
	}


	/**
	 *
	 * TODO: add_option not working  on add_option( $option['option_name'],  $option['option_value'] );
	 *
	 * @param Array $widgets_list
	 *
	 * @return bool true on success or false on failure
	 */
	public function rollback_widgets( $widgets_list ) {

		global $wpdb;

		/**
		 * @var $handler BF_Demo_Widget_Manager
		 */

		if ( $handler = $this->get_instance( 'widget' ) ) {

			$delete_options = false;

			foreach ( $widgets_list as $widget ) {

				if ( ! isset( $widget['type'] ) || ! isset( $widget['id'] ) ) {
					continue;
				}

				if ( $widget['type'] === 'sidebars_widgets' ) {
					update_option( 'sidebars_widgets', $widget['id'] );

				} elseif ( $widget['type'] === 'widgets_settings' ) {

					$settings_options = &$widget['id'];

					if ( is_array( $settings_options ) ) {

						if ( ! $delete_options ) {

							//remove all widgets settings and import previous data
							$wpdb->query( 'DELETE FROM ' . $wpdb->options . ' WHERE option_name LIKE \'widget_%\'' );
							$delete_options = true;

							//options cache make problem while adding options
							wp_cache_delete( 'alloptions', 'options' );
							wp_cache_delete( 'notoptions', 'options' );
						}

						foreach ( $settings_options as $option ) {

							if ( isset( $option['option_name'] ) && isset( $option['option_value'] ) ) {

								wp_cache_delete( $option['option_name'], 'options' );
								add_option( $option['option_name'], $option['option_value'] );
							}
						}

					}
				}
			}

			return true;
		}

		return false;
	}


	/**
	 * import menu data
	 *
	 * @param Array $menus_list
	 *
	 * @return bool true on success or false on failure
	 * @throws BF_Exception
	 */
	public function import_menus( $menus_list ) {

		/**
		 * @var $handler BF_Demo_Menu_Manager
		 */
		if ( $handler = $this->get_instance( 'menu' ) ) {

			//save menu locations before apply changes
			$this->save_update_state( '1', 'nav_menu_locations', get_theme_mod( 'nav_menu_locations' ) );

			/**
			 * post handler need to add items post meta
			 *
			 * @var $handler BF_Demo_Posts_Manager
			 */
			$post_handler = $this->get_instance( 'post' );

			$required_params = array(
				'menu-name'     => '',
				'menu-location' => '',
				'items'         => '',
			);

			foreach ( $menus_list as $menu_list ) {

				if ( array_diff_key( $required_params, $menu_list ) ) {
					return false;
				}

				$created_menu = $handler->create_menu( $menu_list['menu-name'], $menu_list['menu-location'] );
				$this->throw_if_is_wp_error( $created_menu, $menu_list );
				list( $menu_id, $menu_exists ) = $created_menu;

				if ( ! $menu_exists && $menu_id ) {

					$this->save_insert_state( $menu_id, 'menu' );
				}

				if ( ! empty( $menu_list['recently-edit'] ) && $menu_id ) {
					update_user_meta( get_current_user_id(), 'nav_menu_recently_edited', $menu_id );
				}

				$id_list = array( 'parent-id', 'page_id', 'term_id', 'post_id' );

				if ( is_array( $menu_list['items'] ) ) {

					foreach ( $menu_list['items'] as $menu_item ) {

						if ( ! isset( $menu_item['item_type'] ) ) {
							continue;
						}

						$item_type = $menu_item['item_type'];

						unset( $menu_item['item_type'] );

						$this->prepare_params( $menu_item, $id_list );

						$item_id = 0;

						switch ( $item_type ) {

							case 'custom':

								$item_id = $handler->append_link( $menu_item );

								break;

							case 'page':

								if ( isset( $menu_item['page_id'] ) ) {
									$item_id = $handler->append_page_link( $menu_item['page_id'], $menu_item );
								}

								break;

							case 'post':

								if ( isset( $menu_item['post_id'] ) ) {

									$post_type = isset( $menu_item['post_type'] ) ? $menu_item['post_type'] : 'post';

									$item_id = $handler->append_post_link( $menu_item['post_id'], $post_type, $menu_item );
								}

								break;

							case 'term':

								if ( isset( $menu_item['term_id'] ) && isset( $menu_item['taxonomy'] ) ) {
									$item_id = $handler->append_taxonomy_link( $menu_item['term_id'], $menu_item['taxonomy'], $menu_item );

								}

								break;
						}

						$this->throw_if_is_wp_error( $item_id, $menu_item );

						if ( $item_id ) {

							//save IDs
							$this->save_insert_state( $item_id, 'menu-item' );
							$this->save_ID( $item_id, $menu_item );


							// add post meta
							if ( isset( $menu_item['item_meta'] ) && is_array( $menu_item['item_meta'] ) ) {

								// Fix meta ids key
								$_item_meta = array();
								foreach ( $menu_item['item_meta'] as $meta ) {
									$_meta             = $meta;
									$_meta['meta_key'] = '_menu_item_' . $_meta['meta_key'];
									$_item_meta[]      = $_meta;
								}

								$this->handle_post_meta( $item_id, $_item_meta, $post_handler );
							}
						}
					}
				}
			}

			return true;
		}

		return false;
	}


	/**
	 * rollback menu to last status.
	 *
	 * @param Array $menus_list
	 *
	 * @return bool true on success or false on failure
	 */

	public function rollback_menus( $menus_list ) {


		/**
		 * @var $handler BF_Demo_Menu_Manager
		 */
		if ( $handler = $this->get_instance( 'menu' ) ) {

			foreach ( $menus_list as $menu ) {

				if ( ! isset( $menu['type'] ) ) {
					continue;
				}

				if ( $menu['type'] === 'menu-item' ) {

					$handler->remove_item( $menu['id'] );

				} elseif ( $menu['type'] === 'menu' ) {

					$handler->remove_menu( $menu['id'] );
				} elseif ( $menu['type'] === 'nav_menu_locations' ) {

					if ( ! empty( $menu['prev_data'] ) && is_array( $menu['prev_data'] ) ) {

						set_theme_mod( 'nav_menu_locations', $menu['prev_data'] );
					}
				}

			}

			return true;
		}


		return false;
	}

	/***
	 * Demo Rollback Methods
	 */


	/**
	 * start rollback data.
	 *
	 * @param string  $current_data_type rollback data type
	 * @param integer $current_step      step index number
	 * @param string  $demo_id           demo name
	 * @param string  $demo_context      demo context {@see bf_get_demo_data}
	 *
	 * @return bool true on success or false on failure
	 */

	public function rollback_start( $current_data_type, $current_step, $demo_id, $demo_context = 'content' ) {

		$this->set_demo_data( $demo_id, $demo_context );
		$data = $this->get_rollback_data();

		/**
		 * handle rollback final step
		 *
		 * {@see \BF_Product_Demo_Manager::calculate_install_steps} method
		 * with uninstall context will add clean step  for last step.
		 */
		if ( $current_data_type === 'clean' ) {

			return $this->rollback_finished();
		}

		if ( isset( $data[ $current_data_type ][ $current_step ] ) ) {
			$this->active_data_type  = $current_data_type;
			$this->active_step_index = $current_step;

			if ( $handler = $this->get_instance( $current_data_type ) ) {

				$callback_prefix = 'rollback_';
				$method          = strtolower( str_replace( '-', '_', $callback_prefix . $current_data_type ) );
				$callback        = array( $this, $method );

				if ( ! is_callable( $callback ) || $method === __FUNCTION__ ) {
					return false;
				}

				/**
				 * data pass to function is array of data something like this
				 *
				 * array {
				 *
				 *   array {
				 *      id      =>  mixed (often string)  data saved while importing data.
				 *      type    =>  string data imported. arbitrary name, defined importer method
				 *   }
				 *
				 * }
				 */
				$this->handle_event( 'before_rollback', $data[ $current_data_type ][ $current_step ] );

				if ( isset( $this->all_data[ $current_data_type ][ $current_step ] ) ) {
					$this->handle_custom_function( $this->all_data[ $current_data_type ][ $current_step ], 'on_rollback' );
				}


				try {

					// pass all data to install if uninstall_multi_steps was not active
					if ( empty( $this->all_data[ $current_data_type ]['uninstall_multi_steps'] ) ) {
						$result = 1;
						foreach ( $data[ $current_data_type ] as $uninstall_data ) {
							$result &= call_user_func( $callback, $uninstall_data );
						}
					} else {
						$result = call_user_func( $callback, $data[ $current_data_type ][ $current_step ] );
					}

					$this->handle_event( 'after_rollback', $data[ $current_data_type ][ $current_step ] );

					return $result;

				} catch( BF_Exception $e ) {

					return new WP_Error( $e->getCode(), $e->getMessage() );
				}
			}
		}

		return false;
	}


	protected function handle_event( $event, $params = array() ) {

		if ( isset( $this->all_data['events'][ $event ] ) ) {

			$callback = &$this->all_data['events'][ $event ];
			if ( is_callable( $callback ) ) {

				return call_user_func_array( $callback, $params );
			}
		}
	}


	/**
	 * delete rollback data from database
	 *
	 * fire this function after rollback_start().
	 *
	 * @return bool true on success or false on failure.
	 */

	public function rollback_stop() {

		$data = $this->get_rollback_data();

		if ( ! is_array( $data ) ) {
			return false;
		}

		if ( ! isset( $data[ $this->active_data_type ][ $this->active_step_index ] ) ) {
			$this->delete_option_if_necessary( $data );

			return false;
		}

		unset( $data[ $this->active_data_type ][ $this->active_step_index ] );


		if ( $data ) {
			$option_name = sprintf( 'bs_demo_rollback_%s', $this->demo_id );

			return update_option( $option_name, $data, 'no' );
		} else {
			$this->delete_option_if_necessary( $data );

			return true;
		}
	}


	/**
	 * Rollback demo on single request
	 *
	 * @param string $demo_id
	 * @param string $demo_context
	 *
	 * @return bool true on success or false otherwise.
	 */
	public function rollback_force( $demo_id, $demo_context = 'content' ) {

		$this->set_demo_data( $demo_id, $demo_context );
		$all_data = $this->get_rollback_data();
		if ( ! $all_data || ! is_array( $all_data ) ) {
			return false;
		}


		foreach ( $all_data as $current_data_type => $data ) {

			if ( ! is_array( $data ) ) {
				continue;
			}

			if ( $steps = array_keys( $data ) ) {

				foreach ( $steps as $step ) {
					$this->rollback_start( $current_data_type, $step, $demo_id );
					$this->rollback_stop();
				}
			}
		}
		$this->rollback_finished();

		return true;
	}


	/**
	 * Rollback final step.
	 *
	 * delete all temporary data saved in options to make sure uninstalling process
	 * completed and prevent display uninstall demo button after demo uninstalled!
	 *
	 * @see \BF_Product_Demo_Manager::calculate_process_steps
	 *
	 * @return bool always return true.
	 */
	private function rollback_finished() {

		/**
		 * pass empty array to function will delete temporary data saved in options table
		 */
		$data = array();
		$this->delete_option_if_necessary( $data );

		if ( is_callable( 'Better_Framework::factory' ) ) {
			// Clear CSS caches
			Better_Framework::factory( 'custom-css-fe' )->clear_cache( 'all' );
		}

		do_action( 'better-framework/product-pages/install-demo/rollback-finished', $this->demo_id, $this );

		return true;
	}


	/**
	 * Delete demo data saved in options if needed
	 *
	 * @param array $data array of rollback data
	 *
	 * @see get_rollback_data
	 *
	 * @return bool true if data was empty.
	 */
	private function delete_option_if_necessary( &$data ) {

		if ( ! is_array( $data ) ) {

			return false;
		}
		$data = array_filter( $data );

		if ( empty( $data ) ) {

			$option_name           = sprintf( 'bs_demo_rollback_%s', $this->demo_id );
			$temp_vars_option_name = sprintf( 'bs_demo_id_%s', $this->demo_id );

			delete_option( $option_name );
			delete_option( $temp_vars_option_name );

			return true;
		}

		return false;
	}


	/**
	 * Whether a demo is already installed
	 *
	 * @param string $demo_id
	 *
	 * @return bool
	 */
	public static function is_demo_installed( $demo_id ) {

		$options = get_option( sprintf( 'bs_demo_rollback_%s', $demo_id ) );

		return $options && is_array( $options );
	}


	/**
	 * get rollback data for active demo id
	 *
	 * @return mixed
	 */

	protected function get_rollback_data() {

		if ( ! isset( $this->rollback_data[ $this->demo_id ] ) ) {
			$this->rollback_data[ $this->demo_id ] = get_option( sprintf( 'bs_demo_rollback_%s', $this->demo_id ) );
		}


		if ( isset( $this->rollback_data[ $this->demo_id ] ) ) {
			return $this->rollback_data[ $this->demo_id ];
		}
	}


	/**
	 * set rollback data for active demo
	 *
	 * @param mixed $data
	 *
	 * @return bool true on success or false on failure.
	 * @throws BF_Exception
	 */
	protected function set_rollback_data( $data ) {

		$this->throw_if_is_wp_error( $data );

		if ( ! isset( $this->rollback_data[ $this->demo_id ] ) ) {
			$this->rollback_data[ $this->demo_id ] = get_option( sprintf( 'bs_demo_rollback_%s', $this->demo_id ) );
		}

		$this->rollback_data
		[ $this->demo_id ]
		[ $this->active_data_type ]
		[ $this->active_step_index ][] = $data;

		return true;
	}


	/**
	 * @param mixed  $inserted_data
	 * @param string $data_type
	 *
	 * @return bool true on success or false on failure.
	 * @throws BF_Exception
	 */
	protected function save_insert_state( $inserted_data, $data_type ) {

		$this->throw_if_is_wp_error( $inserted_data );

		if ( ! $inserted_data ) {
			return false;
		}

		return $this->set_rollback_data( array(
			'id'   => $inserted_data,
			'type' => $data_type
		) );
	}


	/**
	 * @param mixed  $inserted_data
	 * @param string $data_type
	 * @param mixed  $prev_data
	 *
	 * @return bool true on success or false on failure.
	 * @throws BF_Exception
	 */
	protected function save_update_state( $inserted_data, $data_type, $prev_data ) {

		$this->throw_if_is_wp_error( $inserted_data );

		if ( ! $inserted_data ) {
			return false;
		}


		if ( empty( $prev_data ) ) {

			return $this->save_insert_state( $inserted_data, $data_type );
		}

		return $this->set_rollback_data( array(
			'id'        => $inserted_data,
			'type'      => $data_type,
			'prev_data' => $prev_data
		) );
	}


	/**
	 * @param mixed  $deleted_data
	 * @param string $data_type
	 *
	 * @return bool true on success or false on failure.
	 * @throws BF_Exception
	 */
	protected function save_delete_state( $deleted_data, $data_type ) {

		return $this->set_rollback_data( array(
			'id'   => $deleted_data,
			'type' => $data_type,
		) );
	}

	/***
	 *  Parse Input String
	 */


	/**
	 * change string, apply function or just replace ID with value
	 *
	 * @param string $string
	 *
	 * @return null|string string on success null otherwise.
	 */
	public function apply_pattern( $string ) {

		$data_replace_keys   = array();
		$data_replace_values = array();

		if ( ! is_string( $string ) ) {
			return $string;
		}

		preg_match_all( $this->id_pattern, $string, $matched );

		if ( ! empty( $matched[1] ) ) {
			foreach ( $matched[1] as $index => $ID ) {

				// Advanced custom function pattern
				if ( preg_match( $this->function_pattern, $matched[0][ $index ], $_matched ) ) {

					$callback = &$_matched[1];
					$params   = &$_matched[2];

					// Prepare params
					$params = $this->quoted_explode( $params, ':' );
					$params = array_map( array( $this, 'filter_function_params' ), $params );

					$data_replace_keys[]   = $matched[0][ $index ];
					$data_replace_values[] = call_user_func_array( $callback, $params );

				} // Simple pattern
				else {
					$data_replace_keys[]   = $matched[0][ $index ];
					$data_replace_values[] = $this->get_id( $ID );
				}

			}// foreach
		}// if

		$string = str_replace( $data_replace_keys, $data_replace_values, $string );

		return $string;

	}


	/**
	 * receive imported data information
	 *
	 * @param string $id
	 *
	 * @see search_and_replace_id
	 *
	 * @return mixed null on failure otherwise return saved data
	 */
	protected function get_id( $id ) {

		if ( ! isset( $this->id_list[ $this->demo_id ] ) ) {
			$this->id_list[ $this->demo_id ] = get_option( sprintf( 'bs_demo_id_%s', $this->demo_id ) );
		}

		$id = trim( $id );
		if ( isset( $this->id_list[ $this->demo_id ][ $id ] ) ) {

			return $this->id_list[ $this->demo_id ][ $id ];
		}

		return;
	}


	/**
	 * escape special characters
	 *
	 * @param string $subject
	 *
	 * @return string
	 */
	function regex_escape( $subject ) {

		return str_replace( array( '\\', '^', '-', ']' ), array( '\\\\', '\\^', '\\-', '\\]' ), $subject );
	}


	/**
	 * explode string using delimiter but skip content inside of quotes
	 *
	 * @param string $subject    string to explode
	 * @param string $delimiters explode delimiter
	 * @param string $quotes
	 *
	 * @return string
	 */
	function quoted_explode( $subject, $delimiters = ':', $quotes = '\'' ) {

		$clauses[] = '[^' . $this->regex_escape( $delimiters . $quotes ) . ']';
		foreach ( str_split( $quotes ) as $quote ) {
			$quote     = $this->regex_escape( $quote );
			$clauses[] = "[$quote][^$quote]*[$quote]";
		}

		$regex = '(?:' . implode( '|', $clauses ) . ')+';
		preg_match_all( '/' . str_replace( '/', '\\/', $regex ) . '/', $subject, $matches );

		return $matches[0];
	}


	/**
	 * Filter function parameters. Remove quotes inside around the parameter
	 *
	 * @param string $param
	 *
	 * @return string filtered string
	 */
	private function filter_function_params( $param ) {

		// replace params that are inside {the_id}
		if ( preg_match( '/^{(.*?)}$/', $param, $__matched ) ) {
			$param = $this->get_id( $__matched[1] );
		}

		return trim( $param, "'" );
	}


	/**
	 * update or insert option
	 * this method just used in import_option method
	 *
	 * @see import_options
	 *
	 * @param array                  $option
	 * @param BF_Demo_Option_Manager $handler
	 *
	 * @throws BF_Exception
	 */
	private function insert_update_option( $option, &$handler ) {

		$option_name = $handler->get_option_name( $option );

		if ( empty( $option['insert'] ) ) {

			$prev_option_data = $handler->get_option( $option );
			$update_option    = false;

			if ( ! empty( $option['merge_options'] ) ) {
				if ( $handler->merge_and_update_option( $option ) ) {

					//just save new option indexes, not all indexes
					if ( $prev_option_data && is_array( $prev_option_data ) ) {
						$new_option_data = array_intersect_key( $prev_option_data, $handler->get_option_value( $option ) );
						$this->save_update_state( $option_name, 'merge_option', $new_option_data );
					}
				} else {
					$update_option = true;
				}
			} else {
				$update_option = true;
			}

			if ( $update_option ) {
				$handler->update_option( $option );
				$this->save_update_state( $option_name, 'update_option', $prev_option_data );
			}
		} else {

			$handler->add_option( $option );
			$this->save_insert_state( $option_name, 'add_option' );
		}
	}
}libs/better-framework/product-pages/install-demo/assets/js/index.php000064400000000006151214002520021644 0ustar00<?php
libs/better-framework/product-pages/install-demo/assets/js/bs-product-demo.js000064400000050426151214002520023401 0ustar00(function ($) {
    var bs_product_demo_manager = function () {

        this.demo_steps = [];
        this.$loading_el = false;
        this.$active_box = false;
        this.active_el = false;
        this.ajax_extra_params = {};
        this.progress_min = 10;

        this.init();
    }

    bs_product_demo_manager.prototype = {
        $document: $(document),

        init: function () {
            var self = this;

            self.$document.ready(function () {

                self.demo_install();
                self.demo_uninstall();
            });
        },

        /**
         * context setter
         *
         * @param context {string} context name
         */
        set  context(context) {

            this.ajax_extra_params[ 'context' ] = context;
        },

        /**
         * context getter
         *
         * @returns {string} active context
         */
        get context() {

            return this.ajax_extra_params[ 'context' ];
        },


        /**
         * prepare ajax data
         *
         * @param params {object}
         * @returns {*}
         * @private
         */
        _ajax_params: function (params) {
            var default_obj = {},
                default_params = $("#bs-pages-hidden-params").serializeArray();

            if (default_params) {
                for (var i = 0; i < default_params.length; i++) {
                    default_obj[ default_params[ i ].name ] = default_params[ i ].value;
                }
            }

            return $.extend(default_obj, params);
        },

        /**
         * send ajax request and fire callback on success
         *
         * @param params {object} data to send
         * @param success_callback {Function} callback for ajax.done method
         */
        ajax: function (params, success_callback) {

            var self = this;
            params = this._ajax_params(params);

            $.ajax({
                 url: ajaxurl,
                 type: 'POST',
                 dataType: 'json',
                 data: $.extend(
                     {action: 'bs_pages_ajax', page_id: $("#bs-pages-current-id").val()},
                     params,
                     self.ajax_extra_params
                 )
             })
             .done(success_callback)
             .fail(function () {

                 self.show_error(self.context === 'install' ? 'install-aborted' : 'failed');
             })
        },

        /**
         * Display message to user
         *
         * @param messageEl {string} message selector
         * @private
         */
        _show_message: function (messageEl) {

            if (this.$active_box) {
                messageEl = messageEl || this._getMessageSelector();

                this.$active_box
                    .find('.messages ' + messageEl)
                    .show()
                    .siblings()
                    .hide();
            }
        },

        /**
         * Get message selector by context
         *
         * @return {string} message selector.
         * @private
         */
        _getMessageSelector: function () {
            var result = '';
            switch (this.context) {

                case 'uninstall':
                    result = '.uninstalling';
                    break;

                case 'install':
                    result = '.installing';
                    break;
            }

            return result;
        },

        /**
         * Get ajax bs_pages_action value by context
         *
         * @return {string} ajax action value.
         * @private
         */
        _getAjaxAction: function () {

            var result = '';
            switch (this.context) {

                case 'uninstall':
                    result = 'rollback';
                    break;

                case 'install':
                    result = 'import';
                    break;
            }

            return result;
        },

        /**
         * Run install/uninstall demo process
         *
         * @private
         */
        _demo_process: function () {

            var self = this,
                $this = $(self.active_el).closest('.bs-pages-buttons');
            this.$active_box = $this.closest('.bs-pages-demo-item');

            this.deactivate_boxes();
            this.deactivate_menu();
            this.deactivate_tabs();

            $this.hide();
            self._show_message();

            //display progressbar to user
            self.$loading_el = $this
                .closest('.bs-pages-demo-item')
                .find('.bs-pages-progressbar')
                .css('visibility', 'visible')
                .css('width', self.progress_min + '%'); //default progress bar value is 10 percent

            var demo_id = $this.data('demo-id');

            $(window).on('beforeunload.bs-demo-installer', function(e) {
                return true;
            });
            //get install/uninstall steps from server
            self.ajax(
                {
                    bs_pages_action: 'get_steps',
                    demo_id: demo_id
                },

                function (response) {

                    if (response && typeof response.success !== 'undefined' && response.success) {
                        self.demo_steps = response.result;
                        self.demo_ajax_request(demo_id, 0, 1, 1);
                    } else {
                        self.show_error(self.context === 'uninstall' ? 'uninstall-start-failed' : 'install-start-failed');
                    }
                }
            );
        },

        /**
         * bind click event for installation process
         */
        demo_install: function () {

            var self = this;

            $('.bs-pages-buttons').on('click', '.install-demo a', function (e) {

                e.preventDefault();

                self.active_el = this;

                /**
                 * show confirm modal before start installation process
                 */
                self._confirm(
                    {
                        header: bs_demo_install_loc.install.header,
                        title: bs_demo_install_loc.install.title,
                        body: bs_demo_install_loc.install.body,
                        button_label: bs_demo_install_loc.install.button_yes,
                        button_no: bs_demo_install_loc.install.button_no,
                        checkbox: true
                    },

                    function () {

                        this.close_modal();
                        self.context = 'install';
                        self._demo_process();
                    }
                );
            });
        },

        /**
         * bind click event for rollback process
         */
        demo_uninstall: function () {

            var self = this;

            $('.bs-pages-buttons').on('click', '.uninstall-demo a', function (e) {

                e.preventDefault();

                self.active_el = this;

                /**
                 * show confirm modal before start rollback process
                 */
                self._confirm(
                    {
                        header: bs_demo_install_loc.uninstall.header,
                        title: bs_demo_install_loc.uninstall.title,
                        body: bs_demo_install_loc.uninstall.body,
                        button_label: bs_demo_install_loc.uninstall.button_yes,
                        button_no: bs_demo_install_loc.uninstall.button_no,
                        checkbox: false
                    },
                    function () {


                        this.close_modal();
                        self.context = 'uninstall';
                        self._demo_process();
                    }
                );
            });

        },

        /**
         * Show confirm modal and fire callback if user accepted
         *
         * @param content {object} modal context object {@see BS_Modal} Mustache View Object
         * @param confirm_callback {Function}
         * @private
         */
        _confirm: function (content, confirm_callback) {

            var self = this;
            $.bs_modal({
                content: $.extend(
                    {
                        icon: 'fa-download',
                        image_align: $('body').hasClass('rtl') ? 'left' : 'right',
                        image_src: $(this.active_el).closest('.bs-pages-demo-item').find('.bs-demo-thumbnail').attr('src'),
                        checkbox_label: content.checkbox ? bs_demo_install_loc.checked_label : bs_demo_install_loc.unchecked_label
                    },
                    content
                ),

                buttons: {
                    custom_event: {
                        label: content.button_label,
                        type: 'primary',
                        clicked: function () {
                            confirm_callback.call(this);

                            self.$document.off('change.demo_settings');
                        }
                    },
                    close_modal: {
                        btn_classes: 'bs-modal-button-aside',
                        label: content.button_no || 'No',
                        type: 'secondary',
                        action: 'close',
                        focus:true
                    }
                },

                template: 'single_image'
            });

            /**
             * checkbox dynamic label
             *
             * change check label  `include content` or `Only settings`
             */
            var el = '.bs-modal .toggle-content';
            self.$document.on('change.demo_settings', el, function (e) {

                var $this = $(this), have_content = $this.is(':checked');
                $this.next('.checkbox-label').html(have_content ? bs_demo_install_loc.checked_label : bs_demo_install_loc.unchecked_label);

                self.ajax_extra_params[ 'have_content' ] = have_content ? 'yes' : 'no';

            }).find(el).change();
        },

        /**
         * handle box messages, hide loading message and display success message
         *
         *
         * @private
         */
        _demo_process_complete: function () {

            $(window).off('beforeunload.bs-demo-installer');
            if (this.active_el) {

                this.$active_box = $(this.active_el).closest('.bs-pages-demo-item');

                var $messages = this.$active_box.find('.messages'),
                    successSelector = false,
                    isUninstalling = this.context === 'uninstall',
                    btnSelector = false,
                    animation_delay = 5000,
                    success = true,
                    self = this;


                if (this.context === 'install-start-failed') {
                    btnSelector = '.preview-demo,.install-demo';
                    animation_delay = 0;
                    success = false;
                } else if (this.context === 'uninstall-start-failed') {
                    btnSelector = '.uninstall-demo';
                    animation_delay = 0;
                    success = false;
                } else if (this.context === 'failed') {
                    //process has been failed
                    successSelector = '.failed';
                    animation_delay = 0;
                    success = false;
                } else if (isUninstalling) {
                    // in uninstalling process
                    successSelector = '.uninstalled';
                    btnSelector = '.preview-demo,.install-demo';
                } else if(this.context === 'install-aborted') {
                    animation_delay = 0;
                    btnSelector = '.uninstall-demo';
                } else {
                    // in installing process
                    successSelector = '.installed';
                    btnSelector = '.uninstall-demo';
                }

                // hide loading message
                $messages.children().hide();
                if( successSelector ) {
                    $messages.find(successSelector).show();
                }
                // hide installed message and show uninstall button after 5 second
                $messages
                    .delay(animation_delay)
                    .queue(function (n) {
                        var $this = $(this);

                        // show uninstall button
                        var $buttons = $this
                            .closest('.bs-pages-demo-item')
                            .find('.bs-pages-buttons');

                        $buttons.children().hide();
                        if (btnSelector) {
                            // hide loading message
                            $messages.children().hide();

                            $buttons
                                .show()
                                .find(btnSelector)
                                .show();
                        }

                        n();
                    });

                // add installed class to box element wrapper
                this.$active_box
                    .delay(700)
                    .queue(function (n) {

                        if(success) {
                            $(this)[ isUninstalling ? 'removeClass' : 'addClass' ]('installed');
                        }
                        self.active_boxes();
                        self.active_menu();
                        self.active_tabs();

                        n();
                    });

                self.hide_progressbar(this.$active_box);
            }
        },

        active_menu: function () {
            $('#adminmenuwrap').removeClass('installing-demo');
        },
        active_tabs: function () {
            $('.bs-product-pages-tabs-wrapper').removeClass('installing-demo');
        },
        deactivate_menu: function () {
            $('#adminmenuwrap').addClass('installing-demo');
        },
        deactivate_tabs: function () {
            $('.bs-product-pages-tabs-wrapper').addClass('installing-demo');
        },
        active_boxes: function () {
            //remove disabled class for all boxes
            $(".bs-product-pages-install-demo")
                .find('.bs-pages-demo-item')
                .removeClass('demo-disabled');
        },

        deactivate_boxes: function () {
            //remove disabled class from active demo box
            this.$active_box.removeClass('demo-disabled');

            //add disabled class to another demo boxes
            $(".bs-product-pages-install-demo")
                .find('.bs-pages-demo-item')
                .not(this.$active_box)
                .addClass('demo-disabled');

        },
        hide_progressbar: function ($active_box) {
            $active_box = $active_box || $(this.active_el).closest('.bs-pages-demo-item');
            $active_box
                .find('.bs-pages-progressbar')
                .css('visibility', 'hidden')
                .delay(500)
                .queue(function (n) {
                    $(this).css('width', '0%');
                    n();
                });
        },

        demo_ajax_request: function (demo_id, index, step_number, progress_step) {

            var self = this,
                ajaxParams = {
                    demo_id: demo_id,
                    current_type: self.demo_steps.types[ index ],
                    current_step: step_number,
                    bs_pages_action: self._getAjaxAction()
                };

            self.ajax(
                ajaxParams ,
                function (response) {

                    if (response && typeof response.success !== 'undefined' && response.success) {

                        //increase loading
                        if (self.$loading_el) {
                            self.$loading_el.css(
                                'width',
                                Math.max(
                                    10,
                                    Math.floor(100 / self.demo_steps.total * progress_step)
                                ) + '%'
                            )
                        }

                        //call _demo_process_complete method on last ajax request
                        if (self.demo_steps.steps_count <= index && self.demo_steps.steps[ index ] <= step_number) {
                            self._demo_process_complete();

                        } else {

                            //calculate next step position
                            if (self.demo_steps.steps[ index ] <= step_number) {
                                index++;
                                step_number = 1;
                            } else {
                                step_number++;
                            }

                            self.demo_ajax_request(demo_id, index, step_number, progress_step + 1);
                        }
                    } else {
                        //process failed! so display error modal
                        if(response.result &&  response.result.is_error){
                            response.result.error_message += "\n\n";
                            response.result.error_message += JSON.stringify(ajaxParams);

                            console.error(response.result.error_message, response.result.error_code);

                            var body = bs_demo_install_loc.on_error.display_error
                                                          .replace('%ERROR_CODE%', response.result.error_code)
                                                          .replace('%ERROR_MSG%', response.result.error_message);
                            var modal  = self.show_error(undefined, undefined, {body: body}),
                                $info = modal.$modal.find('.bs-pages-error-section textarea');

                            $info.height($info[ 0 ].scrollHeight);
                            modal.make_vertical_center();
                        } else {
                            self.show_error();
                        }
                    }
                }
            );
        },

        /**
         * Display error modal
         */
        show_error: function (context,loc_index,content) {
            if (this.context === 'failed')
                return;
            var prevContext = this.context,
                rollback_force = true;

            this.context = context || 'failed';

            if (typeof loc_index === 'undefined') {
                loc_index = prevContext === 'install-aborted' ? 'uninstall_error' : 'on_error';
            }
            if( this.context === 'install-start-failed' ) {
                loc_index = 'install_start_error';
                rollback_force = false;
            } else if( this.context === 'uninstall-start-failed' ) {
                loc_index = 'uninstall_start_error';
                rollback_force = false;
            }

            var self = this,
                loc = jQuery.extend(bs_demo_install_loc[ loc_index ], content || {});

            return $.bs_modal({
                content: loc,
                buttons: {
                    close_modal: {
                        label: loc.button_ok,
                        type: 'primary',
                        action: 'close'
                    },
                },
                events: {
                    modal_close: function () {
                        self._show_error_done(context);
                        if(rollback_force) {
                            //rollback request
                            var demo_id = self.$active_box
                                              .find('.bs-pages-buttons')
                                              .data('demo-id');
                            self.ajax(
                                {
                                    bs_pages_action: 'rollback_force',
                                    demo_id: demo_id
                                },
                                function (response) {
                                }
                            );
                        }
                    }
                }
            });
        },

        _show_error_done: function (context) {
            this.context = context || 'failed';
            this._demo_process_complete();
            this.active_boxes();
            this.active_menu();
            this.active_tabs();
            this.hide_progressbar();
        }
    };

    new bs_product_demo_manager();
})(jQuery);libs/better-framework/product-pages/install-demo/assets/css/bs-product-demo.css000064400000006242151214002520023726 0ustar00/**
    =>BS Product Import Style
 **/


/**
* =>BS Product Import Style
**/
.bs-pages-demo-item {
    width: 330px;
    height: 294px;
}

.installed .bs-pages-buttons>span:not(.uninstall-demo) {
    display: none;
}
.installed .bs-pages-buttons .uninstall-demo {
    display: block;
}

.clearfix:after {
    content: " ";
    display: table;
    clear: both;
}

.bs-pages-secondary-btn {
    background: #fbfbfb;
    color: #757575;
    border-color: #e3e3e3;
}
.bs-pages-buttons .uninstall-demo {
    display: none;
}
.installed .bs-pages-buttons .uninstall-demo {
    display: block;
}
.bs-pages-buttons .uninstall-demo .bs-pages-secondary-btn {
    color: #e74a4a;
    -webkit-box-shadow: none;
    -moz-box-shadow: none;
    box-shadow: none;
    border: none;
}


.installed .bs-pages-progressbar .bs-pages-progress {
    background-color: #de3030;
}
.bs-pages-demo-item-footer {
    min-height:232px;
}

.bs-pages-demo-item-footer .messages {
    float: right;
}
.bs-pages-demo-item-footer .messages .fa {
    margin-right: 4px;
    vertical-align: middle;
}
.bs-pages-demo-item-footer .messages>div {
    display: none;
    font-weight: 600;
    vertical-align: middle;
    padding: 15px 12px 15px;
    font-size: 14px;
}
.bs-pages-demo-item-footer .messages>.installing {
    color: #06bb51;
}
.bs-pages-demo-item-footer .messages>.uninstalling,
.bs-pages-demo-item-footer .messages>.failed {
    color: #e74a4a;
}

.bs-pages-demo-item-footer .messages>.installed,
.bs-pages-demo-item-footer .messages>.uninstalled {
    color: #06bb51;
}
.bs-pages-ribbon-wrapper {
    position: relative;
    overflow: visible;
    opacity: 0;

    -webkit-transition: opacity 0.5s;
    -moz-transition: opacity 0.5s;
    -ms-transition: opacity 0.5s;
    -o-transition: opacity 0.5s;
    transition: opacity 0.5s;
}
.installed .bs-pages-ribbon-wrapper {
    opacity: 1;
}
.bs-pages-ribbon-wrapper .bs-pages-ribbon {
    border-right: 62px solid transparent;
    border-top: 62px solid #06bb51;
    height: 0;
    position: absolute;
    width: 0;
    left: 0;
}
.bs-pages-ribbon-label {
    position: absolute;
    color: #fff;
    font-weight: 600;
    font-size: 18px;
    top: 5px;
    left: 10px;
}
.bs-pages-demo-item.demo-disabled .bs-pages-overlay {
    display: block;
}
.bs-pages-demo-item.demo-disabled {
    opacity:0.5;
}


/**
* ->Badges
**/
.bf-item-container .demo-badges{
    position: absolute;
    top: 0;
    right: 0;
    line-height: 0;
}
.bf-item-container .demo-badges .badge{
    display: inline-block;
    line-height: 26px;
    background: #d54e21;
    margin-left: 5px;
    padding: 0 6px;
    font-size: 12px;
    color: #fff;
    font-weight: 700;
}


/**
    =>RTL FIX
 **/
.rtl .bs-pages-demo-item-footer .messages {
    float: left;
}
.rtl .bs-pages-demo-item-footer .messages .fa {
    margin-left: 4px;
    margin-right: auto;
}
.rtl .bs-pages-ribbon-wrapper .bs-pages-ribbon {
    border-left: 62px solid transparent;
    right: 0;
    left: auto;
    border-right: none;
}
.rtl .bs-pages-ribbon-label {
    right: 10px;
    left: auto;
}
.rtl .bf-item-container .demo-badges {
    left: 0;
    right: auto;
}
.rtl .bf-item-container .demo-badges .badge {
    margin-right: 5px;
    margin-left: auto;
}
libs/better-framework/product-pages/install-demo/assets/css/index.php000064400000000006151214002520022020 0ustar00<?php
libs/better-framework/product-pages/install-demo/class-bf-demo-posts-manager.php000064400000017163151214002520024025 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Class BF_Demo_Posts_Manager
 *
 * add or remove post & post meta
 */
class BF_Demo_Posts_Manager {

	/**
	 * Insert or update a post.
	 *
	 * array {
	 *
	 * @see wp_insert_post() $postarr params
	 *
	 * @type integer $thumbnail_id      Future Image Attachment Post ID
	 * @type string  $post_content_file Optional if 'post_content' index exists.file path to post content.
	 *      for long post content can save on file.
	 *
	 * @type string  $post_content      Optional if 'post_content_file' index exists.
	 * }
	 *
	 *
	 * @param Array  $post_params
	 *
	 * @return int|WP_Error WP_Error on Failure or post id on success.
	 */
	public function add_post( $post_params ) {

		$post_params = bf_merge_args( $post_params, array(
			'post_title'        => '',
			'post_status'       => 'publish',
			'post_content_file' => '',
			'post_content'      => '',
			'post_terms'        => '',
			'post_excerpt'      => '',
			'post_type'         => 'post',
			'post_excerpt_file' => '',
		) );

		/**
		 * Remove buggy plugins actions
		 */
		remove_action( 'save_post', 'kgvid_save_post' );

		try {

			if ( empty( $post_params['post_title'] ) ) {
				throw new Exception( 'post title could not be empty.' );
			}

			if ( ! empty( $post_params['post_content_file'] ) && ! is_readable( $post_params['post_content_file'] ) ) {
				throw new Exception( 'cannot read content of post.' );
			}

			if ( $post_params['post_excerpt_file'] && ! is_readable( $post_params['post_excerpt_file'] ) ) {
				throw new Exception( 'cannot read excerpt of post.' );
			}

			if ( ! empty( $post_params['thumbnail_id'] ) && ! wp_attachment_is_image( $post_params['thumbnail_id'] ) ) {
				throw new Exception( 'invalid post thumbnail.' );
			}

			//validate post terms
			$post_terms = array();

			if ( $post_params['post_terms'] && is_array( $post_params['post_terms'] ) ) {

				foreach ( $post_params['post_terms'] as $taxonomy => $terms_id ) {

					if ( ! taxonomy_exists( $taxonomy ) ) {
						throw new Exception( sprintf( 'invalid taxonomy %s', $taxonomy ) );
					}

					$post_terms[ $taxonomy ] = array_map( 'intval', explode( ',', $terms_id ) );
				}
			}


			if ( $post_params['post_content_file'] ) {
				$post_params['post_content'] = BF_Product_Demo_Installer::Run()->apply_pattern( bf_get_local_file_content( $post_params['post_content_file'] ) );
				unset( $post_params['post_content_file'] );
			} elseif ( $post_params['post_content'] ) {

				$post_params['post_content'] = BF_Product_Demo_Installer::Run()->apply_pattern( $post_params['post_content'] );
			}

			// read excerpt from file
			if ( $post_params['post_excerpt_file'] ) {
				$post_params['post_excerpt'] = BF_Product_Demo_Installer::Run()->apply_pattern( bf_get_local_file_content( $post_params['post_excerpt_file'] ) );
				unset( $post_params['post_excerpt_file'] );
			}

			// adds "bs" to slug
			if ( empty( $post_params['post_name'] ) ) {
				$post_params['post_name'] = 'bs-' . $post_params['post_title'];
			}

			BF_Product_Demo_Installer::data_params_filter( $post_params );

			$maybe_post_id = wp_insert_post( $post_params );

			if ( is_wp_error( $maybe_post_id ) ) {
				return $maybe_post_id;
			}

			$post_id = &$maybe_post_id;

			foreach ( $post_terms as $taxonomy => $terms_id ) {
				wp_set_post_terms( $post_id, $terms_id, $taxonomy );
			}

			if ( ! empty( $post_params['thumbnail_id'] ) ) {
				set_post_thumbnail( $post_id, $post_params['thumbnail_id'] );
			}


			if ( ! empty( $post_params['post_format'] ) ) {
				set_post_format( $post_id, $post_params['post_format'] );
			}

			// Regenerates VC styles again because VC can not generate!
			if ( isset( $post_params['prepare_vc_css'] ) && $post_params['prepare_vc_css'] && ! empty( $post_params['post_content'] ) ) {

				// match all shortcodes
				preg_match_all( '/ css=\"([^\"]*)\"/', $post_params['post_content'], $shortcodes );

				$final_css = '';

				foreach ( $shortcodes[1] as $css ) {
					$final_css .= $css;
				}

				update_post_meta( $post_id, '_wpb_shortcodes_custom_css', $final_css );
			}

			return $post_id;

		} catch( Exception $e ) {

			return new WP_Error( 'add_post_error', $e->getMessage() );
		}
	}


	/**
	 * delete a post
	 *
	 * @param $post_id post ID to delete
	 *
	 * @return bool true on success or false on failure
	 */

	public function remove_post( $post_id ) {

		return (bool) wp_delete_post( $post_id, true );
	}


	/**
	 * @param Array $post_params
	 *
	 * @see add_post()
	 *
	 * @return int|WP_Error WP_Error on Failure or post id on success.
	 */

	public function add_page( $post_params ) {

		$post_params['post_type'] = 'page';

		return $this->add_post( $post_params );
	}


	/**
	 *
	 * prepare a array with three index to pass update_post_meta, add_post_meta,
	 * delete_post_meta function via call_user_func_array function.
	 *
	 * @param Array $term_meta_params
	 *
	 * @return array
	 */
	protected function get_meta_params( $term_meta_params ) {

		$required_params = array(
			'post_id'    => '',
			'meta_key'   => '',
			'meta_value' => '',
		);

		if ( ! array_diff_key( $required_params, $term_meta_params ) ) {

			return array(
				$term_meta_params['post_id'],
				$term_meta_params['meta_key'],
				$term_meta_params['meta_value']
			);
		}
	}


	/**
	 * @param Array $post_meta_params
	 *
	 * @see get_meta_params()
	 *
	 * @return int|false Meta ID on success, false on failure.
	 */
	public function add_post_meta( $post_meta_params ) {

		if ( $meta_params = $this->get_meta_params( $post_meta_params ) ) {

			return call_user_func_array( 'add_post_meta', $meta_params );
		}
	}


	/**
	 * @param $post_meta_id post meta unique id in database
	 *
	 * @return bool true on successful delete, false on failure.
	 */
	public function remove_post_meta( $post_meta_id ) {

		return delete_metadata_by_mid( 'post', $post_meta_id );
	}


	/**
	 * delete a post meta from database
	 *
	 * @param Array $post_meta_params
	 *
	 * @see get_meta_params()
	 *
	 * @return int|false Meta ID on success, false on failure.
	 */
	public function delete_post_meta( $post_meta_params ) {

		if ( $meta_params = $this->get_meta_params( $post_meta_params ) ) {

			return call_user_func_array( 'delete_post_meta', $meta_params );
		}
	}


	/**
	 * Update post meta field
	 *
	 * @param Array $post_meta_params
	 *
	 * @see get_meta_params()
	 *
	 * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure.
	 */

	public function update_post_meta( $post_meta_params ) {

		if ( $meta_params = $this->get_meta_params( $post_meta_params ) ) {

			return call_user_func_array( 'update_post_meta', $meta_params );
		}
	}


	/**
	 * get post meta field value
	 *
	 * @param $post_meta_params
	 *
	 * @see get_meta_params()
	 *
	 * @return mixed  value of meta data
	 */
	public function get_post_meta( $post_meta_params ) {

		if ( $meta_params = $this->get_meta_params( $post_meta_params ) ) {

			unset( $meta_params[2] );

			return call_user_func_array( 'get_post_meta', $meta_params );
		}
	}

}
libs/better-framework/product-pages/install-demo/class-bf-demo-media-manager.php000064400000006446151214002520023736 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Class BF_Demo_Media_Manager
 *
 * Import and rollback Media file
 */
class BF_Demo_Media_Manager {

	/**
	 *
	 *
	 * @param string       $image_url   remote image url
	 * @param string|array $args        {
	 *
	 *  Optional. Array or string of arguments to handle upload & resize image.
	 *
	 * @type int           $post_id     The post ID the media is associated with
	 *
	 * @type string        $description Description of the sideloaded file
	 *
	 * @type string        $filename    basename of the file
	 *              default remote file ($image_url) basename
	 *
	 * $type bool   $resize enable generating thumbnail image.
	 *              default true.
	 * }
	 *
	 * @return bool|int|WP_Error int attachment_id  on success WP_Error or False otherwise.
	 */
	public function add_image( $image_url, $args = array() ) {

		//check file type

		$file_basename = basename( $image_url );
		$file_type     = wp_check_filetype( $file_basename );
		if ( empty( $file_type['type'] ) || substr( $file_type['type'], 0, 6 ) !== 'image/' ) {
			return false;
		};


		//some functions need such as media_handle_sideload() exists in this files
		require_once ABSPATH . 'wp-admin/includes/file.php';
		require_once ABSPATH . 'wp-admin/includes/media.php';
		require_once ABSPATH . 'wp-admin/includes/image.php';

		//download image and save in /tmp folder
		$temp_file = download_url( $image_url );
		if ( is_wp_error( $temp_file ) ) {
			return $temp_file;
		}

		$args = wp_parse_args( $args, array(
			'post_id'     => null,
			'description' => null,
			'file_name'   => $file_basename,
			'resize'      => true,
		) );

		//prepare a variable similar to $_FILES to pass media_handle_sideload() function
		$file_data = array(
			'name'     => $args['file_name'],
			'tmp_name' => $temp_file
		);

		//disable generate thumbnails by empty list of image sizes
		if ( ! $args['resize'] ) {

			add_filter( 'intermediate_image_sizes', '__return_empty_array', 9999 );
		}

		$maybe_attachment_id = media_handle_sideload( $file_data, $args['post_id'], $args['description'] );

		if ( is_wp_error( $maybe_attachment_id ) ) {
			return $maybe_attachment_id;
		}


		if ( ! $args['resize'] ) {

			remove_filter( 'intermediate_image_sizes', '__return_empty_array', 9999 );
		}

		$attachment_id = &$maybe_attachment_id;

		return $attachment_id;
	}


	/**
	 * force delete attachment by media ID
	 *
	 * @param $media_id attachment post id in database
	 *
	 * @return bool true on success or false on failure
	 */

	public function remove_image( $media_id ) {


		return (bool) wp_delete_attachment( $media_id, true );
	}
}libs/better-framework/phpunit.xml000064400000002073151214002520013160 0ustar00<phpunit
        bootstrap="tests/bootstrap.php"
        backupGlobals="false"
        colors="true"
        convertErrorsToExceptions="true"
        convertNoticesToExceptions="true"
        convertWarningsToExceptions="true"
>
    <testsuites>

        <testsuite name="elementor">
            <!--<directory prefix="test-" suffix=".php">./tests/elementor</directory>-->
        </testsuite>
        <testsuite name="gutenberg">
            <directory prefix="test-" suffix=".php">./tests/gutenberg</directory>
            <directory prefix="test-" suffix=".php">./tests/transpiler</directory>
        </testsuite>

    </testsuites>

    <php>
        <includePath>.</includePath>

        <env name="custom_abspath" value="true"/>
        <env name="db" value="bf-test"/>
        <env name="include_elementor" value="true"/>
    </php>


    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory prefix="test-" suffix=".php">./tests/</directory>
            <exclude>./tests/vendor/</exclude>
        </whitelist>
    </filter>
</phpunit>
libs/better-framework/admin-menus/class-bf-admin-menus.php000064400000044473151214002520017614 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// Prevent Direct Access
defined( 'ABSPATH' ) or die;


/**
 * Class BF_Admin_Menus
 */
class BF_Admin_Menus {


	/**
	 * Contains list of all active admin menus
	 *
	 * @since 1.4
	 * @var array
	 */
	public $admin_menus = array();


	/**
	 * Contains list of all active admin bar menus
	 *
	 * @var array
	 */
	protected $admin_bar_menus = array();


	/**
	 * contains id of BetterStudio menu
	 *
	 * @since 1.4
	 * @var string
	 */
	protected $main_admin_menu_id = '';


	/**
	 * contains slug of BetterStudio menu
	 *
	 * @since 1.4
	 * @var string
	 */
	protected $main_admin_menu_slug = 'better-studio';


	function __construct() {

		// Used for registering active menus to WP admin menu
		$hook = is_admin() ? 'admin_menu' : 'wp_head';
		add_action( $hook, array( $this, 'wp_admin_menu' ), 5 );

		add_action( 'admin_bar_menu', array( $this, 'wp_admin_bar_menu' ), 81 );

	}


	/**
	 * @param WP_Admin_Bar $wp_admin_bar
	 */
	public function wp_admin_bar_menu( $wp_admin_bar ) {

		if ( $this->admin_bar_menus ) {
			usort( $this->admin_bar_menus, array( $this, 'usort_cmp_by_position' ) );

			$parent_suffix = '-parent';
			foreach ( $this->admin_bar_menus as $menu ) {

				$capability = isset( $menu['capability'] ) ? $menu['capability'] : 'manage_options';

				if ( ! current_user_can( $capability ) ) {
					continue;
				}

				$icon = '';

				// append new  menu and set icon for parent item
				if ( empty( $menu['parent'] ) ) {

					if ( ! empty( $menu['icon'] ) ) {

						$menu = $this->normalize_icon( $menu );

						$class = 'bf-admin-bar-icon-' . str_replace( array( '/', '_' ), '-', $menu['slug'] );
						$icon  = '<span class="' . $class . '"></span>';

						$this->add_css( '.' . $class . ':before{ vertical-align:middle;content: \'' . $menu['icon']['font_code'] . '\' !important; font-family: \'' . $menu['icon']['font_name'] . '\'; font-size: 14px; line-height: 21px;' . ( is_rtl() ? 'vertical-align: middle;' : '' ) . '}', true );
						$this->add_css( '.' . $class . '{font-weight:normal; vertical-align:top;margin-' . ( is_rtl() ? 'left' : 'right' ) . ':10px !important;display: inline-block;line-height: 32px !important;' . ( is_rtl() ? 'float:right' : '' ) . '; text-rendering: auto !important;-webkit-font-smoothing: antialiased !important;-moz-osx-font-smoothing: grayscale !important;}', true );
					}

					$wp_admin_bar->add_node( array(
						'id'     => $menu['slug'] . $parent_suffix,
						'title'  => $icon . ( isset( $menu['parent_title'] ) ? $menu['parent_title'] : $menu['menu_title'] ),
						'href'   => isset( $menu['href'] ) ? $menu['href'] : admin_url( 'admin.php?page=' . $menu['slug'] ),
						'meta'   => isset( $menu['meta'] ) ? $menu['meta'] : array(),
						'parent' => false
					) );

					$menu['parent'] = $menu['slug'];
				}


				$wp_admin_bar->add_node( array(
					'id'     => $menu['slug'],
					'title'  => isset( $menu['menu_title'] ) ? $menu['menu_title'] : $menu['name'],
					'href'   => isset( $menu['href'] ) ? $menu['href'] : admin_url( 'admin.php?page=' . $menu['slug'] ),
					'meta'   => isset( $menu['meta'] ) ? $menu['meta'] : array(),
					'parent' => $menu['parent'] . $parent_suffix
				) );
			}
		}
	}


	/**
	 * Used for adding page to WP menu
	 *
	 * @since 1.4
	 *
	 * @param $menu
	 */
	function add_menupage( $menu ) {

		if ( isset( $menu['id'] ) && isset( $menu['callback'] ) ) {

			$this->admin_menus[ $menu['id'] ] = $menu;

		}

	}


	/**
	 * Used for remove a page from WP menu
	 *
	 * @since 1.4
	 *
	 * @param string $menu_id
	 *
	 * @return bool
	 */
	function remove_menupage( $menu_id ) {

		if ( isset( $this->admin_menus[ $menu_id ] ) ) {

			unset( $this->admin_menus[ $menu_id ] );

			return true;
		}

		return false;
	}


	/**
	 * Used for adding separator to BetterStudio WP menu
	 *
	 * @since 2.0
	 *
	 * @param int    $position
	 * @param string $parent
	 */
	function add_menu_separator( $position = 79, $parent = 'better-studio' ) {

		$id = 'sep-' . mt_rand();

		$this->admin_menus[ $id ] = array(
			'id'         => $id,
			'slug'       => 'sep',
			'name'       => '',
			'page_title' => '',
			'menu_title' => '',
			'callback'   => '',
			'parent'     => $parent,
			'position'   => $position,
		);

	}


	/**
	 * Hook register menus to WordPress
	 *
	 * @since   1.4
	 * @access  public
	 *
	 * @return  void
	 */
	function wp_admin_menu() {

		/**
		 * Action for adding menu pages
		 *
		 * @since 1.4
		 */
		do_action( 'better-framework/admin-menus/admin-menu/before', $this );

		// If there is no submitted admin menu
		if ( bf_count( $this->admin_menus ) == 0 ) {
			return;
		}

		// Collects all menus outside of main BetterStudio menu
		$other_menus = array();

		// Adds admin pages that are outside of BetterStudio main menu
		foreach ( (array) $this->admin_menus as $menu_id => $menu ) {

			if ( isset( $menu['register_menu'] ) && $menu['register_menu'] == false ) {
				unset( $this->admin_menus[ $menu_id ] );
				continue;
			}

			if ( isset( $menu['parent'] ) && $menu['parent'] != 'better-studio' ) {

				if ( isset( $menu['on_admin_bar'] ) && $menu['on_admin_bar'] ) {
					$this->admin_bar_menus[ $menu_id ] = $menu;
				}
				if ( isset( $menu['on_sidebar'] ) && ! $menu['on_sidebar'] ) {
					continue;
				}

				$other_menus[ $menu_id ] = $menu;

				unset( $this->admin_menus[ $menu_id ] ); // remove from main menus
			}
		}

		// Sorts items with position sub array key
		usort( $other_menus, array( $this, 'usort_cmp_by_position' ) );

		// Adds admin pages that are outside of BetterStudio main menu
		foreach ( (array) $other_menus as $menu_id => $menu ) {

			if ( $menu['parent'] === false && isset( $menu['parent_title'] ) ) {

				$_main_admin_menu_id   = 'better-studio/' . $menu['id'];
				$_main_admin_menu_slug = $menu['slug'];

				$capability = isset( $menu['capability'] ) ? $menu['capability'] : 'manage_options';

				// Adds main better studio menu page
				$this->register_menu_page( array(
					'id'         => $_main_admin_menu_id,
					'slug'       => $_main_admin_menu_slug,
					'parent'     => false,
					'name'       => $menu['parent_title'],
					'page_title' => $menu['parent_title'],
					'menu_title' => $menu['parent_title'],
					'callback'   => $menu['callback'],
					'capability' => $capability,
					'icon'       => '',
					'position'   => $menu['position'],
				) );

				// Updates main menu page for new main sub menu
				$this->register_menu_page( array(
					'id'         => $_main_admin_menu_id,
					'slug'       => $_main_admin_menu_slug,
					'parent'     => $_main_admin_menu_slug,
					'name'       => $menu['name'],
					'page_title' => $menu['page_title'],
					'menu_title' => $menu['menu_title'],
					'callback'   => $menu['callback'],
					'capability' => $capability,
					'icon'       => null,
					'position'   => 1,
				) );

				// Adds another temp item to force menu for having sub menu
				$this->register_menu_page( array(
					'id'         => '',
					'slug'       => 'extra',
					'parent'     => $_main_admin_menu_slug,
					'name'       => '',
					'page_title' => '',
					'menu_title' => '',
					'capability' => $capability,
					'icon'       => null,
					'position'   => '99',
				) );

				// Add style for hiding temp sub menu with css
				$this->add_css( '#adminmenu li#toplevel_page_' . str_replace( array( '/' ), '-', $_main_admin_menu_slug ) . ' .wp-submenu li:nth-child(3){ display: none !important; }', true );

				if ( ! empty( $menu['icon'] ) ) {

					$menu = $this->normalize_icon( $menu );

					$this->add_css( '#adminmenu li#toplevel_page_' . str_replace( array( '/' ), '-', $_main_admin_menu_slug ) . ' .wp-menu-image:before{ content: \'' . $menu['icon']['font_code'] . '\' !important; font-family: \'' . $menu['icon']['font_name'] . '\'; font-size: 15px; line-height: 21px;}', true );
				}

				unset( $this->admin_menus[ $menu_id ] );

			} else {

				$this->register_menu_page( $menu );

				unset( $this->admin_menus[ $menu_id ] );

			}
		}

		// add separator if needed
		$this->prepare_menu_separators();

		// Sorts items with position sub array key
		usort( $this->admin_menus, array( $this, "usort_cmp_by_position" ) );

		// When there is only one item in BetterStudio main menu
		if ( bf_count( $this->admin_menus ) == 1 ) {

			$menu = current( $this->admin_menus );

			// Save main menu id tat will be used for hiding
			$this->main_admin_menu_id = 'better-studio/' . $menu['id'];
			// todo check this, here we should set $this->main_admin_menu_slug but we don't!

			// Adds main better studio menu page
			$this->register_menu_page( array(
				'id'         => $this->main_admin_menu_id,
				'slug'       => $this->main_admin_menu_slug,
				'parent'     => false,
				'name'       => '<strong>Better</strong> Studio',
				'page_title' => '<strong>Better</strong> Studio',
				'menu_title' => '<strong>Better</strong> Studio',
				'callback'   => $menu['callback'],
				'capability' => 'manage_options',
				'icon'       => '',
				'position'   => '59.001',
			) );

			// Updates main menu page for new main sub menu
			$this->register_menu_page( array(
				'id'         => $this->main_admin_menu_id,
				'slug'       => $this->main_admin_menu_slug,
				'parent'     => $this->main_admin_menu_slug,
				'name'       => $menu['name'],
				'page_title' => $menu['page_title'],
				'menu_title' => $menu['menu_title'],
				'callback'   => $menu['callback'],
				'capability' => 'manage_options',
				'icon'       => null,
				'position'   => '59.001',
			) );

			// Adds another temp item to force menu for having sub menu
			$this->register_menu_page( array(
				'id'         => '',
				'slug'       => 'extra',
				'parent'     => $this->main_admin_menu_slug,
				'name'       => '',
				'page_title' => '',
				'menu_title' => '',
				'capability' => 'manage_options',
				'icon'       => null,
				'position'   => '59.001',
			) );

			// Add style for hiding temp sub menu with css
			$this->add_css( '#adminmenu li#toplevel_page_' . str_replace( array( '/' ), '-', $this->main_admin_menu_slug ) . ' .wp-submenu li:nth-child(3){ display: none !important; }', true );
			$this->add_css( '#adminmenu li#toplevel_page_' . str_replace( array( '/' ), '-', $this->main_admin_menu_slug ) . ' .wp-menu-image:before{ content: \'\e000\' !important; font-family: \'Better Studio Admin Icons\'; font-size: 15px; line-height: 21px;}', true );

		} else {

			foreach ( $this->admin_menus as $menu_id => $menu ) {

				// Adds main menu and update sub menu
				if ( empty( $this->main_admin_menu_id ) ) {

					// Save main menu id that will be used for hiding
					$this->main_admin_menu_id = 'better-studio/' . $menu['id'];

					if ( isset( $menu['slug'] ) ) {
						$this->main_admin_menu_slug = $menu['slug'];
					} else {
						$this->main_admin_menu_slug = $this->main_admin_menu_id;
					}

					// Adds main better studio menu page
					$this->register_menu_page( array(
						'id'                  => $this->main_admin_menu_id,
						'slug'                => $this->main_admin_menu_slug,
						'parent'              => false,
						'name'                => '<strong>Better</strong> Studio',
						'page_title'          => '<strong>Better</strong> Studio',
						'menu_title'          => '<strong>Better</strong> Studio',
						'callback'            => $menu['callback'],
						'capability'          => 'manage_options',
						'icon'                => '',
						'position'            => '59.001',
						'exclude_from_export' => false,
					) );

					// Updates main menu page for new main sub menu
					$this->register_menu_page( array(
						'id'                  => $this->main_admin_menu_id,
						'slug'                => $this->main_admin_menu_slug,
						'parent'              => $this->main_admin_menu_slug,
						'name'                => $menu['name'],
						'page_title'          => $menu['page_title'],
						'menu_title'          => $menu['menu_title'],
						'callback'            => $menu['callback'],
						'capability'          => 'manage_options',
						'icon'                => null,
						'position'            => '59.001',
						'exclude_from_export' => false,
					) );

				} // add sub menu for main menu
				else {

					$menu['parent'] = $this->main_admin_menu_slug;

					$this->register_menu_page( $menu );

				}
			}


		}

		// adding separator for main menu
		$this->add_css( '
#adminmenu li#toplevel_page_' . str_replace( array( '/' ), '-', $this->main_admin_menu_slug ) . ' { margin-bottom: 10px !important; }
#adminmenu li#toplevel_page_' . str_replace( array( '/' ), '-', $this->main_admin_menu_slug ) . ' ul li a[href=sep]{
height: 0px;
border-top: 1px solid rgba(255, 255, 255, 0.1);
overflow: hidden;
margin: 5px 0;
pointer-events: none;
padding:0;
cursor: default;
}
', true );
		$this->add_css( '#adminmenu li#toplevel_page_' . str_replace( array( '/' ), '-', $this->main_admin_menu_slug ) . ' .wp-menu-image:before{ content: \'\e000\' !important; font-family: \'Better Studio Admin Icons\'; font-size: 15px; line-height: 21px;}', true );

	}


	/**
	 * Adds menu page or sub page to WordPress
	 *
	 * @since 1.4
	 *
	 * @param bool|array $menu
	 */
	public function register_menu_page( $menu = false ) {

		if ( $menu == false || ! is_admin() ) {
			return;
		}

		$menu['parent'] = isset( $menu['parent'] ) ? $menu['parent'] : false;

		// Prepares menu name
		$name = str_replace(
			array(
				'_',
				'-'
			),
			array(
				' ',
				' '
			),
			$menu['id']
		);

		$name = ucwords( $name );

		// Page title
		$menu['page_title'] = isset( $menu['page_title'] ) ? $menu['page_title'] : ucfirst( $menu['id'] );

		// Menu title
		$menu['menu_title'] = isset( $menu['menu_title'] ) ? $menu['menu_title'] : $name;

		// Page shown for users that hav this capabilities
		$menu['capability'] = isset( $menu['capability'] ) ? $menu['capability'] : 'manage_options';

		// Menu icon
		$menu['icon'] = isset( $menu['icon'] ) ? $menu['icon'] : null;

		// Menu position in BetterStudio sub menu
		$menu['position'] = isset( $menu['position'] ) ? $menu['position'] : 40;

		// prepare menu slug
		if ( isset( $menu['slug'] ) ) {
			$menu_slug = $menu['slug'];
		} else {
			$menu_slug = 'better-studio/' . $menu['id'];
		}

		// prepare callback
		if ( ! isset( $menu['callback'] ) ) {
			$menu['callback'] = '';
		}

		if ( $menu['parent'] == false ) {

			call_user_func_array( 'add_' . 'menu' . '_page', array(
					$menu['page_title'],
					$menu['menu_title'],
					$menu['capability'],
					$menu_slug,
					$menu['callback'],
					$menu['icon'],
					$menu['position']
				)
			);

		} else {

			call_user_func_array( 'add_' . 'sub' . 'menu' . '_page', array(
					$menu['parent'],
					$menu['page_title'],
					$menu['menu_title'],
					$menu['capability'],
					$menu_slug,
					$menu['callback']
				)
			);

		}

	}


	/**
	 * Evaluate registered menus and adds smart separators
	 */
	function prepare_menu_separators() {

		$important_pages = false; // Theme pages and other important pages

		$general_pages = false; // General pages

		$plugins_pages = false; // Plugin pages

		$unimportant_pages = false; // Unimportant pages

		foreach ( $this->admin_menus as $menu ) {

			// Important pages
			if ( floatval( $menu['position'] ) > 0 && floatval( $menu['position'] ) < 50 ) {
				$important_pages = true;
			} elseif ( floatval( $menu['position'] ) > 50 && floatval( $menu['position'] ) < 80 ) {
				$general_pages = true;
			} elseif ( floatval( $menu['position'] ) > 80 && floatval( $menu['position'] ) < 100 ) {
				$plugins_pages = true;
			} elseif ( floatval( $menu['position'] ) >= 100 ) {
				$unimportant_pages = true;
			}

		}

		if ( $important_pages && $general_pages && $plugins_pages && $unimportant_pages ) {
			$this->add_menu_separator( 49 );
			$this->add_menu_separator( 79 );
			$this->add_menu_separator( 99 );
		} elseif ( ! $important_pages && $general_pages && $plugins_pages && $unimportant_pages ) {
			$this->add_menu_separator( 79 );
			$this->add_menu_separator( 99 );
		} elseif ( ! $important_pages && ! $general_pages && $plugins_pages && $unimportant_pages ) {
			$this->add_menu_separator( 99 );
		} elseif ( ! $important_pages && ! $general_pages && ! $plugins_pages && $unimportant_pages ) {
			$this->add_menu_separator( 99 );
		} elseif ( $important_pages && $general_pages && ! $plugins_pages && ! $unimportant_pages ) {
			$this->add_menu_separator( 49 );
		} elseif ( $important_pages && $general_pages && ! $plugins_pages && $unimportant_pages ) {
			$this->add_menu_separator( 49 );
			$this->add_menu_separator( 99 );
		} elseif ( $important_pages && $general_pages && $plugins_pages && ! $unimportant_pages ) {
			$this->add_menu_separator( 79 );
		}

	}

	//
	//
	// Handy Functions
	//
	//


	/**
	 * Handy function for sorting arrays with position sub value value
	 *
	 * @since 1.4
	 *
	 * @param $a
	 * @param $b
	 *
	 * @return mixed
	 */
	private function usort_cmp_by_position( $a, $b ) {

		return floatval( $a["position"] ) > floatval( $b["position"] );
	}


	protected function add_css( $code, $to_top = true ) {

		if ( is_user_logged_in() ) {
			call_user_func( is_admin() ? 'bf_add_admin_css' : 'bf_add_css', $code, $to_top, true );
		}
	}


	/**
	 * Changes icon field into standard format.
	 * (Backward compatibility)
	 *
	 * @param $menu
	 *
	 * @return mixed
	 */
	private function normalize_icon( $menu ) {

		if ( is_string( $menu['icon'] ) ) {

			$menu['icon'] = array(
				'icon'      => 'bsfi-publisher',
				'type'      => 'bs-icons',
				'height'    => '',
				'width'     => '',
				'font_code' => $menu['icon'],
				'font_name' => 'Better Studio Admin Icons',
			);
		} else {

			$_check = array(
				'bs-icons'    => 'bs-icons',
				'fontawesome' => 'FontAwesome',
			);

			if ( isset( $_check[ $menu['icon']['type'] ] ) ) {
				$menu['icon']['font_name'] = $_check[ $menu['icon']['type'] ];
			} else {
				$menu['icon']['font_name'] = 'Better Studio Admin Icons';
			}
		}

		return $menu;
	}
}libs/better-framework/class-better-framework.php000064400000125106151214002530016047 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

// Load general handy functions
include BF_PATH . 'functions/path.php';
include BF_PATH . 'functions/query.php';
include BF_PATH . 'functions/content.php';
include BF_PATH . 'functions/other.php';
include BF_PATH . 'functions/enqueue.php';
include BF_PATH . 'functions/shortcodes.php';
include BF_PATH . 'functions/archive.php';
include BF_PATH . 'functions/sidebar.php';
include BF_PATH . 'functions/menu.php';
include BF_PATH . 'functions/options.php';
include BF_PATH . 'functions/multilingual.php';


/**
 * Handy Function for accessing to BetterFramework
 *
 * @return Better_Framework
 */
function Better_Framework() {

	return Better_Framework::self();
}

// Fire Up BetterFramework
Better_Framework();


/**
 * Class Better_Framework
 */
class Better_Framework {


	/**
	 * Version of BF
	 *
	 * @var string
	 */
	public $version = '3.10.17';


	/**
	 * Defines which sections should be include in BF
	 *
	 * @since  1.0
	 * @access public
	 * @var array
	 */
	public $sections = array(
		'admin_panel'            => true,    // Theme option panel generator
		'admin-page'             => true,    // Theme option panel generator
		'admin-menus'            => true,    // Theme option panel generator
		'meta_box'               => true,    // Meta box generator
		'user-meta-box'          => true,    // User meta box generator
		'taxonomy_meta_box'      => false,   // Taxonomy meta box generator
		'load_in_frontend'       => false,   // For loading all BF in frontend, disable this for better performance
		'better-menu'            => false,   // Includes better menu
		'custom-css-fe'          => true,    // BF Front End Custom CSS Generator
		'custom-css-be'          => true,    // BF Back End ( WP Admin ) Custom CSS Generator
		'custom-css-pages'       => false,   // BF Pages Custom CSS
		'custom-css-users'       => true,    // BF Users Custom CSS
		'assets_manager'         => true,    // BF custom css generator
		'page-builder'           => false,   // Page builder functionality extender
		'vc-extender'            => false,   // Deprecated: for backward compatibility
		'woocommerce'            => false,   // WooCommerce functionality
		'bbpress'                => false,   // bbPress functionality
		'product-pages'          => false,   // Products Page
		'product-updater'        => false,   // Products Updater
		'booster'                => false,    // BS Booster
		'fonts-manager'          => false,    // Fonts manager
		'content-injector'       => false,   // Post content injection
		'json-ld'                => false,   // JSON-LD schema generator
		'version-compatibility'  => false,   // Version compatibility manager
		'template-compatibility' => false,   // Files compatibility manager
		'editor-shortcodes'      => false,   // Editor shortcodes
	);


	/**
	 * Inner array of instances
	 *
	 * @var array
	 */
	protected static $instances = array();


	/**
	 * PHP Constructor Function
	 *
	 * @param array $sections default features
	 *
	 * @since  1.0
	 * @access public
	 */
	public function __construct( $sections = array() ) {

		do_action( 'better-framework/before-init' );

		// define features of BF
		$this->sections = bf_merge_args( $sections, $this->sections );
		$this->sections = apply_filters( 'better-framework/sections', $this->sections );

		/**
		 * Booster
		 */
		if ( $this->sections['booster'] === true ) {
			self::factory( 'booster' );
		}

		/**
		 * Fonts Manager
		 */
		if ( $this->sections['fonts-manager'] === true ) {
			self::factory( 'fonts-manager' );
		}
		/**
		 * BF General Functionality For Both Front End and Back End
		 */
		self::factory( 'general' );

		self::factory( 'assets-manager' );


		/**
		 * Content Injector
		 */
		if ( $this->sections['content-injector'] === true ) {
			self::factory( 'content-injector' );
		}

		/**
		 * BF BetterMenu For Improving WP Menu Features
		 */
		if ( $this->sections['better-menu'] === true ) {
			self::factory( 'better-menu' );
		}


		/**
		 * BF Widgets Manager
		 */
		self::factory( 'widgets-manager' );


		/**
		 * BF Shortcodes Manager
		 */
		if ( $this->sections['vc-extender'] === true ||
		     $this->sections['page-builder'] === true
		) {

			self::factory( 'shortcodes-manager' );

			self::factory( 'page-builder-widget-wrapper' );
		}


		/**
		 * Editor Shortcodes
		 */
		if ( $this->sections['editor-shortcodes'] === true ) {
			self::factory( 'editor-shortcodes' );
		}


		/**
		 * BF Custom Generator For Front End
		 */
		if ( $this->sections['custom-css-fe'] ) {
			self::factory( 'custom-css-fe' );
		}

		/**
		 * BF Pages and Posts Front End Custom Generator
		 */
		if ( $this->sections['custom-css-pages'] ) {
			self::factory( 'custom-css-pages' );
		}

		/**
		 * BF Users Front End Custom Generator
		 */
		if ( $this->sections['custom-css-users'] ) {
			self::factory( 'custom-css-users' );
		}


		/**
		 * BF Custom Generator For Back End
		 */
		if ( $this->sections['custom-css-be'] ) {
			self::factory( 'custom-css-be' );
		}


		/**
		 * BF WooCommerce
		 */
		if ( $this->sections['woocommerce'] === true && function_exists( 'is_woocommerce' ) ) {
			self::factory( 'woocommerce' );
		}


		/**
		 * BF bbPress
		 */
		if ( $this->sections['bbpress'] === true && class_exists( 'bbpress' ) ) {
			self::factory( 'bbpress' );
		}


		/**
		 * BF Admin Page
		 */
		if ( $this->sections['admin-page'] === true ) {
			self::factory( 'admin-page', false, true );
		}


		/**
		 * BF Admin Panel Generator
		 */
		if ( $this->sections['admin_panel'] === true ) {
			self::factory( 'admin-panel' );
		}


		/**
		 * Products Page
		 */
		if ( $this->sections['product-pages'] === true ) {
			self::factory( 'product-pages' );
		}


		/**
		 * Products Updater
		 */
		if ( $this->sections['product-updater'] === true ) {
			self::factory( 'product-updater' );
		}

		/**
		 * Json-LD Schema Generator
		 */
		if ( $this->sections['json-ld'] === true ) {
			self::factory( 'json-ld' );
		}

		$hook = is_admin() ? 'admin_enqueue_scripts' : 'wp_enqueue_scripts';
		add_action( $hook, 'Better_Framework::register_assets', 1 );


		/**
		 * Version compatibility manager
		 */
		if ( $this->sections['version-compatibility'] === true ) {
			self::factory( 'version-compatibility' );
		}

		/**
		 * Files compatibility manager
		 */
		if ( $this->sections['template-compatibility'] === true ) {
			self::factory( 'template-compatibility' );
		}

		/**
		 * Disable Loading BF Fully in Front End
		 */
		if ( ! is_admin() && $this->sections['load_in_frontend'] === false ) {
			return;
		}

		/**
		 * BF Admin Menus
		 */
		if ( $this->sections['admin-menus'] === true ) {
			self::factory( 'admin-menus' );
		}

		/**
		 * BF Core Functionality That Used in Back End
		 */
		self::factory( 'admin-notice' );
		self::factory( 'core', false, true );
		self::factory( 'color' );
		self::factory( 'icon-factory' );


		/**
		 * BF Taxonomy Meta Box Generator
		 */
		if ( $this->sections['taxonomy_meta_box'] === true ) {
			self::factory( 'taxonomy-meta' );
		}


		/**
		 * BF Post & Page Meta Box Generator
		 */
		if ( $this->sections['meta_box'] === true ) {
			self::factory( 'meta-box' );
		}


		/**
		 * BF Post & Page Meta Box Generator
		 */
		if ( $this->sections['user-meta-box'] === true ) {
			self::factory( 'user-meta-box' );
		}


		/**
		 * BF Visual Composer Extender
		 */
		if ( $this->sections['vc-extender'] === true ) {
			self::factory( 'vc-extender' );
		}


		// Admin style and scripts
		if ( is_admin() ) {
			// Hook BF admin assets enqueue
			add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ), 100 );
			add_action( 'elementor/editor/before_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ), 100 );
			//			add_action( 'elementor/frontend/before_enqueue_styles', array( $this, 'admin_enqueue_scripts' ), 100 );

			// Hook BF admin ajax requests
			add_action( 'wp_ajax_bf_ajax', array( $this, 'admin_ajax' ) );
			add_action( 'better-framework/panel/image-upload', array( $this, 'handle_file_upload' ) );
		}

	}


	/**
	 * Build the required object instance
	 *
	 * @param string $object
	 * @param bool   $fresh
	 * @param bool   $just_include
	 *
	 * @return null
	 */
	public static function factory( $object = 'options', $fresh = false, $just_include = false ) {

		if ( isset( self::$instances[ $object ] ) && ! $fresh ) {
			return self::$instances[ $object ];
		}

		switch ( $object ) {

			/**
			 * Main BetterFramework Class
			 */
			case 'self':
				$class = 'Better_Framework';
				break;

			/**
			 * General Helper Functions
			 */
			case 'helper':
				include BF_PATH . 'core/class-bf-helper.php';

				$class = 'BF_Helper';
				break;

			/**
			 * Query Helper Functions
			 */
			case 'query-helper':
				include BF_PATH . 'core/class-bf-query.php';

				$class = 'BF_Query';
				break;

			/**
			 * Booster
			 */
			case 'booster':

				if ( ! class_exists( '_WP_Dependency' ) ) {
					/** WordPress Dependency Class */
					require( ABSPATH . WPINC . '/class-wp-dependency.php' );
				}

				if ( ! class_exists( 'WP_Dependencies' ) ) {
					/** WordPress Dependencies Class */
					require( ABSPATH . WPINC . '/class.wp-dependencies.php' );
				}

				include BF_PATH . 'booster/class-bf-minify.php';
				include BF_PATH . 'booster/class-bf-scripts.php';
				include BF_PATH . 'booster/class-bf-styles.php';

				// Initializer
				include BF_PATH . 'booster/class-bf-booster.php';

				include BF_PATH . 'booster/functions.php';

				$class = 'BF_Booster';
				break;


			/**
			 * Custom Fonts Manager
			 */
			case 'fonts-manager':
				include BF_PATH . 'core/fonts-manager/class-bf-fonts-manager.php';

				$class = 'BF_Fonts_Manager';

				break;

			/**
			 * BF General Functionality For Both Front End and Back End
			 */
			case 'general':
				self::factory( 'helper' );

				// todo: this file was deprecated and should be removed in v3
				include BF_PATH . 'core/class-bf-query.php';

				include BF_PATH . 'metabox/functions.php';      // Post meta box public functions
				include BF_PATH . 'taxonomy/functions.php';     // Taxonomy public functions
				include BF_PATH . 'user-metabox/functions.php'; // Taxonomy public functions
				include BF_PATH . 'admin-panel/functions.php';  // Admin Panel public functions
				self::factory( 'options' );

				// todo: this file was deprecated and should delete in v3
				include BF_PATH . 'core/class-bf-posts.php';

				return true;
				break;

			/**
			 * BF_Options Used For Retrieving Theme Panel Options
			 */
			case 'options':
				include BF_PATH . 'admin-panel/class-bf-options.php';

				$class = 'BF_Options';
				break;

			/**
			 * BF BetterMenu For Improving WP Menu Features
			 */
			case 'better-menu':
				include BF_PATH . 'menu/class-bf-menus.php';

				$class = 'BF_Menus';
				break;

			/**
			 * BF Page Builders Extender
			 */
			case 'vc-extender':
			case 'page-builder':

				if ( ! class_exists( 'BF_Admin_Fields' ) ) {
					include BF_PATH . 'core/field-generator/class-bf-admin-fields.php';
				}

				if ( ! class_exists( 'BF_Page_Builder_Extender' ) ) {
					include BF_PATH . 'page-builder/class-bf-page-builder-extender.php';
				}

				$class = 'BF_Page_Builder_Extender';
				break;

			/**
			 * BF Post & Page Meta Box Generator
			 */
			case 'meta-box':
				include BF_PATH . 'metabox/class-bf-metabox-core.php';

				$class = 'BF_Metabox_Core';
				break;

			/**
			 * BF Users Meta Box Generator
			 */
			case 'user-meta-box':
				include BF_PATH . 'user-metabox/class-bf-user-metabox-core.php';

				$class = 'BF_User_Metabox_Core';
				break;

			/**
			 * BF Taxonomy Meta Box Generator
			 */
			case 'taxonomy-meta':
				if ( ! class_exists( 'BF_Admin_Fields' ) ) {
					include BF_PATH . 'core/field-generator/class-bf-admin-fields.php';
				}

				include BF_PATH . 'taxonomy/class-bf-taxonomy-front-end-generator.php';
				include BF_PATH . 'taxonomy/class-bf-taxonomy-meta-field.php';
				include BF_PATH . 'taxonomy/class-bf-taxonomy-core.php';

				$class = 'BF_Taxonomy_Core';
				break;

			/**
			 * BF Admin Panel Generator
			 */
			case 'admin-panel':
				self::factory( 'admin-menus' );
				include BF_PATH . 'admin-panel/class-bf-admin-panel.php';

				$class = 'BF_Admin_Panel';
				break;

			/**
			 * BF Admin Page
			 */
			case 'admin-page':
				self::factory( 'admin-menus' );
				include BF_PATH . 'admin-page/class-bf-admin-page.php';

				$class = 'BF_Admin_Page';
				break;


			/**
			 * BF Admin Menus
			 */
			case 'admin-menus':
				include BF_PATH . 'admin-menus/class-bf-admin-menus.php';

				$class = 'BF_Admin_Menus';
				break;


			/**
			 * BF Shortcodes Manager
			 */
			case 'shortcodes-manager':
				include BF_PATH . 'shortcode/class-bf-shortcodes-manager.php';

				$class = 'BF_Shortcodes_Manager';
				break;

			/**
			 * BF Widgets
			 */
			case 'widgets-manager':

				include BF_PATH . 'widget/class-bf-widget.php';
				include BF_PATH . 'widget/class-bf-widgets-manager.php';

				$class = 'BF_Widgets_Manager';
				break;

			case 'page-builder-widget-wrapper':

				include BF_PATH . 'page-builder/wrappers/class-bf-page-builder-widget-wrapper.php';

				$class = 'BF_Page_Builder_Widget_Wrapper';

				break;

			/**
			 * BF Widgets Field Generator
			 */
			case 'widgets-field-generator':

				if ( ! class_exists( 'BF_Admin_Fields' ) ) {
					include BF_PATH . 'core/field-generator/class-bf-admin-fields.php';
				}

				if ( ! class_exists( 'BF_Widgets_Field_Generator' ) ) {
					include BF_PATH . 'widget/class-bf-widgets-field-generator.php';
				}

				return true;
				break;

			/**
			 * BF Core Functionality That Used in Back End
			 */
			case 'admin-notice':
				include BF_PATH . 'core/class-bf-admin-notices.php';

				$class = 'BF_Admin_Notices';
				break;

			/**
			 * BF Core Functionality That Used in Back End
			 */
			case 'core':

				include BF_PATH . 'core/field-generator/functions.php';

				include BF_PATH . 'core/walkers/class-walker-better-categorydropdown.php';
				include BF_PATH . 'core/field-generator/class-bf-ajax-select-callbacks.php';

				if ( ! class_exists( 'BF_Admin_Fields' ) ) {
					include BF_PATH . 'core/field-generator/class-bf-admin-fields.php';
				}

				include BF_PATH . 'core/class-bf-html-generator.php';

				return true;
				break;

			/**
			 * BF Custom Generator For Front End
			 */
			case 'custom-css':

				if ( ! class_exists( 'BF_Custom_CSS' ) ) {
					include BF_PATH . 'core/custom-css/class-bf-custom-css.php';
				}

				return true;
				break;


			/**
			 * BF Custom Generator For Front End
			 */
			case 'custom-css-fe':
				self::factory( 'custom-css' );
				include BF_PATH . 'core/custom-css/class-bf-front-end-css.php';

				$class = 'BF_Front_End_CSS';
				break;

			/**
			 * BF Custom Generator For Back End
			 */
			case 'custom-css-be':
				self::factory( 'custom-css' );
				include BF_PATH . 'core/custom-css/class-bf-back-end-css.php';

				$class = 'BF_Back_End_CSS';
				break;

			/**
			 * BF Custom Generator Pages and Posts in Front end
			 */
			case 'custom-css-pages':
				self::factory( 'custom-css' );
				include BF_PATH . 'core/custom-css/class-bf-pages-css.php';

				$class = 'BF_Pages_CSS';
				break;

			/**
			 * BF Custom Generator Pages and Posts in Front end
			 */
			case 'custom-css-users':
				self::factory( 'custom-css' );
				include BF_PATH . 'core/custom-css/class-bf-users-css.php';

				$class = 'BF_Users_CSS';
				break;


			/**
			 * BF Color Used For Retrieving User Color Schema and Some Helper Functions For Changing Colors
			 */
			case 'color':
				include BF_PATH . 'libs/class-bf-color.php';

				$class = 'BF_Color';
				break;

			/**
			 * BF Color Used For Retrieving User Color Schema and Some Helper Functions For Changing Colors
			 */
			case 'breadcrumb':
				include BF_PATH . 'libs/class-bf-breadcrumb.php';

				$class = 'BF_Breadcrumb';
				break;

			/**
			 * BF Icon Factory Used For Handling FontIcons Actions
			 */
			case 'icon-factory':
				include BF_PATH . 'libs/icons/class-bf-icons-factory.php';

				$class = 'BF_Icons_Factory';
				break;

			/**
			 * BF WooCommerce
			 */
			case 'woocommerce':
				include BF_PATH . 'woocommerce/abstract-class-bf-woocommerce.php';

				return true;

			/**
			 * BF bbPress
			 */
			case 'bbpress':
				include BF_PATH . 'bbpress/abstract-class-bf-bbpress.php';

				return true;

			/**
			 * Assets Manager
			 */
			case 'assets-manager':
				include BF_PATH . 'core/class-bf-assets-manager.php';

				$class = 'BF_Assets_Manager';
				break;

			/**
			 * Products Manager
			 */
			case 'product-pages':
				include BF_PATH . 'product-pages/init.php';

				return true;

				break;


			/**
			 * Products Updater
			 */
			case 'product-updater':
				include BF_PATH . 'product-updater/init.php';

				return true;

				break;


			/**
			 * editor-shortcodes
			 */
			case 'editor-shortcodes':
				include BF_PATH . 'editor-shortcodes/init.php';

				return true;

				break;

			/**
			 * Content Injector
			 */
			case 'content-injector':
				include BF_PATH . 'content-injector/bf-content-inject.php';

				$class = 'BF_Content_Inject';

				break;

			/**
			 * Json-LD
			 */
			case 'json-ld':
				include BF_PATH . 'json-ld/class-bf-json-ld-generator.php';

				$class = 'BF_Json_LD_Generator';

				break;

			case 'version-compatibility':

				if ( ! class_exists( 'BF_Version_Compatibility' ) ) {
					include BF_PATH . 'compatibility/class-bf-version-compatibility.php';
				}

				$class = 'BF_Version_Compatibility';

				break;

			case 'template-compatibility':

				if ( ! class_exists( 'BF_Template_Compatibility' ) ) {
					include BF_PATH . 'compatibility/class-bf-template-compatibility.php';
				}

				$class = 'BF_Template_Compatibility';

				break;

			case 'htaccess-editor':

				if ( ! class_exists( 'BF_Htaccess_Editor' ) ) {
					include BF_PATH . 'core/utilities/IO/class-bf-htaccess-editor.php';
				}

				$class = 'BF_Htaccess_Editor';

				break;

			default:
				return null;
		}


		// Just prepare/includes files
		if ( $just_include ) {
			return;
		}

		// don't cache fresh objects
		if ( $fresh ) {
			return new $class;
		}


		self::$instances[ $object ] = new $class;

		return self::$instances[ $object ];
	}


	/**
	 * Used for accessing alive instance of Better_Framework
	 *
	 * static
	 *
	 * @since 1.0
	 * @return Better_Framework
	 */
	public static function self() {

		return self::factory( 'self' );
	}


	/**
	 * Used for getting options from BF_Options
	 *
	 * @param bool $fresh
	 *
	 * @return BF_Options
	 */
	public static function options( $fresh = false ) {

		return self::factory( 'options', $fresh );
	}


	/**
	 * Used for accessing shortcodes from BF_Shortcodes_Manager
	 *
	 * @param bool $fresh
	 *
	 * @return BF_Shortcodes_Manager
	 */
	public static function shortcodes( $fresh = false ) {

		return self::factory( 'shortcodes-manager', $fresh );
	}


	/**
	 * Used for accessing taxonomy meta from BF_Taxonomy_Core
	 *
	 * @param bool $fresh
	 *
	 * @return BF_Taxonomy_Core
	 */
	public static function taxonomy_meta( $fresh = false ) {

		return self::factory( 'taxonomy-meta', $fresh );
	}


	/**
	 * Used for accessing post meta from BF_Metabox_Core
	 *
	 * @param bool $fresh
	 *
	 * @return BF_Metabox_Core
	 */
	public static function post_meta( $fresh = false ) {

		return self::factory( 'meta-box', $fresh );
	}


	/**
	 * Used for accessing widget manager from BF_Widgets_Manager
	 *
	 * @param bool $fresh
	 *
	 * @return BF_Widgets_Manager
	 */
	public static function widget_manager( $fresh = false ) {

		return self::factory( 'widgets-manager', $fresh );
	}


	/**
	 * Used for accessing widget manager from BF_Widgets_Manager
	 *
	 * @param bool $fresh
	 *
	 * @return BF_Breadcrumb
	 */
	public static function breadcrumb( $fresh = false ) {

		return self::factory( 'breadcrumb', $fresh );
	}


	/**
	 * Used for accessing BF_Admin_Notices for adding notice to admin panel
	 *
	 * @param bool $fresh
	 *
	 * @return BF_Admin_Notices
	 */
	public static function admin_notices( $fresh = false ) {

		return self::factory( 'admin-notice', $fresh );
	}


	/**
	 * Used for accessing BF_Assets_Manager for enqueue styles and scripts
	 *
	 * @param bool $fresh
	 *
	 * @return BF_Assets_Manager
	 */
	public static function assets_manager( $fresh = false ) {

		return self::factory( 'assets-manager', $fresh );
	}


	/**
	 * Used for accessing BF_Helper
	 *
	 * @param bool $fresh
	 *
	 * @return BF_Helper
	 */
	public static function helper( $fresh = false ) {

		return self::factory( 'helper', $fresh );
	}


	/**
	 * Used for accessing BF_Query
	 *
	 * Deprecated!
	 *
	 * @param bool $fresh
	 *
	 * @return BF_Query
	 */
	public static function helper_query( $fresh = false ) {

		return self::factory( 'query-helper', $fresh );
	}


	/**
	 * Used for accessing BF_Icons_Factory
	 *
	 * @param bool $fresh
	 *
	 * @return BF_Icons_Factory
	 */
	public static function icon_factory( $fresh = false ) {

		return self::factory( 'icon-factory', $fresh );
	}


	/**
	 * Used for accessing BF_Fonts_Manager
	 *
	 * @param bool $fresh
	 *
	 * @return BF_Fonts_Manager
	 */
	public static function fonts_manager( $fresh = false ) {

		return self::factory( 'fonts-manager', $fresh );
	}


	/**
	 * Used for accessing BF_Booster
	 *
	 * @param bool $fresh
	 *
	 * @return \BF_Booster
	 */
	public static function booster( $fresh = false ) {

		return self::factory( 'booster', $fresh );
	}


	/**
	 * Used for accessing BF_User_Metabox_Core
	 *
	 * @param bool $fresh
	 *
	 * @return BF_User_Metabox_Core
	 */
	public static function user_meta( $fresh = false ) {

		return self::factory( 'user-meta-box', $fresh );
	}


	/**
	 * Used for accessing Better_Admin_Panel
	 *
	 * @param bool $fresh
	 *
	 * @return BF_Admin_Panel
	 */
	public static function admin_panel( $fresh = false ) {

		return self::factory( 'admin-panel' );
	}


	/**
	 * Used for accessing Better_Admin_Page
	 *
	 * @param bool $fresh
	 *
	 * @return BF_Admin_Page
	 */
	public static function admin_page( $fresh = false ) {

		return self::factory( 'admin-page' );
	}


	/**
	 * Used for accessing BF_Admin_Menus
	 *
	 * @param bool $fresh
	 *
	 * @return BF_Admin_Menus
	 */
	public static function admin_menus( $fresh = false ) {

		return self::factory( 'admin-menus' );
	}


	/**
	 * Gets a WP_Theme object for a theme.
	 *
	 * @param bool $parent
	 * @param bool $fresh
	 * @param bool $cache_this
	 *
	 * @return  WP_Theme
	 */
	public static function theme( $parent = true, $fresh = false, $cache_this = true ) {

		if ( isset( self::$instances['theme'] ) && ! $fresh ) {
			return self::$instances['theme'];
		}

		$theme = wp_get_theme();

		if ( $parent && ( '' != $theme->get( 'Template' ) ) ) {
			$theme = wp_get_theme( $theme->get( 'Template' ) );
		}

		if ( $cache_this === true ) {
			return self::$instances['theme'] = $theme;
		} else {
			return $theme;
		}

	}


	/**
	 * Reference To HTML Generator Class
	 *
	 * static
	 *
	 * @since 1.0
	 * @return BF_HTML_Generator
	 */
	public static function html() {

		return new BF_HTML_Generator;
	}


	/**
	 * Callback: Handle BF Admin Enqueue's
	 *
	 * Action: admin_enqueue_scripts
	 *
	 * @since   1.0
	 *
	 * @return  object
	 */
	public function admin_enqueue_scripts() {

		if ( stristr( current_filter(), 'elementor' ) ) {

			self::register_assets();
		}

		/*
		 * enqueue admin-scripts in all pages
		 *
		// enqueue scripts if features enabled
		if( $this->sections['admin_panel'] == true  ||
			$this->sections['meta_box'] == true     ||
			$this->sections['better-menu'] == true  ||
			$this->sections['taxonomy_meta_box'] == true
		){
			if( $this->get_current_page_type() != '' ){*/

		// Wordpress 3.5
		if ( function_exists( 'wp_enqueue_media' ) ) {
			wp_enqueue_media();
		}

		// BetterFramework Admin scripts
		wp_enqueue_script( 'better-framework-admin' );

		if ( ( $type = $this->get_current_page_type() ) == '' ) {
			$type = '0';
		}

		$better_framework_loc = array(
			'bf_ajax_url' => admin_url( 'admin-ajax.php' ),
			'nonce'       => wp_create_nonce( 'bf_nonce' ),
			'type'        => $type,
			'lang'        => bf_get_current_lang(),

			// Localized Texts
			'translation' => array(
				'reset_panel'  => array(
					'header'     => __( 'Reset options', 'better-studio' ),
					'title'      => __( 'Are you sure to reset options?', 'better-studio' ),
					'body'       => __( 'With resetting panel all your changes will be lost and will be replaced with default settings.', 'better-studio' ),
					'button_yes' => __( 'Yes, Reset options', 'better-studio' ),
					'button_no'  => __( 'No', 'better-studio' ),
					'resetting'  => __( 'Resetting options', 'better-studio' ),
				),
				'import_panel' => array(
					'prompt' => __( 'Do you really wish to override your current settings?', 'better-studio' ),
				),
				'icon_modal'   => array(
					'custom_icon' => __( 'Custom icon', 'better-studio' ),
				),
				'show_all'     => __( '… See all', 'better-studio' ),
				'widgets'      => array(
					'save' => __( 'Save', 'better-studio' ),
				)
			),

			'loading'     => '<div class="bf-loading-wrapper"><div class="bf-loading-anim"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div></div>',
			'term_select' => array(
				'make_primary' => __( 'Make Primary', 'better-studio' ),
				'excluded'     => __( 'Excluded', 'better-studio' ),
			),

			'on_error' => array(
				'button_ok'       => __( 'Ok', 'better-studio' ),
				'default_message' => __( 'Cannot complete ajax request.', 'better-studio' ),
				'body'            => __( 'please try again several minutes later or contact better studio team support.', 'better-studio' ),
				'header'          => __( 'ajax request failed', 'better-studio' ),
				'title'           => __( 'an error occurred', 'better-studio' ),
				'display_error'   => __( '<div class="bs-pages-error-section">
					<a href="#" class="btn bs-pages-error-copy" data-copied="' . esc_attr__( 'Copied !', 'better-studio' ) . '">
						<i class="fa fa-files-o" aria-hidden="true"></i> Copy</a>  <textarea> Error:  %ERROR_CODE% %ERROR_MSG% </textarea>
				</div>', 'better-studio' ),

				'again' => __( 'Error: please try again', 'better-studio' ),
			),

			'fields' => array(
				'select_popup' => array(
					'header'           => '%%name%%',
					'search'           => __( 'Search...', 'better-studio' ),
					'btn_label'        => __( 'Choose', 'better-studio' ),
					'btn_label_active' => __( 'Current', 'better-studio' ),

					'filter_cat_title' => __( 'Category', 'better-studio' ),
					'categories'       => array(),


					'filter_type_title' => __( 'Type', 'better-studio' ),
					'all_l10n'          => __( 'All', 'better-studio' ),

					'types' => array(),
				),

				'select_popup_confirm' => array(
					'header'        => __( 'Do you want to change %%name%%?', 'better-studio' ),
					'button_ok'     => __( 'Yes, Change', 'better-studio' ),
					'button_cancel' => __( 'Cancel', 'better-studio' ),

					'caption' => '%s',
				),
			)
		);

		if ( $this->sections['page-builder'] || $this->sections['vc-extender'] ) {

			$better_framework_loc['page_builder'] = BF_Page_Builder_Extender::active_page_builders();

			if ( $this->get_current_page_type() === 'widgets' &&
			     'Elementor' === $better_framework_loc['page_builder']
			) {

				$better_framework_loc['shortcodes_id'] = array_keys( BF_Shortcodes_Manager::$shortcodes );
			}
		} else {
			$better_framework_loc['page_builder'] = array();
		}

		wp_localize_script( 'better-framework-admin', 'better_framework_loc', apply_filters( 'better-framework/localized-items', $better_framework_loc ) );

		// BetterFramework admin style
		wp_enqueue_style( 'better-framework-admin' );

		if ( is_rtl() ) {
			wp_enqueue_style( 'better-framework-admin-rtl' );
		}

		if ( $this->get_current_page_type() == 'metabox' ) {
			bf_enqueue_modal( 'icon' ); // safe enqueue for fixing visual composer bug
		}

		bf_enqueue_style( 'better-studio-admin-icon' );
		bf_enqueue_style( 'fontawesome' );
	}


	/**
	 * Used for finding current page type
	 *
	 * @return string
	 */
	public function get_current_page_type() {

		global $pagenow;

		$type = '';

		switch ( $pagenow ) {

			case 'post-new.php':
			case 'post.php':

				if ( isset( $_GET['action'] ) && $_GET['action'] === 'elementor' ) {

					$type = 'widgets';

				} else {

					$type = 'metabox';
				}

				break;

			case 'term.php':
			case 'edit-tags.php':
				$type = 'taxonomy';
				break;

			case 'widgets.php':
				$type = 'widgets';
				break;

			case 'nav-menus.php':
				$type = 'menus';
				break;

			case 'profile.php':
			case 'user-new.php':
			case 'user-edit.php':
				$type = 'users';
				break;

			case 'index.php':
				$type = 'dashboard';
				break;

			default:
				if ( isset( $_GET['page'] ) && ( preg_match( '/^better-studio-/', $_GET['page'] ) || preg_match( '/^better-studio\//', $_GET['page'] ) ) ) {
					$type = 'panel';
				}

		}

		return $type;
	}


	/**
	 * Handle Ajax File Uploads
	 *
	 * @param string $data The variable that includes all options in array
	 *
	 * @since 1.0
	 * @return void
	 */
	public function handle_file_upload( $data ) {

		if ( ! function_exists( 'wp_handle_upload' ) ) {
			require_once ABSPATH . 'wp-admin/includes/file.php';
		}

		$movefile = wp_handle_upload(
			$data,
			array(
				'test_form' => false
			)
		);

		if ( array_key_exists( 'error', $movefile ) ) {
			$upResults = array(
				'status' => 'error',
				'msg'    => $movefile['error']
			);
		} else {
			$upResults = array(
				'status' => 'succeed',
				'url'    => $movefile['url'],
				'path'   => $movefile['file']
			);
		}

		echo json_encode( $upResults );
		die;

	}


	public static function callback_token( $callback ) {

		return wp_create_nonce( sprintf( 'bf-custom-callback:%s', $callback ) );
	}


	/**
	 * Handle All Ajax Requests in Back-End
	 *
	 * @since 1.0
	 * @return mixed
	 */
	public function admin_ajax() {

		// Check Nonce
		if ( ! isset( $_REQUEST['nonce'] ) || ! isset( $_REQUEST['reqID'] ) ) {
			die(
			json_encode(
				array(
					'status' => 'error',
					'msg'    => __( 'Security Error!', 'better-studio' )
				)
			)
			);
		}

		$_nonce = wp_verify_nonce( $_REQUEST['nonce'], 'bf_nonce' );

		// Check Nonce
		if ( $_nonce === false ) {
			die(
			json_encode(
				array(
					'status' => 'error',
					'msg'    => __( 'Security Error!', 'better-studio' )
				)
			)
			);
		}

		try {

			switch ( $_REQUEST['reqID'] ) {

				// Option Panel, Save Settings
				case( 'save_admin_panel_options' ):

					$options = bf_parse_str( ltrim( rtrim( stripslashes( $_REQUEST['data'] ), '&' ), '&' ) );

					$data = array(
						'id'   => $_REQUEST['panelID'],
						'lang' => $_REQUEST['lang'],
						'data' => $options
					);

					do_action( 'better-framework/panel/save', $data );
					break;

				// Ajax Image Uploader
				case( 'image_upload' ):
					$data = $_FILES[ $_REQUEST['file_id'] ];
					do_action( 'better-framework/panel/image-upload', $data, $_REQUEST['file_id'] );
					break;

				// Add Custom Icon
				case( 'add_custom_icon' ):
					do_action( 'better-framework/icons/add-custom-icon', $_REQUEST['icon'] );
					break;

				// Remove Custom Icon
				case( 'remove_custom_icon' ):
					do_action( 'better-framework/icons/remove-custom-icon', $_REQUEST['icon'] );
					break;

				// Option Panel, Reset Settings
				case( 'reset_options_panel' ):

					/**
					 * Fires for handling panel reset
					 *
					 * @since 1.0.0
					 *
					 * @param string $args reset panel data
					 */
					do_action( 'better-framework/panel/reset', array(
						'id'      => $_REQUEST['panelID'],
						'lang'    => $_REQUEST['lang'],
						'options' => $_REQUEST['to_reset']
					) );
					break;

				// Option Panel, Ajax Action
				case( 'ajax_action' ):

					$callback = isset( $_REQUEST['callback'] ) ? $_REQUEST['callback'] : '';

					$args = isset( $_REQUEST['args'] ) ? $_REQUEST['args'] : '';

					$error_message = isset( $_REQUEST['error-message'] ) ? $_REQUEST['error-message'] : __( 'An error occurred while doing action.', 'better-studio' );

					//Security issue fix
					if ( empty( $_REQUEST['bf_call_token'] ) || self::callback_token( $callback ) !== $_REQUEST['bf_call_token'] ) {

						echo json_encode(
							array(
								'status' => 'error',
								'msg'    => __( 'the security token is not valid!', 'better-studio' )
							)
						);

						return;
					}
					if ( ! empty( $callback ) && is_callable( $callback ) ) {

						if ( is_array( $args ) ) {

							$to_return = call_user_func_array( $callback, $args );

						} else {

							$to_return = call_user_func( $callback, $args );

						}

						if ( is_array( $to_return ) ) {
							echo json_encode( $to_return );
						} else {
							echo json_encode(
								array(
									'status' => 'error',
									'msg'    => $error_message
								)
							);
						}

					} else {
						echo json_encode(
							array(
								'status' => 'error',
								'msg'    => $error_message
							)
						);
					}
					break;

				// Option Panel, Ajax Field
				case( 'ajax_field' ):

					if ( isset( $_REQUEST['callback'] ) && is_callable( $_REQUEST['callback'] ) ) {

						$cb = $_REQUEST['callback'];

						$cb_args = array(
							! empty( $_REQUEST['key'] ) ? $_REQUEST['key'] : '',
							! empty( $_REQUEST['exclude'] ) ? $_REQUEST['exclude'] : ''
						);

						$to_return = call_user_func_array( $cb, $cb_args );

						if ( is_array( $to_return ) ) {
							echo count( $to_return ) === 0 ? - 1 : json_encode( $to_return );
						}
					}

					break;

				// Option Panel, Import Settings
				case( 'import' ):

					$data = $_FILES['bf-import-file-input'];

					/**
					 * Fires for handling panel import
					 *
					 * @since 1.1.0
					 *
					 * @param string $data contain import file data
					 * @param string $args contain import arguments
					 */
					do_action( 'better-framework/panel/import', $data, $_REQUEST );

					break;

				case 'fetch-deferred-field':

					if (
						! empty( $_REQUEST['sectionID'] ) &&
						! empty( $_REQUEST['panelID'] ) &&
						is_string( $_REQUEST['sectionID'] )
					) {  // panel field

						do_action( 'better-framework/panel/ajax-panel-field', $_REQUEST['panelID'], $_REQUEST['sectionID'] );
					} elseif ( ! empty( $_REQUEST['sectionID'] ) &&
					           ! empty( $_REQUEST['metabox'] ) &&
					           ! empty( $_REQUEST['metabox_id'] ) &&
					           is_string( $_REQUEST['sectionID'] )
					) { // metabox field

						$type      = isset( $_REQUEST['type'] ) ? $_REQUEST['type'] : '';
						$object_id = isset( $_REQUEST['object_id'] ) ? $_REQUEST['object_id'] : '';


						if ( $type === 'taxonomy' ) {

							$hook = 'better-framework/taxonomy/metabox/ajax-tab';

						} elseif ( $type === 'users' ) {

							$hook = 'better-framework/user-metabox/ajax-tab';

						} else {

							$hook = 'better-framework/metabox/ajax-tab';
						}

						do_action( $hook, $_REQUEST['sectionID'], $_REQUEST['metabox_id'], $object_id );
					}

					break;

				case 'fetch-mce-view-fields':

					if ( ! empty( $_REQUEST['shortcode'] ) ) {

						do_action( 'better-framework/shortcodes/tinymce-fields', wp_unslash( $_REQUEST['shortcode'] ), $_REQUEST );
					}

					break;

				case 'fetch-mce-view-shortcode':

					if ( ! empty( $_REQUEST['shortcodes'] ) ) {
						do_action( 'better-framework/shortcodes/tinymce-view-shortcode', wp_unslash( $_REQUEST['shortcodes'] ), $_REQUEST );
					}

					break;

				case 'term_select_items':


					if ( ! empty( $_REQUEST['data'] ) ) {

						do_action( 'better-framework/fields/term-select-items', $_REQUEST['data'] );
					}

					break;

			}
		} catch( Exception $e ) {

			$result = array(
				'error_message' => $e->getMessage(),
				'error_code'    => $e->getCode(),
				'is_error'      => true,
			);

			echo json_encode( compact( 'result' ) );
		}

		die;
	}


	public static function register_assets() {

		self::register_scripts();
		self::register_styles();
	}


	public static function register_scripts() {

		$version = Better_Framework::self()->version;
		$prefix  = ! bf_is( 'dev' ) ? '.min' : '';

		// Element Query
		bf_register_script( 'element-query', BF_URI . 'assets/js/element-query.min.js', array( 'jquery' ), BF_PATH . 'assets/js/element-query.min.js', $version );

		// PrettyPhoto
		bf_register_script( 'pretty-photo', BF_URI . 'assets/js/pretty-photo' . $prefix . '.js', array( 'jquery' ), BF_PATH . 'assets/js/pretty-photo' . $prefix . '.js', $version );

		//
		// Admin Scripts
		//

		bf_register_script( 'bf-admin-plugins', BF_URI . 'assets/js/admin-plugins.js', array(
			'wp-color-picker',
			'jquery'
		), BF_PATH . 'assets/js/admin-plugins.js', $version );

		// BF Used Plugins JS File
		bf_register_script( 'bf-better-modals', BF_URI . 'assets/js/better-modals.js', array( 'jquery' ), BF_PATH . 'assets/js/better-modals.js', $version );

		// BS-Modal
		bf_register_script( 'mustache', BF_URI . 'assets/js/mustache' . $prefix . '.js', array( 'jquery' ), BF_PATH . 'assets/js/mustache' . $prefix . '.js', $version );
		bf_register_script( 'bf-modal', BF_URI . 'assets/js/bs-modal' . $prefix . '.js', array(
			'mustache',
			'jquery'
		), BF_PATH . 'assets/js/bs-modal' . $prefix . '.js', $version );

		// Ace Code Editor
		if ( is_admin() ) {
			add_action( 'admin_footer', 'BF_Assets_Manager::print_ace_editor_oldie_js' );
		} elseif ( is_user_logged_in() ) {
			add_action( 'wp_footer', 'BF_Assets_Manager::print_ace_editor_oldie_js' );
		}

		// Better Fonts Manager
		bf_register_script( 'selector-modal', BF_URI . 'assets/js/selector-modal' . $prefix . '.js', array( 'jquery' ), BF_PATH . 'assets/js/selector-modal' . $prefix . '.js', $version );
		bf_register_script( 'better-fonts-manager', BF_URI . 'assets/js/better-fonts-manager.js', array( 'selector-modal' ), BF_PATH . 'assets/js/better-fonts-manager.js', Better_Framework::self()->version );

		// TinyMCE Shortcode View
		bf_register_script( 'tinymce-addon', BF_URI . 'assets/js/tinymce-addon' . $prefix . '.js', array( 'jquery' ), BF_PATH . 'assets/js/tinymce-addon' . $prefix . '.js', $version );

		bf_register_script( 'bf-gutenberg-fields', BF_URI . 'gutenberg/dev/dist/blocks.build.js', array(
			'wp-blocks',
			'wp-i18n',
			'wp-element'
		), BF_PATH . 'gutenberg/dev/dist/blocks.build.js', $version );

		bf_register_script( 'bf-gutenberg', BF_URI . 'assets/js/gutenberg' . $prefix . '.js', array(
			'bf-gutenberg-fields',
		), BF_PATH . 'assets/js/gutenberg' . $prefix . '.js', $version );


		// BetterFramework admin script
		bf_register_script( 'better-framework-admin', BF_URI . 'assets/js/admin-scripts.js', array(
			'bf-better-modals',
			'selector-modal',
			'bf-modal',
			'jquery',
			'jquery-ui-core',
			'jquery-ui-widget',
			'jquery-ui-slider',
			'jquery-ui-sortable',
			'bf-admin-plugins',
			'ace-editor-script',

		),
			BF_PATH . 'assets/js/admin-scripts.js',
			$version
		);


		bf_call_func( 'wp' . '_' . 'deregister' . '_' . 'script', 'ace-editor' ); // remove ‌VC troubled script
		wp_register_script(
			'ace-editor-script',
			'https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.8/ace.js',
			array(),
			$version,
			true
		);

		// Slick carousel
		bf_register_script( 'bf-slick', BF_URI . 'assets/js/slick' . $prefix . '.js', array( 'jquery' ), BF_PATH . 'assets/js/slick' . $prefix . '.js', $version );

	}


	public static function register_styles() {

		$prefix = ! bf_is( 'dev' ) ? '.min' : '';

		$version = Better_Framework::self()->version;

		// FontAwesome
		wp_deregister_style( 'fontawesome' );
		wp_deregister_style( 'font-awesome' );
		bf_register_style( 'fontawesome', BF_URI . 'assets/css/font-awesome.min.css', array(), BF_PATH . 'assets/css/font-awesome.min.css', $version );

		// BetterStudio Font Icon
		bf_register_style( 'bs-icons', BF_URI . 'assets/css/bs-icons.css', array(), BF_PATH . 'assets/css/bs-icons.css', $version );

		// Better Studio Admin Icon
		bf_register_style( 'better-studio-admin-icon', BF_URI . 'assets/css/better-studio-admin-icon.css', array(), BF_PATH . 'assets/css/better-studio-admin-icon.css', $version );

		// Pretty Photo
		bf_register_style( 'pretty-photo', BF_URI . 'assets/css/pretty-photo' . $prefix . '.css', array(), BF_PATH . 'assets/css/pretty-photo' . $prefix . '.css', $version );

		// 
		// Admin Styles
		//

		/**
		 * Enqueue Color Picker Dependencies
		 *
		 * uncompressed version also available in assets/js/color-picker.js
		 */
		bf_register_style( 'wp-color-picker' );

		// Modal
		bf_register_style( 'better-modals', BF_URI . 'assets/css/better-modals.css', array(), BF_PATH . 'assets/css/better-modals.css', $version );


		// BF Used Plugins CSS
		bf_register_style( 'bf-admin-pages', BF_URI . 'assets/css/admin-pages.css', array(), BF_PATH . 'assets/css/admin-pages.css', $version );

		// BF Used Plugins CSS
		bf_register_style( 'bf-admin-plugins', BF_URI . 'assets/css/admin-plugins.css', array(), BF_PATH . 'assets/css/admin-plugins.css', $version );

		// CodeMirror (syntax highlighter code editor) CSS
		bf_register_style( 'bf-codemirror-packs', BF_URI . 'assets/css/codemirror-pack.css', array(), BF_PATH . 'assets/css/codemirror-pack.css', $version );

		// BS-Modal
		bf_register_style( 'bf-modal', BF_URI . 'assets/css/bs-modal.css', array(), BF_PATH . 'assets/css/bs-modal.css', $version );


		// BetterFramework admin style
		bf_register_style( 'better-framework-admin', BF_URI . 'assets/css/admin-style.css', array(
			'better-modals',
			'bf-modal',
			'bs-icons',
			'better-studio-admin-icon',
			'bf-admin-plugins',
			'bf-codemirror-packs',
			'wp-color-picker',
		),
			BF_PATH . 'assets/css/admin-style.css',
			$version
		);

		if ( is_rtl() ) {
			bf_register_style(
				'better-framework-admin-rtl',
				BF_URI . 'assets/css/rtl-admin-style.css',
				array(
					'better-framework-admin',
				),
				BF_PATH . 'assets/css/rtl-admin-style.css',
				$version
			);
		}

		// Slick carousel
		bf_register_style( 'bf-slick', BF_URI . 'assets/css/slick' . $prefix . '.css', array(), BF_PATH . 'assets/css/slick' . $prefix . '.css', $version );

	}


	public static function get_core_cache( $key, $default = null ) {

		$options = get_option( 'bf-core-cache' );

		if ( isset( $options[ $key ] ) ) {
			return $options[ $key ];
		}

		return $default;
	}


	/**
	 * @param string $key
	 * @param mixed  $value
	 *
	 * @return bool False if value was not updated and true if value was updated.
	 */
	public static function set_core_cache( $key, $value ) {

		$options = get_option( 'bf-core-cache', array() );

		$options[ $key ] = $value;

		return update_option( 'bf-core-cache', $options );
	}
}
libs/better-framework/init.php000064400000004347151214002530012432 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! class_exists( 'Better_Framework_Factory' ) ) {

	class Better_Framework_Factory {

		static $frameworks = array();

		static $active_framework;


		public static function setup_framework() {

			self::$frameworks = apply_filters( 'better-framework/loader', array() );

			$count = is_array( self::$frameworks ) ? count( self::$frameworks ) : 0;

			if ( ! $count ) {
				return false;
			}

			if ( $count == 1 ) {
				self::load_framework( current( self::$frameworks ) );
			} else {

				$latest_version = null;

				foreach ( self::$frameworks as $framework ) {

					if ( $latest_version == null ) {
						$latest_version = $framework;
						continue;
					}

					if ( version_compare( $latest_version['version'], $framework['version'] ) <= 0 ) {
						$latest_version = $framework;
					}
				}

				self::$active_framework = $latest_version;

				self::load_framework( $latest_version );

			}

			/**
			 * Fires after BetterFramework fully loaded.
			 */
			do_action( 'better-framework/after_setup' );
		}


		/**
		 * Loads framework
		 *
		 * @param $framework
		 */
		public static function load_framework( $framework ) {

			define( 'BF_URI', trailingslashit( $framework['uri'] ) );
			define( 'BF_PATH', trailingslashit( $framework['path'] ) );

			include_once $framework['path'] . 'class-better-framework.php';

		}

	}


	add_action( 'after_setup_theme', array( 'Better_Framework_Factory', 'setup_framework' ) );
}
libs/better-framework/booster/class-bf-styles.php000064400000015326151214002530016156 0ustar00<?php


/**
 * Merge and compress static js/css files.
 *
 * @since 2.9.0
 */
class BF_Styles extends BF_Minify {

	public $printed = array();

	/**
	 * Set current css file
	 *
	 * @see sanitize
	 *
	 * @var string
	 */
	public $_current_file_url;

	/**
	 * Store extra css content
	 *
	 * @see add_css_file
	 *
	 * @var array
	 */
	public $extra_css = array();


	/**
	 * Initialize
	 *
	 * @since 2.9.0
	 */
	public function init() {

		if ( is_admin() ) {

			add_action( 'admin_head', 'BF_Styles::print_head_styles' );
			add_action( 'admin_footer', 'BF_Styles::print_footer_styles' );
		} else {

			add_action( 'wp_head', 'BF_Styles::print_head_styles' );
			add_action( 'wp_footer', 'BF_Styles::print_footer_styles' );
		}
	}


	/**
	 * Print style tags
	 *
	 * @since 2.9.0
	 */
	public function print_output() {

		$handles = $this->do_items( false, 'all' );
		$this->_print_styles( $handles );

		$this->printed = $handles;
	}


	/**
	 *
	 */
	public function print_all_extra_css() {

		if ( ! $this->extra_css ) {
			return;
		}

		foreach ( $this->extra_css as $id => $_ ) {

			if ( $css = $this->get_extra_css( $id ) ) {

				if ( $css['type'] === 'file' ) {
					self::print_style( $css['data'], $id );
				} elseif ( $css['type'] === 'inline' ) {
					self::print_inline_css( $css['data'] );
				}
			}
		}
	}


	/**
	 * @param string $id
	 *
	 * @return array
	 */
	public function get_extra_css( $id ) {

		static $cache_dir, $cache_url;

		if ( ! $cache_dir ) {
			$cache_dir = trailingslashit( WP_CONTENT_DIR . '/' . self::$cache_dir );
			$cache_url = trailingslashit( content_url( self::$cache_dir ) );
		}

		if ( ! isset( $this->extra_css[ $id ] ) ) {
			return array();
		}

		$filename = $this->string_hash( $id ) . '.css';

		if ( is_readable( $cache_dir . $filename ) ) {

			return array(
				'type' => 'file',
				'data' => $cache_url . $filename,
			);
		} else {

			$content = call_user_func( $this->extra_css[ $id ], $id );

			if ( $this->is_dir_writable( $cache_dir ) ) {

				$this->_current_file_url = site_url( add_query_arg( false, false ) );

				$content = $this->sanitize_content( $content );
				$content = $this->minify( $content );
			}

			if ( self::write_file( $cache_dir . $filename, $content ) ) {

				return array(
					'type' => 'file',
					'data' => $cache_url . $filename,
				);
			}

			return array(
				'type' => 'inline',
				'data' => $content,
			);
		}
	}


	/**
	 * Print style tags
	 *
	 * @since 2.9.0
	 */
	public function print_output2() {

		$this->done = array();

		$handles = $this->do_items( array_diff( $this->queue, $this->printed ) );

		$this->_print_styles( $handles );
	}


	/**
	 * Compress css content
	 *
	 * @param string $css
	 * @param array  $handle
	 *
	 * @return string
	 * @since 2.9.0
	 */
	public function sanitize( $css, $handle ) {

		$this->_current_file_url = dirname( $this->registered[ $handle ]->src );


		return $this->sanitize_content( $css );
	}


	public function sanitize_content( $css ) {

		return preg_replace_callback( "'url \s* \( \s*  ([\"\'])? (?(1) (.*?)\\1 | ([^\s\)]+))  \s* \)'isx", array(
			$this,
			'sanitize_url'
		), $css );

	}


	/**
	 * @param array $match
	 *
	 * @access private
	 *
	 * @return string
	 */
	public function sanitize_url( $match ) {

		$path = empty( $match[3] ) ? $match[2] : $match[3];

		// is data URI ?
		if ( substr( $path, 0, 5 ) == 'data:' ) {
			return 'url("' . $path . '")';
		}

		if ( filter_var( $path, FILTER_VALIDATE_URL ) ) {
			return 'url("' . $path . '")';
		}

		if ( $path[0] === '/' ) {

			$parsed_url = parse_url( $this->_current_file_url );
			$url        = $parsed_url['scheme'] . '://' . $parsed_url['host'] . $path;

		} else {

			$url = bf_esc_file_path( trailingslashit( $this->_current_file_url ) . ltrim( $path, '/' ) );
		}

		return 'url("' . $url . '")';
	}


	/**
	 * Print style tags
	 *
	 * @param array $handles
	 *
	 * @since 2.9.0
	 */
	public function _print_styles( $handles ) {

		if ( ! $handles ) {
			return;
		}

		if ( bf_count( $handles ) === 1 ) {
			self::print_style( $this->registered[ $handles[0] ]->src );

			return;
		}

		$file_dir  = trailingslashit( WP_CONTENT_DIR . '/' . self::$cache_dir );
		$file_name = $this->handles_hash( $handles ) . '.css';

		if ( is_readable( $file_dir . $file_name ) || $this->do_minify( $handles, $file_dir . $file_name ) ) {
			self::print_style( content_url( self::$cache_dir . '/' . $file_name ) );
		} else {

			foreach ( $handles as $handle ) {
				self::print_style( $this->registered[ $handle ]->src, $handle );
			}
		}
	}


	/**
	 * Print stylesheet tag
	 *
	 * @param string $url
	 * @param string $handle
	 *
	 * @since 2.9.0
	 */
	public static function print_style( $url, $handle = '' ) {

		if ( ! $handle ) {
			static $i = 0;

			$handle = 'bf-minifed-css-' . ++ $i;
		}

		echo '<link rel=\'stylesheet\' id=\'', $handle, '\' href=\'', $url, '\' type=\'text/css\' media=\'all\' />';
		echo "\n";
	}


	/**
	 * Print inline stylesheet
	 *
	 * @param string $css
	 * @param string $media
	 */
	public static function print_inline_css( $css, $media = 'screen' ) {

		echo '<style type=\'text/css\' media=\'' . $media . '\'>';
		echo $css;
		echo '</style>';
	}


	/**
	 * Print header stylesheet tags
	 */
	public static function print_head_styles() {

		bf_styles()->print_output();

		bf_styles()->print_all_extra_css();
	}


	/**
	 * Print footer stylesheet tags
	 */
	public static function print_footer_styles() {

		bf_styles()->print_output2();
	}


	/**
	 * Callback to compress files content
	 *
	 * @param string $content
	 *
	 * @since 2.9.0
	 * @return string|bool
	 */
	public function minify( $content ) {

		if ( ! bf_booster_is_active( 'minify-css' ) ) {
			return $content;
		}

		$content = str_replace( ' 0px', '0', $content );
		$content = preg_replace( '#\s+#', ' ', $content );
		$content = preg_replace( '#/\*.*?\*/#s', '', $content );
		$content = str_replace( '; ', ';', $content );
		$content = str_replace( ': ', ':', $content );
		$content = str_replace( ' {', '{', $content );
		$content = str_replace( '{ ', '{', $content );
		$content = str_replace( ', ', ',', $content );
		$content = str_replace( '} ', '}', $content );
		$content = str_replace( ';}', '}', $content );
		$content = str_replace( array( "\r", "\n", "\t" ), '', $content );
		$content = str_replace( ' ~ ', '~', $content );
		$content = str_replace( ' > ', '>', $content );
		$content = str_replace( ' + ', '+', $content );
		$content = str_replace( '@media (', '@media(', $content );
		$content = str_replace( ') and (', ')and(', $content );

		return trim( $content );
	}


	/**
	 * Append inline css content into a file
	 *
	 * @param string   $unique_id unique name
	 * @param callable $content_cb
	 */
	public function add_css_file( $unique_id, $content_cb ) {

		$this->extra_css[ $unique_id ] = $content_cb;
	}
}
libs/better-framework/booster/panel-config.php000064400000005541151214002530015503 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// Language  name for smart admin texts
$lang = bf_get_current_lang_raw();
if ( $lang != 'none' ) {
	$lang = bf_get_language_name( $lang );
} else {
	$lang = '';
}


$panels = array(
	'panel-name' => _x( 'BS Speed Booster', 'Panel title', 'better-studio' ),
	'panel-desc' => '<p>' . __( 'Speeds up your site with highly compatibility with cache plugins!', 'better-studio' ) . '</p>',
	'config'     => array(
		'name'                => __( 'BS Speed Booster', 'better-studio' ),
		'parent'              => 'better-studio',
		'slug'                => 'better-studio/booster',
		'page_title'          => __( 'BS Speed Booster', 'better-studio' ),
		'menu_title'          => __( 'Booster', 'better-studio' ),
		'capability'          => 'manage_options',
		'menu_slug'           => __( 'BS Speed Booster', 'better-studio' ),
		'notice-icon'         => BF_URI . 'assets/img/bs-notice-logo.png',
		'icon_url'            => null,
		'position'            => 100.00,
		'exclude_from_export' => false,
		'register_menu'       => apply_filters( 'better-framework/booster/show-menu', true ),
	),
	'texts'      => array(
		'panel-desc-lang'     => '<p>' . __( '%s Language Booster.', 'better-studio' ) . '</p>',
		'panel-desc-lang-all' => '<p>' . __( 'All Languages Booster.', 'better-studio' ) . '</p>',
		'reset-button'        => ! empty( $lang ) ? sprintf( __( 'Reset %s Booster', 'better-studio' ), $lang ) : __( 'Reset Booster', 'better-studio' ),
		'reset-button-all'    => __( 'Reset All Languages Booster', 'better-studio' ),
		'reset-confirm'       => ! empty( $lang ) ? sprintf( __( 'Are you sure to reset %s Booster?', 'better-studio' ), $lang ) : __( 'Are you sure to reset Booster?', 'better-studio' ),
		'reset-confirm-all'   => __( 'Are you sure to reset all languages Booster?', 'better-studio' ),
		'save-button'         => ! empty( $lang ) ? sprintf( __( 'Save %s Booster', 'better-studio' ), $lang ) : __( 'Save Booster', 'better-studio' ),
		'save-button-all'     => __( 'Save All Booster', 'better-studio' ),
		'save-confirm-all'    => __( 'Are you sure to save all Booster? this will override specified Booster\'s per languages', 'better-studio' )
	),
);
libs/better-framework/booster/panel-std.php000064400000001666151214002530015034 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

$fields['minify'] = array(
	'std' => 1,
);

$fields['cache-mega-menu'] = array(
	'std' => 1,
);

$fields['cache-widgets'] = array(
	'std' => 1,
);

$fields['cache-shortcodes'] = array(
	'std' => 1,
);
libs/better-framework/booster/class-bf-booster.php000064400000027030151214002530016303 0ustar00<?php


/**
 * BetterStudio Speed Booster
 *
 *
 * @package  BetterFramework
 * @author   BetterStudio <info@betterstudio.com>
 * @access   public
 * @see      http://www.betterstudio.com
 */
class BF_Booster {


	/**
	 * Panel ID
	 *
	 * @var string
	 */
	public static $option_panel_id = 'bs-booster';


	/**
	 * Inner array of object instances and caches
	 *
	 * @var array
	 */
	protected static $instances = array();


	/**
	 *
	 */
	function __construct() {

		add_filter( 'better-framework/panel/add', array(
			$this,
			'panel_add'
		), 100 );

		add_filter( 'better-framework/panel/' . self::$option_panel_id . '/config', array(
			$this,
			'panel_config'
		), 100 );

		add_filter( 'better-framework/panel/' . self::$option_panel_id . '/fields', array(
			$this,
			'panel_fields'
		), 100 );

		add_filter( 'better-framework/panel/' . self::$option_panel_id . '/std', array(
			$this,
			'panel_std'
		), 100 );

		// Callback for resetting data
		add_filter( 'better-framework/panel/reset/result', array( $this, 'callback_panel_reset_result' ), 10, 2 );

		// Callback for importing data
		add_filter( 'better-framework/panel/import/result', array( $this, 'callback_panel_import_result' ), 10, 3 );

		// Callback changing save result
		add_filter( 'better-framework/panel/save/result', array( $this, 'callback_panel_save_result' ), 10, 2 );

		// Hook BF admin assets enqueue
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );

		self::include_modules();
	}


	/**
	 * Build the required object instance
	 *
	 * @param   string $object
	 * @param   bool   $fresh
	 * @param   bool   $just_include
	 *
	 * @return  null|BF_Booster
	 */
	public static function factory( $object = 'self', $fresh = false, $just_include = false ) {

		if ( isset( self::$instances[ $object ] ) && ! $fresh ) {
			return self::$instances[ $object ];
		}

		switch ( $object ) {

			/**
			 * Main BF_Booster Class
			 */
			case 'self':
				$class = 'BF_Booster';
				break;


			default:
				return null;
		}


		// Just prepare/includes files
		if ( $just_include ) {
			return;
		}

		// don't cache fresh objects
		if ( $fresh ) {
			return new $class;
		}

		self::$instances[ $object ] = new $class;

		return self::$instances[ $object ];
	}


	/**
	 * Used for retrieving options simply and safely for next versions
	 *
	 * @param $option_key
	 *
	 * @return mixed|null
	 */
	public static function get_option( $option_key ) {

		return bf_get_option( $option_key, self::$option_panel_id );
	}


	/**
	 * Callback: Used for enqueue font manager assets
	 *
	 * Filter: admin_enqueue_scripts
	 */
	function admin_enqueue_scripts() {

		if ( Better_Framework()->sections['admin_panel'] != true || Better_Framework()->get_current_page_type() != 'panel' ) {
			return;
		}

	}


	/**
	 * Callback: Setup panel
	 *
	 * Filter: better-framework/panel/options
	 *
	 * @param array $panels
	 *
	 * @return array
	 */
	public function panel_add( $panels ) {

		$panels[ self::$option_panel_id ] = array(
			'id'    => self::$option_panel_id,
			'style' => false,
		);

		return $panels;
	}


	/**
	 * Callback: Init's BF options
	 *
	 * Filter: better-framework/panel/options
	 *
	 * @param $panels
	 *
	 * @return mixed
	 */
	public function panel_config( $panels ) {

		include BF_PATH . 'booster/panel-config.php';

		return $panels;
	}


	/**
	 * Callback: Init's BF options
	 *
	 * Filter: better-framework/panel/options
	 *
	 * @param $fields
	 *
	 * @return mixed
	 */
	public function panel_fields( $fields ) {

		include BF_PATH . 'booster/panel-fields.php';

		return $fields;
	}


	/**
	 * Callback: Init's BF options
	 *
	 * Filter: better-framework/panel/options
	 *
	 * @param $fields
	 *
	 * @return mixed
	 */
	public function panel_std( $fields ) {

		include BF_PATH . 'booster/panel-std.php';

		return $fields;
	}


	/**
	 * Filter callback: Used for resetting current language on resetting panel
	 *
	 * @param   $options
	 * @param   $result
	 *
	 * @return array
	 */
	function callback_panel_reset_result( $result, $options ) {

		// check panel
		if ( $options['id'] != self::$option_panel_id ) {
			return $result;
		}

		// change messages
		if ( $result['status'] == 'succeed' ) {
			$result['msg'] = __( 'BS Booster options reset to default.', 'better-studio' );
		} else {
			$result['msg'] = __( 'An error occurred while resetting BS Booster.', 'better-studio' );
		}

		return $result;
	}


	/**
	 * Filter callback: Used for changing current language on importing translation panel data
	 *
	 * @param $result
	 * @param $data
	 * @param $args
	 *
	 * @return array
	 */
	function callback_panel_import_result( $result, $data, $args ) {

		// check panel
		if ( $args['panel-id'] != self::$option_panel_id ) {
			return $result;
		}

		// change messages
		if ( $result['status'] == 'succeed' ) {
			$result['msg'] = __( 'BS Booster options imported successfully.', 'better-studio' );
		} else {
			if ( $result['msg'] == __( 'Imported data is not for this panel.', 'better-studio' ) ) {
				$result['msg'] = __( 'Imported translation is not for BS Booster.', 'better-studio' );
			} else {
				$result['msg'] = __( 'An error occurred while importing BS Booster options.', 'better-studio' );
			}
		}

		return $result;
	}


	/**
	 * Filter callback: Used for changing save translation panel result
	 *
	 * @param $output
	 * @param $args
	 *
	 * @return string
	 */
	function callback_panel_save_result( $output, $args ) {

		// change only for translation panel
		if ( $args['id'] == self::$option_panel_id ) {
			if ( $output['status'] == 'succeed' ) {
				$output['msg'] = __( 'Booster settings saved.', 'better-studio' );
			} else {
				$output['msg'] = __( 'An error occurred while saving booster!', 'better-studio' );
			}
		}

		return $output;
	}


	/**
	 *
	 */
	public static function reset_cache_cb() {

		// remove all cached css and js files
		BF_Minify::clear_cache( 'all' );

		// remove mega-menus and widgets cache
		BF_Booster_Cache::flush_cache();

		return array(
			'status' => 'succeed',
			'msg'    => __( 'BS Booster cache cleared.', 'better-studio' ),
		);
	}


	/**
	 * Returns state of Booster sections
	 *
	 * @param string $section
	 *
	 * @return bool|mixed
	 */
	public static function is_active( $section = '' ) {

		if ( empty( $section ) ) {
			return false;
		}

		static $state;

		if ( ! is_null( $state ) ) {

			if ( isset( $state[ $section ] ) ) {
				return $state[ $section ];
			} else {
				return false;
			}
		}

		$state = array(
			'minify-css' => self::get_option( 'minify' ),
			'minify-js'  => self::get_option( 'minify' ),
		);

		if ( is_admin() || bf_is( 'dev' ) ) {
			$state['minify-css'] = false;
			$state['minify-js']  = false;
		}

		$state = apply_filters( 'better-framework/booster/active', $state );

		if ( isset( $state[ $section ] ) ) {
			return $state[ $section ];
		} else {
			return false;
		}
	}


	/**
	 * Include booster sub-modules
	 */
	public static function include_modules() {

		if ( ! class_exists( 'BF_Booster_Cache' ) ) {
			include BF_PATH . 'booster/class-bf-booster-cache.php';
		}

		if ( ! class_exists( 'BF_Menu_cache' ) ) {
			// Include menu cache object
			include BF_PATH . 'booster/class-bf-menu-cache.php';
		}

		if ( ! class_exists( 'BF_Widget_Cache' ) ) {
			// Include widget cache object
			include BF_PATH . 'booster/class-bf-widget-cache.php';
		}

		if ( ! class_exists( 'BF_Shortcode_Cache' ) ) {
			// Include shortcode cache object
			include BF_PATH . 'booster/class-bf-shortcode-cache.php';
		}

		self::register_clear_cache_hooks();        // Reset caches
	}


	/**
	 * Register hooks to clear widget and menu cache
	 */
	public static function register_clear_cache_hooks() {

		add_action( 'wp_update_nav_menu', 'BF_Booster_Cache::flush_cache' );

		add_action( 'delete_category', 'BF_Booster_Cache::flush_cache' );
		add_action( 'edit_category', 'BF_Booster_Cache::flush_cache' );
		add_action( 'add_category', 'BF_Booster_Cache::flush_cache' );

		add_action( 'delete_attachment', 'BF_Booster_Cache::flush_cache' );
		add_action( 'edit_attachment', 'BF_Booster_Cache::flush_cache' );
		add_action( 'untrashed_post', 'BF_Booster_Cache::flush_cache' );
		add_action( 'trashed_post', 'BF_Booster_Cache::flush_cache' );
		add_action( 'deleted_post', 'BF_Booster_Cache::flush_cache' );
		add_action( 'save_post', 'BF_Booster_Cache::flush_cache' );

		add_action( 'delete_term', 'BF_Booster_Cache::flush_cache' );
		add_action( 'edit_terms', 'BF_Booster_Cache::flush_cache' );

		add_action( 'wp_set_comment_status', 'BF_Booster_Cache::flush_cache' );
		add_action( 'untrashed_comment', 'BF_Booster_Cache::flush_cache' );
		add_action( 'unspammed_comment', 'BF_Booster_Cache::flush_cache' );
		add_action( 'deleted_comment', 'BF_Booster_Cache::flush_cache' );
		add_action( 'spammed_comment', 'BF_Booster_Cache::flush_cache' );

		add_action( 'upgrader_process_complete', 'BF_Booster_Cache::flush_cache' );
		add_action( 'switch_theme', 'BF_Booster_Cache::flush_cache' );

		add_action( 'deactivated_plugin', 'BF_Booster_Cache::flush_cache' );
		add_action( 'activated_plugin', 'BF_Booster_Cache::flush_cache' );

		add_action( 'better-framework/version-compatibility/checked', 'BF_Booster_Cache::flush_cache' );
		add_action( 'better-framework/template-compatibility/done', 'BF_Booster_Cache::flush_cache' );
		add_action( 'better-framework/panel/save', 'BF_Booster_Cache::flush_cache' );


		// WP rocket compatibility
		add_action( 'after_rocket_clean_cache_busting', 'BF_Booster_Cache::flush_cache' );

		// WP super cache compatibility
		add_action( 'pre_update_option_supercache_stats', 'BF_Booster::wpsc_clean_cache' );

		// W3 Total Cache Compatibility
		add_action( 'w3tc_flush_all', 'BF_Booster_Cache::flush_cache' );

		// WP fastest cache compatibility
		add_action( 'wp_ajax_wpfc_delete_cache', 'BF_Booster::wpfc_toolbar_clean_cache' );
		add_action( 'wp_ajax_wpfc_delete_current_page_cache', 'BF_Booster::wpfc_toolbar_clean_cache' );
		add_action( 'wp_ajax_wpfc_delete_cache_and_minified', 'BF_Booster::wpfc_toolbar_clean_cache' );
		//
		add_action( 'pre_option_WpFastestCachePreLoad', 'BF_Booster::wpfc_admin_clean_cache' );
	}


	/**
	 * Clear booster cache when wp super cache delete.
	 *
	 * @return bool true on success
	 */
	public static function wpsc_clean_cache() {

		if ( ! isset( $_POST['wp_delete_cache'] ) ) {
			return false;
		}

		if ( ! function_exists( 'wpsupercache_site_admin' ) || ! wpsupercache_site_admin() ) {
			return false;
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			return false;
		}

		return BF_Booster_Cache::flush_cache();
	}


	/**
	 * Check user access whether is allow to clear wpfc plugin cache
	 *
	 * @return bool
	 */
	public static function can_user_clean_wpfc_cache() {

		if ( ! is_user_logged_in() ) {
			return false;
		}

		$is_user_valid = ( current_user_can( 'manage_options' ) || current_user_can( 'edit_others_pages' ) ) ? true : false;

		if ( ! $is_user_valid && defined( 'WPFC_TOOLBAR_FOR_AUTHOR' ) && WPFC_TOOLBAR_FOR_AUTHOR ) {
			$is_user_valid = current_user_can( 'delete_published_posts' ) || current_user_can( 'edit_published_posts' );
		}

		return $is_user_valid;
	}


	/**
	 * Clear booster cache when user clicked on WPFC => "delete cache" on admin toolbar
	 */
	public static function wpfc_toolbar_clean_cache() {

		if ( self::can_user_clean_wpfc_cache() ) {
			BF_Booster_Cache::flush_cache();
		}
	}


	/**
	 * Clear booster cache when user clicked on "delete cache" on WPFC admin panel
	 */
	public static function wpfc_admin_clean_cache() {

		if ( self::can_user_clean_wpfc_cache() ) {
			if ( isset( $_POST['wpFastestCachePage'] ) && $_POST['wpFastestCachePage'] === 'deleteCache' ) {
				BF_Booster_Cache::flush_cache();
			}
		}
	}
}
libs/better-framework/booster/class-bf-shortcode-cache.php000064400000014326151214002530017665 0ustar00<?php


/**
 * Cache WordPress shortcodes output for better performance
 *
 * @since      3.0.0
 * @package    BetterFramework/booster
 *
 * @author     BetterStudio <info@betterstudio.com>
 * @copyright  Copyright (c) 2017, BetterStudio
 *
 * @extends    BF_Item_Cache
 */
class BF_Shortcode_Cache extends BF_Booster_Cache {

	/**
	 * Group name for cached data
	 *
	 * @var string
	 */
	public static $cache_group = 'shortcode';

	/**
	 * List of shortcodes which is available for cache
	 *
	 * 'shortcode tag name' => 'cache duration @see $cache_intervals'
	 *
	 * @var array
	 */
	public static $shortcodes2cache = array();


	/**
	 * Store shortcode callback handler
	 *
	 * 'shortcode tag name' => callback to fire when shortcode is found
	 *                          in the order hand, this is second argument ($func) of add_shortcode function
	 *
	 * @var array
	 */
	public static $shortcodes_callback = array();


	/**
	 * A flag to detect is current shortcode nested level.
	 *
	 * @see display_shortcode
	 *
	 * @var int
	 */
	public static $shortcode_level = 0;


	/**
	 * Register event to initialize shortcode cache
	 */
	public static function Run() {

		add_action( 'init', 'BF_Shortcode_Cache::init' );
	}


	/**
	 * Initialize shortcode cache
	 */
	public static function init() {

		if ( is_user_logged_in() ) {
			return;
		}

		// BF Development mode
		if ( bf_is( 'dev' ) ) {
			return;
		}

		// Cache plugin or not active
		if ( ! BF_Booster::get_option( 'cache-shortcodes' ) || self::have_cache_plugin() ) {
			return;
		}

		self::$shortcodes2cache = apply_filters( 'better-framework/booster/shortcodes/config', array() );

		add_action( 'template_redirect', 'BF_Shortcode_Cache::apply_cache', 999 );
	}


	/**
	 * Change shortcode handle callback to response check cache storage before fire it if necessary
	 */
	public static function apply_cache() {

		global $shortcode_tags;

		# TODO: maybe we could replace this block of the code with array_diff/array_intersect stuff! :D
		foreach ( self::$shortcodes2cache as $shortcode_tag => $_ ) {

			if ( ! isset( $shortcode_tags[ $shortcode_tag ] ) ) { # shortcode not found! maybe it's an invalid $shortcode_tag value of the shortcode will register (add_shortcode) further
				continue;
			}

			self::$shortcodes_callback[ $shortcode_tag ] = $shortcode_tags[ $shortcode_tag ];        # TODO: we don't need the original callback if the cache already exists.
			$shortcode_tags[ $shortcode_tag ]            = 'BF_Shortcode_Cache::display_shortcode';
		}
	}


	/**
	 * Handle shortcode output
	 *
	 * @param string|array $atts          shortcode attributes. it could be an empty string
	 * @param string       $content       shortcode inner content
	 * @param string       $shortcode_tag shortcode tag name
	 *
	 * @return string
	 */
	public static function display_shortcode( $atts, $content, $shortcode_tag ) {

		# it's always true. we added this line for more flexibility because we are good citizen
		$can_cache = apply_filters( 'better-framework/booster/shortcodes/cache', self::can_cache( $shortcode_tag ), $atts, $content, $shortcode_tag );

		if ( ! $can_cache ) { # We are not allow to cache this specific shortcode
			return self::fire_shortcode_handler( $atts, $content, $shortcode_tag );
		}

		$cache_key = self::get_cache_key( $atts, $content, $shortcode_tag );

		if ( $cached = self::get_cache( $cache_key, self::$cache_group ) ) { # current shortcode already cached

			return $cached;
		} else { # not cache found!


			self::$shortcode_level ++; # increase shortcode to detect nested shortcodes. $shortcode_level > 1
			$shortcode_output = self::fire_shortcode_handler( $atts, $content, $shortcode_tag );

			if ( is_string( $shortcode_output ) ) { # string means everything is ok

				/**
				 * Just cache parent shortcode
				 *
				 * It doesn't need to cache nested shortcode ( shortcodes in the $content)
				 * if we cache top level shortcode,  another child-shortcodes will also cache
				 */
				if ( self::$shortcode_level === 1 ) {
					$expiration = self::get_cache_duration( $shortcode_tag );
					self::set_cache( $cache_key, $shortcode_output, self::$cache_group, $expiration ); # Cache the shortcode output
				}
			}

			self::$shortcode_level --; # rollback increased value

			return $shortcode_output;
		}
	}


	/**
	 *
	 * Just fire shortcode callback handle without considering cache version
	 *
	 * @param string|array $atts          shortcode attributes. it could be an empty string
	 * @param string       $content       shortcode inner content
	 * @param string       $shortcode_tag shortcode tag name
	 *
	 * @return string|void string on success or void on failure
	 */
	public static function fire_shortcode_handler( &$atts, &$content, &$shortcode_tag ) {

		if ( ! isset( self::$shortcodes_callback[ $shortcode_tag ] ) ) { # invalid $shortcode_tag
			return;
		}

		ob_start(); # Some damn plugins echo the output instead of return it! we handle this issue because we are Better Studio

		$output = call_user_func( self::$shortcodes_callback[ $shortcode_tag ], $atts, $content, $shortcode_tag );
		$buffer = ob_get_clean();

		if ( ! $output && $buffer ) {
			$output = $buffer;
		}

		if ( is_string( $output ) ) {
			return $output;
		}

		# i have no idea why the output is not string :|
	}


	/**
	 * Get unique cache key for the shortcode
	 *
	 * @param string|array $atts
	 * @param string       $content
	 * @param string       $shortcode_tag
	 *
	 * @return string
	 */
	public static function get_cache_key( &$atts, &$content, &$shortcode_tag ) {

		return md5( serialize( $atts ) . $shortcode_tag . $content );
	}


	/**
	 * Is a shortcode available for caching
	 *
	 * @param string $shortcode_tag shortcode tag name
	 *
	 * @return bool
	 */
	public static function can_cache( $shortcode_tag ) {

		return isset( self::$shortcodes2cache[ $shortcode_tag ] );
	}


	/**
	 * Get cache duration interval
	 *
	 * @param string $shortcode_tag shortcode tag name
	 *
	 * @return int|void int on success
	 */
	public static function get_cache_duration( $shortcode_tag ) {

		if ( isset( self::$shortcodes2cache[ $shortcode_tag ] ) ) {

			$dur = self::$shortcodes2cache[ $shortcode_tag ];

			if ( isset( self::$cache_intervals[ $dur ] ) ) {

				return self::$cache_intervals[ $dur ];
			}
		}
	}
}


BF_Shortcode_Cache::Run();
libs/better-framework/booster/class-bf-booster-cache.php000064400000011010151214002530017333 0ustar00<?php


abstract class BF_Booster_Cache {

	/**
	 * Name for transient cache storage
	 *
	 * Special names: the following name will replace to
	 *
	 * {group} > the group of cache
	 * {ID}    > the ID of cache
	 *
	 * @var string
	 */
	public static $cache_name_format = 'bf-booster-{group}-{ID}';

	/**
	 * Determine the durations of the cache
	 *
	 * @var array
	 */
	protected static $cache_intervals = array(
		'long'  => 36000, // 10 Hour
		'short' => 1800, // 30 Minute
	);


	/**
	 * Detect is any cache plugin enabled on site
	 *
	 * @return bool true if enabled
	 */
	public static function have_cache_plugin() {

		if ( defined( 'WP_CACHE' ) && WP_CACHE ) {
			return true;
		}

		// Detect Fastest cache
		$plugins = wp_get_active_and_valid_plugins();

		if ( in_array( WP_PLUGIN_DIR . '/wp-fastest-cache/wpFastestCache.php', $plugins ) ) {
			return true;
		}

		return false;
	}

	/****
	 *
	 *
	 * Cache Methods
	 *
	 *
	 ***/

	/***
	 * Fetch cache from cache storage
	 *
	 * @param string $cache_key   unique label for the cache
	 * @param string $cache_group optional. for categorizing the caches.
	 *
	 * @return mixed cached data success or void on failure.
	 */
	public static function get_cache( $cache_key, $cache_group = 'default' ) {

		$transient_name = self::get_cache_name( $cache_key, $cache_group );

		if ( $group_cached = get_transient( $transient_name ) ) {
			if ( isset( $group_cached[ $cache_key ] ) ) {
				return $group_cached[ $cache_key ];
			}
		}

		return;
	}


	/**
	 * Save Data in Cache Storage
	 *
	 * @param string $cache_key   name of the cache
	 * @param mixed  $data2cache  data to cache
	 * @param string $cache_group optional. cache group
	 * @param null   $expiration  optional. cache expiration time
	 *
	 * @return bool true on success or false otherwise
	 */
	public static function set_cache( $cache_key, $data2cache, $cache_group = 'default', $expiration = null ) {

		$transient_name = self::get_cache_name( $cache_key, $cache_group );

		$current_data = get_transient( $transient_name );
		if ( ! $current_data ) {
			$current_data = array();
		}
		$current_data = (array) $current_data;

		$new_data               = &$current_data;
		$new_data[ $cache_key ] = $data2cache;

		return set_transient( $transient_name, $new_data, $expiration );
	}


	/**
	 * Get unique name for the cache
	 *
	 * @param string $cache_key
	 * @param string $cache_group
	 *
	 * @return string cache name
	 */
	public static function get_cache_name( $cache_key, $cache_group = 'default' ) {

		$replacement = array(
			'{ID}'    => $cache_key,
			'{group}' => $cache_group,
		);

		return str_replace( array_keys( $replacement ), array_values( $replacement ), self::$cache_name_format );
	}


	/**
	 * Delete a specific cache
	 *
	 * @param string $cache_key
	 * @param string $cache_group
	 *
	 * @return bool true on success or false on failure.
	 */
	public static function delete_cache( $cache_key, $cache_group = 'default' ) {

		$transient_name = self::get_cache_name( $cache_key, $cache_group );

		$cache_data = get_transient( $transient_name );

		if ( ! $cache_data ) {
			return false;
		}
		$cache_data = (array) $cache_data;

		unset( $cache_data[ $cache_key ] );

		if ( empty( $cache_data ) ) {

			return delete_transient( $transient_name );
		} else {

			return set_transient( $transient_name, $cache_data ); # When don't pass the third parameter, it will not change
		}
	}


	/**
	 * Flush all of the data in the cache storage
	 *
	 * it doesn't master the cache belong to which group this method will delete all data in any group
	 *
	 * @global wpdb $wpdb wordpress database object
	 *
	 * @return bool true if cache was successfully cleared or false otherwise.
	 */
	public static function flush_cache() {

		global $wpdb;

		$transient_option_prefix  = '_transient_';          # WordPress transient prefix
		$transient_timeout_prefix = '_transient_timeout_';  # Prefix for transient timeout on db

		$transient_name = str_replace( array( '{ID}', '{group}' ), '%', self::$cache_name_format );
		$affected       = 0;

		$affected += $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->options where option_name LIKE %s", "$transient_option_prefix$transient_name" ) );
		$affected += $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->options where option_name LIKE %s", "$transient_timeout_prefix$transient_name" ) );

		return (bool) $affected;
	}


	/**
	 * Get cache durations interval
	 *
	 * @return array
	 */
	public static function cache_intervals() {

		return apply_filters( 'better-framework/booster/cache-intervals', self::$cache_intervals );
	}
}libs/better-framework/booster/panel-fields.php000064400000005331151214002530015501 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

$compatible = __( 'It\'s 100% compatible with all cache plugins', 'better' );
$compatible = "<br><br><strong style='color: #07b251;'>$compatible</strong>";

$fields['minify'] = array(
	'name' => __( 'Minify & Combine All CSS & Javascript Files', 'better-studio' ),
	'desc' => __( 'BS Booster will minify and combine all BetterStudio theme & plugins CSS & Javascript files into 1 file. It\'s highly compatible with all cache plugins.', 'better-studio' ) . $compatible,
	'id'   => 'minify',
	'type' => 'switch',
);


if ( apply_filters( 'better-framework/booster/mega-menu/config', array() ) ) {
	$fields['cache-mega-menu'] = array(
		'name' => __( 'Speed up Mega menus by cache', 'better-studio' ),
		'desc' => __( 'Cache all mega menus to speed up site loading time.', 'better-studio' ) . $compatible,
		'id'   => 'cache-mega-menu',
		'type' => 'switch',
	);
}


if ( apply_filters( 'better-framework/booster/widgets/config', array() ) ) {
	$fields['cache-widgets'] = array(
		'name' => __( 'Speed up Widgets by cache', 'better-studio' ),
		'desc' => __( 'Cache widgets to speed up site loading time.', 'better-studio' ) . $compatible,
		'id'   => 'cache-widgets',
		'type' => 'switch',
	);
}

if ( apply_filters( 'better-framework/booster/shortcodes/config', array() ) ) {
	$fields['cache-shortcodes'] = array(
		'name' => __( 'Speed up Shortcodes by cache', 'better-studio' ),
		'desc' => __( 'Cache shortcodes to speed up site loading time.', 'better-studio' ) . $compatible,
		'id'   => 'cache-shortcodes',
		'type' => 'switch',
	);
}

$fields['reset_cache'] = array(
	'name'        => __( 'Reset All Cache', 'better-studio' ),
	'id'          => 'reset_cache',
	'type'        => 'ajax_action',
	'button-name' => '<i class="fa fa-refresh"></i> ' . __( 'Purge BS Booster Cache', 'better-studio' ),
	'callback'    => 'BF_Booster::reset_cache_cb',
	'confirm'     => __( 'Are you sure for resetting BS Booster cache?', 'better-studio' ),
	'desc'        => __( 'This allows you to reset all Booster cache.', 'better-studio' ),
);
libs/better-framework/booster/class-bf-scripts.php000064400000014176151214002530016324 0ustar00<?php


/**
 * Merge and compress static js/css files.
 *
 * @since 2.9.0
 */
class BF_Scripts extends WP_Scripts {

	/**
	 * Static files path
	 *
	 * @var array
	 *
	 * @since 2.9.0
	 */
	public $files_path = array();


	/**
	 * Put contents into a file
	 *
	 * @param string $filename full path to file
	 * @param string $content
	 *
	 * @return bool true on success or false on failure
	 * @since 2.9.0
	 */
	public function write_file( $filename, $content ) {

		$dir = dirname( $filename );
		if ( ! is_dir( $dir ) ) {
			wp_mkdir_p( $dir );
		}

		return bf_file_system_instance()->put_contents(
			$filename,
			$content
		);
	}


	public function is_dir_writable( $dir_path ) {

		if ( ! is_dir( $dir_path ) ) {
			wp_mkdir_p( $dir_path );
		}

		return is_writeable( $dir_path );
	}


	/**
	 * Get file content
	 *
	 * @param string $handle handle name
	 *
	 * @since 2.9.0
	 * @return bool|string string on success or false on failure
	 */
	public function get_file_content( $handle ) {

		if ( ! empty( $this->files_path[ $handle ] ) && is_readable( $this->files_path[ $handle ] ) ) {

			return bf_get_local_file_content( $this->files_path[ $handle ] );
		}

		return false;
	}


	/**
	 * Get unique file hash
	 *
	 * @param array $handles
	 *
	 * @since 2.9.0
	 * @return string
	 */
	public function file_hash( $handles ) {

		return md5( serialize( array_intersect_key( $this->registered, array_flip( $handles ) ) ) );
	}


	/**
	 * Combine and compress files content
	 *
	 * @param array  $handles
	 * @param string $new_filename
	 *
	 * @since 2.9.0
	 * @return bool true on success or false on failure
	 */
	public function do_minify( $handles, $new_filename ) {

		if ( ! bf_booster_is_active( 'minify-js' ) ) {
			return;
		}

		if ( is_admin() ) {
			return;
		}

		if ( ! $this->is_dir_writable( dirname( $new_filename ) ) ) {
			return false;
		}

		$output = '';

		foreach ( $handles as $handle ) {

			$content = $this->get_file_content( $handle );

			if ( $content === false ) {

				return false;
			}

			$output .= $this->minify( $content ) . "\n\n";
		}


		return $this->write_file( $new_filename, $output );
	}


	//	BF_Minify


	public $handle = array();


	/**
	 * Initialize minify hooks
	 *
	 * @since 2.9.0
	 */
	public function init() {

		if ( is_admin() ) {

			add_action( 'admin_footer', 'BF_Scripts::print_main_script_tag', 1 );
		} else {

			add_action( 'wp_footer', 'BF_Scripts::print_main_script_tag' );

			add_filter( 'script_loader_tag', 'BF_Scripts::add_async_attribute', 10, 2 );
		}
	}


	/**
	 * Print scripts
	 */
	public function print_output() {

		$this->do_items( false, 0 );

		$this->_print_scripts( $this->handle );

	}


	/**
	 * Processes a script dependency.
	 *
	 * @since  2.6.0
	 * @since  2.8.0 Added the `$group` parameter.
	 * @access public
	 *
	 * @see    WP_Dependencies::do_item()
	 *
	 * @param string   $handle The script's registered handle.
	 * @param bool|int $group  Optional. Group level: (int) level, (false) no groups. Default false.
	 *
	 * @return bool true on success, false on failure.
	 */
	public function do_item( $handle, $group = false ) {

		$this->handle[] = $handle;
	}


	/**
	 * Print scripts
	 *
	 * @param array $handles
	 *
	 * @since 2.9.0
	 */
	public function _print_scripts( $handles ) {

		if ( ! $handles ) {
			return;
		}

		if ( bf_count( $handles ) === 1 ) {

			$this->print_inline_script( $handles[0], 'before', false );

			$this->print_extra_script( $handles[0] );

			self::print_script( $this->registered[ $handles[0] ]->src, $handles[0] );

			$this->print_inline_script( $handles[0], 'after', false );

			return;
		}

		$files_url = array();
		$after     = '';

		foreach ( $handles as $handle ) {

			echo $this->print_inline_script( $handle, 'before', false );

			$this->print_extra_script( $handle );

			$files_url[] = $this->registered[ $handle ]->src;

			$after .= $this->print_inline_script( $handle, 'after', false );
		}

		$file_dir  = trailingslashit( WP_CONTENT_DIR . '/' . BF_Minify::$cache_dir );
		$file_name = $this->file_hash( $handles ) . '.js';

		if ( is_readable( $file_dir . $file_name ) || $this->do_minify( $handles, $file_dir . $file_name ) ) {
			self::print_script( content_url( BF_Minify::$cache_dir . '/' . $file_name ) );
		} else {

			foreach ( $handles as $handle ) {
				self::print_script( $this->registered[ $handle ]->src, $handle );
			}
		}

		echo $after;
	}


	/**
	 * Print <script> tag
	 *
	 * @param string $url
	 * @param string $handle
	 *
	 * @since 2.9.0
	 */
	public static function print_script( $url, $handle = 'bs-booster' ) {

		wp_enqueue_script( $handle, $url, array(), false, true );
	}


	/**
	 * Ads async attribute to BS Booster JS
	 *
	 * @param $tag
	 * @param $handle
	 *
	 * @return mixed
	 */
	public static function add_async_attribute( $tag, $handle ) {

		if ( 'bs-booster' !== $handle ) {
			return $tag;
		}

		return str_replace( ' src', ' async="async" src', $tag );
	}


	public static function print_main_script_tag() {

		bf_scripts()->print_output();
	}


	/**
	 * Callback to compress files content
	 *
	 * @param string $content
	 *
	 * @since 2.9.0
	 * @return string|bool
	 */
	public function minify( $content ) {

		return $content;
	}


	public function all_deps( $handles, $recursion = false, $group = false ) {

		return WP_Dependencies::all_deps( $handles, $recursion, $group );

	}


	/**
	 * Prints inline scripts registered for a specific handle.
	 *
	 * @param string $handle   Name of the script to add the inline script to. Must be lowercase.
	 * @param string $position Optional. Whether to add the inline script before the handle
	 *                         or after. Default 'after'.
	 * @param bool   $echo     Optional. Whether to echo the script instead of just returning it.
	 *                         Default true.
	 *
	 * @return string|false Script on success, false otherwise.
	 */
	public function print_inline_script( $handle, $position = 'after', $echo = true ) {

		$output = $this->get_data( $handle, $position );

		if ( empty( $output ) ) {
			return false;
		}

		$output = trim( implode( "\n", $output ), "\n" );

		if ( $echo ) {
			printf( "<script type='text/javascript'>\n%s\n</script>\n", $output );
		}

		return $output;
	}
}
libs/better-framework/booster/functions.php000064400000002530151214002530015144 0ustar00<?php

if ( ! function_exists( 'bf_scripts' ) ) {

	/**
	 * @global $bf_scripts BF_Scripts object
	 *
	 * @since 2.9.0
	 * @return BF_Scripts
	 */
	function bf_scripts() {

		global $bf_scripts;

		if ( $bf_scripts ) {
			return $bf_scripts;
		}

		$bf_scripts = new BF_Scripts();
		$bf_scripts->init();

		return $bf_scripts;
	}
}

if ( ! function_exists( 'bf_style' ) ) {

	/**
	 * @global $bf_styles BF_Styles object
	 *
	 * @since 2.9.0
	 * @return BF_Styles
	 */
	function bf_styles() {

		global $bf_styles;

		if ( $bf_styles ) {
			return $bf_styles;
		}

		$bf_styles = new BF_Styles();
		$bf_styles->init();

		return $bf_styles;
	}
}


if ( ! function_exists( 'bf_localize_script' ) ) {

	/**
	 * @param  $handle
	 * @param  $object_name
	 * @param  $l10n
	 *
	 * @return BF_Styles
	 * @global $bf_styles BF_Styles object
	 *
	 * @since 2.9.0
	 */
	function bf_localize_script( $handle, $object_name, $l10n ) {

		if ( ! bf_booster_is_active( 'minify-js' ) ) {
			wp_localize_script( $handle, $object_name, $l10n );

			return;
		}

		bf_scripts()->localize( $handle, $object_name, $l10n );
	}
}


if ( ! function_exists( 'bf_booster_is_active' ) ) {
	/**
	 * Returns state of Booster sections
	 *
	 * @param string $section
	 *
	 * @return bool|mixed
	 */
	function bf_booster_is_active( $section = '' ) {

		return BF_Booster::is_active( $section );
	}
}
libs/better-framework/booster/index.php000064400000000034151214002530014240 0ustar00<?php
// Silence is golden.
libs/better-framework/booster/class-bf-minify.php000064400000010065151214002530016121 0ustar00<?php


/**
 * Merge and compress static js/css files.
 *
 * @since 2.9.0
 */
abstract class BF_Minify extends WP_Dependencies {

	/**
	 * Relative path to cache directory
	 *
	 * @var string
	 *
	 * @since 2.9.0
	 */
	public static $cache_dir = 'bs-booster-cache';

	/**
	 * Static files path
	 *
	 * @var array
	 *
	 * @since 2.9.0
	 */
	public $files_path = array();


	/**
	 * @return mixed
	 */
	abstract public function print_output();


	/**
	 * Callback to compress files content
	 *
	 * @param string $content
	 *
	 * @since 2.9.0
	 * @return string|bool
	 */
	public function minify( $content ) {

		return $content;
	}


	/**
	 * Callback to compress sanitize files content
	 *
	 * @param string $content
	 * @param array  $handle
	 *
	 * @return string
	 * @since 2.9.0
	 */
	public function sanitize( $content, $handle ) {

		return $content;
	}


	/**
	 * Put contents into a file
	 *
	 * @param string $file_path full path to file
	 * @param string $content   file content
	 *
	 * @return bool true on success or false on failure
	 * @since 2.9.0
	 */
	public static function write_file( $file_path, $content ) {

		$dir = dirname( $file_path );

		if ( ! is_dir( $dir ) ) {
			wp_mkdir_p( $dir );
		}

		return bf_file_system_instance()->put_contents(
			$file_path,
			$content
		);
	}


	public function is_dir_writable( $dir_path ) {

		if ( ! is_dir( $dir_path ) ) {
			wp_mkdir_p( $dir_path );
		}

		return is_writeable( $dir_path );
	}


	/**
	 * Get file content
	 *
	 * @param string $handle handle name
	 *
	 * @since 2.9.0
	 * @return bool|string string on success or false on failure
	 */
	public function get_file_content( $handle ) {

		if ( ! empty( $this->files_path[ $handle ] ) && is_readable( $this->files_path[ $handle ] ) ) {

			return bf_get_local_file_content( $this->files_path[ $handle ] );
		}

		return false;
	}


	/**
	 * Get unique file hash
	 *
	 * @param array $handles
	 *
	 * @since 2.9.0
	 * @return string
	 */
	public function handles_hash( $handles ) {

		return md5( serialize( array_intersect_key( $this->registered, array_flip( $handles ) ) ) );
	}


	public function string_hash( $string ) {

		return md5( $string );
	}


	/**
	 * Combine and compress files content
	 *
	 * @param array  $handles
	 * @param string $new_filename
	 *
	 * @since 2.9.0
	 * @return bool true on success or false on failure
	 */
	public function do_minify( $handles, $new_filename ) {

		if ( ! bf_booster_is_active( 'minify-css' ) ) {
			return;
		}

		if ( is_admin() ) {
			return;
		}

		if ( ! $this->is_dir_writable( dirname( $new_filename ) ) ) {
			return false;
		}

		$output = '';

		foreach ( $handles as $handle ) {

			$content = $this->get_file_content( $handle );

			if ( $content === false ) {

				return false;
			}

			$output .= $this->sanitize( $content, $handle ) . "\n";
		}

		if ( $output = $this->minify( $output ) ) {

			return self::write_file( $new_filename, $output );
		}

		return false;
	}


	public static function add_hooks() {

		add_action( 'bs-booster/minify/clear-cache', 'BF_Minify::clear_cache' );
	}


	public static function register_schedule() {

		if ( ! wp_next_scheduled( 'bs-booster/minify/clear-cache' ) ) {
			wp_schedule_event( time(), 'daily', 'bs-booster/minify/clear-cache' );
		}

	}


	/**
	 * Clears all minified caches (files)
	 *
	 * @param string $type all|outdated
	 *
	 * @return bool
	 */
	public static function clear_cache( $type = 'outdated' ) {

		$dir = trailingslashit( WP_CONTENT_DIR . '/' . self::$cache_dir );

		if ( $files = bf_file_system_instance()->dirlist( $dir, false, false ) ) {

			$files = array_keys( $files );
		} else {

			return false;
		}

		$current_time = time();
		$duration     = DAY_IN_SECONDS * 2;

		if ( $type == 'outdated' ) {
			foreach ( $files as $file ) {

				$delete_file = $duration < ( $current_time - fileatime( $dir . $file ) );

				if ( $delete_file ) {

					@unlink( $dir . $file );
				}

			}
		} else {
			foreach ( $files as $file ) {
				@unlink( $dir . $file );
			}
		}

		return true;
	} // clear_cache
}


if ( is_admin() ) {
	BF_Minify::register_schedule();
}

BF_Minify::add_hooks();
libs/better-framework/booster/class-bf-menu-cache.php000064400000006312151214002530016633 0ustar00<?php


/**
 * Cache WordPress nav menus for better performance
 *
 * @since      3.0.0
 * @package    BetterFramework/booster
 *
 * @author     BetterStudio <info@betterstudio.com>
 * @copyright  Copyright (c) 2017, BetterStudio
 *
 * @extends    BF_Item_Cache
 */
class BF_Menu_cache extends BF_Booster_Cache {

	/**
	 * Group name for cached data
	 *
	 * @var string
	 */
	public static $cache_group = 'menu';

	/**
	 * Flag to determine can cache the active mega menu
	 *
	 * @var bool|string unique id for cache if it's enable
	 */
	protected static $cache_menu = false;

	/**
	 * List of the mega-menus that is available for cache
	 *
	 * 'mega menu type' => 'cache duration @see $cache_intervals'
	 *
	 * @var array
	 */
	protected static $mega_menus2cache = array();


	/**
	 *  Register event to initialize menu cache
	 */
	public static function Run() {

		add_action( 'init', 'BF_Menu_cache::init' );
	}


	/**
	 * Initialize Menu Cache
	 */
	public static function init() {

		if ( is_user_logged_in() ) {
			return;
		}

		// BF Development mode
		if ( bf_is( 'dev' ) ) {
			return;
		}

		// Cache plugin or not active
		if ( ! BF_Booster::get_option( 'cache-mega-menu' ) || self::have_cache_plugin() ) {
			return;
		}

		self::$mega_menus2cache = apply_filters( 'better-framework/booster/mega-menu/config', array() );

		add_filter( 'better-framework/menu/mega/end_lvl', 'BF_Menu_cache::print_cached_version', 5 );
		add_filter( 'better-framework/menu/mega/end_lvl', 'BF_Menu_cache::cache_mega_menu', 15 );
	}


	/**
	 * Append cached version of the bf mega-menu if available
	 *
	 * @param array $args
	 *
	 * @return array
	 */
	public static function print_cached_version( $args ) {

		$cache_key = self::get_cache_key( $args );

		if ( ! isset( $args['current-item']->mega_menu ) ) {
			return $args;
		}

		$can_cache = apply_filters( 'better-framework/booster/mega-menu/cache', self::can_cache( $args['current-item']->mega_menu ), $args );

		if ( ! $can_cache ) {
			return $args;
		}

		if ( $cached = parent::get_cache( $cache_key, self::$cache_group ) ) {
			$args['output'] = $cached;

			self::$cache_menu = false; # turn cache flag off to prevent save a cached data into cache storage over and over!
		} else {

			self::$cache_menu = $cache_key; # no cache found. so we enable cache flag to collect and cache the menu @see cache_mega_menu
		}

		return $args;
	}


	/**
	 * Cache the output of bf mega menu if necessary
	 *
	 * @param array $args bf mega menu arguments
	 *
	 * @return array.
	 */
	public static function cache_mega_menu( $args ) {

		if ( self::$cache_menu && $args['output'] ) {
			self::set_cache( self::$cache_menu, $args['output'], self::$cache_group );
		}

		return $args;
	}


	/**
	 * Is current mega menu available for caching
	 *
	 * @param string $mega_menu Root ID for widget
	 *
	 * @return bool
	 */
	public static function can_cache( $mega_menu ) {

		return isset( self::$mega_menus2cache[ $mega_menu ] );
	}


	/**
	 * Generate unique cache id for current mega menu
	 *
	 * @param array $args
	 *
	 * @return string
	 */
	protected static function get_cache_key( $args ) {

		return md5( serialize( wp_array_slice_assoc( $args, array( 'current-item', 'sub-menu', 'depth' ) ) ) );
	}
}


BF_Menu_cache::Run();
libs/better-framework/booster/class-bf-widget-cache.php000064400000007376151214002530017165 0ustar00<?php


/**
 * Cache WordPress widgets output for better performance
 *
 * @since      3.0.0
 * @package    BetterFramework/booster
 *
 * @author     BetterStudio <info@betterstudio.com>
 * @copyright  Copyright (c) 2017, BetterStudio
 *
 * @extends    BF_Item_Cache
 */
class BF_Widget_Cache extends BF_Booster_Cache {

	/**
	 * Group name for cached data
	 *
	 * @var string
	 */
	public static $cache_group = 'widget';

	/**
	 * List of widgets that is available for cache
	 *
	 * 'base id of widget' => 'cache duration @see $cache_intervals'
	 *
	 * @var array
	 */
	public static $widgets2cache = array();


	/**
	 * Register event to initialize widget cache
	 */
	public static function Run() {

		add_action( 'init', 'BF_Widget_Cache::init' );
	}


	/**
	 * Initialize widget cache
	 */
	public static function init() {

		if ( is_user_logged_in() ) {
			return;
		}

		// BF Development mode
		if ( bf_is( 'dev' ) ) {
			return;
		}

		// Cache plugin or not active
		if ( ! BF_Booster::get_option( 'cache-widgets' ) || self::have_cache_plugin() ) {
			return;
		}

		self::$widgets2cache = apply_filters( 'better-framework/booster/widgets/config', array() );

		add_filter( 'widget_display_callback', 'BF_Widget_Cache::display_widget', 2, 3 );
	}


	/**
	 * Handle widget display callback
	 *
	 * Fetch widget output from the cache storage or fire the widget callback if necessary
	 *
	 *
	 * @param array     $instance  The current widget instance's settings
	 * @param WP_Widget $wp_widget The current widget instance
	 * @param array     $args      An array of default widget arguments
	 *
	 * @return bool|array
	 */
	public static function display_widget( $instance, $wp_widget, $args ) {


		if ( false === $instance ) { # False means another high priority hook did some stuff and we must leave it!
			return false;
		}

		$id_base   = $wp_widget->id_base;
		$can_cache = apply_filters( 'better-framework/booster/widgets/cache', self::can_cache( $id_base ), $instance, $args, $id_base, $wp_widget );

		if ( ! $can_cache ) { # We are not allow to cache this specific widget
			return $instance;
		}

		$cache_key = self::get_cache_key( $instance, $args );

		if ( $cached = self::get_cache( $cache_key, self::$cache_group ) ) { # The current widget already cached

			echo $cached;


		} else { # not cache found!

			// Fire the widget output callback and cache it

			$expiration = self::get_cache_duration( $id_base );

			ob_start();

			$wp_widget->widget( $args, $instance );

			$widget_output = ob_get_contents();

			self::set_cache( $cache_key, $widget_output, self::$cache_group, $expiration ); // Cache the widget output

			ob_end_flush(); // Print the output then delete the buffer
		}

		return false; # Return false tell WordPress to avoid fire output callback again
	}


	/**
	 * Get unique cache key for the widget
	 *
	 * @param array $instance The current widget instance's settings
	 * @param array $args     An array of default widget arguments
	 *
	 * @return string
	 */
	public static function get_cache_key( &$instance, &$args ) {

		return md5( $args['widget_id'] . serialize( $instance ) );
	}


	/**
	 * Is a widget available for caching
	 *
	 * @param string $widget_id_base Root ID for widget
	 *
	 * @return bool
	 */
	public static function can_cache( $widget_id_base ) {

		return isset( self::$widgets2cache[ $widget_id_base ] );
	}


	/**
	 * Get cache duration interval
	 *
	 * @param string $widget_id_base Root ID for widget
	 *
	 * @return int|void int on success
	 */
	public static function get_cache_duration( $widget_id_base ) {

		if ( isset( self::$widgets2cache[ $widget_id_base ] ) ) {

			$dur = self::$widgets2cache[ $widget_id_base ];

			if ( isset( self::$cache_intervals[ $dur ] ) ) {

				return self::$cache_intervals[ $dur ];
			}
		}
	}
}


BF_Widget_Cache::Run();
libs/better-framework/index.php000064400000000012151214002530012557 0ustar00<?php
die;libs/better-framework/shortcode/class-bf-shortcode.php000064400000026717151214002530017150 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Base class for all shortcodes that have some general functionality for all of them
 *
 */
class BF_Shortcode {

	/**
	 * Shortcode id
	 *
	 * @var string
	 */
	public $id;


	/**
	 * Widget ID For Class Name
	 *
	 * @var string
	 */
	public $widget_id;


	/**
	 * the enclosed content (if the shortcode is used in its enclosing form)
	 *
	 * @var string
	 */
	public $content;


	/**
	 * Name Of Shortcode Used In VC
	 *
	 * @var string
	 */
	public $name = '';


	/**
	 * Description Of Shortcode Used In VC
	 *
	 * @var string
	 */
	public $description = '';


	/**
	 * Icon URL Of Shortcode Used In VC
	 *
	 * @var string
	 */
	public $icon = '';


	/**
	 * contains an array of attributes to add to this item
	 *
	 * @var array
	 */
	public $defaults = array();


	/**
	 * contains options for shortcode
	 *
	 * @var array
	 */
	public $options = array();


	/**
	 * Define this shortcode have widget or not
	 *
	 * @var bool
	 */
	public $have_widget = false;


	/**
	 * Define this shortcode have VC add-on
	 *
	 * @deprecated use available_in_page_builder property
	 *
	 * @var bool
	 */
	public $have_vc_add_on = false;


	/**
	 * Define this shortcode have tinymce add-on
	 *
	 * @var bool
	 */
	public $have_tinymce_add_on = false;


	/**
	 * Define this shortcode have gutenberg block
	 *
	 * @var bool
	 */
	public $have_gutenberg_add_on = false;


	/**
	 * Is shortcode available in active page builder plugin?
	 *
	 * @var bool
	 */
	public $available_in_page_builder;


	/**
	 * Constructor.
	 */
	function __construct( $id = '', $options = array() ) {

		if ( empty( $id ) ) {
			return false;
		}

		$this->id = $id;

		if ( isset( $options['defaults'] ) ) {
			$this->defaults = $options['defaults'];
			unset( $options['defaults'] );
		}

		if ( isset( $options['have_widget'] ) ) {
			$this->have_widget = $options['have_widget'];
			unset( $options['have_widget'] );
		}

		// Deprecated option use available_in_page_builder instead

		if ( isset( $options['have_vc_add_on'] ) ) {
			$this->have_vc_add_on = $options['have_vc_add_on'];

			if ( ! isset( $options['available_in_page_builder'] ) ) {
				$options['available_in_page_builder'] = $options['have_vc_add_on'];
			}

			unset( $options['have_vc_add_on'] );
		}


		if ( isset( $options['available_in_page_builder'] ) ) {

			$this->available_in_page_builder = $options['available_in_page_builder'];
		}


		if ( isset( $options['have_tinymce_add_on'] ) ) {
			$this->have_tinymce_add_on = $options['have_tinymce_add_on'];
			unset( $options['have_tinymce_add_on'] );

			if ( $this->have_tinymce_add_on ) {
				BF_Shortcodes_Manager::register_tinymce_addon( $id );
			}
		}

		if ( isset( $options['name'] ) ) {
			$this->name = $options['name'];
		}

		if ( isset( $options['have_gutenberg_add_on'] ) ) {

			$this->have_gutenberg_add_on = $options['have_gutenberg_add_on'];
			unset( $options['have_gutenberg_add_on'] );

			if ( $this->have_gutenberg_add_on ) {

				if ( ! class_exists( 'BF_Gutenberg_Shortcode_Wrapper' ) ) {

					require BF_PATH . 'gutenberg/class-bf-gutenberg-shortcode-wrapper.php';
				}

				BF_Gutenberg_Shortcode_Wrapper::register( $id, $this->page_builder_settings() );
			}
		}

		$this->options = $options;

		// Deprecated: Register VC Add-on
		if ( $this->can_register_vc_add_on() ) {

			$this->register_vc_add_on();
		}

		if ( $this->available_in_page_builder ) {

			$this->register_in_page_builder();
		}
	}


	/**
	 * Determines need to register visual composer add-on
	 *
	 * @return bool
	 */
	public function can_register_vc_add_on() {

		if ( ! $this->have_vc_add_on ) {
			return false;
		}

		if ( ! is_user_logged_in() || ! defined( 'WPB_VC_VERSION' ) ) {
			return false;
		}

		$register = false;

		if ( is_admin() ) {
			$register = bf_is_doing_ajax( 'vc_edit_form' ) || ! bf_is_doing_ajax();
		} elseif ( function_exists( 'vc_is_inline' ) && vc_is_inline() ) { // Fix for vc inline editor
			$register = true;
		}

		return $register;
	}


	/**
	 * Registers Visual Composer Add-on
	 *
	 * Must override in child classes
	 *
	 * @deprecated it's just for backward compatibility, please override page_builder_settings() instead.
	 */
	function register_vc_add_on() {

		return false;
	}


	/**
	 * @since 3.8.0
	 * @return array
	 */
	public function page_builder_settings() {

		return array(
			'id'       => $this->id,
			'name'     => $this->name,
			'desc'     => $this->description,
			'icon_url' => isset( $this->options['icon_url'] ) ? $this->options['icon_url'] : false
		);
	}


	/**
	 * Add shortcode to page builder elements list.
	 *
	 * @since 3.8.0
	 * @return bool true on success
	 */
	public function register_in_page_builder() {

		/**
		 * @var BF_Page_Builder_Extender $page_builder
		 */
		$page_builder = Better_Framework::factory( 'page-builder' );

		Better_Framework::factory( 'page-builder', false, true );

		foreach ( \BF_Page_Builder_Extender::active_page_builders() as $id ) {

			if ( ! $wrapper_class = $page_builder->wrapper_class( $id ) ) {
				return false;
			}

			if ( $hook = call_user_func( array( $wrapper_class, 'register_map_hook' ) ) ) {

				add_action( $hook, array( $this, 'register_map' ) );

			} else {

				$this->register_map( $wrapper_class );
			}
		}

		return true;
	}


	public function register_map( $wrapper_class ) {

		/**
		 * @var BF_Page_Builder_Wrapper $wrapper
		 */
		$wrapper  = new $wrapper_class();
		$settings = $this->page_builder_settings();

		if ( ! isset( $settings['icon'] ) && isset( $settings['id'] ) ) {
			$settings['icon'] = $settings['id'] . '-icon';
		}

		// normalize data
		if ( isset( $settings['base'] ) ) {

			$settings['id'] = $settings['base'];

			unset( $settings['base'] );
		}

		$wrapper->register_map(
			$settings,
			$this->page_builder_fields( $wrapper->unique_id() )
		);
	}


	/**
	 * Prepares shortcodes atts
	 *
	 * @param &$atts
	 */
	function prepare_atts( &$atts ) {

		// king composer __empty__ value fix

		$atts = array_filter( $atts, array( $this, 'filter_kc_empty' ) );

		$class = bf_shortcode_custom_css_class( $atts );
		if ( ! empty( $atts['css-class'] ) ) {
			$atts['css-class'] .= ' ' . $class;
		} else {
			$atts['css-class'] = $class;
		}

		if ( isset( $atts['bs-show-desktop'] ) && ! $atts['bs-show-desktop'] ) {
			$atts['css-class'] .= ' bs-hidden-lg';
		}

		if ( isset( $atts['bs-show-tablet'] ) && ! $atts['bs-show-tablet'] ) {
			$atts['css-class'] .= ' bs-hidden-md';
		}

		if ( isset( $atts['bs-show-phone'] ) && ! $atts['bs-show-phone'] ) {
			$atts['css-class'] .= ' bs-hidden-sm';
		}

		if ( ! empty( $atts['bs-text-color-scheme'] ) ) {
			$atts['css-class'] .= " bs-{$atts['bs-text-color-scheme']}-scheme";
		}
	}


	/**
	 * @param mixed $value
	 *
	 * @return bool
	 */
	protected function filter_kc_empty( $value ) {

		return '__empty__' !== $value;
	}


	/**
	 * Handle shortcode
	 *
	 * @param $atts
	 * @param $content
	 *
	 * @return string
	 */
	function handle_shortcode( $atts, $content ) {

		$atts = bf_merge_args( $atts, $this->defaults );

		$this->prepare_atts( $atts );

		$atts['shortcode-id'] = $this->id; // adds shortcode id to atts for using it inside filters

		// customize atts from outside
		$atts = apply_filters( 'better-framework/shortcodes/atts', $atts, $this->id );

		return $this->display( $atts, $content );
	}


	/**
	 * Handle widget display
	 *
	 * @param $atts
	 *
	 * @return string
	 */
	function handle_widget( $atts ) {

		$atts = bf_merge_args( $atts, $this->defaults );

		$this->prepare_atts( $atts );

		// customize atts from outside
		$atts = apply_filters( 'better-framework/widgets/atts', $atts, $this->id );

		return $this->display( $atts );

	}


	/**
	 * This function must override in child's for displaying results
	 *
	 * @param $atts
	 * @param $content
	 *
	 * @return string
	 */
	function display( array $atts, $content = '' ) {

		return '';
	}


	/**
	 * Method returns a proper array of attributes
	 */
	function get_atts( $atts ) {

		return bf_merge_args( $atts, $this->defaults );
	}


	/**
	 * Method returns a string of attributes
	 *
	 */
	function get_atts_string( $atts ) {

		$attr = '';

		foreach ( $this->get_atts( $atts ) as $key => $value ) {
			$attr .= " $key='" . trim( $value ) . "'";
		}

		return $attr;
	}


	/**
	 * Method returns the completed shortcode as a string
	 */
	function do_shortcode( $atts = array(), $content = '', $echo = false ) {

		//initializing
		$attrs = $this->get_atts_string( $atts );

		if ( $this->content ) {
			$content = $this->content . "[/$this->id]";
		}

		ob_start();
		echo do_shortcode( "[$this->id $attrs]$content" );
		$output = ob_get_clean();

		if ( $echo ) {
			echo $output; // escaped before

			return '';
		}

		return $output;
	}


	/**
	 * Load widget for shortcode
	 */
	function load_widget() {

		if ( $this->widget_id ) {
			BF_Widgets_Manager::register_widget_for_shortcode( $this->id, $this->options );
		} else {
			BF_Widgets_Manager::register_widget_for_shortcode( $this->id, $this->options );
		}
	}


	/**
	 * Get fields config array
	 *
	 * @inheritdoc This method must override in subclass
	 *
	 * @since      3.0.0
	 * @return array
	 */
	public function get_fields() {

		return array();
	}

	public function gutenberg_live_edit() {

		return '';
	}

	/**
	 * @return array
	 */
	public function gutenberg_attributes() {

		return array();
	}


	/**
	 * Maps all listing VC params
	 *
	 * @param string $page_builder_id
	 *
	 * @since 3.8.0
	 * @return array
	 */
	public function page_builder_fields( $page_builder_id ) {

		/**
		 * @var BF_Page_Builder_Extender $page_builder
		 */
		$page_builder = Better_Framework::factory( 'page-builder' );
		$fields       = $page_builder->transform( $page_builder_id, $this->get_fields(), $this->defaults );

		if ( $fields && ! is_wp_error( $fields ) ) {
			return $fields;
		}


		return array();
	}


	/**
	 * @see        page_builder_fields
	 *
	 * @deprecated it's just for backward compatibility, please use page_builder_fields() instead.
	 * @return array
	 */
	public function vc_map_listing_all() {

		return $this->page_builder_fields( 'VC' );
	}


	/**
	 * Tinymce View Settings
	 *
	 * @return array {
	 *
	 * @type string $name           name of the shortcode
	 * @type array  $scripts        dedicated scripts for the shortcode. array like bf_enqueue_tinymce_style() return
	 *       values
	 * @type array  $style          dedicated styles  for the shortcode. array like bf_enqueue_tinymce_style() return
	 *       values
	 *
	 * @type array  $sub_shortcodes information to insert a new shortcode inside the
	 *                               main one EX:[tabs] [tab][/tab] [/tabs].   array{
	 *      'repeater field id' => 'shortcodeName',
	 *      ...
	 *
	 *      EX: array(
	 *       'single_tab_settings' => 'tab'
	 *      )
	 *      it will we collect each repeater item, and the create [tab attr1=a attr2=b]
	 * }
	 * }
	 */
	public function tinymce_settings() {

		return array();
	}
}
libs/better-framework/shortcode/class-bf-shortcodes-manager.php000064400000040667151214002540020744 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Manage all shortcode element registration
 */
class BF_Shortcodes_Manager {


	/**
	 * Contain All shortcodes
	 *
	 * @var array
	 */
	public static $shortcodes = array();


	/**
	 * Instances of all BetterFramework active shortcode
	 *
	 * @var array
	 */
	private static $shortcode_instances = array();

	/**
	 * Store tinymce view shortcodes
	 *
	 * @var array
	 *
	 * @since 3.0.0
	 */
	static $tinymce_shortcodes = array();

	/**
	 * Store tinymce view shortcodes
	 *
	 * @var array
	 *
	 * @since 3.0.0
	 */
	static $tinymce_extra_enqueues = array();

	/**
	 * @var array
	 */
	static $tinymce_shortcode_info = array();


	function __construct() {

		// Base class for all shortcodes
		if ( ! class_exists( 'BF_Shortcode' ) ) {
			include BF_PATH . 'shortcode/class-bf-shortcode.php';
		}

		// Filter active shortcodes
		self::load_shortcodes();

		// Initialize active shortcodes
		self::init_shortcodes();

		// Add widgets
		add_action( 'widgets_init', array( __CLASS__, 'load_widgets' ) );

		add_action( 'better-framework/shortcodes/tinymce-fields', array( __CLASS__, 'print_tinymce_fields' ), 11, 2 );
		add_action( 'better-framework/shortcodes/tinymce-view-shortcode', array(
			__CLASS__,
			'tinymce_view_bulk_shortcodes'
		), 11, 2 );

		add_action( 'admin_footer', array( __CLASS__, 'enqueue_tinymce_add_on_scripts' ) );

		// Fire-up gutenberg middleware

		$this->gutenberg_compatibility();
	}


	/**
	 * Get active short codes from bf_active_shortcodes filter
	 */
	public static function load_shortcodes() {

		self::$shortcodes = apply_filters( 'better-framework/shortcodes', array() );

	}


	/**
	 * Initialize active shortcodes
	 *
	 * @param bool $instance
	 */
	public static function init_shortcodes( $instance = false ) {

		foreach ( self::$shortcodes as $key => $shortcode ) {

			self::factory( $key, $shortcode, $instance );
		}
	}


	/**
	 * @param string $base_widget_id
	 *
	 * @return bool
	 */
	public static function can_init_vc_shortcodes( $base_widget_id = '' ) {

		$result = false;

		if ( is_admin() ) {
			if ( bf_is_doing_ajax( 'vc_edit_form' ) || ! bf_is_doing_ajax() ) {
				$result = true;
			} elseif ( // is save-widget request
				! empty( $_REQUEST['action'] ) && $_REQUEST['action'] === 'save-widget' &&
				! empty( $_REQUEST['widget-id'] ) && ! empty( $_REQUEST['id_base'] ) &&
				$_REQUEST['id_base'] === $base_widget_id
			) {
				$result = true;
			}
		} elseif ( bf_get_current_sidebar() ) { // fix for inside sidebar call od factory method
			$result = true;
		} elseif ( function_exists( 'vc_is_inline' ) && vc_is_inline() ) { // Fix for vc inline editor
			$result = true;
		}

		return $result;
	}


	/**
	 * Check is a shortcode registered
	 *
	 * @param string $key
	 *
	 * @since 3.3.3
	 * @return bool
	 */
	public static function shortcode_exists( $key ) {

		return isset( self::$shortcodes[ $key ]['shortcode_class'] );
	}


	/**
	 * Factory For All BF Active Shortcodes
	 *
	 * @param string $key
	 * @param array  $options
	 * @param bool   $instance
	 *
	 * @return \BF_Shortcode|null
	 */
	static function factory( $key = '', $options = array(), $instance = false ) {

		if ( $key == '' ) {
			return null;
		}

		$instance = $instance || self::can_init_vc_shortcodes( $key );

		//TODO: we cannot make more than one instance of each shortcode
		//we need it for creating instance with separate attribute
		if ( isset( self::$shortcode_instances[ $key ] ) ) {
			return self::$shortcode_instances[ $key ];
		} else {

			//
			// Short Code That Haves Specific Handler Out Side Of BF
			//
			if ( isset( self::$shortcodes[ $key ]['shortcode_class'] ) ) {

				// Create instance for shortcode class
				if ( $instance ) {

					$class = self::$shortcodes[ $key ]['shortcode_class'];

					self::$shortcode_instances[ $key ] = new $class( $key, self::$shortcodes[ $key ] );

					// register shortcode and be theme check plugin friend
					call_user_func(
						'add' . '_' . 'shortcode',
						self::$shortcode_instances[ $key ]->id,
						array(
							self::$shortcode_instances[ $key ],
							'handle_shortcode'
						)
					);

					return self::$shortcode_instances[ $key ];
				}

				// register shortcode and be theme check plugin friend
				call_user_func( 'add' . '_' . 'shortcode', $key, array( __CLASS__, 'handle_shortcodes' ) );

				return null;
			}

			//
			// Active Shortcodes In Inner BF
			//
			$class = bf_convert_string_to_class_name( $key, 'BF_', '_Shortcode' );

			if ( ! class_exists( $class ) ) {
				if ( file_exists( bf_get_dir( 'shortcode/shortcodes/class-bf-' . $key . '-shortcode.php' ) ) ) {
					include 'shortcode/shortcodes/class-bf-' . $key . '-shortcode.php';
				}
			}

			self::$shortcode_instances[ $key ] = new $class( $key, $options );

			return self::$shortcode_instances[ $key ];
		}
	}


	/**
	 * Handle shortcodes wrapper
	 *
	 * @param $atts
	 * @param $content
	 * @param $shortcode_id
	 *
	 * @return string
	 */
	public static function handle_shortcodes( $atts, $content, $shortcode_id ) {

		if ( isset( self::$shortcode_instances[ $shortcode_id ] ) ) {
			return self::$shortcode_instances[ $shortcode_id ]->handle_shortcode( $atts, $content );
		}

		// if this shortcode is not valid
		if ( empty( self::$shortcodes[ $shortcode_id ]['shortcode_class'] ) ) {
			return '';
		}

		$class = self::$shortcodes[ $shortcode_id ]['shortcode_class'];

		self::$shortcode_instances[ $shortcode_id ] = new $class( $shortcode_id, self::$shortcodes[ $shortcode_id ] );

		return self::$shortcode_instances[ $shortcode_id ]->handle_shortcode( $atts, $content );
	}


	/**
	 * Load widget for shortcode
	 */
	public static function load_widgets() {

		foreach ( self::$shortcodes as $key => $shortcode ) {

			if ( isset( $shortcode['widget_class'] ) && class_exists( $shortcode['widget_class'] ) && is_subclass_of( $shortcode['widget_class'], 'WP_Widget' ) ) {
				register_widget( $shortcode['widget_class'] );
			}
		}
	}


	/**
	 * @param string $shortcode
	 * @param array  $settings
	 */
	public static function register_tinymce_addon( $shortcode, $settings = array() ) {

		self::$tinymce_shortcodes[] = $shortcode;
	}


	/**
	 *
	 */
	public static function enqueue_tinymce_add_on_scripts() {

		global $post;

		if ( self::$tinymce_shortcodes ) {

			if ( empty( $post->ID ) || get_post_meta( $post->ID, '_wpb_vc_js_status', true ) !== 'true' ) {

				$shortcodes = array();

				foreach ( self::$tinymce_shortcodes as $shortcode ) {

					if ( isset( self::$shortcode_instances[ $shortcode ] ) ) {

						$settings = self::$shortcode_instances[ $shortcode ]->tinymce_settings();

						$shortcodes[] = compact( 'shortcode', 'settings' );
					}
				}

				if ( version_compare( '5.3', PHP_VERSION, '>' ) ) {
					$doshortcode_steps = 3;
				} elseif ( version_compare( '5.4', PHP_VERSION, '>' ) ) {
					$doshortcode_steps = 4;
				} elseif ( version_compare( '5.5', PHP_VERSION, '>' ) ) {
					$doshortcode_steps = 5;
				} elseif ( version_compare( '7.0', PHP_VERSION, '<=' ) ) {
					$doshortcode_steps = 10;
				} elseif ( version_compare( '5.5', PHP_VERSION, '<=' ) ) {
					$doshortcode_steps = 8;
				} else {
					$doshortcode_steps = 3;
				}

				bf_enqueue_script( 'tinymce-addon' );
				bf_localize_script( 'tinymce-addon', 'BF_TinyMCE_View', array(
					'shortcodes' => $shortcodes,
					'l10n'       => array(
						'modal' => array(
							'header' => __( '%shortcode% Settings', 'better-studio' ),
						)
					),

					'doshortcode_steps' => $doshortcode_steps
				) );
			}
		}
	}


	public static function print_tinymce_fields( $main_shortcode, $args ) {

		if ( ! ( $instance = self::factory( $main_shortcode, array(), true ) ) || ! $instance->have_tinymce_add_on ) {
			wp_send_json_error();
		}

		$item_values = empty( $args['shortcode_values'] ) ? array() : $args['shortcode_values'];

		/**
		 * Fill $item_values with sub-shortcodes information to enable user to edit them
		 */
		$shortcode_settings = $instance->tinymce_settings();

		if ( ! empty( $item_values['innercontent'] ) && ! empty( $shortcode_settings['sub_shortcodes'] ) ) {

			$item_values['innercontent'] = wp_unslash( $item_values['innercontent'] );

			$fields = array();
			foreach ( $instance->get_fields() as $field ) {
				$fields[ $field['id'] ] = $field;
			}

			// Parse shortcodes in inner-content
			if ( preg_match_all( '@\[([^<>&/\[\]\x00-\x20=]++)@', $item_values['innercontent'], $matches ) ) {
				global $shortcode_tags;

				$shortcode_tags_org = $shortcode_tags;
				$shortcodes_list    = array_unique( $matches[1] ); // list of shortcodes exits in the content
				foreach ( $shortcodes_list as $_shortcode ) {
					$shortcode_tags[ $_shortcode ] = array( __CLASS__, 'collect_shortcode_info' );
				}
				$shortcodes_list = null;

				$info = &BF_Shortcodes_Manager::$tinymce_shortcode_info;
				$info = array();
				do_shortcode( $item_values['innercontent'] );
				$shortcode_tags = $shortcode_tags_org;

				$shortcode_content_keys = array();

				/**
				 * Append found data to $item_values
				 *
				 * @see BF_Shortcode::tinymce_settings for more information
				 */
				foreach ( $shortcode_settings['sub_shortcodes'] as $field_key => $_shortcode ) {
					if ( empty( $info[ $_shortcode ] ) ) {
						continue;
					}

					if ( ! isset( $shortcode_content_keys[ $field_key ] ) ) {

						if ( ! empty( $fields[ $field_key ]['options'] ) ) {

							foreach ( $fields[ $field_key ]['options'] as $_option ) {
								if ( ! empty( $_option['shortcode_content'] ) ) {
									$shortcode_content_keys[ $field_key ] = $_option['id'];
									break;
								}
							}
						}
					}

					foreach ( $info[ $_shortcode ] as $_shortcode_info ) {
						// Single repeater item value
						$repeater_item_values = $_shortcode_info['atts'];
						if ( ! empty( $shortcode_content_keys[ $field_key ] ) ) {
							$repeater_item_values[ $shortcode_content_keys[ $field_key ] ] = $_shortcode_info['content'];
						}

						$item_values[ $field_key ][] = $repeater_item_values;
					}
				}
			}
		} elseif ( empty( $shortcode_settings['sub_shortcodes'] ) && isset( $item_values['innercontent'] ) ) {


			$item_values['_content']     = $item_values['innercontent'];
			$item_values['innercontent'] = '';

		}

		if ( ! class_exists( 'BF_Tinymce_View_Field_Generator' ) ) {
			require BF_PATH . 'tinymce/class-bf-tinymce-view-field-generator.php';
		}

		$items = array(
			'fields' => $instance->get_fields(),
		);

		ob_start();
		$generator = new BF_Tinymce_View_Field_Generator( $items, $main_shortcode, $item_values );
		$generator->output();

		wp_send_json_success( array(
			'output'   => ob_get_clean(),
			'settings' => array(
				'shortcode_content_fields' => $generator->shortcode_content_fields,
			)
		) );
	}


	public static function collect_shortcode_info( $atts, $content, $shortcode ) {

		BF_Shortcodes_Manager::$tinymce_shortcode_info[ $shortcode ][] = compact( 'atts', 'content' );
	}


	/**
	 * @param array $shortcodes
	 * @param array $args
	 */
	public static function tinymce_view_bulk_shortcodes( $shortcodes, $args ) {

		if ( empty( $args['post_id'] ) || ! is_array( $shortcodes ) ) {
			wp_send_json_error();
		}


		ob_start(); // Some stupid third-party plugins print stuff in `wp_enqueue_scripts` hook
		do_action( 'wp_enqueue_scripts' );
		ob_end_clean();


		$output = array();

		foreach ( $shortcodes as $shortcode ) {
			if ( isset( $shortcode['shortcode'] ) && isset( $shortcode['id'] ) ) {
				$output [ $shortcode['id'] ] = self::tinymce_view_shortcode( $shortcode['shortcode'], $args['post_id'] );
			}
		}

		wp_send_json_success( $output );
	}


	public static function tinymce_view_shortcode( $shortcode, $post_id = 0 ) {

		global $post;

		if ( preg_match( '#^\s*\[\s*([^\s\]]+)#', $shortcode, $match ) ) {
			$shortcode_name = $match[1];
		} else {
			$shortcode_name = $shortcode;
		}

		if ( ! $instance = self::factory( $shortcode_name, array(), true ) ) {
			return array();
		}

		if ( $post_id ) {
			$post = get_post( (int) $post_id );
		}

		if ( $post && current_user_can( 'edit_post', $post->ID ) ) {
			setup_postdata( $post );
		}

		$parsed = do_shortcode( wpautop( $shortcode ) );

		if ( empty( $parsed ) ) {
			return array(
				'type'    => 'no-items',
				'message' => __( 'No items found.', 'better-studio' ),
			);
		}

		$s = $instance->tinymce_settings();

		if ( isset( self::$tinymce_extra_enqueues['styles'] ) ) {

			if ( ! isset( $s['styles'] ) ) {
				$s['styles'] = array();
			}

			$s['styles'] = array_merge( self::$tinymce_extra_enqueues['styles'], $s['styles'] );
		}
		if ( isset( self::$tinymce_extra_enqueues['scripts'] ) ) {

			if ( ! isset( $s['scripts'] ) ) {
				$s['scripts'] = array();
			}

			$s['scripts'] = array_merge( self::$tinymce_extra_enqueues['scripts'], $s['scripts'] );
		}

		//
		// Handle Scripts
		//
		$scripts_output = '';

		if ( ! empty( $s['scripts'] ) ) {

			if ( bf_booster_is_active( 'minify-js' ) ) {
				bf_scripts()->done = array();
			} else {
				wp_scripts()->done = array();
			}

			ob_start();

			$inline_scripts = '';
			foreach ( $s['scripts'] as $idx => $script ) {

				if ( $script['type'] === 'inline' ) {
					$inline_scripts .= $script['data'];
					$inline_scripts .= "\n";
				} elseif ( $script['type'] === 'custom' ) {
					bf_scripts()->print_script( $script['url'], 'custom-script-' . $idx );
				} elseif ( ! empty( $script['handles'] ) ) {
					bf_print_scripts( $script['handles'] );
				}
			}
			$scripts_output .= ob_get_contents();
			if ( $inline_scripts ) {
				$scripts_output .= ' <script> ' . $inline_scripts . ' </script> ';
			}
			$inline_scripts = null;

			ob_end_clean();
		}

		//
		// Handle Styles
		//
		$styles_output = '';

		if ( ! empty( $s['styles'] ) ) {

			if ( bf_booster_is_active( 'minify-css' ) ) {
				bf_styles()->done = array();
			} else {
				wp_styles()->done = array();
			}

			ob_start();

			$inline_styles = '';
			foreach ( $s['styles'] as $idx => $style ) {

				if ( $style['type'] === 'inline' ) {
					$inline_styles .= $style['data'];
					$inline_styles .= "\n";
				} elseif ( $style['type'] === 'custom' ) {
					bf_styles()->print_style( $style['url'], 'custom-stylesheet-' . $idx );
				} elseif ( $style['type'] === 'extra' ) {

					foreach ( $style['handles'] as $id ) {

						if ( $css = bf_styles()->get_extra_css( $id ) ) {

							if ( $css['type'] === 'file' ) {
								BF_Styles::print_style( $css['data'], $id );
							} elseif ( $css['type'] === 'inline' ) {
								$inline_styles .= $css['data'];
								$inline_styles .= "\n";
							}
						}
					}
				} elseif ( ! empty( $style['handles'] ) ) {
					bf_print_styles( $style['handles'] );
				}
			}

			$styles_output .= ob_get_contents();

			if ( $inline_styles ) {
				$styles_output .= ' <style> ' . $inline_styles . ' </style> ';
			}
			$inline_styles = null;

			ob_end_clean();
		}

		// FIX: support for external stylesheet
		if ( stristr( $styles_output, '<link ' ) && ! $scripts_output ) {
			$scripts_output .= '<script></script>';
		}

		return array(
			'head' => $styles_output,
			'body' => $parsed . $scripts_output,
		);
	}


	/**
	 * @return array
	 */
	public static function shortcodes_list() {

		return self::$shortcodes;
	}


	/**
	 * Fire-up gutenberg compatibility classes.
	 *
	 * @since 3.9.1
	 */
	public function gutenberg_compatibility() {

		global $pagenow;

		if ( ! in_array( $pagenow, array( 'post.php', 'post-new.php' ), true )
		     &&
		     is_admin()
		     &&
		     ! bf_is_block_render_request()
		     &&
		     ! bf_is_doing_ajax( 'bf_ajax' ) ) {
			return;
		}

		if ( ! class_exists( 'BF_Gutenberg_Shortcode_Wrapper' ) ) {
			require BF_PATH . 'gutenberg/class-bf-gutenberg-shortcode-wrapper.php';
		}

		BF_Gutenberg_Shortcode_Wrapper::instance();

		add_action( 'init', array( $this, 'gutenberg_register_block' ) );

	}


	public function gutenberg_register_block() {

		foreach ( self::$shortcodes as $shortcode => $_ ) {

			BF_Gutenberg_Shortcode_Wrapper::register_block( $shortcode );
		}
	}
}
libs/better-framework/libs/icons/class-bf-icons-factory.php000064400000005544151214002540020004 0ustar00<?php


/**
 * Handles generation off all icons
 */
class BF_Icons_Factory {

	/**
	 * Inner array of icons instances
	 *
	 * @var array
	 */
	private static $instances = array();


	private static $custom_icons_id = 'bf_custom_icons_list';


	/**
	 * @return string
	 */
	public static function get_custom_icons_id() {

		return self::$custom_icons_id;
	}


	/**
	 * @param string $custom_icons_id
	 */
	public static function set_custom_icons_id( $custom_icons_id ) {

		self::$custom_icons_id = $custom_icons_id;
	}


	/**
	 * Init
	 */
	function __construct() {

		if ( is_admin() ) {
			add_action( 'better-framework/icons/add-custom-icon', array( $this, 'add_custom_icon' ) );
			add_action( 'better-framework/icons/remove-custom-icon', array( $this, 'remove_custom_icon' ) );
		}
	}


	/**
	 * Handles custom icon add action
	 *
	 * @param $icon
	 */
	function add_custom_icon( $icon ) {

		$icons_list = get_option( self::get_custom_icons_id() );

		if ( $icons_list == false ) {
			$icons_list = array();
		}

		$icon['id'] = 'icon-' . uniqid();

		$icons_list[ $icon['id'] ] = $icon;

		update_option( self::get_custom_icons_id(), $icons_list, 'no' );

		die( json_encode(
			array(
				'status' => 'success',
				'msg'    => __( 'Icon added successfully', 'better-studio' ),
				'icon'   => $icon,
			)
		) );

	}


	/**
	 * Handles custom icon upload action
	 *
	 * @param $icon_id
	 */
	function remove_custom_icon( $icon_id ) {

		$icons_list = get_option( self::get_custom_icons_id() );

		if ( $icons_list != false && isset( $icons_list[ $icon_id ] ) ) {
			unset( $icons_list[ $icon_id ] );
			update_option( self::get_custom_icons_id(), $icons_list, 'no' );
		}

		die( json_encode(
			array(
				'status' => 'success',
				'msg'    => __( 'Icon removed successfully', 'better-studio' ),
				'icon'   => $icon_id,
			)
		) );

	}


	/**
	 * used for getting instance of a type of icons
	 *
	 * @param string $icon
	 *
	 * @return BF_Fontawesome|BF_BS_Icons
	 */
	public static function getInstance( $icon = '' ) {

		if ( isset( self::$instances[ $icon ] ) ) {
			return self::$instances[ $icon ];
		}

		if ( empty( $icon ) ) {
			return false;
		}

		$_icon = $icon;

		// class name
		if ( $icon == 'bs-icons' ) {
			$icon = 'BS_Icons';
		} else {
			$icon = ucfirst( $icon );
		}

		if ( ! class_exists( 'BF_' . $icon ) ) {
			require_once BF_PATH . 'libs/icons/class-bf-' . $_icon . '.php';
		}

		// Init icon library
		$class                    = 'BF_' . $icon;
		self::$instances[ $icon ] = new $class;

		return self::$instances[ $icon ];
	}


	/**
	 * DEPRECATED: use bf_get_icon_tag function.
	 *
	 * Handy function for creating icon tag from id
	 *
	 * @param        $icon
	 * @param string $class
	 *
	 * @deprecated use bf_get_icon_tag function
	 *
	 * @return string
	 */
	public function get_icon_tag_from_id( $icon, $class = '' ) {

		return bf_get_icon_tag( $icon, $class );
	}

}libs/better-framework/libs/icons/class-bf-bs-icons.php000064400000024336151214002540016741 0ustar00<?php


/**
 * Used for handling all actions about BS Icons in PHP
 */
class BF_BS_Icons {

	/**
	 * List of all icons
	 *
	 * @var array
	 */
	public $icons = array();


	/**
	 * List of all categories
	 *
	 * @var array
	 */
	public $categories = array();


	/**
	 * Version on current BS Font Icons
	 *
	 * @var string
	 */
	public $version = '1.0.0';


	function __construct() {

		// Categories

		$this->categories = array(
			'bs-cat-1' => array(
				'id'    => 'bs-cat-1',
				'label' => 'BS Icons'
			),
		);

		$this->icons = array(
			'bsfi-facebook'     => array(
				'label'     => 'Facebook',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b000',
			),
			'bsfi-twitter'      => array(
				'label'     => 'Twitter',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b001',
			),
			'bsfi-dribbble'     => array(
				'label'     => 'Dribbble',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b002',
			),
			'bsfi-vimeo'        => array(
				'label'     => 'Viemo',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b003',
			),
			'bsfi-rss'          => array(
				'label'     => 'RSS',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b004',
			),
			'bsfi-github'       => array(
				'label'     => 'Github',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b005',
			),
			'bsfi-vk'           => array(
				'label'     => 'VK',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b006',
			),
			'bsfi-delicious'    => array(
				'label'     => 'Delicious',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b007',
			),
			'bsfi-youtube'      => array(
				'label'     => 'Youtube',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b008',
			),
			'bsfi-soundcloud'   => array(
				'label'     => 'SoundCloud',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b009',
			),
			'bsfi-behance'      => array(
				'label'     => 'Behance',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b00a',
			),
			'bsfi-pinterest'    => array(
				'label'     => 'Pinterest',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b00b',
			),
			'bsfi-vine'         => array(
				'label'     => 'Vine',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b00c',
			),
			'bsfi-steam'        => array(
				'label'     => 'Steam',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b00d',
			),
			'bsfi-flickr'       => array(
				'label'     => 'Flickr',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b00e',
			),
			'bsfi-envato'       => array(
				'label'     => 'Envato',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b00f',
			),
			'bsfi-forrst'       => array(
				'label'     => 'Forrst',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b010',
			),
			'bsfi-mailchimp'    => array(
				'label'     => 'MailChimp',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b011',
			),
			'bsfi-linkedin'     => array(
				'label'     => 'Linkedin',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b012',
			),
			'bsfi-tumblr'       => array(
				'label'     => 'Tumblr',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b013',
			),
			'bsfi-500px'        => array(
				'label'     => '500px',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b014',
			),
			'bsfi-members'      => array(
				'label'     => 'Members',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b015',
			),
			'bsfi-comments'     => array(
				'label'     => 'Comments',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b016',
			),
			'bsfi-posts'        => array(
				'label'     => 'Posts',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b017',
			),
			'bsfi-instagram'    => array(
				'label'     => 'Instagram',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b018',
			),
			'bsfi-whatsapp'     => array(
				'label'     => 'Whatsapp',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b019',
			),
			'bsfi-line'         => array(
				'label'     => 'Line',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b01a',
			),
			'bsfi-blackberry'   => array(
				'label'     => 'BlackBerry',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b01b',
			),
			'bsfi-viber'        => array(
				'label'     => 'Viber',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b01c',
			),
			'bsfi-skype'        => array(
				'label'     => 'Skype',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b01d',
			),
			'bsfi-gplus'        => array(
				'label'     => 'Google Plus',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b01e',
			),
			'bsfi-telegram'     => array(
				'label'     => 'Telegram',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b01f',
			),
			'bsfi-apple'        => array(
				'label'     => 'Apple',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b020',
			),
			'bsfi-android'      => array(
				'label'     => 'Android',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b021',
			),
			'bsfi-fire-1'       => array(
				'label'     => 'Fire 1',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b022',
			),
			'bsfi-fire-2'       => array(
				'label'     => 'Fire 2',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b023',
			),
			'bsfi-fire-3'       => array(
				'label'     => 'Fire 3',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b026',
			),
			'bsfi-fire-4'       => array(
				'label'     => 'Fire 4',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b027',
			),
			'bsfi-betterstudio' => array(
				'label'     => 'BetterStudio',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b025',
			),
			'bsfi-publisher'    => array(
				'label'     => 'Publisher',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b024',
			),
			'bsfi-google'       => array(
				'label'     => 'Google+ <span class="text-muted">Alias</span>',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b01e',
			),
			'bsfi-bbm'          => array(
				'label'     => 'BBM <span class="text-muted">Alias</span>',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b01b',
			),
			'bsfi-appstore'     => array(
				'label'     => 'AppStore <span class="text-muted">Alias</span>',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b020',
			),
			'bsfi-quote-1'      => array(
				'label'     => 'Quote 1',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b040',
			),
			'bsfi-quote-2'      => array(
				'label'     => 'Quote 2',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b041',
			),
			'bsfi-quote-3'      => array(
				'label'     => 'Quote 3',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b042',
			),
			'bsfi-quote-4'      => array(
				'label'     => 'Quote 4',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b043',
			),
			'bsfi-quote-5'      => array(
				'label'     => 'Quote 5',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b044',
			),
			'bsfi-quote-6'      => array(
				'label'     => 'Quote 6',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b045',
			),
			'bsfi-quote-7'      => array(
				'label'     => 'Quote 7',
				'category'  => array( 'bs-cat-1' ),
				'font_code' => '\b046',
			),
			'bsfi-quote-1'      => array(
				'label'    => 'Quote 1',
				'category' => array( 'bs-cat-1' )
			),
			'bsfi-quote-2'      => array(
				'label'    => 'Quote 2',
				'category' => array( 'bs-cat-1' )
			),
			'bsfi-quote-3'      => array(
				'label'    => 'Quote 3',
				'category' => array( 'bs-cat-1' )
			),
			'bsfi-quote-4'      => array(
				'label'    => 'Quote 4',
				'category' => array( 'bs-cat-1' )
			),
			'bsfi-quote-5'      => array(
				'label'    => 'Quote 5',
				'category' => array( 'bs-cat-1' )
			),
			'bsfi-quote-6'      => array(
				'label'    => 'Quote 6',
				'category' => array( 'bs-cat-1' )
			),
			'bsfi-quote-7'      => array(
				'label'    => 'Quote 7',
				'category' => array( 'bs-cat-1' )
			),
			'bsfi-better-amp'   => array(
				'label'    => 'Better AMP',
				'category' => array( 'bs-cat-1' )
			),
			'bsfi-ok-ru'        => array(
				'label'    => 'Okru',
				'category' => array( 'bs-cat-1' )
			),
			'bsfi-snapchat'     => array(
				'label'    => 'Snapchat',
				'category' => array( 'bs-cat-1' )
			),
			'bsfi-comments-1'   => array(
				'label'    => 'Comment 1',
				'category' => array( 'bs-cat-1' )
			),
			'bsfi-comments-2'   => array(
				'label'    => 'Comment 2',
				'category' => array( 'bs-cat-1' )
			),
			'bsfi-comments-3'   => array(
				'label'    => 'Comment 3',
				'category' => array( 'bs-cat-1' )
			),
			'bsfi-comments-4'   => array(
				'label'    => 'Comment 4',
				'category' => array( 'bs-cat-1' )
			),
			'bsfi-comments-5'   => array(
				'label'    => 'Comment 5',
				'category' => array( 'bs-cat-1' )
			),
			'bsfi-comments-6'   => array(
				'label'    => 'Comment 6',
				'category' => array( 'bs-cat-1' )
			),
			'bsfi-comments-7'   => array(
				'label'    => 'Comment 7',
				'category' => array( 'bs-cat-1' )
			),
			'bsfi-calender'     => array(
				'label'    => 'Calender',
				'category' => array( 'bs-cat-1' )
			),
		);

		// Count each category icons
		$this->countCategoriesIcons();

	}


	/**
	 * Counts icons in each category
	 */
	function countCategoriesIcons() {

		foreach ( (array) $this->icons as $icon ) {

			if ( isset( $icon['category'] ) && bf_count( $icon['category'] ) ) {

				foreach ( $icon['category'] as $key => $category ) {

					if ( ! isset( $this->categories[ $category ] ) ) {
						continue;
					}

					if ( isset( $this->categories[ $category ]['counts'] ) ) {
						$this->categories[ $category ]['counts'] = intval( $this->categories[ $category ]['counts'] ) + 1;
					} else {
						$this->categories[ $category ]['counts'] = 1;
					}
				}
			}
		}

	}


	/**
	 * Generate tag icon
	 *
	 * @param $icon_key
	 * @param $classes
	 *
	 * @return string
	 */
	function getIconTag( $icon_key, $classes = '' ) {

		$classes = apply_filters( 'better_bs_icons_classes', $classes );

		if ( ! isset( $this->icons[ $icon_key ] ) ) {
			return '';
		}

		return '<i class="bf-icon ' . $icon_key . ' ' . $classes . '"></i>';

	}
}
libs/better-framework/libs/icons/class-bf-fontawesome.php000064400000367675151214002540017573 0ustar00<?php


/**
 * Used for handling all actions about Fontawesome in PHP
 */
class BF_Fontawesome {

	/**
	 * List of all icons
	 *
	 * @var array
	 */
	public $icons = array();


	/**
	 * List of all categories
	 *
	 * @var array
	 */
	public $categories = array();


	/**
	 * Version on current Awesomefont
	 *
	 * @var string
	 */
	public $version = '4.7.0';


	function __construct() {

		// Categories


		$this->categories = array(
			1  => array(
				'id'    => 1,
				'label' => '41 New Icons In 4.7'
			),
			2  => array(
				'id'    => 2,
				'label' => 'Web Application Icons'
			),
			3  => array(
				'id'    => 3,
				'label' => 'Accessibility Icons'
			),
			4  => array(
				'id'    => 4,
				'label' => 'Hand Icons'
			),
			5  => array(
				'id'    => 5,
				'label' => 'Transportation Icons'
			),
			6  => array(
				'id'    => 6,
				'label' => 'Gender Icons'
			),
			7  => array(
				'id'    => 7,
				'label' => 'File Type Icons'
			),
			8  => array(
				'id'    => 8,
				'label' => 'Spinner Icons'
			),
			9  => array(
				'id'    => 9,
				'label' => 'Form Control Icons'
			),
			10 => array(
				'id'    => 10,
				'label' => 'Payment Icons'
			),
			11 => array(
				'id'    => 11,
				'label' => 'Chart Icons'
			),
			12 => array(
				'id'    => 12,
				'label' => 'Currency Icons'
			),
			13 => array(
				'id'    => 13,
				'label' => 'Text Editor Icons'
			),
			14 => array(
				'id'    => 14,
				'label' => 'Directional Icons'
			),
			15 => array(
				'id'    => 15,
				'label' => 'Video Player Icons'
			),
			16 => array(
				'id'    => 16,
				'label' => 'Brand Icons'
			),
			17 => array(
				'id'    => 17,
				'label' => 'Medical Icons'
			),
		);

		// Cat 1


		$this->icons = array(
			'fa-address-book'                        => array(
				'label'     => 'Address Book',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2b9',
			),
			'fa-address-book-o'                      => array(
				'label'     => 'Address Book <span class="text-muted">(Outline)</span>',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2ba',
			),
			'fa-address-card'                        => array(
				'label'     => 'Address Card',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2bb',
			),
			'fa-address-card-o'                      => array(
				'label'     => 'Address Card <span class="text-muted">(Outline)</span>',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2bc',
			),
			'fa-bandcamp'                            => array(
				'label'     => 'Bandcamp',
				'category'  => array( 1, 16 ),
				'font_code' => '\f2d5',
			),
			'fa-bath'                                => array(
				'label'     => 'Bath',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2cd',
			),
			'fa-bathtub'                             => array(
				'label'     => 'Bathtub',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2cd',
			),
			'fa-drivers-license'                     => array(
				'label'     => 'Drivers License',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2c2',
			),
			'fa-drivers-license-o'                   => array(
				'label'     => 'Drivers License <span class="text-muted">(Outline)</span>',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2c3',
			),
			'fa-eercast'                             => array(
				'label'     => 'Eercast',
				'category'  => array( 1, 16 ),
				'font_code' => '\f2da',
			),
			'fa-envelope-open'                       => array(
				'label'     => 'Envelope Open',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2b6',
			),
			'fa-envelope-open-o'                     => array(
				'label'     => 'Envelope Open <span class="text-muted">(Outline)</span>',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2b7',
			),
			'fa-etsy'                                => array(
				'label'     => 'Etsy',
				'category'  => array( 1, 16 ),
				'font_code' => '\f2d7',
			),
			'fa-free-code-camp'                      => array(
				'label'     => 'Free Code Camp',
				'category'  => array( 1, 16 ),
				'font_code' => '\f2c5',
			),
			'fa-grav'                                => array(
				'label'     => 'Grav',
				'category'  => array( 1, 16 ),
				'font_code' => '\f2d6',
			),
			'fa-handshake-o'                         => array(
				'label'     => 'Handshake <span class="text-muted">(Outline)</span>',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2b5',
			),
			'fa-id-badge'                            => array(
				'label'     => 'Id Badge',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2c1',
			),
			'fa-id-card'                             => array(
				'label'     => 'Id Card',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2c2',
			),
			'fa-id-card-o'                           => array(
				'label'     => 'Id Card <span class="text-muted">(Outline)</span>',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2c3',
			),
			'fa-imdb'                                => array(
				'label'     => 'Imdb',
				'category'  => array( 1, 16 ),
				'font_code' => '\f2d8',
			),
			'fa-linode'                              => array(
				'label'     => 'Linode',
				'category'  => array( 1, 16 ),
				'font_code' => '\f2b8',
			),
			'fa-meetup'                              => array(
				'label'     => 'Meetup',
				'category'  => array( 1, 16 ),
				'font_code' => '\f2e0',
			),
			'fa-microchip'                           => array(
				'label'     => 'Microchip',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2db',
			),
			'fa-podcast'                             => array(
				'label'     => 'Podcast',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2ce',
			),
			'fa-quora'                               => array(
				'label'     => 'Quora',
				'category'  => array( 1, 16 ),
				'font_code' => '\f2c4',
			),
			'fa-ravelry'                             => array(
				'label'     => 'Ravelry',
				'category'  => array( 1, 16 ),
				'font_code' => '\f2d9',
			),
			'fa-s15'                                 => array(
				'label'     => 'S15',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2cd',
			),
			'fa-shower'                              => array(
				'label'     => 'Shower',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2cc',
			),
			'fa-snowflake-o'                         => array(
				'label'     => 'Snowflake <span class="text-muted">(Outline)</span>',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2dc',
			),
			'fa-superpowers'                         => array(
				'label'     => 'Superpowers',
				'category'  => array( 1, 16 ),
				'font_code' => '\f2dd',
			),
			'fa-telegram'                            => array(
				'label'     => 'Telegram',
				'category'  => array( 1, 16 ),
				'font_code' => '\f2c6',
			),
			'fa-thermometer'                         => array(
				'label'     => 'Thermometer',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2c7',
			),
			'fa-thermometer-0'                       => array(
				'label'     => 'Thermometer 0',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2cb',
			),
			'fa-thermometer-1'                       => array(
				'label'     => 'Thermometer 1',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2ca',
			),
			'fa-thermometer-2'                       => array(
				'label'     => 'Thermometer 2',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2c9',
			),
			'fa-thermometer-3'                       => array(
				'label'     => 'Thermometer 3',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2c8',
			),
			'fa-thermometer-4'                       => array(
				'label'     => 'Thermometer 4',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2c7',
			),
			'fa-thermometer-empty'                   => array(
				'label'     => 'Thermometer Empty',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2cb',
			),
			'fa-thermometer-full'                    => array(
				'label'     => 'Thermometer Full',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2c7',
			),
			'fa-thermometer-half'                    => array(
				'label'     => 'Thermometer Half',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2c9',
			),
			'fa-thermometer-quarter'                 => array(
				'label'     => 'Thermometer Quarter',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2ca',
			),
			'fa-thermometer-three-quarters'          => array(
				'label'     => 'Thermometer Three Quarters',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2c8',
			),
			'fa-times-rectangle'                     => array(
				'label'     => 'Times Rectangle',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2d3',
			),
			'fa-times-rectangle-o'                   => array(
				'label'     => 'Times Rectangle <span class="text-muted">(Outline)</span>',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2d4',
			),
			'fa-user-circle'                         => array(
				'label'     => 'User Circle',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2bd',
			),
			'fa-user-circle-o'                       => array(
				'label'     => 'User Circle <span class="text-muted">(Outline)</span>',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2be',
			),
			'fa-user-o'                              => array(
				'label'     => 'User <span class="text-muted">(Outline)</span>',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2c0',
			),
			'fa-vcard'                               => array(
				'label'     => 'Vcard',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2bb',
			),
			'fa-vcard-o'                             => array(
				'label'     => 'Vcard <span class="text-muted">(Outline)</span>',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2bc',
			),
			'fa-window-close'                        => array(
				'label'     => 'Window Close',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2d3',
			),
			'fa-window-close-o'                      => array(
				'label'     => 'Window Close <span class="text-muted">(Outline)</span>',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2d4',
			),
			'fa-window-maximize'                     => array(
				'label'     => 'Window Maximize',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2d0',
			),
			'fa-window-minimize'                     => array(
				'label'     => 'Window Minimize',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2d1',
			),
			'fa-window-restore'                      => array(
				'label'     => 'Window Restore',
				'category'  => array( 1, 2 ),
				'font_code' => '\f2d2',
			),
			'fa-wpexplorer'                          => array(
				'label'     => 'Wpexplorer',
				'category'  => array( 1, 16 ),
				'font_code' => '\f2de',
			),
			'fa-adjust'                              => array(
				'label'     => 'Adjust',
				'category'  => array( 2 ),
				'font_code' => '\f042',
			),
			'fa-american-sign-language-interpreting' => array(
				'label'     => 'American Sign Language Interpreting',
				'category'  => array( 2, 3 ),
				'font_code' => '\f2a3',
			),
			'fa-anchor'                              => array(
				'label'     => 'Anchor',
				'category'  => array( 2 ),
				'font_code' => '\f13d',
			),
			'fa-archive'                             => array(
				'label'     => 'Archive',
				'category'  => array( 2 ),
				'font_code' => '\f187',
			),
			'fa-area-chart'                          => array(
				'label'     => 'Area Chart',
				'category'  => array( 2, 11 ),
				'font_code' => '\f1fe',
			),
			'fa-arrows'                              => array(
				'label'     => 'Arrows',
				'category'  => array( 2, 14 ),
				'font_code' => '\f047',
			),
			'fa-arrows-h'                            => array(
				'label'     => 'Arrows H',
				'category'  => array( 2, 14 ),
				'font_code' => '\f07e',
			),
			'fa-arrows-v'                            => array(
				'label'     => 'Arrows V',
				'category'  => array( 2, 14 ),
				'font_code' => '\f07d',
			),
			'fa-asl-interpreting'                    => array(
				'label'     => 'Asl Interpreting',
				'category'  => array( 2, 3 ),
				'font_code' => '\f2a3',
			),
			'fa-assistive-listening-systems'         => array(
				'label'     => 'Assistive Listening Systems',
				'category'  => array( 2, 3 ),
				'font_code' => '\f2a2',
			),
			'fa-asterisk'                            => array(
				'label'     => 'Asterisk',
				'category'  => array( 2 ),
				'font_code' => '\f069',
			),
			'fa-at'                                  => array(
				'label'     => 'At',
				'category'  => array( 2 ),
				'font_code' => '\f1fa',
			),
			'fa-audio-description'                   => array(
				'label'     => 'Audio Description',
				'category'  => array( 2, 3 ),
				'font_code' => '\f29e',
			),
			'fa-automobile'                          => array(
				'label'     => 'Automobile',
				'category'  => array( 2, 5 ),
				'font_code' => '\f1b9',
			),
			'fa-balance-scale'                       => array(
				'label'     => 'Balance Scale',
				'category'  => array( 2 ),
				'font_code' => '\f24e',
			),
			'fa-ban'                                 => array(
				'label'     => 'Ban',
				'category'  => array( 2 ),
				'font_code' => '\f05e',
			),
			'fa-bank'                                => array(
				'label'     => 'Bank',
				'category'  => array( 2 ),
				'font_code' => '\f19c',
			),
			'fa-bar-chart'                           => array(
				'label'     => 'Bar Chart',
				'category'  => array( 2, 11 ),
				'font_code' => '\f080',
			),
			'fa-bar-chart-o'                         => array(
				'label'     => 'Bar Chart <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 11 ),
				'font_code' => '\f080',
			),
			'fa-barcode'                             => array(
				'label'     => 'Barcode',
				'category'  => array( 2 ),
				'font_code' => '\f02a',
			),
			'fa-bars'                                => array(
				'label'     => 'Bars',
				'category'  => array( 2 ),
				'font_code' => '\f0c9',
			),
			'fa-battery'                             => array(
				'label'     => 'Battery',
				'category'  => array( 2 ),
				'font_code' => '\f240',
			),
			'fa-battery-0'                           => array(
				'label'     => 'Battery 0',
				'category'  => array( 2 ),
				'font_code' => '\f244',
			),
			'fa-battery-1'                           => array(
				'label'     => 'Battery 1',
				'category'  => array( 2 ),
				'font_code' => '\f243',
			),
			'fa-battery-2'                           => array(
				'label'     => 'Battery 2',
				'category'  => array( 2 ),
				'font_code' => '\f242',
			),
			'fa-battery-3'                           => array(
				'label'     => 'Battery 3',
				'category'  => array( 2 ),
				'font_code' => '\f241',
			),
			'fa-battery-4'                           => array(
				'label'     => 'Battery 4',
				'category'  => array( 2 ),
				'font_code' => '\f240',
			),
			'fa-battery-empty'                       => array(
				'label'     => 'Battery Empty',
				'category'  => array( 2 ),
				'font_code' => '\f244',
			),
			'fa-battery-full'                        => array(
				'label'     => 'Battery Full',
				'category'  => array( 2 ),
				'font_code' => '\f240',
			),
			'fa-battery-half'                        => array(
				'label'     => 'Battery Half',
				'category'  => array( 2 ),
				'font_code' => '\f242',
			),
			'fa-battery-quarter'                     => array(
				'label'     => 'Battery Quarter',
				'category'  => array( 2 ),
				'font_code' => '\f243',
			),
			'fa-battery-three-quarters'              => array(
				'label'     => 'Battery Three Quarters',
				'category'  => array( 2 ),
				'font_code' => '\f241',
			),
			'fa-bed'                                 => array(
				'label'     => 'Bed',
				'category'  => array( 2 ),
				'font_code' => '\f236',
			),
			'fa-beer'                                => array(
				'label'     => 'Beer',
				'category'  => array( 2 ),
				'font_code' => '\f0fc',
			),
			'fa-bell'                                => array(
				'label'     => 'Bell',
				'category'  => array( 2 ),
				'font_code' => '\f0f3',
			),
			'fa-bell-o'                              => array(
				'label'     => 'Bell <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f0a2',
			),
			'fa-bell-slash'                          => array(
				'label'     => 'Bell Slash',
				'category'  => array( 2 ),
				'font_code' => '\f1f6',
			),
			'fa-bell-slash-o'                        => array(
				'label'     => 'Bell Slash <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f1f7',
			),
			'fa-bicycle'                             => array(
				'label'     => 'Bicycle',
				'category'  => array( 2, 5 ),
				'font_code' => '\f206',
			),
			'fa-binoculars'                          => array(
				'label'     => 'Binoculars',
				'category'  => array( 2 ),
				'font_code' => '\f1e5',
			),
			'fa-birthday-cake'                       => array(
				'label'     => 'Birthday Cake',
				'category'  => array( 2 ),
				'font_code' => '\f1fd',
			),
			'fa-blind'                               => array(
				'label'     => 'Blind',
				'category'  => array( 2, 3 ),
				'font_code' => '\f29d',
			),
			'fa-bluetooth'                           => array(
				'label'     => 'Bluetooth',
				'category'  => array( 2, 16 ),
				'font_code' => '\f293',
			),
			'fa-bluetooth-b'                         => array(
				'label'     => 'Bluetooth B',
				'category'  => array( 2, 16 ),
				'font_code' => '\f294',
			),
			'fa-bolt'                                => array(
				'label'     => 'Bolt',
				'category'  => array( 2 ),
				'font_code' => '\f0e7',
			),
			'fa-bomb'                                => array(
				'label'     => 'Bomb',
				'category'  => array( 2 ),
				'font_code' => '\f1e2',
			),
			'fa-book'                                => array(
				'label'     => 'Book',
				'category'  => array( 2 ),
				'font_code' => '\f02d',
			),
			'fa-bookmark'                            => array(
				'label'     => 'Bookmark',
				'category'  => array( 2 ),
				'font_code' => '\f02e',
			),
			'fa-bookmark-o'                          => array(
				'label'     => 'Bookmark <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f097',
			),
			'fa-braille'                             => array(
				'label'     => 'Braille',
				'category'  => array( 2, 3 ),
				'font_code' => '\f2a1',
			),
			'fa-briefcase'                           => array(
				'label'     => 'Briefcase',
				'category'  => array( 2 ),
				'font_code' => '\f0b1',
			),
			'fa-bug'                                 => array(
				'label'     => 'Bug',
				'category'  => array( 2 ),
				'font_code' => '\f188',
			),
			'fa-building'                            => array(
				'label'     => 'Building',
				'category'  => array( 2 ),
				'font_code' => '\f1ad',
			),
			'fa-building-o'                          => array(
				'label'     => 'Building <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f0f7',
			),
			'fa-bullhorn'                            => array(
				'label'     => 'Bullhorn',
				'category'  => array( 2 ),
				'font_code' => '\f0a1',
			),
			'fa-bullseye'                            => array(
				'label'     => 'Bullseye',
				'category'  => array( 2 ),
				'font_code' => '\f140',
			),
			'fa-bus'                                 => array(
				'label'     => 'Bus',
				'category'  => array( 2, 5 ),
				'font_code' => '\f207',
			),
			'fa-cab'                                 => array(
				'label'     => 'Cab',
				'category'  => array( 2, 5 ),
				'font_code' => '\f1ba',
			),
			'fa-calculator'                          => array(
				'label'     => 'Calculator',
				'category'  => array( 2 ),
				'font_code' => '\f1ec',
			),
			'fa-calendar'                            => array(
				'label'     => 'Calendar',
				'category'  => array( 2 ),
				'font_code' => '\f073',
			),
			'fa-calendar-check-o'                    => array(
				'label'     => 'Calendar Check <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f274',
			),
			'fa-calendar-minus-o'                    => array(
				'label'     => 'Calendar Minus <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f272',
			),
			'fa-calendar-o'                          => array(
				'label'     => 'Calendar <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f133',
			),
			'fa-calendar-plus-o'                     => array(
				'label'     => 'Calendar Plus <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f271',
			),
			'fa-calendar-times-o'                    => array(
				'label'     => 'Calendar Times <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f273',
			),
			'fa-camera'                              => array(
				'label'     => 'Camera',
				'category'  => array( 2 ),
				'font_code' => '\f030',
			),
			'fa-camera-retro'                        => array(
				'label'     => 'Camera Retro',
				'category'  => array( 2 ),
				'font_code' => '\f083',
			),
			'fa-car'                                 => array(
				'label'     => 'Car',
				'category'  => array( 2, 5 ),
				'font_code' => '\f1b9',
			),
			'fa-caret-square-o-down'                 => array(
				'label'     => 'Caret Square Down <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 14 ),
				'font_code' => '\f150',
			),
			'fa-caret-square-o-left'                 => array(
				'label'     => 'Caret Square Left <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 14 ),
				'font_code' => '\f191',
			),
			'fa-caret-square-o-right'                => array(
				'label'     => 'Caret Square Right <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 14 ),
				'font_code' => '\f152',
			),
			'fa-caret-square-o-up'                   => array(
				'label'     => 'Caret Square Up <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 14 ),
				'font_code' => '\f151',
			),
			'fa-cart-arrow-down'                     => array(
				'label'     => 'Cart Arrow Down',
				'category'  => array( 2 ),
				'font_code' => '\f218',
			),
			'fa-cart-plus'                           => array(
				'label'     => 'Cart Plus',
				'category'  => array( 2 ),
				'font_code' => '\f217',
			),
			'fa-cc'                                  => array(
				'label'     => 'Cc',
				'category'  => array( 2, 3 ),
				'font_code' => '\f20a',
			),
			'fa-certificate'                         => array(
				'label'     => 'Certificate',
				'category'  => array( 2 ),
				'font_code' => '\f0a3',
			),
			'fa-check'                               => array(
				'label'     => 'Check',
				'category'  => array( 2 ),
				'font_code' => '\f00c',
			),
			'fa-check-circle'                        => array(
				'label'     => 'Check Circle',
				'category'  => array( 2 ),
				'font_code' => '\f058',
			),
			'fa-check-circle-o'                      => array(
				'label'     => 'Check Circle <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f05d',
			),
			'fa-check-square'                        => array(
				'label'     => 'Check Square',
				'category'  => array( 2, 9 ),
				'font_code' => '\f14a',
			),
			'fa-check-square-o'                      => array(
				'label'     => 'Check Square <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 9 ),
				'font_code' => '\f046',
			),
			'fa-child'                               => array(
				'label'     => 'Child',
				'category'  => array( 2 ),
				'font_code' => '\f1ae',
			),
			'fa-circle'                              => array(
				'label'     => 'Circle',
				'category'  => array( 2, 9 ),
				'font_code' => '\f111',
			),
			'fa-circle-o'                            => array(
				'label'     => 'Circle <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 9 ),
				'font_code' => '\f10c',
			),
			'fa-circle-o-notch'                      => array(
				'label'     => 'Circle Notch <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 8 ),
				'font_code' => '\f1ce',
			),
			'fa-circle-thin'                         => array(
				'label'     => 'Circle Thin',
				'category'  => array( 2 ),
				'font_code' => '\f1db',
			),
			'fa-clock-o'                             => array(
				'label'     => 'Clock <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f017',
			),
			'fa-clone'                               => array(
				'label'     => 'Clone',
				'category'  => array( 2 ),
				'font_code' => '\f24d',
			),
			'fa-close'                               => array(
				'label'     => 'Close',
				'category'  => array( 2 ),
				'font_code' => '\f00d',
			),
			'fa-cloud'                               => array(
				'label'     => 'Cloud',
				'category'  => array( 2 ),
				'font_code' => '\f0c2',
			),
			'fa-cloud-download'                      => array(
				'label'     => 'Cloud Download',
				'category'  => array( 2 ),
				'font_code' => '\f0ed',
			),
			'fa-cloud-upload'                        => array(
				'label'     => 'Cloud Upload',
				'category'  => array( 2 ),
				'font_code' => '\f0ee',
			),
			'fa-code'                                => array(
				'label'     => 'Code',
				'category'  => array( 2 ),
				'font_code' => '\f121',
			),
			'fa-code-fork'                           => array(
				'label'     => 'Code Fork',
				'category'  => array( 2 ),
				'font_code' => '\f126',
			),
			'fa-coffee'                              => array(
				'label'     => 'Coffee',
				'category'  => array( 2 ),
				'font_code' => '\f0f4',
			),
			'fa-cog'                                 => array(
				'label'     => 'Cog',
				'category'  => array( 2, 8 ),
				'font_code' => '\f013',
			),
			'fa-cogs'                                => array(
				'label'     => 'Cogs',
				'category'  => array( 2 ),
				'font_code' => '\f085',
			),
			'fa-comment'                             => array(
				'label'     => 'Comment',
				'category'  => array( 2 ),
				'font_code' => '\f075',
			),
			'fa-comment-o'                           => array(
				'label'     => 'Comment <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f0e5',
			),
			'fa-commenting'                          => array(
				'label'     => 'Commenting',
				'category'  => array( 2 ),
				'font_code' => '\f27a',
			),
			'fa-commenting-o'                        => array(
				'label'     => 'Commenting <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f27b',
			),
			'fa-comments'                            => array(
				'label'     => 'Comments',
				'category'  => array( 2 ),
				'font_code' => '\f086',
			),
			'fa-comments-o'                          => array(
				'label'     => 'Comments <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f0e6',
			),
			'fa-compass'                             => array(
				'label'     => 'Compass',
				'category'  => array( 2 ),
				'font_code' => '\f14e',
			),
			'fa-copyright'                           => array(
				'label'     => 'Copyright',
				'category'  => array( 2 ),
				'font_code' => '\f1f9',
			),
			'fa-creative-commons'                    => array(
				'label'     => 'Creative Commons',
				'category'  => array( 2 ),
				'font_code' => '\f25e',
			),
			'fa-credit-card'                         => array(
				'label'     => 'Credit Card',
				'category'  => array( 2, 10 ),
				'font_code' => '\f09d',
			),
			'fa-credit-card-alt'                     => array(
				'label'     => 'Credit Card Alt',
				'category'  => array( 2, 10 ),
				'font_code' => '\f283',
			),
			'fa-crop'                                => array(
				'label'     => 'Crop',
				'category'  => array( 2 ),
				'font_code' => '\f125',
			),
			'fa-crosshairs'                          => array(
				'label'     => 'Crosshairs',
				'category'  => array( 2 ),
				'font_code' => '\f05b',
			),
			'fa-cube'                                => array(
				'label'     => 'Cube',
				'category'  => array( 2 ),
				'font_code' => '\f1b2',
			),
			'fa-cubes'                               => array(
				'label'     => 'Cubes',
				'category'  => array( 2 ),
				'font_code' => '\f1b3',
			),
			'fa-cutlery'                             => array(
				'label'     => 'Cutlery',
				'category'  => array( 2 ),
				'font_code' => '\f0f5',
			),
			'fa-dashboard'                           => array(
				'label'     => 'Dashboard',
				'category'  => array( 2 ),
				'font_code' => '\f0e4',
			),
			'fa-database'                            => array(
				'label'     => 'Database',
				'category'  => array( 2 ),
				'font_code' => '\f1c0',
			),
			'fa-deaf'                                => array(
				'label'     => 'Deaf',
				'category'  => array( 2, 3 ),
				'font_code' => '\f2a4',
			),
			'fa-deafness'                            => array(
				'label'     => 'Deafness',
				'category'  => array( 2, 3 ),
				'font_code' => '\f2a4',
			),
			'fa-desktop'                             => array(
				'label'     => 'Desktop',
				'category'  => array( 2 ),
				'font_code' => '\f108',
			),
			'fa-diamond'                             => array(
				'label'     => 'Diamond',
				'category'  => array( 2 ),
				'font_code' => '\f219',
			),
			'fa-dot-circle-o'                        => array(
				'label'     => 'Dot Circle <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 9 ),
				'font_code' => '\f192',
			),
			'fa-download'                            => array(
				'label'     => 'Download',
				'category'  => array( 2 ),
				'font_code' => '\f019',
			),
			'fa-edit'                                => array(
				'label'     => 'Edit',
				'category'  => array( 2 ),
				'font_code' => '\f044',
			),
			'fa-ellipsis-h'                          => array(
				'label'     => 'Ellipsis H',
				'category'  => array( 2 ),
				'font_code' => '\f141',
			),
			'fa-ellipsis-v'                          => array(
				'label'     => 'Ellipsis V',
				'category'  => array( 2 ),
				'font_code' => '\f142',
			),
			'fa-envelope'                            => array(
				'label'     => 'Envelope',
				'category'  => array( 2 ),
				'font_code' => '\f0e0',
			),
			'fa-envelope-o'                          => array(
				'label'     => 'Envelope <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f003',
			),
			'fa-envelope-square'                     => array(
				'label'     => 'Envelope Square',
				'category'  => array( 2 ),
				'font_code' => '\f199',
			),
			'fa-eraser'                              => array(
				'label'     => 'Eraser',
				'category'  => array( 2, 13 ),
				'font_code' => '\f12d',
			),
			'fa-exchange'                            => array(
				'label'     => 'Exchange',
				'category'  => array( 2, 14 ),
				'font_code' => '\f0ec',
			),
			'fa-exclamation'                         => array(
				'label'     => 'Exclamation',
				'category'  => array( 2 ),
				'font_code' => '\f12a',
			),
			'fa-exclamation-circle'                  => array(
				'label'     => 'Exclamation Circle',
				'category'  => array( 2 ),
				'font_code' => '\f06a',
			),
			'fa-exclamation-triangle'                => array(
				'label'     => 'Exclamation Triangle',
				'category'  => array( 2 ),
				'font_code' => '\f071',
			),
			'fa-external-link'                       => array(
				'label'     => 'External Link',
				'category'  => array( 2 ),
				'font_code' => '\f08e',
			),
			'fa-external-link-square'                => array(
				'label'     => 'External Link Square',
				'category'  => array( 2 ),
				'font_code' => '\f14c',
			),
			'fa-eye'                                 => array(
				'label'     => 'Eye',
				'category'  => array( 2 ),
				'font_code' => '\f06e',
			),
			'fa-eye-slash'                           => array(
				'label'     => 'Eye Slash',
				'category'  => array( 2 ),
				'font_code' => '\f070',
			),
			'fa-eyedropper'                          => array(
				'label'     => 'Eyedropper',
				'category'  => array( 2 ),
				'font_code' => '\f1fb',
			),
			'fa-fax'                                 => array(
				'label'     => 'Fax',
				'category'  => array( 2 ),
				'font_code' => '\f1ac',
			),
			'fa-feed'                                => array(
				'label'     => 'Feed',
				'category'  => array( 2 ),
				'font_code' => '\f09e',
			),
			'fa-female'                              => array(
				'label'     => 'Female',
				'category'  => array( 2 ),
				'font_code' => '\f182',
			),
			'fa-fighter-jet'                         => array(
				'label'     => 'Fighter Jet',
				'category'  => array( 2, 5 ),
				'font_code' => '\f0fb',
			),
			'fa-file-archive-o'                      => array(
				'label'     => 'File Archive <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 7 ),
				'font_code' => '\f1c6',
			),
			'fa-file-audio-o'                        => array(
				'label'     => 'File Audio <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 7 ),
				'font_code' => '\f1c7',
			),
			'fa-file-code-o'                         => array(
				'label'     => 'File Code <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 7 ),
				'font_code' => '\f1c9',
			),
			'fa-file-excel-o'                        => array(
				'label'     => 'File Excel <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 7 ),
				'font_code' => '\f1c3',
			),
			'fa-file-image-o'                        => array(
				'label'     => 'File Image <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 7 ),
				'font_code' => '\f1c5',
			),
			'fa-file-movie-o'                        => array(
				'label'     => 'File Movie <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 7 ),
				'font_code' => '\f1c8',
			),
			'fa-file-pdf-o'                          => array(
				'label'     => 'File Pdf <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 7 ),
				'font_code' => '\f1c1',
			),
			'fa-file-photo-o'                        => array(
				'label'     => 'File Photo <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 7 ),
				'font_code' => '\f1c5',
			),
			'fa-file-picture-o'                      => array(
				'label'     => 'File Picture <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 7 ),
				'font_code' => '\f1c5',
			),
			'fa-file-powerpoint-o'                   => array(
				'label'     => 'File Powerpoint <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 7 ),
				'font_code' => '\f1c4',
			),
			'fa-file-sound-o'                        => array(
				'label'     => 'File Sound <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 7 ),
				'font_code' => '\f1c7',
			),
			'fa-file-video-o'                        => array(
				'label'     => 'File Video <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 7 ),
				'font_code' => '\f1c8',
			),
			'fa-file-word-o'                         => array(
				'label'     => 'File Word <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 7 ),
				'font_code' => '\f1c2',
			),
			'fa-file-zip-o'                          => array(
				'label'     => 'File Zip <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 7 ),
				'font_code' => '\f1c6',
			),
			'fa-film'                                => array(
				'label'     => 'Film',
				'category'  => array( 2 ),
				'font_code' => '\f008',
			),
			'fa-filter'                              => array(
				'label'     => 'Filter',
				'category'  => array( 2 ),
				'font_code' => '\f0b0',
			),
			'fa-fire'                                => array(
				'label'     => 'Fire',
				'category'  => array( 2 ),
				'font_code' => '\f06d',
			),
			'fa-fire-extinguisher'                   => array(
				'label'     => 'Fire Extinguisher',
				'category'  => array( 2 ),
				'font_code' => '\f134',
			),
			'fa-flag'                                => array(
				'label'     => 'Flag',
				'category'  => array( 2 ),
				'font_code' => '\f024',
			),
			'fa-flag-checkered'                      => array(
				'label'     => 'Flag Checkered',
				'category'  => array( 2 ),
				'font_code' => '\f11e',
			),
			'fa-flag-o'                              => array(
				'label'     => 'Flag <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f11d',
			),
			'fa-flash'                               => array(
				'label'     => 'Flash',
				'category'  => array( 2 ),
				'font_code' => '\f0e7',
			),
			'fa-flask'                               => array(
				'label'     => 'Flask',
				'category'  => array( 2 ),
				'font_code' => '\f0c3',
			),
			'fa-folder'                              => array(
				'label'     => 'Folder',
				'category'  => array( 2 ),
				'font_code' => '\f07b',
			),
			'fa-folder-o'                            => array(
				'label'     => 'Folder <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f114',
			),
			'fa-folder-open'                         => array(
				'label'     => 'Folder Open',
				'category'  => array( 2 ),
				'font_code' => '\f07c',
			),
			'fa-folder-open-o'                       => array(
				'label'     => 'Folder Open <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f115',
			),
			'fa-frown-o'                             => array(
				'label'     => 'Frown <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f119',
			),
			'fa-futbol-o'                            => array(
				'label'     => 'Futbol <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f1e3',
			),
			'fa-gamepad'                             => array(
				'label'     => 'Gamepad',
				'category'  => array( 2 ),
				'font_code' => '\f11b',
			),
			'fa-gavel'                               => array(
				'label'     => 'Gavel',
				'category'  => array( 2 ),
				'font_code' => '\f0e3',
			),
			'fa-gear'                                => array(
				'label'     => 'Gear',
				'category'  => array( 2, 8 ),
				'font_code' => '\f013',
			),
			'fa-gears'                               => array(
				'label'     => 'Gears',
				'category'  => array( 2 ),
				'font_code' => '\f085',
			),
			'fa-gift'                                => array(
				'label'     => 'Gift',
				'category'  => array( 2 ),
				'font_code' => '\f06b',
			),
			'fa-glass'                               => array(
				'label'     => 'Glass',
				'category'  => array( 2 ),
				'font_code' => '\f000',
			),
			'fa-globe'                               => array(
				'label'     => 'Globe',
				'category'  => array( 2 ),
				'font_code' => '\f0ac',
			),
			'fa-graduation-cap'                      => array(
				'label'     => 'Graduation Cap',
				'category'  => array( 2 ),
				'font_code' => '\f19d',
			),
			'fa-group'                               => array(
				'label'     => 'Group',
				'category'  => array( 2 ),
				'font_code' => '\f0c0',
			),
			'fa-hand-grab-o'                         => array(
				'label'     => 'Hand Grab <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 4 ),
				'font_code' => '\f255',
			),
			'fa-hand-lizard-o'                       => array(
				'label'     => 'Hand Lizard <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 4 ),
				'font_code' => '\f258',
			),
			'fa-hand-paper-o'                        => array(
				'label'     => 'Hand Paper <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 4 ),
				'font_code' => '\f256',
			),
			'fa-hand-peace-o'                        => array(
				'label'     => 'Hand Peace <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 4 ),
				'font_code' => '\f25b',
			),
			'fa-hand-pointer-o'                      => array(
				'label'     => 'Hand Pointer <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 4 ),
				'font_code' => '\f25a',
			),
			'fa-hand-rock-o'                         => array(
				'label'     => 'Hand Rock <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 4 ),
				'font_code' => '\f255',
			),
			'fa-hand-scissors-o'                     => array(
				'label'     => 'Hand Scissors <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 4 ),
				'font_code' => '\f257',
			),
			'fa-hand-spock-o'                        => array(
				'label'     => 'Hand Spock <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 4 ),
				'font_code' => '\f259',
			),
			'fa-hand-stop-o'                         => array(
				'label'     => 'Hand Stop <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 4 ),
				'font_code' => '\f256',
			),
			'fa-hard-of-hearing'                     => array(
				'label'     => 'Hard Of Hearing',
				'category'  => array( 2, 3 ),
				'font_code' => '\f2a4',
			),
			'fa-hashtag'                             => array(
				'label'     => 'Hashtag',
				'category'  => array( 2 ),
				'font_code' => '\f292',
			),
			'fa-hdd-o'                               => array(
				'label'     => 'Hdd <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f0a0',
			),
			'fa-headphones'                          => array(
				'label'     => 'Headphones',
				'category'  => array( 2 ),
				'font_code' => '\f025',
			),
			'fa-heart'                               => array(
				'label'     => 'Heart',
				'category'  => array( 2, 17 ),
				'font_code' => '\f004',
			),
			'fa-heart-o'                             => array(
				'label'     => 'Heart <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 17 ),
				'font_code' => '\f08a',
			),
			'fa-heartbeat'                           => array(
				'label'     => 'Heartbeat',
				'category'  => array( 2, 17 ),
				'font_code' => '\f21e',
			),
			'fa-history'                             => array(
				'label'     => 'History',
				'category'  => array( 2 ),
				'font_code' => '\f1da',
			),
			'fa-home'                                => array(
				'label'     => 'Home',
				'category'  => array( 2 ),
				'font_code' => '\f015',
			),
			'fa-hotel'                               => array(
				'label'     => 'Hotel',
				'category'  => array( 2 ),
				'font_code' => '\f236',
			),
			'fa-hourglass'                           => array(
				'label'     => 'Hourglass',
				'category'  => array( 2 ),
				'font_code' => '\f254',
			),
			'fa-hourglass-1'                         => array(
				'label'     => 'Hourglass 1',
				'category'  => array( 2 ),
				'font_code' => '\f251',
			),
			'fa-hourglass-2'                         => array(
				'label'     => 'Hourglass 2',
				'category'  => array( 2 ),
				'font_code' => '\f252',
			),
			'fa-hourglass-3'                         => array(
				'label'     => 'Hourglass 3',
				'category'  => array( 2 ),
				'font_code' => '\f253',
			),
			'fa-hourglass-end'                       => array(
				'label'     => 'Hourglass End',
				'category'  => array( 2 ),
				'font_code' => '\f253',
			),
			'fa-hourglass-half'                      => array(
				'label'     => 'Hourglass Half',
				'category'  => array( 2 ),
				'font_code' => '\f252',
			),
			'fa-hourglass-o'                         => array(
				'label'     => 'Hourglass <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f250',
			),
			'fa-hourglass-start'                     => array(
				'label'     => 'Hourglass Start',
				'category'  => array( 2 ),
				'font_code' => '\f251',
			),
			'fa-i-cursor'                            => array(
				'label'     => 'I Cursor',
				'category'  => array( 2 ),
				'font_code' => '\f246',
			),
			'fa-image'                               => array(
				'label'     => 'Image',
				'category'  => array( 2 ),
				'font_code' => '\f03e',
			),
			'fa-inbox'                               => array(
				'label'     => 'Inbox',
				'category'  => array( 2 ),
				'font_code' => '\f01c',
			),
			'fa-industry'                            => array(
				'label'     => 'Industry',
				'category'  => array( 2 ),
				'font_code' => '\f275',
			),
			'fa-info'                                => array(
				'label'     => 'Info',
				'category'  => array( 2 ),
				'font_code' => '\f129',
			),
			'fa-info-circle'                         => array(
				'label'     => 'Info Circle',
				'category'  => array( 2 ),
				'font_code' => '\f05a',
			),
			'fa-institution'                         => array(
				'label'     => 'Institution',
				'category'  => array( 2 ),
				'font_code' => '\f19c',
			),
			'fa-key'                                 => array(
				'label'     => 'Key',
				'category'  => array( 2 ),
				'font_code' => '\f084',
			),
			'fa-keyboard-o'                          => array(
				'label'     => 'Keyboard <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f11c',
			),
			'fa-language'                            => array(
				'label'     => 'Language',
				'category'  => array( 2 ),
				'font_code' => '\f1ab',
			),
			'fa-laptop'                              => array(
				'label'     => 'Laptop',
				'category'  => array( 2 ),
				'font_code' => '\f109',
			),
			'fa-leaf'                                => array(
				'label'     => 'Leaf',
				'category'  => array( 2 ),
				'font_code' => '\f06c',
			),
			'fa-legal'                               => array(
				'label'     => 'Legal',
				'category'  => array( 2 ),
				'font_code' => '\f0e3',
			),
			'fa-lemon-o'                             => array(
				'label'     => 'Lemon <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f094',
			),
			'fa-level-down'                          => array(
				'label'     => 'Level Down',
				'category'  => array( 2 ),
				'font_code' => '\f149',
			),
			'fa-level-up'                            => array(
				'label'     => 'Level Up',
				'category'  => array( 2 ),
				'font_code' => '\f148',
			),
			'fa-life-bouy'                           => array(
				'label'     => 'Life Bouy',
				'category'  => array( 2 ),
				'font_code' => '\f1cd',
			),
			'fa-life-buoy'                           => array(
				'label'     => 'Life Buoy',
				'category'  => array( 2 ),
				'font_code' => '\f1cd',
			),
			'fa-life-ring'                           => array(
				'label'     => 'Life Ring',
				'category'  => array( 2 ),
				'font_code' => '\f1cd',
			),
			'fa-life-saver'                          => array(
				'label'     => 'Life Saver',
				'category'  => array( 2 ),
				'font_code' => '\f1cd',
			),
			'fa-lightbulb-o'                         => array(
				'label'     => 'Lightbulb <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f0eb',
			),
			'fa-line-chart'                          => array(
				'label'     => 'Line Chart',
				'category'  => array( 2, 11 ),
				'font_code' => '\f201',
			),
			'fa-location-arrow'                      => array(
				'label'     => 'Location Arrow',
				'category'  => array( 2 ),
				'font_code' => '\f124',
			),
			'fa-lock'                                => array(
				'label'     => 'Lock',
				'category'  => array( 2 ),
				'font_code' => '\f023',
			),
			'fa-low-vision'                          => array(
				'label'     => 'Low Vision',
				'category'  => array( 2, 3 ),
				'font_code' => '\f2a8',
			),
			'fa-magic'                               => array(
				'label'     => 'Magic',
				'category'  => array( 2 ),
				'font_code' => '\f0d0',
			),
			'fa-magnet'                              => array(
				'label'     => 'Magnet',
				'category'  => array( 2 ),
				'font_code' => '\f076',
			),
			'fa-mail-forward'                        => array(
				'label'     => 'Mail Forward',
				'category'  => array( 2 ),
				'font_code' => '\f064',
			),
			'fa-mail-reply'                          => array(
				'label'     => 'Mail Reply',
				'category'  => array( 2 ),
				'font_code' => '\f112',
			),
			'fa-mail-reply-all'                      => array(
				'label'     => 'Mail Reply All',
				'category'  => array( 2 ),
				'font_code' => '\f122',
			),
			'fa-male'                                => array(
				'label'     => 'Male',
				'category'  => array( 2 ),
				'font_code' => '\f183',
			),
			'fa-map'                                 => array(
				'label'     => 'Map',
				'category'  => array( 2 ),
				'font_code' => '\f279',
			),
			'fa-map-marker'                          => array(
				'label'     => 'Map Marker',
				'category'  => array( 2 ),
				'font_code' => '\f041',
			),
			'fa-map-o'                               => array(
				'label'     => 'Map <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f278',
			),
			'fa-map-pin'                             => array(
				'label'     => 'Map Pin',
				'category'  => array( 2 ),
				'font_code' => '\f276',
			),
			'fa-map-signs'                           => array(
				'label'     => 'Map Signs',
				'category'  => array( 2 ),
				'font_code' => '\f277',
			),
			'fa-meh-o'                               => array(
				'label'     => 'Meh <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f11a',
			),
			'fa-microphone'                          => array(
				'label'     => 'Microphone',
				'category'  => array( 2 ),
				'font_code' => '\f130',
			),
			'fa-microphone-slash'                    => array(
				'label'     => 'Microphone Slash',
				'category'  => array( 2 ),
				'font_code' => '\f131',
			),
			'fa-minus'                               => array(
				'label'     => 'Minus',
				'category'  => array( 2 ),
				'font_code' => '\f068',
			),
			'fa-minus-circle'                        => array(
				'label'     => 'Minus Circle',
				'category'  => array( 2 ),
				'font_code' => '\f056',
			),
			'fa-minus-square'                        => array(
				'label'     => 'Minus Square',
				'category'  => array( 2, 9 ),
				'font_code' => '\f146',
			),
			'fa-minus-square-o'                      => array(
				'label'     => 'Minus Square <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 9 ),
				'font_code' => '\f147',
			),
			'fa-mobile'                              => array(
				'label'     => 'Mobile',
				'category'  => array( 2 ),
				'font_code' => '\f10b',
			),
			'fa-mobile-phone'                        => array(
				'label'     => 'Mobile Phone',
				'category'  => array( 2 ),
				'font_code' => '\f10b',
			),
			'fa-money'                               => array(
				'label'     => 'Money',
				'category'  => array( 2, 12 ),
				'font_code' => '\f0d6',
			),
			'fa-moon-o'                              => array(
				'label'     => 'Moon <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f186',
			),
			'fa-mortar-board'                        => array(
				'label'     => 'Mortar Board',
				'category'  => array( 2 ),
				'font_code' => '\f19d',
			),
			'fa-motorcycle'                          => array(
				'label'     => 'Motorcycle',
				'category'  => array( 2, 5 ),
				'font_code' => '\f21c',
			),
			'fa-mouse-pointer'                       => array(
				'label'     => 'Mouse Pointer',
				'category'  => array( 2 ),
				'font_code' => '\f245',
			),
			'fa-music'                               => array(
				'label'     => 'Music',
				'category'  => array( 2 ),
				'font_code' => '\f001',
			),
			'fa-navicon'                             => array(
				'label'     => 'Navicon',
				'category'  => array( 2 ),
				'font_code' => '\f0c9',
			),
			'fa-newspaper-o'                         => array(
				'label'     => 'Newspaper <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f1ea',
			),
			'fa-object-group'                        => array(
				'label'     => 'Object Group',
				'category'  => array( 2 ),
				'font_code' => '\f247',
			),
			'fa-object-ungroup'                      => array(
				'label'     => 'Object Ungroup',
				'category'  => array( 2 ),
				'font_code' => '\f248',
			),
			'fa-paint-brush'                         => array(
				'label'     => 'Paint Brush',
				'category'  => array( 2 ),
				'font_code' => '\f1fc',
			),
			'fa-paper-plane'                         => array(
				'label'     => 'Paper Plane',
				'category'  => array( 2 ),
				'font_code' => '\f1d8',
			),
			'fa-paper-plane-o'                       => array(
				'label'     => 'Paper Plane <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f1d9',
			),
			'fa-paw'                                 => array(
				'label'     => 'Paw',
				'category'  => array( 2 ),
				'font_code' => '\f1b0',
			),
			'fa-pencil'                              => array(
				'label'     => 'Pencil',
				'category'  => array( 2 ),
				'font_code' => '\f040',
			),
			'fa-pencil-square'                       => array(
				'label'     => 'Pencil Square',
				'category'  => array( 2 ),
				'font_code' => '\f14b',
			),
			'fa-pencil-square-o'                     => array(
				'label'     => 'Pencil Square <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f044',
			),
			'fa-percent'                             => array(
				'label'     => 'Percent',
				'category'  => array( 2 ),
				'font_code' => '\f295',
			),
			'fa-phone'                               => array(
				'label'     => 'Phone',
				'category'  => array( 2 ),
				'font_code' => '\f095',
			),
			'fa-phone-square'                        => array(
				'label'     => 'Phone Square',
				'category'  => array( 2 ),
				'font_code' => '\f098',
			),
			'fa-photo'                               => array(
				'label'     => 'Photo',
				'category'  => array( 2 ),
				'font_code' => '\f03e',
			),
			'fa-picture-o'                           => array(
				'label'     => 'Picture <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f03e',
			),
			'fa-pie-chart'                           => array(
				'label'     => 'Pie Chart',
				'category'  => array( 2, 11 ),
				'font_code' => '\f200',
			),
			'fa-plane'                               => array(
				'label'     => 'Plane',
				'category'  => array( 2, 5 ),
				'font_code' => '\f072',
			),
			'fa-plug'                                => array(
				'label'     => 'Plug',
				'category'  => array( 2 ),
				'font_code' => '\f1e6',
			),
			'fa-plus'                                => array(
				'label'     => 'Plus',
				'category'  => array( 2 ),
				'font_code' => '\f067',
			),
			'fa-plus-circle'                         => array(
				'label'     => 'Plus Circle',
				'category'  => array( 2 ),
				'font_code' => '\f055',
			),
			'fa-plus-square'                         => array(
				'label'     => 'Plus Square',
				'category'  => array( 2, 9, 17 ),
				'font_code' => '\f0fe',
			),
			'fa-plus-square-o'                       => array(
				'label'     => 'Plus Square <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 9 ),
				'font_code' => '\f196',
			),
			'fa-power-off'                           => array(
				'label'     => 'Power Off',
				'category'  => array( 2 ),
				'font_code' => '\f011',
			),
			'fa-print'                               => array(
				'label'     => 'Print',
				'category'  => array( 2 ),
				'font_code' => '\f02f',
			),
			'fa-puzzle-piece'                        => array(
				'label'     => 'Puzzle Piece',
				'category'  => array( 2 ),
				'font_code' => '\f12e',
			),
			'fa-qrcode'                              => array(
				'label'     => 'Qrcode',
				'category'  => array( 2 ),
				'font_code' => '\f029',
			),
			'fa-question'                            => array(
				'label'     => 'Question',
				'category'  => array( 2 ),
				'font_code' => '\f128',
			),
			'fa-question-circle'                     => array(
				'label'     => 'Question Circle',
				'category'  => array( 2 ),
				'font_code' => '\f059',
			),
			'fa-question-circle-o'                   => array(
				'label'     => 'Question Circle <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 3 ),
				'font_code' => '\f29c',
			),
			'fa-quote-left'                          => array(
				'label'     => 'Quote Left',
				'category'  => array( 2 ),
				'font_code' => '\f10d',
			),
			'fa-quote-right'                         => array(
				'label'     => 'Quote Right',
				'category'  => array( 2 ),
				'font_code' => '\f10e',
			),
			'fa-random'                              => array(
				'label'     => 'Random',
				'category'  => array( 2, 15 ),
				'font_code' => '\f074',
			),
			'fa-recycle'                             => array(
				'label'     => 'Recycle',
				'category'  => array( 2 ),
				'font_code' => '\f1b8',
			),
			'fa-refresh'                             => array(
				'label'     => 'Refresh',
				'category'  => array( 2, 8 ),
				'font_code' => '\f021',
			),
			'fa-registered'                          => array(
				'label'     => 'Registered',
				'category'  => array( 2 ),
				'font_code' => '\f25d',
			),
			'fa-remove'                              => array(
				'label'     => 'Remove',
				'category'  => array( 2 ),
				'font_code' => '\f00d',
			),
			'fa-reorder'                             => array(
				'label'     => 'Reorder',
				'category'  => array( 2 ),
				'font_code' => '\f0c9',
			),
			'fa-reply'                               => array(
				'label'     => 'Reply',
				'category'  => array( 2 ),
				'font_code' => '\f112',
			),
			'fa-reply-all'                           => array(
				'label'     => 'Reply All',
				'category'  => array( 2 ),
				'font_code' => '\f122',
			),
			'fa-retweet'                             => array(
				'label'     => 'Retweet',
				'category'  => array( 2 ),
				'font_code' => '\f079',
			),
			'fa-road'                                => array(
				'label'     => 'Road',
				'category'  => array( 2 ),
				'font_code' => '\f018',
			),
			'fa-rocket'                              => array(
				'label'     => 'Rocket',
				'category'  => array( 2, 5 ),
				'font_code' => '\f135',
			),
			'fa-rss'                                 => array(
				'label'     => 'Rss',
				'category'  => array( 2 ),
				'font_code' => '\f09e',
			),
			'fa-rss-square'                          => array(
				'label'     => 'Rss Square',
				'category'  => array( 2 ),
				'font_code' => '\f143',
			),
			'fa-search'                              => array(
				'label'     => 'Search',
				'category'  => array( 2 ),
				'font_code' => '\f002',
			),
			'fa-search-minus'                        => array(
				'label'     => 'Search Minus',
				'category'  => array( 2 ),
				'font_code' => '\f010',
			),
			'fa-search-plus'                         => array(
				'label'     => 'Search Plus',
				'category'  => array( 2 ),
				'font_code' => '\f00e',
			),
			'fa-send'                                => array(
				'label'     => 'Send',
				'category'  => array( 2 ),
				'font_code' => '\f1d8',
			),
			'fa-send-o'                              => array(
				'label'     => 'Send <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f1d9',
			),
			'fa-server'                              => array(
				'label'     => 'Server',
				'category'  => array( 2 ),
				'font_code' => '\f233',
			),
			'fa-share'                               => array(
				'label'     => 'Share',
				'category'  => array( 2 ),
				'font_code' => '\f064',
			),
			'fa-share-alt'                           => array(
				'label'     => 'Share Alt',
				'category'  => array( 2, 16 ),
				'font_code' => '\f1e0',
			),
			'fa-share-alt-square'                    => array(
				'label'     => 'Share Alt Square',
				'category'  => array( 2, 16 ),
				'font_code' => '\f1e1',
			),
			'fa-share-square'                        => array(
				'label'     => 'Share Square',
				'category'  => array( 2 ),
				'font_code' => '\f14d',
			),
			'fa-share-square-o'                      => array(
				'label'     => 'Share Square <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f045',
			),
			'fa-shield'                              => array(
				'label'     => 'Shield',
				'category'  => array( 2 ),
				'font_code' => '\f132',
			),
			'fa-ship'                                => array(
				'label'     => 'Ship',
				'category'  => array( 2, 5 ),
				'font_code' => '\f21a',
			),
			'fa-shopping-bag'                        => array(
				'label'     => 'Shopping Bag',
				'category'  => array( 2 ),
				'font_code' => '\f290',
			),
			'fa-shopping-basket'                     => array(
				'label'     => 'Shopping Basket',
				'category'  => array( 2 ),
				'font_code' => '\f291',
			),
			'fa-shopping-cart'                       => array(
				'label'     => 'Shopping Cart',
				'category'  => array( 2 ),
				'font_code' => '\f07a',
			),
			'fa-sign-in'                             => array(
				'label'     => 'Sign In',
				'category'  => array( 2 ),
				'font_code' => '\f090',
			),
			'fa-sign-language'                       => array(
				'label'     => 'Sign Language',
				'category'  => array( 2, 3 ),
				'font_code' => '\f2a7',
			),
			'fa-sign-out'                            => array(
				'label'     => 'Sign Out',
				'category'  => array( 2 ),
				'font_code' => '\f08b',
			),
			'fa-signal'                              => array(
				'label'     => 'Signal',
				'category'  => array( 2 ),
				'font_code' => '\f012',
			),
			'fa-signing'                             => array(
				'label'     => 'Signing',
				'category'  => array( 2, 3 ),
				'font_code' => '\f2a7',
			),
			'fa-sitemap'                             => array(
				'label'     => 'Sitemap',
				'category'  => array( 2 ),
				'font_code' => '\f0e8',
			),
			'fa-sliders'                             => array(
				'label'     => 'Sliders',
				'category'  => array( 2 ),
				'font_code' => '\f1de',
			),
			'fa-smile-o'                             => array(
				'label'     => 'Smile <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f118',
			),
			'fa-soccer-ball-o'                       => array(
				'label'     => 'Soccer Ball <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f1e3',
			),
			'fa-sort'                                => array(
				'label'     => 'Sort',
				'category'  => array( 2 ),
				'font_code' => '\f0dc',
			),
			'fa-sort-alpha-asc'                      => array(
				'label'     => 'Sort Alpha Asc',
				'category'  => array( 2 ),
				'font_code' => '\f15d',
			),
			'fa-sort-alpha-desc'                     => array(
				'label'     => 'Sort Alpha Desc',
				'category'  => array( 2 ),
				'font_code' => '\f15e',
			),
			'fa-sort-amount-asc'                     => array(
				'label'     => 'Sort Amount Asc',
				'category'  => array( 2 ),
				'font_code' => '\f160',
			),
			'fa-sort-amount-desc'                    => array(
				'label'     => 'Sort Amount Desc',
				'category'  => array( 2 ),
				'font_code' => '\f161',
			),
			'fa-sort-asc'                            => array(
				'label'     => 'Sort Asc',
				'category'  => array( 2 ),
				'font_code' => '\f0de',
			),
			'fa-sort-desc'                           => array(
				'label'     => 'Sort Desc',
				'category'  => array( 2 ),
				'font_code' => '\f0dd',
			),
			'fa-sort-down'                           => array(
				'label'     => 'Sort Down',
				'category'  => array( 2 ),
				'font_code' => '\f0dd',
			),
			'fa-sort-numeric-asc'                    => array(
				'label'     => 'Sort Numeric Asc',
				'category'  => array( 2 ),
				'font_code' => '\f162',
			),
			'fa-sort-numeric-desc'                   => array(
				'label'     => 'Sort Numeric Desc',
				'category'  => array( 2 ),
				'font_code' => '\f163',
			),
			'fa-sort-up'                             => array(
				'label'     => 'Sort Up',
				'category'  => array( 2 ),
				'font_code' => '\f0de',
			),
			'fa-space-shuttle'                       => array(
				'label'     => 'Space Shuttle',
				'category'  => array( 2, 5 ),
				'font_code' => '\f197',
			),
			'fa-spinner'                             => array(
				'label'     => 'Spinner',
				'category'  => array( 2, 8 ),
				'font_code' => '\f110',
			),
			'fa-spoon'                               => array(
				'label'     => 'Spoon',
				'category'  => array( 2 ),
				'font_code' => '\f1b1',
			),
			'fa-square'                              => array(
				'label'     => 'Square',
				'category'  => array( 2, 9 ),
				'font_code' => '\f0c8',
			),
			'fa-square-o'                            => array(
				'label'     => 'Square <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 9 ),
				'font_code' => '\f096',
			),
			'fa-star'                                => array(
				'label'     => 'Star',
				'category'  => array( 2 ),
				'font_code' => '\f005',
			),
			'fa-star-half'                           => array(
				'label'     => 'Star Half',
				'category'  => array( 2 ),
				'font_code' => '\f089',
			),
			'fa-star-half-empty'                     => array(
				'label'     => 'Star Half Empty',
				'category'  => array( 2 ),
				'font_code' => '\f123',
			),
			'fa-star-half-full'                      => array(
				'label'     => 'Star Half Full',
				'category'  => array( 2 ),
				'font_code' => '\f123',
			),
			'fa-star-half-o'                         => array(
				'label'     => 'Star Half <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f123',
			),
			'fa-star-o'                              => array(
				'label'     => 'Star <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f006',
			),
			'fa-sticky-note'                         => array(
				'label'     => 'Sticky Note',
				'category'  => array( 2 ),
				'font_code' => '\f249',
			),
			'fa-sticky-note-o'                       => array(
				'label'     => 'Sticky Note <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f24a',
			),
			'fa-street-view'                         => array(
				'label'     => 'Street View',
				'category'  => array( 2 ),
				'font_code' => '\f21d',
			),
			'fa-suitcase'                            => array(
				'label'     => 'Suitcase',
				'category'  => array( 2 ),
				'font_code' => '\f0f2',
			),
			'fa-sun-o'                               => array(
				'label'     => 'Sun <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f185',
			),
			'fa-support'                             => array(
				'label'     => 'Support',
				'category'  => array( 2 ),
				'font_code' => '\f1cd',
			),
			'fa-tablet'                              => array(
				'label'     => 'Tablet',
				'category'  => array( 2 ),
				'font_code' => '\f10a',
			),
			'fa-tachometer'                          => array(
				'label'     => 'Tachometer',
				'category'  => array( 2 ),
				'font_code' => '\f0e4',
			),
			'fa-tag'                                 => array(
				'label'     => 'Tag',
				'category'  => array( 2 ),
				'font_code' => '\f02b',
			),
			'fa-tags'                                => array(
				'label'     => 'Tags',
				'category'  => array( 2 ),
				'font_code' => '\f02c',
			),
			'fa-tasks'                               => array(
				'label'     => 'Tasks',
				'category'  => array( 2 ),
				'font_code' => '\f0ae',
			),
			'fa-taxi'                                => array(
				'label'     => 'Taxi',
				'category'  => array( 2, 5 ),
				'font_code' => '\f1ba',
			),
			'fa-television'                          => array(
				'label'     => 'Television',
				'category'  => array( 2 ),
				'font_code' => '\f26c',
			),
			'fa-terminal'                            => array(
				'label'     => 'Terminal',
				'category'  => array( 2 ),
				'font_code' => '\f120',
			),
			'fa-thumb-tack'                          => array(
				'label'     => 'Thumb Tack',
				'category'  => array( 2 ),
				'font_code' => '\f08d',
			),
			'fa-thumbs-down'                         => array(
				'label'     => 'Thumbs Down',
				'category'  => array( 2, 4 ),
				'font_code' => '\f165',
			),
			'fa-thumbs-o-down'                       => array(
				'label'     => 'Thumbs Down <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 4 ),
				'font_code' => '\f088',
			),
			'fa-thumbs-o-up'                         => array(
				'label'     => 'Thumbs Up <span class="text-muted">(Outline)</span>',
				'category'  => array( 2, 4 ),
				'font_code' => '\f087',
			),
			'fa-thumbs-up'                           => array(
				'label'     => 'Thumbs Up',
				'category'  => array( 2, 4 ),
				'font_code' => '\f164',
			),
			'fa-ticket'                              => array(
				'label'     => 'Ticket',
				'category'  => array( 2 ),
				'font_code' => '\f145',
			),
			'fa-times'                               => array(
				'label'     => 'Times',
				'category'  => array( 2 ),
				'font_code' => '\f00d',
			),
			'fa-times-circle'                        => array(
				'label'     => 'Times Circle',
				'category'  => array( 2 ),
				'font_code' => '\f057',
			),
			'fa-times-circle-o'                      => array(
				'label'     => 'Times Circle <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f05c',
			),
			'fa-tint'                                => array(
				'label'     => 'Tint',
				'category'  => array( 2 ),
				'font_code' => '\f043',
			),
			'fa-toggle-down'                         => array(
				'label'     => 'Toggle Down',
				'category'  => array( 2, 14 ),
				'font_code' => '\f150',
			),
			'fa-toggle-left'                         => array(
				'label'     => 'Toggle Left',
				'category'  => array( 2, 14 ),
				'font_code' => '\f191',
			),
			'fa-toggle-off'                          => array(
				'label'     => 'Toggle Off',
				'category'  => array( 2 ),
				'font_code' => '\f204',
			),
			'fa-toggle-on'                           => array(
				'label'     => 'Toggle On',
				'category'  => array( 2 ),
				'font_code' => '\f205',
			),
			'fa-toggle-right'                        => array(
				'label'     => 'Toggle Right',
				'category'  => array( 2, 14 ),
				'font_code' => '\f152',
			),
			'fa-toggle-up'                           => array(
				'label'     => 'Toggle Up',
				'category'  => array( 2, 14 ),
				'font_code' => '\f151',
			),
			'fa-trademark'                           => array(
				'label'     => 'Trademark',
				'category'  => array( 2 ),
				'font_code' => '\f25c',
			),
			'fa-trash'                               => array(
				'label'     => 'Trash',
				'category'  => array( 2 ),
				'font_code' => '\f1f8',
			),
			'fa-trash-o'                             => array(
				'label'     => 'Trash <span class="text-muted">(Outline)</span>',
				'category'  => array( 2 ),
				'font_code' => '\f014',
			),
			'fa-tree'                                => array(
				'label'     => 'Tree',
				'category'  => array( 2 ),
				'font_code' => '\f1bb',
			),
			'fa-trophy'                              => array(
				'label'     => 'Trophy',
				'category'  => array( 2 ),
				'font_code' => '\f091',
			),
			'fa-truck'                               => array(
				'label'     => 'Truck',
				'category'  => array( 2, 5 ),
				'font_code' => '\f0d1',
			),
			'fa-tty'                                 => array(
				'label'     => 'Tty',
				'category'  => array( 2, 3 ),
				'font_code' => '\f1e4',
			),
			'fa-tv'                                  => array(
				'label'     => 'Tv',
				'category'  => array( 2 ),
				'font_code' => '\f26c',
			),
			'fa-umbrella'                            => array(
				'label'     => 'Umbrella',
				'category'  => array( 2 ),
				'font_code' => '\f0e9',
			),
			'fa-universal-access'                    => array(
				'label'     => 'Universal Access',
				'category'  => array( 2, 3 ),
				'font_code' => '\f29a',
			),
			'fa-university'                          => array(
				'label'     => 'University',
				'category'  => array( 2 ),
				'font_code' => '\f19c',
			),
			'fa-unlock'                              => array(
				'label'     => 'Unlock',
				'category'  => array( 2 ),
				'font_code' => '\f09c',
			),
			'fa-unlock-alt'                          => array(
				'label'     => 'Unlock Alt',
				'category'  => array( 2 ),
				'font_code' => '\f13e',
			),
			'fa-unsorted'                            => array(
				'label'     => 'Unsorted',
				'category'  => array( 2 ),
				'font_code' => '\f0dc',
			),
			'fa-upload'                              => array(
				'label'     => 'Upload',
				'category'  => array( 2 ),
				'font_code' => '\f093',
			),
			'fa-user'                                => array(
				'label'     => 'User',
				'category'  => array( 2 ),
				'font_code' => '\f007',
			),
			'fa-user-plus'                           => array(
				'label'     => 'User Plus',
				'category'  => array( 2 ),
				'font_code' => '\f234',
			),
			'fa-user-secret'                         => array(
				'label'     => 'User Secret',
				'category'  => array( 2 ),
				'font_code' => '\f21b',
			),
			'fa-user-times'                          => array(
				'label'     => 'User Times',
				'category'  => array( 2 ),
				'font_code' => '\f235',
			),
			'fa-users'                               => array(
				'label'     => 'Users',
				'category'  => array( 2 ),
				'font_code' => '\f0c0',
			),
			'fa-video-camera'                        => array(
				'label'     => 'Video Camera',
				'category'  => array( 2 ),
				'font_code' => '\f03d',
			),
			'fa-volume-control-phone'                => array(
				'label'     => 'Volume Control Phone',
				'category'  => array( 2, 3 ),
				'font_code' => '\f2a0',
			),
			'fa-volume-down'                         => array(
				'label'     => 'Volume Down',
				'category'  => array( 2 ),
				'font_code' => '\f027',
			),
			'fa-volume-off'                          => array(
				'label'     => 'Volume Off',
				'category'  => array( 2 ),
				'font_code' => '\f026',
			),
			'fa-volume-up'                           => array(
				'label'     => 'Volume Up',
				'category'  => array( 2 ),
				'font_code' => '\f028',
			),
			'fa-warning'                             => array(
				'label'     => 'Warning',
				'category'  => array( 2 ),
				'font_code' => '\f071',
			),
			'fa-wheelchair'                          => array(
				'label'     => 'Wheelchair',
				'category'  => array( 2, 3, 5, 17 ),
				'font_code' => '\f193',
			),
			'fa-wheelchair-alt'                      => array(
				'label'     => 'Wheelchair Alt',
				'category'  => array( 2, 3, 5, 17 ),
				'font_code' => '\f29b',
			),
			'fa-wifi'                                => array(
				'label'     => 'Wifi',
				'category'  => array( 2 ),
				'font_code' => '\f1eb',
			),
			'fa-wrench'                              => array(
				'label'     => 'Wrench',
				'category'  => array( 2 ),
				'font_code' => '\f0ad',
			),
			'fa-hand-o-down'                         => array(
				'label'     => 'Hand Down <span class="text-muted">(Outline)</span>',
				'category'  => array( 4, 14 ),
				'font_code' => '\f0a7',
			),
			'fa-hand-o-left'                         => array(
				'label'     => 'Hand Left <span class="text-muted">(Outline)</span>',
				'category'  => array( 4, 14 ),
				'font_code' => '\f0a5',
			),
			'fa-hand-o-right'                        => array(
				'label'     => 'Hand Right <span class="text-muted">(Outline)</span>',
				'category'  => array( 4, 14 ),
				'font_code' => '\f0a4',
			),
			'fa-hand-o-up'                           => array(
				'label'     => 'Hand Up <span class="text-muted">(Outline)</span>',
				'category'  => array( 4, 14 ),
				'font_code' => '\f0a6',
			),
			'fa-ambulance'                           => array(
				'label'     => 'Ambulance',
				'category'  => array( 5, 17 ),
				'font_code' => '\f0f9',
			),
			'fa-subway'                              => array(
				'label'     => 'Subway',
				'category'  => array( 5 ),
				'font_code' => '\f239',
			),
			'fa-train'                               => array(
				'label'     => 'Train',
				'category'  => array( 5 ),
				'font_code' => '\f238',
			),
			'fa-genderless'                          => array(
				'label'     => 'Genderless',
				'category'  => array( 6 ),
				'font_code' => '\f22d',
			),
			'fa-intersex'                            => array(
				'label'     => 'Intersex',
				'category'  => array( 6 ),
				'font_code' => '\f224',
			),
			'fa-mars'                                => array(
				'label'     => 'Mars',
				'category'  => array( 6 ),
				'font_code' => '\f222',
			),
			'fa-mars-double'                         => array(
				'label'     => 'Mars Double',
				'category'  => array( 6 ),
				'font_code' => '\f227',
			),
			'fa-mars-stroke'                         => array(
				'label'     => 'Mars Stroke',
				'category'  => array( 6 ),
				'font_code' => '\f229',
			),
			'fa-mars-stroke-h'                       => array(
				'label'     => 'Mars Stroke H',
				'category'  => array( 6 ),
				'font_code' => '\f22b',
			),
			'fa-mars-stroke-v'                       => array(
				'label'     => 'Mars Stroke V',
				'category'  => array( 6 ),
				'font_code' => '\f22a',
			),
			'fa-mercury'                             => array(
				'label'     => 'Mercury',
				'category'  => array( 6 ),
				'font_code' => '\f223',
			),
			'fa-neuter'                              => array(
				'label'     => 'Neuter',
				'category'  => array( 6 ),
				'font_code' => '\f22c',
			),
			'fa-transgender'                         => array(
				'label'     => 'Transgender',
				'category'  => array( 6 ),
				'font_code' => '\f224',
			),
			'fa-transgender-alt'                     => array(
				'label'     => 'Transgender Alt',
				'category'  => array( 6 ),
				'font_code' => '\f225',
			),
			'fa-venus'                               => array(
				'label'     => 'Venus',
				'category'  => array( 6 ),
				'font_code' => '\f221',
			),
			'fa-venus-double'                        => array(
				'label'     => 'Venus Double',
				'category'  => array( 6 ),
				'font_code' => '\f226',
			),
			'fa-venus-mars'                          => array(
				'label'     => 'Venus Mars',
				'category'  => array( 6 ),
				'font_code' => '\f228',
			),
			'fa-file'                                => array(
				'label'     => 'File',
				'category'  => array( 7, 13 ),
				'font_code' => '\f15b',
			),
			'fa-file-o'                              => array(
				'label'     => 'File <span class="text-muted">(Outline)</span>',
				'category'  => array( 7, 13 ),
				'font_code' => '\f016',
			),
			'fa-file-text'                           => array(
				'label'     => 'File Text',
				'category'  => array( 7, 13 ),
				'font_code' => '\f15c',
			),
			'fa-file-text-o'                         => array(
				'label'     => 'File Text <span class="text-muted">(Outline)</span>',
				'category'  => array( 7, 13 ),
				'font_code' => '\f0f6',
			),
			'fa-cc-amex'                             => array(
				'label'     => 'Cc Amex',
				'category'  => array( 10, 16 ),
				'font_code' => '\f1f3',
			),
			'fa-cc-diners-club'                      => array(
				'label'     => 'Cc Diners Club',
				'category'  => array( 10, 16 ),
				'font_code' => '\f24c',
			),
			'fa-cc-discover'                         => array(
				'label'     => 'Cc Discover',
				'category'  => array( 10, 16 ),
				'font_code' => '\f1f2',
			),
			'fa-cc-jcb'                              => array(
				'label'     => 'Cc Jcb',
				'category'  => array( 10, 16 ),
				'font_code' => '\f24b',
			),
			'fa-cc-mastercard'                       => array(
				'label'     => 'Cc Mastercard',
				'category'  => array( 10, 16 ),
				'font_code' => '\f1f1',
			),
			'fa-cc-paypal'                           => array(
				'label'     => 'Cc Paypal',
				'category'  => array( 10, 16 ),
				'font_code' => '\f1f4',
			),
			'fa-cc-stripe'                           => array(
				'label'     => 'Cc Stripe',
				'category'  => array( 10, 16 ),
				'font_code' => '\f1f5',
			),
			'fa-cc-visa'                             => array(
				'label'     => 'Cc Visa',
				'category'  => array( 10, 16 ),
				'font_code' => '\f1f0',
			),
			'fa-google-wallet'                       => array(
				'label'     => 'Google Wallet',
				'category'  => array( 10, 16 ),
				'font_code' => '\f1ee',
			),
			'fa-paypal'                              => array(
				'label'     => 'Paypal',
				'category'  => array( 10, 16 ),
				'font_code' => '\f1ed',
			),
			'fa-bitcoin'                             => array(
				'label'     => 'Bitcoin',
				'category'  => array( 12, 16 ),
				'font_code' => '\f15a',
			),
			'fa-btc'                                 => array(
				'label'     => 'Btc',
				'category'  => array( 12, 16 ),
				'font_code' => '\f15a',
			),
			'fa-cny'                                 => array(
				'label'     => 'Cny',
				'category'  => array( 12 ),
				'font_code' => '\f157',
			),
			'fa-dollar'                              => array(
				'label'     => 'Dollar',
				'category'  => array( 12 ),
				'font_code' => '\f155',
			),
			'fa-eur'                                 => array(
				'label'     => 'Eur',
				'category'  => array( 12 ),
				'font_code' => '\f153',
			),
			'fa-euro'                                => array(
				'label'     => 'Euro',
				'category'  => array( 12 ),
				'font_code' => '\f153',
			),
			'fa-gbp'                                 => array(
				'label'     => 'Gbp',
				'category'  => array( 12 ),
				'font_code' => '\f154',
			),
			'fa-gg'                                  => array(
				'label'     => 'Gg',
				'category'  => array( 12, 16 ),
				'font_code' => '\f260',
			),
			'fa-gg-circle'                           => array(
				'label'     => 'Gg Circle',
				'category'  => array( 12, 16 ),
				'font_code' => '\f261',
			),
			'fa-ils'                                 => array(
				'label'     => 'Ils',
				'category'  => array( 12 ),
				'font_code' => '\f20b',
			),
			'fa-inr'                                 => array(
				'label'     => 'Inr',
				'category'  => array( 12 ),
				'font_code' => '\f156',
			),
			'fa-jpy'                                 => array(
				'label'     => 'Jpy',
				'category'  => array( 12 ),
				'font_code' => '\f157',
			),
			'fa-krw'                                 => array(
				'label'     => 'Krw',
				'category'  => array( 12 ),
				'font_code' => '\f159',
			),
			'fa-rmb'                                 => array(
				'label'     => 'Rmb',
				'category'  => array( 12 ),
				'font_code' => '\f157',
			),
			'fa-rouble'                              => array(
				'label'     => 'Rouble',
				'category'  => array( 12 ),
				'font_code' => '\f158',
			),
			'fa-rub'                                 => array(
				'label'     => 'Rub',
				'category'  => array( 12 ),
				'font_code' => '\f158',
			),
			'fa-ruble'                               => array(
				'label'     => 'Ruble',
				'category'  => array( 12 ),
				'font_code' => '\f158',
			),
			'fa-rupee'                               => array(
				'label'     => 'Rupee',
				'category'  => array( 12 ),
				'font_code' => '\f156',
			),
			'fa-shekel'                              => array(
				'label'     => 'Shekel',
				'category'  => array( 12 ),
				'font_code' => '\f20b',
			),
			'fa-sheqel'                              => array(
				'label'     => 'Sheqel',
				'category'  => array( 12 ),
				'font_code' => '\f20b',
			),
			'fa-try'                                 => array(
				'label'     => 'Try',
				'category'  => array( 12 ),
				'font_code' => '\f195',
			),
			'fa-turkish-lira'                        => array(
				'label'     => 'Turkish Lira',
				'category'  => array( 12 ),
				'font_code' => '\f195',
			),
			'fa-usd'                                 => array(
				'label'     => 'Usd',
				'category'  => array( 12 ),
				'font_code' => '\f155',
			),
			'fa-won'                                 => array(
				'label'     => 'Won',
				'category'  => array( 12 ),
				'font_code' => '\f159',
			),
			'fa-yen'                                 => array(
				'label'     => 'Yen',
				'category'  => array( 12 ),
				'font_code' => '\f157',
			),
			'fa-align-center'                        => array(
				'label'     => 'Align Center',
				'category'  => array( 13 ),
				'font_code' => '\f037',
			),
			'fa-align-justify'                       => array(
				'label'     => 'Align Justify',
				'category'  => array( 13 ),
				'font_code' => '\f039',
			),
			'fa-align-left'                          => array(
				'label'     => 'Align Left',
				'category'  => array( 13 ),
				'font_code' => '\f036',
			),
			'fa-align-right'                         => array(
				'label'     => 'Align Right',
				'category'  => array( 13 ),
				'font_code' => '\f038',
			),
			'fa-bold'                                => array(
				'label'     => 'Bold',
				'category'  => array( 13 ),
				'font_code' => '\f032',
			),
			'fa-chain'                               => array(
				'label'     => 'Chain',
				'category'  => array( 13 ),
				'font_code' => '\f0c1',
			),
			'fa-chain-broken'                        => array(
				'label'     => 'Chain Broken',
				'category'  => array( 13 ),
				'font_code' => '\f127',
			),
			'fa-clipboard'                           => array(
				'label'     => 'Clipboard',
				'category'  => array( 13 ),
				'font_code' => '\f0ea',
			),
			'fa-columns'                             => array(
				'label'     => 'Columns',
				'category'  => array( 13 ),
				'font_code' => '\f0db',
			),
			'fa-copy'                                => array(
				'label'     => 'Copy',
				'category'  => array( 13 ),
				'font_code' => '\f0c5',
			),
			'fa-cut'                                 => array(
				'label'     => 'Cut',
				'category'  => array( 13 ),
				'font_code' => '\f0c4',
			),
			'fa-dedent'                              => array(
				'label'     => 'Dedent',
				'category'  => array( 13 ),
				'font_code' => '\f03b',
			),
			'fa-files-o'                             => array(
				'label'     => 'Files <span class="text-muted">(Outline)</span>',
				'category'  => array( 13 ),
				'font_code' => '\f0c5',
			),
			'fa-floppy-o'                            => array(
				'label'     => 'Floppy <span class="text-muted">(Outline)</span>',
				'category'  => array( 13 ),
				'font_code' => '\f0c7',
			),
			'fa-font'                                => array(
				'label'     => 'Font',
				'category'  => array( 13 ),
				'font_code' => '\f031',
			),
			'fa-header'                              => array(
				'label'     => 'Header',
				'category'  => array( 13 ),
				'font_code' => '\f1dc',
			),
			'fa-indent'                              => array(
				'label'     => 'Indent',
				'category'  => array( 13 ),
				'font_code' => '\f03c',
			),
			'fa-italic'                              => array(
				'label'     => 'Italic',
				'category'  => array( 13 ),
				'font_code' => '\f033',
			),
			'fa-link'                                => array(
				'label'     => 'Link',
				'category'  => array( 13 ),
				'font_code' => '\f0c1',
			),
			'fa-list'                                => array(
				'label'     => 'List',
				'category'  => array( 13 ),
				'font_code' => '\f03a',
			),
			'fa-list-alt'                            => array(
				'label'     => 'List Alt',
				'category'  => array( 13 ),
				'font_code' => '\f022',
			),
			'fa-list-ol'                             => array(
				'label'     => 'List Ol',
				'category'  => array( 13 ),
				'font_code' => '\f0cb',
			),
			'fa-list-ul'                             => array(
				'label'     => 'List Ul',
				'category'  => array( 13 ),
				'font_code' => '\f0ca',
			),
			'fa-outdent'                             => array(
				'label'     => 'Outdent',
				'category'  => array( 13 ),
				'font_code' => '\f03b',
			),
			'fa-paperclip'                           => array(
				'label'     => 'Paperclip',
				'category'  => array( 13 ),
				'font_code' => '\f0c6',
			),
			'fa-paragraph'                           => array(
				'label'     => 'Paragraph',
				'category'  => array( 13 ),
				'font_code' => '\f1dd',
			),
			'fa-paste'                               => array(
				'label'     => 'Paste',
				'category'  => array( 13 ),
				'font_code' => '\f0ea',
			),
			'fa-repeat'                              => array(
				'label'     => 'Repeat',
				'category'  => array( 13 ),
				'font_code' => '\f01e',
			),
			'fa-rotate-left'                         => array(
				'label'     => 'Rotate Left',
				'category'  => array( 13 ),
				'font_code' => '\f0e2',
			),
			'fa-rotate-right'                        => array(
				'label'     => 'Rotate Right',
				'category'  => array( 13 ),
				'font_code' => '\f01e',
			),
			'fa-save'                                => array(
				'label'     => 'Save',
				'category'  => array( 13 ),
				'font_code' => '\f0c7',
			),
			'fa-scissors'                            => array(
				'label'     => 'Scissors',
				'category'  => array( 13 ),
				'font_code' => '\f0c4',
			),
			'fa-strikethrough'                       => array(
				'label'     => 'Strikethrough',
				'category'  => array( 13 ),
				'font_code' => '\f0cc',
			),
			'fa-subscript'                           => array(
				'label'     => 'Subscript',
				'category'  => array( 13 ),
				'font_code' => '\f12c',
			),
			'fa-superscript'                         => array(
				'label'     => 'Superscript',
				'category'  => array( 13 ),
				'font_code' => '\f12b',
			),
			'fa-table'                               => array(
				'label'     => 'Table',
				'category'  => array( 13 ),
				'font_code' => '\f0ce',
			),
			'fa-text-height'                         => array(
				'label'     => 'Text Height',
				'category'  => array( 13 ),
				'font_code' => '\f034',
			),
			'fa-text-width'                          => array(
				'label'     => 'Text Width',
				'category'  => array( 13 ),
				'font_code' => '\f035',
			),
			'fa-th'                                  => array(
				'label'     => 'Th',
				'category'  => array( 13 ),
				'font_code' => '\f00a',
			),
			'fa-th-large'                            => array(
				'label'     => 'Th Large',
				'category'  => array( 13 ),
				'font_code' => '\f009',
			),
			'fa-th-list'                             => array(
				'label'     => 'Th List',
				'category'  => array( 13 ),
				'font_code' => '\f00b',
			),
			'fa-underline'                           => array(
				'label'     => 'Underline',
				'category'  => array( 13 ),
				'font_code' => '\f0cd',
			),
			'fa-undo'                                => array(
				'label'     => 'Undo',
				'category'  => array( 13 ),
				'font_code' => '\f0e2',
			),
			'fa-unlink'                              => array(
				'label'     => 'Unlink',
				'category'  => array( 13 ),
				'font_code' => '\f127',
			),
			'fa-angle-double-down'                   => array(
				'label'     => 'Angle Double Down',
				'category'  => array( 14 ),
				'font_code' => '\f103',
			),
			'fa-angle-double-left'                   => array(
				'label'     => 'Angle Double Left',
				'category'  => array( 14 ),
				'font_code' => '\f100',
			),
			'fa-angle-double-right'                  => array(
				'label'     => 'Angle Double Right',
				'category'  => array( 14 ),
				'font_code' => '\f101',
			),
			'fa-angle-double-up'                     => array(
				'label'     => 'Angle Double Up',
				'category'  => array( 14 ),
				'font_code' => '\f102',
			),
			'fa-angle-down'                          => array(
				'label'     => 'Angle Down',
				'category'  => array( 14 ),
				'font_code' => '\f107',
			),
			'fa-angle-left'                          => array(
				'label'     => 'Angle Left',
				'category'  => array( 14 ),
				'font_code' => '\f104',
			),
			'fa-angle-right'                         => array(
				'label'     => 'Angle Right',
				'category'  => array( 14 ),
				'font_code' => '\f105',
			),
			'fa-angle-up'                            => array(
				'label'     => 'Angle Up',
				'category'  => array( 14 ),
				'font_code' => '\f106',
			),
			'fa-arrow-circle-down'                   => array(
				'label'     => 'Arrow Circle Down',
				'category'  => array( 14 ),
				'font_code' => '\f0ab',
			),
			'fa-arrow-circle-left'                   => array(
				'label'     => 'Arrow Circle Left',
				'category'  => array( 14 ),
				'font_code' => '\f0a8',
			),
			'fa-arrow-circle-o-down'                 => array(
				'label'     => 'Arrow Circle Down <span class="text-muted">(Outline)</span>',
				'category'  => array( 14 ),
				'font_code' => '\f01a',
			),
			'fa-arrow-circle-o-left'                 => array(
				'label'     => 'Arrow Circle Left <span class="text-muted">(Outline)</span>',
				'category'  => array( 14 ),
				'font_code' => '\f190',
			),
			'fa-arrow-circle-o-right'                => array(
				'label'     => 'Arrow Circle Right <span class="text-muted">(Outline)</span>',
				'category'  => array( 14 ),
				'font_code' => '\f18e',
			),
			'fa-arrow-circle-o-up'                   => array(
				'label'     => 'Arrow Circle Up <span class="text-muted">(Outline)</span>',
				'category'  => array( 14 ),
				'font_code' => '\f01b',
			),
			'fa-arrow-circle-right'                  => array(
				'label'     => 'Arrow Circle Right',
				'category'  => array( 14 ),
				'font_code' => '\f0a9',
			),
			'fa-arrow-circle-up'                     => array(
				'label'     => 'Arrow Circle Up',
				'category'  => array( 14 ),
				'font_code' => '\f0aa',
			),
			'fa-arrow-down'                          => array(
				'label'     => 'Arrow Down',
				'category'  => array( 14 ),
				'font_code' => '\f063',
			),
			'fa-arrow-left'                          => array(
				'label'     => 'Arrow Left',
				'category'  => array( 14 ),
				'font_code' => '\f060',
			),
			'fa-arrow-right'                         => array(
				'label'     => 'Arrow Right',
				'category'  => array( 14 ),
				'font_code' => '\f061',
			),
			'fa-arrow-up'                            => array(
				'label'     => 'Arrow Up',
				'category'  => array( 14 ),
				'font_code' => '\f062',
			),
			'fa-arrows-alt'                          => array(
				'label'     => 'Arrows Alt',
				'category'  => array( 14, 15 ),
				'font_code' => '\f0b2',
			),
			'fa-caret-down'                          => array(
				'label'     => 'Caret Down',
				'category'  => array( 14 ),
				'font_code' => '\f0d7',
			),
			'fa-caret-left'                          => array(
				'label'     => 'Caret Left',
				'category'  => array( 14 ),
				'font_code' => '\f0d9',
			),
			'fa-caret-right'                         => array(
				'label'     => 'Caret Right',
				'category'  => array( 14 ),
				'font_code' => '\f0da',
			),
			'fa-caret-up'                            => array(
				'label'     => 'Caret Up',
				'category'  => array( 14 ),
				'font_code' => '\f0d8',
			),
			'fa-chevron-circle-down'                 => array(
				'label'     => 'Chevron Circle Down',
				'category'  => array( 14 ),
				'font_code' => '\f13a',
			),
			'fa-chevron-circle-left'                 => array(
				'label'     => 'Chevron Circle Left',
				'category'  => array( 14 ),
				'font_code' => '\f137',
			),
			'fa-chevron-circle-right'                => array(
				'label'     => 'Chevron Circle Right',
				'category'  => array( 14 ),
				'font_code' => '\f138',
			),
			'fa-chevron-circle-up'                   => array(
				'label'     => 'Chevron Circle Up',
				'category'  => array( 14 ),
				'font_code' => '\f139',
			),
			'fa-chevron-down'                        => array(
				'label'     => 'Chevron Down',
				'category'  => array( 14 ),
				'font_code' => '\f078',
			),
			'fa-chevron-left'                        => array(
				'label'     => 'Chevron Left',
				'category'  => array( 14 ),
				'font_code' => '\f053',
			),
			'fa-chevron-right'                       => array(
				'label'     => 'Chevron Right',
				'category'  => array( 14 ),
				'font_code' => '\f054',
			),
			'fa-chevron-up'                          => array(
				'label'     => 'Chevron Up',
				'category'  => array( 14 ),
				'font_code' => '\f077',
			),
			'fa-long-arrow-down'                     => array(
				'label'     => 'Long Arrow Down',
				'category'  => array( 14 ),
				'font_code' => '\f175',
			),
			'fa-long-arrow-left'                     => array(
				'label'     => 'Long Arrow Left',
				'category'  => array( 14 ),
				'font_code' => '\f177',
			),
			'fa-long-arrow-right'                    => array(
				'label'     => 'Long Arrow Right',
				'category'  => array( 14 ),
				'font_code' => '\f178',
			),
			'fa-long-arrow-up'                       => array(
				'label'     => 'Long Arrow Up',
				'category'  => array( 14 ),
				'font_code' => '\f176',
			),
			'fa-backward'                            => array(
				'label'     => 'Backward',
				'category'  => array( 15 ),
				'font_code' => '\f04a',
			),
			'fa-compress'                            => array(
				'label'     => 'Compress',
				'category'  => array( 15 ),
				'font_code' => '\f066',
			),
			'fa-eject'                               => array(
				'label'     => 'Eject',
				'category'  => array( 15 ),
				'font_code' => '\f052',
			),
			'fa-expand'                              => array(
				'label'     => 'Expand',
				'category'  => array( 15 ),
				'font_code' => '\f065',
			),
			'fa-fast-backward'                       => array(
				'label'     => 'Fast Backward',
				'category'  => array( 15 ),
				'font_code' => '\f049',
			),
			'fa-fast-forward'                        => array(
				'label'     => 'Fast Forward',
				'category'  => array( 15 ),
				'font_code' => '\f050',
			),
			'fa-forward'                             => array(
				'label'     => 'Forward',
				'category'  => array( 15 ),
				'font_code' => '\f04e',
			),
			'fa-pause'                               => array(
				'label'     => 'Pause',
				'category'  => array( 15 ),
				'font_code' => '\f04c',
			),
			'fa-pause-circle'                        => array(
				'label'     => 'Pause Circle',
				'category'  => array( 15 ),
				'font_code' => '\f28b',
			),
			'fa-pause-circle-o'                      => array(
				'label'     => 'Pause Circle <span class="text-muted">(Outline)</span>',
				'category'  => array( 15 ),
				'font_code' => '\f28c',
			),
			'fa-play'                                => array(
				'label'     => 'Play',
				'category'  => array( 15 ),
				'font_code' => '\f04b',
			),
			'fa-play-circle'                         => array(
				'label'     => 'Play Circle',
				'category'  => array( 15 ),
				'font_code' => '\f144',
			),
			'fa-play-circle-o'                       => array(
				'label'     => 'Play Circle <span class="text-muted">(Outline)</span>',
				'category'  => array( 15 ),
				'font_code' => '\f01d',
			),
			'fa-step-backward'                       => array(
				'label'     => 'Step Backward',
				'category'  => array( 15 ),
				'font_code' => '\f048',
			),
			'fa-step-forward'                        => array(
				'label'     => 'Step Forward',
				'category'  => array( 15 ),
				'font_code' => '\f051',
			),
			'fa-stop'                                => array(
				'label'     => 'Stop',
				'category'  => array( 15 ),
				'font_code' => '\f04d',
			),
			'fa-stop-circle'                         => array(
				'label'     => 'Stop Circle',
				'category'  => array( 15 ),
				'font_code' => '\f28d',
			),
			'fa-stop-circle-o'                       => array(
				'label'     => 'Stop Circle <span class="text-muted">(Outline)</span>',
				'category'  => array( 15 ),
				'font_code' => '\f28e',
			),
			'fa-youtube-play'                        => array(
				'label'     => 'Youtube Play',
				'category'  => array( 15, 16 ),
				'font_code' => '\f16a',
			),
			'fa-500px'                               => array(
				'label'     => '500px',
				'category'  => array( 16 ),
				'font_code' => '\f26e',
			),
			'fa-adn'                                 => array(
				'label'     => 'Adn',
				'category'  => array( 16 ),
				'font_code' => '\f170',
			),
			'fa-amazon'                              => array(
				'label'     => 'Amazon',
				'category'  => array( 16 ),
				'font_code' => '\f270',
			),
			'fa-android'                             => array(
				'label'     => 'Android',
				'category'  => array( 16 ),
				'font_code' => '\f17b',
			),
			'fa-angellist'                           => array(
				'label'     => 'Angellist',
				'category'  => array( 16 ),
				'font_code' => '\f209',
			),
			'fa-apple'                               => array(
				'label'     => 'Apple',
				'category'  => array( 16 ),
				'font_code' => '\f179',
			),
			'fa-behance'                             => array(
				'label'     => 'Behance',
				'category'  => array( 16 ),
				'font_code' => '\f1b4',
			),
			'fa-behance-square'                      => array(
				'label'     => 'Behance Square',
				'category'  => array( 16 ),
				'font_code' => '\f1b5',
			),
			'fa-bitbucket'                           => array(
				'label'     => 'Bitbucket',
				'category'  => array( 16 ),
				'font_code' => '\f171',
			),
			'fa-bitbucket-square'                    => array(
				'label'     => 'Bitbucket Square',
				'category'  => array( 16 ),
				'font_code' => '\f172',
			),
			'fa-black-tie'                           => array(
				'label'     => 'Black Tie',
				'category'  => array( 16 ),
				'font_code' => '\f27e',
			),
			'fa-buysellads'                          => array(
				'label'     => 'Buysellads',
				'category'  => array( 16 ),
				'font_code' => '\f20d',
			),
			'fa-chrome'                              => array(
				'label'     => 'Chrome',
				'category'  => array( 16 ),
				'font_code' => '\f268',
			),
			'fa-codepen'                             => array(
				'label'     => 'Codepen',
				'category'  => array( 16 ),
				'font_code' => '\f1cb',
			),
			'fa-codiepie'                            => array(
				'label'     => 'Codiepie',
				'category'  => array( 16 ),
				'font_code' => '\f284',
			),
			'fa-connectdevelop'                      => array(
				'label'     => 'Connectdevelop',
				'category'  => array( 16 ),
				'font_code' => '\f20e',
			),
			'fa-contao'                              => array(
				'label'     => 'Contao',
				'category'  => array( 16 ),
				'font_code' => '\f26d',
			),
			'fa-css3'                                => array(
				'label'     => 'Css3',
				'category'  => array( 16 ),
				'font_code' => '\f13c',
			),
			'fa-dashcube'                            => array(
				'label'     => 'Dashcube',
				'category'  => array( 16 ),
				'font_code' => '\f210',
			),
			'fa-delicious'                           => array(
				'label'     => 'Delicious',
				'category'  => array( 16 ),
				'font_code' => '\f1a5',
			),
			'fa-deviantart'                          => array(
				'label'     => 'Deviantart',
				'category'  => array( 16 ),
				'font_code' => '\f1bd',
			),
			'fa-digg'                                => array(
				'label'     => 'Digg',
				'category'  => array( 16 ),
				'font_code' => '\f1a6',
			),
			'fa-dribbble'                            => array(
				'label'     => 'Dribbble',
				'category'  => array( 16 ),
				'font_code' => '\f17d',
			),
			'fa-dropbox'                             => array(
				'label'     => 'Dropbox',
				'category'  => array( 16 ),
				'font_code' => '\f16b',
			),
			'fa-drupal'                              => array(
				'label'     => 'Drupal',
				'category'  => array( 16 ),
				'font_code' => '\f1a9',
			),
			'fa-edge'                                => array(
				'label'     => 'Edge',
				'category'  => array( 16 ),
				'font_code' => '\f282',
			),
			'fa-empire'                              => array(
				'label'     => 'Empire',
				'category'  => array( 16 ),
				'font_code' => '\f1d1',
			),
			'fa-envira'                              => array(
				'label'     => 'Envira',
				'category'  => array( 16 ),
				'font_code' => '\f299',
			),
			'fa-expeditedssl'                        => array(
				'label'     => 'Expeditedssl',
				'category'  => array( 16 ),
				'font_code' => '\f23e',
			),
			'fa-fa'                                  => array(
				'label'     => 'Fa',
				'category'  => array( 16 ),
				'font_code' => '\f2b4',
			),
			'fa-facebook'                            => array(
				'label'     => 'Facebook',
				'category'  => array( 16 ),
				'font_code' => '\f09a',
			),
			'fa-facebook-f'                          => array(
				'label'     => 'Facebook F',
				'category'  => array( 16 ),
				'font_code' => '\f09a',
			),
			'fa-facebook-official'                   => array(
				'label'     => 'Facebook Official',
				'category'  => array( 16 ),
				'font_code' => '\f230',
			),
			'fa-facebook-square'                     => array(
				'label'     => 'Facebook Square',
				'category'  => array( 16 ),
				'font_code' => '\f082',
			),
			'fa-firefox'                             => array(
				'label'     => 'Firefox',
				'category'  => array( 16 ),
				'font_code' => '\f269',
			),
			'fa-first-order'                         => array(
				'label'     => 'First Order',
				'category'  => array( 16 ),
				'font_code' => '\f2b0',
			),
			'fa-flickr'                              => array(
				'label'     => 'Flickr',
				'category'  => array( 16 ),
				'font_code' => '\f16e',
			),
			'fa-font-awesome'                        => array(
				'label'     => 'Font Awesome',
				'category'  => array( 16 ),
				'font_code' => '\f2b4',
			),
			'fa-fonticons'                           => array(
				'label'     => 'Fonticons',
				'category'  => array( 16 ),
				'font_code' => '\f280',
			),
			'fa-fort-awesome'                        => array(
				'label'     => 'Fort Awesome',
				'category'  => array( 16 ),
				'font_code' => '\f286',
			),
			'fa-forumbee'                            => array(
				'label'     => 'Forumbee',
				'category'  => array( 16 ),
				'font_code' => '\f211',
			),
			'fa-foursquare'                          => array(
				'label'     => 'Foursquare',
				'category'  => array( 16 ),
				'font_code' => '\f180',
			),
			'fa-ge'                                  => array(
				'label'     => 'Ge',
				'category'  => array( 16 ),
				'font_code' => '\f1d1',
			),
			'fa-get-pocket'                          => array(
				'label'     => 'Get Pocket',
				'category'  => array( 16 ),
				'font_code' => '\f265',
			),
			'fa-git'                                 => array(
				'label'     => 'Git',
				'category'  => array( 16 ),
				'font_code' => '\f1d3',
			),
			'fa-git-square'                          => array(
				'label'     => 'Git Square',
				'category'  => array( 16 ),
				'font_code' => '\f1d2',
			),
			'fa-github'                              => array(
				'label'     => 'Github',
				'category'  => array( 16 ),
				'font_code' => '\f09b',
			),
			'fa-github-alt'                          => array(
				'label'     => 'Github Alt',
				'category'  => array( 16 ),
				'font_code' => '\f113',
			),
			'fa-github-square'                       => array(
				'label'     => 'Github Square',
				'category'  => array( 16 ),
				'font_code' => '\f092',
			),
			'fa-gitlab'                              => array(
				'label'     => 'Gitlab',
				'category'  => array( 16 ),
				'font_code' => '\f296',
			),
			'fa-gittip'                              => array(
				'label'     => 'Gittip',
				'category'  => array( 16 ),
				'font_code' => '\f184',
			),
			'fa-glide'                               => array(
				'label'     => 'Glide',
				'category'  => array( 16 ),
				'font_code' => '\f2a5',
			),
			'fa-glide-g'                             => array(
				'label'     => 'Glide G',
				'category'  => array( 16 ),
				'font_code' => '\f2a6',
			),
			'fa-google'                              => array(
				'label'     => 'Google',
				'category'  => array( 16 ),
				'font_code' => '\f1a0',
			),
			'fa-google-plus'                         => array(
				'label'     => 'Google Plus',
				'category'  => array( 16 ),
				'font_code' => '\f0d5',
			),
			'fa-google-plus-circle'                  => array(
				'label'     => 'Google Plus Circle',
				'category'  => array( 16 ),
				'font_code' => '\f2b3',
			),
			'fa-google-plus-official'                => array(
				'label'     => 'Google Plus Official',
				'category'  => array( 16 ),
				'font_code' => '\f2b3',
			),
			'fa-google-plus-square'                  => array(
				'label'     => 'Google Plus Square',
				'category'  => array( 16 ),
				'font_code' => '\f0d4',
			),
			'fa-gratipay'                            => array(
				'label'     => 'Gratipay',
				'category'  => array( 16 ),
				'font_code' => '\f184',
			),
			'fa-hacker-news'                         => array(
				'label'     => 'Hacker News',
				'category'  => array( 16 ),
				'font_code' => '\f1d4',
			),
			'fa-houzz'                               => array(
				'label'     => 'Houzz',
				'category'  => array( 16 ),
				'font_code' => '\f27c',
			),
			'fa-html5'                               => array(
				'label'     => 'Html5',
				'category'  => array( 16 ),
				'font_code' => '\f13b',
			),
			'fa-instagram'                           => array(
				'label'     => 'Instagram',
				'category'  => array( 16 ),
				'font_code' => '\f16d',
			),
			'fa-internet-explorer'                   => array(
				'label'     => 'Internet Explorer',
				'category'  => array( 16 ),
				'font_code' => '\f26b',
			),
			'fa-ioxhost'                             => array(
				'label'     => 'Ioxhost',
				'category'  => array( 16 ),
				'font_code' => '\f208',
			),
			'fa-joomla'                              => array(
				'label'     => 'Joomla',
				'category'  => array( 16 ),
				'font_code' => '\f1aa',
			),
			'fa-jsfiddle'                            => array(
				'label'     => 'Jsfiddle',
				'category'  => array( 16 ),
				'font_code' => '\f1cc',
			),
			'fa-lastfm'                              => array(
				'label'     => 'Lastfm',
				'category'  => array( 16 ),
				'font_code' => '\f202',
			),
			'fa-lastfm-square'                       => array(
				'label'     => 'Lastfm Square',
				'category'  => array( 16 ),
				'font_code' => '\f203',
			),
			'fa-leanpub'                             => array(
				'label'     => 'Leanpub',
				'category'  => array( 16 ),
				'font_code' => '\f212',
			),
			'fa-linkedin'                            => array(
				'label'     => 'Linkedin',
				'category'  => array( 16 ),
				'font_code' => '\f0e1',
			),
			'fa-linkedin-square'                     => array(
				'label'     => 'Linkedin Square',
				'category'  => array( 16 ),
				'font_code' => '\f08c',
			),
			'fa-linux'                               => array(
				'label'     => 'Linux',
				'category'  => array( 16 ),
				'font_code' => '\f17c',
			),
			'fa-maxcdn'                              => array(
				'label'     => 'Maxcdn',
				'category'  => array( 16 ),
				'font_code' => '\f136',
			),
			'fa-meanpath'                            => array(
				'label'     => 'Meanpath',
				'category'  => array( 16 ),
				'font_code' => '\f20c',
			),
			'fa-medium'                              => array(
				'label'     => 'Medium',
				'category'  => array( 16 ),
				'font_code' => '\f23a',
			),
			'fa-mixcloud'                            => array(
				'label'     => 'Mixcloud',
				'category'  => array( 16 ),
				'font_code' => '\f289',
			),
			'fa-modx'                                => array(
				'label'     => 'Modx',
				'category'  => array( 16 ),
				'font_code' => '\f285',
			),
			'fa-odnoklassniki'                       => array(
				'label'     => 'Odnoklassniki',
				'category'  => array( 16 ),
				'font_code' => '\f263',
			),
			'fa-odnoklassniki-square'                => array(
				'label'     => 'Odnoklassniki Square',
				'category'  => array( 16 ),
				'font_code' => '\f264',
			),
			'fa-opencart'                            => array(
				'label'     => 'Opencart',
				'category'  => array( 16 ),
				'font_code' => '\f23d',
			),
			'fa-openid'                              => array(
				'label'     => 'Openid',
				'category'  => array( 16 ),
				'font_code' => '\f19b',
			),
			'fa-opera'                               => array(
				'label'     => 'Opera',
				'category'  => array( 16 ),
				'font_code' => '\f26a',
			),
			'fa-optin-monster'                       => array(
				'label'     => 'Optin Monster',
				'category'  => array( 16 ),
				'font_code' => '\f23c',
			),
			'fa-pagelines'                           => array(
				'label'     => 'Pagelines',
				'category'  => array( 16 ),
				'font_code' => '\f18c',
			),
			'fa-pied-piper'                          => array(
				'label'     => 'Pied Piper',
				'category'  => array( 16 ),
				'font_code' => '\f2ae',
			),
			'fa-pied-piper-alt'                      => array(
				'label'     => 'Pied Piper Alt',
				'category'  => array( 16 ),
				'font_code' => '\f1a8',
			),
			'fa-pied-piper-pp'                       => array(
				'label'     => 'Pied Piper Pp',
				'category'  => array( 16 ),
				'font_code' => '\f1a7',
			),
			'fa-pinterest'                           => array(
				'label'     => 'Pinterest',
				'category'  => array( 16 ),
				'font_code' => '\f0d2',
			),
			'fa-pinterest-p'                         => array(
				'label'     => 'Pinterest P',
				'category'  => array( 16 ),
				'font_code' => '\f231',
			),
			'fa-pinterest-square'                    => array(
				'label'     => 'Pinterest Square',
				'category'  => array( 16 ),
				'font_code' => '\f0d3',
			),
			'fa-product-hunt'                        => array(
				'label'     => 'Product Hunt',
				'category'  => array( 16 ),
				'font_code' => '\f288',
			),
			'fa-qq'                                  => array(
				'label'     => 'Qq',
				'category'  => array( 16 ),
				'font_code' => '\f1d6',
			),
			'fa-ra'                                  => array(
				'label'     => 'Ra',
				'category'  => array( 16 ),
				'font_code' => '\f1d0',
			),
			'fa-rebel'                               => array(
				'label'     => 'Rebel',
				'category'  => array( 16 ),
				'font_code' => '\f1d0',
			),
			'fa-reddit'                              => array(
				'label'     => 'Reddit',
				'category'  => array( 16 ),
				'font_code' => '\f1a1',
			),
			'fa-reddit-alien'                        => array(
				'label'     => 'Reddit Alien',
				'category'  => array( 16 ),
				'font_code' => '\f281',
			),
			'fa-reddit-square'                       => array(
				'label'     => 'Reddit Square',
				'category'  => array( 16 ),
				'font_code' => '\f1a2',
			),
			'fa-renren'                              => array(
				'label'     => 'Renren',
				'category'  => array( 16 ),
				'font_code' => '\f18b',
			),
			'fa-resistance'                          => array(
				'label'     => 'Resistance',
				'category'  => array( 16 ),
				'font_code' => '\f1d0',
			),
			'fa-safari'                              => array(
				'label'     => 'Safari',
				'category'  => array( 16 ),
				'font_code' => '\f267',
			),
			'fa-scribd'                              => array(
				'label'     => 'Scribd',
				'category'  => array( 16 ),
				'font_code' => '\f28a',
			),
			'fa-sellsy'                              => array(
				'label'     => 'Sellsy',
				'category'  => array( 16 ),
				'font_code' => '\f213',
			),
			'fa-shirtsinbulk'                        => array(
				'label'     => 'Shirtsinbulk',
				'category'  => array( 16 ),
				'font_code' => '\f214',
			),
			'fa-simplybuilt'                         => array(
				'label'     => 'Simplybuilt',
				'category'  => array( 16 ),
				'font_code' => '\f215',
			),
			'fa-skyatlas'                            => array(
				'label'     => 'Skyatlas',
				'category'  => array( 16 ),
				'font_code' => '\f216',
			),
			'fa-skype'                               => array(
				'label'     => 'Skype',
				'category'  => array( 16 ),
				'font_code' => '\f17e',
			),
			'fa-slack'                               => array(
				'label'     => 'Slack',
				'category'  => array( 16 ),
				'font_code' => '\f198',
			),
			'fa-slideshare'                          => array(
				'label'     => 'Slideshare',
				'category'  => array( 16 ),
				'font_code' => '\f1e7',
			),
			'fa-snapchat'                            => array(
				'label'     => 'Snapchat',
				'category'  => array( 16 ),
				'font_code' => '\f2ab',
			),
			'fa-snapchat-ghost'                      => array(
				'label'     => 'Snapchat Ghost',
				'category'  => array( 16 ),
				'font_code' => '\f2ac',
			),
			'fa-snapchat-square'                     => array(
				'label'     => 'Snapchat Square',
				'category'  => array( 16 ),
				'font_code' => '\f2ad',
			),
			'fa-soundcloud'                          => array(
				'label'     => 'Soundcloud',
				'category'  => array( 16 ),
				'font_code' => '\f1be',
			),
			'fa-spotify'                             => array(
				'label'     => 'Spotify',
				'category'  => array( 16 ),
				'font_code' => '\f1bc',
			),
			'fa-stack-exchange'                      => array(
				'label'     => 'Stack Exchange',
				'category'  => array( 16 ),
				'font_code' => '\f18d',
			),
			'fa-stack-overflow'                      => array(
				'label'     => 'Stack Overflow',
				'category'  => array( 16 ),
				'font_code' => '\f16c',
			),
			'fa-steam'                               => array(
				'label'     => 'Steam',
				'category'  => array( 16 ),
				'font_code' => '\f1b6',
			),
			'fa-steam-square'                        => array(
				'label'     => 'Steam Square',
				'category'  => array( 16 ),
				'font_code' => '\f1b7',
			),
			'fa-stumbleupon'                         => array(
				'label'     => 'Stumbleupon',
				'category'  => array( 16 ),
				'font_code' => '\f1a4',
			),
			'fa-stumbleupon-circle'                  => array(
				'label'     => 'Stumbleupon Circle',
				'category'  => array( 16 ),
				'font_code' => '\f1a3',
			),
			'fa-tencent-weibo'                       => array(
				'label'     => 'Tencent Weibo',
				'category'  => array( 16 ),
				'font_code' => '\f1d5',
			),
			'fa-themeisle'                           => array(
				'label'     => 'Themeisle',
				'category'  => array( 16 ),
				'font_code' => '\f2b2',
			),
			'fa-trello'                              => array(
				'label'     => 'Trello',
				'category'  => array( 16 ),
				'font_code' => '\f181',
			),
			'fa-tripadvisor'                         => array(
				'label'     => 'Tripadvisor',
				'category'  => array( 16 ),
				'font_code' => '\f262',
			),
			'fa-tumblr'                              => array(
				'label'     => 'Tumblr',
				'category'  => array( 16 ),
				'font_code' => '\f173',
			),
			'fa-tumblr-square'                       => array(
				'label'     => 'Tumblr Square',
				'category'  => array( 16 ),
				'font_code' => '\f174',
			),
			'fa-twitch'                              => array(
				'label'     => 'Twitch',
				'category'  => array( 16 ),
				'font_code' => '\f1e8',
			),
			'fa-twitter'                             => array(
				'label'     => 'Twitter',
				'category'  => array( 16 ),
				'font_code' => '\f099',
			),
			'fa-twitter-square'                      => array(
				'label'     => 'Twitter Square',
				'category'  => array( 16 ),
				'font_code' => '\f081',
			),
			'fa-usb'                                 => array(
				'label'     => 'Usb',
				'category'  => array( 16 ),
				'font_code' => '\f287',
			),
			'fa-viacoin'                             => array(
				'label'     => 'Viacoin',
				'category'  => array( 16 ),
				'font_code' => '\f237',
			),
			'fa-viadeo'                              => array(
				'label'     => 'Viadeo',
				'category'  => array( 16 ),
				'font_code' => '\f2a9',
			),
			'fa-viadeo-square'                       => array(
				'label'     => 'Viadeo Square',
				'category'  => array( 16 ),
				'font_code' => '\f2aa',
			),
			'fa-vimeo'                               => array(
				'label'     => 'Vimeo',
				'category'  => array( 16 ),
				'font_code' => '\f27d',
			),
			'fa-vimeo-square'                        => array(
				'label'     => 'Vimeo Square',
				'category'  => array( 16 ),
				'font_code' => '\f194',
			),
			'fa-vine'                                => array(
				'label'     => 'Vine',
				'category'  => array( 16 ),
				'font_code' => '\f1ca',
			),
			'fa-vk'                                  => array(
				'label'     => 'Vk',
				'category'  => array( 16 ),
				'font_code' => '\f189',
			),
			'fa-wechat'                              => array(
				'label'     => 'Wechat',
				'category'  => array( 16 ),
				'font_code' => '\f1d7',
			),
			'fa-weibo'                               => array(
				'label'     => 'Weibo',
				'category'  => array( 16 ),
				'font_code' => '\f18a',
			),
			'fa-weixin'                              => array(
				'label'     => 'Weixin',
				'category'  => array( 16 ),
				'font_code' => '\f1d7',
			),
			'fa-whatsapp'                            => array(
				'label'     => 'Whatsapp',
				'category'  => array( 16 ),
				'font_code' => '\f232',
			),
			'fa-wikipedia-w'                         => array(
				'label'     => 'Wikipedia W',
				'category'  => array( 16 ),
				'font_code' => '\f266',
			),
			'fa-windows'                             => array(
				'label'     => 'Windows',
				'category'  => array( 16 ),
				'font_code' => '\f17a',
			),
			'fa-wordpress'                           => array(
				'label'     => 'Wordpress',
				'category'  => array( 16 ),
				'font_code' => '\f19a',
			),
			'fa-wpbeginner'                          => array(
				'label'     => 'Wpbeginner',
				'category'  => array( 16 ),
				'font_code' => '\f297',
			),
			'fa-wpforms'                             => array(
				'label'     => 'Wpforms',
				'category'  => array( 16 ),
				'font_code' => '\f298',
			),
			'fa-xing'                                => array(
				'label'     => 'Xing',
				'category'  => array( 16 ),
				'font_code' => '\f168',
			),
			'fa-xing-square'                         => array(
				'label'     => 'Xing Square',
				'category'  => array( 16 ),
				'font_code' => '\f169',
			),
			'fa-y-combinator'                        => array(
				'label'     => 'Y Combinator',
				'category'  => array( 16 ),
				'font_code' => '\f23b',
			),
			'fa-y-combinator-square'                 => array(
				'label'     => 'Y Combinator Square',
				'category'  => array( 16 ),
				'font_code' => '\f1d4',
			),
			'fa-yahoo'                               => array(
				'label'     => 'Yahoo',
				'category'  => array( 16 ),
				'font_code' => '\f19e',
			),
			'fa-yc'                                  => array(
				'label'     => 'Yc',
				'category'  => array( 16 ),
				'font_code' => '\f23b',
			),
			'fa-yc-square'                           => array(
				'label'     => 'Yc Square',
				'category'  => array( 16 ),
				'font_code' => '\f1d4',
			),
			'fa-yelp'                                => array(
				'label'     => 'Yelp',
				'category'  => array( 16 ),
				'font_code' => '\f1e9',
			),
			'fa-yoast'                               => array(
				'label'     => 'Yoast',
				'category'  => array( 16 ),
				'font_code' => '\f2b1',
			),
			'fa-youtube'                             => array(
				'label'     => 'Youtube',
				'category'  => array( 16 ),
				'font_code' => '\f167',
			),
			'fa-youtube-square'                      => array(
				'label'     => 'Youtube Square',
				'category'  => array( 16 ),
				'font_code' => '\f166',
			),
			'fa-h-square'                            => array(
				'label'     => 'H Square',
				'category'  => array( 17 ),
				'font_code' => '\f0fd',
			),
			'fa-hospital-o'                          => array(
				'label'     => 'Hospital <span class="text-muted">(Outline)</span>',
				'category'  => array( 17 ),
				'font_code' => '\f0f8',
			),
			'fa-medkit'                              => array(
				'label'     => 'Medkit',
				'category'  => array( 17 ),
				'font_code' => '\f0fa',
			),
			'fa-stethoscope'                         => array(
				'label'     => 'Stethoscope',
				'category'  => array( 17 ),
				'font_code' => '\f0f1',
			),
			'fa-user-md'                             => array(
				'label'     => 'User Md',
				'category'  => array( 17 ),
				'font_code' => '\f0f0',
			),
		);

		// Count each category icons
		$this->countCategoriesIcons();

	}


	/**
	 * Counts icons in each category
	 */
	function countCategoriesIcons() {

		foreach ( (array) $this->icons as $icon ) {

			if ( isset( $icon['category'] ) && bf_count( $icon['category'] ) ) {

				foreach ( $icon['category'] as $key => $category ) {

					if ( ! isset( $this->categories[ $category ] ) ) {
						continue;
					}

					if ( isset( $this->categories[ $category ]['counts'] ) ) {
						$this->categories[ $category ]['counts'] = intval( $this->categories[ $category ]['counts'] ) + 1;
					} else {
						$this->categories[ $category ]['counts'] = 1;
					}
				}
			}
		}

	}


	/**
	 * Generate tag icon
	 *
	 * @param $icon_key
	 * @param $classes
	 *
	 * @return string
	 */
	function getIconTag( $icon_key, $classes = '' ) {

		$classes = apply_filters( 'better_fontawesome_icons_classes', $classes );

		if ( ! isset( $this->icons[ $icon_key ] ) ) {
			return '';
		}

		return '<i class="bf-icon fa ' . $icon_key . ' ' . $classes . '"></i>';

	}
}
libs/better-framework/libs/class-bf-breadcrumb.php000064400000130262151214002540016213 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * BF Breadcrumb is cloned from "Breadcrumb Trail" and changed to be useful for our projects
 *
 * Home: https://github.com/aliaghdam/breadcrumb-trail
 *
 * @package          BF Breadcrumb
 * @parent_package   BreadcrumbTrail
 * @version          1.3.0
 * @link             https://github.com/aliaghdam/breadcrumb-trail
 * @link             http://themehybrid.com/plugins/breadcrumb-trail
 * @license          http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 */
class BF_Breadcrumb {

	/**
	 * Array of items belonging to the current breadcrumb trail.
	 *
	 * @since  0.1.0
	 * @access public
	 * @var    array
	 */
	public $items = array();

	/**
	 * Arguments used to build the breadcrumb trail.
	 *
	 * @since  0.1.0
	 * @access public
	 * @var    array
	 */
	public $args = array();

	/**
	 * Array of text labels.
	 *
	 * @since  1.0.0
	 * @access public
	 * @var    array
	 */
	public $labels = array();

	/**
	 * Array of post types (key) and taxonomies (value) to use for single post views.
	 *
	 * @since  1.0.0
	 * @access public
	 * @var    array
	 */
	public $post_taxonomy = array();

	/**
	 * A tag format
	 *
	 * @var string
	 */
	public $a_format = '<a itemprop="item" href="%s">%s</a>';

	/**
	 * A tag format
	 *
	 * @var string
	 */
	public $a_format_n = '<a href="%s">%s</a>';

	/**
	 * A tag format + rel
	 *
	 * @var string
	 */
	public $a_format_rel = '<a itemprop="item" href="%s" rel="%s">%s</a>';

	/**
	 * A tag format + rel
	 *
	 * @var string
	 */
	public $a_format_rel_n = '<a href="%s" rel="%s">%s</a>';

	/* ====== Magic Methods ====== */

	/**
	 * Magic method to use in case someone tries to output the layout object as a string.
	 * We'll just return the trail HTML.
	 *
	 * @since  1.0.0
	 * @access public
	 * @return string
	 */
	public function __toString() {

		return $this->trail();
	}


	/**
	 * Sets up the breadcrumb properties.  Calls the `BF_Breadcrumb::add_items()` method
	 * to creat the array of breadcrumb items.
	 *
	 * @since    0.6.0
	 * @access   public
	 *
	 * @internal param array $args {
	 *
	 * @internal param string $container Container HTML element. nav|div
	 * @internal param string $before String to output before breadcrumb menu.
	 * @internal param string $after String to output after breadcrumb menu.
	 * @internal param bool $show_on_front Whether to show when `is_front_page()`.
	 * @internal param bool $network Whether to link to the network main site (multisite only).
	 * @internal param bool $show_title Whether to show the title (last item) in the trail.
	 * @internal param bool $show_browse Whether to show the breadcrumb menu header.
	 * @internal param array $labels Text labels. @see BF_Breadcrumb::set_labels()
	 * @internal param array $post_taxonomy Taxonomies to use for post types. @see BF_Breadcrumb::set_post_taxonomy()
	 * @internal param bool $echo Whether to print or return the breadcrumbs.
	 *         }
	 */
	public function __construct() {

		$defaults = array(
			'container'         => 'nav',
			'before'            => '',
			'after'             => '',
			'show_on_front'     => true,
			'network'           => false,
			'show_title'        => true,
			'show_browse'       => false,
			'labels'            => array(),
			'post_taxonomy'     => array(),
			'echo'              => true,
			// added
			'show_date_in_post' => false,
			'custom_class'      => '',
		);

		$this->args = apply_filters( 'better-framework/breadcrumb/options', $defaults );

		$this->labels = $this->args['labels'];
		unset( $this->args['lables'] );

		$this->post_taxonomy = $this->args['post_taxonomy'];
	}


	/* ====== Public Methods ====== */

	/**
	 * Generates breadcrumb.
	 *
	 * @param array $args
	 */
	public function generate( $args = array() ) {

		$this->args = bf_merge_args( $args, $this->args );

		$this->add_items();

		$this->trail();
	}


	/**
	 * Formats the HTML output for the breadcrumb trail.
	 *
	 * @since  0.6.0
	 * @access public
	 * @return string
	 */
	public function trail() {

		// Set up variables that we'll need.
		$breadcrumb       = '';
		$breadcrumb_items = '';
		$item_count       = bf_count( $this->items );
		$item_position    = 0;

		// Connect the breadcrumb trail if there are items in the trail.
		if ( $item_count ) {

			// Loop through the items and add them to the list.
			foreach ( $this->items as $k => $item ) {

				$_item = '';

				if ( ! isset( $item['before'] ) ) {
					$item['before'] = '';
				}

				if ( ! isset( $item['after'] ) ) {
					$item['after'] = '';
				}

				// Iterate the item position.
				$item_position ++;

				$_item .= "<span itemprop=\"name\">{$item['name']}</span>";

				// Add list item classes.
				$item_class = 'bf-breadcrumb-item';

				// begin and end classes
				if ( 1 === $item_position ) {
					$item_class .= ' bf-breadcrumb-begin';
				} elseif ( ( $item_count - 1 ) === $k ) {
					$item_class .= ' bf-breadcrumb-end';
				}

				if ( ! empty( $item['link'] ) ) {

					if ( ! empty( $item['type'] ) && $item['type'] == 'current' && ! empty( $item['link'] ) ) {
						$_item = sprintf( '%s<meta itemprop="item" content="%s"/>', $_item, $item['link'] );
					} else {

						// Custom rel attribute
						$rel = '';
						if ( ! empty( $item['rel'] ) ) {
							$rel = 'rel="' . $item['rel'] . '"';
						}

						$_item = sprintf( '<a itemprop="item" href="%s" %s>%s</a>', $item['link'], $rel, $_item );
					}
				}

                // Build the meta position HTML.
                $_item .= sprintf( '<meta itemprop="position" content="%s" />', absint( $item_position ) );

                // Build the list item.
				$breadcrumb_items .= sprintf( '<li itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem" class="%s">%s</li>', $item_class, $_item );
			}

			// Add 'browse' label if it should be shown.
			if ( true === $this->args['show_browse'] ) {
				$breadcrumb .= sprintf( '<h2 class="bf-breadcrumb-browse">%s</h2>', $this->labels['browse'] );
			}

			// Open the unordered list.
			$breadcrumb .= '<ul class="bf-breadcrumb-items" itemscope itemtype="http://schema.org/BreadcrumbList">';

			// Add the number of items and item list order schema.
			$breadcrumb .= sprintf( '<meta name="numberOfItems" content="%d" />', absint( $item_position ) );
			$breadcrumb .= '<meta name="itemListOrder" content="Ascending" />';

			$breadcrumb .= $breadcrumb_items;

			// Close the unordered list.
			$breadcrumb .= '</ul>';

			// Wrap the breadcrumb trail.
			$breadcrumb = sprintf(
				'<%1$s role="navigation" aria-label="%2$s" class="bf-breadcrumb clearfix %3$s">%4$s%5$s%6$s</%1$s>',
				tag_escape( $this->args['container'] ),
				esc_attr( $this->labels['aria_label'] ),
				$this->args['custom_class'],
				$this->args['before'],
				$breadcrumb,
				$this->args['after']
			);
		}

		if ( false === $this->args['echo'] ) {
			return $breadcrumb;
		}

		echo $breadcrumb;
	}

	/* ====== Protected Methods ====== */

	/**
	 * Sets the labels property.  Parses the inputted labels array with the defaults.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @return void
	 */
	protected function set_labels() {

		$defaults = array(
			'browse'              => esc_html__( 'Browse:', 'better-studio' ),
			'aria_label'          => esc_attr_x( 'Breadcrumbs', 'breadcrumbs aria label', 'better-studio' ),
			'home'                => esc_html__( 'Home', 'better-studio' ),
			'error_404'           => esc_html__( '404 Not Found', 'better-studio' ),
			'archives'            => esc_html__( 'Archives', 'better-studio' ),
			// Translators: %s is the search query. The HTML entities are opening and closing curly quotes.
			'search'              => esc_html__( 'Search results for &#8220;%s&#8221;', 'better-studio' ),
			// Translators: %s is the page number.
			'paged'               => esc_html__( 'Page %s', 'better-studio' ),
			// Translators: Minute archive title. %s is the minute time format.
			'archive_minute'      => esc_html__( 'Minute %s', 'better-studio' ),
			// Translators: Weekly archive title. %s is the week date format.
			'archive_week'        => esc_html__( 'Week %s', 'better-studio' ),

			// "%s" is replaced with the translated date/time format.
			'archive_minute_hour' => '%s',
			'archive_hour'        => '%s',
			'archive_day'         => '%s',
			'archive_month'       => '%s',
			'archive_year'        => '%s',
		);

		$this->labels = apply_filters( 'bf_breadcrumb_labels', wp_parse_args( $this->args['labels'], $defaults ) );
	}


	/**
	 * Sets the `$post_taxonomy` property.  This is an array of post types (key) and taxonomies (value).
	 * The taxonomy's terms are shown on the singular post view if set.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @return void
	 */
	protected function set_post_taxonomy() {

		$defaults = array();

		// If post permalink is set to `%postname%`, use the `category` taxonomy.
		if ( '%postname%' === trim( get_option( 'permalink_structure' ), '/' ) ) {
			$defaults['post'] = 'category';
		}

		$this->post_taxonomy = apply_filters( 'bf_breadcrumb_post_taxonomy', wp_parse_args( $this->args['post_taxonomy'], $defaults ) );
	}


	/**
	 * Runs through the various WordPress conditional tags to check the current page being viewed.  Once
	 * a condition is met, a specific method is launched to add items to the `$items` array.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @return void
	 */
	protected function add_items() {

		// If viewing the front page.
		if ( is_front_page() ) {
			$this->add_front_page_items();
		} // If not viewing the front page.
		else {

			// Add the network and site home links.
			$this->add_network_home_link();
			$this->add_site_home_link();

			// If viewing the home/blog page.
			if ( is_home() ) {
				$this->add_posts_page_items();
			} // bbPress custom pages
			elseif ( function_exists( 'is_bbpress' ) && is_bbpress() ) {
				$this->add_bbpress_items();
			} // If viewing a single post.
			elseif ( is_singular() ) {
				$this->add_singular_items();
			} // If viewing an archive page.
			elseif ( is_archive() ) {

				if ( is_post_type_archive() ) {
					$this->add_post_type_archive_items();
				} elseif ( is_category() || is_tag() || is_tax() ) {
					$this->add_term_archive_items();
				} elseif ( is_author() ) {
					$this->add_user_archive_items();
				} elseif ( get_query_var( 'minute' ) && get_query_var( 'hour' ) ) {
					$this->add_minute_hour_archive_items();
				} elseif ( get_query_var( 'minute' ) ) {
					$this->add_minute_archive_items();
				} elseif ( get_query_var( 'hour' ) ) {
					$this->add_hour_archive_items();
				} elseif ( is_day() ) {
					$this->add_day_archive_items();
				} elseif ( get_query_var( 'w' ) ) {
					$this->add_week_archive_items();
				} elseif ( is_month() ) {
					$this->add_month_archive_items();
				} elseif ( is_year() ) {
					$this->add_year_archive_items();
				} else {
					$this->add_default_archive_items();
				}
			} // If viewing a search results page.
			elseif ( is_search() ) {
				$this->add_search_items();
			} // If viewing the 404 page.
			elseif ( is_404() ) {
				$this->add_404_items();
			}
		}

		// Add paged items if they exist.
		$this->add_paged_items();

		// Allow developers to overwrite the items for the breadcrumb trail.
		$this->items = apply_filters( 'bf_breadcrumb_items', $this->items, $this->args );
	}


	/**
	 * Gets front items based on $wp_rewrite->front.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @return void
	 */
	protected function add_rewrite_front_items() {

		global $wp_rewrite;

		if ( $wp_rewrite->front ) {
			$this->add_path_parents( $wp_rewrite->front );
		}
	}


	/**
	 * Adds the page/paged number to the items array.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @return void
	 */
	protected function add_paged_items() {

		// If viewing a paged singular post.
		if ( is_singular() && 1 < get_query_var( 'page' ) && true === $this->args['show_title'] ) {
			$this->items[] = array(
				'link' => home_url( $_SERVER['REQUEST_URI'] ),
				'name' => sprintf( $this->labels['paged'], number_format_i18n( absint( get_query_var( 'page' ) ) ) ),
				'type' => 'current',
			);
		} // If viewing a paged archive-type page.
		elseif ( is_paged() && true === $this->args['show_title'] ) {
			$this->items[] = array(
				'name' => sprintf( $this->labels['paged'], number_format_i18n( absint( get_query_var( 'paged' ) ) ) ),
			);
		}
	}


	/**
	 * Adds the network (all sites) home page link to the items array.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @return void
	 */
	protected function add_network_home_link() {

		if ( is_multisite() && ! is_main_site() && true === $this->args['network'] ) {
			$this->items[] = array(
				'link' => network_home_url(),
				'rel'  => 'home',
				'name' => $this->labels['home'],
				'type' => 'home',
			);
		}
	}


	/**
	 * Adds the current site's home page link to the items array.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @return void
	 */
	protected function add_site_home_link() {

		$network = is_multisite() && ! is_main_site() && true === $this->args['network'];
		$label   = $network ? get_bloginfo( 'name' ) : $this->labels['home'];

		if ( $network ) {
			$this->items[] = array(
				'link' => home_url(),
				'rel'  => 'home',
				'name' => $label,
				'type' => 'home',
			);
		} else {
			$this->items[] = array(
				'link' => home_url(),
				'name' => $label,
				'type' => 'home',
				'rel'  => 'home',
			);
		}
	}


	/**
	 * Adds items for the front page to the items array.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @return void
	 */
	protected function add_front_page_items() {

		// Only show front items if the 'show_on_front' argument is set to 'true'.
		if ( true === $this->args['show_on_front'] || is_paged() || ( is_singular() && 1 < get_query_var( 'page' ) ) ) {

			// Add network home link.
			$this->add_network_home_link();

			// If on a paged view, add the site home link.
			if ( is_paged() ) {
				$this->add_site_home_link();
			} // If on the main front page, add the network home title.
			elseif ( true === $this->args['show_title'] ) {
				$this->items[] = array(
					'name' => is_multisite() && true === $this->args['network'] ? get_bloginfo( 'name' ) : $this->labels['home'],
				);
			}
		}
	}


	/**
	 * Adds items for the posts page (i.e., is_home()) to the items array.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @return void
	 */
	protected function add_posts_page_items() {

		// Get the post ID and post.
		$post_id = get_queried_object_id();
		$post    = get_post( $post_id );

		// If the post has parents, add them to the trail.
		if ( 0 < $post->post_parent ) {
			$this->add_post_parents( $post->post_parent );
		}

		// Get the page title.
		$title = get_the_title( $post_id );

		// Add the posts page item.
		$this->items[] = array(
			'link' => get_permalink( $post_id ),
			'name' => $title,
			'type' => 'current',
		);

	}


	/**
	 * Adds singular post items to the items array.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @return void
	 */
	protected function add_singular_items() {

		// Get the queried post.
		$post    = get_queried_object();
		$post_id = get_queried_object_id();

		// If the post has a parent, follow the parent trail.
		if ( 0 < $post->post_parent ) {
			$this->add_post_parents( $post->post_parent );
		} // If the post doesn't have a parent, get its hierarchy based off the post type.
		else {
			$this->add_post_hierarchy( $post_id );
		}

		// Display terms for specific post type taxonomy if requested.
		if ( ! empty( $this->post_taxonomy[ $post->post_type ] ) ) {
			$this->add_post_terms( $post_id, $this->post_taxonomy[ $post->post_type ] );
		}

		// End with the post title.
		if ( $post_title = single_post_title( '', false ) ) {
			$this->items[] = array(
				'link' => get_permalink( $post_id ),
				'name' => $post_title,
				'type' => 1 < get_query_var( 'page' ) ? '' : 'current', // current only for first page!
			);
		}
	}


	/**
	 * Adds the items to the trail items array for taxonomy term archives.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @global object $wp_rewrite
	 * @return void
	 */
	protected function add_term_archive_items() {

		global $wp_rewrite;

		// Get some taxonomy and term variables.
		$term           = get_queried_object();
		$taxonomy       = false;
		$done_post_type = false;

		if ( isset( $term->taxonomy ) ) {
			$taxonomy = get_taxonomy( $term->taxonomy );
		}

		if ( ! $taxonomy ) {
			return;
		}

		// If there are rewrite rules for the taxonomy.
		if ( false !== $taxonomy->rewrite ) {

			// If 'with_front' is true, dd $wp_rewrite->front to the trail.
			if ( $taxonomy->rewrite['with_front'] && $wp_rewrite->front ) {
				$this->add_rewrite_front_items();
			}

			// Get parent pages by path if they exist.
			$this->add_path_parents( $taxonomy->rewrite['slug'] );

			// Add post type archive if its 'has_archive' matches the taxonomy rewrite 'slug'.
			if ( $taxonomy->rewrite['slug'] ) {

				$slug = trim( $taxonomy->rewrite['slug'], '/' );

				// Deals with the situation if the slug has a '/' between multiple
				// strings. For example, "movies/genres" where "movies" is the post
				// type archive.
				$matches = explode( '/', $slug );

				// If matches are found for the path.
				if ( isset( $matches ) ) {

					// Reverse the array of matches to search for posts in the proper order.
					$matches = array_reverse( $matches );

					// Loop through each of the path matches.
					foreach ( $matches as $match ) {

						// If a match is found.
						$slug = $match;

						// Get public post types that match the rewrite slug.
						$post_types = $this->get_post_types_by_slug( $match );

						if ( ! empty( $post_types ) ) {

							$post_type_object = $post_types[0];

							// Add support for a non-standard label of 'archive_title' (special use case).
							$label = ! empty( $post_type_object->labels->archive_title ) ? $post_type_object->labels->archive_title : $post_type_object->labels->name;

							// Core filter hook.
							$label = apply_filters( 'post_type_archive_title', $label, $post_type_object->name );

							// Add the post type archive link to the trail.
							$this->items[] = array(
								'link' => get_post_type_archive_link( $post_type_object->name ),
								'name' => $label,
							);

							$done_post_type = true;

							// Break out of the loop.
							break;
						}
					}
				}
			}
		}

		// If there's a single post type for the taxonomy, use it.
		if ( false === $done_post_type && 1 === bf_count( $taxonomy->object_type ) && post_type_exists( $taxonomy->object_type[0] ) ) {

			// If the post type is 'post'.
			if ( 'post' === $taxonomy->object_type[0] ) {
				$post_id = get_option( 'page_for_posts' );

				if ( 'posts' !== get_option( 'show_on_front' ) && 0 < $post_id ) {

					$this->items[] = array(
						'link' => get_permalink( $post_id ),
						'name' => get_the_title( $post_id ),
					);

				}

				// If the post type is not 'post'.
			} else {
				$post_type_object = get_post_type_object( $taxonomy->object_type[0] );

				$label = ! empty( $post_type_object->labels->archive_title ) ? $post_type_object->labels->archive_title : $post_type_object->labels->name;

				// Core filter hook.
				$label = apply_filters( 'post_type_archive_title', $label, $post_type_object->name );

				$this->items[] = array(
					'link' => get_post_type_archive_link( $post_type_object->name ),
					'name' => $label,
				);

			}
		}

		// If the taxonomy is hierarchical, list its parent terms.
		if ( is_taxonomy_hierarchical( $term->taxonomy ) && $term->parent ) {
			$this->add_term_parents( $term->parent, $term->taxonomy );
		}

		// Add the term name to the trail end.
		$this->items[] = array(
			'link' => get_term_link( $term, $term->taxonomy ),
			'name' => single_term_title( '', false ),
			'type' => 'current',
		);

	}


	/**
	 * Adds the items to the trail items array for post type archives.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @return void
	 */
	protected function add_post_type_archive_items() {

		$post_type = get_query_var( 'post_type' );

		if ( is_array( $post_type ) ) {
			$post_type = array_shift( $post_type );
		}

		// Get the post type object.
		if ( ! $post_type_object = get_post_type_object( $post_type ) ) {
			return;
		}


		if ( false !== $post_type_object->rewrite ) {

			// If 'with_front' is true, add $wp_rewrite->front to the trail.
			if ( $post_type_object->rewrite['with_front'] ) {
				$this->add_rewrite_front_items();
			}

			// If there's a rewrite slug, check for parents.
			if ( ! empty( $post_type_object->rewrite['slug'] ) ) {
				$this->add_path_parents( $post_type_object->rewrite['slug'] );
			}
		}

		// Add the post type [plural] name to the trail end.
		$this->items[] = array(
			'link' => get_post_type_archive_link( $post_type_object->name ),
			'name' => post_type_archive_title( '', false ),
			'type' => 'current',
		);
	}


	/**
	 * Adds the items to the trail items array for user (author) archives.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @global object $wp_rewrite
	 * @return void
	 */
	protected function add_user_archive_items() {

		global $wp_rewrite;

		// Add $wp_rewrite->front to the trail.
		$this->add_rewrite_front_items();

		// Get the user ID.
		$user_id = get_query_var( 'author' );

		// If $author_base exists, check for parent pages.
		if ( ! empty( $wp_rewrite->author_base ) ) {
			$this->add_path_parents( $wp_rewrite->author_base );
		}

		// Add the author's display name to the trail end.
		$this->items[] = array(
			'link' => get_author_posts_url( $user_id ),
			'name' => get_the_author_meta( 'display_name', $user_id ),
			'type' => 'current',
		);
	}


	/**
	 * Adds the items to the trail items array for minute + hour archives.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @return void
	 */
	protected function add_minute_hour_archive_items() {

		// Add $wp_rewrite->front to the trail.
		$this->add_rewrite_front_items();

		// Add the minute + hour item.
		if ( true === $this->args['show_title'] ) {

			$this->items[] = array(
				'link' => home_url( $_SERVER['REQUEST_URI'] ),
				'name' => sprintf( $this->labels['archive_minute_hour'], get_the_time( esc_html_x( 'g:i a', 'minute and hour archives time format', 'better-studio' ) ) ),
				'type' => 'current',
			);

		}
	}


	/**
	 * Adds the items to the trail items array for minute archives.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @return void
	 */
	protected function add_minute_archive_items() {

		// Add $wp_rewrite->front to the trail.
		$this->add_rewrite_front_items();

		// Add the minute item.
		if ( true === $this->args['show_title'] ) {

			$this->items[] = array(
				'link' => home_url( $_SERVER['REQUEST_URI'] ),
				'name' => sprintf( $this->labels['archive_minute'], get_the_time( esc_html_x( 'i', 'minute archives time format', 'better-studio' ) ) ),
				'type' => 'current',
			);

		}
	}


	/**
	 * Adds the items to the trail items array for hour archives.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @return void
	 */
	protected function add_hour_archive_items() {

		// Add $wp_rewrite->front to the trail.
		$this->add_rewrite_front_items();

		// Add the hour item.
		if ( true === $this->args['show_title'] ) {

			$this->items[] = array(
				'link' => home_url( $_SERVER['REQUEST_URI'] ),
				'name' => sprintf( $this->labels['archive_hour'], get_the_time( esc_html_x( 'g a', 'hour archives time format', 'better-studio' ) ) ),
				'type' => 'current',
			);

		}
	}


	/**
	 * Adds the items to the trail items array for day archives.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @return void
	 */
	protected function add_day_archive_items() {

		// Add $wp_rewrite->front to the trail.
		$this->add_rewrite_front_items();

		// Get year, month, and day.
		$year  = sprintf( $this->labels['archive_year'], get_the_time( esc_html_x( 'Y', 'yearly archives date format', 'better-studio' ) ) );
		$month = sprintf( $this->labels['archive_month'], get_the_time( esc_html_x( 'F', 'monthly archives date format', 'better-studio' ) ) );
		$day   = sprintf( $this->labels['archive_day'], get_the_time( esc_html_x( 'j', 'daily archives date format', 'better-studio' ) ) );

		// Add the year and month items.
		$this->items[] = array(
			'link' => get_year_link( get_the_time( 'Y' ) ),
			'name' => $year,
		);

		$this->items[] = array(
			'link' => get_month_link( get_the_time( 'Y' ), get_the_time( 'm' ) ),
			'name' => $month,
		);

		// Add the day item.
		$this->items[] = array(
			'link' => get_day_link( get_the_time( 'Y' ), get_the_time( 'm' ), get_the_time( 'd' ) ),
			'name' => $day,
			'type' => 'current',
		);
	}


	/**
	 * Adds the items to the trail items array for week archives.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @return void
	 */
	protected function add_week_archive_items() {

		// Add $wp_rewrite->front to the trail.
		$this->add_rewrite_front_items();

		// Get the year and week.
		$year = sprintf( $this->labels['archive_year'], get_the_time( esc_html_x( 'Y', 'yearly archives date format', 'better-studio' ) ) );
		$week = sprintf( $this->labels['archive_week'], get_the_time( esc_html_x( 'W', 'weekly archives date format', 'better-studio' ) ) );

		// Add the year item.
		$this->items[] = array(
			'link' => get_year_link( get_the_time( 'Y' ) ),
			'name' => $year,
		);

		// Add the week item.
		$this->items[] = array(
			'link' => get_day_link( get_the_time( 'Y' ), get_the_time( 'm' ), get_the_time( 'd' ) ),
			'name' => $week,
			'type' => 'current',
		);
	}


	/**
	 * Adds the items to the trail items array for month archives.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @return void
	 */
	protected function add_month_archive_items() {

		// Add $wp_rewrite->front to the trail.
		$this->add_rewrite_front_items();

		// Get the year and month.
		$year  = sprintf( $this->labels['archive_year'], get_the_time( esc_html_x( 'Y', 'yearly archives date format', 'better-studio' ) ) );
		$month = sprintf( $this->labels['archive_month'], get_the_time( esc_html_x( 'F', 'monthly archives date format', 'better-studio' ) ) );

		// Add the year item.
		$this->items[] = array(
			'link' => get_year_link( get_the_time( 'Y' ) ),
			'name' => $year,
		);

		// Add the month item.
		$this->items[] = array(
			'link' => get_month_link( get_the_time( 'Y' ), get_the_time( 'm' ) ),
			'name' => $month,
			'type' => 'current',
		);
	}


	/**
	 * Adds the items to the trail items array for year archives.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @return void
	 */
	protected function add_year_archive_items() {

		// Add $wp_rewrite->front to the trail.
		$this->add_rewrite_front_items();

		// Get the year.
		$year = sprintf( $this->labels['archive_year'], get_the_time( esc_html_x( 'Y', 'yearly archives date format', 'better-studio' ) ) );

		// Add the year item.
		$this->items[] = array(
			'link' => get_year_link( get_the_time( 'Y' ) ),
			'name' => $year,
			'type' => 'current',
		);

	}


	/**
	 * Adds the items to the trail items array for archives that don't have a more specific method
	 * defined in this class.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @return void
	 */
	protected function add_default_archive_items() {

		// If this is a date-/time-based archive, add $wp_rewrite->front to the trail.
		if ( is_date() || is_time() ) {
			$this->add_rewrite_front_items();
		}

		if ( true === $this->args['show_title'] ) {

			$this->items[] = array(
				'link' => home_url( $_SERVER['REQUEST_URI'] ),
				'name' => $this->labels['archives'],
				'type' => 'current',
			);

		}
	}


	/**
	 * Adds the items to the trail items array for search results.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @return void
	 */
	protected function add_search_items() {

		$this->items[] = array(
			'link' => get_search_link(),
			'name' => sprintf( $this->labels['search'], get_search_query() ),
			'type' => 'current',
		);
	}


	/**
	 * Adds the items to the trail items array for 404 pages.
	 *
	 * @since  1.0.0
	 * @access protected
	 * @return void
	 */
	protected function add_404_items() {

		if ( true === $this->args['show_title'] ) {

			$this->items[] = array(
				'link' => get_search_link(),
				'name' => $this->labels['error_404'],
				'type' => 'current',
			);

		}
	}


	/**
	 * Adds a specific post's parents to the items array.
	 *
	 * @since  1.0.0
	 * @access protected
	 *
	 * @param  int $post_id
	 *
	 * @return void
	 */
	protected function add_post_parents( $post_id ) {

		$parents = array();

		while( $post_id ) {

			// Get the post by ID.
			$post = get_post( $post_id );

			if ( ! $post ) {
				break;
			}

			// If we hit a page that's set as the front page, bail.
			if ( 'page' == $post->post_type && 'page' == get_option( 'show_on_front' ) && $post_id == get_option( 'page_on_front' ) ) {
				break;
			}

			// Add the formatted post link to the array of parents.
			$parents[] = array(
				'link' => get_permalink( $post_id ),
				'name' => get_the_title( $post_id ),
			);


			// If there's no longer a post parent, break out of the loop.
			if ( 0 >= $post->post_parent ) {
				break;
			}

			// Change the post ID to the parent post to continue looping.
			$post_id = $post->post_parent;
		}

		// Get the post hierarchy based off the final parent post.
		$this->add_post_hierarchy( $post_id );

		// Display terms for specific post type taxonomy if requested.
		if ( ! empty( $this->post_taxonomy[ $post->post_type ] ) ) {
			$this->add_post_terms( $post_id, $this->post_taxonomy[ $post->post_type ] );
		}

		// Merge the parent items into the items array.
		$this->items = array_merge( $this->items, array_reverse( $parents ) );
	}


	/**
	 * Adds a specific post's hierarchy to the items array.  The hierarchy is determined by post type's
	 * rewrite arguments and whether it has an archive page.
	 *
	 * @since  1.0.0
	 * @access protected
	 *
	 * @param  int $post_id
	 *
	 * @return void
	 */
	protected function add_post_hierarchy( $post_id ) {

		// Get the post type.
		$post_type        = get_post_type( $post_id );
		$post_type_object = get_post_type_object( $post_type );

		// If this is the 'post' post type, get the rewrite front items and map the rewrite tags.
		if ( 'post' === $post_type ) {

			// Add $wp_rewrite->front to the trail.
			$this->add_rewrite_front_items();

			if ( $this->args['show_date_in_post'] ) {
				$this->map_rewrite_tags( $post_id, get_option( 'permalink_structure' ) );
			}

		} // If the post type has rewrite rules.
		elseif ( isset( $post_type_object->rewrite ) && false !== $post_type_object->rewrite ) {

			// If 'with_front' is true, add $wp_rewrite->front to the trail.
			if ( $post_type_object->rewrite['with_front'] ) {
				$this->add_rewrite_front_items();
			}

			// If there's a path, check for parents.
			if ( ! empty( $post_type_object->rewrite['slug'] ) ) {
				$this->add_path_parents( $post_type_object->rewrite['slug'] );
			}
		}

		// If there's an archive page, add it to the trail.
		if ( ! empty( $post_type_object->has_archive ) ) {

			// Add support for a non-standard label of 'archive_title' (special use case).
			$label = ! empty( $post_type_object->labels->archive_title ) ? $post_type_object->labels->archive_title : $post_type_object->labels->name;

			// Core filter hook.
			$label = apply_filters( 'post_type_archive_title', $label, $post_type_object->name );

			$this->items[] = array(
				'link' => get_post_type_archive_link( $post_type ),
				'name' => $label,
			);

		}

	}


	/**
	 * Gets post types by slug.  This is needed because the get_post_types() function doesn't exactly
	 * match the 'has_archive' argument when it's set as a string instead of a boolean.
	 *
	 * @since  0.6.0
	 * @access protected
	 *
	 * @param  int $slug The post type archive slug to search for.
	 *
	 * @return array
	 */
	protected function get_post_types_by_slug( $slug ) {

		$return = array();

		$post_types = get_post_types( array(), 'objects' );

		foreach ( $post_types as $type ) {

			if ( $slug === $type->has_archive || ( true === $type->has_archive && $slug === $type->rewrite['slug'] ) ) {
				$return[] = $type;
			}
		}

		return $return;
	}


	/**
	 * Adds a post's terms from a specific taxonomy to the items array.
	 *
	 * @since  1.0.0
	 * @access protected
	 *
	 * @param  int    $post_id  The ID of the post to get the terms for.
	 * @param  string $taxonomy The taxonomy to get the terms from.
	 *
	 * @return void
	 */
	protected function add_post_terms( $post_id, $taxonomy ) {

		// Gets primary category (BF or YoastSEO)
		if ( function_exists( 'bf_get_post_primary_cat' ) ) {
			$term = bf_get_post_primary_cat();
		} else {
			$term = false;
		}

		if ( ! $term || is_wp_error( $term ) ) {

			$terms = get_the_terms( $post_id, $taxonomy );

			if ( ! $terms || is_wp_error( $terms ) ) {
				return;
			}

			// Sort the terms by ID and get the first category.
			if ( function_exists( 'wp_list_sort' ) ) {
				usort( $terms, 'wp_list_sort' );
			} else {
				usort( $terms, '_usort_terms_by_ID' );
			}

			$term = get_term( $terms[0], $taxonomy );

			if ( ! $term || is_wp_error( $term ) ) {
				return;
			}
		}

		// If the category has a parent, add the hierarchy to the trail.
		if ( 0 < $term->parent ) {
			$this->add_term_parents( $term->parent, $taxonomy );
		}

		// Add the category archive link to the trail.
		$this->items[] = array(
			'link' => get_term_link( $term, $taxonomy ),
			'name' => $term->name,
		);

	}


	/**
	 * Get parent posts by path.  Currently, this method only supports getting parents of the 'page'
	 * post type.  The goal of this function is to create a clear path back to home given what would
	 * normally be a "ghost" directory.  If any page matches the given path, it'll be added.
	 *
	 * @since  1.0.0
	 * @access protected
	 *
	 * @param  string $path The path (slug) to search for posts by.
	 *
	 * @return void
	 */
	function add_path_parents( $path ) {

		// Trim '/' off $path in case we just got a simple '/' instead of a real path.
		$path = trim( $path, '/' );

		// If there's no path, return.
		if ( empty( $path ) ) {
			return;
		}

		// Get parent post by the path.
		$post = get_page_by_path( $path );

		if ( ! empty( $post ) ) {
			$this->add_post_parents( $post->ID );
		} elseif ( is_null( $post ) ) {

			// Separate post names into separate paths by '/'.
			$path = trim( $path, '/' );
			preg_match_all( "/\/.*?\z/", $path, $matches );

			// If matches are found for the path.
			if ( isset( $matches ) ) {

				// Reverse the array of matches to search for posts in the proper order.
				$matches = array_reverse( $matches );

				// Loop through each of the path matches.
				foreach ( $matches as $match ) {

					// If a match is found.
					if ( isset( $match[0] ) ) {

						// Get the parent post by the given path.
						$path = str_replace( $match[0], '', $path );
						$post = get_page_by_path( trim( $path, '/' ) );

						// If a parent post is found, set the $post_id and break out of the loop.
						if ( ! empty( $post ) && 0 < $post->ID ) {
							$this->add_post_parents( $post->ID );
							break;
						}
					}
				}
			}
		}
	}


	/**
	 * Searches for term parents of hierarchical taxonomies.  This function is similar to the WordPress
	 * function get_category_parents() but handles any type of taxonomy.
	 *
	 * @since  1.0.0
	 *
	 * @param  int    $term_id  ID of the term to get the parents of.
	 * @param  string $taxonomy Name of the taxonomy for the given term.
	 *
	 * @return void
	 */
	function add_term_parents( $term_id, $taxonomy ) {

		// Set up some default arrays.
		$parents = array();

		// While there is a parent ID, add the parent term link to the $parents array.
		while( $term_id ) {

			// Get the parent term.
			$term = get_term( $term_id, $taxonomy );

			if ( ! $term || is_wp_error( $term ) ) {
				break;
			}

			$link = get_term_link( $term, $taxonomy );

			if ( ! $link || is_wp_error( $link ) ) {
				break;
			}

			// Add the formatted term link to the array of parent terms.
			$parents[] = array(
				'link' => $link,
				'name' => $term->name,
			);

			// Set the parent term's parent as the parent ID.
			$term_id = $term->parent;
		}

		// If we have parent terms, reverse the array to put them in the proper order for the trail.
		if ( ! empty( $parents ) ) {
			$this->items = array_merge( $this->items, array_reverse( $parents ) );
		}
	}


	/**
	 * Turns %tag% from permalink structures into usable links for the breadcrumb trail.  This feels kind of
	 * hackish for now because we're checking for specific %tag% examples and only doing it for the 'post'
	 * post type.  In the future, maybe it'll handle a wider variety of possibilities, especially for custom post
	 * types.
	 *
	 * @since  0.6.0
	 * @access protected
	 *
	 * @param  int    $post_id ID of the post whose parents we want.
	 * @param  string $path    Path of a potential parent page.
	 * @param  array  $args    Mixed arguments for the menu.
	 *
	 * @return array
	 */
	protected function map_rewrite_tags( $post_id, $path ) {

		$post = get_post( $post_id );

		// If the post doesn't have the `post` post type, bail.
		if ( 'post' !== $post->post_type ) {
			return;
		}

		// Trim '/' from both sides of the $path.
		$path = trim( $path, '/' );

		// Split the $path into an array of strings.
		$matches = explode( '/', $path );

		// If matches are found for the path.
		if ( is_array( $matches ) ) {

			// Loop through each of the matches, adding each to the $trail array.
			foreach ( $matches as $match ) {

				// Trim any '/' from the $match.
				$tag = trim( $match, '/' );

				// If using the %year% tag, add a link to the yearly archive.
				if ( '%year%' == $tag ) {

					$this->items[] = array(
						'link' => get_year_link( get_the_time( 'Y', $post_id ) ),
						'name' => sprintf( $this->labels['archive_year'], get_the_time( esc_html_x( 'Y', 'yearly archives date format', 'better-studio' ) ) ),
					);

				} // If using the %monthnum% tag, add a link to the monthly archive.
				elseif ( '%monthnum%' == $tag ) {

					$this->items[] = array(
						'link' => get_month_link( get_the_time( 'Y', $post_id ), get_the_time( 'm', $post_id ) ),
						'name' => sprintf( $this->labels['archive_month'], get_the_time( esc_html_x( 'F', 'monthly archives date format', 'better-studio' ) ) ),
					);

				} // If using the %day% tag, add a link to the daily archive.
				elseif ( '%day%' == $tag ) {

					$this->items[] = array(
						'link' => get_day_link( get_the_time( 'Y', $post_id ), get_the_time( 'm', $post_id ), get_the_time( 'd', $post_id ) ),
						'name' => sprintf( $this->labels['archive_day'], get_the_time( esc_html_x( 'j', 'daily archives date format', 'better-studio' ) ) ),
					);

				} // If using the %author% tag, add a link to the post author archive.
				elseif ( '%author%' == $tag ) {

					$this->items[] = array(
						'link' => get_author_posts_url( $post->post_author ),
						'name' => get_the_author_meta( 'display_name', $post->post_author ),
					);

				} // If using the %category% tag, add a link to the first category archive to match permalinks.
				elseif ( '%category%' == $tag ) {

					// Force override terms in this post type.
					$this->post_taxonomy[ $post->post_type ] = false;

					// Add the post categories.
					$this->add_post_terms( $post_id, 'category' );
				}
			}
		}
	}


	/**
	 * Fixes user breadcrumb for bbPress custom rewrite rules
	 *
	 * @since  1.1.0
	 */
	function add_bbpress_items() {

		if ( bbp_is_forum_archive() ) {
			$this->bbp_is_forum_archive();
		} elseif ( bbp_is_topic_archive() ) {
			$this->bbp_is_topic_archive();
		} elseif ( bbp_is_topic_tag() ) {
			$this->bbp_is_topic_tag();
		} elseif ( bbp_is_topic_tag_edit() ) {
			$this->bbp_is_topic_tag_edit();
		} elseif ( bbp_is_single_forum() ) {
			$this->bbp_is_single_forum();
		} elseif ( bbp_is_single_topic() ) {
			$this->bbp_is_single_topic();
		} elseif ( bbp_is_single_reply() ) {
			$this->bbp_is_single_topic();
		} elseif ( bbp_is_topic_edit() ) {
			$this->bbp_is_single_topic();
		} elseif ( bbp_is_reply_edit() ) {
			$this->bbp_is_single_topic();
		} elseif ( bbp_is_single_view() ) {
			$this->bbp_is_single_view();
		} elseif ( bbp_is_single_user() ) {
			$this->bbp_user();
		} elseif ( bbp_is_search() || bbp_is_search_results() ) {
			$this->bbp_is_search();
		}
	}


	/**
	 * Viewing a topic archive
	 *
	 * @since  1.2.0
	 */
	function bbp_is_forum_archive() {

		$this->items[] = array(
			'link' => home_url( $_SERVER['REQUEST_URI'] ),
			'name' => bbp_get_forum_archive_title(),
			'type' => 'current',
		);
	}


	/**
	 * Viewing a topic archive.
	 *
	 * @since  1.2.0
	 */
	function bbp_is_topic_archive() {

		$this->items[] = array(
			'link' => home_url( $_SERVER['REQUEST_URI'] ),
			'name' => bbp_get_topic_archive_title(),
			'type' => 'current',
		);
	}


	/**
	 * Topic page
	 *
	 * @since  1.2.0
	 */
	function bbp_is_topic_tag() {

		$this->items[] = array(
			'link' => home_url( $_SERVER['REQUEST_URI'] ),
			'name' => bbp_get_topic_tag_name(),
			'type' => 'current',
		);
	}


	/**
	 * Topic edit page
	 *
	 * @since  1.2.0
	 */
	function bbp_is_topic_tag_edit() {

		$this->items[] = array(
			'link' => home_url( $_SERVER['REQUEST_URI'] ),
			'name' => bbp_get_topic_tag_name(),
			'type' => 'current',
		);
	}


	/**
	 * Forum single page
	 *
	 * @since  1.2.0
	 */
	function bbp_is_single_forum() {

		$this->items[] = array(
			'link' => get_post_type_archive_link( bbp_get_forum_post_type() ),
			'name' => bbp_get_forum_archive_title(),
		);

		$this->bbp_forum_parents();

		$this->items[] = array(
			'link' => home_url( $_SERVER['REQUEST_URI'] ),
			'name' => bbp_get_forum_title(),
			'type' => 'current',
		);
	}


	/**
	 * Topic single page
	 *
	 * @since  1.2.0
	 */
	function bbp_is_single_topic() {

		$this->items[] = array(
			'link' => get_post_type_archive_link( bbp_get_forum_post_type() ),
			'name' => bbp_get_forum_archive_title(),
		);

		$this->bbp_forum_parents();

		$this->items[] = array(
			'link' => home_url( $_SERVER['REQUEST_URI'] ),
			'name' => bbp_get_topic_title(),
			'type' => 'current',
		);
	}


	/**
	 * For all view pages
	 *
	 * @since  1.2.0
	 */
	function bbp_is_single_view() {

		$this->items[] = array(
			'link' => home_url( $_SERVER['REQUEST_URI'] ),
			'name' => bbp_get_view_title(),
			'type' => 'current',
		);
	}


	/**
	 * Adds all parent forums
	 *
	 * @since  1.2.0
	 */
	function bbp_forum_parents() {

		$parent = bbp_get_forum_parent_id();

		if ( $parent ) {

			$parents = array();

			while( $parent ) {

				$parents[] = array(
					'link' => bbp_get_forum_permalink( $parent ),
					'name' => bbp_get_forum_title( $parent ),
				);
				$parent    = bbp_get_forum_parent_id( $parent );
			}

			if ( ! empty( $parents ) ) {
				// Reverse items list for correct order
				$this->items = array_merge( $this->items, array_reverse( $parents ) );
			}
		}

	}


	/**
	 * For all user related pages
	 *
	 * @since  1.2.0
	 */
	function bbp_user() {

		$user_id = bbp_get_user_id();
		if ( empty( $user_id ) ) {
			return;
		}

		$user = get_userdata( $user_id );
		if ( is_wp_error( $user_id ) ) {
			return;
		}

		if ( bbp_is_replies_created() ) {
			$current = __( 'Replies', 'better-studio' );
		} elseif ( bbp_is_topics_created() || bbp_is_single_view() ) {
			$current = __( 'Topics', 'better-studio' );
		} elseif ( bbp_is_favorites() ) {
			$current = __( 'Favorites', 'better-studio' );
		} elseif ( bbp_is_subscriptions() ) {
			$current = __( 'Subscriptions', 'better-studio' );
		} elseif ( bbp_is_single_user_edit() ) {
			$current = __( 'Profile edit', 'better-studio' );
		} elseif ( bbp_is_single_user() ) {
			$current = __( 'Profile', 'better-studio' );
		}

		if ( empty( $current ) ) {
			return;
		}

		$this->items[] = array(
			'link' => get_post_type_archive_link( bbp_get_forum_post_type() ),
			'name' => bbp_get_forum_archive_title(),
		);

		$this->items[] = array(
			'link' => bbp_get_user_profile_url(),
			'name' => $user->display_name,
		);

		$this->items[] = array(
			'link' => home_url( $_SERVER['REQUEST_URI'] ),
			'name' => $current,
			'type' => 'current',
		);

	}


	/**
	 * For forum search
	 *
	 * @since  1.2.0
	 */
	function bbp_is_search() {

		$this->items[] = array(
			'link' => home_url( $_SERVER['REQUEST_URI'] ),
			'name' => bbp_get_search_title(),
			'type' => 'current',
		);
	}

}
libs/better-framework/libs/class-bf-color.php000064400000010353151214002540015221 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Handy Functions for Color
 */
class BF_Color {

	/**
	 * Contains User profile Colors
	 *
	 * @var array
	 */
	private static $user_profile_color = null;


	function __construct() {

		add_action( 'admin_enqueue_scripts', array( $this, 'get_user_colors' ), 1 );
	}


	/**
	 * Used for reliving current user color schema informations
	 */
	function get_user_colors() {

		global $_wp_admin_css_colors;

		$user_color = get_user_option( 'admin_color' );
		if ( empty( $user_color ) ) {
			return '';
		}

		$user_color = $_wp_admin_css_colors[ $user_color ];

		if ( empty( $user_color ) || ! is_object( $user_color ) ) {
			return '';
		}

		self::$user_profile_color['color-1'] = $user_color->colors[0]; // background
		self::$user_profile_color['color-2'] = $user_color->colors[1]; // lighter background
		self::$user_profile_color['color-3'] = $user_color->colors[2]; // active color
		self::$user_profile_color['color-4'] = $user_color->colors[3]; // hover active color

		switch ( get_user_option( 'admin_color' ) ) {
			case 'light':
				self::$user_profile_color['color-3'] = '#888';
				break;
			case 'midnight':
				self::$user_profile_color['color-3'] = '#e14d43';
				break;
		}

	}


	/**
	 * Used for Retrieving User Profile Color
	 *
	 * color-1 => background
	 * color-2 => lighter background
	 * color-3 => active color
	 * color-4 => hover active color
	 *
	 * @param $color_type
	 *
	 * @return array
	 */
	public static function get_user_profile_color( $color_type ) {

		if ( is_null( self::$user_profile_color ) ) {
			// todo why i did this?!!?
			return 'NOOOOO';

		}

		return self::$user_profile_color[ $color_type ];
	}


	/**
	 * Change Color Brighter or Darker
	 *
	 *
	 * Steps should be between -255 and 255. Negative = darker, positive = lighter
	 *
	 * @param $hex
	 * @param $steps
	 *
	 * @return string
	 */
	static function change_color( $hex, $steps ) {

		// Steps should be between -255 and 255. Negative = darker, positive = lighter
		$steps = max( - 255, min( 255, $steps ) );

		// Format the hex color string
		$hex = str_replace( '#', '', $hex );
		if ( strlen( $hex ) == 3 ) {
			$hex = str_repeat( substr( $hex, 0, 1 ), 2 ) . str_repeat( substr( $hex, 1, 1 ), 2 ) . str_repeat( substr( $hex, 2, 1 ), 2 );
		}

		// Get decimal values
		$r = hexdec( substr( $hex, 0, 2 ) );
		$g = hexdec( substr( $hex, 2, 2 ) );
		$b = hexdec( substr( $hex, 4, 2 ) );

		// Adjust number of steps and keep it inside 0 to 255
		$r = max( 0, min( 255, $r + $steps ) );
		$g = max( 0, min( 255, $g + $steps ) );
		$b = max( 0, min( 255, $b + $steps ) );

		$r_hex = str_pad( dechex( $r ), 2, '0', STR_PAD_LEFT );
		$g_hex = str_pad( dechex( $g ), 2, '0', STR_PAD_LEFT );
		$b_hex = str_pad( dechex( $b ), 2, '0', STR_PAD_LEFT );

		return '#' . $r_hex . $g_hex . $b_hex;
	}


	public static function hex_to_rgba( $color, $opacity = false ) {

		$default = 'rgb(0,0,0)';

		if ( empty( $color ) ) {
			return $default;
		}

		if ( $color[0] == '#' ) {
			$color = substr( $color, 1 );
		}

		if ( strlen( $color ) == 6 ) {
			$hex = array( $color[0] . $color[1], $color[2] . $color[3], $color[4] . $color[5] );
		} elseif ( strlen( $color ) == 3 ) {
			$hex = array( $color[0] . $color[0], $color[1] . $color[1], $color[2] . $color[2] );
		} else {
			return $default;
		}

		$rgb = array_map( 'hexdec', $hex );

		if ( $opacity ) {
			if ( abs( $opacity ) > 1 ) {
				$opacity = 1.0;
			}

			$output = 'rgba(' . implode( ",", $rgb ) . ',' . $opacity . ')';
		} else {
			$output = 'rgb(' . implode( ",", $rgb ) . ')';
		}

		return $output;
	}

}libs/better-framework/taxonomy/class-bf-taxonomy-core.php000064400000011345151214002540017636 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Manage all functionality for generating fields and retrieving fields data from them
 */
class BF_Taxonomy_Core {

	/**
	 * Contain all options that retrieved from better-framework/taxonomy/options and used for generating forms
	 *
	 * @var array
	 */
	public $taxonomy_options = array();


	/**
	 * Used for protect redundancy loading
	 *
	 * @var bool
	 */
	public $options_loaded = false;


	/**
	 * Used for caching terms data for next calls
	 * it was used for old meta and currently will not used
	 *
	 * @var array
	 */
	public static $cache = array();


	/**
	 * Contains all metabox's
	 *
	 * @var array
	 */
	public static $metabox = array();


	/**
	 * Contains config for all metabox's
	 *
	 * @var array
	 */
	public static $config = array();


	/**
	 * Contains all fields
	 *
	 * @var array
	 */
	public static $fields = array();


	/**
	 * Contains all std
	 *
	 * @var array
	 */
	public static $std = array();


	/**
	 * Contains all css
	 *
	 * @var array
	 */
	public static $css = array();


	/**
	 * Initializes all metabox
	 */
	public static function init_metabox() {

		static $loaded;

		if ( $loaded ) {
			return;
		}

		self::$metabox = apply_filters( 'better-framework/taxonomy/metabox/add', array() );

	}


	/**
	 * loads and returns metabox config
	 *
	 * @param string $metabox_id
	 *
	 * @return array
	 */
	public static function get_metabox_config( $metabox_id = '' ) {

		if ( empty( $metabox_id ) ) {
			return array();
		}

		if ( isset( self::$config[ $metabox_id ] ) ) {
			return self::$config[ $metabox_id ];
		}
		self::$config[ $metabox_id ] = apply_filters( 'better-framework/taxonomy/metabox/' . $metabox_id . '/config', array() );

		return self::$config[ $metabox_id ];
	}


	/**
	 * loads and returns metabox std values
	 *
	 * @param string $metabox_id
	 *
	 * @return array
	 */
	public static function get_metabox_std( $metabox_id = '' ) {

		if ( empty( $metabox_id ) || ! isset( self::$metabox[ $metabox_id ] ) ) {
			return array();
		}

		if ( isset( self::$std[ $metabox_id ] ) ) {
			return self::$std[ $metabox_id ];
		}

		return self::$std[ $metabox_id ] = apply_filters( 'better-framework/taxonomy/metabox/' . $metabox_id . '/std', array() );
	}


	/**
	 * loads and returns metabox std values
	 *
	 * @param string $metabox_id
	 *
	 * @return array
	 */
	public static function get_metabox_fields( $metabox_id = '' ) {

		if ( empty( $metabox_id ) || ! isset( self::$metabox[ $metabox_id ] ) ) {
			return array();
		}

		if ( isset( self::$fields[ $metabox_id ] ) ) {
			return self::$fields[ $metabox_id ];
		}

		return self::$fields[ $metabox_id ] = apply_filters( 'better-framework/taxonomy/metabox/' . $metabox_id . '/fields', array() );
	}


	/**
	 * loads and returns metabox css
	 *
	 * @param string $metabox_id
	 *
	 * @return array
	 */
	public static function get_metabox_css( $metabox_id = '' ) {

		if ( empty( $metabox_id ) || ! isset( self::$metabox[ $metabox_id ] ) ) {
			return array();
		}

		if ( isset( self::$css[ $metabox_id ] ) ) {
			return self::$css[ $metabox_id ];
		}

		return self::$css[ $metabox_id ] = apply_filters( 'better-framework/taxonomy/metabox/' . $metabox_id . '/css', array() );
	}


	/**
	 *
	 */
	function __construct() {

		self::init_metabox();

		add_action( 'admin_init', array( $this, 'register_taxonomies' ) );
	}


	/**
	 * Register taxonomy fields
	 */
	function register_taxonomies() {

		if ( ! is_admin() ) {
			return;
		}

		if ( ! class_exists( 'BF_Taxonomy_Meta_Field' ) ) {
			bf_require_once( 'taxonomy/class-bf-taxonomy-meta-field.php' );
		}

		foreach ( self::$metabox as $metabox_id => $metabox ) {
			new BF_Taxonomy_Meta_Field( $metabox_id );
		}
	}


	/**
	 * Deprecated: Use bf_get_term_meta
	 *
	 * Used For retrieving meta of term
	 *
	 * @param   int|object  $term    Term ID or object
	 * @param   string      $meta_id Custom Field ID
	 * @param   bool|string $default Default Value
	 *
	 * @return bool
	 */
	public function get_term_meta( $term, $meta_id, $default = null ) {

		return bf_get_term_meta( $meta_id, $term, $default );
	}
}
libs/better-framework/taxonomy/class-bf-taxonomy-front-end-generator.php000064400000016072151214002540022570 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Taxonomies Field Generator For Admin
 */
class BF_Taxonomy_Front_End_Generator extends BF_Admin_Fields {


	/**
	 * @see BF_Metabox_Core::init_metabox apply_filters
	 *
	 * @var string
	 */
	public $metabox_id;


	/**
	 * Constructor Function
	 *
	 * @param array  $items
	 * @param        $id         term ID
	 * @param array  $values
	 * @param string $metabox_id metabox ID {@see  self::$metabox_id}  doc
	 *
	 * @since  1.0
	 * @access public
	 * @return \BF_Taxonomy_Front_End_Generator
	 */
	public function __construct( array &$items, &$id, &$values = array(), $metabox_id = false ) {

		// Parent Constructor
		$generator_options = array(
			'templates_dir' => BF_PATH . 'taxonomy/templates/'
		);
		parent::__construct( $generator_options );

		$this->items  = $items;
		$this->id     = $id;
		$this->values = $values;

		$this->metabox_id = $metabox_id;
	}


	/**
	 * Make input name from options variable
	 *
	 * @param  (array) $options Options array
	 *
	 * @since  1.0
	 * @access public
	 * @return string
	 */
	public function input_name( &$options ) {

		$id   = isset( $options['id'] ) ? $options['id'] : '';
		$type = isset( $options['type'] ) ? $options['type'] : '';

		switch ( $type ) {

			case( 'repeater' ):
				return "bf-term-meta[%s][%d][%s]";
				break;

			default:
				return "bf-term-meta[{$id}]";
				break;
		}

	}


	/**
	 * Used for generating fields
	 */
	public function callback( $is_ajax = false ) {

		$items_has_tab    = ! $is_ajax;
		$skip_ajax_fields = ! $is_ajax;
		$has_tab          = false;
		$tab_counter      = 0;
		$group_counter    = array();

		$metabox_name = isset( $this->items['config']['name'] ) ? $this->items['config']['name'] : __( 'Better Options', 'better-studio' );

		// Base wrapper
		if ( ! $is_ajax ) {
			$wrapper = Better_Framework::html()->add( 'div' );
			$wrapper = $wrapper->class( 'bf-tax-meta-wrap bf-metabox-wrap bf-clearfix' )->data( 'id', $this->id );
			if ( $this->metabox_id ) {
				$wrapper->data( 'metabox-id', $this->metabox_id );
			}
			// Better Option Title
			$wrapper->text(
				Better_Framework::html()->add( 'div' )->class( 'bf-tax-metabox-title' )->text(
					Better_Framework::html()->add( 'h3' )->text( $metabox_name )
				)
			);
		}


		$container = Better_Framework::html()->add( 'div' );

		if ( ! $is_ajax ) {
			$container = $container->class( 'bf-metabox-container' );
		}

		// Add Tab
		if ( $items_has_tab && ! $is_ajax ) {
			$container->class( 'bf-with-tabs' );
			$tabs_container = Better_Framework::html()->add( 'div' )->class( 'bf-metabox-tabs' );
			$tabs_container->text( $this->get_tabs() );
			$wrapper->text( $tabs_container->display() );
		}

		foreach ( $this->items['fields'] as $field ) {

			$field['input_name'] = $this->input_name( $field );

			$field['value'] = isset( $field['id'] ) && isset( $this->values[ $field['id'] ] ) ? $this->values[ $field['id'] ] : false;

			if ( isset( $field['type'] ) && $field['type'] == 'info' && $field['std'] ) {
				$field['value'] = $field['std'];
			}

			if ( $skip_ajax_fields && ! empty( $field['ajax-tab-field'] ) ) { // Backward compatibility
				continue;
			}

			if ( $skip_ajax_fields && ! empty( $field['ajax-section-field'] ) ) {
				continue;
			}

			if ( $field['type'] == 'repeater' ) {
				$field['clone-name-format'] = 'bf-term-meta[%s][%d][%s]';
				$field['metabox-id']        = $this->id;
				$field['metabox-field']     = true;
			}

			if ( $field['type'] == 'tab' || $field['type'] == 'subtab' ) {

				if ( $has_tab ) {

					// close all opened groups
					foreach ( array_reverse( $group_counter ) as $level_k => $level_v ) {

						if ( $level_v === 0 ) {
							continue;
						}

						for ( $i = 0; $i < $level_v; $i ++ ) {
							$container->text( $this->get_fields_group_close( $field ) );
						}

						$group_counter[ $level_k ] = 0;
					}
				}
				$is_subtab = $field['type'] == 'subtab';

				if ( $tab_counter != 0 ) {
					$container->text( '</div><!-- /Section -->' );
				}

				if ( $is_subtab ) {
					$container->text( "\n\n<!-- Section -->\n<div class='group subtab-group' id='bf-metabox-{$this->id}-{$field["id"]}'>\n" );
				} else {
					$container->text( "\n\n<!-- Section -->\n<div class='group' id='bf-metabox-{$this->id}-{$field["id"]}'>\n" );
				}
				$has_tab = true;
				$tab_counter ++;
				continue;
			}

			//
			// Close group
			//
			if ( $field['type'] == 'group_close' ) {

				if ( isset( $field['level'] ) && $field['level'] === 'all' ) {

					krsort( $group_counter );

					// close all opened groups
					foreach ( $group_counter as $level_k => $level_v ) {

						if ( $level_v === 0 ) {
							continue;
						}

						for ( $i = 0; $i < $level_v; $i ++ ) {
							$container->text( $this->get_fields_group_close( $field ) );
						}

						$group_counter[ $level_k ] = 0;
					}

				} else {

					krsort( $group_counter );

					// close last opened group
					foreach ( $group_counter as $level_k => $level_v ) {

						if ( ! $level_v ) {
							continue;
						}

						for ( $i = 0; $i < $level_v; $i ++ ) {
							$container->text( $this->get_fields_group_close( $field ) );
							$group_counter[ $level_k ] --;
							break;
						}

					}
				}


				continue;
			}

			//
			// Group
			// All nested groups and same level groups should be closed
			//
			if ( $field['type'] == 'group' ) {

				if ( ! isset( $field['level'] ) ) {
					$field['level'] = 0;
				}

				if ( ! isset( $group_counter[ $field['level'] ] ) ) {
					$group_counter[ $field['level'] ] = 0;
				}

				krsort( $group_counter );

				foreach ( $group_counter as $level_k => $level_v ) {

					if ( $level_k < $field['level'] ) {
						continue;
					}

					for ( $i = 0; $i < $level_v; $i ++ ) {
						$container->text( $this->get_fields_group_close( $field ) );
					}

					$group_counter[ $level_k ] = 0;
				}

				$container->text( $this->get_fields_group_start( $field ) );

				$group_counter[ $field['level'] ] ++;
			}

			if ( ! in_array( $field['type'], $this->supported_fields ) ) {
				continue;
			}

			$container->text(
				$this->section(
					call_user_func(
						array( $this, $field['type'] ),
						$field
					),
					$field
				)
			);

		}

		// last sub tab closing
		if ( $has_tab ) {
			$container->text( "</div><!-- /Section -->" );
		}


		if ( $is_ajax ) {
			echo $container->display();
		} else {
			$wrapper->text(
				$container->display()
			);
			echo $wrapper;  // escaped before
		}


	} // callback
}
libs/better-framework/taxonomy/functions.php000064400000021445151214002540015354 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! function_exists( 'bf_use_wp_term_meta' ) ) {

	/**
	 * Check WordPress version support term meta
	 *
	 * @return bool true on support
	 */
	function bf_use_wp_term_meta() {

		static $bf_use_wp_term_meta;

		if ( is_null( $bf_use_wp_term_meta ) ) {
			$bf_use_wp_term_meta = get_option( 'db_version' ) >= 34370 && function_exists( 'add_term_meta' );
		}

		return $bf_use_wp_term_meta;
	}
}

if ( ! function_exists( 'bf_get_term_meta' ) ) {
	/**
	 * Used For retrieving meta of term
	 *
	 * @param   int|object  $term_id       Term ID or object
	 * @param   string      $meta_key      Custom Field ID
	 * @param   bool|string $force_default Default Value
	 * @param   bool        $single        Whether to return a single value. If false, an array of all values matching the
	 *                                     `$term_id`/`$key` pair will be returned. Default: false.
	 *
	 * @return mixed If `$single` is false, an array of metadata values. If `$single` is true, a single metadata value.
	 */
	function bf_get_term_meta( $meta_key, $term_id = null, $force_default = null, $single = true ) {

		// Extract ID from term object if passed
		if ( is_object( $term_id ) ) {

			if ( ! is_a( $term_id, 'WP_Term' ) ) {
				return bf_get_term_meta_default( $meta_key, $force_default );
			}

			if ( isset( $term_id->term_id ) ) {
				$term_id = $term_id->term_id;
			} else {
				return $force_default;
			}
		}


		if ( bf_use_wp_term_meta() ) {

			if ( ! $term_id ) {
				if ( is_category() || is_tag() || is_tax() ) {
					$queried_object = get_queried_object();
					$term_id        = isset( $queried_object->term_id ) ? $queried_object->term_id : 0;
				}
			}

			if ( $term_id ) {

				$meta_value = get_term_meta( $term_id, $meta_key, $single );

				if ( is_null( $meta_value ) || $meta_value === '' ) {
					// Calculates default value from panel
					if ( is_null( $force_default ) ) {
						return bf_get_term_meta_default( $meta_key, '' );
					} else {
						return $force_default;
					}
				}
			} else {
				return bf_get_term_meta_default( $meta_key, '' );
			}


			return $meta_value;
		}


		// If term ID not passed
		if ( is_null( $term_id ) ) {
			// If its category or tag archive get that term ID
			if ( is_category() || is_tag() || is_tax() ) {
				$queried_object = get_queried_object();
				$term_id        = isset( $queried_object->term_id ) ? $queried_object->term_id : 0;
			} else {
				return $force_default;
			}

		}


		// init 
		if ( ! class_exists( 'BF_Taxonomy_Core' ) ) {
			Better_Framework()->taxonomy_meta();
		}


		// Return it from cache
		if ( isset( BF_Taxonomy_Core::$cache[ $term_id ][ $meta_key ] ) ) {
			return BF_Taxonomy_Core::$cache[ $term_id ][ $meta_key ];
		} elseif ( empty( $meta_key ) ) {
			if ( $cached = BF_Taxonomy_Core::$cache[ $term_id ] ) {
				return $cached;
			}
		}

		// Returns from saved meta
		if ( $output = get_option( 'bf_term_' . $term_id ) ) {
			if ( isset( $output[ $meta_key ] ) ) {
				BF_Taxonomy_Core::$cache[ $term_id ] = $output; // Save to cache

				return $output[ $meta_key ];
			} elseif ( empty( $meta_key ) ) {
				return $output;
			}
		}

		// Default value for function have more priority to std field
		if ( ! is_null( $force_default ) ) {
			return $force_default;
		}

		// Calculates and returns from meta box STD value
		return bf_get_term_meta_default( $meta_key, '' );
	}
}


if ( ! function_exists( 'bf_echo_term_meta' ) ) {
	/**
	 * Used For echo meta of term
	 *
	 * @param   int|object  $term_id       Term ID or object
	 * @param   string      $meta_id       Custom Field ID
	 * @param   bool|string $force_default Default Value
	 *
	 * @return bool
	 */
	function bf_echo_term_meta( $meta_id, $term_id = null, $force_default = null ) {

		echo bf_get_term_meta( $meta_id, $term_id, $force_default ); // escaped before
	}
}


if ( ! function_exists( 'bf_update_term_meta' ) ) {

	/**
	 * Updates term metadata.
	 *
	 * Use the `$prev_value` parameter to differentiate between meta fields with the same key and term ID.
	 *
	 * If the meta field for the term does not exist, it will be added.
	 *
	 * @param int    $term_id    Term ID.
	 * @param string $meta_key   Metadata key.
	 * @param mixed  $meta_value Metadata value.
	 * @param mixed  $prev_value Optional. Previous value to check before removing.
	 *
	 * @return int|WP_Error|bool Meta ID if the key didn't previously exist. true on successful update.
	 *                           WP_Error when term_id is ambiguous between taxonomies. False on failure.
	 */
	function bf_update_term_meta( $term_id, $meta_key, $meta_value, $prev_value = '' ) {

		if ( bf_use_wp_term_meta() ) {
			return update_term_meta( $term_id, $meta_key, $meta_value, $prev_value );
		}

		//use old method
		$all_meta  = get_option( 'bf_term_' . $term_id, array() );
		$old_value = isset( $all_meta[ $meta_key ] ) ? $all_meta[ $meta_key ] : null;

		// Compare existing value to new value if no prev value given and the key exists only once.
		if ( empty( $prev_value ) ) {
			if ( $old_value === $meta_value ) {
				return false;
			}
		} else {
			$prev_value = maybe_serialize( $prev_value );
			if ( maybe_serialize( $old_value ) !== $prev_value ) {
				return false;
			}
		}

		$all_meta[ $meta_key ] = $meta_value;

		return update_option( 'bf_term_' . $term_id, $all_meta, 'no' );
	}
}

if ( ! function_exists( 'bf_delete_term_meta' ) ) {

	/**
	 * Removes metadata matching criteria from a term.
	 *
	 * @param int    $term_id    Term ID.
	 * @param string $meta_key   Metadata name.
	 * @param mixed  $meta_value Optional. Metadata value. If provided, rows will only be removed that match the value.
	 *
	 * @return bool true on success, false on failure.
	 */
	function bf_delete_term_meta( $term_id, $meta_key, $meta_value = '' ) {

		if ( bf_use_wp_term_meta() ) {
			return delete_term_meta( $term_id, $meta_key, $meta_value );
		}

		//use old method
		$all_meta  = get_option( 'bf_term_' . $term_id, array() );
		$old_value = isset( $all_meta[ $meta_key ] ) ? $all_meta[ $meta_key ] : null;

		// Compare existing value to new value if no prev value given and the key exists only once.
		if ( ! empty( $meta_value ) ) {
			$meta_value = maybe_serialize( $meta_value );
			if ( maybe_serialize( $old_value ) !== $meta_value ) {
				return false;
			}
		}
		unset( $all_meta[ $meta_key ] );

		return update_option( 'bf_term_' . $term_id, $all_meta, 'no' );
	}
}


if ( ! function_exists( 'bf_add_term_meta' ) ) {

	/**
	 * Adds metadata to a term.
	 *
	 * @param int    $term_id    Term ID.
	 * @param string $meta_key   Metadata name.
	 * @param mixed  $meta_value Metadata value.
	 * @param bool   $unique     Optional. Whether to bail if an entry with the same key is found for the term.
	 *                           Default false.
	 *
	 * @return int|WP_Error|bool Meta ID on success. WP_Error when term_id is ambiguous between taxonomies.
	 *                           False on failure.
	 */
	function bf_add_term_meta( $term_id, $meta_key, $meta_value, $unique = false ) {

		if ( bf_use_wp_term_meta() ) {
			return add_term_meta( $term_id, $meta_key, $meta_value, $unique );
		}

		return bf_update_term_meta( $term_id, $meta_key, $meta_value );
	}
}


if ( ! function_exists( 'bf_get_term_meta_default' ) ) {
	/**
	 * @param      $meta_key
	 * @param null $default
	 *
	 * @return null
	 */
	function bf_get_term_meta_default( $meta_key, $default = null ) {

		// init
		if ( ! class_exists( 'BF_Taxonomy_Core' ) ) {
			Better_Framework()->taxonomy_meta();
		}

		// Iterate All Metaboxe
		foreach ( BF_Taxonomy_Core::$metabox as $metabox_id => $metabox ) {

			$metabox_std = BF_Taxonomy_Core::get_metabox_std( $metabox_id );

			if ( ! isset( $metabox_std[ $meta_key ] ) ) {
				unset( $metabox_std );
				continue;
			}

			if ( isset( $metabox['panel-id'] ) ) {
				$std_id = BF_Options::get_panel_std_id( $metabox['panel-id'] );
			} else {
				$std_id = 'std';
			}

			if ( isset( $metabox_std[ $meta_key ][ $std_id ] ) ) {
				return $metabox_std[ $meta_key ][ $std_id ];
			} elseif ( isset( $metabox_std[ $meta_key ]['std'] ) ) {
				return $metabox_std[ $meta_key ]['std'];
			} else {
				return $default;
			}

		}// for

	} // bf_get_term_meta_default
}
libs/better-framework/taxonomy/class-bf-taxonomy-meta-field.php000064400000015630151214002540020716 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Used for adding custom fields to Taxonomy fields
 */
class BF_Taxonomy_Meta_Field {

	public $metabox_id = '';


	/**
	 * Initialize Taxonomy Meta
	 *
	 * @param $metabox_id
	 */
	public function __construct( $metabox_id ) {

		if ( ! isset( BF_Taxonomy_Core::$metabox[ $metabox_id ] ) ) {
			return;
		}

		$this->metabox_id = $metabox_id;

		$metabox_config = BF_Taxonomy_Core::get_metabox_config( $metabox_id );

		if ( ! is_array( $metabox_config['taxonomies'] ) ) {

			add_action( $metabox_config['taxonomies'] . '_add_form_fields', array(
				$this,
				'add_form_fields'
			), 10, 2 );

			add_action( $metabox_config['taxonomies'] . '_edit_form', array(
				$this,
				'add_form_fields'
			), 10, 2 );

			add_action( 'create_' . $metabox_config['taxonomies'], array( $this, 'save_fields' ) );

			add_action( 'edited_' . $metabox_config['taxonomies'], array(
				$this,
				'save_fields'
			), 10, 2 );

		} else {

			foreach ( $metabox_config['taxonomies'] as $taxonomy ) {

				add_action( $taxonomy . '_add_form_fields', array( $this, 'add_form_fields' ), 10, 2 );
				add_action( $taxonomy . '_edit_form', array( $this, 'add_form_fields' ), 10, 2 );

				add_action( 'create_' . $taxonomy, array( $this, 'save_fields' ) );
				add_action( 'edited_' . $taxonomy, array( $this, 'save_fields' ) );

			}

		}

		add_action( 'delete_term', array( __CLASS__, 'delete_tax_data' ), 10, 2 );

		unset( $metabox_config );
		unset( $metabox_id );

		if ( ! has_action( 'better-framework/taxonomy/metabox/ajax-tab', __CLASS__ . '::ajax_tab' ) ) {
			/**
			 * Action to handle ajax taxonomy metabox tabs
			 */
			add_action( 'better-framework/taxonomy/metabox/ajax-tab', __CLASS__ . '::ajax_tab', 10, 3 );
		}
	}


	/**
	 * Adds fields to add and edit form in Taxonomy admin form
	 *
	 * @param null
	 */
	public function add_form_fields( $term = null ) {

		$values = array();

		if ( is_object( $term ) ) {
			$term_id = $term->term_id;
		} else {
			$term_id = '';
		}


		$metabox = array(
			'config' => BF_Taxonomy_Core::get_metabox_config( $this->metabox_id ),
			'fields' => BF_Taxonomy_Core::get_metabox_fields( $this->metabox_id ),
		);

		foreach ( $metabox['fields'] as $key => $field ) {

			if ( $field['type'] == 'tab' || $field['type'] == 'group' ) {
				continue;
			}

			if ( ! empty( $field['id'] ) ) {

				//  this returns default value if term mta is not saved before
				$values[ $field['id'] ] = bf_get_term_meta( $field['id'], $term_id );

			}
		}

		$front_end = new BF_Taxonomy_Front_End_Generator( $metabox, $term_id, $values, $this->metabox_id );

		echo $front_end->callback();  // escaped before

	}


	/**
	 * Save taxonomy custom options as an option
	 *
	 * @param $term_id
	 */
	public function save_fields( $term_id ) {

		if ( ! isset( $_POST['bf-term-meta'] ) ) {
			return;
		}

		if ( isset( BF_Taxonomy_Core::$metabox[ $this->metabox_id ]['panel-id'] ) ) {
			$std_id = Better_Framework::options()->get_panel_std_id( BF_Taxonomy_Core::$metabox[ $this->metabox_id ]['panel-id'] );
		} else {
			$std_id = 'std';
		}


		foreach ( BF_Taxonomy_Core::get_metabox_std( $this->metabox_id ) as $key => $field ) {

			// add / update meta
			if ( isset( $_POST['bf-term-meta'][ $key ] ) ) {

				$save = true;

				// check for saving default or not!?
				if ( isset( $field['save-std'] ) && ! $field['save-std'] ) {

					if ( isset( $field[ $std_id ] ) && $_POST['bf-term-meta'][ $key ] == $field[ $std_id ] ) {
						$save = false;
					} elseif ( isset( $field['std'] ) && $_POST['bf-term-meta'][ $key ] == $field['std'] ) {
						$save = false;
					}
				}

				if ( $save === false ) {
					bf_delete_term_meta( $term_id, $key );
				} else {
					bf_update_term_meta( $term_id, $key, $_POST['bf-term-meta'][ $key ] );
				}

			}// if
		}// for

	} // save_fields


	/**
	 * Delete taxonomy option from option table
	 *
	 * @param $term
	 * @param $term_id
	 */
	public static function delete_tax_data( $term, $term_id ) {

		if ( $all_meta = bf_get_term_meta( '', $term_id ) ) {
			foreach ( $all_meta as $meta_key => $meta_value ) {
				bf_delete_term_meta( $term_id, $meta_key );
			}
		}
	}


	public static function ajax_tab( $section_id, $metabox_id, $term_id ) {

		$metabox       = array(
			'config' => BF_Taxonomy_Core::get_metabox_config( $metabox_id ),
			'fields' => BF_Taxonomy_Core::get_metabox_fields( $metabox_id ),
		);
		$use_generator = true;
		$values        = array();


		if ( empty( $metabox['fields'][ $section_id ]['ajax-section-handler'] ) ) {

			foreach ( $metabox['fields'] as $key => $field ) {

				// Backward compatibility
				if ( isset( $field['ajax-tab-field'] ) ) {
					$field['ajax-section-field'] = $field['ajax-tab-field'];
				}

				if ( empty( $field['ajax-section-field'] ) || $field['ajax-section-field'] !== $section_id ) {
					unset( $metabox['fields'][ $key ] );
				} elseif ( $field['type'] !== 'tab' && $field['type'] !== 'group' ) {


					if ( isset( $field['type'] ) && $field['type'] == 'info' && $field['std'] ) {
						$field['value'] = $field['std'];
					} else {
						//  this returns default value if term mta is not saved before
						$values[ $field['id'] ] = bf_get_term_meta( $field['id'], $term_id );
					}

				}
			}

		} else {

			$parent_field = $metabox['fields'][ $section_id ];

			$args = isset( $parent_field['ajax-section-handler-args'] ) ? $parent_field['ajax-section-handler-args'] : array();
			$args = array_merge( $args, compact( 'metabox_id', 'section_id' ) );

			if (
				! isset( $parent_field['ajax-section-handler-type'] ) ||
				$parent_field['ajax-section-handler-type'] === 'field-generator'
			) {

				$metabox['fields'] = call_user_func( $parent_field['ajax-section-handler'], $args );

				foreach ( $metabox['fields'] as $key => $field ) {

					$values[ $field['id'] ] = bf_get_term_meta( $field['id'], $term_id );
				}
			} else {

				$use_generator = false;
				$out           = call_user_func( $parent_field['ajax-section-handler'], $args );

			}
		}


		if ( $use_generator ) {
			$front_end = new BF_Taxonomy_Front_End_Generator( $metabox, $term_id, $values, $metabox_id );
			ob_start();
			echo $front_end->callback( true );  // escaped before
			$out = ob_get_clean();
		}

		wp_send_json( array( 'out' => $out, 'tab_id' => $section_id ) );
	}
}
libs/better-framework/taxonomy/index.php000064400000000012151214002540014436 0ustar00<?php
die;libs/better-framework/taxonomy/templates/default.php000064400000005551151214002540016766 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes   = $classes['section'];
$container_classes = $classes['container'];

$heading_classes  = $classes['heading'];
$controls_classes = $classes['controls'];
$explain_classes  = $classes['explain'];

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];

if ( ! isset( $options['desc'] ) || empty( $options['desc'] ) ) {
	$controls_classes .= ' ' . 'no-desc';
}


$section_attr = $this->get_section_filter_attr( $options );

?>
<div
		class="<?php echo esc_attr( $container_classes ); ?> bf-metabox bf-clearfix" <?php echo $section_attr// escaped before; ?>>
	<div class="<?php echo esc_attr( $section_classes ); ?> bf-clearfix"
	     data-id="<?php echo esc_attr( $options['id'] ); ?>">

		<div class="<?php echo esc_attr( $heading_classes ); ?> bf-clearfix">
			<h3><label><?php echo esc_attr( $options['name'] ); ?></label></h3>
		</div>

		<div class="<?php echo esc_attr( $controls_classes ); ?> bf-clearfix">
			<?php echo $input; // escaped before ?>
		</div>

		<?php if ( ! empty( $options['desc'] ) ) { ?>
			<div
					class="<?php echo esc_attr( $explain_classes ); ?> bf-clearfix"><?php echo wp_kses( $options['desc'], 'better-studio' ); ?></div>
		<?php } ?>

	</div>
</div>libs/better-framework/taxonomy/templates/hr.php000064400000001600151214002540015742 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div class="bf-section-container bf-clearfix">
	<div class="bf-section-hr bf-clearfix">
		<?php echo $input; // escaped before ?>
	</div>
</div>libs/better-framework/taxonomy/templates/info.php000064400000005700151214002540016271 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


$classes = $this->get_classes( $options );
$iri     = isset( $options['repeater_item'] ) && $options['repeater_item'] == true; // Is this section for a repeater item

$section_classes = $classes['section'] . ' bf-widget-field-section';

$heading_classes  = $classes['heading'] . ' bf-heading';
$controls_classes = $classes['controls'] . ' bf-control not-prepared';
$explain_classes  = $classes['explain'] . ' bf-desc';

if ( $iri ) {

	$section_classes  .= ' ' . $classes['repeater-section'];
	$heading_classes  .= ' ' . $classes['repeater-heading'];
	$controls_classes .= ' ' . $classes['repeater-controls'];
	$explain_classes  .= ' ' . $classes['repeater-explain'];

} else {

	$section_classes  .= ' ' . $classes['nonrepeater-section'];
	$heading_classes  .= ' ' . $classes['nonrepeater-heading'];
	$controls_classes .= ' ' . $classes['nonrepeater-controls'];
	$explain_classes  .= ' ' . $classes['nonrepeater-explain'];

}

$section_classes  .= ' ' . $classes['section-class-by-filed-type'];
$heading_classes  .= ' ' . $classes['heading-class-by-filed-type'];
$controls_classes .= ' ' . $classes['controls-class-by-filed-type'];
$explain_classes  .= ' ' . $classes['explain-class-by-filed-type'];


if ( ! isset( $options['info-type'] ) ) {
	$options['info-type'] = 'info';
}

if ( ! isset( $options['state'] ) ) {
	$options['state'] = 'open';
}

?>
<div class="bf-section-container bf-metabox bf-clearfix">
	<div
			class="bf-section-info <?php echo esc_attr( $options['info-type'] ); ?> <?php echo esc_attr( $options['state'] ); ?> bf-clearfix">
		<div class="bf-section-info-title bf-clearfix">
			<h3><?php

				switch ( $options['info-type'] ) {

					case 'help':
						echo '<i class="fa fa-support"></i> ';
						break;

					case 'info':
						echo '<i class="fa fa-info"></i> ';
						break;

					case 'warning':
						echo '<i class="fa fa-warning"></i> ';
						break;

					case 'danger':
						echo '<i class="fa fa-exclamation"></i> ';
						break;

					default:
						echo '<i class="fa fa-info"></i> ';
						break;


				}

				echo esc_html( $options['name'] ); ?></h3>
		</div>
		<div class="<?php echo esc_attr( $controls_classes ); ?>  bf-clearfix">
			<?php echo $input; // escaped before in generating ?>
		</div>
	</div>
</div>libs/better-framework/assets/js/slick.min.js000064400000126313151214002540015120 0ustar00/*
     _ _      _       _
 ___| (_) ___| | __  (_)___
/ __| | |/ __| |/ /  | / __|
\__ \ | | (__|   < _ | \__ \
|___/_|_|\___|_|\_(_)/ |___/
                   |__/

 Version: 1.6.0
  Author: Ken Wheeler
 Website: http://kenwheeler.github.io
    Docs: http://kenwheeler.github.io/slick
    Repo: http://github.com/kenwheeler/slick
  Issues: http://github.com/kenwheeler/slick/issues
 */
!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):"undefined"!=typeof exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){"use strict";var b=window.Slick||{};b=function(){function c(c,d){var f,e=this;e.defaults={accessibility:!0,adaptiveHeight:!1,appendArrows:a(c),appendDots:a(c),arrows:!0,asNavFor:null,prevArrow:'<button type="button" data-role="none" class="slick-prev" aria-label="Previous" tabindex="0" role="button">Previous</button>',nextArrow:'<button type="button" data-role="none" class="slick-next" aria-label="Next" tabindex="0" role="button">Next</button>',autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:"50px",cssEase:"ease",customPaging:function(b,c){return a('<button type="button" data-role="none" role="button" tabindex="0" />').text(c+1)},dots:!1,dotsClass:"slick-dots",draggable:!0,easing:"linear",edgeFriction:.35,fade:!1,focusOnSelect:!1,infinite:!0,initialSlide:0,lazyLoad:"ondemand",mobileFirst:!1,pauseOnHover:!0,pauseOnFocus:!0,pauseOnDotsHover:!1,respondTo:"window",responsive:null,rows:1,rtl:!1,slide:"",slidesPerRow:1,slidesToShow:1,slidesToScroll:1,speed:500,swipe:!0,swipeToSlide:!1,touchMove:!0,touchThreshold:5,useCSS:!0,useTransform:!0,variableWidth:!1,vertical:!1,verticalSwiping:!1,waitForAnimate:!0,zIndex:1e3,slideMargin:0,classPrefix:"slick-"},e.initials={animating:!1,dragging:!1,autoPlayTimer:null,currentDirection:0,currentLeft:null,currentSlide:0,direction:1,$dots:null,listWidth:null,listHeight:null,loadIndex:0,$nextArrow:null,$prevArrow:null,slideCount:null,slideWidth:null,$slideTrack:null,$slides:null,sliding:!1,slideOffset:0,swipeLeft:null,$list:null,touchObject:{},transformsEnabled:!1,unslicked:!1},a.extend(e,e.initials),e.activeBreakpoint=null,e.animType=null,e.animProp=null,e.breakpoints=[],e.breakpointSettings=[],e.cssTransitions=!1,e.focussed=!1,e.interrupted=!1,e.hidden="hidden",e.paused=!0,e.positionProp=null,e.respondTo=null,e.rowCount=1,e.shouldClick=!0,e.$slider=a(c),e.$slidesCache=null,e.transformType=null,e.transitionType=null,e.visibilityChange="visibilitychange",e.windowWidth=0,e.windowTimer=null,f=a(c).data("slick")||{},e.options=a.extend({},e.defaults,d,f),e.currentSlide=e.options.initialSlide,e.originalSettings=e.options,"undefined"!=typeof document.mozHidden?(e.hidden="mozHidden",e.visibilityChange="mozvisibilitychange"):"undefined"!=typeof document.webkitHidden&&(e.hidden="webkitHidden",e.visibilityChange="webkitvisibilitychange"),e.autoPlay=a.proxy(e.autoPlay,e),e.autoPlayClear=a.proxy(e.autoPlayClear,e),e.autoPlayIterator=a.proxy(e.autoPlayIterator,e),e.changeSlide=a.proxy(e.changeSlide,e),e.clickHandler=a.proxy(e.clickHandler,e),e.selectHandler=a.proxy(e.selectHandler,e),e.setPosition=a.proxy(e.setPosition,e),e.swipeHandler=a.proxy(e.swipeHandler,e),e.dragHandler=a.proxy(e.dragHandler,e),e.keyHandler=a.proxy(e.keyHandler,e),e.instanceUid=b++,e.htmlExpr=/^(?:\s*(<[\w\W]+>)[^>]*)$/,e.registerBreakpoints(),e.init(!0)}var b=0;return c}(),b.prototype.activateADA=function(){var a=this;a.$slideTrack.find("."+a.options.classPrefix+"active").attr({"aria-hidden":"false"}).find("a, input, button, select").attr({tabindex:"0"})},b.prototype.addSlide=b.prototype.slickAdd=function(b,c,d){var e=this;if("boolean"==typeof c)d=c,c=null;else if(c<0||c>=e.slideCount)return!1;e.unload(),"number"==typeof c?0===c&&0===e.$slides.length?a(b).appendTo(e.$slideTrack):d?a(b).insertBefore(e.$slides.eq(c)):a(b).insertAfter(e.$slides.eq(c)):d===!0?a(b).prependTo(e.$slideTrack):a(b).appendTo(e.$slideTrack),e.$slides=e.$slideTrack.children(this.options.slide),e.$slideTrack.children(this.options.slide).detach(),e.$slideTrack.append(e.$slides),e.$slides.each(function(b,c){a(c).attr("data-"+e.options.classPrefix+"index",b)}),e.$slidesCache=e.$slides,e.reinit()},b.prototype.animateHeight=function(){var a=this;if(1===a.options.slidesToShow&&a.options.adaptiveHeight===!0&&a.options.vertical===!1){var b=a.$slides.eq(a.currentSlide).outerHeight(!0);a.$list.animate({height:b},a.options.speed)}},b.prototype.animateSlide=function(b,c){var d={},e=this;if(e.animateHeight(),e.options.rtl===!0&&e.options.vertical===!1&&(b=-b),e.transformsEnabled===!1)e.options.vertical===!1?e.$slideTrack.animate({left:b},e.options.speed,e.options.easing,c):e.$slideTrack.animate({top:b},e.options.speed,e.options.easing,c);else if(e.cssTransitions===!1)e.options.rtl===!0&&(e.currentLeft=-e.currentLeft),a({animStart:e.currentLeft}).animate({animStart:b},{duration:e.options.speed,easing:e.options.easing,step:function(a){a=Math.ceil(a),e.options.vertical===!1?(d[e.animType]="translate("+a+"px, 0px)",e.$slideTrack.css(d)):(d[e.animType]="translate(0px,"+a+"px)",e.$slideTrack.css(d))},complete:function(){c&&c.call()}});else{e.applyTransition();var f=e.options.rtl===!0?1:-1;b=Math.ceil(b+e.options.slideMargin*f),e.options.vertical===!1?d[e.animType]="translate3d("+b+"px, 0px, 0px)":d[e.animType]="translate3d(0px,"+b+"px, 0px)",e.$slideTrack.css(d),c&&setTimeout(function(){e.disableTransition(),c.call()},e.options.speed)}},b.prototype.getNavTarget=function(){var b=this,c=b.options.asNavFor;return c&&null!==c&&(c=a(c).not(b.$slider)),c},b.prototype.asNavFor=function(b){var c=this,d=c.getNavTarget();null!==d&&"object"==typeof d&&d.each(function(){var c=a(this).slick("getSlick");c.unslicked||c.slideHandler(b,!0)})},b.prototype.applyTransition=function(a){var b=this,c={};b.options.fade===!1?c[b.transitionType]=b.transformType+" "+b.options.speed+"ms "+b.options.cssEase:c[b.transitionType]="opacity "+b.options.speed+"ms "+b.options.cssEase,b.options.fade===!1?b.$slideTrack.css(c):b.$slides.eq(a).css(c)},b.prototype.autoPlay=function(){var a=this;a.autoPlayClear(),a.slideCount>a.options.slidesToShow&&(a.autoPlayTimer=setInterval(a.autoPlayIterator,a.options.autoplaySpeed))},b.prototype.autoPlayClear=function(){var a=this;a.autoPlayTimer&&clearInterval(a.autoPlayTimer)},b.prototype.autoPlayIterator=function(){var a=this,b=a.currentSlide+a.options.slidesToScroll;a.paused||a.interrupted||a.focussed||(a.options.infinite===!1&&(1===a.direction&&a.currentSlide+1===a.slideCount-1?a.direction=0:0===a.direction&&(b=a.currentSlide-a.options.slidesToScroll,a.currentSlide-1===0&&(a.direction=1))),a.slideHandler(b))},b.prototype.buildArrows=function(){var b=this;b.options.arrows===!0&&(b.$prevArrow=a(b.options.prevArrow).addClass(b.options.classPrefix+"arrow"),b.$nextArrow=a(b.options.nextArrow).addClass(b.options.classPrefix+"arrow"),b.slideCount>b.options.slidesToShow?(b.$prevArrow.removeClass(b.options.classPrefix+"hidden").removeAttr("aria-hidden tabindex"),b.$nextArrow.removeClass(b.options.classPrefix+"hidden").removeAttr("aria-hidden tabindex"),b.htmlExpr.test(b.options.prevArrow)&&b.$prevArrow.prependTo(b.options.appendArrows),b.htmlExpr.test(b.options.nextArrow)&&b.$nextArrow.appendTo(b.options.appendArrows),b.options.infinite!==!0&&b.$prevArrow.addClass(b.options.classPrefix+"disabled").attr("aria-disabled","true")):b.$prevArrow.add(b.$nextArrow).addClass(b.options.classPrefix+"hidden").attr({"aria-disabled":"true",tabindex:"-1"}))},b.prototype.buildDots=function(){var c,d,b=this;if(b.options.dots===!0&&b.slideCount>b.options.slidesToShow){for(b.$slider.addClass(b.options.classPrefix+"dotted"),d=a("<ul />").addClass(b.options.dotsClass),c=0;c<=b.getDotCount();c+=1)d.append(a("<li />").append(b.options.customPaging.call(this,b,c)));b.$dots=d.appendTo(b.options.appendDots),b.$dots.find("li").first().addClass(b.options.classPrefix+"active").attr("aria-hidden","false")}},b.prototype.buildOut=function(){var b=this;if(b.$slides=b.$slider.children(b.options.slide+":not(."+b.options.classPrefix+"cloned)").addClass(b.options.classPrefix+"slide"),b.options.slideMargin){var c=b.options.rtl===!0?"right":"left";b.$slides.css("margin-"+c,b.options.slideMargin)}b.slideCount=b.$slides.length,b.$slides.each(function(c,d){a(d).attr("data-"+b.options.classPrefix+"index",c).data("originalStyling",a(d).attr("style")||"")}),b.$slider.addClass(b.options.classPrefix+"slider"),b.$slideTrack=0===b.slideCount?a('<div class="'+b.options.classPrefix+'track"/>').appendTo(b.$slider):b.$slides.wrapAll('<div class="'+b.options.classPrefix+'track"/>').parent(),b.$list=b.$slideTrack.wrap('<div aria-live="polite" class="'+b.options.classPrefix+'list"/>').parent(),b.$slideTrack.css("opacity",0),b.options.centerMode!==!0&&b.options.swipeToSlide!==!0||(b.options.slidesToScroll=1),a("img[data-lazy]",b.$slider).not("[src]").addClass(b.options.classPrefix+"loading"),b.setupInfinite(),b.buildArrows(),b.buildDots(),b.updateDots(),b.setSlideClasses("number"==typeof b.currentSlide?b.currentSlide:0),b.options.draggable===!0&&b.$list.addClass("draggable")},b.prototype.buildRows=function(){var b,c,d,e,f,g,h,a=this;if(e=document.createDocumentFragment(),g=a.$slider.children(),a.options.rows>1){for(h=a.options.slidesPerRow*a.options.rows,f=Math.ceil(g.length/h),b=0;b<f;b++){var i=document.createElement("div");for(c=0;c<a.options.rows;c++){var j=document.createElement("div");for(d=0;d<a.options.slidesPerRow;d++){var k=b*h+(c*a.options.slidesPerRow+d);g.get(k)&&j.appendChild(g.get(k))}i.appendChild(j)}e.appendChild(i)}a.$slider.empty().append(e),a.$slider.children().children().children().css({width:100/a.options.slidesPerRow+"%",display:"inline-block"})}},b.prototype.checkResponsive=function(b,c){var e,f,g,d=this,h=!1,i=d.$slider.width(),j=window.innerWidth||a(window).width();if("window"===d.respondTo?g=j:"slider"===d.respondTo?g=i:"min"===d.respondTo&&(g=Math.min(j,i)),d.options.responsive&&d.options.responsive.length&&null!==d.options.responsive){f=null;for(e in d.breakpoints)d.breakpoints.hasOwnProperty(e)&&(d.originalSettings.mobileFirst===!1?g<d.breakpoints[e]&&(f=d.breakpoints[e]):g>d.breakpoints[e]&&(f=d.breakpoints[e]));null!==f?null!==d.activeBreakpoint?(f!==d.activeBreakpoint||c)&&(d.activeBreakpoint=f,"unslick"===d.breakpointSettings[f]?d.unslick(f):(d.options=a.extend({},d.originalSettings,d.breakpointSettings[f]),b===!0&&(d.currentSlide=d.options.initialSlide),d.refresh(b)),h=f):(d.activeBreakpoint=f,"unslick"===d.breakpointSettings[f]?d.unslick(f):(d.options=a.extend({},d.originalSettings,d.breakpointSettings[f]),b===!0&&(d.currentSlide=d.options.initialSlide),d.refresh(b)),h=f):null!==d.activeBreakpoint&&(d.activeBreakpoint=null,d.options=d.originalSettings,b===!0&&(d.currentSlide=d.options.initialSlide),d.refresh(b),h=f),b||h===!1||d.$slider.trigger("breakpoint",[d,h])}},b.prototype.changeSlide=function(b,c){var f,g,h,d=this,e=a(b.currentTarget);switch(e.is("a")&&b.preventDefault(),e.is("li")||(e=e.closest("li")),h=d.slideCount%d.options.slidesToScroll!==0,f=h?0:(d.slideCount-d.currentSlide)%d.options.slidesToScroll,b.data.message){case"previous":g=0===f?d.options.slidesToScroll:d.options.slidesToShow-f,d.slideCount>d.options.slidesToShow&&d.slideHandler(d.currentSlide-g,!1,c);break;case"next":g=0===f?d.options.slidesToScroll:f,d.slideCount>d.options.slidesToShow&&d.slideHandler(d.currentSlide+g,!1,c);break;case"index":var i=0===b.data.index?0:b.data.index||e.index()*d.options.slidesToScroll;d.slideHandler(d.checkNavigable(i),!1,c),e.children().trigger("focus");break;default:return}},b.prototype.checkNavigable=function(a){var c,d,b=this;if(c=b.getNavigableIndexes(),d=0,a>c[c.length-1])a=c[c.length-1];else for(var e in c){if(a<c[e]){a=d;break}d=c[e]}return a},b.prototype.cleanUpEvents=function(){var b=this;b.options.dots&&null!==b.$dots&&a("li",b.$dots).off("click.slick",b.changeSlide).off("mouseenter.slick",a.proxy(b.interrupt,b,!0)).off("mouseleave.slick",a.proxy(b.interrupt,b,!1)),b.$slider.off("focus.slick blur.slick"),b.options.arrows===!0&&b.slideCount>b.options.slidesToShow&&(b.$prevArrow&&b.$prevArrow.off("click.slick",b.changeSlide),b.$nextArrow&&b.$nextArrow.off("click.slick",b.changeSlide)),b.$list.off("touchstart.slick mousedown.slick",b.swipeHandler),b.$list.off("touchmove.slick mousemove.slick",b.swipeHandler),b.$list.off("touchend.slick mouseup.slick",b.swipeHandler),b.$list.off("touchcancel.slick mouseleave.slick",b.swipeHandler),b.$list.off("click.slick",b.clickHandler),a(document).off(b.visibilityChange,b.visibility),b.cleanUpSlideEvents(),b.options.accessibility===!0&&b.$list.off("keydown.slick",b.keyHandler),b.options.focusOnSelect===!0&&a(b.$slideTrack).children().off("click.slick",b.selectHandler),a(window).off("orientationchange.slick.slick-"+b.instanceUid,b.orientationChange),a(window).off("resize.slick.slick-"+b.instanceUid,b.resize),a("[draggable!=true]",b.$slideTrack).off("dragstart",b.preventDefault),a(window).off("load.slick.slick-"+b.instanceUid,b.setPosition),a(document).off("ready.slick.slick-"+b.instanceUid,b.setPosition)},b.prototype.cleanUpSlideEvents=function(){var b=this;b.$list.off("mouseenter.slick",a.proxy(b.interrupt,b,!0)),b.$list.off("mouseleave.slick",a.proxy(b.interrupt,b,!1))},b.prototype.cleanUpRows=function(){var b,a=this;a.options.rows>1&&(b=a.$slides.children().children(),b.removeAttr("style"),a.$slider.empty().append(b))},b.prototype.clickHandler=function(a){var b=this;b.shouldClick===!1&&(a.stopImmediatePropagation(),a.stopPropagation(),a.preventDefault())},b.prototype.destroy=function(b){var c=this;c.autoPlayClear(),c.touchObject={},c.cleanUpEvents(),a("."+c.options.classPrefix+"cloned",c.$slider).detach(),c.$dots&&c.$dots.remove(),c.$prevArrow&&c.$prevArrow.length&&(c.$prevArrow.removeClass(c.options.classPrefix+"disabled "+c.options.classPrefix+"arrow "+c.options.classPrefix+"hidden").removeAttr("aria-hidden aria-disabled tabindex").css("display",""),c.htmlExpr.test(c.options.prevArrow)&&c.$prevArrow.remove()),c.$nextArrow&&c.$nextArrow.length&&(c.$nextArrow.removeClass(c.options.classPrefix+"disabled "+c.options.classPrefix+"arrow "+c.options.classPrefix+"hidden").removeAttr("aria-hidden aria-disabled tabindex").css("display",""),c.htmlExpr.test(c.options.nextArrow)&&c.$nextArrow.remove()),c.$slides&&(c.$slides.removeClass(c.options.classPrefix+"slide "+c.options.classPrefix+"active "+c.options.classPrefix+"center "+c.options.classPrefix+"visible "+c.options.classPrefix+"current").removeAttr("aria-hidden").removeAttr("data-"+c.options.classPrefix+"index").each(function(){a(this).attr("style",a(this).data("originalStyling"))}),c.$slideTrack.children(this.options.slide).detach(),c.$slideTrack.detach(),c.$list.detach(),c.$slider.append(c.$slides)),c.cleanUpRows(),c.$slider.removeClass(c.options.classPrefix+"slider"),c.$slider.removeClass(c.options.classPrefix+"initialized"),c.$slider.removeClass(c.options.classPrefix+"dotted"),c.unslicked=!0,b||c.$slider.trigger("destroy",[c])},b.prototype.disableTransition=function(a){var b=this,c={};c[b.transitionType]="",b.options.fade===!1?b.$slideTrack.css(c):b.$slides.eq(a).css(c)},b.prototype.fadeSlide=function(a,b){var c=this;c.cssTransitions===!1?(c.$slides.eq(a).css({zIndex:c.options.zIndex}),c.$slides.eq(a).animate({opacity:1},c.options.speed,c.options.easing,b)):(c.applyTransition(a),c.$slides.eq(a).css({opacity:1,zIndex:c.options.zIndex}),b&&setTimeout(function(){c.disableTransition(a),b.call()},c.options.speed))},b.prototype.fadeSlideOut=function(a){var b=this;b.cssTransitions===!1?b.$slides.eq(a).animate({opacity:0,zIndex:b.options.zIndex-2},b.options.speed,b.options.easing):(b.applyTransition(a),b.$slides.eq(a).css({opacity:0,zIndex:b.options.zIndex-2}))},b.prototype.filterSlides=b.prototype.slickFilter=function(a){var b=this;null!==a&&(b.$slidesCache=b.$slides,b.unload(),b.$slideTrack.children(this.options.slide).detach(),b.$slidesCache.filter(a).appendTo(b.$slideTrack),b.reinit())},b.prototype.focusHandler=function(){var b=this;b.$slider.off("focus.slick blur.slick").on("focus.slick blur.slick","*:not(."+b.options.classPrefix+"arrow)",function(c){c.stopImmediatePropagation();var d=a(this);setTimeout(function(){b.options.pauseOnFocus&&(b.focussed=d.is(":focus"),b.autoPlay())},0)})},b.prototype.getCurrent=b.prototype.slickCurrentSlide=function(){var a=this;return a.currentSlide},b.prototype.getDotCount=function(){var a=this,b=0,c=0,d=0;if(a.options.infinite===!0)for(;b<a.slideCount;)++d,b=c+a.options.slidesToScroll,c+=a.options.slidesToScroll<=a.options.slidesToShow?a.options.slidesToScroll:a.options.slidesToShow;else if(a.options.centerMode===!0)d=a.slideCount;else if(a.options.asNavFor)for(;b<a.slideCount;)++d,b=c+a.options.slidesToScroll,c+=a.options.slidesToScroll<=a.options.slidesToShow?a.options.slidesToScroll:a.options.slidesToShow;else d=1+Math.ceil((a.slideCount-a.options.slidesToShow)/a.options.slidesToScroll);return d-1},b.prototype.getLeft=function(a){var c,d,f,b=this,e=0;return b.slideOffset=0,d=b.$slides.first().outerHeight(!0),b.options.infinite===!0?(b.slideCount>b.options.slidesToShow&&(b.slideOffset=b.slideWidth*b.options.slidesToShow*-1,e=d*b.options.slidesToShow*-1),b.slideCount%b.options.slidesToScroll!==0&&a+b.options.slidesToScroll>b.slideCount&&b.slideCount>b.options.slidesToShow&&(a>b.slideCount?(b.slideOffset=(b.options.slidesToShow-(a-b.slideCount))*b.slideWidth*-1,e=(b.options.slidesToShow-(a-b.slideCount))*d*-1):(b.slideOffset=b.slideCount%b.options.slidesToScroll*b.slideWidth*-1,e=b.slideCount%b.options.slidesToScroll*d*-1))):a+b.options.slidesToShow>b.slideCount&&(b.slideOffset=(a+b.options.slidesToShow-b.slideCount)*b.slideWidth,e=(a+b.options.slidesToShow-b.slideCount)*d),b.slideCount<=b.options.slidesToShow&&(b.slideOffset=0,e=0),b.options.centerMode===!0&&b.options.infinite===!0?b.slideOffset+=b.slideWidth*Math.floor(b.options.slidesToShow/2)-b.slideWidth:b.options.centerMode===!0&&(b.slideOffset=0,b.slideOffset+=b.slideWidth*Math.floor(b.options.slidesToShow/2)),c=b.options.vertical===!1?a*b.slideWidth*-1+b.slideOffset:a*d*-1+e,b.options.variableWidth===!0&&(f=b.slideCount<=b.options.slidesToShow||b.options.infinite===!1?b.$slideTrack.children("."+b.options.classPrefix+"slide").eq(a):b.$slideTrack.children("."+b.options.classPrefix+"slide").eq(a+b.options.slidesToShow),c=b.options.rtl===!0?f[0]?(b.$slideTrack.width()-f[0].offsetLeft-f.width())*-1:0:f[0]?f[0].offsetLeft*-1:0,b.options.centerMode===!0&&(f=b.slideCount<=b.options.slidesToShow||b.options.infinite===!1?b.$slideTrack.children("."+b.options.classPrefix+"slide").eq(a):b.$slideTrack.children("."+b.options.classPrefix+"slide").eq(a+b.options.slidesToShow+1),c=b.options.rtl===!0?f[0]?(b.$slideTrack.width()-f[0].offsetLeft-f.width())*-1:0:f[0]?f[0].offsetLeft*-1:0,c+=(b.$list.width()-f.outerWidth())/2)),c},b.prototype.getOption=b.prototype.slickGetOption=function(a){var b=this;return b.options[a]},b.prototype.getNavigableIndexes=function(){var e,a=this,b=0,c=0,d=[];for(a.options.infinite===!1?e=a.slideCount:(b=a.options.slidesToScroll*-1,c=a.options.slidesToScroll*-1,e=2*a.slideCount);b<e;)d.push(b),b=c+a.options.slidesToScroll,c+=a.options.slidesToScroll<=a.options.slidesToShow?a.options.slidesToScroll:a.options.slidesToShow;return d},b.prototype.getSlick=function(){return this},b.prototype.getSlideCount=function(){var c,d,e,b=this;return e=b.options.centerMode===!0?b.slideWidth*Math.floor(b.options.slidesToShow/2):0,b.options.swipeToSlide===!0?(b.$slideTrack.find("."+b.options.classPrefix+"slide").each(function(c,f){if(f.offsetLeft-e+a(f).outerWidth()/2>b.swipeLeft*-1)return d=f,!1}),c=Math.abs(a(d).attr("data-"+b.options.classPrefix+"index")-b.currentSlide)||1):b.options.slidesToScroll},b.prototype.goTo=b.prototype.slickGoTo=function(a,b){var c=this;c.changeSlide({data:{message:"index",index:parseInt(a)}},b)},b.prototype.init=function(b){var c=this;a(c.$slider).hasClass(c.options.classPrefix+"initialized")||(a(c.$slider).addClass(c.options.classPrefix+"initialized"),c.buildRows(),c.buildOut(),c.setProps(),c.startLoad(),c.loadSlider(),c.initializeEvents(),c.updateArrows(),c.updateDots(),c.checkResponsive(!0),c.focusHandler()),b&&c.$slider.trigger("init",[c]),c.options.accessibility===!0&&c.initADA(),c.options.autoplay&&(c.paused=!1,c.autoPlay())},b.prototype.initADA=function(){var b=this;b.$slides.add(b.$slideTrack.find("."+b.options.classPrefix+"cloned")).attr({"aria-hidden":"true",tabindex:"-1"}).find("a, input, button, select").attr({tabindex:"-1"}),b.$slideTrack.attr("role","listbox"),b.$slides.not(b.$slideTrack.find("."+b.options.classPrefix+"cloned")).each(function(c){a(this).attr("role","option");var d=b.options.centerMode?c:Math.floor(c/b.options.slidesToShow);b.options.dots===!0&&a(this).attr("aria-describedby",b.options.classPrefix+"-slide"+b.instanceUid+d)}),null!==b.$dots&&b.$dots.attr("role","tablist").find("li").each(function(c){a(this).attr({role:"presentation","aria-selected":"false","aria-controls":"navigation"+b.instanceUid+c,id:b.options.classPrefix+"-slide"+b.instanceUid+c})}).first().attr("aria-selected","true").end().find("button").attr("role","button").end().closest("div").attr("role","toolbar"),b.activateADA()},b.prototype.initArrowEvents=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.off("click.slick").on("click.slick",{message:"previous"},a.changeSlide),a.$nextArrow.off("click.slick").on("click.slick",{message:"next"},a.changeSlide))},b.prototype.initDotEvents=function(){var b=this;b.options.dots===!0&&b.slideCount>b.options.slidesToShow&&a("li",b.$dots).on("click.slick",{message:"index"},b.changeSlide),b.options.dots===!0&&b.options.pauseOnDotsHover===!0&&a("li",b.$dots).on("mouseenter.slick",a.proxy(b.interrupt,b,!0)).on("mouseleave.slick",a.proxy(b.interrupt,b,!1))},b.prototype.initSlideEvents=function(){var b=this;b.options.pauseOnHover&&(b.$list.on("mouseenter.slick",a.proxy(b.interrupt,b,!0)),b.$list.on("mouseleave.slick",a.proxy(b.interrupt,b,!1)))},b.prototype.initializeEvents=function(){var b=this;b.initArrowEvents(),b.initDotEvents(),b.initSlideEvents(),b.$list.on("touchstart.slick mousedown.slick",{action:"start"},b.swipeHandler),b.$list.on("touchmove.slick mousemove.slick",{action:"move"},b.swipeHandler),b.$list.on("touchend.slick mouseup.slick",{action:"end"},b.swipeHandler),b.$list.on("touchcancel.slick mouseleave.slick",{action:"end"},b.swipeHandler),b.$list.on("click.slick",b.clickHandler),a(document).on(b.visibilityChange,a.proxy(b.visibility,b)),b.options.accessibility===!0&&b.$list.on("keydown.slick",b.keyHandler),b.options.focusOnSelect===!0&&a(b.$slideTrack).children().on("click.slick",b.selectHandler),a(window).on("orientationchange.slick.slick-"+b.instanceUid,a.proxy(b.orientationChange,b)),a(window).on("resize.slick.slick-"+b.instanceUid,a.proxy(b.resize,b)),a("[draggable!=true]",b.$slideTrack).on("dragstart",b.preventDefault),a(window).on("load.slick.slick-"+b.instanceUid,b.setPosition),a(document).on("ready.slick.slick-"+b.instanceUid,b.setPosition)},b.prototype.initUI=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.show(),a.$nextArrow.show()),a.options.dots===!0&&a.slideCount>a.options.slidesToShow&&a.$dots.show()},b.prototype.keyHandler=function(a){var b=this;a.target.tagName.match("TEXTAREA|INPUT|SELECT")||(37===a.keyCode&&b.options.accessibility===!0?b.changeSlide({data:{message:b.options.rtl===!0?"next":"previous"}}):39===a.keyCode&&b.options.accessibility===!0&&b.changeSlide({data:{message:b.options.rtl===!0?"previous":"next"}}))},b.prototype.lazyLoad=function(){function g(c){a("img[data-lazy]",c).each(function(){var c=a(this),d=a(this).attr("data-lazy"),e=document.createElement("img");e.onload=function(){c.animate({opacity:0},100,function(){c.attr("src",d).animate({opacity:1},200,function(){c.removeAttr("data-lazy").removeClass(b.options.classPrefix+"loading")}),b.$slider.trigger("lazyLoaded",[b,c,d])})},e.onerror=function(){c.removeAttr("data-lazy").removeClass(b.options.classPrefix+"loading").addClass(b.options.classPrefix+"lazyload-error"),b.$slider.trigger("lazyLoadError",[b,c,d])},e.src=d})}var c,d,e,f,b=this;b.options.centerMode===!0?b.options.infinite===!0?(e=b.currentSlide+(b.options.slidesToShow/2+1),f=e+b.options.slidesToShow+2):(e=Math.max(0,b.currentSlide-(b.options.slidesToShow/2+1)),f=2+(b.options.slidesToShow/2+1)+b.currentSlide):(e=b.options.infinite?b.options.slidesToShow+b.currentSlide:b.currentSlide,f=Math.ceil(e+b.options.slidesToShow),b.options.fade===!0&&(e>0&&e--,f<=b.slideCount&&f++)),c=b.$slider.find("."+b.options.classPrefix+"slide").slice(e,f),g(c),b.slideCount<=b.options.slidesToShow?(d=b.$slider.find("."+b.options.classPrefix+"slide"),g(d)):b.currentSlide>=b.slideCount-b.options.slidesToShow?(d=b.$slider.find("."+b.options.classPrefix+"cloned").slice(0,b.options.slidesToShow),g(d)):0===b.currentSlide&&(d=b.$slider.find("."+b.options.classPrefix+"cloned").slice(b.options.slidesToShow*-1),g(d))},b.prototype.loadSlider=function(){var a=this;a.setPosition(),a.$slideTrack.css({opacity:1}),a.$slider.removeClass(a.options.classPrefix+"loading"),a.initUI(),"progressive"===a.options.lazyLoad&&a.progressiveLazyLoad()},b.prototype.next=b.prototype.slickNext=function(){var a=this;a.changeSlide({data:{message:"next"}})},b.prototype.orientationChange=function(){var a=this;a.checkResponsive(),a.setPosition()},b.prototype.pause=b.prototype.slickPause=function(){var a=this;a.autoPlayClear(),a.paused=!0},b.prototype.play=b.prototype.slickPlay=function(){var a=this;a.autoPlay(),a.options.autoplay=!0,a.paused=!1,a.focussed=!1,a.interrupted=!1},b.prototype.postSlide=function(a){var b=this;b.unslicked||(b.$slider.trigger("afterChange",[b,a]),b.animating=!1,b.setPosition(),b.swipeLeft=null,b.options.autoplay&&b.autoPlay(),b.options.accessibility===!0&&b.initADA())},b.prototype.prev=b.prototype.slickPrev=function(){var a=this;a.changeSlide({data:{message:"previous"}})},b.prototype.preventDefault=function(a){a.preventDefault()},b.prototype.progressiveLazyLoad=function(b){b=b||1;var e,f,g,c=this,d=a("img[data-lazy]",c.$slider);d.length?(e=d.first(),f=e.attr("data-lazy"),g=document.createElement("img"),g.onload=function(){e.attr("src",f).removeAttr("data-lazy").removeClass(c.options.classPrefix+"loading"),c.options.adaptiveHeight===!0&&c.setPosition(),c.$slider.trigger("lazyLoaded",[c,e,f]),c.progressiveLazyLoad()},g.onerror=function(){b<3?setTimeout(function(){c.progressiveLazyLoad(b+1)},500):(e.removeAttr("data-lazy").removeClass(c.options.classPrefix+"loading").addClass(c.options.classPrefix+"lazyload-error"),c.$slider.trigger("lazyLoadError",[c,e,f]),c.progressiveLazyLoad())},g.src=f):c.$slider.trigger("allImagesLoaded",[c])},b.prototype.refresh=function(b){var d,e,c=this;e=c.slideCount-c.options.slidesToShow,!c.options.infinite&&c.currentSlide>e&&(c.currentSlide=e),c.slideCount<=c.options.slidesToShow&&(c.currentSlide=0),d=c.currentSlide,c.destroy(!0),a.extend(c,c.initials,{currentSlide:d}),c.init(),b||c.changeSlide({data:{message:"index",index:d}},!1)},b.prototype.registerBreakpoints=function(){var c,d,e,b=this,f=b.options.responsive||null;if("array"===a.type(f)&&f.length){b.respondTo=b.options.respondTo||"window";for(c in f)if(e=b.breakpoints.length-1,d=f[c].breakpoint,f.hasOwnProperty(c)){for(;e>=0;)b.breakpoints[e]&&b.breakpoints[e]===d&&b.breakpoints.splice(e,1),e--;b.breakpoints.push(d),b.breakpointSettings[d]=f[c].settings}b.breakpoints.sort(function(a,c){return b.options.mobileFirst?a-c:c-a})}},b.prototype.reinit=function(){var b=this;if(b.$slides=b.$slideTrack.children(b.options.slide).addClass(b.options.classPrefix+"slide"),b.options.slideMargin){var c=b.options.rtl===!0?"right":"left";b.$slides.css("margin-"+c,b.options.slideMargin)}b.slideCount=b.$slides.length,b.currentSlide>=b.slideCount&&0!==b.currentSlide&&(b.currentSlide=b.currentSlide-b.options.slidesToScroll),b.slideCount<=b.options.slidesToShow&&(b.currentSlide=0),b.registerBreakpoints(),b.setProps(),b.setupInfinite(),b.buildArrows(),b.updateArrows(),b.initArrowEvents(),b.buildDots(),b.updateDots(),b.initDotEvents(),b.cleanUpSlideEvents(),b.initSlideEvents(),b.checkResponsive(!1,!0),b.options.focusOnSelect===!0&&a(b.$slideTrack).children().on("click.slick",b.selectHandler),b.setSlideClasses("number"==typeof b.currentSlide?b.currentSlide:0),b.setPosition(),b.focusHandler(),b.paused=!b.options.autoplay,b.autoPlay(),b.$slider.trigger("reInit",[b])},b.prototype.resize=function(){var b=this;a(window).width()!==b.windowWidth&&(clearTimeout(b.windowDelay),b.windowDelay=window.setTimeout(function(){b.windowWidth=a(window).width(),b.checkResponsive(),b.unslicked||b.setPosition()},50))},b.prototype.removeSlide=b.prototype.slickRemove=function(a,b,c){var d=this;return"boolean"==typeof a?(b=a,a=b===!0?0:d.slideCount-1):a=b===!0?--a:a,!(d.slideCount<1||a<0||a>d.slideCount-1)&&(d.unload(),c===!0?d.$slideTrack.children().remove():d.$slideTrack.children(this.options.slide).eq(a).remove(),d.$slides=d.$slideTrack.children(this.options.slide),d.$slideTrack.children(this.options.slide).detach(),d.$slideTrack.append(d.$slides),d.$slidesCache=d.$slides,void d.reinit())},b.prototype.setCSS=function(a){var d,e,b=this,c={};b.options.rtl===!0&&(a=-a);var f=b.options.rtl===!0?1:-1;d="left"==b.positionProp?Math.ceil(a+b.options.slideMargin*f)+"px":"0px",e="top"==b.positionProp?Math.ceil(a)+"px":"0px",c[b.positionProp]=a,b.transformsEnabled===!1?b.$slideTrack.css(c):(c={},b.cssTransitions===!1?(c[b.animType]="translate("+d+", "+e+")",b.$slideTrack.css(c)):(c[b.animType]="translate3d("+d+", "+e+", 0px)",b.$slideTrack.css(c)))},b.prototype.setDimensions=function(){var a=this;a.options.vertical===!1?a.options.centerMode===!0&&a.$list.css({padding:"0px "+a.options.centerPadding}):(a.$list.height(a.$slides.first().outerHeight(!0)*a.options.slidesToShow),a.options.centerMode===!0&&a.$list.css({padding:a.options.centerPadding+" 0px"})),a.listWidth=a.$list.width(),a.listHeight=a.$list.height(),a.options.vertical===!1&&a.options.variableWidth===!1?(a.slideWidth=Math.ceil(a.listWidth/a.options.slidesToShow),a.slideWidth+=a.options.slideMargin,a.$slideTrack.width(Math.ceil(a.slideWidth*a.$slideTrack.children("."+a.options.classPrefix+"slide").length))):a.options.variableWidth===!0?a.$slideTrack.width(5e3*a.slideCount):(a.slideWidth=Math.ceil(a.listWidth),a.$slideTrack.height(Math.ceil(a.$slides.first().outerHeight(!0)*a.$slideTrack.children("."+a.options.classPrefix+"slide").length)));var b=a.$slides.first().outerWidth(!0)-a.$slides.first().width();a.options.variableWidth===!1&&a.$slideTrack.children("."+a.options.classPrefix+"slide").width(a.slideWidth-b)},b.prototype.setFade=function(){var c,b=this;b.$slides.each(function(d,e){c=b.slideWidth*d*-1,b.options.rtl===!0?a(e).css({position:"relative",right:c,top:0,zIndex:b.options.zIndex-2,opacity:0}):a(e).css({position:"relative",left:c,top:0,zIndex:b.options.zIndex-2,opacity:0})}),b.$slides.eq(b.currentSlide).css({zIndex:b.options.zIndex-1,opacity:1})},b.prototype.setHeight=function(){var a=this;if(1===a.options.slidesToShow&&a.options.adaptiveHeight===!0&&a.options.vertical===!1){var b=a.$slides.eq(a.currentSlide).outerHeight(!0);a.$list.css("height",b)}},b.prototype.setOption=b.prototype.slickSetOption=function(){var c,d,e,f,h,b=this,g=!1;if("object"===a.type(arguments[0])?(e=arguments[0],g=arguments[1],h="multiple"):"string"===a.type(arguments[0])&&(e=arguments[0],f=arguments[1],g=arguments[2],"responsive"===arguments[0]&&"array"===a.type(arguments[1])?h="responsive":"undefined"!=typeof arguments[1]&&(h="single")),"single"===h)b.options[e]=f;else if("multiple"===h)a.each(e,function(a,c){b.options[a]=c});else if("responsive"===h)for(d in f)if("array"!==a.type(b.options.responsive))b.options.responsive=[f[d]];else{for(c=b.options.responsive.length-1;c>=0;)b.options.responsive[c].breakpoint===f[d].breakpoint&&b.options.responsive.splice(c,1),c--;b.options.responsive.push(f[d])}g&&(b.unload(),b.reinit())},b.prototype.setPosition=function(){var a=this;a.setDimensions(),a.setHeight(),a.options.fade===!1?a.setCSS(a.getLeft(a.currentSlide)):a.setFade(),a.$slider.trigger("setPosition",[a])},b.prototype.setProps=function(){var a=this,b=document.body.style;a.positionProp=a.options.vertical===!0?"top":"left","top"===a.positionProp?a.$slider.addClass(a.options.classPrefix+"vertical"):a.$slider.removeClass(a.options.classPrefix+"vertical"),
void 0===b.WebkitTransition&&void 0===b.MozTransition&&void 0===b.msTransition||a.options.useCSS===!0&&(a.cssTransitions=!0),a.options.fade&&("number"==typeof a.options.zIndex?a.options.zIndex<3&&(a.options.zIndex=3):a.options.zIndex=a.defaults.zIndex),void 0!==b.OTransform&&(a.animType="OTransform",a.transformType="-o-transform",a.transitionType="OTransition",void 0===b.perspectiveProperty&&void 0===b.webkitPerspective&&(a.animType=!1)),void 0!==b.MozTransform&&(a.animType="MozTransform",a.transformType="-moz-transform",a.transitionType="MozTransition",void 0===b.perspectiveProperty&&void 0===b.MozPerspective&&(a.animType=!1)),void 0!==b.webkitTransform&&(a.animType="webkitTransform",a.transformType="-webkit-transform",a.transitionType="webkitTransition",void 0===b.perspectiveProperty&&void 0===b.webkitPerspective&&(a.animType=!1)),void 0!==b.msTransform&&(a.animType="msTransform",a.transformType="-ms-transform",a.transitionType="msTransition",void 0===b.msTransform&&(a.animType=!1)),void 0!==b.transform&&a.animType!==!1&&(a.animType="transform",a.transformType="transform",a.transitionType="transition"),a.transformsEnabled=a.options.useTransform&&null!==a.animType&&a.animType!==!1},b.prototype.setSlideClasses=function(a){var c,d,e,f,b=this;d=b.$slider.find("."+b.options.classPrefix+"slide").removeClass(b.options.classPrefix+"active "+b.options.classPrefix+"center "+b.options.classPrefix+"current").attr("aria-hidden","true"),b.$slides.eq(a).addClass(b.options.classPrefix+"current"),b.options.centerMode===!0?(c=Math.floor(b.options.slidesToShow/2),b.options.infinite===!0&&(a>=c&&a<=b.slideCount-1-c?b.$slides.slice(a-c,a+c+1).addClass(b.options.classPrefix+"active").attr("aria-hidden","false"):(e=b.options.slidesToShow+a,d.slice(e-c+1,e+c+2).addClass(b.options.classPrefix+"active").attr("aria-hidden","false")),0===a?d.eq(d.length-1-b.options.slidesToShow).addClass(b.options.classPrefix+"center"):a===b.slideCount-1&&d.eq(b.options.slidesToShow).addClass(b.options.classPrefix+"center")),b.$slides.eq(a).addClass(b.options.classPrefix+"center")):a>=0&&a<=b.slideCount-b.options.slidesToShow?b.$slides.slice(a,a+b.options.slidesToShow).addClass(b.options.classPrefix+"active").attr("aria-hidden","false"):d.length<=b.options.slidesToShow?d.addClass(b.options.classPrefix+"active").attr("aria-hidden","false"):(f=b.slideCount%b.options.slidesToShow,e=b.options.infinite===!0?b.options.slidesToShow+a:a,b.options.slidesToShow==b.options.slidesToScroll&&b.slideCount-a<b.options.slidesToShow?d.slice(e-(b.options.slidesToShow-f),e+f).addClass(b.options.classPrefix+"active").attr("aria-hidden","false"):d.slice(e,e+b.options.slidesToShow).addClass(b.options.classPrefix+"active").attr("aria-hidden","false")),"ondemand"===b.options.lazyLoad&&b.lazyLoad()},b.prototype.setupInfinite=function(){var c,d,e,b=this;if(b.options.fade===!0&&(b.options.centerMode=!1),b.options.infinite===!0&&b.options.fade===!1&&(d=null,b.slideCount>b.options.slidesToShow)){for(e=b.options.centerMode===!0?b.options.slidesToShow+1:b.options.slidesToShow,c=b.slideCount;c>b.slideCount-e;c-=1)d=c-1,a(b.$slides[d]).clone(!0).attr("id","").attr("data-"+b.options.classPrefix+"index",d-b.slideCount).prependTo(b.$slideTrack).addClass(b.options.classPrefix+"cloned");for(c=0;c<e;c+=1)d=c,a(b.$slides[d]).clone(!0).attr("id","").attr("data-"+b.options.classPrefix+"index",d+b.slideCount).appendTo(b.$slideTrack).addClass(b.options.classPrefix+"cloned");b.$slideTrack.find("."+b.options.classPrefix+"cloned").find("[id]").each(function(){a(this).attr("id","")})}},b.prototype.interrupt=function(a){var b=this;a||b.autoPlay(),b.interrupted=a},b.prototype.selectHandler=function(b){var c=this,d=a(b.target).is("."+c.options.classPrefix+"slide")?a(b.target):a(b.target).parents("."+c.options.classPrefix+"slide"),e=parseInt(d.attr("data-"+c.options.classPrefix+"index"));return e||(e=0),c.slideCount<=c.options.slidesToShow?(c.setSlideClasses(e),void c.asNavFor(e)):void c.slideHandler(e)},b.prototype.slideHandler=function(a,b,c){var d,e,f,g,j,h=null,i=this;if(b=b||!1,(i.animating!==!0||i.options.waitForAnimate!==!0)&&!(i.options.fade===!0&&i.currentSlide===a||i.slideCount<=i.options.slidesToShow))return b===!1&&i.asNavFor(a),d=a,h=i.getLeft(d),g=i.getLeft(i.currentSlide),i.currentLeft=null===i.swipeLeft?g:i.swipeLeft,i.options.infinite===!1&&i.options.centerMode===!1&&(a<0||a>i.getDotCount()*i.options.slidesToScroll)?void(i.options.fade===!1&&(d=i.currentSlide,c!==!0?i.animateSlide(g,function(){i.postSlide(d)}):i.postSlide(d))):i.options.infinite===!1&&i.options.centerMode===!0&&(a<0||a>i.slideCount-i.options.slidesToScroll)?void(i.options.fade===!1&&(d=i.currentSlide,c!==!0?i.animateSlide(g,function(){i.postSlide(d)}):i.postSlide(d))):(i.options.autoplay&&clearInterval(i.autoPlayTimer),e=d<0?i.slideCount%i.options.slidesToScroll!==0?i.slideCount-i.slideCount%i.options.slidesToScroll:i.slideCount+d:d>=i.slideCount?i.slideCount%i.options.slidesToScroll!==0?0:d-i.slideCount:d,i.animating=!0,i.$slider.trigger("beforeChange",[i,i.currentSlide,e]),f=i.currentSlide,i.currentSlide=e,i.setSlideClasses(i.currentSlide),i.options.asNavFor&&(j=i.getNavTarget(),j=j.slick("getSlick"),j.slideCount<=j.options.slidesToShow&&j.setSlideClasses(i.currentSlide)),i.updateDots(),i.updateArrows(),i.options.fade===!0?(c!==!0?(i.fadeSlideOut(f),i.fadeSlide(e,function(){i.postSlide(e)})):i.postSlide(e),void i.animateHeight()):void(c!==!0?i.animateSlide(h,function(){i.postSlide(e)}):i.postSlide(e)))},b.prototype.startLoad=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.hide(),a.$nextArrow.hide()),a.options.dots===!0&&a.slideCount>a.options.slidesToShow&&a.$dots.hide(),a.$slider.addClass(a.options.classPrefix+"loading")},b.prototype.swipeDirection=function(){var a,b,c,d,e=this;return a=e.touchObject.startX-e.touchObject.curX,b=e.touchObject.startY-e.touchObject.curY,c=Math.atan2(b,a),d=Math.round(180*c/Math.PI),d<0&&(d=360-Math.abs(d)),d<=45&&d>=0?e.options.rtl===!1?"left":"right":d<=360&&d>=315?e.options.rtl===!1?"left":"right":d>=135&&d<=225?e.options.rtl===!1?"right":"left":e.options.verticalSwiping===!0?d>=35&&d<=135?"down":"up":"vertical"},b.prototype.swipeEnd=function(a){var c,d,b=this;if(b.dragging=!1,b.interrupted=!1,b.shouldClick=!(b.touchObject.swipeLength>10),void 0===b.touchObject.curX)return!1;if(b.touchObject.edgeHit===!0&&b.$slider.trigger("edge",[b,b.swipeDirection()]),b.touchObject.swipeLength>=b.touchObject.minSwipe){switch(d=b.swipeDirection()){case"left":case"down":c=b.options.swipeToSlide?b.checkNavigable(b.currentSlide+b.getSlideCount()):b.currentSlide+b.getSlideCount(),b.currentDirection=0;break;case"right":case"up":c=b.options.swipeToSlide?b.checkNavigable(b.currentSlide-b.getSlideCount()):b.currentSlide-b.getSlideCount(),b.currentDirection=1}"vertical"!=d&&(b.slideHandler(c),b.touchObject={},b.$slider.trigger("swipe",[b,d]))}else b.touchObject.startX!==b.touchObject.curX&&(b.slideHandler(b.currentSlide),b.touchObject={})},b.prototype.swipeHandler=function(a){var b=this;if(!(b.options.swipe===!1||"ontouchend"in document&&b.options.swipe===!1||b.options.draggable===!1&&a.type.indexOf("mouse")!==-1))switch(b.touchObject.fingerCount=a.originalEvent&&void 0!==a.originalEvent.touches?a.originalEvent.touches.length:1,b.touchObject.minSwipe=b.listWidth/b.options.touchThreshold,b.options.verticalSwiping===!0&&(b.touchObject.minSwipe=b.listHeight/b.options.touchThreshold),a.data.action){case"start":b.swipeStart(a);break;case"move":b.swipeMove(a);break;case"end":b.swipeEnd(a)}},b.prototype.swipeMove=function(a){var d,e,f,g,h,b=this;return h=void 0!==a.originalEvent?a.originalEvent.touches:null,!(!b.dragging||h&&1!==h.length)&&(d=b.getLeft(b.currentSlide),b.touchObject.curX=void 0!==h?h[0].pageX:a.clientX,b.touchObject.curY=void 0!==h?h[0].pageY:a.clientY,b.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(b.touchObject.curX-b.touchObject.startX,2))),b.options.verticalSwiping===!0&&(b.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(b.touchObject.curY-b.touchObject.startY,2)))),e=b.swipeDirection(),"vertical"!==e?(void 0!==a.originalEvent&&b.touchObject.swipeLength>4&&a.preventDefault(),g=(b.options.rtl===!1?1:-1)*(b.touchObject.curX>b.touchObject.startX?1:-1),b.options.verticalSwiping===!0&&(g=b.touchObject.curY>b.touchObject.startY?1:-1),f=b.touchObject.swipeLength,b.touchObject.edgeHit=!1,b.options.infinite===!1&&(0===b.currentSlide&&"right"===e||b.currentSlide>=b.getDotCount()&&"left"===e)&&(f=b.touchObject.swipeLength*b.options.edgeFriction,b.touchObject.edgeHit=!0),b.options.vertical===!1?b.swipeLeft=d+f*g:b.swipeLeft=d+f*(b.$list.height()/b.listWidth)*g,b.options.verticalSwiping===!0&&(b.swipeLeft=d+f*g),b.options.fade!==!0&&b.options.touchMove!==!1&&(b.animating===!0?(b.swipeLeft=null,!1):void b.setCSS(b.swipeLeft))):void 0)},b.prototype.swipeStart=function(a){var c,b=this;return b.interrupted=!0,1!==b.touchObject.fingerCount||b.slideCount<=b.options.slidesToShow?(b.touchObject={},!1):(void 0!==a.originalEvent&&void 0!==a.originalEvent.touches&&(c=a.originalEvent.touches[0]),b.touchObject.startX=b.touchObject.curX=void 0!==c?c.pageX:a.clientX,b.touchObject.startY=b.touchObject.curY=void 0!==c?c.pageY:a.clientY,void(b.dragging=!0))},b.prototype.unfilterSlides=b.prototype.slickUnfilter=function(){var a=this;null!==a.$slidesCache&&(a.unload(),a.$slideTrack.children(this.options.slide).detach(),a.$slidesCache.appendTo(a.$slideTrack),a.reinit())},b.prototype.unload=function(){var b=this;a("."+b.options.classPrefix+"cloned",b.$slider).remove(),b.$dots&&b.$dots.remove(),b.$prevArrow&&b.htmlExpr.test(b.options.prevArrow)&&b.$prevArrow.remove(),b.$nextArrow&&b.htmlExpr.test(b.options.nextArrow)&&b.$nextArrow.remove(),b.$slides.removeClass(b.options.classPrefix+"slide "+b.options.classPrefix+"active "+b.options.classPrefix+"visible "+b.options.classPrefix+"current").attr("aria-hidden","true").css("width","")},b.prototype.unslick=function(a){var b=this;b.$slider.trigger("unslick",[b,a]),b.destroy()},b.prototype.updateArrows=function(){var b,a=this;b=Math.floor(a.options.slidesToShow/2),a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&!a.options.infinite&&(a.$prevArrow.removeClass(a.options.classPrefix+"disabled").attr("aria-disabled","false"),a.$nextArrow.removeClass(a.options.classPrefix+"disabled").attr("aria-disabled","false"),0===a.currentSlide?(a.$prevArrow.addClass(a.options.classPrefix+"disabled").attr("aria-disabled","true"),a.$nextArrow.removeClass(a.options.classPrefix+"disabled").attr("aria-disabled","false")):a.currentSlide>=a.slideCount-a.options.slidesToShow&&a.options.centerMode===!1?(a.$nextArrow.addClass(a.options.classPrefix+"disabled").attr("aria-disabled","true"),a.$prevArrow.removeClass(a.options.classPrefix+"disabled").attr("aria-disabled","false")):a.currentSlide>=a.slideCount-1&&a.options.centerMode===!0&&(a.$nextArrow.addClass(a.options.classPrefix+"disabled").attr("aria-disabled","true"),a.$prevArrow.removeClass(a.options.classPrefix+"disabled").attr("aria-disabled","false")))},b.prototype.updateDots=function(){var a=this;null!==a.$dots&&(a.$dots.find("li").removeClass(a.options.classPrefix+"active").attr("aria-hidden","true"),a.$dots.find("li").eq(Math.floor(a.currentSlide/a.options.slidesToScroll)).addClass(a.options.classPrefix+"active").attr("aria-hidden","false"))},b.prototype.visibility=function(){var a=this;a.options.autoplay&&(document[a.hidden]?a.interrupted=!0:a.interrupted=!1)},a.fn.slick=function(){var f,g,a=this,c=arguments[0],d=Array.prototype.slice.call(arguments,1),e=a.length;for(f=0;f<e;f++)if("object"==typeof c||"undefined"==typeof c?a[f].slick=new b(a[f],c):g=a[f].slick[c].apply(a[f].slick,d),"undefined"!=typeof g)return g;return a}});libs/better-framework/assets/js/tinymce-addon.min.js000064400000011770151214002540016546 0ustar00/***
 *  BetterStudio Themes Core.
 *
 *  ______  _____   _____ _                           _____
 *  | ___ \/  ___| |_   _| |                         /  __ \
 *  | |_/ /\ `--.    | | | |__   ___ _ __ ___   ___  | /  \/ ___  _ __ ___
 *  | ___ \ `--. \   | | | '_ \ / _ \ '_ ` _ \ / _ \ | |    / _ \| '__/ _ \
 *  | |_/ //\__/ /   | | | | | |  __/ | | | | |  __/ | \__/\ (_) | | |  __/
 *  \____/ \____/    \_/ |_| |_|\___|_| |_| |_|\___|  \____/\___/|_|  \___|
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */
var BetterStudio_TinyMCE_View={settings:{},fetchShortcodes:[],shortcodeCounter:0,fetchAllQueue:0,repeaterPrefix:"bf-metabox-option",init:function(t){var e=this;BF_TinyMCE_View.shortcodes&&BF_TinyMCE_View.shortcodes.forEach(function(t){e.registerView(t)}),this.$=t},initEditModal:function(t){function e(){s.children(".group").hide()}function o(t){t.find(":input:first").trigger("force-change")}var n=this,s=n.$(".tinymce-addon-fields",t);s.length&&(e(),s.children(".group:first").show(),n.$(".tabs-wrapper li:first").addClass("active-tab"),n.$(".bf-tab-item-a",s).on("click",function(){var t=n.$(this).closest("li"),i=t.data("go"),r="bf-tmv-"+i;t.addClass("active-tab"),t.siblings("li").removeClass("active-tab");var c=n.$("#"+r,s);e(),c.fadeIn(500),o(c)}))},setSettings:function(t){t&&t.shortcode&&(this.settings[t.shortcode]=t.settings)},getSettings:function(t){return this.settings[t]},registerView:function(t){var e=this;t=_.extend({},{extend:{}},t),t.settings&&e.setSettings(t),wp.mce.views.register(t.shortcode,_.extend({},e.viewsBaseClass(t),t.extend))},doShortcode:function(t,e){var o=this;clearTimeout(o.fetchAllQueue),o.fetchAllQueue=setTimeout(function(){o.fetchAllShortcodes.call(o)}),o.fetchShortcodes.push({query:{shortcode:t,id:o.shortcodeCounter},id:o.shortcodeCounter,view:e}),o.shortcodeCounter++},fetchAllShortcodes:function(){var t,e=this,o=_.pluck(e.fetchShortcodes,"query"),n=parseInt(BF_TinyMCE_View.doshortcode_steps||5),s=_.groupBy(o,function(t,e){return Math.floor(e/n)}),i=Better_Framework._length(s),r=0;for(var c in s)t=s[c],wp.ajax.post("bf_ajax",{reqID:"fetch-mce-view-shortcode",nonce:better_framework_loc.nonce,shortcodes:t,post_id:wp.media.view.settings.post.id}).done(function(t){_.each(t,function(t,o){var n=_.findWhere(e.fetchShortcodes,{id:parseInt(o)});n&&n.view&&("no-items"===t.type?n.view.setError("["+n.view.shortcode.tag+"]<br/>"+t.message,"no-alt"):n.view.render(t))})}).always(function(){++r===i&&(e.fetchShortcodes=[],e.shortcodeCounter=0)})},viewsBaseClass:function(){var t=this;return wp.mce.bsShortcodes?wp.mce.bsShortcodes:(wp.mce.bsShortcodes={args:{},initialize:function(){var e=this;t.doShortcode(e.shortcode.string(),e)},shortcode_data:{},edit:function(e,o){var n=this,s=wp.shortcode.next(n.shortcode.tag,e),i=s.shortcode.attrs.named;i.innercontent=s.shortcode.content;var r={custom_event:{label:BS_Shortcode_loc.save,type:"primary",clicked:function(){var e=this,s={};t.$(".bs-modal-body",this.$modal).clone();t.$(".mce-field",this.$modal).each(function(){if("radio"!==this.type||this.checked){var t=this.name.match(/\[(.*?)\]/g);if(t){var e,o=this.name.match(/^(.*?)(?=\[)/)[1];"undefined"==typeof s[o]&&(s[o]={}),e=s[o];for(var n=0;n<t.length;n++)o=t[n].substr(0,t[n].length-1).substr(1),"undefined"==typeof e[o]&&(e[o]={}),e=e[o];e.__VALUE__=this.value}else s[this.name]=this.value}}).promise().done(function(){var i=t.getSettings(n.shortcode.tag),r="";if(i.sub_shortcodes){var c,a,d;for(c in i.sub_shortcodes)s[c]&&(a=i.sub_shortcodes[c],_.each(s[c],function(t){t=_.mapObject(t,function(t){return"object"==typeof t&&"__VALUE__"in t?t.__VALUE__:t}),d="string"==typeof i.extra.shortcode_content_fields[c]?i.extra.shortcode_content_fields[c]:"";var e="";d&&"undefined"!=typeof t[d]&&(e=t[d],delete t[d]),r+="\n	",r+=wp.shortcode.string({tag:a,content:e,attrs:t,type:"close"})}),delete s[c])}r&&(r+="\n"),o(wp.shortcode.string({tag:n.shortcode.tag,attrs:_.pick(s,_.identity),type:"open",content:r}),!1),e.close_modal("tinymce")})}},close_modal:{type:"secondary",action:"close",label:better_framework_loc.translation.reset_panel.button_no,focus:!0}},c=t.$.bs_modal({modalId:"es-modal",skin:"loading",content:{header:"Loading...",title:"Loading...",body:""},buttons:r,events:{before_append_html:function(){var t=155e3;this.$overlay.css("z-index",t),this.$modal.css("z-index",t+1)},after_append_html:function(){t.initEditModal(this.$modal)}}});wp.ajax.post("bf_ajax",{action:"bf_ajax",reqID:"fetch-mce-view-fields",nonce:better_framework_loc.nonce,shortcode:n.shortcode.tag,shortcode_content:s.shortcode.content,shortcode_values:i}).done(function(e){c.change_skin({skin:"skin-1",animations:{},content:{header:function(o){var s=t.getSettings(n.shortcode.tag),i=s.name||"";return e.settings&&(s.extra=e.settings,t.setSettings({settings:s,shortcode:n.shortcode.tag})),o.toString().replace("%shortcode%",i)}(BF_TinyMCE_View.l10n.modal.header),title:"",body:e.output},buttons:r})})}},wp.mce.bsShortcodes)}};jQuery(function(){BetterStudio_TinyMCE_View.init(jQuery)});libs/better-framework/assets/js/html5shiv.min.js000064400000005120151214002550015727 0ustar00
/**
 * @preserve HTML5 Shiv 3.7.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
 **/
!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.2",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b)}(this,document);libs/better-framework/assets/js/tests/gutenberg.test.js000064400000001755151214002550017336 0ustar00const bfGutenberg = require('../gutenberg');

describe("Test field generator", function () {

    it("Fire element callback", () => {

        const elementMock = jest.fn();

        let field = require('./fixtures/field1');

        bfGutenberg.buildSingleField(elementMock, field);

        expect(elementMock).toHaveBeenCalledTimes(1);

        expect(elementMock).toHaveBeenCalledWith(bfGutenberg.getComponent('TextControl'), field.args);
    });

    it("Should generate fields", () => {


        let fired = 0, logTrace = [];

        const elementMock = jest.fn(function (a, b, c) {

            let log = [a, b];

            if (c) {
                log.push(c);
            }

            logTrace.push(log);

            return ++fired;
        });

        bfGutenberg.buildFields(elementMock, require('./fixtures/field2'));

        expect(elementMock).toHaveBeenCalledTimes(8);

        let trace = require('./fixtures/field2.expect');

        expect(logTrace).toEqual(trace);
    });
});
libs/better-framework/assets/js/tests/fixtures/field2.expect.json000064400000001404151214002550021227 0ustar00[
  [
    "TextControl",
    {
      "type": "text",
      "label": "Field Title"
    }
  ],
  [
    "PanelBody",
    {
      "title": "Group title",
      "initialOpen": true
    },
    1
  ],
  [
    "TextControl",
    {
      "type": "text",
      "label": "Field2 Title"
    }
  ],
  [
    "PanelBody",
    {
      "title": "Group2 title",
      "initialOpen": false
    },
    3
  ],
  [
    "TextControl",
    {
      "type": "text",
      "label": "Field3 Title"
    }
  ],
  [
    "TextControl",
    {
      "type": "text",
      "label": "Field3_2 Title"
    }
  ],
  [
    "TextControl",
    {
      "type": "text",
      "label": "Field3_3 Title"
    }
  ],
  [
    "PanelBody",
    {
      "title": "Group3 title",
      "initialOpen": false
    },
    7
  ]
]libs/better-framework/assets/js/tests/fixtures/field1.json000064400000000157151214002550017743 0ustar00{
  "id": "title",
  "component": "TextControl",
  "args": {
    "type": "text",
    "label": "Tab Title"
  }
}libs/better-framework/assets/js/tests/fixtures/field2.json000064400000002440151214002550017741 0ustar00
[
  {
    "id": "the_id",
    "component": "PanelBody",
    "args": {
      "title": "Group title",
      "initialOpen": true
    },
    "children": [
      {
        "id": "text",
        "component": "TextControl",
        "args": {
          "type": "text",
          "label": "Field Title"
        }
      }
    ]
  },
  {
    "id": "the_id2",
    "component": "PanelBody",
    "args": {
      "title": "Group2 title",
      "initialOpen": false
    },
    "children": [
      {
        "id": "text2",
        "component": "TextControl",
        "args": {
          "type": "text",
          "label": "Field2 Title"
        }
      }
    ]
  },
  {
    "id": "the_id3",
    "component": "PanelBody",
    "args": {
      "title": "Group3 title",
      "initialOpen": false
    },
    "children": [
      {
        "id": "text3",
        "component": "TextControl",
        "args": {
          "type": "text",
          "label": "Field3 Title"
        }
      },
      {
        "id": "text3_2",
        "component": "TextControl",
        "args": {
          "type": "text",
          "label": "Field3_2 Title"
        }
      },
      {
        "id": "text3_3",
        "component": "TextControl",
        "args": {
          "type": "text",
          "label": "Field3_3 Title"
        }
      }
    ]
  }
]libs/better-framework/assets/js/widgets.js000064400000000147151214002550014674 0ustar00/**
 * BetterFramework Widgets & Shortcodes
 * Copyright 2014 BetterStudio
 * @license BetterStudio
 */libs/better-framework/assets/js/bs-modal.min.js000064400000030057151214002550015511 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */
!function(t){"use strict";var n=0,s=[],e=function(n){function s(){return!0}this.options=t.extend(!0,{template:"default",skin:"skin-1",initialZIndex:0,show:!0,content:{},close_button:!0,button_position:"right",animations:{delay:600,open:"bs-animate bs-fadeInDown",close:"bs-animate bs-fadeOutUp"},buttons:{},events:{before_click:s,clicked:s,handle_keyup:function(t,n,s){return s}},styles:{modal:"",container:""},modalId:"modal-"+Math.floor(999*Math.random()),modalClass:"",destroyHtml:!0,is_vertical_center:!0},n),this.$modal=!1,this.$overlay=!1,this.timerTimeouts=[],this.$document=!1,this.modalID=!1,this.visible=!1,this.init()};e.prototype={templates:{"default":'\n<div class="bs-modal-default"  {{#inline_style}} style="{{inline_style}}" {{/inline_style}}>\n    {{#close_button}}\n    <a href="#" class="bs-close-modal">\n        <i class="fa fa-times" aria-hidden="true"></i>\n    </a>\n    {{/close_button}}\n    <div class="bs-modal-header-wrapper bs-modal-clearfix">\n        <h2 class="bs-modal-header">\n            {{#icon}}\n            <i class="fa {{icon}}"></i>\n            {{/icon}}\n\n            {{header}}\n        </h2>\n    </div>\n\n    <div class="bs-modal-body">\n        {{{bs_body}}}\n    </div>\n\n    {{#bs_buttons}}\n    <div class="bs-modal-bottom bs-modal-buttons-{{btn_position}} bs-modal-clearfix">\n        {{{bs_buttons}}}\n    </div>\n    {{/bs_buttons}}\n</div>',single_image:'\n<div class="bs-modal-default" {{#inline_style}} style="{{inline_style}}" {{/inline_style}}>\n    {{#close_button}}\n    <a href="#" class="bs-close-modal">\n        <i class="fa fa-times" aria-hidden="true"></i>\n    </a>\n    {{/close_button}}\n    <div class="bs-modal-header-wrapper bs-modal-clearfix">\n        <h2 class="bs-modal-header">\n            {{#icon}}\n            <i class="fa {{icon}}"></i>\n            {{/icon}}\n\n            {{header}}\n        </h2>\n    </div>\n\n    <div class="bs-modal-body bf-clearfix">\n        \n        <div class="bs-modal-image bf-clearfix" {{#image_align}} style="float:{{image_align}}"{{/image_align}}>\n\n            <img src="{{image_src}}" {{#image_style}} style="{{image_style}}"{{/image_style}}/>\n            \n            {{#image_caption}}\n            <div class="bs-modal-image-caption">\n                {{image_caption}}\n            </div>\n            {{/image_caption}}\n        </div>\n        {{{bs_body}}}\n    </div>\n\n    {{#bs_buttons}}\n    <div class="bs-modal-bottom bs-modal-buttons-left bs-modal-clearfix">\n        {{{bs_buttons}}}\n        \n        {{#checkbox}}\n        <div class="bs-modal-checkbox">\n            <input type="checkbox" name="include_content" class="toggle-content" value="1" checked="checked"> <label class="checkbox-label">{{checkbox_label}}</label>\n        </div>\n        {{/checkbox}}\n    </div>\n    {{/bs_buttons}}\n</div>'},skins:{"skin-1":'<div class="bs-modal-description">\n   {{#title}} <h3 class="bs-modal-title">{{title}}</h3>\n   {{/title}} \n    {{{body}}}\n</div>',loading:' <div class="bs-modal-loading bs-modal-loading-1">\n    <img src="data:image/false;base64,R0lGODlhIAAIAPEAALy8vHh4eP///wAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hhPcHRpbWl6ZWQgd2l0aCBlemdpZi5jb20AIfkEBQsAAQAsAAAAACAACAAAAiGEb6GBuNyiWxK8Wq/UuHFPdaCSheLxTeSJmiPEWq4KNwUAIfkEBQsAAAAsAAAAAAgACAAAAgaMj6nL7V0AIfkEBQsAAgAsAAAAABQACAAAAhuEb6IS7Y3QYs/FM6u9IOvAdcsHcp4WnlU6fgUAIfkEBQsAAgAsDAAAABQACAAAAhuEb6IS7Y3QYs/FM6u9IOvAdcsHcp4WnlU6fgUAOw==" />\n\n     <div class="bs-modal-loading-heading">\n         <h4>{{loading_heading}}</h4>\n     </div>\n </div>\n',"loading-2":' <div class="bs-modal-loading">\n     <div class="la-line-scale-pulse-out-rapid la-2x">\n         <div></div>\n         <div></div>\n         <div></div>\n         <div></div>\n         <div></div>\n     </div>\n     \n     <div class="bs-modal-loading-heading">\n         <h4>{{loading_heading}}</h4>\n     </div>\n</div>\n',success:' <div class="bs-modal-success">\n     \n     <i class="fa fa-thumbs-o-up" aria-hidden="true"></i>\n     \n     <div class="bs-modal-bs-modal-success-heading">\n         <h4>{{success_heading}}</h4>\n     </div>\n</div>\n'},button_struct:'<a {{#href}}href="{{href}}"{{/href}} {{#btn_classes}}class="{{btn_classes}}"{{/btn_classes}} id="{{id}}">{{{label}}}</a>',debug:function(t){console.error(t)},get_html:function(n,s,e){if("undefined"==typeof this.templates[n])return this.debug("invalid template name"),!1;if("undefined"==typeof this.skins[s])return this.debug("invalid skin"),!1;Mustache.parse(this.templates[n]);Mustache.parse(this.skins[s]);var i=Mustache.render(this.skins[s],e),o={bs_body:i,bs_buttons:this.generate_buttons(),close_button:this.options.close_button,inline_style:this.options.styles.modal,btn_position:this.options.button_position};return this.handle_event("prepare_html",this,n,s,e),Mustache.render(this.templates[n],t.extend(e,o))},before_append_html:function(t){this.handle_event("before_append_html",this,t)},after_append_html:function(t){this.options.is_vertical_center&&this.make_vertical_center(),this.$modal.focus(),this.handle_event("after_append_html",this,t)},after_close_modal:function(){t(window).off("resize.bs-modal"),s.pop()},has_button:function(){return"object"==typeof this.options.buttons},append_html:function(){this.before_append_html("modal");var t=this.get_html(this.options.template,this.options.skin,this.options.content);return"string"!=typeof t?t:(this.$modal.html(t),this.after_append_html("modal"),!0)},generate_buttons:function(){if(!this.has_button())return"";Mustache.parse(this.button_struct);var t="";for(var n in this.options.buttons)t+="\n",t+=Mustache.render(this.button_struct,this.get_button_replacement_object(n));return t},get_button_replacement_object:function(n){if("object"!=typeof this.options.buttons[n])return this.debug("invalid button id"),{};var s=t.extend({focus:!1},this.options.buttons[n]);return delete s.clicked,s.id=n,"string"!=typeof s.btn_classes&&(s.btn_classes=""),-1!==t.inArray(s.type,["primary","secondary"])&&(s.btn_classes+=" bs-modal-btn-"+s.type),s.focus&&(s.btn_classes+=" bs-modal-btn-focus"),s},close_modal:function(t){this.visible=!1;var n=this,t=t||"callback";n.handle_event("modal_close",this,t);for(var s=0;s<this.timerTimeouts.length;s++)clearTimeout(this.timerTimeouts[s]);n.$modal.removeClass(this.options.animations.open).addClass(this.options.animations.close).delay(this.options.animations.delay).queue(function(t){n.$modal.hide().removeClass(n.options.animations.close),n.options.destroyHtml?n.$modal.remove():n.$modal.clearQueue(),t()}),n.$overlay.fadeOut(this.options.animations.delay,function(){n.options.destroyHtml&&n.find().remove(),n.$document.removeClass("modal-open").removeClass("modal-open-vc"),n.keyup_unbind(),n.handle_event("modal_closed",this,t)}),n.after_close_modal()},keyup_unbind:function(){this.options.destroyHtml&&this.$document.off("keyup.bs-modal-"+this.getModalID())},handle_event:function(t,n){var s=Array.prototype.slice.call(arguments,2);return"function"==typeof this.options.events[t]?this.options.events[t].apply(this,[n,this.options].concat(s)):void 0},handle_timer:function(t){var n=this;this.timerTimeouts.push(setTimeout(function(){t.callback.call(n,n.option)},t.delay))},change_skin:function(s,e){e="boolean"==typeof e?e:!0;var i=t.extend(e,{template:this.options.template,skin:this.options.skin,content:this.options.content,animations:{open:!1,body:!1,delay:20},buttons:{},styles:{}},s);if(this.options.buttons=i.buttons,i.styles.container){var o={inline_style:i.styles.container},a=Mustache.render('<div class="bs-modal" {{#inline_style}} style="{{inline_style}}" {{/inline_style}}></div>\n',o);this.$modal[0].outerHTML=a,this.$modal=this.find(".bs-modal").css("z-index",n+1).show(),this.afterWrapperHtmlGenerated()}var l=this.get_html(i.template,i.skin,i.content);return"string"!=typeof l?l:(this.$modal.html(l).removeClass(this.options.animations.open).delay(20).queue(function(n){i.animations.open&&t(this).addClass(i.animations.open),n()}).removeClass(function(t,n){return(n.match(/(^|\s)skin-\S+/g)||[]).join(" ")}).addClass("skin-"+i.skin).find(".bs-modal-body").addClass(i.animations.body),"object"==typeof i.timer&&this.handle_timer(i.timer),this.after_append_html("change_skin"),void this.handle_event("modal_loaded",this))},make_vertical_center:function(){var n=this;t(window).on("resize.bs-modal",function(){if(!n.isModalLast())return!1;var t=n.$modal.innerHeight(),s=window.innerHeight;if(s>t)var e=Math.ceil((s-t)/2);else var e=35;n.$modal.css("top",e)}).trigger("resize.bs-modal")},getModalID:function(){return this.modalID},setModalID:function(t){this.modalID=t},setActiveModalId:function(t){s.push(t)},getActiveModalId:function(){return s.length?s[s.length-1]:0},isModalLast:function(){return this.getActiveModalId()===this.getModalID()},find:function(n){var s=this.$document.find("#"+this.getModalID());return n?t(n,s):s},_fixModalZindex:function(){},show:function(){var t=this;t.$document.find(".vc_ui-panel.vc_active .vc_ui-panel-window-inner").length&&t.$document.addClass("modal-alongside-vc-panel"),this.$overlay.fadeIn(this.options.animations.open,function(){t.$document.addClass("modal-open")}),this.$modal.addClass(t.options.animations.open).addClass("skin-"+t.options.skin).show().delay(t.options.animations.delay).queue(function(n){"object"==typeof t.options.timer&&t.handle_timer(t.options.timer),n()}),this.setActiveModalId(this.getModalID()),this.visible=!0,this.handle_event("modal_show",this)},init:function(){this.$document=t(document.body);var s=this;this.setModalID(this.options.modalId),this.setActiveModalId(this.getModalID());var e=0===this.find().length;if(e){var i={inline_style:this.options.styles.container,modal_id:this.getModalID(),modal_class:this.options.modalClass};this.$document.append(Mustache.render('<div id="{{modal_id}}"{{#modal_class}} class="{{modal_class}}"{{/modal_class}}>\n    <div class="bs-modal-overlay"></div>\n        <div class="bs-modal" {{#inline_style}} style="{{inline_style}}" {{/inline_style}}>\n    </div>\n</div>',i))}this.$modal=this.find(".bs-modal"),this.$overlay=this.find(".bs-modal-overlay"),n?(n=Math.max(n,this.options.initialZIndex),n++,this.$overlay.css("z-index",n),this.$modal.css("z-index",n+1)):this.options.initialZIndex?(this.$overlay.css("z-index",this.options.initialZIndex),this.$modal.css("z-index",this.options.initialZIndex+1),n=this.options.initialZIndex):n=parseInt(this.$modal.css("z-index")),e&&s.afterWrapperHtmlGenerated(),this.options.close_button&&this.$document.on("keyup.bs-modal-"+this.getModalID(),function(n){if(!s.handle_event("handle_keyup",n,s.isModalLast()))return!1;if("TEXTAREA"===n.target.tagName)return!1;if(s.options.close_button&&27===n.which)s.close_modal("esc");else if(13===n.which){if(s.has_button()){var e=s.$modal.find(".bs-modal-bottom"),i=t(".bs-modal-btn-focus",e);i.length||(i=t(".bs-modal-btn-primary",e)),i.trigger("click")}s.keyup_unbind()}}),this.options.show&&s.show(),e&&s.append_html(),this.handle_event("modal_loaded",this)},afterWrapperHtmlGenerated:function(){var n=this;this.$modal.on("click","a",function(s){if(n.handle_event("before_click",this)){var e=t(this),i=e.attr("id");if(e.hasClass("bs-close-modal"))s.preventDefault(),n.close_modal("btn");else if(i&&"object"==typeof n.options.buttons[i]){var o=n.options.buttons[i];switch(o.action){case"close":n.close_modal("link")}"function"==typeof o.clicked&&o.clicked.call(n)}n.handle_event("clicked",this)}})}},t.bs_modal=function(t){return new e(t)},t.bs_modal_template=function(t,n){return n?void(e.prototype.templates[t]=n):e.prototype.templates[t]}}(jQuery);libs/better-framework/assets/js/slick.js000064400000252316151214002550014342 0ustar00/*
     _ _      _       _
 ___| (_) ___| | __  (_)___
/ __| | |/ __| |/ /  | / __|
\__ \ | | (__|   < _ | \__ \
|___/_|_|\___|_|\_(_)/ |___/
                   |__/

 Version: 1.6.0
  Author: Ken Wheeler
 Website: http://kenwheeler.github.io
    Docs: http://kenwheeler.github.io/slick
    Repo: http://github.com/kenwheeler/slick
  Issues: http://github.com/kenwheeler/slick/issues

 */
/* global window, document, define, jQuery, setInterval, clearInterval */
(function(factory) {
    'use strict';
    if (typeof define === 'function' && define.amd) {
        define(['jquery'], factory);
    } else if (typeof exports !== 'undefined') {
        module.exports = factory(require('jquery'));
    } else {
        factory(jQuery);
    }

}(function($) {
    'use strict';
    var Slick = window.Slick || {};

    Slick = (function() {

        var instanceUid = 0;

        function Slick(element, settings) {

            var _ = this, dataSettings;

            _.defaults = {
                accessibility: true,
                adaptiveHeight: false,
                appendArrows: $(element),
                appendDots: $(element),
                arrows: true,
                asNavFor: null,
                prevArrow: '<button type="button" data-role="none" class="slick-prev" aria-label="Previous" tabindex="0" role="button">Previous</button>',
                nextArrow: '<button type="button" data-role="none" class="slick-next" aria-label="Next" tabindex="0" role="button">Next</button>',
                autoplay: false,
                autoplaySpeed: 3000,
                centerMode: false,
                centerPadding: '50px',
                cssEase: 'ease',
                customPaging: function(slider, i) {
                    return $('<button type="button" data-role="none" role="button" tabindex="0" />').text(i + 1);
                },
                dots: false,
                dotsClass: 'slick-dots',
                draggable: true,
                easing: 'linear',
                edgeFriction: 0.35,
                fade: false,
                focusOnSelect: false,
                infinite: true,
                initialSlide: 0,
                lazyLoad: 'ondemand',
                mobileFirst: false,
                pauseOnHover: true,
                pauseOnFocus: true,
                pauseOnDotsHover: false,
                respondTo: 'window',
                responsive: null,
                rows: 1,
                rtl: false,
                slide: '',
                slidesPerRow: 1,
                slidesToShow: 1,
                slidesToScroll: 1,
                speed: 500,
                swipe: true,
                swipeToSlide: false,
                touchMove: true,
                touchThreshold: 5,
                useCSS: true,
                useTransform: true,
                variableWidth: false,
                vertical: false,
                verticalSwiping: false,
                waitForAnimate: true,
                zIndex: 1000,
                slideMargin: 0,
                classPrefix: 'slick-',
            };

            _.initials = {
                animating: false,
                dragging: false,
                autoPlayTimer: null,
                currentDirection: 0,
                currentLeft: null,
                currentSlide: 0,
                direction: 1,
                $dots: null,
                listWidth: null,
                listHeight: null,
                loadIndex: 0,
                $nextArrow: null,
                $prevArrow: null,
                slideCount: null,
                slideWidth: null,
                $slideTrack: null,
                $slides: null,
                sliding: false,
                slideOffset: 0,
                swipeLeft: null,
                $list: null,
                touchObject: {},
                transformsEnabled: false,
                unslicked: false
            };

            $.extend(_, _.initials);

            _.activeBreakpoint = null;
            _.animType = null;
            _.animProp = null;
            _.breakpoints = [];
            _.breakpointSettings = [];
            _.cssTransitions = false;
            _.focussed = false;
            _.interrupted = false;
            _.hidden = 'hidden';
            _.paused = true;
            _.positionProp = null;
            _.respondTo = null;
            _.rowCount = 1;
            _.shouldClick = true;
            _.$slider = $(element);
            _.$slidesCache = null;
            _.transformType = null;
            _.transitionType = null;
            _.visibilityChange = 'visibilitychange';
            _.windowWidth = 0;
            _.windowTimer = null;

            dataSettings = $(element).data('slick') || {};

            _.options = $.extend({}, _.defaults, settings, dataSettings);

            _.currentSlide = _.options.initialSlide;

            _.originalSettings = _.options;

            if (typeof document.mozHidden !== 'undefined') {
                _.hidden = 'mozHidden';
                _.visibilityChange = 'mozvisibilitychange';
            } else if (typeof document.webkitHidden !== 'undefined') {
                _.hidden = 'webkitHidden';
                _.visibilityChange = 'webkitvisibilitychange';
            }

            _.autoPlay = $.proxy(_.autoPlay, _);
            _.autoPlayClear = $.proxy(_.autoPlayClear, _);
            _.autoPlayIterator = $.proxy(_.autoPlayIterator, _);
            _.changeSlide = $.proxy(_.changeSlide, _);
            _.clickHandler = $.proxy(_.clickHandler, _);
            _.selectHandler = $.proxy(_.selectHandler, _);
            _.setPosition = $.proxy(_.setPosition, _);
            _.swipeHandler = $.proxy(_.swipeHandler, _);
            _.dragHandler = $.proxy(_.dragHandler, _);
            _.keyHandler = $.proxy(_.keyHandler, _);

            _.instanceUid = instanceUid++;

            // A simple way to check for HTML strings
            // Strict HTML recognition (must start with <)
            // Extracted from jQuery v1.11 source
            _.htmlExpr = /^(?:\s*(<[\w\W]+>)[^>]*)$/;


            _.registerBreakpoints();
            _.init(true);

        }

        return Slick;

    }());

    Slick.prototype.activateADA = function() {
        var _ = this;

        _.$slideTrack.find('.' + _.options.classPrefix + 'active').attr({
            'aria-hidden': 'false'
        }).find('a, input, button, select').attr({
            'tabindex': '0'
        });

    };

    Slick.prototype.addSlide = Slick.prototype.slickAdd = function(markup, index, addBefore) {

        var _ = this;

        if (typeof(index) === 'boolean') {
            addBefore = index;
            index = null;
        } else if (index < 0 || (index >= _.slideCount)) {
            return false;
        }

        _.unload();

        if (typeof(index) === 'number') {
            if (index === 0 && _.$slides.length === 0) {
                $(markup).appendTo(_.$slideTrack);
            } else if (addBefore) {
                $(markup).insertBefore(_.$slides.eq(index));
            } else {
                $(markup).insertAfter(_.$slides.eq(index));
            }
        } else {
            if (addBefore === true) {
                $(markup).prependTo(_.$slideTrack);
            } else {
                $(markup).appendTo(_.$slideTrack);
            }
        }

        _.$slides = _.$slideTrack.children(this.options.slide);

        _.$slideTrack.children(this.options.slide).detach();

        _.$slideTrack.append(_.$slides);

        _.$slides.each(function(index, element) {
            $(element).attr('data-'+_.options.classPrefix+'index', index);
        });

        _.$slidesCache = _.$slides;

        _.reinit();

    };

    Slick.prototype.animateHeight = function() {
        var _ = this;
        if (_.options.slidesToShow === 1 && _.options.adaptiveHeight === true && _.options.vertical === false) {
            var targetHeight = _.$slides.eq(_.currentSlide).outerHeight(true);
            _.$list.animate({
                height: targetHeight
            }, _.options.speed);
        }
    };

    Slick.prototype.animateSlide = function(targetLeft, callback) {

        var animProps = {},
            _ = this;

        _.animateHeight();

        if (_.options.rtl === true && _.options.vertical === false) {
            targetLeft = -targetLeft;
        }
        if (_.transformsEnabled === false) {
            if (_.options.vertical === false) {
                _.$slideTrack.animate({
                    left: targetLeft
                }, _.options.speed, _.options.easing, callback);
            } else {
                _.$slideTrack.animate({
                    top: targetLeft
                }, _.options.speed, _.options.easing, callback);
            }

        } else {

            if (_.cssTransitions === false) {
                if (_.options.rtl === true) {
                    _.currentLeft = -(_.currentLeft);
                }
                $({
                    animStart: _.currentLeft
                }).animate({
                    animStart: targetLeft
                }, {
                    duration: _.options.speed,
                    easing: _.options.easing,
                    step: function(now) {
                        now = Math.ceil(now);
                        if (_.options.vertical === false) {
                            animProps[_.animType] = 'translate(' +
                                now + 'px, 0px)';
                            _.$slideTrack.css(animProps);
                        } else {
                            animProps[_.animType] = 'translate(0px,' +
                                now + 'px)';
                            _.$slideTrack.css(animProps);
                        }
                    },
                    complete: function() {
                        if (callback) {
                            callback.call();
                        }
                    }
                });

            } else {

                _.applyTransition();
                var _marginFactor = _.options.rtl === true ? 1 : -1;
                targetLeft = Math.ceil(targetLeft + ( _.options.slideMargin * _marginFactor));

                if (_.options.vertical === false) {
                    animProps[_.animType] = 'translate3d(' + targetLeft + 'px, 0px, 0px)';
                } else {
                    animProps[_.animType] = 'translate3d(0px,' + targetLeft + 'px, 0px)';
                }
                _.$slideTrack.css(animProps);

                if (callback) {
                    setTimeout(function() {

                        _.disableTransition();

                        callback.call();
                    }, _.options.speed);
                }

            }

        }

    };

    Slick.prototype.getNavTarget = function() {

        var _ = this,
            asNavFor = _.options.asNavFor;

        if ( asNavFor && asNavFor !== null ) {
            asNavFor = $(asNavFor).not(_.$slider);
        }

        return asNavFor;

    };

    Slick.prototype.asNavFor = function(index) {

        var _ = this,
            asNavFor = _.getNavTarget();

        if ( asNavFor !== null && typeof asNavFor === 'object' ) {
            asNavFor.each(function() {
                var target = $(this).slick('getSlick');
                if(!target.unslicked) {
                    target.slideHandler(index, true);
                }
            });
        }

    };

    Slick.prototype.applyTransition = function(slide) {

        var _ = this,
            transition = {};

        if (_.options.fade === false) {
            transition[_.transitionType] = _.transformType + ' ' + _.options.speed + 'ms ' + _.options.cssEase;
        } else {
            transition[_.transitionType] = 'opacity ' + _.options.speed + 'ms ' + _.options.cssEase;
        }

        if (_.options.fade === false) {
            _.$slideTrack.css(transition);
        } else {
            _.$slides.eq(slide).css(transition);
        }

    };

    Slick.prototype.autoPlay = function() {

        var _ = this;

        _.autoPlayClear();

        if ( _.slideCount > _.options.slidesToShow ) {
            _.autoPlayTimer = setInterval( _.autoPlayIterator, _.options.autoplaySpeed );
        }

    };

    Slick.prototype.autoPlayClear = function() {

        var _ = this;

        if (_.autoPlayTimer) {
            clearInterval(_.autoPlayTimer);
        }

    };

    Slick.prototype.autoPlayIterator = function() {

        var _ = this,
            slideTo = _.currentSlide + _.options.slidesToScroll;

        if ( !_.paused && !_.interrupted && !_.focussed ) {

            if ( _.options.infinite === false ) {

                if ( _.direction === 1 && ( _.currentSlide + 1 ) === ( _.slideCount - 1 )) {
                    _.direction = 0;
                }

                else if ( _.direction === 0 ) {

                    slideTo = _.currentSlide - _.options.slidesToScroll;

                    if ( _.currentSlide - 1 === 0 ) {
                        _.direction = 1;
                    }

                }

            }

            _.slideHandler( slideTo );

        }

    };

    Slick.prototype.buildArrows = function() {

        var _ = this;

        if (_.options.arrows === true ) {

            _.$prevArrow = $(_.options.prevArrow).addClass(_.options.classPrefix + 'arrow');
            _.$nextArrow = $(_.options.nextArrow).addClass(_.options.classPrefix + 'arrow');

            if( _.slideCount > _.options.slidesToShow ) {

                _.$prevArrow.removeClass(_.options.classPrefix + 'hidden').removeAttr('aria-hidden tabindex');
                _.$nextArrow.removeClass(_.options.classPrefix + 'hidden').removeAttr('aria-hidden tabindex');

                if (_.htmlExpr.test(_.options.prevArrow)) {
                    _.$prevArrow.prependTo(_.options.appendArrows);
                }

                if (_.htmlExpr.test(_.options.nextArrow)) {
                    _.$nextArrow.appendTo(_.options.appendArrows);
                }

                if (_.options.infinite !== true) {
                    _.$prevArrow
                        .addClass(_.options.classPrefix + 'disabled')
                        .attr('aria-disabled', 'true');
                }

            } else {

                _.$prevArrow.add( _.$nextArrow )

                    .addClass(_.options.classPrefix + 'hidden')
                    .attr({
                        'aria-disabled': 'true',
                        'tabindex': '-1'
                    });

            }

        }

    };

    Slick.prototype.buildDots = function() {

        var _ = this,
            i, dot;

        if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {

            _.$slider.addClass(_.options.classPrefix + 'dotted');

            dot = $('<ul />').addClass(_.options.dotsClass);

            for (i = 0; i <= _.getDotCount(); i += 1) {
                dot.append($('<li />').append(_.options.customPaging.call(this, _, i)));
            }

            _.$dots = dot.appendTo(_.options.appendDots);

            _.$dots.find('li').first().addClass(_.options.classPrefix + 'active').attr('aria-hidden', 'false');

        }

    };

    Slick.prototype.buildOut = function() {

        var _ = this;

        _.$slides =
            _.$slider
                .children( _.options.slide + ':not('+'.' + _.options.classPrefix+'cloned)')
                .addClass(_.options.classPrefix + 'slide');

        if( _.options.slideMargin ) {
            var mPos = _.options.rtl === true ? 'right' : 'left';
            _.$slides.css('margin-' + mPos, _.options.slideMargin);
        }
        _.slideCount = _.$slides.length;

        _.$slides.each(function(index, element) {
            $(element)
                .attr('data-'+_.options.classPrefix+'index', index)
                .data('originalStyling', $(element).attr('style') || '');
        });

        _.$slider.addClass(_.options.classPrefix + 'slider');

        _.$slideTrack = (_.slideCount === 0) ?
            $('<div class="'+_.options.classPrefix + 'track"/>').appendTo(_.$slider) :
            _.$slides.wrapAll('<div class="'+_.options.classPrefix + 'track"/>').parent();

        _.$list = _.$slideTrack.wrap(
            '<div aria-live="polite" class="'+_.options.classPrefix + 'list"/>').parent();
        _.$slideTrack.css('opacity', 0);

        if (_.options.centerMode === true || _.options.swipeToSlide === true) {
            _.options.slidesToScroll = 1;
        }

        $('img[data-lazy]', _.$slider).not('[src]').addClass(_.options.classPrefix + 'loading');

        _.setupInfinite();

        _.buildArrows();

        _.buildDots();

        _.updateDots();


        _.setSlideClasses(typeof _.currentSlide === 'number' ? _.currentSlide : 0);

        if (_.options.draggable === true) {
            _.$list.addClass('draggable');
        }

    };

    Slick.prototype.buildRows = function() {

        var _ = this, a, b, c, newSlides, numOfSlides, originalSlides,slidesPerSection;

        newSlides = document.createDocumentFragment();
        originalSlides = _.$slider.children();

        if(_.options.rows > 1) {

            slidesPerSection = _.options.slidesPerRow * _.options.rows;
            numOfSlides = Math.ceil(
                originalSlides.length / slidesPerSection
            );

            for(a = 0; a < numOfSlides; a++){
                var slide = document.createElement('div');
                for(b = 0; b < _.options.rows; b++) {
                    var row = document.createElement('div');
                    for(c = 0; c < _.options.slidesPerRow; c++) {
                        var target = (a * slidesPerSection + ((b * _.options.slidesPerRow) + c));
                        if (originalSlides.get(target)) {
                            row.appendChild(originalSlides.get(target));
                        }
                    }
                    slide.appendChild(row);
                }
                newSlides.appendChild(slide);
            }

            _.$slider.empty().append(newSlides);
            _.$slider.children().children().children()
                .css({
                    'width':(100 / _.options.slidesPerRow) + '%',
                    'display': 'inline-block'
                });

        }

    };

    Slick.prototype.checkResponsive = function(initial, forceUpdate) {

        var _ = this,
            breakpoint, targetBreakpoint, respondToWidth, triggerBreakpoint = false;
        var sliderWidth = _.$slider.width();
        var windowWidth = window.innerWidth || $(window).width();

        if (_.respondTo === 'window') {
            respondToWidth = windowWidth;
        } else if (_.respondTo === 'slider') {
            respondToWidth = sliderWidth;
        } else if (_.respondTo === 'min') {
            respondToWidth = Math.min(windowWidth, sliderWidth);
        }

        if ( _.options.responsive &&
            _.options.responsive.length &&
            _.options.responsive !== null) {

            targetBreakpoint = null;

            for (breakpoint in _.breakpoints) {
                if (_.breakpoints.hasOwnProperty(breakpoint)) {
                    if (_.originalSettings.mobileFirst === false) {
                        if (respondToWidth < _.breakpoints[breakpoint]) {
                            targetBreakpoint = _.breakpoints[breakpoint];
                        }
                    } else {
                        if (respondToWidth > _.breakpoints[breakpoint]) {
                            targetBreakpoint = _.breakpoints[breakpoint];
                        }
                    }
                }
            }

            if (targetBreakpoint !== null) {
                if (_.activeBreakpoint !== null) {
                    if (targetBreakpoint !== _.activeBreakpoint || forceUpdate) {
                        _.activeBreakpoint =
                            targetBreakpoint;
                        if (_.breakpointSettings[targetBreakpoint] === 'unslick') {
                            _.unslick(targetBreakpoint);
                        } else {
                            _.options = $.extend({}, _.originalSettings,
                                _.breakpointSettings[
                                    targetBreakpoint]);
                            if (initial === true) {
                                _.currentSlide = _.options.initialSlide;
                            }
                            _.refresh(initial);
                        }
                        triggerBreakpoint = targetBreakpoint;
                    }
                } else {
                    _.activeBreakpoint = targetBreakpoint;
                    if (_.breakpointSettings[targetBreakpoint] === 'unslick') {
                        _.unslick(targetBreakpoint);
                    } else {
                        _.options = $.extend({}, _.originalSettings,
                            _.breakpointSettings[
                                targetBreakpoint]);
                        if (initial === true) {
                            _.currentSlide = _.options.initialSlide;
                        }
                        _.refresh(initial);
                    }
                    triggerBreakpoint = targetBreakpoint;
                }
            } else {
                if (_.activeBreakpoint !== null) {
                    _.activeBreakpoint = null;
                    _.options = _.originalSettings;
                    if (initial === true) {
                        _.currentSlide = _.options.initialSlide;
                    }
                    _.refresh(initial);
                    triggerBreakpoint = targetBreakpoint;
                }
            }

            // only trigger breakpoints during an actual break. not on initialize.
            if( !initial && triggerBreakpoint !== false ) {
                _.$slider.trigger('breakpoint', [_, triggerBreakpoint]);
            }
        }

    };

    Slick.prototype.changeSlide = function(event, dontAnimate) {

        var _ = this,
            $target = $(event.currentTarget),
            indexOffset, slideOffset, unevenOffset;

        // If target is a link, prevent default action.
        if($target.is('a')) {
            event.preventDefault();
        }

        // If target is not the <li> element (ie: a child), find the <li>.
        if(!$target.is('li')) {
            $target = $target.closest('li');
        }

        unevenOffset = (_.slideCount % _.options.slidesToScroll !== 0);
        indexOffset = unevenOffset ? 0 : (_.slideCount - _.currentSlide) % _.options.slidesToScroll;

        switch (event.data.message) {

            case 'previous':
                slideOffset = indexOffset === 0 ? _.options.slidesToScroll : _.options.slidesToShow - indexOffset;
                if (_.slideCount > _.options.slidesToShow) {
                    _.slideHandler(_.currentSlide - slideOffset, false, dontAnimate);
                }
                break;

            case 'next':
                slideOffset = indexOffset === 0 ? _.options.slidesToScroll : indexOffset;
                if (_.slideCount > _.options.slidesToShow) {
                    _.slideHandler(_.currentSlide + slideOffset, false, dontAnimate);
                }
                break;

            case 'index':
                var index = event.data.index === 0 ? 0 :
                    event.data.index || $target.index() * _.options.slidesToScroll;

                _.slideHandler(_.checkNavigable(index), false, dontAnimate);
                $target.children().trigger('focus');
                break;

            default:
                return;
        }

    };

    Slick.prototype.checkNavigable = function(index) {

        var _ = this,
            navigables, prevNavigable;

        navigables = _.getNavigableIndexes();
        prevNavigable = 0;
        if (index > navigables[navigables.length - 1]) {
            index = navigables[navigables.length - 1];
        } else {
            for (var n in navigables) {
                if (index < navigables[n]) {
                    index = prevNavigable;
                    break;
                }
                prevNavigable = navigables[n];
            }
        }

        return index;
    };

    Slick.prototype.cleanUpEvents = function() {

        var _ = this;

        if (_.options.dots && _.$dots !== null) {

            $('li', _.$dots)
                .off('click.slick', _.changeSlide)
                .off('mouseenter.slick', $.proxy(_.interrupt, _, true))
                .off('mouseleave.slick', $.proxy(_.interrupt, _, false));

        }

        _.$slider.off('focus.slick blur.slick');

        if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {
            _.$prevArrow && _.$prevArrow.off('click.slick', _.changeSlide);
            _.$nextArrow && _.$nextArrow.off('click.slick', _.changeSlide);
        }

        _.$list.off('touchstart.slick mousedown.slick', _.swipeHandler);
        _.$list.off('touchmove.slick mousemove.slick', _.swipeHandler);
        _.$list.off('touchend.slick mouseup.slick', _.swipeHandler);
        _.$list.off('touchcancel.slick mouseleave.slick', _.swipeHandler);

        _.$list.off('click.slick', _.clickHandler);

        $(document).off(_.visibilityChange, _.visibility);

        _.cleanUpSlideEvents();

        if (_.options.accessibility === true) {
            _.$list.off('keydown.slick', _.keyHandler);
        }

        if (_.options.focusOnSelect === true) {
            $(_.$slideTrack).children().off('click.slick', _.selectHandler);
        }

        $(window).off('orientationchange.slick.slick-' + _.instanceUid, _.orientationChange);

        $(window).off('resize.slick.slick-' + _.instanceUid, _.resize);

        $('[draggable!=true]', _.$slideTrack).off('dragstart', _.preventDefault);

        $(window).off('load.slick.slick-' + _.instanceUid, _.setPosition);
        $(document).off('ready.slick.slick-' + _.instanceUid, _.setPosition);

    };

    Slick.prototype.cleanUpSlideEvents = function() {

        var _ = this;

        _.$list.off('mouseenter.slick', $.proxy(_.interrupt, _, true));
        _.$list.off('mouseleave.slick', $.proxy(_.interrupt, _, false));

    };

    Slick.prototype.cleanUpRows = function() {

        var _ = this, originalSlides;

        if(_.options.rows > 1) {
            originalSlides = _.$slides.children().children();
            originalSlides.removeAttr('style');
            _.$slider.empty().append(originalSlides);
        }

    };

    Slick.prototype.clickHandler = function(event) {

        var _ = this;

        if (_.shouldClick === false) {
            event.stopImmediatePropagation();
            event.stopPropagation();
            event.preventDefault();
        }

    };

    Slick.prototype.destroy = function(refresh) {

        var _ = this;

        _.autoPlayClear();

        _.touchObject = {};

        _.cleanUpEvents();

        $('.' + _.options.classPrefix + 'cloned', _.$slider).detach();

        if (_.$dots) {
            _.$dots.remove();
        }


        if ( _.$prevArrow && _.$prevArrow.length ) {

            _.$prevArrow
                .removeClass(_.options.classPrefix + 'disabled ' + _.options.classPrefix + 'arrow ' + _.options.classPrefix + 'hidden')
                .removeAttr('aria-hidden aria-disabled tabindex')
                .css('display','');

            if ( _.htmlExpr.test( _.options.prevArrow )) {
                _.$prevArrow.remove();
            }
        }

        if ( _.$nextArrow && _.$nextArrow.length ) {

            _.$nextArrow
                .removeClass(_.options.classPrefix + 'disabled ' + _.options.classPrefix + 'arrow ' + _.options.classPrefix + 'hidden')
                .removeAttr('aria-hidden aria-disabled tabindex')
                .css('display','');

            if ( _.htmlExpr.test( _.options.nextArrow )) {
                _.$nextArrow.remove();
            }

        }


        if (_.$slides) {

            _.$slides
                .removeClass(_.options.classPrefix + 'slide ' + _.options.classPrefix + 'active ' + _.options.classPrefix + 'center ' + _.options.classPrefix + 'visible ' + _.options.classPrefix + 'current')
                .removeAttr('aria-hidden')
                .removeAttr('data-'+_.options.classPrefix+'index')
                .each(function(){
                    $(this).attr('style', $(this).data('originalStyling'));
                });

            _.$slideTrack.children(this.options.slide).detach();

            _.$slideTrack.detach();

            _.$list.detach();

            _.$slider.append(_.$slides);
        }

        _.cleanUpRows();

        _.$slider.removeClass(_.options.classPrefix + 'slider');
        _.$slider.removeClass(_.options.classPrefix + 'initialized');
        _.$slider.removeClass(_.options.classPrefix + 'dotted');

        _.unslicked = true;

        if(!refresh) {
            _.$slider.trigger('destroy', [_]);
        }

    };

    Slick.prototype.disableTransition = function(slide) {

        var _ = this,
            transition = {};

        transition[_.transitionType] = '';

        if (_.options.fade === false) {
            _.$slideTrack.css(transition);
        } else {
            _.$slides.eq(slide).css(transition);
        }

    };

    Slick.prototype.fadeSlide = function(slideIndex, callback) {

        var _ = this;

        if (_.cssTransitions === false) {

            _.$slides.eq(slideIndex).css({
                zIndex: _.options.zIndex
            });

            _.$slides.eq(slideIndex).animate({
                opacity: 1
            }, _.options.speed, _.options.easing, callback);

        } else {

            _.applyTransition(slideIndex);

            _.$slides.eq(slideIndex).css({
                opacity: 1,
                zIndex: _.options.zIndex
            });

            if (callback) {
                setTimeout(function() {

                    _.disableTransition(slideIndex);

                    callback.call();
                }, _.options.speed);
            }

        }

    };

    Slick.prototype.fadeSlideOut = function(slideIndex) {

        var _ = this;

        if (_.cssTransitions === false) {

            _.$slides.eq(slideIndex).animate({
                opacity: 0,
                zIndex: _.options.zIndex - 2
            }, _.options.speed, _.options.easing);

        } else {

            _.applyTransition(slideIndex);

            _.$slides.eq(slideIndex).css({
                opacity: 0,
                zIndex: _.options.zIndex - 2
            });

        }

    };

    Slick.prototype.filterSlides = Slick.prototype.slickFilter = function(filter) {

        var _ = this;

        if (filter !== null) {

            _.$slidesCache = _.$slides;

            _.unload();

            _.$slideTrack.children(this.options.slide).detach();

            _.$slidesCache.filter(filter).appendTo(_.$slideTrack);

            _.reinit();

        }

    };

    Slick.prototype.focusHandler = function() {

        var _ = this;

        _.$slider
            .off('focus.slick blur.slick')
            .on('focus.slick blur.slick',
                '*:not(' + '.' + _.options.classPrefix + 'arrow)', function(event) {

            event.stopImmediatePropagation();
            var $sf = $(this);

            setTimeout(function() {

                if( _.options.pauseOnFocus ) {
                    _.focussed = $sf.is(':focus');
                    _.autoPlay();
                }

            }, 0);

        });
    };

    Slick.prototype.getCurrent = Slick.prototype.slickCurrentSlide = function() {

        var _ = this;
        return _.currentSlide;

    };

    Slick.prototype.getDotCount = function() {

        var _ = this;

        var breakPoint = 0;
        var counter = 0;
        var pagerQty = 0;

        if (_.options.infinite === true) {
            while (breakPoint < _.slideCount) {
                ++pagerQty;
                breakPoint = counter + _.options.slidesToScroll;
                counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow;
            }
        } else if (_.options.centerMode === true) {
            pagerQty = _.slideCount;
        } else if(!_.options.asNavFor) {
            pagerQty = 1 + Math.ceil((_.slideCount - _.options.slidesToShow) / _.options.slidesToScroll);
        }else {
            while (breakPoint < _.slideCount) {
                ++pagerQty;
                breakPoint = counter + _.options.slidesToScroll;
                counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow;
            }
        }

        return pagerQty - 1;

    };

    Slick.prototype.getLeft = function(slideIndex) {

        var _ = this,
            targetLeft,
            verticalHeight,
            verticalOffset = 0,
            targetSlide;

        _.slideOffset = 0;
        verticalHeight = _.$slides.first().outerHeight(true);

        if (_.options.infinite === true) {
            if (_.slideCount > _.options.slidesToShow) {
                _.slideOffset = (_.slideWidth * _.options.slidesToShow) * -1;
                verticalOffset = (verticalHeight * _.options.slidesToShow) * -1;
            }
            if (_.slideCount % _.options.slidesToScroll !== 0) {
                if (slideIndex + _.options.slidesToScroll > _.slideCount && _.slideCount > _.options.slidesToShow) {
                    if (slideIndex > _.slideCount) {
                        _.slideOffset = ((_.options.slidesToShow - (slideIndex - _.slideCount)) * _.slideWidth) * -1;
                        verticalOffset = ((_.options.slidesToShow - (slideIndex - _.slideCount)) * verticalHeight) * -1;
                    } else {
                        _.slideOffset = ((_.slideCount % _.options.slidesToScroll) * _.slideWidth) * -1;
                        verticalOffset = ((_.slideCount % _.options.slidesToScroll) * verticalHeight) * -1;
                    }
                }
            }
        } else {
            if (slideIndex + _.options.slidesToShow > _.slideCount) {
                _.slideOffset = ((slideIndex + _.options.slidesToShow) - _.slideCount) * _.slideWidth;
                verticalOffset = ((slideIndex + _.options.slidesToShow) - _.slideCount) * verticalHeight;
            }
        }

        if (_.slideCount <= _.options.slidesToShow) {
            _.slideOffset = 0;
            verticalOffset = 0;
        }

        if (_.options.centerMode === true && _.options.infinite === true) {
            _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2) - _.slideWidth;
        } else if (_.options.centerMode === true) {
            _.slideOffset = 0;
            _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2);
        }

        if (_.options.vertical === false) {
            targetLeft = ((slideIndex * _.slideWidth) * -1) + _.slideOffset;
        } else {
            targetLeft = ((slideIndex * verticalHeight) * -1) + verticalOffset;
        }

        if (_.options.variableWidth === true) {

            if (_.slideCount <= _.options.slidesToShow || _.options.infinite === false) {
                targetSlide = _.$slideTrack.children('.' + _.options.classPrefix + 'slide').eq(slideIndex);
            } else {
                targetSlide = _.$slideTrack.children('.' + _.options.classPrefix + 'slide').eq(slideIndex + _.options.slidesToShow);
            }

            if (_.options.rtl === true) {
                if (targetSlide[0]) {
                    targetLeft = (_.$slideTrack.width() - targetSlide[0].offsetLeft - targetSlide.width()) * -1;
                } else {
                    targetLeft =  0;
                }
            } else {
                targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0;
            }

            if (_.options.centerMode === true) {
                if (_.slideCount <= _.options.slidesToShow || _.options.infinite === false) {
                    targetSlide = _.$slideTrack.children('.' + _.options.classPrefix + 'slide').eq(slideIndex);
                } else {
                    targetSlide = _.$slideTrack.children('.' + _.options.classPrefix + 'slide').eq(slideIndex + _.options.slidesToShow + 1);
                }

                if (_.options.rtl === true) {
                    if (targetSlide[0]) {
                        targetLeft = (_.$slideTrack.width() - targetSlide[0].offsetLeft - targetSlide.width()) * -1;
                    } else {
                        targetLeft =  0;
                    }
                } else {
                    targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0;
                }

                targetLeft += (_.$list.width() - targetSlide.outerWidth()) / 2;
            }
        }

        return targetLeft;

    };

    Slick.prototype.getOption = Slick.prototype.slickGetOption = function(option) {

        var _ = this;

        return _.options[option];

    };

    Slick.prototype.getNavigableIndexes = function() {

        var _ = this,
            breakPoint = 0,
            counter = 0,
            indexes = [],
            max;

        if (_.options.infinite === false) {
            max = _.slideCount;
        } else {
            breakPoint = _.options.slidesToScroll * -1;
            counter = _.options.slidesToScroll * -1;
            max = _.slideCount * 2;
        }

        while (breakPoint < max) {
            indexes.push(breakPoint);
            breakPoint = counter + _.options.slidesToScroll;
            counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow;
        }

        return indexes;

    };

    Slick.prototype.getSlick = function() {

        return this;

    };

    Slick.prototype.getSlideCount = function() {

        var _ = this,
            slidesTraversed, swipedSlide, centerOffset;

        centerOffset = _.options.centerMode === true ? _.slideWidth * Math.floor(_.options.slidesToShow / 2) : 0;

        if (_.options.swipeToSlide === true) {
            _.$slideTrack.find('.' + _.options.classPrefix + 'slide').each(function(index, slide) {
                if (slide.offsetLeft - centerOffset + ($(slide).outerWidth() / 2) > (_.swipeLeft * -1)) {
                    swipedSlide = slide;
                    return false;
                }
            });

            slidesTraversed = Math.abs($(swipedSlide).attr('data-'+_.options.classPrefix+'index') - _.currentSlide) || 1;

            return slidesTraversed;

        } else {
            return _.options.slidesToScroll;
        }

    };

    Slick.prototype.goTo = Slick.prototype.slickGoTo = function(slide, dontAnimate) {

        var _ = this;

        _.changeSlide({
            data: {
                message: 'index',
                index: parseInt(slide)
            }
        }, dontAnimate);

    };

    Slick.prototype.init = function(creation) {

        var _ = this;

        if (!$(_.$slider).hasClass(_.options.classPrefix + 'initialized')) {

            $(_.$slider).addClass(_.options.classPrefix + 'initialized');

            _.buildRows();
            _.buildOut();
            _.setProps();
            _.startLoad();
            _.loadSlider();
            _.initializeEvents();
            _.updateArrows();
            _.updateDots();
            _.checkResponsive(true);
            _.focusHandler();

        }

        if (creation) {
            _.$slider.trigger('init', [_]);
        }

        if (_.options.accessibility === true) {
            _.initADA();
        }

        if ( _.options.autoplay ) {

            _.paused = false;
            _.autoPlay();

        }

    };

    Slick.prototype.initADA = function() {
        var _ = this;
        _.$slides.add(_.$slideTrack.find('.' + _.options.classPrefix + 'cloned')).attr({
            'aria-hidden': 'true',
            'tabindex': '-1'
        }).find('a, input, button, select').attr({
            'tabindex': '-1'
        });

        _.$slideTrack.attr('role', 'listbox');

        _.$slides.not(_.$slideTrack.find('.' + _.options.classPrefix + 'cloned')).each(function(i) {
            $(this).attr('role', 'option');

            //Evenly distribute aria-describedby tags through available dots.
            var describedBySlideId = _.options.centerMode ? i : Math.floor(i / _.options.slidesToShow);

            if (_.options.dots === true) {
                $(this).attr('aria-describedby', _.options.classPrefix + '-slide' + _.instanceUid + describedBySlideId + '');
            }
        });

        if (_.$dots !== null) {
            _.$dots.attr('role', 'tablist').find('li').each(function(i) {
                $(this).attr({
                    'role': 'presentation',
                    'aria-selected': 'false',
                    'aria-controls': 'navigation' + _.instanceUid + i + '',
                    'id': _.options.classPrefix + '-slide' + _.instanceUid + i + ''
                });
            })
                .first().attr('aria-selected', 'true').end()
                .find('button').attr('role', 'button').end()
                .closest('div').attr('role', 'toolbar');
        }
        _.activateADA();

    };

    Slick.prototype.initArrowEvents = function() {

        var _ = this;

        if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {
            _.$prevArrow
               .off('click.slick')
               .on('click.slick', {
                    message: 'previous'
               }, _.changeSlide);
            _.$nextArrow
               .off('click.slick')
               .on('click.slick', {
                    message: 'next'
               }, _.changeSlide);
        }

    };

    Slick.prototype.initDotEvents = function() {

        var _ = this;

        if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {
            $('li', _.$dots).on('click.slick', {
                message: 'index'
            }, _.changeSlide);
        }

        if ( _.options.dots === true && _.options.pauseOnDotsHover === true ) {

            $('li', _.$dots)
                .on('mouseenter.slick', $.proxy(_.interrupt, _, true))
                .on('mouseleave.slick', $.proxy(_.interrupt, _, false));

        }

    };

    Slick.prototype.initSlideEvents = function() {

        var _ = this;

        if ( _.options.pauseOnHover ) {

            _.$list.on('mouseenter.slick', $.proxy(_.interrupt, _, true));
            _.$list.on('mouseleave.slick', $.proxy(_.interrupt, _, false));

        }

    };

    Slick.prototype.initializeEvents = function() {

        var _ = this;

        _.initArrowEvents();

        _.initDotEvents();
        _.initSlideEvents();

        _.$list.on('touchstart.slick mousedown.slick', {
            action: 'start'
        }, _.swipeHandler);
        _.$list.on('touchmove.slick mousemove.slick', {
            action: 'move'
        }, _.swipeHandler);
        _.$list.on('touchend.slick mouseup.slick', {
            action: 'end'
        }, _.swipeHandler);
        _.$list.on('touchcancel.slick mouseleave.slick', {
            action: 'end'
        }, _.swipeHandler);

        _.$list.on('click.slick', _.clickHandler);

        $(document).on(_.visibilityChange, $.proxy(_.visibility, _));

        if (_.options.accessibility === true) {
            _.$list.on('keydown.slick', _.keyHandler);
        }

        if (_.options.focusOnSelect === true) {
            $(_.$slideTrack).children().on('click.slick', _.selectHandler);
        }

        $(window).on('orientationchange.slick.slick-' + _.instanceUid, $.proxy(_.orientationChange, _));

        $(window).on('resize.slick.slick-' + _.instanceUid, $.proxy(_.resize, _));

        $('[draggable!=true]', _.$slideTrack).on('dragstart', _.preventDefault);

        $(window).on('load.slick.slick-' + _.instanceUid, _.setPosition);
        $(document).on('ready.slick.slick-' + _.instanceUid, _.setPosition);

    };

    Slick.prototype.initUI = function() {

        var _ = this;

        if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {

            _.$prevArrow.show();
            _.$nextArrow.show();

        }

        if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {

            _.$dots.show();

        }

    };

    Slick.prototype.keyHandler = function(event) {

        var _ = this;
         //Dont slide if the cursor is inside the form fields and arrow keys are pressed
        if(!event.target.tagName.match('TEXTAREA|INPUT|SELECT')) {
            if (event.keyCode === 37 && _.options.accessibility === true) {
                _.changeSlide({
                    data: {
                        message: _.options.rtl === true ? 'next' :  'previous'
                    }
                });
            } else if (event.keyCode === 39 && _.options.accessibility === true) {
                _.changeSlide({
                    data: {
                        message: _.options.rtl === true ? 'previous' : 'next'
                    }
                });
            }
        }

    };

    Slick.prototype.lazyLoad = function() {

        var _ = this,
            loadRange, cloneRange, rangeStart, rangeEnd;

        function loadImages(imagesScope) {

            $('img[data-lazy]', imagesScope).each(function() {

                var image = $(this),
                    imageSource = $(this).attr('data-lazy'),
                    imageToLoad = document.createElement('img');

                imageToLoad.onload = function() {

                    image
                        .animate({ opacity: 0 }, 100, function() {
                            image
                                .attr('src', imageSource)
                                .animate({ opacity: 1 }, 200, function() {
                                    image
                                        .removeAttr('data-lazy')
                                        .removeClass(_.options.classPrefix + 'loading');
                                });
                            _.$slider.trigger('lazyLoaded', [_, image, imageSource]);
                        });

                };

                imageToLoad.onerror = function() {

                    image
                        .removeAttr( 'data-lazy' )
                        .removeClass( _.options.classPrefix + 'loading' )
                        .addClass( _.options.classPrefix + 'lazyload-error' );

                    _.$slider.trigger('lazyLoadError', [ _, image, imageSource ]);

                };

                imageToLoad.src = imageSource;

            });

        }

        if (_.options.centerMode === true) {
            if (_.options.infinite === true) {
                rangeStart = _.currentSlide + (_.options.slidesToShow / 2 + 1);
                rangeEnd = rangeStart + _.options.slidesToShow + 2;
            } else {
                rangeStart = Math.max(0, _.currentSlide - (_.options.slidesToShow / 2 + 1));
                rangeEnd = 2 + (_.options.slidesToShow / 2 + 1) + _.currentSlide;
            }
        } else {
            rangeStart = _.options.infinite ? _.options.slidesToShow + _.currentSlide : _.currentSlide;
            rangeEnd = Math.ceil(rangeStart + _.options.slidesToShow);
            if (_.options.fade === true) {
                if (rangeStart > 0) rangeStart--;
                if (rangeEnd <= _.slideCount) rangeEnd++;
            }
        }

        loadRange = _.$slider.find('.' + _.options.classPrefix + 'slide').slice(rangeStart, rangeEnd);
        loadImages(loadRange);

        if (_.slideCount <= _.options.slidesToShow) {
            cloneRange = _.$slider.find('.' + _.options.classPrefix + 'slide');
            loadImages(cloneRange);
        } else
        if (_.currentSlide >= _.slideCount - _.options.slidesToShow) {
            cloneRange = _.$slider.find('.' + _.options.classPrefix + 'cloned').slice(0, _.options.slidesToShow);
            loadImages(cloneRange);
        } else if (_.currentSlide === 0) {
            cloneRange = _.$slider.find('.' + _.options.classPrefix + 'cloned').slice(_.options.slidesToShow * -1);
            loadImages(cloneRange);
        }

    };

    Slick.prototype.loadSlider = function() {

        var _ = this;

        _.setPosition();

        _.$slideTrack.css({
            opacity: 1
        });

        _.$slider.removeClass(_.options.classPrefix + 'loading');

        _.initUI();

        if (_.options.lazyLoad === 'progressive') {
            _.progressiveLazyLoad();
        }

    };

    Slick.prototype.next = Slick.prototype.slickNext = function() {

        var _ = this;

        _.changeSlide({
            data: {
                message: 'next'
            }
        });

    };

    Slick.prototype.orientationChange = function() {

        var _ = this;

        _.checkResponsive();
        _.setPosition();

    };

    Slick.prototype.pause = Slick.prototype.slickPause = function() {

        var _ = this;

        _.autoPlayClear();
        _.paused = true;

    };

    Slick.prototype.play = Slick.prototype.slickPlay = function() {

        var _ = this;

        _.autoPlay();
        _.options.autoplay = true;
        _.paused = false;
        _.focussed = false;
        _.interrupted = false;

    };

    Slick.prototype.postSlide = function(index) {

        var _ = this;

        if( !_.unslicked ) {

            _.$slider.trigger('afterChange', [_, index]);

            _.animating = false;

            _.setPosition();

            _.swipeLeft = null;

            if ( _.options.autoplay ) {
                _.autoPlay();
            }

            if (_.options.accessibility === true) {
                _.initADA();
            }

        }

    };

    Slick.prototype.prev = Slick.prototype.slickPrev = function() {

        var _ = this;

        _.changeSlide({
            data: {
                message: 'previous'
            }
        });

    };

    Slick.prototype.preventDefault = function(event) {

        event.preventDefault();

    };

    Slick.prototype.progressiveLazyLoad = function( tryCount ) {

        tryCount = tryCount || 1;

        var _ = this,
            $imgsToLoad = $( 'img[data-lazy]', _.$slider ),
            image,
            imageSource,
            imageToLoad;

        if ( $imgsToLoad.length ) {

            image = $imgsToLoad.first();
            imageSource = image.attr('data-lazy');
            imageToLoad = document.createElement('img');

            imageToLoad.onload = function() {

                image
                    .attr( 'src', imageSource )
                    .removeAttr('data-lazy')
                    .removeClass(_.options.classPrefix + 'loading');

                if ( _.options.adaptiveHeight === true ) {
                    _.setPosition();
                }

                _.$slider.trigger('lazyLoaded', [ _, image, imageSource ]);
                _.progressiveLazyLoad();

            };

            imageToLoad.onerror = function() {

                if ( tryCount < 3 ) {

                    /**
                     * try to load the image 3 times,
                     * leave a slight delay so we don't get
                     * servers blocking the request.
                     */
                    setTimeout( function() {
                        _.progressiveLazyLoad( tryCount + 1 );
                    }, 500 );

                } else {

                    image
                        .removeAttr( 'data-lazy' )
                        .removeClass( _.options.classPrefix + 'loading' )
                        .addClass( _.options.classPrefix + 'lazyload-error' );

                    _.$slider.trigger('lazyLoadError', [ _, image, imageSource ]);

                    _.progressiveLazyLoad();

                }

            };

            imageToLoad.src = imageSource;

        } else {

            _.$slider.trigger('allImagesLoaded', [ _ ]);

        }

    };

    Slick.prototype.refresh = function( initializing ) {

        var _ = this, currentSlide, lastVisibleIndex;

        lastVisibleIndex = _.slideCount - _.options.slidesToShow;

        // in non-infinite sliders, we don't want to go past the
        // last visible index.
        if( !_.options.infinite && ( _.currentSlide > lastVisibleIndex )) {
            _.currentSlide = lastVisibleIndex;
        }

        // if less slides than to show, go to start.
        if ( _.slideCount <= _.options.slidesToShow ) {
            _.currentSlide = 0;

        }

        currentSlide = _.currentSlide;

        _.destroy(true);

        $.extend(_, _.initials, { currentSlide: currentSlide });

        _.init();

        if( !initializing ) {

            _.changeSlide({
                data: {
                    message: 'index',
                    index: currentSlide
                }
            }, false);

        }

    };

    Slick.prototype.registerBreakpoints = function() {

        var _ = this, breakpoint, currentBreakpoint, l,
            responsiveSettings = _.options.responsive || null;

        if ( $.type(responsiveSettings) === 'array' && responsiveSettings.length ) {

            _.respondTo = _.options.respondTo || 'window';

            for ( breakpoint in responsiveSettings ) {

                l = _.breakpoints.length-1;
                currentBreakpoint = responsiveSettings[breakpoint].breakpoint;

                if (responsiveSettings.hasOwnProperty(breakpoint)) {

                    // loop through the breakpoints and cut out any existing
                    // ones with the same breakpoint number, we don't want dupes.
                    while( l >= 0 ) {
                        if( _.breakpoints[l] && _.breakpoints[l] === currentBreakpoint ) {
                            _.breakpoints.splice(l,1);
                        }
                        l--;
                    }

                    _.breakpoints.push(currentBreakpoint);
                    _.breakpointSettings[currentBreakpoint] = responsiveSettings[breakpoint].settings;

                }

            }

            _.breakpoints.sort(function(a, b) {
                return ( _.options.mobileFirst ) ? a-b : b-a;
            });

        }

    };

    Slick.prototype.reinit = function() {

        var _ = this;

        _.$slides =
            _.$slideTrack
                .children(_.options.slide)
                .addClass(_.options.classPrefix + 'slide');

        if( _.options.slideMargin ) {
            var mPos = _.options.rtl === true ? 'right' : 'left';
            _.$slides.css('margin-'+mPos, _.options.slideMargin);
        }
        _.slideCount = _.$slides.length;

        if (_.currentSlide >= _.slideCount && _.currentSlide !== 0) {
            _.currentSlide = _.currentSlide - _.options.slidesToScroll;
        }

        if (_.slideCount <= _.options.slidesToShow) {
            _.currentSlide = 0;
        }

        _.registerBreakpoints();

        _.setProps();
        _.setupInfinite();
        _.buildArrows();
        _.updateArrows();
        _.initArrowEvents();
        _.buildDots();
        _.updateDots();
        _.initDotEvents();
        _.cleanUpSlideEvents();
        _.initSlideEvents();

        _.checkResponsive(false, true);

        if (_.options.focusOnSelect === true) {
            $(_.$slideTrack).children().on('click.slick', _.selectHandler);
        }

        _.setSlideClasses(typeof _.currentSlide === 'number' ? _.currentSlide : 0);

        _.setPosition();
        _.focusHandler();

        _.paused = !_.options.autoplay;
        _.autoPlay();

        _.$slider.trigger('reInit', [_]);

    };

    Slick.prototype.resize = function() {

        var _ = this;

        if ($(window).width() !== _.windowWidth) {
            clearTimeout(_.windowDelay);
            _.windowDelay = window.setTimeout(function() {
                _.windowWidth = $(window).width();
                _.checkResponsive();
                if( !_.unslicked ) { _.setPosition(); }
            }, 50);
        }
    };

    Slick.prototype.removeSlide = Slick.prototype.slickRemove = function(index, removeBefore, removeAll) {

        var _ = this;

        if (typeof(index) === 'boolean') {
            removeBefore = index;
            index = removeBefore === true ? 0 : _.slideCount - 1;
        } else {
            index = removeBefore === true ? --index : index;
        }

        if (_.slideCount < 1 || index < 0 || index > _.slideCount - 1) {
            return false;
        }

        _.unload();

        if (removeAll === true) {
            _.$slideTrack.children().remove();
        } else {
            _.$slideTrack.children(this.options.slide).eq(index).remove();
        }

        _.$slides = _.$slideTrack.children(this.options.slide);

        _.$slideTrack.children(this.options.slide).detach();

        _.$slideTrack.append(_.$slides);

        _.$slidesCache = _.$slides;

        _.reinit();

    };

    Slick.prototype.setCSS = function(position) {

        var _ = this,
            positionProps = {},
            x, y;

        if (_.options.rtl === true) {
            position = -position;
        }
        var _marginFactor = _.options.rtl === true ? 1 : -1;
        x = _.positionProp == 'left' ? Math.ceil(position + (_.options.slideMargin * _marginFactor)) + 'px' : '0px';
        y = _.positionProp == 'top' ? Math.ceil(position) + 'px' : '0px';

        positionProps[_.positionProp] = position;

        if (_.transformsEnabled === false) {
            _.$slideTrack.css(positionProps);
        } else {
            positionProps = {};
            if (_.cssTransitions === false) {
                positionProps[_.animType] = 'translate(' + x + ', ' + y + ')';
                _.$slideTrack.css(positionProps);
            } else {
                positionProps[_.animType] = 'translate3d(' + x + ', ' + y + ', 0px)';
                _.$slideTrack.css(positionProps);
            }
        }

    };

    Slick.prototype.setDimensions = function() {

        var _ = this;

        if (_.options.vertical === false) {
            if (_.options.centerMode === true) {
                _.$list.css({
                    padding: ('0px ' + _.options.centerPadding)
                });
            }
        } else {
            _.$list.height(_.$slides.first().outerHeight(true) * _.options.slidesToShow);
            if (_.options.centerMode === true) {
                _.$list.css({
                    padding: (_.options.centerPadding + ' 0px')
                });
            }
        }

        _.listWidth = _.$list.width();
        _.listHeight = _.$list.height();


        if (_.options.vertical === false && _.options.variableWidth === false) {
            _.slideWidth  = Math.ceil(_.listWidth / _.options.slidesToShow);
            _.slideWidth += _.options.slideMargin;
            _.$slideTrack.width(Math.ceil((_.slideWidth * _.$slideTrack.children('.' + _.options.classPrefix + 'slide').length)));

        } else if (_.options.variableWidth === true) {
            _.$slideTrack.width(5000 * _.slideCount);
        } else {
            _.slideWidth = Math.ceil(_.listWidth);
            _.$slideTrack.height(Math.ceil((_.$slides.first().outerHeight(true) * _.$slideTrack.children('.' + _.options.classPrefix + 'slide').length)));
        }

        var offset = _.$slides.first().outerWidth(true) - _.$slides.first().width();
        if (_.options.variableWidth === false) _.$slideTrack.children('.' + _.options.classPrefix + 'slide').width(_.slideWidth - offset);

    };

    Slick.prototype.setFade = function() {

        var _ = this,
            targetLeft;

        _.$slides.each(function(index, element) {
            targetLeft = (_.slideWidth * index) * -1;
            if (_.options.rtl === true) {
                $(element).css({
                    position: 'relative',
                    right: targetLeft,
                    top: 0,
                    zIndex: _.options.zIndex - 2,
                    opacity: 0
                });
            } else {
                $(element).css({
                    position: 'relative',
                    left: targetLeft,
                    top: 0,
                    zIndex: _.options.zIndex - 2,
                    opacity: 0
                });
            }
        });

        _.$slides.eq(_.currentSlide).css({
            zIndex: _.options.zIndex - 1,
            opacity: 1
        });

    };

    Slick.prototype.setHeight = function() {

        var _ = this;

        if (_.options.slidesToShow === 1 && _.options.adaptiveHeight === true && _.options.vertical === false) {
            var targetHeight = _.$slides.eq(_.currentSlide).outerHeight(true);
            _.$list.css('height', targetHeight);
        }

    };

    Slick.prototype.setOption =
    Slick.prototype.slickSetOption = function() {

        /**
         * accepts arguments in format of:
         *
         *  - for changing a single option's value:
         *     .slick("setOption", option, value, refresh )
         *
         *  - for changing a set of responsive options:
         *     .slick("setOption", 'responsive', [{}, ...], refresh )
         *
         *  - for updating multiple values at once (not responsive)
         *     .slick("setOption", { 'option': value, ... }, refresh )
         */

        var _ = this, l, item, option, value, refresh = false, type;

        if( $.type( arguments[0] ) === 'object' ) {

            option =  arguments[0];
            refresh = arguments[1];
            type = 'multiple';

        } else if ( $.type( arguments[0] ) === 'string' ) {

            option =  arguments[0];
            value = arguments[1];
            refresh = arguments[2];

            if ( arguments[0] === 'responsive' && $.type( arguments[1] ) === 'array' ) {

                type = 'responsive';

            } else if ( typeof arguments[1] !== 'undefined' ) {

                type = 'single';

            }

        }

        if ( type === 'single' ) {

            _.options[option] = value;


        } else if ( type === 'multiple' ) {

            $.each( option , function( opt, val ) {

                _.options[opt] = val;

            });


        } else if ( type === 'responsive' ) {

            for ( item in value ) {

                if( $.type( _.options.responsive ) !== 'array' ) {

                    _.options.responsive = [ value[item] ];

                } else {

                    l = _.options.responsive.length-1;

                    // loop through the responsive object and splice out duplicates.
                    while( l >= 0 ) {

                        if( _.options.responsive[l].breakpoint === value[item].breakpoint ) {

                            _.options.responsive.splice(l,1);

                        }

                        l--;

                    }

                    _.options.responsive.push( value[item] );

                }

            }

        }

        if ( refresh ) {

            _.unload();
            _.reinit();

        }

    };

    Slick.prototype.setPosition = function() {

        var _ = this;

        _.setDimensions();

        _.setHeight();

        if (_.options.fade === false) {
            _.setCSS(_.getLeft(_.currentSlide));
        } else {
            _.setFade();
        }

        _.$slider.trigger('setPosition', [_]);

    };

    Slick.prototype.setProps = function() {

        var _ = this,
            bodyStyle = document.body.style;

        _.positionProp = _.options.vertical === true ? 'top' : 'left';

        if (_.positionProp === 'top') {
            _.$slider.addClass(_.options.classPrefix + 'vertical');
        } else {
            _.$slider.removeClass(_.options.classPrefix + 'vertical');
        }

        if (bodyStyle.WebkitTransition !== undefined ||
            bodyStyle.MozTransition !== undefined ||
            bodyStyle.msTransition !== undefined) {
            if (_.options.useCSS === true) {
                _.cssTransitions = true;
            }
        }

        if ( _.options.fade ) {
            if ( typeof _.options.zIndex === 'number' ) {
                if( _.options.zIndex < 3 ) {
                    _.options.zIndex = 3;
                }
            } else {
                _.options.zIndex = _.defaults.zIndex;
            }
        }

        if (bodyStyle.OTransform !== undefined) {
            _.animType = 'OTransform';
            _.transformType = '-o-transform';
            _.transitionType = 'OTransition';
            if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false;
        }
        if (bodyStyle.MozTransform !== undefined) {
            _.animType = 'MozTransform';
            _.transformType = '-moz-transform';
            _.transitionType = 'MozTransition';
            if (bodyStyle.perspectiveProperty === undefined && bodyStyle.MozPerspective === undefined) _.animType = false;
        }
        if (bodyStyle.webkitTransform !== undefined) {
            _.animType = 'webkitTransform';
            _.transformType = '-webkit-transform';
            _.transitionType = 'webkitTransition';
            if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false;
        }
        if (bodyStyle.msTransform !== undefined) {
            _.animType = 'msTransform';
            _.transformType = '-ms-transform';
            _.transitionType = 'msTransition';
            if (bodyStyle.msTransform === undefined) _.animType = false;
        }
        if (bodyStyle.transform !== undefined && _.animType !== false) {
            _.animType = 'transform';
            _.transformType = 'transform';
            _.transitionType = 'transition';
        }
        _.transformsEnabled = _.options.useTransform && (_.animType !== null && _.animType !== false);
    };


    Slick.prototype.setSlideClasses = function(index) {

        var _ = this,
            centerOffset, allSlides, indexOffset, remainder;

        allSlides = _.$slider
            .find('.' + _.options.classPrefix + 'slide')
            .removeClass(_.options.classPrefix + 'active ' + _.options.classPrefix + 'center ' + _.options.classPrefix + 'current')
            .attr('aria-hidden', 'true');

        _.$slides
            .eq(index)
            .addClass(_.options.classPrefix + 'current');

        if (_.options.centerMode === true) {

            centerOffset = Math.floor(_.options.slidesToShow / 2);

            if (_.options.infinite === true) {

                if (index >= centerOffset && index <= (_.slideCount - 1) - centerOffset) {

                    _.$slides
                        .slice(index - centerOffset, index + centerOffset + 1)
                        .addClass(_.options.classPrefix + 'active')
                        .attr('aria-hidden', 'false');

                } else {

                    indexOffset = _.options.slidesToShow + index;
                    allSlides
                        .slice(indexOffset - centerOffset + 1, indexOffset + centerOffset + 2)
                        .addClass(_.options.classPrefix + 'active')
                        .attr('aria-hidden', 'false');

                }

                if (index === 0) {

                    allSlides
                        .eq(allSlides.length - 1 - _.options.slidesToShow)
                        .addClass(_.options.classPrefix + 'center');

                } else if (index === _.slideCount - 1) {

                    allSlides
                        .eq(_.options.slidesToShow)
                        .addClass(_.options.classPrefix + 'center');

                }

            }

            _.$slides
                .eq(index)
                .addClass(_.options.classPrefix + 'center');

        } else {

            if (index >= 0 && index <= (_.slideCount - _.options.slidesToShow)) {

                _.$slides
                    .slice(index, index + _.options.slidesToShow)
                    .addClass(_.options.classPrefix + 'active')
                    .attr('aria-hidden', 'false');

            } else if (allSlides.length <= _.options.slidesToShow) {

                allSlides
                    .addClass(_.options.classPrefix + 'active')
                    .attr('aria-hidden', 'false');

            } else {

                remainder = _.slideCount % _.options.slidesToShow;
                indexOffset = _.options.infinite === true ? _.options.slidesToShow + index : index;

                if (_.options.slidesToShow == _.options.slidesToScroll && (_.slideCount - index) < _.options.slidesToShow) {

                    allSlides
                        .slice(indexOffset - (_.options.slidesToShow - remainder), indexOffset + remainder)
                        .addClass(_.options.classPrefix + 'active')
                        .attr('aria-hidden', 'false');

                } else {

                    allSlides
                        .slice(indexOffset, indexOffset + _.options.slidesToShow)
                        .addClass(_.options.classPrefix + 'active')
                        .attr('aria-hidden', 'false');

                }

            }

        }

        if (_.options.lazyLoad === 'ondemand') {
            _.lazyLoad();
        }

    };

    Slick.prototype.setupInfinite = function() {

        var _ = this,
            i, slideIndex, infiniteCount;

        if (_.options.fade === true) {
            _.options.centerMode = false;
        }

        if (_.options.infinite === true && _.options.fade === false) {

            slideIndex = null;

            if (_.slideCount > _.options.slidesToShow) {

                if (_.options.centerMode === true) {
                    infiniteCount = _.options.slidesToShow + 1;
                } else {
                    infiniteCount = _.options.slidesToShow;
                }

                for (i = _.slideCount; i > (_.slideCount -
                        infiniteCount); i -= 1) {
                    slideIndex = i - 1;
                    $(_.$slides[slideIndex]).clone(true).attr('id', '')
                        .attr('data-'+_.options.classPrefix+'index', slideIndex - _.slideCount)
                        .prependTo(_.$slideTrack).addClass(_.options.classPrefix + 'cloned');
                }
                for (i = 0; i < infiniteCount; i += 1) {
                    slideIndex = i;
                    $(_.$slides[slideIndex]).clone(true).attr('id', '')
                        .attr('data-'+_.options.classPrefix+'index', slideIndex + _.slideCount)
                        .appendTo(_.$slideTrack).addClass(_.options.classPrefix + 'cloned');
                }
                _.$slideTrack.find('.' + _.options.classPrefix + 'cloned').find('[id]').each(function() {
                    $(this).attr('id', '');
                });

            }

        }

    };

    Slick.prototype.interrupt = function( toggle ) {

        var _ = this;

        if( !toggle ) {
            _.autoPlay();
        }
        _.interrupted = toggle;

    };

    Slick.prototype.selectHandler = function(event) {

        var _ = this;

        var targetElement =
            $(event.target).is('.' + _.options.classPrefix + 'slide') ?
                $(event.target) :
                $(event.target).parents('.' + _.options.classPrefix + 'slide');

        var index = parseInt(targetElement.attr('data-'+_.options.classPrefix+'index'));

        if (!index) index = 0;

        if (_.slideCount <= _.options.slidesToShow) {

            _.setSlideClasses(index);
            _.asNavFor(index);
            return;

        }

        _.slideHandler(index);

    };

    Slick.prototype.slideHandler = function(index, sync, dontAnimate) {

        var targetSlide, animSlide, oldSlide, slideLeft, targetLeft = null,
            _ = this, navTarget;

        sync = sync || false;

        if (_.animating === true && _.options.waitForAnimate === true) {
            return;
        }

        if (_.options.fade === true && _.currentSlide === index) {
            return;
        }

        if (_.slideCount <= _.options.slidesToShow) {
            return;
        }

        if (sync === false) {
            _.asNavFor(index);
        }

        targetSlide = index;
        targetLeft = _.getLeft(targetSlide);
        slideLeft = _.getLeft(_.currentSlide);

        _.currentLeft = _.swipeLeft === null ? slideLeft : _.swipeLeft;

        if (_.options.infinite === false && _.options.centerMode === false && (index < 0 || index > _.getDotCount() * _.options.slidesToScroll)) {
            if (_.options.fade === false) {
                targetSlide = _.currentSlide;
                if (dontAnimate !== true) {
                    _.animateSlide(slideLeft, function() {
                        _.postSlide(targetSlide);
                    });
                } else {
                    _.postSlide(targetSlide);
                }
            }
            return;
        } else if (_.options.infinite === false && _.options.centerMode === true && (index < 0 || index > (_.slideCount - _.options.slidesToScroll))) {
            if (_.options.fade === false) {
                targetSlide = _.currentSlide;
                if (dontAnimate !== true) {
                    _.animateSlide(slideLeft, function() {
                        _.postSlide(targetSlide);
                    });
                } else {
                    _.postSlide(targetSlide);
                }
            }
            return;
        }

        if ( _.options.autoplay ) {
            clearInterval(_.autoPlayTimer);
        }

        if (targetSlide < 0) {
            if (_.slideCount % _.options.slidesToScroll !== 0) {
                animSlide = _.slideCount - (_.slideCount % _.options.slidesToScroll);
            } else {
                animSlide = _.slideCount + targetSlide;
            }
        } else if (targetSlide >= _.slideCount) {
            if (_.slideCount % _.options.slidesToScroll !== 0) {
                animSlide = 0;
            } else {
                animSlide = targetSlide - _.slideCount;
            }
        } else {
            animSlide = targetSlide;
        }

        _.animating = true;

        _.$slider.trigger('beforeChange', [_, _.currentSlide, animSlide]);

        oldSlide = _.currentSlide;
        _.currentSlide = animSlide;

        _.setSlideClasses(_.currentSlide);

        if ( _.options.asNavFor ) {

            navTarget = _.getNavTarget();
            navTarget = navTarget.slick('getSlick');

            if ( navTarget.slideCount <= navTarget.options.slidesToShow ) {
                navTarget.setSlideClasses(_.currentSlide);
            }

        }

        _.updateDots();
        _.updateArrows();

        if (_.options.fade === true) {
            if (dontAnimate !== true) {

                _.fadeSlideOut(oldSlide);

                _.fadeSlide(animSlide, function() {
                    _.postSlide(animSlide);
                });

            } else {
                _.postSlide(animSlide);
            }
            _.animateHeight();
            return;
        }

        if (dontAnimate !== true) {
            _.animateSlide(targetLeft, function() {
                _.postSlide(animSlide);
            });
        } else {
            _.postSlide(animSlide);
        }

    };

    Slick.prototype.startLoad = function() {

        var _ = this;

        if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {

            _.$prevArrow.hide();
            _.$nextArrow.hide();

        }

        if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {

            _.$dots.hide();

        }

        _.$slider.addClass(_.options.classPrefix + 'loading');

    };

    Slick.prototype.swipeDirection = function() {

        var xDist, yDist, r, swipeAngle, _ = this;

        xDist = _.touchObject.startX - _.touchObject.curX;
        yDist = _.touchObject.startY - _.touchObject.curY;
        r = Math.atan2(yDist, xDist);

        swipeAngle = Math.round(r * 180 / Math.PI);
        if (swipeAngle < 0) {
            swipeAngle = 360 - Math.abs(swipeAngle);
        }

        if ((swipeAngle <= 45) && (swipeAngle >= 0)) {
            return (_.options.rtl === false ? 'left' : 'right');
        }
        if ((swipeAngle <= 360) && (swipeAngle >= 315)) {
            return (_.options.rtl === false ? 'left' : 'right');
        }
        if ((swipeAngle >= 135) && (swipeAngle <= 225)) {
            return (_.options.rtl === false ? 'right' : 'left');
        }
        if (_.options.verticalSwiping === true) {
            if ((swipeAngle >= 35) && (swipeAngle <= 135)) {
                return 'down';
            } else {
                return 'up';
            }
        }

        return 'vertical';

    };

    Slick.prototype.swipeEnd = function(event) {

        var _ = this,
            slideCount,
            direction;

        _.dragging = false;
        _.interrupted = false;
        _.shouldClick = ( _.touchObject.swipeLength > 10 ) ? false : true;

        if ( _.touchObject.curX === undefined ) {
            return false;
        }

        if ( _.touchObject.edgeHit === true ) {
            _.$slider.trigger('edge', [_, _.swipeDirection() ]);
        }

        if ( _.touchObject.swipeLength >= _.touchObject.minSwipe ) {

            direction = _.swipeDirection();

            switch ( direction ) {

                case 'left':
                case 'down':

                    slideCount =
                        _.options.swipeToSlide ?
                            _.checkNavigable( _.currentSlide + _.getSlideCount() ) :
                            _.currentSlide + _.getSlideCount();

                    _.currentDirection = 0;

                    break;

                case 'right':
                case 'up':

                    slideCount =
                        _.options.swipeToSlide ?
                            _.checkNavigable( _.currentSlide - _.getSlideCount() ) :
                            _.currentSlide - _.getSlideCount();

                    _.currentDirection = 1;

                    break;

                default:


            }

            if( direction != 'vertical' ) {

                _.slideHandler( slideCount );
                _.touchObject = {};
                _.$slider.trigger('swipe', [_, direction ]);

            }

        } else {

            if ( _.touchObject.startX !== _.touchObject.curX ) {

                _.slideHandler( _.currentSlide );
                _.touchObject = {};

            }

        }

    };

    Slick.prototype.swipeHandler = function(event) {

        var _ = this;

        if ((_.options.swipe === false) || ('ontouchend' in document && _.options.swipe === false)) {
            return;
        } else if (_.options.draggable === false && event.type.indexOf('mouse') !== -1) {
            return;
        }

        _.touchObject.fingerCount = event.originalEvent && event.originalEvent.touches !== undefined ?
            event.originalEvent.touches.length : 1;

        _.touchObject.minSwipe = _.listWidth / _.options
            .touchThreshold;

        if (_.options.verticalSwiping === true) {
            _.touchObject.minSwipe = _.listHeight / _.options
                .touchThreshold;
        }

        switch (event.data.action) {

            case 'start':
                _.swipeStart(event);
                break;

            case 'move':
                _.swipeMove(event);
                break;

            case 'end':
                _.swipeEnd(event);
                break;

        }

    };

    Slick.prototype.swipeMove = function(event) {

        var _ = this,
            edgeWasHit = false,
            curLeft, swipeDirection, swipeLength, positionOffset, touches;

        touches = event.originalEvent !== undefined ? event.originalEvent.touches : null;

        if (!_.dragging || touches && touches.length !== 1) {
            return false;
        }

        curLeft = _.getLeft(_.currentSlide);

        _.touchObject.curX = touches !== undefined ? touches[0].pageX : event.clientX;
        _.touchObject.curY = touches !== undefined ? touches[0].pageY : event.clientY;

        _.touchObject.swipeLength = Math.round(Math.sqrt(
            Math.pow(_.touchObject.curX - _.touchObject.startX, 2)));

        if (_.options.verticalSwiping === true) {
            _.touchObject.swipeLength = Math.round(Math.sqrt(
                Math.pow(_.touchObject.curY - _.touchObject.startY, 2)));
        }

        swipeDirection = _.swipeDirection();

        if (swipeDirection === 'vertical') {
            return;
        }

        if (event.originalEvent !== undefined && _.touchObject.swipeLength > 4) {
            event.preventDefault();
        }

        positionOffset = (_.options.rtl === false ? 1 : -1) * (_.touchObject.curX > _.touchObject.startX ? 1 : -1);
        if (_.options.verticalSwiping === true) {
            positionOffset = _.touchObject.curY > _.touchObject.startY ? 1 : -1;
        }


        swipeLength = _.touchObject.swipeLength;

        _.touchObject.edgeHit = false;

        if (_.options.infinite === false) {
            if ((_.currentSlide === 0 && swipeDirection === 'right') || (_.currentSlide >= _.getDotCount() && swipeDirection === 'left')) {
                swipeLength = _.touchObject.swipeLength * _.options.edgeFriction;
                _.touchObject.edgeHit = true;
            }
        }

        if (_.options.vertical === false) {
            _.swipeLeft = curLeft + swipeLength * positionOffset;
        } else {
            _.swipeLeft = curLeft + (swipeLength * (_.$list.height() / _.listWidth)) * positionOffset;
        }
        if (_.options.verticalSwiping === true) {
            _.swipeLeft = curLeft + swipeLength * positionOffset;
        }

        if (_.options.fade === true || _.options.touchMove === false) {
            return false;
        }

        if (_.animating === true) {
            _.swipeLeft = null;
            return false;
        }

        _.setCSS(_.swipeLeft);

    };

    Slick.prototype.swipeStart = function(event) {

        var _ = this,
            touches;

        _.interrupted = true;

        if (_.touchObject.fingerCount !== 1 || _.slideCount <= _.options.slidesToShow) {
            _.touchObject = {};
            return false;
        }

        if (event.originalEvent !== undefined && event.originalEvent.touches !== undefined) {
            touches = event.originalEvent.touches[0];
        }

        _.touchObject.startX = _.touchObject.curX = touches !== undefined ? touches.pageX : event.clientX;
        _.touchObject.startY = _.touchObject.curY = touches !== undefined ? touches.pageY : event.clientY;

        _.dragging = true;

    };

    Slick.prototype.unfilterSlides = Slick.prototype.slickUnfilter = function() {

        var _ = this;

        if (_.$slidesCache !== null) {

            _.unload();

            _.$slideTrack.children(this.options.slide).detach();

            _.$slidesCache.appendTo(_.$slideTrack);

            _.reinit();

        }

    };

    Slick.prototype.unload = function() {

        var _ = this;

        $('.' + _.options.classPrefix + 'cloned', _.$slider).remove();

        if (_.$dots) {
            _.$dots.remove();
        }

        if (_.$prevArrow && _.htmlExpr.test(_.options.prevArrow)) {
            _.$prevArrow.remove();
        }

        if (_.$nextArrow && _.htmlExpr.test(_.options.nextArrow)) {
            _.$nextArrow.remove();
        }

        _.$slides
            .removeClass(_.options.classPrefix + 'slide ' + _.options.classPrefix + 'active ' + _.options.classPrefix + 'visible ' + _.options.classPrefix + 'current')
            .attr('aria-hidden', 'true')
            .css('width', '');

    };

    Slick.prototype.unslick = function(fromBreakpoint) {

        var _ = this;
        _.$slider.trigger('unslick', [_, fromBreakpoint]);
        _.destroy();

    };

    Slick.prototype.updateArrows = function() {

        var _ = this,
            centerOffset;

        centerOffset = Math.floor(_.options.slidesToShow / 2);

        if ( _.options.arrows === true &&
            _.slideCount > _.options.slidesToShow &&
            !_.options.infinite ) {

            _.$prevArrow.removeClass(_.options.classPrefix + 'disabled').attr('aria-disabled', 'false');
            _.$nextArrow.removeClass(_.options.classPrefix + 'disabled').attr('aria-disabled', 'false');

            if (_.currentSlide === 0) {

                _.$prevArrow.addClass(_.options.classPrefix + 'disabled').attr('aria-disabled', 'true');
                _.$nextArrow.removeClass(_.options.classPrefix + 'disabled').attr('aria-disabled', 'false');

            } else if (_.currentSlide >= _.slideCount - _.options.slidesToShow && _.options.centerMode === false) {

                _.$nextArrow.addClass(_.options.classPrefix + 'disabled').attr('aria-disabled', 'true');
                _.$prevArrow.removeClass(_.options.classPrefix + 'disabled').attr('aria-disabled', 'false');

            } else if (_.currentSlide >= _.slideCount - 1 && _.options.centerMode === true) {

                _.$nextArrow.addClass(_.options.classPrefix + 'disabled').attr('aria-disabled', 'true');
                _.$prevArrow.removeClass(_.options.classPrefix + 'disabled').attr('aria-disabled', 'false');

            }

        }

    };

    Slick.prototype.updateDots = function() {

        var _ = this;

        if (_.$dots !== null) {

            _.$dots
                .find('li')
                .removeClass(_.options.classPrefix + 'active')
                .attr('aria-hidden', 'true');

            _.$dots
                .find('li')
                .eq(Math.floor(_.currentSlide / _.options.slidesToScroll))
                .addClass(_.options.classPrefix + 'active')
                .attr('aria-hidden', 'false');

        }

    };

    Slick.prototype.visibility = function() {

        var _ = this;

        if ( _.options.autoplay ) {

            if ( document[_.hidden] ) {

                _.interrupted = true;

            } else {

                _.interrupted = false;

            }

        }

    };

    $.fn.slick = function() {
        var _ = this,
            opt = arguments[0],
            args = Array.prototype.slice.call(arguments, 1),
            l = _.length,
            i,
            ret;
        for (i = 0; i < l; i++) {
            if (typeof opt == 'object' || typeof opt == 'undefined')
                _[i].slick = new Slick(_[i], opt);
            else
                ret = _[i].slick[opt].apply(_[i].slick, args);
            if (typeof ret != 'undefined') return ret;
        }
        return _;
    };

}));
libs/better-framework/assets/js/mustache.js000064400000045654151214002550015053 0ustar00/*!
 * mustache.js - Logic-less {{mustache}} templates with JavaScript
 * http://github.com/janl/mustache.js
 */

/*global define: false Mustache: true*/

(function defineMustache (global, factory) {
  if (typeof exports === 'object' && exports && typeof exports.nodeName !== 'string') {
    factory(exports); // CommonJS
  } else if (typeof define === 'function' && define.amd) {
    define(['exports'], factory); // AMD
  } else {
    global.Mustache = {};
    factory(global.Mustache); // script, wsh, asp
  }
}(this, function mustacheFactory (mustache) {

  var objectToString = Object.prototype.toString;
  var isArray = Array.isArray || function isArrayPolyfill (object) {
    return objectToString.call(object) === '[object Array]';
  };

  function isFunction (object) {
    return typeof object === 'function';
  }

  /**
   * More correct typeof string handling array
   * which normally returns typeof 'object'
   */
  function typeStr (obj) {
    return isArray(obj) ? 'array' : typeof obj;
  }

  function escapeRegExp (string) {
    return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&');
  }

  /**
   * Null safe way of checking whether or not an object,
   * including its prototype, has a given property
   */
  function hasProperty (obj, propName) {
    return obj != null && typeof obj === 'object' && (propName in obj);
  }

  // Workaround for https://issues.apache.org/jira/browse/COUCHDB-577
  // See https://github.com/janl/mustache.js/issues/189
  var regExpTest = RegExp.prototype.test;
  function testRegExp (re, string) {
    return regExpTest.call(re, string);
  }

  var nonSpaceRe = /\S/;
  function isWhitespace (string) {
    return !testRegExp(nonSpaceRe, string);
  }

  var entityMap = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#39;',
    '/': '&#x2F;',
    '`': '&#x60;',
    '=': '&#x3D;'
  };

  function escapeHtml (string) {
    return String(string).replace(/[&<>"'`=\/]/g, function fromEntityMap (s) {
      return entityMap[s];
    });
  }

  var whiteRe = /\s*/;
  var spaceRe = /\s+/;
  var equalsRe = /\s*=/;
  var curlyRe = /\s*\}/;
  var tagRe = /#|\^|\/|>|\{|&|=|!/;

  /**
   * Breaks up the given `template` string into a tree of tokens. If the `tags`
   * argument is given here it must be an array with two string values: the
   * opening and closing tags used in the template (e.g. [ "<%", "%>" ]). Of
   * course, the default is to use mustaches (i.e. mustache.tags).
   *
   * A token is an array with at least 4 elements. The first element is the
   * mustache symbol that was used inside the tag, e.g. "#" or "&". If the tag
   * did not contain a symbol (i.e. {{myValue}}) this element is "name". For
   * all text that appears outside a symbol this element is "text".
   *
   * The second element of a token is its "value". For mustache tags this is
   * whatever else was inside the tag besides the opening symbol. For text tokens
   * this is the text itself.
   *
   * The third and fourth elements of the token are the start and end indices,
   * respectively, of the token in the original template.
   *
   * Tokens that are the root node of a subtree contain two more elements: 1) an
   * array of tokens in the subtree and 2) the index in the original template at
   * which the closing tag for that section begins.
   */
  function parseTemplate (template, tags) {
    if (!template)
      return [];

    var sections = [];     // Stack to hold section tokens
    var tokens = [];       // Buffer to hold the tokens
    var spaces = [];       // Indices of whitespace tokens on the current line
    var hasTag = false;    // Is there a {{tag}} on the current line?
    var nonSpace = false;  // Is there a non-space char on the current line?

    // Strips all whitespace tokens array for the current line
    // if there was a {{#tag}} on it and otherwise only space.
    function stripSpace () {
      if (hasTag && !nonSpace) {
        while (spaces.length)
          delete tokens[spaces.pop()];
      } else {
        spaces = [];
      }

      hasTag = false;
      nonSpace = false;
    }

    var openingTagRe, closingTagRe, closingCurlyRe;
    function compileTags (tagsToCompile) {
      if (typeof tagsToCompile === 'string')
        tagsToCompile = tagsToCompile.split(spaceRe, 2);

      if (!isArray(tagsToCompile) || tagsToCompile.length !== 2)
        throw new Error('Invalid tags: ' + tagsToCompile);

      openingTagRe = new RegExp(escapeRegExp(tagsToCompile[0]) + '\\s*');
      closingTagRe = new RegExp('\\s*' + escapeRegExp(tagsToCompile[1]));
      closingCurlyRe = new RegExp('\\s*' + escapeRegExp('}' + tagsToCompile[1]));
    }

    compileTags(tags || mustache.tags);

    var scanner = new Scanner(template);

    var start, type, value, chr, token, openSection;
    while (!scanner.eos()) {
      start = scanner.pos;

      // Match any text between tags.
      value = scanner.scanUntil(openingTagRe);

      if (value) {
        for (var i = 0, valueLength = value.length; i < valueLength; ++i) {
          chr = value.charAt(i);

          if (isWhitespace(chr)) {
            spaces.push(tokens.length);
          } else {
            nonSpace = true;
          }

          tokens.push([ 'text', chr, start, start + 1 ]);
          start += 1;

          // Check for whitespace on the current line.
          if (chr === '\n')
            stripSpace();
        }
      }

      // Match the opening tag.
      if (!scanner.scan(openingTagRe))
        break;

      hasTag = true;

      // Get the tag type.
      type = scanner.scan(tagRe) || 'name';
      scanner.scan(whiteRe);

      // Get the tag value.
      if (type === '=') {
        value = scanner.scanUntil(equalsRe);
        scanner.scan(equalsRe);
        scanner.scanUntil(closingTagRe);
      } else if (type === '{') {
        value = scanner.scanUntil(closingCurlyRe);
        scanner.scan(curlyRe);
        scanner.scanUntil(closingTagRe);
        type = '&';
      } else {
        value = scanner.scanUntil(closingTagRe);
      }

      // Match the closing tag.
      if (!scanner.scan(closingTagRe))
        throw new Error('Unclosed tag at ' + scanner.pos);

      token = [ type, value, start, scanner.pos ];
      tokens.push(token);

      if (type === '#' || type === '^') {
        sections.push(token);
      } else if (type === '/') {
        // Check section nesting.
        openSection = sections.pop();

        if (!openSection)
          throw new Error('Unopened section "' + value + '" at ' + start);

        if (openSection[1] !== value)
          throw new Error('Unclosed section "' + openSection[1] + '" at ' + start);
      } else if (type === 'name' || type === '{' || type === '&') {
        nonSpace = true;
      } else if (type === '=') {
        // Set the tags for the next time around.
        compileTags(value);
      }
    }

    // Make sure there are no open sections when we're done.
    openSection = sections.pop();

    if (openSection)
      throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos);

    return nestTokens(squashTokens(tokens));
  }

  /**
   * Combines the values of consecutive text tokens in the given `tokens` array
   * to a single token.
   */
  function squashTokens (tokens) {
    var squashedTokens = [];

    var token, lastToken;
    for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
      token = tokens[i];

      if (token) {
        if (token[0] === 'text' && lastToken && lastToken[0] === 'text') {
          lastToken[1] += token[1];
          lastToken[3] = token[3];
        } else {
          squashedTokens.push(token);
          lastToken = token;
        }
      }
    }

    return squashedTokens;
  }

  /**
   * Forms the given array of `tokens` into a nested tree structure where
   * tokens that represent a section have two additional items: 1) an array of
   * all tokens that appear in that section and 2) the index in the original
   * template that represents the end of that section.
   */
  function nestTokens (tokens) {
    var nestedTokens = [];
    var collector = nestedTokens;
    var sections = [];

    var token, section;
    for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
      token = tokens[i];

      switch (token[0]) {
        case '#':
        case '^':
          collector.push(token);
          sections.push(token);
          collector = token[4] = [];
          break;
        case '/':
          section = sections.pop();
          section[5] = token[2];
          collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens;
          break;
        default:
          collector.push(token);
      }
    }

    return nestedTokens;
  }

  /**
   * A simple string scanner that is used by the template parser to find
   * tokens in template strings.
   */
  function Scanner (string) {
    this.string = string;
    this.tail = string;
    this.pos = 0;
  }

  /**
   * Returns `true` if the tail is empty (end of string).
   */
  Scanner.prototype.eos = function eos () {
    return this.tail === '';
  };

  /**
   * Tries to match the given regular expression at the current position.
   * Returns the matched text if it can match, the empty string otherwise.
   */
  Scanner.prototype.scan = function scan (re) {
    var match = this.tail.match(re);

    if (!match || match.index !== 0)
      return '';

    var string = match[0];

    this.tail = this.tail.substring(string.length);
    this.pos += string.length;

    return string;
  };

  /**
   * Skips all text until the given regular expression can be matched. Returns
   * the skipped string, which is the entire tail if no match can be made.
   */
  Scanner.prototype.scanUntil = function scanUntil (re) {
    var index = this.tail.search(re), match;

    switch (index) {
      case -1:
        match = this.tail;
        this.tail = '';
        break;
      case 0:
        match = '';
        break;
      default:
        match = this.tail.substring(0, index);
        this.tail = this.tail.substring(index);
    }

    this.pos += match.length;

    return match;
  };

  /**
   * Represents a rendering context by wrapping a view object and
   * maintaining a reference to the parent context.
   */
  function Context (view, parentContext) {
    this.view = view;
    this.cache = { '.': this.view };
    this.parent = parentContext;
  }

  /**
   * Creates a new context using the given view with this context
   * as the parent.
   */
  Context.prototype.push = function push (view) {
    return new Context(view, this);
  };

  /**
   * Returns the value of the given name in this context, traversing
   * up the context hierarchy if the value is absent in this context's view.
   */
  Context.prototype.lookup = function lookup (name) {
    var cache = this.cache;

    var value;
    if (cache.hasOwnProperty(name)) {
      value = cache[name];
    } else {
      var context = this, names, index, lookupHit = false;

      while (context) {
        if (name.indexOf('.') > 0) {
          value = context.view;
          names = name.split('.');
          index = 0;

          /**
           * Using the dot notion path in `name`, we descend through the
           * nested objects.
           *
           * To be certain that the lookup has been successful, we have to
           * check if the last object in the path actually has the property
           * we are looking for. We store the result in `lookupHit`.
           *
           * This is specially necessary for when the value has been set to
           * `undefined` and we want to avoid looking up parent contexts.
           **/
          while (value != null && index < names.length) {
            if (index === names.length - 1)
              lookupHit = hasProperty(value, names[index]);

            value = value[names[index++]];
          }
        } else {
          value = context.view[name];
          lookupHit = hasProperty(context.view, name);
        }

        if (lookupHit)
          break;

        context = context.parent;
      }

      cache[name] = value;
    }

    if (isFunction(value))
      value = value.call(this.view);

    return value;
  };

  /**
   * A Writer knows how to take a stream of tokens and render them to a
   * string, given a context. It also maintains a cache of templates to
   * avoid the need to parse the same template twice.
   */
  function Writer () {
    this.cache = {};
  }

  /**
   * Clears all cached templates in this writer.
   */
  Writer.prototype.clearCache = function clearCache () {
    this.cache = {};
  };

  /**
   * Parses and caches the given `template` and returns the array of tokens
   * that is generated from the parse.
   */
  Writer.prototype.parse = function parse (template, tags) {
    var cache = this.cache;
    var tokens = cache[template];

    if (tokens == null)
      tokens = cache[template] = parseTemplate(template, tags);

    return tokens;
  };

  /**
   * High-level method that is used to render the given `template` with
   * the given `view`.
   *
   * The optional `partials` argument may be an object that contains the
   * names and templates of partials that are used in the template. It may
   * also be a function that is used to load partial templates on the fly
   * that takes a single argument: the name of the partial.
   */
  Writer.prototype.render = function render (template, view, partials) {
    var tokens = this.parse(template);
    var context = (view instanceof Context) ? view : new Context(view);
    return this.renderTokens(tokens, context, partials, template);
  };

  /**
   * Low-level method that renders the given array of `tokens` using
   * the given `context` and `partials`.
   *
   * Note: The `originalTemplate` is only ever used to extract the portion
   * of the original template that was contained in a higher-order section.
   * If the template doesn't use higher-order sections, this argument may
   * be omitted.
   */
  Writer.prototype.renderTokens = function renderTokens (tokens, context, partials, originalTemplate) {
    var buffer = '';

    var token, symbol, value;
    for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
      value = undefined;
      token = tokens[i];
      symbol = token[0];

      if (symbol === '#') value = this.renderSection(token, context, partials, originalTemplate);
      else if (symbol === '^') value = this.renderInverted(token, context, partials, originalTemplate);
      else if (symbol === '>') value = this.renderPartial(token, context, partials, originalTemplate);
      else if (symbol === '&') value = this.unescapedValue(token, context);
      else if (symbol === 'name') value = this.escapedValue(token, context);
      else if (symbol === 'text') value = this.rawValue(token);

      if (value !== undefined)
        buffer += value;
    }

    return buffer;
  };

  Writer.prototype.renderSection = function renderSection (token, context, partials, originalTemplate) {
    var self = this;
    var buffer = '';
    var value = context.lookup(token[1]);

    // This function is used to render an arbitrary template
    // in the current context by higher-order sections.
    function subRender (template) {
      return self.render(template, context, partials);
    }

    if (!value) return;

    if (isArray(value)) {
      for (var j = 0, valueLength = value.length; j < valueLength; ++j) {
        buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate);
      }
    } else if (typeof value === 'object' || typeof value === 'string' || typeof value === 'number') {
      buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate);
    } else if (isFunction(value)) {
      if (typeof originalTemplate !== 'string')
        throw new Error('Cannot use higher-order sections without the original template');

      // Extract the portion of the original template that the section contains.
      value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender);

      if (value != null)
        buffer += value;
    } else {
      buffer += this.renderTokens(token[4], context, partials, originalTemplate);
    }
    return buffer;
  };

  Writer.prototype.renderInverted = function renderInverted (token, context, partials, originalTemplate) {
    var value = context.lookup(token[1]);

    // Use JavaScript's definition of falsy. Include empty arrays.
    // See https://github.com/janl/mustache.js/issues/186
    if (!value || (isArray(value) && value.length === 0))
      return this.renderTokens(token[4], context, partials, originalTemplate);
  };

  Writer.prototype.renderPartial = function renderPartial (token, context, partials) {
    if (!partials) return;

    var value = isFunction(partials) ? partials(token[1]) : partials[token[1]];
    if (value != null)
      return this.renderTokens(this.parse(value), context, partials, value);
  };

  Writer.prototype.unescapedValue = function unescapedValue (token, context) {
    var value = context.lookup(token[1]);
    if (value != null)
      return value;
  };

  Writer.prototype.escapedValue = function escapedValue (token, context) {
    var value = context.lookup(token[1]);
    if (value != null)
      return mustache.escape(value);
  };

  Writer.prototype.rawValue = function rawValue (token) {
    return token[1];
  };

  mustache.name = 'mustache.js';
  mustache.version = '2.2.1';
  mustache.tags = [ '{{', '}}' ];

  // All high-level mustache.* functions use this writer.
  var defaultWriter = new Writer();

  /**
   * Clears all cached templates in the default writer.
   */
  mustache.clearCache = function clearCache () {
    return defaultWriter.clearCache();
  };

  /**
   * Parses and caches the given template in the default writer and returns the
   * array of tokens it contains. Doing this ahead of time avoids the need to
   * parse templates on the fly as they are rendered.
   */
  mustache.parse = function parse (template, tags) {
    return defaultWriter.parse(template, tags);
  };

  /**
   * Renders the `template` with the given `view` and `partials` using the
   * default writer.
   */
  mustache.render = function render (template, view, partials) {
    if (typeof template !== 'string') {
      throw new TypeError('Invalid template! Template should be a "string" ' +
                          'but "' + typeStr(template) + '" was given as the first ' +
                          'argument for mustache#render(template, view, partials)');
    }

    return defaultWriter.render(template, view, partials);
  };

  // This is here for backwards compatibility with 0.4.x.,
  /*eslint-disable */ // eslint wants camel cased function name
  mustache.to_html = function to_html (template, view, partials, send) {
    /*eslint-enable*/

    var result = mustache.render(template, view, partials);

    if (isFunction(send)) {
      send(result);
    } else {
      return result;
    }
  };

  // Export the escaping function so that the user may override it.
  // See https://github.com/janl/mustache.js/issues/244
  mustache.escape = escapeHtml;

  // Export these mainly for testing, but also for advanced usage.
  mustache.Scanner = Scanner;
  mustache.Context = Context;
  mustache.Writer = Writer;

}));
libs/better-framework/assets/js/better-modals.js000064400000042651151214002550015776 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */

(function ($) {

    var Better_Framework_Modals = {

        loaded: false,

        init: function () {

            var Better_Icon_Modal = $('#better-icon-modal').on('opening', function (a, b, c, d) {
                var $this = $(this),
                    zIndex = 1.5e5;

                $this.closest('.remodal-wrapper').css('z-index', zIndex + 1);
                $(".remodal-overlay").css('z-index', zIndex);
            }).remodal({
                hashTracking: false,
                closeOnEscape: true
            });

            $(document).on('click', '.bf-icon-modal-handler', function (e) {

                e.preventDefault();

                if (!Better_Icon_Modal) {
                    console.error('icons modal not found!');

                    return;
                }

                var $field_container = $(this),
                    $input = $field_container.find('input.icon-input'),
                    $modal = $('#better-icon-modal'),
                    $search_input = $modal.find('input.better-icons-search-input');

                // Summarize data
                var selected = {
                    id: $input.attr('value'),
                    label: $input.data('label')
                };

                $modal.find('.icons-list .icon-select-option[data-value="' + selected.id + '"]').addClass('selected');

                Better_Icon_Modal.$handler = $(this);

                icons_modal_reset_all_filters();

                Better_Icon_Modal.open();

                $search_input.focus();

            });


            $(document).on('closing', '.better-modal.icon-modal', function (e) {

                // No icon selected
                if ($('.better-modal.icon-modal .icons-list .icon-select-option.selected').length == 0) {
                    return;
                }

                var $field_container = Better_Icon_Modal.$handler,
                    $selected_container = $field_container.find('.selected-option'),
                    $input = $field_container.find('input.icon-input'),
                    $input_width = $field_container.find('input.icon-input-width'),
                    $input_height = $field_container.find('input.icon-input-height'),
                    $input_type = $field_container.find('input.icon-input-type'),
                    $input_font_code = $field_container.find('input.icon-input-font-code'),
                    $selected_icon = $('.better-modal.icon-modal .icons-list .icon-select-option.selected');

                // Summarize data
                var selected = {
                    id: $selected_icon.data('value'),
                    label: $selected_icon.data('label'),
                    code: $selected_icon.data('font-code'),
                    width: '',
                    height: '',
                    type: ''
                };

                if ($selected_icon.hasClass('custom-icon')) {
                    selected.label = 'custom ';
                    selected.width = $('.better-modal.icon-modal .icon-fields input[name="icon-width"]').val();
                    selected.height = $('.better-modal.icon-modal .custom-icon-fields .icon-fields input[name="icon-height"]').val();
                    selected.type = $selected_icon.data('type');
                    selected.id = $selected_icon.data('custom-icon');
                } else {
                    selected.type = $selected_icon.data('type');
                }

                // Update view data
                if (selected.id != '') {

                    if (selected.type == 'custom-icon') {
                        $selected_container.html('<i class="bf-icon bf-custom-icon "><img src="' + selected.id + '"></i> ' + better_framework_loc.translation.icon_modal.custom_icon);
                    } else {
                        $selected_container.html('<i class="bf-icon fa ' + selected.id + '"></i>' + selected.label);
                    }
                } else {
                    $selected_container.html(selected.label);
                }

                var input;
                // Update field data
                $input.attr('label', selected.label);

                input = $input_width.val(selected.width).change()[0];
                input && input.dispatchEvent(new Event('input'));

                input = $input_height.val(selected.height).change()[0];
                input && input.dispatchEvent(new Event('input'));

                input = $input_type.val(selected.type).change()[0];
                input && input.dispatchEvent(new Event('input'));

                input = $input_font_code.val(selected.code).change()[0];
                input && input.dispatchEvent(new Event('input'));

                input = $input.val(selected.id).change()[0];
                input && input.dispatchEvent(new Event('input'));


                custom_icon_hide();
                $(this).find('.icon-select-option.selected').removeClass('selected');

            });

            $(document).on('click', '.better-modal.icon-modal .icons-list .icon-select-option', function () {

                $('.better-modal.icon-modal  .icons-list').find('.icon-select-option.selected').removeClass('selected');

                if ($(this).hasClass('custom-icon')) {

                    var $this = $(this),
                        $modal = $('#better-icon-modal');

                    $modal.find('.custom-icon-fields .icon-preview').attr('src', $this.data('custom-icon')).css({
                        'max-width': $this.data('width') + 'px',
                        'max-height': 'auto'
                    });

                    $modal.find('.icon-fields input[name="icon-width"]').val($this.data('width'));
                    $modal.find('.icon-fields input[name="icon-height"]').val('');

                    $(this).toggleClass('selected');

                    custom_icon_show();

                } else {
                    $(this).toggleClass('selected');
                    Better_Icon_Modal.close();
                }
            });

            $(document).on('click', '.better-modal.icon-modal .icons-list .icon-select-option .delete-icon', function (e) {
                e.stopPropagation();
                $.ajax({
                    type: 'POST',
                    dataType: 'json',
                    url: better_framework_loc.bf_ajax_url,
                    data: {
                        action: 'bf_ajax',
                        reqID: 'remove_custom_icon',
                        nonce: better_framework_loc.nonce,
                        icon: $(this).closest('.icon-select-option').data('id')
                    }
                });

                $(this).closest('.icon-select-option').remove();

                if ($('.better-modal.icon-modal .icons-list.custom-icons-list .icon-select-option').length == 0) {
                    $('.better-modal.icon-modal .no-custom-icon').removeClass('hidden');
                } else {
                    $('.better-modal.icon-modal .no-custom-icon').addClass('hidden');
                }

            });

            $(document).on('click', '.better-modal.icon-modal .upload-custom-icon-container .section-footer .bf-button', function () {
                Better_Icon_Modal.close();
            });

            $('.better-modal.icon-modal .icons-container').mCustomScrollbar({
                theme: 'dark',
                live: true,
                scrollInertia: 2000
            });

            // Category Filter
            $(document).on('click', '.better-icons-category-list .icon-category', function () {

                var $this = $(this),
                    $modal = $('#better-icon-modal'),
                    $options_list = $modal.find('.icons-list.font-icons'),
                    $search_input = $modal.find('input.better-icons-search-input');

                if ($this.hasClass('selected')) {
                    return;
                }

                // clear search input
                $search_input.val('').parent().removeClass('show-clean').find('.clean').addClass('fa-search').removeClass('fa-times-circle');

                $modal.find('.better-icons-category-list li.selected').removeClass('selected');

                $this.addClass('selected');

                if ($this.attr('id') === 'cat-all') {

                    $options_list.find('li').show();

                } else {

                    $options_list.find('li').each(function () {

                        if ($(this).hasClass('default-option'))
                            return true;

                        var _cats = $(this).data('categories').split(' ');

                        if (_cats.indexOf($this.attr('id')) < 0) {
                            $(this).hide();
                        } else {
                            $(this).show();
                        }

                    });

                }
                return false;

            });


            // Search
            $(document).on('keyup', '#better-icon-modal .better-icons-search-input', function () {

                if ($(this).val() != '') {
                    $(this).parent().addClass('show-clean').find('.clean').removeClass('fa-search').addClass('fa-times-circle');
                } else {
                    $(this).parent().removeClass('show-clean').find('.clean').addClass('fa-search').removeClass('fa-times-circle');
                }

                icons_modal_reset_cats_filter();

                icons_modal_text_filter($(this).val());

                return false;

            });


            $(document).on('click', '#better-icon-modal .better-icons-search .clean', function () {

                var $modal = $('#better-icon-modal'),
                    $search_input = $modal.find('input.better-icons-search-input');

                icons_modal_text_filter('');

                $search_input.val('').parent().removeClass('show-clean').find('.clean').addClass('fa-search').removeClass('fa-times-circle');

            });

            $(document).on('click', '.better-modal.icon-modal .upload-custom-icon', function () {
                var _this = $(this);

                var custom_uploader;

                var media_title = _this.data('media-title');
                var media_button_text = _this.data('button-text');

                if (custom_uploader) {
                    custom_uploader.open();
                    return;
                }

                custom_uploader = wp.media.frames.file_frame = wp.media({
                    title: media_title,
                    button: {
                        text: media_button_text
                    },
                    multiple: false//,
                    //library: { type : 'image'}
                });

                custom_uploader.on('select', function () {

                    var attachment = custom_uploader.state().get('selection').first().toJSON();

                    var icon = {
                        'type': 'custom-icon',
                        'icon': attachment.url,
                        'width': attachment.width,
                        'height': attachment.height
                    };

                    custom_icon_show_loading();

                    var $modal = $('#better-icon-modal');

                    $modal.find('.better-icons-category-list li.selected').removeClass('selected');

                    $modal.find('.custom-icon-fields .icon-preview').attr('src', icon.icon).css({
                        'max-width': icon.width + 'px',
                        'max-height': 'auto'
                    });

                    $modal.find('.icon-fields input[name="icon-width"]').val(icon.width);
                    $modal.find('.icon-fields input[name="icon-height"]').val('');

                    $modal.find('.icons-list.custom-icons-list').append('<li data-id="icon-" class="icon-select-option custom-icon selected" data-custom-icon="' + icon.icon + '" data-width="' + icon.width + '" data-height="' + icon.height + '" data-type="custom-icon"> \
                <i class="bf-custom-icon"><img src="' + icon.icon + '"></i><i class="fa fa-close delete-icon"></i></li>');

                    custom_icon_show();

                    $.ajax({
                        type: 'POST',
                        dataType: 'json',
                        url: better_framework_loc.bf_ajax_url,
                        data: {
                            action: 'bf_ajax',
                            reqID: 'add_custom_icon',
                            nonce: better_framework_loc.nonce,
                            icon: icon
                        }
                    });
                });

                custom_uploader.open();

                if ($('.better-modal.icon-modal .icons-list.custom-icons-list .icon-select-option').length == 0) {
                    $('.better-modal.icon-modal .no-custom-icon').removeClass('hidden');
                } else {
                    $('.better-modal.icon-modal .no-custom-icon').addClass('hidden');
                }

                return false;
            });


            $(document).on('click', '.better-modal.icon-modal .upload-custom-icon-container .close-custom-icon', function () {
                custom_icon_hide();
            });

            $(document).on('keyup', '.better-modal.icon-modal .upload-custom-icon-container .custom-icon-fields .icon-fields input[name="icon-width"]', function () {
                $('.better-modal.icon-modal .custom-icon-fields .icon-preview').css({
                    'max-width': $(this).val() + 'px'
                });
            });

            $(document).on('keyup', '.better-modal.icon-modal .upload-custom-icon-container .custom-icon-fields .icon-fields input[name="icon-height"]', function () {
                $('.better-modal.icon-modal .custom-icon-fields .icon-preview').css({
                    'max-height': $(this).val() + 'px'
                });
            });


            function custom_icon_show_loading() {
                $('#better-icon-modal .upload-custom-icon-container').addClass('show show-loading');
            }

            function custom_icon_hide_loading() {
                $('#better-icon-modal .upload-custom-icon-container').addClass('show').removeClass('show-loading');
            }

            function custom_icon_hide() {
                $('#better-icon-modal .upload-custom-icon-container').removeClass('show show-loading');
                $('#better-icon-modal .better-icons-search').removeClass('hidden');
            }

            function custom_icon_show() {
                $('#better-icon-modal .upload-custom-icon-container').addClass('show').removeClass('show-loading');
                $('#better-icon-modal .better-icons-search').addClass('hidden');
            }


            // Used for clearing all filters
            function icons_modal_reset_all_filters() {

                var $modal = $('#better-icon-modal'),
                    $search_input = $modal.find('input.better-icons-search-input');

                $search_input.val('').parent().removeClass('show-clean').find('.clean').addClass('fa-search').removeClass('fa-times-circle');

                icons_modal_text_filter('');

                icons_modal_reset_cats_filter();
            }


            // Used for clearing just category filter
            function icons_modal_reset_cats_filter() {

                var $modal = $('#better-icon-modal'),
                    $options_list = $modal.find('.icons-list');

                $options_list.find('.icon-select-option').show();

                $modal.find('.better-icons-category-list li').removeClass('selected');
                $modal.find('.better-icons-category-list li#cat-all').addClass('selected');
            }


            // filters element with one text
            function icons_modal_text_filter($search_text) {

                var $modal = $('#better-icon-modal'),
                    $options_list = $modal.find('.icons-list');

                if ($search_text) {
                    $options_list.find(".label:not(:Contains(" + $search_text + "))").parent().hide();
                    $options_list.find(".label:Contains(" + $search_text + ")").parent().show();
                } else {
                    $options_list.find("li").show();
                }

            }


            this.loaded = true;
        }
    }
// load when ready
    $(function () {

        Better_Framework_Modals.init();
    });


    $(window).load(function () {

        if (!Better_Framework_Modals.loaded) {

            Better_Framework_Modals.init();
        }
    });

})(jQuery);

// res : http://stackoverflow.com/questions/1766299/make-search-input-to-filter-through-list-jquery
// custom css expression for a case-insensitive contains()
(function ($) {
    jQuery.expr[':'].Contains = function (a, i, m) {
        return (a.textContent || a.innerText || "").toUpperCase().indexOf(m[3].toUpperCase()) >= 0;
    };
})(jQuery);
libs/better-framework/assets/js/admin-plugins.js000064400000513325151214002550016004 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */

// TODO: Clean up this file

/*!
 * jQuery Cookie Plugin v1.3.1
 * https://github.com/carhartl/jquery-cookie
 *
 * Copyright 2013 Klaus Hartl
 * Released under the MIT license
 */
(function(b){if(typeof define==="function"&&define.amd){define(["jquery"],b)}else{b(jQuery)}}(function(j){var h=/\+/g;function k(a){return a}function g(a){return decodeURIComponent(a.replace(h," "))}function i(b){if(b.indexOf('"')===0){b=b.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,"\\")}try{return l.json?JSON.parse(b):b}catch(a){}}var l=j.cookie=function(c,d,A){if(d!==undefined){A=j.extend({},l.defaults,A);if(typeof A.expires==="number"){var b=A.expires,B=A.expires=new Date();B.setDate(B.getDate()+b)}d=l.json?JSON.stringify(d):String(d);return(document.cookie=[l.raw?c:encodeURIComponent(c),"=",l.raw?d:encodeURIComponent(d),A.expires?"; expires="+A.expires.toUTCString():"",A.path?"; path="+A.path:"",A.domain?"; domain="+A.domain:"",A.secure?"; secure":""].join(""))}var y=l.raw?k:g;var a=document.cookie.split("; ");var z=c?undefined:{};for(var e=0,t=a.length;e<t;e++){var f=a[e].split("=");var x=y(f.shift());var w=y(f.join("="));if(c&&c===x){z=i(w);break}if(!c){z[x]=i(w)}}return z};l.defaults={};j.removeCookie=function(a,b){if(j.cookie(a)!==undefined){j.cookie(a,"",j.extend({},b,{expires:-1}));return true}return false}}));!function(H,F,G){var E,J="sortable2",D={drag:true,drop:true,exclude:"",nested:true,vertical:true},x={afterMove:function(a,b){},containerSelector:"ol, ul",distance:0,handle:"",itemSelector:"li",isValidTarget:function(a,b){return true},onCancel:function(b,c,a){},onDrag:function(b,c,a){b.css(c)},onDragStart:function(b,c,a){b.css({height:b.height(),width:b.width()});b.addClass("dragged");H("body").addClass("dragging")},onDrop:function(b,c,a){b.removeClass("dragged").removeAttr("style");H("body").removeClass("dragging")},onMousedown:function(c,a,b){a.preventDefault()},placeholder:'<li class="placeholder"/>',pullPlaceholder:true,serialize:function(a,b,c){var e=H.extend({},a.data());if(c){return b}else{if(b[0]){e.children=b;delete e.subContainer}}delete e.sortable;return e},tolerance:0},u={},A=0;if("ontouchstart" in F){E={start:"touchstart.sortable",end:"touchend.sortable touchcancel.sortable",move:"touchmove.sortable"}}else{E={start:"mousedown.sortable",end:"mouseup.sortable",move:"mousemove.sortable"}}function t(b,c){var e=Math.max(0,b[0]-c[0],c[0]-b[1]),a=Math.max(0,b[2]-c[1],c[1]-b[3]);return e+a}function d(a,b,c){var e=a.slice((c||b)+1||a.length);a.length=b<0?a.length+b:b;return a.push.apply(a,e)}function y(h,b,e){var f=h.length,g=e?"offset":"position";while(f--){var c=h[f].el?h[f].el:H(h[f]),a=c[g]();b[f]=[a.left,a.left+c.outerWidth(true),a.top,a.top+c.outerHeight(true)]}}function I(a,c){var b=c.offset();return{left:a.left-b.left,top:a.top-b.top}}function v(c,a,e){a=[a.left,a.top];e=e&&[e.left,e.top];var b,f=c.length,g=[];while(f--){b=c[f];g[f]=[f,t(b,a),e&&t(b,e)]}g=g.sort(function(h,i){return i[1]-h[1]||i[2]-h[2]||i[0]-h[0]});return g}function w(a,f,h,g){var c=a.find(f),b=c.length;while(b--){var e=c.eq(b).data(J);if(e){e[h](g)}}}function z(a){this.options=H.extend({},x,a);this.containers=[];this.childGroups=[];this.scrolledProxy=H.proxy(this.scrolled,this);this.dragProxy=H.proxy(this.drag,this);this.dropProxy=H.proxy(this.drop,this);if(this.options.parentGroup){this.options.parentGroup.childGroups.push(this)}else{this.placeholder=H(this.options.placeholder);if(!a.isValidTarget){this.options.isValidTarget=G}}}z.get=function(a){if(!u[a.group]){if(!a.group){a.group=A++}u[a.group]=new z(a)}return u[a.group]};z.prototype={dragInit:function(a,b){this.$document=H(b.el[0].ownerDocument);this.toggleListeners("on");this.item=H(a.target).closest(this.options.itemSelector);this.itemContainer=b;this.setPointer(a);this.options.onMousedown(this.item,a,x.onMousedown)},drag:function(a){if(!this.dragging){if(!this.distanceMet(a)){return}w(this.item,this.options.containerSelector,"disable",true);this.options.onDragStart(this.item,this.itemContainer,x.onDragStart);this.item.before(this.placeholder);this.dragging=true}this.setPointer(a);this.options.onDrag(this.item,I(this.pointer,this.item.offsetParent()),x.onDrag);var f=a.pageX,e=a.pageY,b=this.sameResultBox,c=this.options.tolerance;if(!b||b.top-c>e||b.bottom+c<e||b.left-c>f||b.right+c<f){if(!this.searchValidTarget()){this.placeholder.detach()}}},drop:function(a){this.toggleListeners("off");if(this.dragging){if(this.placeholder.closest("html")[0]){this.placeholder.before(this.item).detach()}else{this.options.onCancel(this.item,this.itemContainer,x.onCancel)}this.options.onDrop(this.item,this.getContainer(this.item),x.onDrop);w(this.item,this.options.containerSelector,"enable",true);this.clearDimensions();this.clearOffsetParent();this.lastAppendedItem=this.sameResultBox=G;this.dragging=false}this.item=G},searchValidTarget:function(i,b){if(!i){i=this.relativePointer||this.pointer;b=this.lastRelativePointer||this.lastPointer}var f=v(this.getContainerDimensions(),i,b),c=f.length;while(c--){var e=f[c][0],h=f[c][1];if(!h||this.options.pullPlaceholder){var g=this.containers[e];if(!this.$getOffsetParent()){var a=g.getItemOffsetParent();i=I(i,a);b=I(b,a)}if(g.searchValidTarget(i,b)){return true}}}},movePlaceholder:function(e,c,a,f){var b=this.lastAppendedItem;if(!f&&b&&b[0]===c[0]){return}c[a](this.placeholder);this.lastAppendedItem=c;this.sameResultBox=f;this.options.afterMove(this.placeholder,e)},getContainerDimensions:function(){if(!this.containerDimensions){y(this.containers,this.containerDimensions=[],!this.$getOffsetParent())}return this.containerDimensions},getContainer:function(a){return a.closest(this.options.containerSelector).data(J)},$getOffsetParent:function(){if(this.offsetParent===G){var b=this.containers.length-1,a=this.containers[b].getItemOffsetParent();if(!this.options.parentGroup){while(b--){if(a[0]!=this.containers[b].getItemOffsetParent()[0]){a=false;break}}}this.offsetParent=a}return this.offsetParent},clearOffsetParent:function(){this.offsetParent=G},setPointer:function(b){var a={left:b.pageX,top:b.pageY};if(this.$getOffsetParent()){var c=I(a,this.$getOffsetParent());this.lastRelativePointer=this.relativePointer;this.relativePointer=c}this.lastPointer=this.pointer;this.pointer=a},distanceMet:function(a){return(Math.max(Math.abs(this.pointer.left-a.pageX),Math.abs(this.pointer.top-a.pageY))>=this.options.distance)},addContainer:function(a){this.containers.push(a)},removeContainer:function(b){var a=H.inArray(b,this.containers);a!==-1&&d(this.containers,a)},scrolled:function(a){this.clearDimensions();this.clearOffsetParent()},toggleListeners:function(a){this.$document[a](E.move,this.dragProxy)[a](E.end,this.dropProxy)[a]("scroll.sortable",this.scrolledProxy)},clearDimensions:function(){this.containerDimensions=G;var a=this.containers.length;while(a--){this.containers[a].itemDimensions=G}a=this.childGroups.length;while(a--){this.childGroups[a].clearDimensions()}}};function C(a,b){this.el=a;this.childGroups=[];this.floatRight=false;this.dragInitProxy=H.proxy(this.dragInit,this);this.options=H.extend({},D,b);this.group=z.get(this.options);this.rootGroup=this.options.rootGroup=this.options.rootGroup||this.group;this.parentGroup=this.options.parentGroup=this.options.parentGroup||this.group;this.handle=this.rootGroup.options.handle||this.rootGroup.options.itemSelector;this.enable(true)}C.prototype={dragInit:function(a){var b=this.rootGroup;if(!b.item&&a.which===1&&this.options.drag&&!H(a.target).is(this.options.exclude)){b.dragInit(a,this)}},searchValidTarget:function(b,i){var f=v(this.getItemDimensions(),b,i),h=f.length,e=this.rootGroup,c=!e.options.isValidTarget||e.options.isValidTarget(e.item,this);if(!h&&c){e.movePlaceholder(this,this.el,"append");return true}else{while(h--){var g=f[h][0],j=f[h][1];if(!j&&this.options.nested&&this.getContainerGroup(g)){var a=this.getContainerGroup(g).searchValidTarget(b,i);if(a){return true}}else{if(c){this.movePlaceholder(g,b);return true}}}}},movePlaceholder:function(e,m){var n=H(this.items[e]),g=this.itemDimensions[e],f="after",l=n.outerWidth(),a=n.outerHeight(),h=n.offset(),k={left:h.left,right:h.left+l,top:h.top,bottom:h.top+a};if(this.options.vertical){var b=(g[2]+g[3])/2,c=m.top<=b;if(c){f="before";k.bottom-=a/2}else{k.top+=a/2}}else{var j=(g[0]+g[1])/2,i=m.left<=j;if(i!=this.floatRight){f="before";k.right-=l/2}else{k.left+=l/2}}this.rootGroup.movePlaceholder(this,n,f,k)},getItemDimensions:function(){if(!this.itemDimensions){this.items=this.$getChildren(this.el,"item").filter(":not(.dragged)").get();y(this.items,this.itemDimensions=[])}return this.itemDimensions},getItemOffsetParent:function(){var a,b=this.el;if(b.css("position")==="relative"||b.css("position")==="absolute"||b.css("position")==="fixed"){a=b}else{a=b.offsetParent()}return a},getContainerGroup:function(b){var a=H.data(this.items[b],"subContainer");if(a===G){var c=this.$getChildren(this.items[b],"container");a=false;if(c[0]){var e=H.extend({},this.options,{parentGroup:this.group,group:A++});a=c[J](e).data(J).group}H.data(this.items[b],"subContainer",a)}return a},$getChildren:function(a,b){return H(a).children(this.rootGroup.options[b+"Selector"])},_serialize:function(b,c){var a=this,f=c?"item":"container",e=this.$getChildren(b,f).not(this.options.exclude).map(function(){return a._serialize(H(this),!c)}).get();return this.rootGroup.options.serialize(b,e,c)}};var B={enable:function(a){if(this.options.drop){this.group.addContainer(this)}if(!a){w(this.el,this.options.containerSelector,"enable",true)}this.el.on(E.start,this.handle,this.dragInitProxy)},disable:function(a){if(this.options.drop){this.group.removeContainer(this)}if(!a){w(this.el,this.options.containerSelector,"disable",true)}this.el.off(E.start)},serialize:function(){return this._serialize(this.el,true)}};H.extend(C.prototype,B);H.fn[J]=function(b){var a=Array.prototype.slice.call(arguments,1);return this.map(function(){var c=H(this),e=c.data(J);if(e&&B[b]){return B[b].apply(e,a)||this}else{if(!e&&(b===G||typeof b==="object")){c.data(J,new C(c,b))}}return this})}}(jQuery,window);

/*!
 * jQuery blockUI plugin
 * Version 2.59.0-2013.04.05
 * @requires jQuery v1.7 or later
 *
 * Examples at: http://malsup.com/jquery/block/
 * Copyright (c) 2007-2013 M. Alsup
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * Thanks to Amir-Hossein Sobhi for some excellent contributions!
 */
(function(){function b(x){x.fn._fadeIn=x.fn.fadeIn;var D=x.noop||function(){};var t=/MSIE/.test(navigator.userAgent);var B=/MSIE 6.0/.test(navigator.userAgent)&&!/MSIE 8.0/.test(navigator.userAgent);var w=document.documentMode||0;var A=x.isFunction(document.createElement("div").style.setExpression);x.blockUI=function(c){C(window,c)};x.unblockUI=function(c){y(window,c)};x.growlUI=function(c,e,d,g){var f=x('<div class="growlUI"></div>');if(c){f.append("<h1>"+c+"</h1>")}if(e){f.append("<h2>"+e+"</h2>")}if(d===undefined){d=3000}x.blockUI({message:f,fadeIn:700,fadeOut:1000,centerY:false,timeout:d,showOverlay:false,onUnblock:g,css:x.blockUI.defaults.growlCSS})};x.fn.block=function(c){if(this[0]===window){x.blockUI(c);return this}var d=x.extend({},x.blockUI.defaults,c||{});this.each(function(){var e=x(this);if(d.ignoreIfBlocked&&e.data("blockUI.isBlocked")){return}e.unblock({fadeOut:0})});return this.each(function(){if(x.css(this,"position")=="static"){this.style.position="relative";x(this).data("blockUI.static",true)}this.style.zoom=1;C(this,c)})};x.fn.unblock=function(c){if(this[0]===window){x.unblockUI(c);return this}return this.each(function(){y(this,c)})};x.blockUI.version=2.59;x.blockUI.defaults={message:"<h1>Please wait...</h1>",title:null,draggable:true,theme:false,css:{padding:0,margin:0,width:"30%",top:"40%",left:"35%",textAlign:"center",color:"#000",border:"3px solid #aaa",backgroundColor:"#fff",cursor:"wait"},themedCSS:{width:"30%",top:"40%",left:"35%"},overlayCSS:{backgroundColor:"#000",opacity:0.6,cursor:"wait"},cursorReset:"default",growlCSS:{width:"350px",top:"10px",left:"",right:"10px",border:"none",padding:"5px",opacity:0.6,cursor:"default",color:"#fff",backgroundColor:"#000","-webkit-border-radius":"10px","-moz-border-radius":"10px","border-radius":"10px"},iframeSrc:/^https/i.test(window.location.href||"")?"javascript:false":"about:blank",forceIframe:false,baseZ:1000,centerX:true,centerY:true,allowBodyStretch:true,bindEvents:true,constrainTabKey:true,fadeIn:200,fadeOut:400,timeout:0,showOverlay:true,focusInput:true,onBlock:null,onUnblock:null,onOverlayClick:null,quirksmodeOffsetHack:4,blockMsgClass:"blockMsg",ignoreIfBlocked:false};var E=null;var z=[];function C(S,p){var V,e;var Y=(S==window);var l=(p&&p.message!==undefined?p.message:undefined);p=x.extend({},x.blockUI.defaults,p||{});if(p.ignoreIfBlocked&&x(S).data("blockUI.isBlocked")){return}p.overlayCSS=x.extend({},x.blockUI.defaults.overlayCSS,p.overlayCSS||{});V=x.extend({},x.blockUI.defaults.css,p.css||{});if(p.onOverlayClick){p.overlayCSS.cursor="pointer"}e=x.extend({},x.blockUI.defaults.themedCSS,p.themedCSS||{});l=l===undefined?p.message:l;if(Y&&E){y(window,{fadeOut:0})}if(l&&typeof l!="string"&&(l.parentNode||l.jquery)){var j=l.jquery?l[0]:l;var c={};x(S).data("blockUI.history",c);c.el=j;c.parent=j.parentNode;c.display=j.style.display;c.position=j.style.position;if(c.parent){c.parent.removeChild(j)}}x(S).data("blockUI.onUnblock",p.onUnblock);var W=p.baseZ;var f,g,h,m;if(t||p.forceIframe){f=x('<iframe class="blockUI" style="z-index:'+(W++)+';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+p.iframeSrc+'"></iframe>')}else{f=x('<div class="blockUI" style="display:none"></div>')}if(p.theme){g=x('<div class="blockUI blockOverlay ui-widget-overlay" style="z-index:'+(W++)+';display:none"></div>')}else{g=x('<div class="blockUI blockOverlay" style="z-index:100000;display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>')}if(p.theme&&Y){m='<div class="blockUI '+p.blockMsgClass+' blockPage ui-dialog ui-widget ui-corner-all" style="z-index:'+(W+10)+';display:none;position:fixed">';if(p.title){m+='<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(p.title||"&nbsp;")+"</div>"}m+='<div class="ui-widget-content ui-dialog-content"></div>';m+="</div>"}else{if(p.theme){m='<div class="blockUI '+p.blockMsgClass+' blockElement ui-dialog ui-widget ui-corner-all" style="z-index:'+(W+10)+';display:none;position:absolute">';if(p.title){m+='<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(p.title||"&nbsp;")+"</div>"}m+='<div class="ui-widget-content ui-dialog-content"></div>';m+="</div>"}else{if(Y){m='<div class="blockUI '+p.blockMsgClass+' blockPage" style="z-index:'+(W+10)+';display:none;position:fixed"></div>'}else{m='<div class="blockUI '+p.blockMsgClass+' blockElement" style="z-index:'+(W+10)+';display:none;position:absolute"></div>'}}}h=x(m);if(l){if(p.theme){h.css(e);h.addClass("ui-widget-content")}else{h.css(V)}}if(!p.theme){g.css(p.overlayCSS)}g.css("position",Y?"fixed":"absolute");if(t||p.forceIframe){f.css("opacity",0)}var Z=[f,g,h],d=Y?x("body"):x(S);x.each(Z,function(){this.appendTo(d)});if(p.theme&&p.draggable&&x.fn.draggable){h.draggable({handle:".ui-dialog-titlebar",cancel:"li"})}var n=A&&(!x.support.boxModel||x("object,embed",Y?null:S).length>0);if(B||n){if(Y&&p.allowBodyStretch&&x.support.boxModel){x("html,body").css("height","100%")}if((B||!x.support.boxModel)&&!Y){var q=s(S,"borderTopWidth"),i=s(S,"borderLeftWidth");var aa=q?"(0 - "+q+")":0;var U=i?"(0 - "+i+")":0}x.each(Z,function(J,G){var K=G[0].style;K.position="absolute";if(J<2){if(Y){K.setExpression("height","Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.support.boxModel?0:"+p.quirksmodeOffsetHack+') + "px"')}else{K.setExpression("height",'this.parentNode.offsetHeight + "px"')}if(Y){K.setExpression("width",'jQuery.support.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"')}else{K.setExpression("width",'this.parentNode.offsetWidth + "px"')}if(U){K.setExpression("left",U)}if(aa){K.setExpression("top",aa)}}else{if(p.centerY){if(Y){K.setExpression("top",'(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"')}K.marginTop=0}else{if(!p.centerY&&Y){var I=(p.css&&p.css.top)?parseInt(p.css.top,10):0;var H="((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "+I+') + "px"';K.setExpression("top",H)}}}})}if(l){if(p.theme){h.find(".ui-widget-content").append(l)}else{h.append(l)}if(l.jquery||l.nodeType){x(l).show()}}if((t||p.forceIframe)&&p.showOverlay){f.show()}if(p.fadeIn){var k=p.onBlock?p.onBlock:D;var T=(p.showOverlay&&!l)?k:D;var X=l?k:D;if(p.showOverlay){g._fadeIn(p.fadeIn,T)}if(l){h._fadeIn(p.fadeIn,X)}}else{if(p.showOverlay){g.show()}if(l){h.show()}if(p.onBlock){p.onBlock()}}u(1,S,p);if(Y){E=h[0];z=x(":input:enabled:visible",E);if(p.focusInput){setTimeout(a,20)}}else{F(h[0],p.centerX,p.centerY)}if(p.timeout){var o=setTimeout(function(){if(Y){x.unblockUI(p)}else{x(S).unblock(p)}},p.timeout);x(S).data("blockUI.timeout",o)}}function y(f,d){var e;var g=(f==window);var h=x(f);var c=h.data("blockUI.history");var j=h.data("blockUI.timeout");if(j){clearTimeout(j);h.removeData("blockUI.timeout")}d=x.extend({},x.blockUI.defaults,d||{});u(0,f,d);if(d.onUnblock===null){d.onUnblock=h.data("blockUI.onUnblock");h.removeData("blockUI.onUnblock")}var i;if(g){i=x("body").children().filter(".blockUI").add("body > .blockUI")}else{i=h.find(">.blockUI")}if(d.cursorReset){if(i.length>1){i[1].style.cursor=d.cursorReset}if(i.length>2){i[2].style.cursor=d.cursorReset}}if(g){E=z=null}if(d.fadeOut){e=i.length;i.fadeOut(d.fadeOut,function(){if(--e===0){v(i,c,d,f)}})}else{v(i,c,d,f)}}function v(d,i,j,c){var e=x(c);d.each(function(l,k){if(this.parentNode){this.parentNode.removeChild(this)}});if(i&&i.el){i.el.style.display=i.display;i.el.style.position=i.position;if(i.parent){i.parent.appendChild(i.el)}e.removeData("blockUI.history")}if(e.data("blockUI.static")){e.css("position","static")}if(typeof j.onUnblock=="function"){j.onUnblock(c,j)}var h=x(document.body),f=h.width(),g=h[0].style.width;h.width(f-1).width(f);h[0].style.width=g}function u(h,d,c){var e=d==window,f=x(d);if(!h&&(e&&!E||!e&&!f.data("blockUI.isBlocked"))){return}f.data("blockUI.isBlocked",h);if(!e||!c.bindEvents||(h&&!c.showOverlay)){return}var g="mousedown mouseup keydown keypress keyup touchstart touchend touchmove";if(h){x(document).bind(g,c,r)}else{x(document).unbind(g,r)}}function r(c){if(c.keyCode&&c.keyCode==9){if(E&&c.data.constrainTabKey){var f=z;var g=!c.shiftKey&&c.target===f[f.length-1];var h=c.shiftKey&&c.target===f[0];if(g||h){setTimeout(function(){a(h)},10);return false}}}var e=c.data;var d=x(c.target);if(d.hasClass("blockOverlay")&&e.onOverlayClick){e.onOverlayClick()}if(d.parents("div."+e.blockMsgClass).length>0){return true}return d.parents().children().filter("div.blockUI").length===0}function a(d){if(!z){return}var c=z[d===true?z.length-1:0];if(c){c.focus()}}function F(h,g,i){var c=h.parentNode,d=h.style;var f=((c.offsetWidth-h.offsetWidth)/2)-s(c,"borderLeftWidth");var e=((c.offsetHeight-h.offsetHeight)/2)-s(c,"borderTopWidth");if(g){d.left=f>0?(f+"px"):"0"}if(i){d.top=e>0?(e+"px"):"0"}}function s(d,c){return parseInt(x.css(d,c),10)||0}}if(typeof define==="function"&&define.amd&&define.amd.jQuery){define(["jquery"],b)}else{b(jQuery)}})();(function(y){var p=function(b,c){typeof c=="undefined"&&(c={});this.init(b,c)},m=p.prototype,u,v=["canvas","vml"],o=["oval","spiral","square","rect","roundRect"],a=/^\#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/,w=navigator.appVersion.indexOf("MSIE")!==-1&&parseFloat(navigator.appVersion.split("MSIE")[1])===8?true:false,n=!!document.createElement("canvas").getContext,x=true,t=function(d,e,c){var d=document.createElement(d),b;for(b in c){d[b]=c[b]}typeof e!=="undefined"&&e.appendChild(d);return d},q=function(d,b){for(var c in b){d.style[c]=b[c]}return d},f=function(d,b){for(var c in b){d.setAttribute(c,b[c])}return d},k=function(d,e,c,b){d.save();d.translate(e,c);d.rotate(b);d.translate(-e,-c);d.beginPath()};m.init=function(d,e){if(typeof e.safeVML==="boolean"){x=e.safeVML}try{this.mum=document.getElementById(d)!==void 0?document.getElementById(d):document.body}catch(c){this.mum=document.body}e.id=typeof e.id!=="undefined"?e.id:"canvasLoader";this.cont=t("div",this.mum,{id:e.id});if(n){u=v[0],this.can=t("canvas",this.cont),this.con=this.can.getContext("2d"),this.cCan=q(t("canvas",this.cont),{display:"none"}),this.cCon=this.cCan.getContext("2d")}else{u=v[1];if(typeof p.vmlSheet==="undefined"){document.getElementsByTagName("head")[0].appendChild(t("style"));p.vmlSheet=document.styleSheets[document.styleSheets.length-1];var g=["group","oval","roundrect","fill"],b;for(b in g){p.vmlSheet.addRule(g[b],"behavior:url(#default#VML); position:absolute;")}}this.vml=t("group",this.cont)}this.setColor(this.color);this.draw();q(this.cont,{display:"none"})};m.cont={};m.can={};m.con={};m.cCan={};m.cCon={};m.timer={};m.activeId=0;m.diameter=40;m.setDiameter=function(b){this.diameter=Math.round(Math.abs(b));this.redraw()};m.getDiameter=function(){return this.diameter};m.cRGB={};m.color="#000000";m.setColor=function(b){this.color=a.test(b)?b:"#000000";this.cRGB=this.getRGB(this.color);this.redraw()};m.getColor=function(){return this.color};m.shape=o[0];m.setShape=function(b){for(var c in o){if(b===o[c]){this.shape=b;this.redraw();break}}};m.getShape=function(){return this.shape};m.density=40;m.setDensity=function(b){this.density=x&&u===v[1]?Math.round(Math.abs(b))<=40?Math.round(Math.abs(b)):40:Math.round(Math.abs(b));if(this.density>360){this.density=360}this.activeId=0;this.redraw()};m.getDensity=function(){return this.density};m.range=1.3;m.setRange=function(b){this.range=Math.abs(b);this.redraw()};m.getRange=function(){return this.range};m.speed=2;m.setSpeed=function(b){this.speed=Math.round(Math.abs(b))};m.getSpeed=function(){return this.speed};m.fps=24;m.setFPS=function(b){this.fps=Math.round(Math.abs(b));this.reset()};m.getFPS=function(){return this.fps};m.getRGB=function(b){b=b.charAt(0)==="#"?b.substring(1,7):b;return{r:parseInt(b.substring(0,2),16),g:parseInt(b.substring(2,4),16),b:parseInt(b.substring(4,6),16)}};m.draw=function(){var c=0,j,b,l,r,z,e,d,i=this.density,B=Math.round(i*this.range),g,A,h=0;A=this.cCon;var s=this.diameter;if(u===v[0]){A.clearRect(0,0,1000,1000);f(this.can,{width:s,height:s});for(f(this.cCan,{width:s,height:s});c<i;){g=c<=B?1-1/B*c:g=0;e=270-360/i*c;d=e/180*Math.PI;A.fillStyle="rgba("+this.cRGB.r+","+this.cRGB.g+","+this.cRGB.b+","+g.toString()+")";switch(this.shape){case o[0]:case o[1]:j=s*0.07;r=s*0.47+Math.cos(d)*(s*0.47-j)-s*0.47;z=s*0.47+Math.sin(d)*(s*0.47-j)-s*0.47;A.beginPath();this.shape===o[1]?A.arc(s*0.5+r,s*0.5+z,j*g,0,Math.PI*2,false):A.arc(s*0.5+r,s*0.5+z,j,0,Math.PI*2,false);break;case o[2]:j=s*0.12;r=Math.cos(d)*(s*0.47-j)+s*0.5;z=Math.sin(d)*(s*0.47-j)+s*0.5;k(A,r,z,d);A.fillRect(r,z-j*0.5,j,j);break;case o[3]:case o[4]:b=s*0.3,l=b*0.27,r=Math.cos(d)*(l+(s-l)*0.13)+s*0.5,z=Math.sin(d)*(l+(s-l)*0.13)+s*0.5,k(A,r,z,d),this.shape===o[3]?A.fillRect(r,z-l*0.5,b,l):(j=l*0.55,A.moveTo(r+j,z-l*0.5),A.lineTo(r+b-j,z-l*0.5),A.quadraticCurveTo(r+b,z-l*0.5,r+b,z-l*0.5+j),A.lineTo(r+b,z-l*0.5+l-j),A.quadraticCurveTo(r+b,z-l*0.5+l,r+b-j,z-l*0.5+l),A.lineTo(r+j,z-l*0.5+l),A.quadraticCurveTo(r,z-l*0.5+l,r,z-l*0.5+l-j),A.lineTo(r,z-l*0.5+j),A.quadraticCurveTo(r,z-l*0.5,r+j,z-l*0.5))}A.closePath();A.fill();A.restore();++c}}else{q(this.cont,{width:s,height:s});q(this.vml,{width:s,height:s});switch(this.shape){case o[0]:case o[1]:d="oval";j=140;break;case o[2]:d="roundrect";j=120;break;case o[3]:case o[4]:d="roundrect",j=300}b=l=j;r=500-l;for(z=-l*0.5;c<i;){g=c<=B?1-1/B*c:g=0;e=270-360/i*c;switch(this.shape){case o[1]:b=l=j*g;r=500-j*0.5-j*g*0.5;z=(j-j*g)*0.5;break;case o[0]:case o[2]:w&&(z=0,this.shape===o[2]&&(r=500-l*0.5));break;case o[3]:case o[4]:b=j*0.95,l=b*0.28,w?(r=0,z=500-l*0.5):(r=500-b,z=-l*0.5),h=this.shape===o[4]?0.6:0}A=f(q(t("group",this.vml),{width:1000,height:1000,rotation:e}),{coordsize:"1000,1000",coordorigin:"-500,-500"});A=q(t(d,A,{stroked:false,arcSize:h}),{width:b,height:l,top:z,left:r});t("fill",A,{color:this.color,opacity:g});++c}}this.tick(true)};m.clean=function(){if(u===v[0]){this.con.clearRect(0,0,1000,1000)}else{var b=this.vml;if(b.hasChildNodes()){for(;b.childNodes.length>=1;){b.removeChild(b.firstChild)}}}};m.redraw=function(){this.clean();this.draw()};m.reset=function(){typeof this.timer==="number"&&(this.hide(),this.show())};m.tick=function(c){var b=this.con,d=this.diameter;c||(this.activeId+=360/this.density*this.speed);u===v[0]?(b.clearRect(0,0,d,d),k(b,d*0.5,d*0.5,this.activeId/180*Math.PI),b.drawImage(this.cCan,0,0,d,d),b.restore()):(this.activeId>=360&&(this.activeId-=360),q(this.vml,{rotation:this.activeId}))};m.show=function(){if(typeof this.timer!=="number"){var b=this;this.timer=self.setInterval(function(){b.tick()},Math.round(1000/this.fps));q(this.cont,{display:"block"})}};m.hide=function(){typeof this.timer==="number"&&(clearInterval(this.timer),delete this.timer,q(this.cont,{display:"none"}))};m.kill=function(){var c=this.cont;typeof this.timer==="number"&&this.hide();u===v[0]?(c.removeChild(this.can),c.removeChild(this.cCan)):c.removeChild(this.vml);for(var b in this){delete this[b]}};y.CanvasLoader=p})(window);

/*!
 PowerTip - v1.2.0 - 2013-04-03
 http://stevenbenner.github.com/jquery-powertip/
 Copyright (c) 2013 Steven Benner (http://stevenbenner.com/).
 Released under MIT license.
 https://raw.github.com/stevenbenner/jquery-powertip/master/LICENSE.txt
*/
(function(a){if(typeof define==="function"&&define.amd){define(["jquery"],a)}else{a(jQuery)}}(function(k){var A=k(document),s=k(window),w=k("body");var n="displayController",e="hasActiveHover",d="forcedOpen",u="hasMouseMove",f="mouseOnToPopup",g="originalTitle",y="powertip",o="powertipjq",l="powertiptarget",E=180/Math.PI;var c={isTipOpen:false,isFixedTipOpen:false,isClosing:false,tipOpenImminent:false,activeHover:null,currentX:0,currentY:0,previousX:0,previousY:0,desyncTimeout:null,mouseTrackingActive:false,delayInProgress:false,windowWidth:0,windowHeight:0,scrollTop:0,scrollLeft:0};var p={none:0,top:1,bottom:2,left:4,right:8};k.fn.powerTip=function(F,N){if(!this.length){return this}if(k.type(F)==="string"&&k.powerTip[F]){return k.powerTip[F].call(this,this,N)}var O=k.extend({},k.fn.powerTip.defaults,F),G=new x(O);h();this.each(function M(){var R=k(this),Q=R.data(y),P=R.data(o),T=R.data(l),S;if(R.data(n)){k.powerTip.destroy(R)}S=R.attr("title");if(!Q&&!T&&!P&&S){R.data(y,S);R.data(g,S);R.removeAttr("title")}R.data(n,new t(R,O,G))});if(!O.manual){this.on({"mouseenter.powertip":function J(P){k.powerTip.show(this,P)},"mouseleave.powertip":function L(){k.powerTip.hide(this)},"focus.powertip":function K(){k.powerTip.show(this)},"blur.powertip":function H(){k.powerTip.hide(this,true)},"keydown.powertip":function I(P){if(P.keyCode===27){k.powerTip.hide(this,true)}}})}return this};k.fn.powerTip.defaults={fadeInTime:200,fadeOutTime:100,followMouse:false,popupId:"powerTip",intentSensitivity:7,intentPollInterval:100,closeDelay:100,placement:"n",smartPlacement:false,offset:10,mouseOnToPopup:false,manual:false};k.fn.powerTip.smartPlacementLists={n:["n","ne","nw","s"],e:["e","ne","se","w","nw","sw","n","s","e"],s:["s","se","sw","n"],w:["w","nw","sw","e","ne","se","n","s","w"],nw:["nw","w","sw","n","s","se","nw"],ne:["ne","e","se","n","s","sw","ne"],sw:["sw","w","nw","s","n","ne","sw"],se:["se","e","ne","s","n","nw","se"],"nw-alt":["nw-alt","n","ne-alt","sw-alt","s","se-alt","w","e"],"ne-alt":["ne-alt","n","nw-alt","se-alt","s","sw-alt","e","w"],"sw-alt":["sw-alt","s","se-alt","nw-alt","n","ne-alt","w","e"],"se-alt":["se-alt","s","sw-alt","ne-alt","n","nw-alt","e","w"]};k.powerTip={show:function z(F,G){if(G){i(G);c.previousX=G.pageX;c.previousY=G.pageY;k(F).data(n).show()}else{k(F).first().data(n).show(true,true)}return F},reposition:function r(F){k(F).first().data(n).resetPosition();return F},hide:function D(G,F){if(G){k(G).first().data(n).hide(F)}else{if(c.activeHover){c.activeHover.data(n).hide(true)}}return G},destroy:function C(G){k(G).off(".powertip").each(function F(){var I=k(this),H=[g,n,e,d];if(I.data(g)){I.attr("title",I.data(g));H.push(y)}I.removeData(H)});return G}};k.powerTip.showTip=k.powerTip.show;k.powerTip.closeTip=k.powerTip.hide;function b(){var F=this;F.top="auto";F.left="auto";F.right="auto";F.bottom="auto";F.set=function(H,G){if(k.isNumeric(G)){F[H]=Math.round(G)}}}function t(K,N,F){var J=null;function L(P,Q){M();if(!K.data(e)){if(!P){c.tipOpenImminent=true;J=setTimeout(function O(){J=null;I()},N.intentPollInterval)}else{if(Q){K.data(d,true)}F.showTip(K)}}}function G(P){M();c.tipOpenImminent=false;if(K.data(e)){K.data(d,false);if(!P){c.delayInProgress=true;J=setTimeout(function O(){J=null;F.hideTip(K);c.delayInProgress=false},N.closeDelay)}else{F.hideTip(K)}}}function I(){var Q=Math.abs(c.previousX-c.currentX),O=Math.abs(c.previousY-c.currentY),P=Q+O;if(P<N.intentSensitivity){F.showTip(K)}else{c.previousX=c.currentX;c.previousY=c.currentY;L()}}function M(){J=clearTimeout(J);c.delayInProgress=false}function H(){F.resetPosition(K)}this.show=L;this.hide=G;this.cancel=M;this.resetPosition=H}function j(){function G(M,L,J,O,P){var K=L.split("-")[0],N=new b(),I;if(q(M)){I=H(M,K)}else{I=F(M,K)}switch(L){case"n":N.set("left",I.left-(J/2));N.set("bottom",c.windowHeight-I.top+P);break;case"e":N.set("left",I.left+P);N.set("top",I.top-(O/2));break;case"s":N.set("left",I.left-(J/2));N.set("top",I.top+P);break;case"w":N.set("top",I.top-(O/2));N.set("right",c.windowWidth-I.left+P);break;case"nw":N.set("bottom",c.windowHeight-I.top+P);N.set("right",c.windowWidth-I.left-20);break;case"nw-alt":N.set("left",I.left);N.set("bottom",c.windowHeight-I.top+P);break;case"ne":N.set("left",I.left-20);N.set("bottom",c.windowHeight-I.top+P);break;case"ne-alt":N.set("bottom",c.windowHeight-I.top+P);N.set("right",c.windowWidth-I.left);break;case"sw":N.set("top",I.top+P);N.set("right",c.windowWidth-I.left-20);break;case"sw-alt":N.set("left",I.left);N.set("top",I.top+P);break;case"se":N.set("left",I.left-20);N.set("top",I.top+P);break;case"se-alt":N.set("top",I.top+P);N.set("right",c.windowWidth-I.left);break}return N}function F(K,J){var O=K.offset(),N=K.outerWidth(),I=K.outerHeight(),M,L;switch(J){case"n":M=O.left+N/2;L=O.top;break;case"e":M=O.left+N;L=O.top+I/2;break;case"s":M=O.left+N/2;L=O.top+I;break;case"w":M=O.left;L=O.top+I/2;break;case"nw":M=O.left;L=O.top;break;case"ne":M=O.left+N;L=O.top;break;case"sw":M=O.left;L=O.top+I;break;case"se":M=O.left+N;L=O.top+I;break}return{top:L,left:M}}function H(O,K){var S=O.closest("svg")[0],N=O[0],W=S.createSVGPoint(),L=N.getBBox(),V=N.getScreenCTM(),M=L.width/2,Q=L.height/2,P=[],I=["nw","n","ne","e","se","s","sw","w"],U,X,R,T;function J(){P.push(W.matrixTransform(V))}W.x=L.x;W.y=L.y;J();W.x+=M;J();W.x+=M;J();W.y+=Q;J();W.y+=Q;J();W.x-=M;J();W.x-=M;J();W.y-=Q;J();if(P[0].y!==P[1].y||P[0].x!==P[7].x){X=Math.atan2(V.b,V.a)*E;R=Math.ceil(((X%360)-22.5)/45);if(R<1){R+=8}while(R--){I.push(I.shift())}}for(T=0;T<P.length;T++){if(I[T]===K){U=P[T];break}}return{top:U.y+c.scrollTop,left:U.x+c.scrollLeft}}this.compute=G}function x(Q){var P=new j(),O=k("#"+Q.popupId);if(O.length===0){O=k("<div/>",{id:Q.popupId});if(w.length===0){w=k("body")}w.append(O)}if(Q.followMouse){if(!O.data(u)){A.on("mousemove",M);s.on("scroll",M);O.data(u,true)}}if(Q.mouseOnToPopup){O.on({mouseenter:function L(){if(O.data(f)){if(c.activeHover){c.activeHover.data(n).cancel()}}},mouseleave:function N(){if(c.activeHover){c.activeHover.data(n).hide()}}})}function I(S){S.data(e,true);O.queue(function R(T){H(S);T()})}function H(S){var U;if(!S.data(e)){return}if(c.isTipOpen){if(!c.isClosing){K(c.activeHover)}O.delay(100).queue(function R(V){H(S);V()});return}S.trigger("powerTipPreRender");U=B(S);if(U){O.empty().append(U)}else{return}S.trigger("powerTipRender");c.activeHover=S;c.isTipOpen=true;O.data(f,Q.mouseOnToPopup);if(!Q.followMouse){G(S);c.isFixedTipOpen=true}else{M()}O.fadeIn(Q.fadeInTime,function T(){if(!c.desyncTimeout){c.desyncTimeout=setInterval(J,500)}S.trigger("powerTipOpen")})}function K(R){c.isClosing=true;c.activeHover=null;c.isTipOpen=false;c.desyncTimeout=clearInterval(c.desyncTimeout);R.data(e,false);R.data(d,false);O.fadeOut(Q.fadeOutTime,function S(){var T=new b();c.isClosing=false;c.isFixedTipOpen=false;O.removeClass();T.set("top",c.currentY+Q.offset);T.set("left",c.currentX+Q.offset);O.css(T);R.trigger("powerTipClose")})}function M(){if(!c.isFixedTipOpen&&(c.isTipOpen||(c.tipOpenImminent&&O.data(u)))){var R=O.outerWidth(),V=O.outerHeight(),U=new b(),S,T;U.set("top",c.currentY+Q.offset);U.set("left",c.currentX+Q.offset);S=m(U,R,V);if(S!==p.none){T=a(S);if(T===1){if(S===p.right){U.set("left",c.windowWidth-R)}else{if(S===p.bottom){U.set("top",c.scrollTop+c.windowHeight-V)}}}else{U.set("left",c.currentX-R-Q.offset);U.set("top",c.currentY-V-Q.offset)}}O.css(U)}}function G(S){var R,T;if(Q.smartPlacement){R=k.fn.powerTip.smartPlacementLists[Q.placement];k.each(R,function(U,W){var V=m(F(S,W),O.outerWidth(),O.outerHeight());T=W;if(V===p.none){return false}})}else{F(S,Q.placement);T=Q.placement}O.addClass(T)}function F(U,T){var R=0,S,W,V=new b();V.set("top",0);V.set("left",0);O.css(V);do{S=O.outerWidth();W=O.outerHeight();V=P.compute(U,T,S,W,Q.offset);O.css(V)}while(++R<=5&&(S!==O.outerWidth()||W!==O.outerHeight()));return V}function J(){var R=false;if(c.isTipOpen&&!c.isClosing&&!c.delayInProgress){if(c.activeHover.data(e)===false||c.activeHover.is(":disabled")){R=true}else{if(!v(c.activeHover)&&!c.activeHover.is(":focus")&&!c.activeHover.data(d)){if(O.data(f)){if(!v(O)){R=true}}else{R=true}}}if(R){K(c.activeHover)}}}this.showTip=I;this.hideTip=K;this.resetPosition=G}function q(F){return window.SVGElement&&F[0] instanceof SVGElement}function h(){if(!c.mouseTrackingActive){c.mouseTrackingActive=true;k(function H(){c.scrollLeft=s.scrollLeft();c.scrollTop=s.scrollTop();c.windowWidth=s.width();c.windowHeight=s.height()});A.on("mousemove",i);s.on({resize:function G(){c.windowWidth=s.width();c.windowHeight=s.height()},scroll:function F(){var I=s.scrollLeft(),J=s.scrollTop();if(I!==c.scrollLeft){c.currentX+=I-c.scrollLeft;c.scrollLeft=I}if(J!==c.scrollTop){c.currentY+=J-c.scrollTop;c.scrollTop=J}}})}}function i(F){c.currentX=F.pageX;c.currentY=F.pageY}function v(F){var H=F.offset(),J=F[0].getBoundingClientRect(),I=J.right-J.left,G=J.bottom-J.top;return c.currentX>=H.left&&c.currentX<=H.left+I&&c.currentY>=H.top&&c.currentY<=H.top+G}function B(I){var G=I.data(y),F=I.data(o),K=I.data(l),H,J;if(G){if(k.isFunction(G)){G=G.call(I[0])}J=G}else{if(F){if(k.isFunction(F)){F=F.call(I[0])}if(F.length>0){J=F.clone(true,true)}}else{if(K){H=k("#"+K);if(H.length>0){J=H.html()}}}}return J}function m(M,L,K){var G=c.scrollTop,J=c.scrollLeft,I=G+c.windowHeight,F=J+c.windowWidth,H=p.none;if(M.top<G||Math.abs(M.bottom-c.windowHeight)-K<G){H|=p.top}if(M.top+K>I||Math.abs(M.bottom-c.windowHeight)>I){H|=p.bottom}if(M.left<J||M.right+L>F){H|=p.left}if(M.left+L>F||M.right<J){H|=p.right}return H}function a(G){var F=0;while(G){G&=G-1;F++}return F}}));(function(a){if(typeof define==="function"&&define.amd){define(["jquery","jquery.ui.widget"],a)}else{a(window.jQuery)}}(function(a){a.support.xhrFileUpload=!!(window.XMLHttpRequestUpload&&window.FileReader);a.support.xhrFormDataFileUpload=!!window.FormData;a.widget("blueimp.fileupload",{options:{dropZone:a(document),pasteZone:a(document),fileInput:undefined,replaceFileInput:true,paramName:undefined,singleFileUploads:true,limitMultiFileUploads:undefined,sequentialUploads:false,limitConcurrentUploads:undefined,forceIframeTransport:false,redirect:undefined,redirectParamName:undefined,postMessage:undefined,multipart:true,maxChunkSize:undefined,uploadedBytes:undefined,recalculateProgress:true,progressInterval:100,bitrateInterval:500,autoUpload:true,messages:{uploadedBytes:"Uploaded bytes exceed file size"},i18n:function(c,b){c=this.messages[c]||c.toString();if(b){a.each(b,function(d,e){c=c.replace("{"+d+"}",e)})}return c},formData:function(b){return b.serializeArray()},add:function(c,b){if(b.autoUpload||(b.autoUpload!==false&&a(this).fileupload("option","autoUpload"))){b.process().done(function(){b.submit()})}},processData:false,contentType:false,cache:false},_specialOptions:["fileInput","dropZone","pasteZone","multipart","forceIframeTransport"],_BitrateTimer:function(){this.timestamp=((Date.now)?Date.now():(new Date()).getTime());this.loaded=0;this.bitrate=0;this.getBitrate=function(d,c,b){var e=d-this.timestamp;if(!this.bitrate||!b||e>b){this.bitrate=(c-this.loaded)*(1000/e)*8;this.loaded=c;this.timestamp=d}return this.bitrate}},_isXHRUpload:function(b){return !b.forceIframeTransport&&((!b.multipart&&a.support.xhrFileUpload)||a.support.xhrFormDataFileUpload)},_getFormData:function(b){var c;if(typeof b.formData==="function"){return b.formData(b.form)}if(a.isArray(b.formData)){return b.formData}if(a.type(b.formData)==="object"){c=[];a.each(b.formData,function(d,e){c.push({name:d,value:e})});return c}return[]},_getTotal:function(c){var b=0;a.each(c,function(d,e){b+=e.size||1});return b},_initProgressObject:function(c){var b={loaded:0,total:0,bitrate:0};if(c._progress){a.extend(c._progress,b)}else{c._progress=b}},_initResponseObject:function(b){var c;if(b._response){for(c in b._response){if(b._response.hasOwnProperty(c)){delete b._response[c]}}}else{b._response={}}},_onProgress:function(f,d){if(f.lengthComputable){var c=((Date.now)?Date.now():(new Date()).getTime()),b;if(d._time&&d.progressInterval&&(c-d._time<d.progressInterval)&&f.loaded!==f.total){return}d._time=c;b=Math.floor(f.loaded/f.total*(d.chunkSize||d._progress.total))+(d.uploadedBytes||0);this._progress.loaded+=(b-d._progress.loaded);this._progress.bitrate=this._bitrateTimer.getBitrate(c,this._progress.loaded,d.bitrateInterval);d._progress.loaded=d.loaded=b;d._progress.bitrate=d.bitrate=d._bitrateTimer.getBitrate(c,b,d.bitrateInterval);this._trigger("progress",f,d);this._trigger("progressall",f,this._progress)}},_initProgressListener:function(b){var c=this,d=b.xhr?b.xhr():a.ajaxSettings.xhr();if(d.upload){a(d.upload).bind("progress",function(f){var g=f.originalEvent;f.lengthComputable=g.lengthComputable;f.loaded=g.loaded;f.total=g.total;c._onProgress(f,b)});b.xhr=function(){return d}}},_isInstanceOf:function(b,c){return Object.prototype.toString.call(c)==="[object "+b+"]"},_initXHRData:function(c){var e=this,g,d=c.files[0],b=c.multipart||!a.support.xhrFileUpload,f=c.paramName[0];c.headers=c.headers||{};if(c.contentRange){c.headers["Content-Range"]=c.contentRange}if(!b){c.headers["Content-Disposition"]='attachment; filename="'+encodeURI(d.name)+'"';c.contentType=d.type;c.data=c.blob||d}else{if(a.support.xhrFormDataFileUpload){if(c.postMessage){g=this._getFormData(c);if(c.blob){g.push({name:f,value:c.blob})}else{a.each(c.files,function(h,i){g.push({name:c.paramName[h]||f,value:i})})}}else{if(e._isInstanceOf("FormData",c.formData)){g=c.formData}else{g=new FormData();a.each(this._getFormData(c),function(h,i){g.append(i.name,i.value)})}if(c.blob){c.headers["Content-Disposition"]='attachment; filename="'+encodeURI(d.name)+'"';g.append(f,c.blob,d.name)}else{a.each(c.files,function(h,i){if(e._isInstanceOf("File",i)||e._isInstanceOf("Blob",i)){g.append(c.paramName[h]||f,i,i.name)}})}}c.data=g}}c.blob=null},_initIframeSettings:function(b){var c=a("<a></a>").prop("href",b.url).prop("host");b.dataType="iframe "+(b.dataType||"");b.formData=this._getFormData(b);if(b.redirect&&c&&c!==location.host){b.formData.push({name:b.redirectParamName||"redirect",value:b.redirect})}},_initDataSettings:function(b){if(this._isXHRUpload(b)){if(!this._chunkedUpload(b,true)){if(!b.data){this._initXHRData(b)}this._initProgressListener(b)}if(b.postMessage){b.dataType="postmessage "+(b.dataType||"")}}else{this._initIframeSettings(b)}},_getParamName:function(b){var c=a(b.fileInput),d=b.paramName;if(!d){d=[];c.each(function(){var e=a(this),f=e.prop("name")||"files[]",g=(e.prop("files")||[1]).length;while(g){d.push(f);g-=1}});if(!d.length){d=[c.prop("name")||"files[]"]}}else{if(!a.isArray(d)){d=[d]}}return d},_initFormSettings:function(b){if(!b.form||!b.form.length){b.form=a(b.fileInput.prop("form"));if(!b.form.length){b.form=a(this.options.fileInput.prop("form"))}}b.paramName=this._getParamName(b);if(!b.url){b.url=b.form.prop("action")||location.href}b.type=(b.type||b.form.prop("method")||"").toUpperCase();if(b.type!=="POST"&&b.type!=="PUT"&&b.type!=="PATCH"){b.type="POST"}if(!b.formAcceptCharset){b.formAcceptCharset=b.form.attr("accept-charset")}},_getAJAXSettings:function(c){var b=a.extend({},this.options,c);this._initFormSettings(b);this._initDataSettings(b);return b},_getDeferredState:function(b){if(b.state){return b.state()}if(b.isResolved()){return"resolved"}if(b.isRejected()){return"rejected"}return"pending"},_enhancePromise:function(b){b.success=b.done;b.error=b.fail;b.complete=b.always;return b},_getXHRPromise:function(e,d,c){var b=a.Deferred(),f=b.promise();d=d||this.options.context||f;if(e===true){b.resolveWith(d,c)}else{if(e===false){b.rejectWith(d,c)}}f.abort=b.promise;return this._enhancePromise(f)},_addConvenienceMethods:function(f,d){var c=this,b=function(e){return a.Deferred().resolveWith(c,[e]).promise()};d.process=function(g,e){if(g||e){d._processQueue=this._processQueue=(this._processQueue||b(this)).pipe(g,e)}return this._processQueue||b(this)};d.submit=function(){if(this.state()!=="pending"){d.jqXHR=this.jqXHR=(c._trigger("submit",f,this)!==false)&&c._onSend(f,this)}return this.jqXHR||c._getXHRPromise()};d.abort=function(){if(this.jqXHR){return this.jqXHR.abort()}return c._getXHRPromise()};d.state=function(){if(this.jqXHR){return c._getDeferredState(this.jqXHR)}if(this._processQueue){return c._getDeferredState(this._processQueue)}};d.progress=function(){return this._progress};d.response=function(){return this._response}},_getUploadedBytes:function(d){var b=d.getResponseHeader("Range"),e=b&&b.split("-"),c=e&&e.length>1&&parseInt(e[1],10);return c&&c+1},_chunkedUpload:function(m,g){var f=this,d=m.files[0],e=d.size,b=m.uploadedBytes=m.uploadedBytes||0,c=m.maxChunkSize||e,i=d.slice||d.webkitSlice||d.mozSlice,j=a.Deferred(),l=j.promise(),h,k;if(!(this._isXHRUpload(m)&&i&&(b||c<e))||m.data){return false}if(g){return true}if(b>=e){d.error=m.i18n("uploadedBytes");return this._getXHRPromise(false,m.context,[null,"error",d.error])}k=function(){var p=a.extend({},m),n=p._progress.loaded;p.blob=i.call(d,b,b+c,d.type);p.chunkSize=p.blob.size;p.contentRange="bytes "+b+"-"+(b+p.chunkSize-1)+"/"+e;f._initXHRData(p);f._initProgressListener(p);h=((f._trigger("chunksend",null,p)!==false&&a.ajax(p))||f._getXHRPromise(false,p.context)).done(function(o,r,q){b=f._getUploadedBytes(q)||(b+p.chunkSize);if(n+p.chunkSize-p._progress.loaded){f._onProgress(a.Event("progress",{lengthComputable:true,loaded:b-p.uploadedBytes,total:b-p.uploadedBytes}),p)}m.uploadedBytes=p.uploadedBytes=b;p.result=o;p.textStatus=r;p.jqXHR=q;f._trigger("chunkdone",null,p);f._trigger("chunkalways",null,p);if(b<e){k()}else{j.resolveWith(p.context,[o,r,q])}}).fail(function(o,r,q){p.jqXHR=o;p.textStatus=r;p.errorThrown=q;f._trigger("chunkfail",null,p);f._trigger("chunkalways",null,p);j.rejectWith(p.context,[o,r,q])})};this._enhancePromise(l);l.abort=function(){return h.abort()};k();return l},_beforeSend:function(c,b){if(this._active===0){this._trigger("start");this._bitrateTimer=new this._BitrateTimer();this._progress.loaded=this._progress.total=0;this._progress.bitrate=0}this._initResponseObject(b);this._initProgressObject(b);b._progress.loaded=b.loaded=b.uploadedBytes||0;b._progress.total=b.total=this._getTotal(b.files)||1;b._progress.bitrate=b.bitrate=0;this._active+=1;this._progress.loaded+=b.loaded;this._progress.total+=b.total},_onDone:function(b,g,f,d){var e=d._progress.total,c=d._response;if(d._progress.loaded<e){this._onProgress(a.Event("progress",{lengthComputable:true,loaded:e,total:e}),d)}c.result=d.result=b;c.textStatus=d.textStatus=g;c.jqXHR=d.jqXHR=f;this._trigger("done",null,d)},_onFail:function(d,f,e,c){var b=c._response;if(c.recalculateProgress){this._progress.loaded-=c._progress.loaded;this._progress.total-=c._progress.total}b.jqXHR=c.jqXHR=d;b.textStatus=c.textStatus=f;b.errorThrown=c.errorThrown=e;this._trigger("fail",null,c)},_onAlways:function(d,e,c,b){this._trigger("always",null,b)},_onSend:function(h,f){if(!f.submit){this._addConvenienceMethods(h,f)}var g=this,j,b,i,c,k=g._getAJAXSettings(f),d=function(){g._sending+=1;k._bitrateTimer=new g._BitrateTimer();j=j||(((b||g._trigger("send",h,k)===false)&&g._getXHRPromise(false,k.context,b))||g._chunkedUpload(k)||a.ajax(k)).done(function(e,m,l){g._onDone(e,m,l,k)}).fail(function(e,m,l){g._onFail(e,m,l,k)}).always(function(m,n,l){g._onAlways(m,n,l,k);g._sending-=1;g._active-=1;if(k.limitConcurrentUploads&&k.limitConcurrentUploads>g._sending){var e=g._slots.shift();while(e){if(g._getDeferredState(e)==="pending"){e.resolve();break}e=g._slots.shift()}}if(g._active===0){g._trigger("stop")}});return j};this._beforeSend(h,k);if(this.options.sequentialUploads||(this.options.limitConcurrentUploads&&this.options.limitConcurrentUploads<=this._sending)){if(this.options.limitConcurrentUploads>1){i=a.Deferred();this._slots.push(i);c=i.pipe(d)}else{c=(this._sequence=this._sequence.pipe(d,d))}c.abort=function(){b=[undefined,"abort","abort"];if(!j){if(i){i.rejectWith(k.context,b)}return d()}return j.abort()};return this._enhancePromise(c)}return d()},_onAdd:function(k,g){var j=this,n=true,m=a.extend({},this.options,g),d=m.limitMultiFileUploads,h=this._getParamName(m),c,b,l,f;if(!(m.singleFileUploads||d)||!this._isXHRUpload(m)){l=[g.files];c=[h]}else{if(!m.singleFileUploads&&d){l=[];c=[];for(f=0;f<g.files.length;f+=d){l.push(g.files.slice(f,f+d));b=h.slice(f,f+d);if(!b.length){b=h}c.push(b)}}else{c=h}}g.originalFiles=g.files;a.each(l||g.files,function(e,i){var o=a.extend({},g);o.files=l?i:[i];o.paramName=c[e];j._initResponseObject(o);j._initProgressObject(o);j._addConvenienceMethods(k,o);n=j._trigger("add",k,o);return n});return n},_replaceFileInput:function(b){var c=b.clone(true);a("<form></form>").append(c)[0].reset();b.after(c).detach();a.cleanData(b.unbind("remove"));this.options.fileInput=this.options.fileInput.map(function(d,e){if(e===b[0]){return c[0]}return e});if(b[0]===this.element[0]){this.element=c}},_handleFileTreeEntry:function(f,g){var e=this,b=a.Deferred(),c=function(h){if(h&&!h.entry){h.entry=f}b.resolve([h])},d;g=g||"";if(f.isFile){if(f._file){f._file.relativePath=g;b.resolve(f._file)}else{f.file(function(h){h.relativePath=g;b.resolve(h)},c)}}else{if(f.isDirectory){d=f.createReader();d.readEntries(function(h){e._handleFileTreeEntries(h,g+f.name+"/").done(function(i){b.resolve(i)}).fail(c)},c)}else{b.resolve([])}}return b.promise()},_handleFileTreeEntries:function(b,d){var c=this;return a.when.apply(a,a.map(b,function(e){return c._handleFileTreeEntry(e,d)})).pipe(function(){return Array.prototype.concat.apply([],arguments)})},_getDroppedFiles:function(c){c=c||{};var b=c.items;if(b&&b.length&&(b[0].webkitGetAsEntry||b[0].getAsEntry)){return this._handleFileTreeEntries(a.map(b,function(e){var d;if(e.webkitGetAsEntry){d=e.webkitGetAsEntry();if(d){d._file=e.getAsFile()}return d}return e.getAsEntry()}))}return a.Deferred().resolve(a.makeArray(c.files)).promise()},_getSingleFileInputFiles:function(d){d=a(d);var b=d.prop("webkitEntries")||d.prop("entries"),c,e;if(b&&b.length){return this._handleFileTreeEntries(b)}c=a.makeArray(d.prop("files"));if(!c.length){e=d.prop("value");if(!e){return a.Deferred().resolve([]).promise()}c=[{name:e.replace(/^.*\\/,"")}]}else{if(c[0].name===undefined&&c[0].fileName){a.each(c,function(f,g){g.name=g.fileName;g.size=g.fileSize})}}return a.Deferred().resolve(c).promise()},_getFileInputFiles:function(b){if(!(b instanceof a)||b.length===1){return this._getSingleFileInputFiles(b)}return a.when.apply(a,a.map(b,this._getSingleFileInputFiles)).pipe(function(){return Array.prototype.concat.apply([],arguments)})},_onChange:function(d){var b=this,c={fileInput:a(d.target),form:a(d.target.form)};this._getFileInputFiles(c.fileInput).always(function(e){c.files=e;if(b.options.replaceFileInput){b._replaceFileInput(c.fileInput)}if(b._trigger("change",d,c)!==false){b._onAdd(d,c)}})},_onPaste:function(d){var b=d.originalEvent&&d.originalEvent.clipboardData&&d.originalEvent.clipboardData.items,c={files:[]};if(b&&b.length){a.each(b,function(e,g){var f=g.getAsFile&&g.getAsFile();if(f){c.files.push(f)}});if(this._trigger("paste",d,c)===false||this._onAdd(d,c)===false){return false}}},_onDrop:function(f){var b=this,d=f.dataTransfer=f.originalEvent&&f.originalEvent.dataTransfer,c={};if(d&&d.files&&d.files.length){f.preventDefault();this._getDroppedFiles(d).always(function(e){c.files=e;if(b._trigger("drop",f,c)!==false){b._onAdd(f,c)}})}},_onDragOver:function(c){var b=c.dataTransfer=c.originalEvent&&c.originalEvent.dataTransfer;if(b){if(this._trigger("dragover",c)===false){return false}if(a.inArray("Files",b.types)!==-1){b.dropEffect="copy";c.preventDefault()}}},_initEventHandlers:function(){if(this._isXHRUpload(this.options)){this._on(this.options.dropZone,{dragover:this._onDragOver,drop:this._onDrop});this._on(this.options.pasteZone,{paste:this._onPaste})}this._on(this.options.fileInput,{change:this._onChange})},_destroyEventHandlers:function(){this._off(this.options.dropZone,"dragover drop");this._off(this.options.pasteZone,"paste");this._off(this.options.fileInput,"change")},_setOption:function(b,c){var d=a.inArray(b,this._specialOptions)!==-1;if(d){this._destroyEventHandlers()}this._super(b,c);if(d){this._initSpecialOptions();this._initEventHandlers()}},_initSpecialOptions:function(){var b=this.options;if(b.fileInput===undefined){b.fileInput=this.element.is('input[type="file"]')?this.element:this.element.find('input[type="file"]')}else{if(!(b.fileInput instanceof a)){b.fileInput=a(b.fileInput)}}if(!(b.dropZone instanceof a)){b.dropZone=a(b.dropZone)}if(!(b.pasteZone instanceof a)){b.pasteZone=a(b.pasteZone)}},_getRegExp:function(d){var c=d.split("/"),b=c.pop();c.shift();return new RegExp(c.join("/"),b)},_isRegExpOption:function(b,c){return b!=="url"&&a.type(c)==="string"&&/^\/.*\/[igm]{0,3}$/.test(c)},_initDataAttributes:function(){var c=this,b=this.options;a.each(a(this.element[0].cloneNode(false)).data(),function(d,e){if(c._isRegExpOption(d,e)){e=c._getRegExp(e)}b[d]=e})},_create:function(){this._initDataAttributes();this._initSpecialOptions();this._slots=[];this._sequence=this._getXHRPromise(true);this._sending=this._active=0;this._initProgressObject(this);this._initEventHandlers()},active:function(){return this._active},progress:function(){return this._progress},add:function(c){var b=this;if(!c||this.options.disabled){return}if(c.fileInput&&!c.files){this._getFileInputFiles(c.fileInput).always(function(d){c.files=d;b._onAdd(null,c)})}else{c.files=a.makeArray(c.files);this._onAdd(null,c)}},send:function(f){if(f&&!this.options.disabled){if(f.fileInput&&!f.files){var d=this,b=a.Deferred(),g=b.promise(),c,e;g.abort=function(){e=true;if(c){return c.abort()}b.reject(null,"abort","abort");return g};this._getFileInputFiles(f.fileInput).always(function(h){if(e){return}f.files=h;c=d._onSend(null,f).then(function(i,k,j){b.resolve(i,k,j)},function(i,k,j){b.reject(i,k,j)})});return this._enhancePromise(g)}f.files=a.makeArray(f.files);if(f.files.length){return this._onSend(null,f)}}return this._getXHRPromise(false,f&&f.context)}})}));(function(a){if(typeof define==="function"&&define.amd){define(["jquery"],a)}else{a(window.jQuery)}}(function(b){var a=0;b.ajaxTransport("iframe",function(c){if(c.async){var e,d,f;return{send:function(g,h){e=b('<form style="display:none;"></form>');e.attr("accept-charset",c.formAcceptCharset);f=/\?/.test(c.url)?"&":"?";if(c.type==="DELETE"){c.url=c.url+f+"_method=DELETE";c.type="POST"}else{if(c.type==="PUT"){c.url=c.url+f+"_method=PUT";c.type="POST"}else{if(c.type==="PATCH"){c.url=c.url+f+"_method=PATCH";c.type="POST"}}}a+=1;d=b('<iframe src="javascript:false;" name="iframe-transport-'+a+'"></iframe>').bind("load",function(){var i,j=b.isArray(c.paramName)?c.paramName:[c.paramName];d.unbind("load").bind("load",function(){var k;try{k=d.contents();if(!k.length||!k[0].firstChild){throw new Error()}}catch(l){k=undefined}h(200,"success",{iframe:k});b('<iframe src="javascript:false;"></iframe>').appendTo(e);window.setTimeout(function(){e.remove()},0)});e.prop("target",d.prop("name")).prop("action",c.url).prop("method",c.type);if(c.formData){b.each(c.formData,function(k,l){b('<input type="hidden"/>').prop("name",l.name).val(l.value).appendTo(e)})}if(c.fileInput&&c.fileInput.length&&c.type==="POST"){i=c.fileInput.clone();c.fileInput.after(function(k){return i[k]});if(c.paramName){c.fileInput.each(function(k){b(this).prop("name",j[k]||c.paramName)})}e.append(c.fileInput).prop("enctype","multipart/form-data").prop("encoding","multipart/form-data")}e.submit();if(i&&i.length){c.fileInput.each(function(l,k){var m=b(i[l]);b(k).prop("name",m.prop("name"));m.replaceWith(k)})}});e.append(d).appendTo(document.body)},abort:function(){if(d){d.unbind("load").prop("src","javascript".concat(":false;"))}if(e){e.remove()}}}}});b.ajaxSetup({converters:{"iframe text":function(c){return c&&b(c[0].body).text()},"iframe json":function(c){return c&&b.parseJSON(b(c[0].body).text())},"iframe html":function(c){return c&&b(c[0].body).html()},"iframe xml":function(c){var d=c&&c[0];return d&&b.isXMLDoc(d)?d:b.parseXML((d.XMLDocument&&d.XMLDocument.xml)||b(d.body).html())},"iframe script":function(c){return c&&b.globalEval(b(c[0].body).text())}}})}));(function(b){b.fn.zclip=function(d){if(typeof d=="object"&&!d.length){var a=b.extend({path:"ZeroClipboard.swf",copy:null,beforeCopy:null,afterCopy:null,clickAfter:true,setHandCursor:true,setCSSEffects:true},d);return this.each(function(){var c=b(this);if(c.is(":visible")&&(typeof a.copy=="string"||b.isFunction(a.copy))){ZeroClipboard.setMoviePath(a.path);var f=new ZeroClipboard.Client();if(b.isFunction(a.copy)){c.bind("zClip_copy",a.copy)}if(b.isFunction(a.beforeCopy)){c.bind("zClip_beforeCopy",a.beforeCopy)}if(b.isFunction(a.afterCopy)){c.bind("zClip_afterCopy",a.afterCopy)}f.setHandCursor(a.setHandCursor);f.setCSSEffects(a.setCSSEffects);f.addEventListener("mouseOver",function(e){c.trigger("mouseenter")});f.addEventListener("mouseOut",function(e){c.trigger("mouseleave")});f.addEventListener("mouseDown",function(e){c.trigger("mousedown");if(!b.isFunction(a.copy)){f.setText(a.copy)}else{f.setText(c.triggerHandler("zClip_copy"))}if(b.isFunction(a.beforeCopy)){c.trigger("zClip_beforeCopy")}});f.addEventListener("complete",function(h,e){if(b.isFunction(a.afterCopy)){c.trigger("zClip_afterCopy")}else{if(e.length>500){e=e.substr(0,500)+"...\n\n("+(e.length-500)+" characters not shown)"}c.removeClass("hover");alert("Copied text to clipboard:\n\n "+e)}if(a.clickAfter){c.trigger("click")}});f.glue(c[0],c.parent()[0]);b(window).bind("load resize",function(){f.reposition()})}})}else{if(typeof d=="string"){return this.each(function(){var c=b(this);d=d.toLowerCase();var g=c.data("zclipId");var h=b("#"+g+".zclip");if(d=="remove"){h.remove();c.removeClass("active hover")}else{if(d=="hide"){h.hide();c.removeClass("active hover")}else{if(d=="show"){h.show()}}}})}}}})(jQuery);var ZeroClipboard={version:"1.0.7",clients:{},moviePath:"ZeroClipboard.swf",nextId:1,jQuery:function(b){if(typeof(b)=="string"){b=document.getElementById(b)}if(!b.addClass){b.hide=function(){this.style.display="none"};b.show=function(){this.style.display=""};b.addClass=function(a){this.removeClass(a);this.className+=" "+a};b.removeClass=function(g){var f=this.className.split(/\s+/);var a=-1;for(var h=0;h<f.length;h++){if(f[h]==g){a=h;h=f.length}}if(a>-1){f.splice(a,1);this.className=f.join(" ")}return this};b.hasClass=function(a){return !!this.className.match(new RegExp("\\s*"+a+"\\s*"))}}return b},setMoviePath:function(b){this.moviePath=b},dispatch:function(g,e,h){var f=this.clients[g];if(f){f.receiveEvent(e,h)}},register:function(c,d){this.clients[c]=d},getDOMObjectPosition:function(f,e){var d={left:0,top:0,width:f.width?f.width:f.offsetWidth,height:f.height?f.height:f.offsetHeight};if(f&&(f!=e)){d.left+=f.offsetLeft;d.top+=f.offsetTop}return d},Client:function(b){this.handlers={};this.id=ZeroClipboard.nextId++;this.movieId="ZeroClipboardMovie_"+this.id;ZeroClipboard.register(this.id,this);if(b){this.glue(b)}}};ZeroClipboard.Client.prototype={id:0,ready:false,movie:null,clipText:"",handCursorEnabled:true,cssEffects:true,handlers:null,glue:function(k,g,j){this.domElement=ZeroClipboard.jQuery(k);var i=99;if(this.domElement.style.zIndex){i=parseInt(this.domElement.style.zIndex,10)+1}if(typeof(g)=="string"){g=ZeroClipboard.jQuery(g)}else{if(typeof(g)=="undefined"){g=document.getElementsByTagName("body")[0]}}var l=ZeroClipboard.getDOMObjectPosition(this.domElement,g);this.div=document.createElement("div");this.div.className="zclip";this.div.id="zclip-"+this.movieId;jQuery(this.domElement).data("zclipId","zclip-"+this.movieId);var h=this.div.style;h.position="absolute";h.left=""+l.left+"px";h.top=""+l.top+"px";h.width=""+l.width+"px";h.height=""+l.height+"px";h.zIndex=i;if(typeof(j)=="object"){for(addedStyle in j){h[addedStyle]=j[addedStyle]}}g.appendChild(this.div);this.div.innerHTML=this.getHTML(l.width,l.height)},getHTML:function(i,g){var j="";var f="id="+this.id+"&width="+i+"&height="+g;if(navigator.userAgent.match(/MSIE/)){var h=location.href.match(/^https/i)?"https://":"http://";j+='<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="'+h+'download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="'+i+'" height="'+g+'" id="'+this.movieId+'" align="middle"><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="false" /><param name="movie" value="'+ZeroClipboard.moviePath+'" /><param name="loop" value="false" /><param name="menu" value="false" /><param name="quality" value="best" /><param name="bgcolor" value="#ffffff" /><param name="flashvars" value="'+f+'"/><param name="wmode" value="transparent"/></object>'}else{j+='<embed id="'+this.movieId+'" src="'+ZeroClipboard.moviePath+'" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="'+i+'" height="'+g+'" name="'+this.movieId+'" align="middle" allowScriptAccess="always" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="'+f+'" wmode="transparent" />'}return j},hide:function(){if(this.div){this.div.style.left="-2000px"}},show:function(){this.reposition()},destroy:function(){if(this.domElement&&this.div){this.hide();this.div.innerHTML="";var d=document.getElementsByTagName("body")[0];try{d.removeChild(this.div)}catch(c){}this.domElement=null;this.div=null}},reposition:function(f){if(f){this.domElement=ZeroClipboard.jQuery(f);if(!this.domElement){this.hide()}}if(this.domElement&&this.div){var d=ZeroClipboard.getDOMObjectPosition(this.domElement);var e=this.div.style;e.left=""+d.left+"px";e.top=""+d.top+"px"}},setText:function(b){this.clipText=b;if(this.ready){this.movie.setText(b)}},addEventListener:function(d,c){d=d.toString().toLowerCase().replace(/^on/,"");if(!this.handlers[d]){this.handlers[d]=[]}this.handlers[d].push(c)},setHandCursor:function(b){this.handCursorEnabled=b;if(this.ready){this.movie.setHandCursor(b)}},setCSSEffects:function(b){this.cssEffects=!!b},receiveEvent:function(m,l){m=m.toString().toLowerCase().replace(/^on/,"");switch(m){case"load":this.movie=document.getElementById(this.movieId);if(!this.movie){var n=this;setTimeout(function(){n.receiveEvent("load",null)},1);return}if(!this.ready&&navigator.userAgent.match(/Firefox/)&&navigator.userAgent.match(/Windows/)){var n=this;setTimeout(function(){n.receiveEvent("load",null)},100);this.ready=true;return}this.ready=true;try{this.movie.setText(this.clipText)}catch(j){}try{this.movie.setHandCursor(this.handCursorEnabled)}catch(j){}break;case"mouseover":if(this.domElement&&this.cssEffects){this.domElement.addClass("hover");if(this.recoverActive){this.domElement.addClass("active")}}break;case"mouseout":if(this.domElement&&this.cssEffects){this.recoverActive=false;if(this.domElement.hasClass("active")){this.domElement.removeClass("active");this.recoverActive=true}this.domElement.removeClass("hover")}break;case"mousedown":if(this.domElement&&this.cssEffects){this.domElement.addClass("active")}break;case"mouseup":if(this.domElement&&this.cssEffects){this.domElement.removeClass("active");this.recoverActive=false}break}if(this.handlers[m]){for(var e=0,i=this.handlers[m].length;e<i;e++){var k=this.handlers[m][e];if(typeof(k)=="function"){k(this,l)}else{if((typeof(k)=="object")&&(k.length==2)){k[0][k[1]](this,l)}else{if(typeof(k)=="string"){window[k](this,l)}}}}}}};

/* == jquery mousewheel plugin == Version: 3.1.13, License: MIT License (MIT) */
!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})});!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})});

/* == malihu jquery custom scrollbar plugin == Version: 3.1.5, License: MIT License (MIT) */
!function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"undefined"!=typeof module&&module.exports?module.exports=e:e(jQuery,window,document)}(function(e){!function(t){var o="function"==typeof define&&define.amd,a="undefined"!=typeof module&&module.exports,n="https:"==document.location.protocol?"https:":"http:",i="cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js";o||(a?require("jquery-mousewheel")(e):e.event.special.mousewheel||e("head").append(decodeURI("%3Cscript src="+n+"//"+i+"%3E%3C/script%3E"))),t()}(function(){var t,o="mCustomScrollbar",a="mCS",n=".mCustomScrollbar",i={setTop:0,setLeft:0,axis:"y",scrollbarPosition:"inside",scrollInertia:950,autoDraggerLength:!0,alwaysShowScrollbar:0,snapOffset:0,mouseWheel:{enable:!0,scrollAmount:"auto",axis:"y",deltaFactor:"auto",disableOver:["select","option","keygen","datalist","textarea"]},scrollButtons:{scrollType:"stepless",scrollAmount:"auto"},keyboard:{enable:!0,scrollType:"stepless",scrollAmount:"auto"},contentTouchScroll:25,documentTouchScroll:!0,advanced:{autoScrollOnFocus:"input,textarea,select,button,datalist,keygen,a[tabindex],area,object,[contenteditable='true']",updateOnContentResize:!0,updateOnImageLoad:"auto",autoUpdateTimeout:60},theme:"light",callbacks:{onTotalScrollOffset:0,onTotalScrollBackOffset:0,alwaysTriggerOffsets:!0}},r=0,l={},s=window.attachEvent&&!window.addEventListener?1:0,c=!1,d=["mCSB_dragger_onDrag","mCSB_scrollTools_onDrag","mCS_img_loaded","mCS_disabled","mCS_destroyed","mCS_no_scrollbar","mCS-autoHide","mCS-dir-rtl","mCS_no_scrollbar_y","mCS_no_scrollbar_x","mCS_y_hidden","mCS_x_hidden","mCSB_draggerContainer","mCSB_buttonUp","mCSB_buttonDown","mCSB_buttonLeft","mCSB_buttonRight"],u={init:function(t){var t=e.extend(!0,{},i,t),o=f.call(this);if(t.live){var s=t.liveSelector||this.selector||n,c=e(s);if("off"===t.live)return void m(s);l[s]=setTimeout(function(){c.mCustomScrollbar(t),"once"===t.live&&c.length&&m(s)},500)}else m(s);return t.setWidth=t.set_width?t.set_width:t.setWidth,t.setHeight=t.set_height?t.set_height:t.setHeight,t.axis=t.horizontalScroll?"x":p(t.axis),t.scrollInertia=t.scrollInertia>0&&t.scrollInertia<17?17:t.scrollInertia,"object"!=typeof t.mouseWheel&&1==t.mouseWheel&&(t.mouseWheel={enable:!0,scrollAmount:"auto",axis:"y",preventDefault:!1,deltaFactor:"auto",normalizeDelta:!1,invert:!1}),t.mouseWheel.scrollAmount=t.mouseWheelPixels?t.mouseWheelPixels:t.mouseWheel.scrollAmount,t.mouseWheel.normalizeDelta=t.advanced.normalizeMouseWheelDelta?t.advanced.normalizeMouseWheelDelta:t.mouseWheel.normalizeDelta,t.scrollButtons.scrollType=g(t.scrollButtons.scrollType),h(t),e(o).each(function(){var o=e(this);if(!o.data(a)){o.data(a,{idx:++r,opt:t,scrollRatio:{y:null,x:null},overflowed:null,contentReset:{y:null,x:null},bindEvents:!1,tweenRunning:!1,sequential:{},langDir:o.css("direction"),cbOffsets:null,trigger:null,poll:{size:{o:0,n:0},img:{o:0,n:0},change:{o:0,n:0}}});var n=o.data(a),i=n.opt,l=o.data("mcs-axis"),s=o.data("mcs-scrollbar-position"),c=o.data("mcs-theme");l&&(i.axis=l),s&&(i.scrollbarPosition=s),c&&(i.theme=c,h(i)),v.call(this),n&&i.callbacks.onCreate&&"function"==typeof i.callbacks.onCreate&&i.callbacks.onCreate.call(this),e("#mCSB_"+n.idx+"_container img:not(."+d[2]+")").addClass(d[2]),u.update.call(null,o)}})},update:function(t,o){var n=t||f.call(this);return e(n).each(function(){var t=e(this);if(t.data(a)){var n=t.data(a),i=n.opt,r=e("#mCSB_"+n.idx+"_container"),l=e("#mCSB_"+n.idx),s=[e("#mCSB_"+n.idx+"_dragger_vertical"),e("#mCSB_"+n.idx+"_dragger_horizontal")];if(!r.length)return;n.tweenRunning&&Q(t),o&&n&&i.callbacks.onBeforeUpdate&&"function"==typeof i.callbacks.onBeforeUpdate&&i.callbacks.onBeforeUpdate.call(this),t.hasClass(d[3])&&t.removeClass(d[3]),t.hasClass(d[4])&&t.removeClass(d[4]),l.css("max-height","none"),l.height()!==t.height()&&l.css("max-height",t.height()),_.call(this),"y"===i.axis||i.advanced.autoExpandHorizontalScroll||r.css("width",x(r)),n.overflowed=y.call(this),M.call(this),i.autoDraggerLength&&S.call(this),b.call(this),T.call(this);var c=[Math.abs(r[0].offsetTop),Math.abs(r[0].offsetLeft)];"x"!==i.axis&&(n.overflowed[0]?s[0].height()>s[0].parent().height()?B.call(this):(G(t,c[0].toString(),{dir:"y",dur:0,overwrite:"none"}),n.contentReset.y=null):(B.call(this),"y"===i.axis?k.call(this):"yx"===i.axis&&n.overflowed[1]&&G(t,c[1].toString(),{dir:"x",dur:0,overwrite:"none"}))),"y"!==i.axis&&(n.overflowed[1]?s[1].width()>s[1].parent().width()?B.call(this):(G(t,c[1].toString(),{dir:"x",dur:0,overwrite:"none"}),n.contentReset.x=null):(B.call(this),"x"===i.axis?k.call(this):"yx"===i.axis&&n.overflowed[0]&&G(t,c[0].toString(),{dir:"y",dur:0,overwrite:"none"}))),o&&n&&(2===o&&i.callbacks.onImageLoad&&"function"==typeof i.callbacks.onImageLoad?i.callbacks.onImageLoad.call(this):3===o&&i.callbacks.onSelectorChange&&"function"==typeof i.callbacks.onSelectorChange?i.callbacks.onSelectorChange.call(this):i.callbacks.onUpdate&&"function"==typeof i.callbacks.onUpdate&&i.callbacks.onUpdate.call(this)),N.call(this)}})},scrollTo:function(t,o){if("undefined"!=typeof t&&null!=t){var n=f.call(this);return e(n).each(function(){var n=e(this);if(n.data(a)){var i=n.data(a),r=i.opt,l={trigger:"external",scrollInertia:r.scrollInertia,scrollEasing:"mcsEaseInOut",moveDragger:!1,timeout:60,callbacks:!0,onStart:!0,onUpdate:!0,onComplete:!0},s=e.extend(!0,{},l,o),c=Y.call(this,t),d=s.scrollInertia>0&&s.scrollInertia<17?17:s.scrollInertia;c[0]=X.call(this,c[0],"y"),c[1]=X.call(this,c[1],"x"),s.moveDragger&&(c[0]*=i.scrollRatio.y,c[1]*=i.scrollRatio.x),s.dur=ne()?0:d,setTimeout(function(){null!==c[0]&&"undefined"!=typeof c[0]&&"x"!==r.axis&&i.overflowed[0]&&(s.dir="y",s.overwrite="all",G(n,c[0].toString(),s)),null!==c[1]&&"undefined"!=typeof c[1]&&"y"!==r.axis&&i.overflowed[1]&&(s.dir="x",s.overwrite="none",G(n,c[1].toString(),s))},s.timeout)}})}},stop:function(){var t=f.call(this);return e(t).each(function(){var t=e(this);t.data(a)&&Q(t)})},disable:function(t){var o=f.call(this);return e(o).each(function(){var o=e(this);if(o.data(a)){o.data(a);N.call(this,"remove"),k.call(this),t&&B.call(this),M.call(this,!0),o.addClass(d[3])}})},destroy:function(){var t=f.call(this);return e(t).each(function(){var n=e(this);if(n.data(a)){var i=n.data(a),r=i.opt,l=e("#mCSB_"+i.idx),s=e("#mCSB_"+i.idx+"_container"),c=e(".mCSB_"+i.idx+"_scrollbar");r.live&&m(r.liveSelector||e(t).selector),N.call(this,"remove"),k.call(this),B.call(this),n.removeData(a),$(this,"mcs"),c.remove(),s.find("img."+d[2]).removeClass(d[2]),l.replaceWith(s.contents()),n.removeClass(o+" _"+a+"_"+i.idx+" "+d[6]+" "+d[7]+" "+d[5]+" "+d[3]).addClass(d[4])}})}},f=function(){return"object"!=typeof e(this)||e(this).length<1?n:this},h=function(t){var o=["rounded","rounded-dark","rounded-dots","rounded-dots-dark"],a=["rounded-dots","rounded-dots-dark","3d","3d-dark","3d-thick","3d-thick-dark","inset","inset-dark","inset-2","inset-2-dark","inset-3","inset-3-dark"],n=["minimal","minimal-dark"],i=["minimal","minimal-dark"],r=["minimal","minimal-dark"];t.autoDraggerLength=e.inArray(t.theme,o)>-1?!1:t.autoDraggerLength,t.autoExpandScrollbar=e.inArray(t.theme,a)>-1?!1:t.autoExpandScrollbar,t.scrollButtons.enable=e.inArray(t.theme,n)>-1?!1:t.scrollButtons.enable,t.autoHideScrollbar=e.inArray(t.theme,i)>-1?!0:t.autoHideScrollbar,t.scrollbarPosition=e.inArray(t.theme,r)>-1?"outside":t.scrollbarPosition},m=function(e){l[e]&&(clearTimeout(l[e]),$(l,e))},p=function(e){return"yx"===e||"xy"===e||"auto"===e?"yx":"x"===e||"horizontal"===e?"x":"y"},g=function(e){return"stepped"===e||"pixels"===e||"step"===e||"click"===e?"stepped":"stepless"},v=function(){var t=e(this),n=t.data(a),i=n.opt,r=i.autoExpandScrollbar?" "+d[1]+"_expand":"",l=["<div id='mCSB_"+n.idx+"_scrollbar_vertical' class='mCSB_scrollTools mCSB_"+n.idx+"_scrollbar mCS-"+i.theme+" mCSB_scrollTools_vertical"+r+"'><div class='"+d[12]+"'><div id='mCSB_"+n.idx+"_dragger_vertical' class='mCSB_dragger' style='position:absolute;'><div class='mCSB_dragger_bar' /></div><div class='mCSB_draggerRail' /></div></div>","<div id='mCSB_"+n.idx+"_scrollbar_horizontal' class='mCSB_scrollTools mCSB_"+n.idx+"_scrollbar mCS-"+i.theme+" mCSB_scrollTools_horizontal"+r+"'><div class='"+d[12]+"'><div id='mCSB_"+n.idx+"_dragger_horizontal' class='mCSB_dragger' style='position:absolute;'><div class='mCSB_dragger_bar' /></div><div class='mCSB_draggerRail' /></div></div>"],s="yx"===i.axis?"mCSB_vertical_horizontal":"x"===i.axis?"mCSB_horizontal":"mCSB_vertical",c="yx"===i.axis?l[0]+l[1]:"x"===i.axis?l[1]:l[0],u="yx"===i.axis?"<div id='mCSB_"+n.idx+"_container_wrapper' class='mCSB_container_wrapper' />":"",f=i.autoHideScrollbar?" "+d[6]:"",h="x"!==i.axis&&"rtl"===n.langDir?" "+d[7]:"";i.setWidth&&t.css("width",i.setWidth),i.setHeight&&t.css("height",i.setHeight),i.setLeft="y"!==i.axis&&"rtl"===n.langDir?"989999px":i.setLeft,t.addClass(o+" _"+a+"_"+n.idx+f+h).wrapInner("<div id='mCSB_"+n.idx+"' class='mCustomScrollBox mCS-"+i.theme+" "+s+"'><div id='mCSB_"+n.idx+"_container' class='mCSB_container' style='position:relative; top:"+i.setTop+"; left:"+i.setLeft+";' dir='"+n.langDir+"' /></div>");var m=e("#mCSB_"+n.idx),p=e("#mCSB_"+n.idx+"_container");"y"===i.axis||i.advanced.autoExpandHorizontalScroll||p.css("width",x(p)),"outside"===i.scrollbarPosition?("static"===t.css("position")&&t.css("position","relative"),t.css("overflow","visible"),m.addClass("mCSB_outside").after(c)):(m.addClass("mCSB_inside").append(c),p.wrap(u)),w.call(this);var g=[e("#mCSB_"+n.idx+"_dragger_vertical"),e("#mCSB_"+n.idx+"_dragger_horizontal")];g[0].css("min-height",g[0].height()),g[1].css("min-width",g[1].width())},x=function(t){var o=[t[0].scrollWidth,Math.max.apply(Math,t.children().map(function(){return e(this).outerWidth(!0)}).get())],a=t.parent().width();return o[0]>a?o[0]:o[1]>a?o[1]:"100%"},_=function(){var t=e(this),o=t.data(a),n=o.opt,i=e("#mCSB_"+o.idx+"_container");if(n.advanced.autoExpandHorizontalScroll&&"y"!==n.axis){i.css({width:"auto","min-width":0,"overflow-x":"scroll"});var r=Math.ceil(i[0].scrollWidth);3===n.advanced.autoExpandHorizontalScroll||2!==n.advanced.autoExpandHorizontalScroll&&r>i.parent().width()?i.css({width:r,"min-width":"100%","overflow-x":"inherit"}):i.css({"overflow-x":"inherit",position:"absolute"}).wrap("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />").css({width:Math.ceil(i[0].getBoundingClientRect().right+.4)-Math.floor(i[0].getBoundingClientRect().left),"min-width":"100%",position:"relative"}).unwrap()}},w=function(){var t=e(this),o=t.data(a),n=o.opt,i=e(".mCSB_"+o.idx+"_scrollbar:first"),r=oe(n.scrollButtons.tabindex)?"tabindex='"+n.scrollButtons.tabindex+"'":"",l=["<a href='#' class='"+d[13]+"' "+r+" />","<a href='#' class='"+d[14]+"' "+r+" />","<a href='#' class='"+d[15]+"' "+r+" />","<a href='#' class='"+d[16]+"' "+r+" />"],s=["x"===n.axis?l[2]:l[0],"x"===n.axis?l[3]:l[1],l[2],l[3]];n.scrollButtons.enable&&i.prepend(s[0]).append(s[1]).next(".mCSB_scrollTools").prepend(s[2]).append(s[3])},S=function(){var t=e(this),o=t.data(a),n=e("#mCSB_"+o.idx),i=e("#mCSB_"+o.idx+"_container"),r=[e("#mCSB_"+o.idx+"_dragger_vertical"),e("#mCSB_"+o.idx+"_dragger_horizontal")],l=[n.height()/i.outerHeight(!1),n.width()/i.outerWidth(!1)],c=[parseInt(r[0].css("min-height")),Math.round(l[0]*r[0].parent().height()),parseInt(r[1].css("min-width")),Math.round(l[1]*r[1].parent().width())],d=s&&c[1]<c[0]?c[0]:c[1],u=s&&c[3]<c[2]?c[2]:c[3];r[0].css({height:d,"max-height":r[0].parent().height()-10}).find(".mCSB_dragger_bar").css({"line-height":c[0]+"px"}),r[1].css({width:u,"max-width":r[1].parent().width()-10})},b=function(){var t=e(this),o=t.data(a),n=e("#mCSB_"+o.idx),i=e("#mCSB_"+o.idx+"_container"),r=[e("#mCSB_"+o.idx+"_dragger_vertical"),e("#mCSB_"+o.idx+"_dragger_horizontal")],l=[i.outerHeight(!1)-n.height(),i.outerWidth(!1)-n.width()],s=[l[0]/(r[0].parent().height()-r[0].height()),l[1]/(r[1].parent().width()-r[1].width())];o.scrollRatio={y:s[0],x:s[1]}},C=function(e,t,o){var a=o?d[0]+"_expanded":"",n=e.closest(".mCSB_scrollTools");"active"===t?(e.toggleClass(d[0]+" "+a),n.toggleClass(d[1]),e[0]._draggable=e[0]._draggable?0:1):e[0]._draggable||("hide"===t?(e.removeClass(d[0]),n.removeClass(d[1])):(e.addClass(d[0]),n.addClass(d[1])))},y=function(){var t=e(this),o=t.data(a),n=e("#mCSB_"+o.idx),i=e("#mCSB_"+o.idx+"_container"),r=null==o.overflowed?i.height():i.outerHeight(!1),l=null==o.overflowed?i.width():i.outerWidth(!1),s=i[0].scrollHeight,c=i[0].scrollWidth;return s>r&&(r=s),c>l&&(l=c),[r>n.height(),l>n.width()]},B=function(){var t=e(this),o=t.data(a),n=o.opt,i=e("#mCSB_"+o.idx),r=e("#mCSB_"+o.idx+"_container"),l=[e("#mCSB_"+o.idx+"_dragger_vertical"),e("#mCSB_"+o.idx+"_dragger_horizontal")];if(Q(t),("x"!==n.axis&&!o.overflowed[0]||"y"===n.axis&&o.overflowed[0])&&(l[0].add(r).css("top",0),G(t,"_resetY")),"y"!==n.axis&&!o.overflowed[1]||"x"===n.axis&&o.overflowed[1]){var s=dx=0;"rtl"===o.langDir&&(s=i.width()-r.outerWidth(!1),dx=Math.abs(s/o.scrollRatio.x)),r.css("left",s),l[1].css("left",dx),G(t,"_resetX")}},T=function(){function t(){r=setTimeout(function(){e.event.special.mousewheel?(clearTimeout(r),W.call(o[0])):t()},100)}var o=e(this),n=o.data(a),i=n.opt;if(!n.bindEvents){if(I.call(this),i.contentTouchScroll&&D.call(this),E.call(this),i.mouseWheel.enable){var r;t()}P.call(this),U.call(this),i.advanced.autoScrollOnFocus&&H.call(this),i.scrollButtons.enable&&F.call(this),i.keyboard.enable&&q.call(this),n.bindEvents=!0}},k=function(){var t=e(this),o=t.data(a),n=o.opt,i=a+"_"+o.idx,r=".mCSB_"+o.idx+"_scrollbar",l=e("#mCSB_"+o.idx+",#mCSB_"+o.idx+"_container,#mCSB_"+o.idx+"_container_wrapper,"+r+" ."+d[12]+",#mCSB_"+o.idx+"_dragger_vertical,#mCSB_"+o.idx+"_dragger_horizontal,"+r+">a"),s=e("#mCSB_"+o.idx+"_container");n.advanced.releaseDraggableSelectors&&l.add(e(n.advanced.releaseDraggableSelectors)),n.advanced.extraDraggableSelectors&&l.add(e(n.advanced.extraDraggableSelectors)),o.bindEvents&&(e(document).add(e(!A()||top.document)).unbind("."+i),l.each(function(){e(this).unbind("."+i)}),clearTimeout(t[0]._focusTimeout),$(t[0],"_focusTimeout"),clearTimeout(o.sequential.step),$(o.sequential,"step"),clearTimeout(s[0].onCompleteTimeout),$(s[0],"onCompleteTimeout"),o.bindEvents=!1)},M=function(t){var o=e(this),n=o.data(a),i=n.opt,r=e("#mCSB_"+n.idx+"_container_wrapper"),l=r.length?r:e("#mCSB_"+n.idx+"_container"),s=[e("#mCSB_"+n.idx+"_scrollbar_vertical"),e("#mCSB_"+n.idx+"_scrollbar_horizontal")],c=[s[0].find(".mCSB_dragger"),s[1].find(".mCSB_dragger")];"x"!==i.axis&&(n.overflowed[0]&&!t?(s[0].add(c[0]).add(s[0].children("a")).css("display","block"),l.removeClass(d[8]+" "+d[10])):(i.alwaysShowScrollbar?(2!==i.alwaysShowScrollbar&&c[0].css("display","none"),l.removeClass(d[10])):(s[0].css("display","none"),l.addClass(d[10])),l.addClass(d[8]))),"y"!==i.axis&&(n.overflowed[1]&&!t?(s[1].add(c[1]).add(s[1].children("a")).css("display","block"),l.removeClass(d[9]+" "+d[11])):(i.alwaysShowScrollbar?(2!==i.alwaysShowScrollbar&&c[1].css("display","none"),l.removeClass(d[11])):(s[1].css("display","none"),l.addClass(d[11])),l.addClass(d[9]))),n.overflowed[0]||n.overflowed[1]?o.removeClass(d[5]):o.addClass(d[5])},O=function(t){var o=t.type,a=t.target.ownerDocument!==document&&null!==frameElement?[e(frameElement).offset().top,e(frameElement).offset().left]:null,n=A()&&t.target.ownerDocument!==top.document&&null!==frameElement?[e(t.view.frameElement).offset().top,e(t.view.frameElement).offset().left]:[0,0];switch(o){case"pointerdown":case"MSPointerDown":case"pointermove":case"MSPointerMove":case"pointerup":case"MSPointerUp":return a?[t.originalEvent.pageY-a[0]+n[0],t.originalEvent.pageX-a[1]+n[1],!1]:[t.originalEvent.pageY,t.originalEvent.pageX,!1];case"touchstart":case"touchmove":case"touchend":var i=t.originalEvent.touches[0]||t.originalEvent.changedTouches[0],r=t.originalEvent.touches.length||t.originalEvent.changedTouches.length;return t.target.ownerDocument!==document?[i.screenY,i.screenX,r>1]:[i.pageY,i.pageX,r>1];default:return a?[t.pageY-a[0]+n[0],t.pageX-a[1]+n[1],!1]:[t.pageY,t.pageX,!1]}},I=function(){function t(e,t,a,n){if(h[0].idleTimer=d.scrollInertia<233?250:0,o.attr("id")===f[1])var i="x",s=(o[0].offsetLeft-t+n)*l.scrollRatio.x;else var i="y",s=(o[0].offsetTop-e+a)*l.scrollRatio.y;G(r,s.toString(),{dir:i,drag:!0})}var o,n,i,r=e(this),l=r.data(a),d=l.opt,u=a+"_"+l.idx,f=["mCSB_"+l.idx+"_dragger_vertical","mCSB_"+l.idx+"_dragger_horizontal"],h=e("#mCSB_"+l.idx+"_container"),m=e("#"+f[0]+",#"+f[1]),p=d.advanced.releaseDraggableSelectors?m.add(e(d.advanced.releaseDraggableSelectors)):m,g=d.advanced.extraDraggableSelectors?e(!A()||top.document).add(e(d.advanced.extraDraggableSelectors)):e(!A()||top.document);m.bind("contextmenu."+u,function(e){e.preventDefault()}).bind("mousedown."+u+" touchstart."+u+" pointerdown."+u+" MSPointerDown."+u,function(t){if(t.stopImmediatePropagation(),t.preventDefault(),ee(t)){c=!0,s&&(document.onselectstart=function(){return!1}),L.call(h,!1),Q(r),o=e(this);var a=o.offset(),l=O(t)[0]-a.top,u=O(t)[1]-a.left,f=o.height()+a.top,m=o.width()+a.left;f>l&&l>0&&m>u&&u>0&&(n=l,i=u),C(o,"active",d.autoExpandScrollbar)}}).bind("touchmove."+u,function(e){e.stopImmediatePropagation(),e.preventDefault();var a=o.offset(),r=O(e)[0]-a.top,l=O(e)[1]-a.left;t(n,i,r,l)}),e(document).add(g).bind("mousemove."+u+" pointermove."+u+" MSPointerMove."+u,function(e){if(o){var a=o.offset(),r=O(e)[0]-a.top,l=O(e)[1]-a.left;if(n===r&&i===l)return;t(n,i,r,l)}}).add(p).bind("mouseup."+u+" touchend."+u+" pointerup."+u+" MSPointerUp."+u,function(){o&&(C(o,"active",d.autoExpandScrollbar),o=null),c=!1,s&&(document.onselectstart=null),L.call(h,!0)})},D=function(){function o(e){if(!te(e)||c||O(e)[2])return void(t=0);t=1,b=0,C=0,d=1,y.removeClass("mCS_touch_action");var o=I.offset();u=O(e)[0]-o.top,f=O(e)[1]-o.left,z=[O(e)[0],O(e)[1]]}function n(e){if(te(e)&&!c&&!O(e)[2]&&(T.documentTouchScroll||e.preventDefault(),e.stopImmediatePropagation(),(!C||b)&&d)){g=K();var t=M.offset(),o=O(e)[0]-t.top,a=O(e)[1]-t.left,n="mcsLinearOut";if(E.push(o),W.push(a),z[2]=Math.abs(O(e)[0]-z[0]),z[3]=Math.abs(O(e)[1]-z[1]),B.overflowed[0])var i=D[0].parent().height()-D[0].height(),r=u-o>0&&o-u>-(i*B.scrollRatio.y)&&(2*z[3]<z[2]||"yx"===T.axis);if(B.overflowed[1])var l=D[1].parent().width()-D[1].width(),h=f-a>0&&a-f>-(l*B.scrollRatio.x)&&(2*z[2]<z[3]||"yx"===T.axis);r||h?(U||e.preventDefault(),b=1):(C=1,y.addClass("mCS_touch_action")),U&&e.preventDefault(),w="yx"===T.axis?[u-o,f-a]:"x"===T.axis?[null,f-a]:[u-o,null],I[0].idleTimer=250,B.overflowed[0]&&s(w[0],R,n,"y","all",!0),B.overflowed[1]&&s(w[1],R,n,"x",L,!0)}}function i(e){if(!te(e)||c||O(e)[2])return void(t=0);t=1,e.stopImmediatePropagation(),Q(y),p=K();var o=M.offset();h=O(e)[0]-o.top,m=O(e)[1]-o.left,E=[],W=[]}function r(e){if(te(e)&&!c&&!O(e)[2]){d=0,e.stopImmediatePropagation(),b=0,C=0,v=K();var t=M.offset(),o=O(e)[0]-t.top,a=O(e)[1]-t.left;if(!(v-g>30)){_=1e3/(v-p);var n="mcsEaseOut",i=2.5>_,r=i?[E[E.length-2],W[W.length-2]]:[0,0];x=i?[o-r[0],a-r[1]]:[o-h,a-m];var u=[Math.abs(x[0]),Math.abs(x[1])];_=i?[Math.abs(x[0]/4),Math.abs(x[1]/4)]:[_,_];var f=[Math.abs(I[0].offsetTop)-x[0]*l(u[0]/_[0],_[0]),Math.abs(I[0].offsetLeft)-x[1]*l(u[1]/_[1],_[1])];w="yx"===T.axis?[f[0],f[1]]:"x"===T.axis?[null,f[1]]:[f[0],null],S=[4*u[0]+T.scrollInertia,4*u[1]+T.scrollInertia];var y=parseInt(T.contentTouchScroll)||0;w[0]=u[0]>y?w[0]:0,w[1]=u[1]>y?w[1]:0,B.overflowed[0]&&s(w[0],S[0],n,"y",L,!1),B.overflowed[1]&&s(w[1],S[1],n,"x",L,!1)}}}function l(e,t){var o=[1.5*t,2*t,t/1.5,t/2];return e>90?t>4?o[0]:o[3]:e>60?t>3?o[3]:o[2]:e>30?t>8?o[1]:t>6?o[0]:t>4?t:o[2]:t>8?t:o[3]}function s(e,t,o,a,n,i){e&&G(y,e.toString(),{dur:t,scrollEasing:o,dir:a,overwrite:n,drag:i})}var d,u,f,h,m,p,g,v,x,_,w,S,b,C,y=e(this),B=y.data(a),T=B.opt,k=a+"_"+B.idx,M=e("#mCSB_"+B.idx),I=e("#mCSB_"+B.idx+"_container"),D=[e("#mCSB_"+B.idx+"_dragger_vertical"),e("#mCSB_"+B.idx+"_dragger_horizontal")],E=[],W=[],R=0,L="yx"===T.axis?"none":"all",z=[],P=I.find("iframe"),H=["touchstart."+k+" pointerdown."+k+" MSPointerDown."+k,"touchmove."+k+" pointermove."+k+" MSPointerMove."+k,"touchend."+k+" pointerup."+k+" MSPointerUp."+k],U=void 0!==document.body.style.touchAction&&""!==document.body.style.touchAction;I.bind(H[0],function(e){o(e)}).bind(H[1],function(e){n(e)}),M.bind(H[0],function(e){i(e)}).bind(H[2],function(e){r(e)}),P.length&&P.each(function(){e(this).bind("load",function(){A(this)&&e(this.contentDocument||this.contentWindow.document).bind(H[0],function(e){o(e),i(e)}).bind(H[1],function(e){n(e)}).bind(H[2],function(e){r(e)})})})},E=function(){function o(){return window.getSelection?window.getSelection().toString():document.selection&&"Control"!=document.selection.type?document.selection.createRange().text:0}function n(e,t,o){d.type=o&&i?"stepped":"stepless",d.scrollAmount=10,j(r,e,t,"mcsLinearOut",o?60:null)}var i,r=e(this),l=r.data(a),s=l.opt,d=l.sequential,u=a+"_"+l.idx,f=e("#mCSB_"+l.idx+"_container"),h=f.parent();f.bind("mousedown."+u,function(){t||i||(i=1,c=!0)}).add(document).bind("mousemove."+u,function(e){if(!t&&i&&o()){var a=f.offset(),r=O(e)[0]-a.top+f[0].offsetTop,c=O(e)[1]-a.left+f[0].offsetLeft;r>0&&r<h.height()&&c>0&&c<h.width()?d.step&&n("off",null,"stepped"):("x"!==s.axis&&l.overflowed[0]&&(0>r?n("on",38):r>h.height()&&n("on",40)),"y"!==s.axis&&l.overflowed[1]&&(0>c?n("on",37):c>h.width()&&n("on",39)))}}).bind("mouseup."+u+" dragend."+u,function(){t||(i&&(i=0,n("off",null)),c=!1)})},W=function(){function t(t,a){if(Q(o),!z(o,t.target)){var r="auto"!==i.mouseWheel.deltaFactor?parseInt(i.mouseWheel.deltaFactor):s&&t.deltaFactor<100?100:t.deltaFactor||100,d=i.scrollInertia;if("x"===i.axis||"x"===i.mouseWheel.axis)var u="x",f=[Math.round(r*n.scrollRatio.x),parseInt(i.mouseWheel.scrollAmount)],h="auto"!==i.mouseWheel.scrollAmount?f[1]:f[0]>=l.width()?.9*l.width():f[0],m=Math.abs(e("#mCSB_"+n.idx+"_container")[0].offsetLeft),p=c[1][0].offsetLeft,g=c[1].parent().width()-c[1].width(),v="y"===i.mouseWheel.axis?t.deltaY||a:t.deltaX;else var u="y",f=[Math.round(r*n.scrollRatio.y),parseInt(i.mouseWheel.scrollAmount)],h="auto"!==i.mouseWheel.scrollAmount?f[1]:f[0]>=l.height()?.9*l.height():f[0],m=Math.abs(e("#mCSB_"+n.idx+"_container")[0].offsetTop),p=c[0][0].offsetTop,g=c[0].parent().height()-c[0].height(),v=t.deltaY||a;"y"===u&&!n.overflowed[0]||"x"===u&&!n.overflowed[1]||((i.mouseWheel.invert||t.webkitDirectionInvertedFromDevice)&&(v=-v),i.mouseWheel.normalizeDelta&&(v=0>v?-1:1),(v>0&&0!==p||0>v&&p!==g||i.mouseWheel.preventDefault)&&(t.stopImmediatePropagation(),t.preventDefault()),t.deltaFactor<5&&!i.mouseWheel.normalizeDelta&&(h=t.deltaFactor,d=17),G(o,(m-v*h).toString(),{dir:u,dur:d}))}}if(e(this).data(a)){var o=e(this),n=o.data(a),i=n.opt,r=a+"_"+n.idx,l=e("#mCSB_"+n.idx),c=[e("#mCSB_"+n.idx+"_dragger_vertical"),e("#mCSB_"+n.idx+"_dragger_horizontal")],d=e("#mCSB_"+n.idx+"_container").find("iframe");d.length&&d.each(function(){e(this).bind("load",function(){A(this)&&e(this.contentDocument||this.contentWindow.document).bind("mousewheel."+r,function(e,o){t(e,o)})})}),l.bind("mousewheel."+r,function(e,o){t(e,o)})}},R=new Object,A=function(t){var o=!1,a=!1,n=null;if(void 0===t?a="#empty":void 0!==e(t).attr("id")&&(a=e(t).attr("id")),a!==!1&&void 0!==R[a])return R[a];if(t){try{var i=t.contentDocument||t.contentWindow.document;n=i.body.innerHTML}catch(r){}o=null!==n}else{try{var i=top.document;n=i.body.innerHTML}catch(r){}o=null!==n}return a!==!1&&(R[a]=o),o},L=function(e){var t=this.find("iframe");if(t.length){var o=e?"auto":"none";t.css("pointer-events",o)}},z=function(t,o){var n=o.nodeName.toLowerCase(),i=t.data(a).opt.mouseWheel.disableOver,r=["select","textarea"];return e.inArray(n,i)>-1&&!(e.inArray(n,r)>-1&&!e(o).is(":focus"))},P=function(){var t,o=e(this),n=o.data(a),i=a+"_"+n.idx,r=e("#mCSB_"+n.idx+"_container"),l=r.parent(),s=e(".mCSB_"+n.idx+"_scrollbar ."+d[12]);s.bind("mousedown."+i+" touchstart."+i+" pointerdown."+i+" MSPointerDown."+i,function(o){c=!0,e(o.target).hasClass("mCSB_dragger")||(t=1)}).bind("touchend."+i+" pointerup."+i+" MSPointerUp."+i,function(){c=!1}).bind("click."+i,function(a){if(t&&(t=0,e(a.target).hasClass(d[12])||e(a.target).hasClass("mCSB_draggerRail"))){Q(o);var i=e(this),s=i.find(".mCSB_dragger");if(i.parent(".mCSB_scrollTools_horizontal").length>0){if(!n.overflowed[1])return;var c="x",u=a.pageX>s.offset().left?-1:1,f=Math.abs(r[0].offsetLeft)-u*(.9*l.width())}else{if(!n.overflowed[0])return;var c="y",u=a.pageY>s.offset().top?-1:1,f=Math.abs(r[0].offsetTop)-u*(.9*l.height())}G(o,f.toString(),{dir:c,scrollEasing:"mcsEaseInOut"})}})},H=function(){var t=e(this),o=t.data(a),n=o.opt,i=a+"_"+o.idx,r=e("#mCSB_"+o.idx+"_container"),l=r.parent();r.bind("focusin."+i,function(){var o=e(document.activeElement),a=r.find(".mCustomScrollBox").length,i=0;o.is(n.advanced.autoScrollOnFocus)&&(Q(t),clearTimeout(t[0]._focusTimeout),t[0]._focusTimer=a?(i+17)*a:0,t[0]._focusTimeout=setTimeout(function(){var e=[ae(o)[0],ae(o)[1]],a=[r[0].offsetTop,r[0].offsetLeft],s=[a[0]+e[0]>=0&&a[0]+e[0]<l.height()-o.outerHeight(!1),a[1]+e[1]>=0&&a[0]+e[1]<l.width()-o.outerWidth(!1)],c="yx"!==n.axis||s[0]||s[1]?"all":"none";"x"===n.axis||s[0]||G(t,e[0].toString(),{dir:"y",scrollEasing:"mcsEaseInOut",overwrite:c,dur:i}),"y"===n.axis||s[1]||G(t,e[1].toString(),{dir:"x",scrollEasing:"mcsEaseInOut",overwrite:c,dur:i})},t[0]._focusTimer))})},U=function(){var t=e(this),o=t.data(a),n=a+"_"+o.idx,i=e("#mCSB_"+o.idx+"_container").parent();i.bind("scroll."+n,function(){0===i.scrollTop()&&0===i.scrollLeft()||e(".mCSB_"+o.idx+"_scrollbar").css("visibility","hidden")})},F=function(){var t=e(this),o=t.data(a),n=o.opt,i=o.sequential,r=a+"_"+o.idx,l=".mCSB_"+o.idx+"_scrollbar",s=e(l+">a");s.bind("contextmenu."+r,function(e){e.preventDefault()}).bind("mousedown."+r+" touchstart."+r+" pointerdown."+r+" MSPointerDown."+r+" mouseup."+r+" touchend."+r+" pointerup."+r+" MSPointerUp."+r+" mouseout."+r+" pointerout."+r+" MSPointerOut."+r+" click."+r,function(a){function r(e,o){i.scrollAmount=n.scrollButtons.scrollAmount,j(t,e,o)}if(a.preventDefault(),ee(a)){var l=e(this).attr("class");switch(i.type=n.scrollButtons.scrollType,a.type){case"mousedown":case"touchstart":case"pointerdown":case"MSPointerDown":if("stepped"===i.type)return;c=!0,o.tweenRunning=!1,r("on",l);break;case"mouseup":case"touchend":case"pointerup":case"MSPointerUp":case"mouseout":case"pointerout":case"MSPointerOut":if("stepped"===i.type)return;c=!1,i.dir&&r("off",l);break;case"click":if("stepped"!==i.type||o.tweenRunning)return;r("on",l)}}})},q=function(){function t(t){function a(e,t){r.type=i.keyboard.scrollType,r.scrollAmount=i.keyboard.scrollAmount,"stepped"===r.type&&n.tweenRunning||j(o,e,t)}switch(t.type){case"blur":n.tweenRunning&&r.dir&&a("off",null);break;case"keydown":case"keyup":var l=t.keyCode?t.keyCode:t.which,s="on";if("x"!==i.axis&&(38===l||40===l)||"y"!==i.axis&&(37===l||39===l)){if((38===l||40===l)&&!n.overflowed[0]||(37===l||39===l)&&!n.overflowed[1])return;"keyup"===t.type&&(s="off"),e(document.activeElement).is(u)||(t.preventDefault(),t.stopImmediatePropagation(),a(s,l))}else if(33===l||34===l){if((n.overflowed[0]||n.overflowed[1])&&(t.preventDefault(),t.stopImmediatePropagation()),"keyup"===t.type){Q(o);var f=34===l?-1:1;if("x"===i.axis||"yx"===i.axis&&n.overflowed[1]&&!n.overflowed[0])var h="x",m=Math.abs(c[0].offsetLeft)-f*(.9*d.width());else var h="y",m=Math.abs(c[0].offsetTop)-f*(.9*d.height());G(o,m.toString(),{dir:h,scrollEasing:"mcsEaseInOut"})}}else if((35===l||36===l)&&!e(document.activeElement).is(u)&&((n.overflowed[0]||n.overflowed[1])&&(t.preventDefault(),t.stopImmediatePropagation()),"keyup"===t.type)){if("x"===i.axis||"yx"===i.axis&&n.overflowed[1]&&!n.overflowed[0])var h="x",m=35===l?Math.abs(d.width()-c.outerWidth(!1)):0;else var h="y",m=35===l?Math.abs(d.height()-c.outerHeight(!1)):0;G(o,m.toString(),{dir:h,scrollEasing:"mcsEaseInOut"})}}}var o=e(this),n=o.data(a),i=n.opt,r=n.sequential,l=a+"_"+n.idx,s=e("#mCSB_"+n.idx),c=e("#mCSB_"+n.idx+"_container"),d=c.parent(),u="input,textarea,select,datalist,keygen,[contenteditable='true']",f=c.find("iframe"),h=["blur."+l+" keydown."+l+" keyup."+l];f.length&&f.each(function(){e(this).bind("load",function(){A(this)&&e(this.contentDocument||this.contentWindow.document).bind(h[0],function(e){t(e)})})}),s.attr("tabindex","0").bind(h[0],function(e){t(e)})},j=function(t,o,n,i,r){function l(e){u.snapAmount&&(f.scrollAmount=u.snapAmount instanceof Array?"x"===f.dir[0]?u.snapAmount[1]:u.snapAmount[0]:u.snapAmount);var o="stepped"!==f.type,a=r?r:e?o?p/1.5:g:1e3/60,n=e?o?7.5:40:2.5,s=[Math.abs(h[0].offsetTop),Math.abs(h[0].offsetLeft)],d=[c.scrollRatio.y>10?10:c.scrollRatio.y,c.scrollRatio.x>10?10:c.scrollRatio.x],m="x"===f.dir[0]?s[1]+f.dir[1]*(d[1]*n):s[0]+f.dir[1]*(d[0]*n),v="x"===f.dir[0]?s[1]+f.dir[1]*parseInt(f.scrollAmount):s[0]+f.dir[1]*parseInt(f.scrollAmount),x="auto"!==f.scrollAmount?v:m,_=i?i:e?o?"mcsLinearOut":"mcsEaseInOut":"mcsLinear",w=!!e;return e&&17>a&&(x="x"===f.dir[0]?s[1]:s[0]),G(t,x.toString(),{dir:f.dir[0],scrollEasing:_,dur:a,onComplete:w}),e?void(f.dir=!1):(clearTimeout(f.step),void(f.step=setTimeout(function(){l()},a)))}function s(){clearTimeout(f.step),$(f,"step"),Q(t)}var c=t.data(a),u=c.opt,f=c.sequential,h=e("#mCSB_"+c.idx+"_container"),m="stepped"===f.type,p=u.scrollInertia<26?26:u.scrollInertia,g=u.scrollInertia<1?17:u.scrollInertia;switch(o){case"on":if(f.dir=[n===d[16]||n===d[15]||39===n||37===n?"x":"y",n===d[13]||n===d[15]||38===n||37===n?-1:1],Q(t),oe(n)&&"stepped"===f.type)return;l(m);break;case"off":s(),(m||c.tweenRunning&&f.dir)&&l(!0)}},Y=function(t){var o=e(this).data(a).opt,n=[];return"function"==typeof t&&(t=t()),t instanceof Array?n=t.length>1?[t[0],t[1]]:"x"===o.axis?[null,t[0]]:[t[0],null]:(n[0]=t.y?t.y:t.x||"x"===o.axis?null:t,n[1]=t.x?t.x:t.y||"y"===o.axis?null:t),"function"==typeof n[0]&&(n[0]=n[0]()),"function"==typeof n[1]&&(n[1]=n[1]()),n},X=function(t,o){if(null!=t&&"undefined"!=typeof t){var n=e(this),i=n.data(a),r=i.opt,l=e("#mCSB_"+i.idx+"_container"),s=l.parent(),c=typeof t;o||(o="x"===r.axis?"x":"y");var d="x"===o?l.outerWidth(!1)-s.width():l.outerHeight(!1)-s.height(),f="x"===o?l[0].offsetLeft:l[0].offsetTop,h="x"===o?"left":"top";switch(c){case"function":return t();case"object":var m=t.jquery?t:e(t);if(!m.length)return;return"x"===o?ae(m)[1]:ae(m)[0];case"string":case"number":if(oe(t))return Math.abs(t);if(-1!==t.indexOf("%"))return Math.abs(d*parseInt(t)/100);if(-1!==t.indexOf("-="))return Math.abs(f-parseInt(t.split("-=")[1]));if(-1!==t.indexOf("+=")){var p=f+parseInt(t.split("+=")[1]);return p>=0?0:Math.abs(p)}if(-1!==t.indexOf("px")&&oe(t.split("px")[0]))return Math.abs(t.split("px")[0]);if("top"===t||"left"===t)return 0;if("bottom"===t)return Math.abs(s.height()-l.outerHeight(!1));if("right"===t)return Math.abs(s.width()-l.outerWidth(!1));if("first"===t||"last"===t){var m=l.find(":"+t);return"x"===o?ae(m)[1]:ae(m)[0]}return e(t).length?"x"===o?ae(e(t))[1]:ae(e(t))[0]:(l.css(h,t),void u.update.call(null,n[0]))}}},N=function(t){function o(){return clearTimeout(f[0].autoUpdate),0===l.parents("html").length?void(l=null):void(f[0].autoUpdate=setTimeout(function(){return c.advanced.updateOnSelectorChange&&(s.poll.change.n=i(),s.poll.change.n!==s.poll.change.o)?(s.poll.change.o=s.poll.change.n,void r(3)):c.advanced.updateOnContentResize&&(s.poll.size.n=l[0].scrollHeight+l[0].scrollWidth+f[0].offsetHeight+l[0].offsetHeight+l[0].offsetWidth,s.poll.size.n!==s.poll.size.o)?(s.poll.size.o=s.poll.size.n,void r(1)):!c.advanced.updateOnImageLoad||"auto"===c.advanced.updateOnImageLoad&&"y"===c.axis||(s.poll.img.n=f.find("img").length,s.poll.img.n===s.poll.img.o)?void((c.advanced.updateOnSelectorChange||c.advanced.updateOnContentResize||c.advanced.updateOnImageLoad)&&o()):(s.poll.img.o=s.poll.img.n,void f.find("img").each(function(){n(this)}))},c.advanced.autoUpdateTimeout))}function n(t){function o(e,t){return function(){
    return t.apply(e,arguments)}}function a(){this.onload=null,e(t).addClass(d[2]),r(2)}if(e(t).hasClass(d[2]))return void r();var n=new Image;n.onload=o(n,a),n.src=t.src}function i(){c.advanced.updateOnSelectorChange===!0&&(c.advanced.updateOnSelectorChange="*");var e=0,t=f.find(c.advanced.updateOnSelectorChange);return c.advanced.updateOnSelectorChange&&t.length>0&&t.each(function(){e+=this.offsetHeight+this.offsetWidth}),e}function r(e){clearTimeout(f[0].autoUpdate),u.update.call(null,l[0],e)}var l=e(this),s=l.data(a),c=s.opt,f=e("#mCSB_"+s.idx+"_container");return t?(clearTimeout(f[0].autoUpdate),void $(f[0],"autoUpdate")):void o()},V=function(e,t,o){return Math.round(e/t)*t-o},Q=function(t){var o=t.data(a),n=e("#mCSB_"+o.idx+"_container,#mCSB_"+o.idx+"_container_wrapper,#mCSB_"+o.idx+"_dragger_vertical,#mCSB_"+o.idx+"_dragger_horizontal");n.each(function(){Z.call(this)})},G=function(t,o,n){function i(e){return s&&c.callbacks[e]&&"function"==typeof c.callbacks[e]}function r(){return[c.callbacks.alwaysTriggerOffsets||w>=S[0]+y,c.callbacks.alwaysTriggerOffsets||-B>=w]}function l(){var e=[h[0].offsetTop,h[0].offsetLeft],o=[x[0].offsetTop,x[0].offsetLeft],a=[h.outerHeight(!1),h.outerWidth(!1)],i=[f.height(),f.width()];t[0].mcs={content:h,top:e[0],left:e[1],draggerTop:o[0],draggerLeft:o[1],topPct:Math.round(100*Math.abs(e[0])/(Math.abs(a[0])-i[0])),leftPct:Math.round(100*Math.abs(e[1])/(Math.abs(a[1])-i[1])),direction:n.dir}}var s=t.data(a),c=s.opt,d={trigger:"internal",dir:"y",scrollEasing:"mcsEaseOut",drag:!1,dur:c.scrollInertia,overwrite:"all",callbacks:!0,onStart:!0,onUpdate:!0,onComplete:!0},n=e.extend(d,n),u=[n.dur,n.drag?0:n.dur],f=e("#mCSB_"+s.idx),h=e("#mCSB_"+s.idx+"_container"),m=h.parent(),p=c.callbacks.onTotalScrollOffset?Y.call(t,c.callbacks.onTotalScrollOffset):[0,0],g=c.callbacks.onTotalScrollBackOffset?Y.call(t,c.callbacks.onTotalScrollBackOffset):[0,0];if(s.trigger=n.trigger,0===m.scrollTop()&&0===m.scrollLeft()||(e(".mCSB_"+s.idx+"_scrollbar").css("visibility","visible"),m.scrollTop(0).scrollLeft(0)),"_resetY"!==o||s.contentReset.y||(i("onOverflowYNone")&&c.callbacks.onOverflowYNone.call(t[0]),s.contentReset.y=1),"_resetX"!==o||s.contentReset.x||(i("onOverflowXNone")&&c.callbacks.onOverflowXNone.call(t[0]),s.contentReset.x=1),"_resetY"!==o&&"_resetX"!==o){if(!s.contentReset.y&&t[0].mcs||!s.overflowed[0]||(i("onOverflowY")&&c.callbacks.onOverflowY.call(t[0]),s.contentReset.x=null),!s.contentReset.x&&t[0].mcs||!s.overflowed[1]||(i("onOverflowX")&&c.callbacks.onOverflowX.call(t[0]),s.contentReset.x=null),c.snapAmount){var v=c.snapAmount instanceof Array?"x"===n.dir?c.snapAmount[1]:c.snapAmount[0]:c.snapAmount;o=V(o,v,c.snapOffset)}switch(n.dir){case"x":var x=e("#mCSB_"+s.idx+"_dragger_horizontal"),_="left",w=h[0].offsetLeft,S=[f.width()-h.outerWidth(!1),x.parent().width()-x.width()],b=[o,0===o?0:o/s.scrollRatio.x],y=p[1],B=g[1],T=y>0?y/s.scrollRatio.x:0,k=B>0?B/s.scrollRatio.x:0;break;case"y":var x=e("#mCSB_"+s.idx+"_dragger_vertical"),_="top",w=h[0].offsetTop,S=[f.height()-h.outerHeight(!1),x.parent().height()-x.height()],b=[o,0===o?0:o/s.scrollRatio.y],y=p[0],B=g[0],T=y>0?y/s.scrollRatio.y:0,k=B>0?B/s.scrollRatio.y:0}b[1]<0||0===b[0]&&0===b[1]?b=[0,0]:b[1]>=S[1]?b=[S[0],S[1]]:b[0]=-b[0],t[0].mcs||(l(),i("onInit")&&c.callbacks.onInit.call(t[0])),clearTimeout(h[0].onCompleteTimeout),J(x[0],_,Math.round(b[1]),u[1],n.scrollEasing),!s.tweenRunning&&(0===w&&b[0]>=0||w===S[0]&&b[0]<=S[0])||J(h[0],_,Math.round(b[0]),u[0],n.scrollEasing,n.overwrite,{onStart:function(){n.callbacks&&n.onStart&&!s.tweenRunning&&(i("onScrollStart")&&(l(),c.callbacks.onScrollStart.call(t[0])),s.tweenRunning=!0,C(x),s.cbOffsets=r())},onUpdate:function(){n.callbacks&&n.onUpdate&&i("whileScrolling")&&(l(),c.callbacks.whileScrolling.call(t[0]))},onComplete:function(){if(n.callbacks&&n.onComplete){"yx"===c.axis&&clearTimeout(h[0].onCompleteTimeout);var e=h[0].idleTimer||0;h[0].onCompleteTimeout=setTimeout(function(){i("onScroll")&&(l(),c.callbacks.onScroll.call(t[0])),i("onTotalScroll")&&b[1]>=S[1]-T&&s.cbOffsets[0]&&(l(),c.callbacks.onTotalScroll.call(t[0])),i("onTotalScrollBack")&&b[1]<=k&&s.cbOffsets[1]&&(l(),c.callbacks.onTotalScrollBack.call(t[0])),s.tweenRunning=!1,h[0].idleTimer=0,C(x,"hide")},e)}}})}},J=function(e,t,o,a,n,i,r){function l(){S.stop||(x||m.call(),x=K()-v,s(),x>=S.time&&(S.time=x>S.time?x+f-(x-S.time):x+f-1,S.time<x+1&&(S.time=x+1)),S.time<a?S.id=h(l):g.call())}function s(){a>0?(S.currVal=u(S.time,_,b,a,n),w[t]=Math.round(S.currVal)+"px"):w[t]=o+"px",p.call()}function c(){f=1e3/60,S.time=x+f,h=window.requestAnimationFrame?window.requestAnimationFrame:function(e){return s(),setTimeout(e,.01)},S.id=h(l)}function d(){null!=S.id&&(window.requestAnimationFrame?window.cancelAnimationFrame(S.id):clearTimeout(S.id),S.id=null)}function u(e,t,o,a,n){switch(n){case"linear":case"mcsLinear":return o*e/a+t;case"mcsLinearOut":return e/=a,e--,o*Math.sqrt(1-e*e)+t;case"easeInOutSmooth":return e/=a/2,1>e?o/2*e*e+t:(e--,-o/2*(e*(e-2)-1)+t);case"easeInOutStrong":return e/=a/2,1>e?o/2*Math.pow(2,10*(e-1))+t:(e--,o/2*(-Math.pow(2,-10*e)+2)+t);case"easeInOut":case"mcsEaseInOut":return e/=a/2,1>e?o/2*e*e*e+t:(e-=2,o/2*(e*e*e+2)+t);case"easeOutSmooth":return e/=a,e--,-o*(e*e*e*e-1)+t;case"easeOutStrong":return o*(-Math.pow(2,-10*e/a)+1)+t;case"easeOut":case"mcsEaseOut":default:var i=(e/=a)*e,r=i*e;return t+o*(.499999999999997*r*i+-2.5*i*i+5.5*r+-6.5*i+4*e)}}e._mTween||(e._mTween={top:{},left:{}});var f,h,r=r||{},m=r.onStart||function(){},p=r.onUpdate||function(){},g=r.onComplete||function(){},v=K(),x=0,_=e.offsetTop,w=e.style,S=e._mTween[t];"left"===t&&(_=e.offsetLeft);var b=o-_;S.stop=0,"none"!==i&&d(),c()},K=function(){return window.performance&&window.performance.now?window.performance.now():window.performance&&window.performance.webkitNow?window.performance.webkitNow():Date.now?Date.now():(new Date).getTime()},Z=function(){var e=this;e._mTween||(e._mTween={top:{},left:{}});for(var t=["top","left"],o=0;o<t.length;o++){var a=t[o];e._mTween[a].id&&(window.requestAnimationFrame?window.cancelAnimationFrame(e._mTween[a].id):clearTimeout(e._mTween[a].id),e._mTween[a].id=null,e._mTween[a].stop=1)}},$=function(e,t){try{delete e[t]}catch(o){e[t]=null}},ee=function(e){return!(e.which&&1!==e.which)},te=function(e){var t=e.originalEvent.pointerType;return!(t&&"touch"!==t&&2!==t)},oe=function(e){return!isNaN(parseFloat(e))&&isFinite(e)},ae=function(e){var t=e.parents(".mCSB_container");return[e.offset().top-t.offset().top,e.offset().left-t.offset().left]},ne=function(){function e(){var e=["webkit","moz","ms","o"];if("hidden"in document)return"hidden";for(var t=0;t<e.length;t++)if(e[t]+"Hidden"in document)return e[t]+"Hidden";return null}var t=e();return t?document[t]:!1};e.fn[o]=function(t){return u[t]?u[t].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof t&&t?void e.error("Method "+t+" does not exist"):u.init.apply(this,arguments)},e[o]=function(t){return u[t]?u[t].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof t&&t?void e.error("Method "+t+" does not exist"):u.init.apply(this,arguments)},e[o].defaults=i,window[o]=!0,e(window).bind("load",function(){e(n)[o](),e.extend(e.expr[":"],{mcsInView:e.expr[":"].mcsInView||function(t){var o,a,n=e(t),i=n.parents(".mCSB_container");if(i.length)return o=i.parent(),a=[i[0].offsetTop,i[0].offsetLeft],a[0]+ae(n)[0]>=0&&a[0]+ae(n)[0]<o.height()-n.outerHeight(!1)&&a[1]+ae(n)[1]>=0&&a[1]+ae(n)[1]<o.width()-n.outerWidth(!1)},mcsInSight:e.expr[":"].mcsInSight||function(t,o,a){var n,i,r,l,s=e(t),c=s.parents(".mCSB_container"),d="exact"===a[3]?[[1,0],[1,0]]:[[.9,.1],[.6,.4]];if(c.length)return n=[s.outerHeight(!1),s.outerWidth(!1)],r=[c[0].offsetTop+ae(s)[0],c[0].offsetLeft+ae(s)[1]],i=[c.parent()[0].offsetHeight,c.parent()[0].offsetWidth],l=[n[0]<i[0]?d[0]:d[1],n[1]<i[1]?d[0]:d[1]],r[0]-i[0]*l[0][0]<0&&r[0]+n[0]-i[0]*l[0][1]>=0&&r[1]-i[1]*l[1][0]<0&&r[1]+n[1]-i[1]*l[1][1]>=0},mcsOverflow:e.expr[":"].mcsOverflow||function(t){var o=e(t).data(a);if(o)return o.overflowed[0]||o.overflowed[1]}})})})});

/* Chosen v1.1.0 | (c) 2011-2013 by Harvest | MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md */
!function(){var a,AbstractChosen,Chosen,SelectParser,b,c={}.hasOwnProperty,d=function(a,b){function d(){this.constructor=a}for(var e in b)c.call(b,e)&&(a[e]=b[e]);return d.prototype=b.prototype,a.prototype=new d,a.__super__=b.prototype,a};SelectParser=function(){function SelectParser(){this.options_index=0,this.parsed=[]}return SelectParser.prototype.add_node=function(a){return"OPTGROUP"===a.nodeName.toUpperCase()?this.add_group(a):this.add_option(a)},SelectParser.prototype.add_group=function(a){var b,c,d,e,f,g;for(b=this.parsed.length,this.parsed.push({array_index:b,group:!0,label:this.escapeExpression(a.label),children:0,disabled:a.disabled}),f=a.childNodes,g=[],d=0,e=f.length;e>d;d++)c=f[d],g.push(this.add_option(c,b,a.disabled));return g},SelectParser.prototype.add_option=function(a,b,c){return"OPTION"===a.nodeName.toUpperCase()?(""!==a.text?(null!=b&&(this.parsed[b].children+=1),this.parsed.push({array_index:this.parsed.length,options_index:this.options_index,value:a.value,text:a.text,html:a.innerHTML,selected:a.selected,disabled:c===!0?c:a.disabled,group_array_index:b,classes:a.className,style:a.style.cssText})):this.parsed.push({array_index:this.parsed.length,options_index:this.options_index,empty:!0}),this.options_index+=1):void 0},SelectParser.prototype.escapeExpression=function(a){var b,c;return null==a||a===!1?"":/[\&\<\>\"\'\`]/.test(a)?(b={"<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","`":"&#x60;"},c=/&(?!\w+;)|[\<\>\"\'\`]/g,a.replace(c,function(a){return b[a]||"&amp;"})):a},SelectParser}(),SelectParser.select_to_array=function(a){var b,c,d,e,f;for(c=new SelectParser,f=a.childNodes,d=0,e=f.length;e>d;d++)b=f[d],c.add_node(b);return c.parsed},AbstractChosen=function(){function AbstractChosen(a,b){this.form_field=a,this.options=null!=b?b:{},AbstractChosen.browser_is_supported()&&(this.is_multiple=this.form_field.multiple,this.set_default_text(),this.set_default_values(),this.setup(),this.set_up_html(),this.register_observers())}return AbstractChosen.prototype.set_default_values=function(){var a=this;return this.click_test_action=function(b){return a.test_active_click(b)},this.activate_action=function(b){return a.activate_field(b)},this.active_field=!1,this.mouse_on_container=!1,this.results_showing=!1,this.result_highlighted=null,this.allow_single_deselect=null!=this.options.allow_single_deselect&&null!=this.form_field.options[0]&&""===this.form_field.options[0].text?this.options.allow_single_deselect:!1,this.disable_search_threshold=this.options.disable_search_threshold||0,this.disable_search=this.options.disable_search||!1,this.enable_split_word_search=null!=this.options.enable_split_word_search?this.options.enable_split_word_search:!0,this.group_search=null!=this.options.group_search?this.options.group_search:!0,this.search_contains=this.options.search_contains||!1,this.single_backstroke_delete=null!=this.options.single_backstroke_delete?this.options.single_backstroke_delete:!0,this.max_selected_options=this.options.max_selected_options||1/0,this.inherit_select_classes=this.options.inherit_select_classes||!1,this.display_selected_options=null!=this.options.display_selected_options?this.options.display_selected_options:!0,this.display_disabled_options=null!=this.options.display_disabled_options?this.options.display_disabled_options:!0},AbstractChosen.prototype.set_default_text=function(){return this.default_text=this.form_field.getAttribute("data-placeholder")?this.form_field.getAttribute("data-placeholder"):this.is_multiple?this.options.placeholder_text_multiple||this.options.placeholder_text||AbstractChosen.default_multiple_text:this.options.placeholder_text_single||this.options.placeholder_text||AbstractChosen.default_single_text,this.results_none_found=this.form_field.getAttribute("data-no_results_text")||this.options.no_results_text||AbstractChosen.default_no_result_text},AbstractChosen.prototype.mouse_enter=function(){return this.mouse_on_container=!0},AbstractChosen.prototype.mouse_leave=function(){return this.mouse_on_container=!1},AbstractChosen.prototype.input_focus=function(){var a=this;if(this.is_multiple){if(!this.active_field)return setTimeout(function(){return a.container_mousedown()},50)}else if(!this.active_field)return this.activate_field()},AbstractChosen.prototype.input_blur=function(){var a=this;return this.mouse_on_container?void 0:(this.active_field=!1,setTimeout(function(){return a.blur_test()},100))},AbstractChosen.prototype.results_option_build=function(a){var b,c,d,e,f;for(b="",f=this.results_data,d=0,e=f.length;e>d;d++)c=f[d],b+=c.group?this.result_add_group(c):this.result_add_option(c),(null!=a?a.first:void 0)&&(c.selected&&this.is_multiple?this.choice_build(c):c.selected&&!this.is_multiple&&this.single_set_selected_text(c.text));return b},AbstractChosen.prototype.result_add_option=function(a){var b,c;return a.search_match?this.include_option_in_results(a)?(b=[],a.disabled||a.selected&&this.is_multiple||b.push("active-result"),!a.disabled||a.selected&&this.is_multiple||b.push("disabled-result"),a.selected&&b.push("result-selected"),null!=a.group_array_index&&b.push("group-option"),""!==a.classes&&b.push(a.classes),c=document.createElement("li"),c.className=b.join(" "),c.style.cssText=a.style,c.setAttribute("data-option-array-index",a.array_index),c.innerHTML=a.search_text,this.outerHTML(c)):"":""},AbstractChosen.prototype.result_add_group=function(a){var b;return a.search_match||a.group_match?a.active_options>0?(b=document.createElement("li"),b.className="group-result",b.innerHTML=a.search_text,this.outerHTML(b)):"":""},AbstractChosen.prototype.results_update_field=function(){return this.set_default_text(),this.is_multiple||this.results_reset_cleanup(),this.result_clear_highlight(),this.results_build(),this.results_showing?this.winnow_results():void 0},AbstractChosen.prototype.reset_single_select_options=function(){var a,b,c,d,e;for(d=this.results_data,e=[],b=0,c=d.length;c>b;b++)a=d[b],a.selected?e.push(a.selected=!1):e.push(void 0);return e},AbstractChosen.prototype.results_toggle=function(){return this.results_showing?this.results_hide():this.results_show()},AbstractChosen.prototype.results_search=function(){return this.results_showing?this.winnow_results():this.results_show()},AbstractChosen.prototype.winnow_results=function(){var a,b,c,d,e,f,g,h,i,j,k,l,m;for(this.no_results_clear(),e=0,g=this.get_search_text(),a=g.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),d=this.search_contains?"":"^",c=new RegExp(d+a,"i"),j=new RegExp(a,"i"),m=this.results_data,k=0,l=m.length;l>k;k++)b=m[k],b.search_match=!1,f=null,this.include_option_in_results(b)&&(b.group&&(b.group_match=!1,b.active_options=0),null!=b.group_array_index&&this.results_data[b.group_array_index]&&(f=this.results_data[b.group_array_index],0===f.active_options&&f.search_match&&(e+=1),f.active_options+=1),(!b.group||this.group_search)&&(b.search_text=b.group?b.label:b.html,b.search_match=this.search_string_match(b.search_text,c),b.search_match&&!b.group&&(e+=1),b.search_match?(g.length&&(h=b.search_text.search(j),i=b.search_text.substr(0,h+g.length)+"</em>"+b.search_text.substr(h+g.length),b.search_text=i.substr(0,h)+"<em>"+i.substr(h)),null!=f&&(f.group_match=!0)):null!=b.group_array_index&&this.results_data[b.group_array_index].search_match&&(b.search_match=!0)));return this.result_clear_highlight(),1>e&&g.length?(this.update_results_content(""),this.no_results(g)):(this.update_results_content(this.results_option_build()),this.winnow_results_set_highlight())},AbstractChosen.prototype.search_string_match=function(a,b){var c,d,e,f;if(b.test(a))return!0;if(this.enable_split_word_search&&(a.indexOf(" ")>=0||0===a.indexOf("["))&&(d=a.replace(/\[|\]/g,"").split(" "),d.length))for(e=0,f=d.length;f>e;e++)if(c=d[e],b.test(c))return!0},AbstractChosen.prototype.choices_count=function(){var a,b,c,d;if(null!=this.selected_option_count)return this.selected_option_count;for(this.selected_option_count=0,d=this.form_field.options,b=0,c=d.length;c>b;b++)a=d[b],a.selected&&(this.selected_option_count+=1);return this.selected_option_count},AbstractChosen.prototype.choices_click=function(a){return a.preventDefault(),this.results_showing||this.is_disabled?void 0:this.results_show()},AbstractChosen.prototype.keyup_checker=function(a){var b,c;switch(b=null!=(c=a.which)?c:a.keyCode,this.search_field_scale(),b){case 8:if(this.is_multiple&&this.backstroke_length<1&&this.choices_count()>0)return this.keydown_backstroke();if(!this.pending_backstroke)return this.result_clear_highlight(),this.results_search();break;case 13:if(a.preventDefault(),this.results_showing)return this.result_select(a);break;case 27:return this.results_showing&&this.results_hide(),!0;case 9:case 38:case 40:case 16:case 91:case 17:break;default:return this.results_search()}},AbstractChosen.prototype.clipboard_event_checker=function(){var a=this;return setTimeout(function(){return a.results_search()},50)},AbstractChosen.prototype.container_width=function(){return null!=this.options.width?this.options.width:""+this.form_field.offsetWidth+"px"},AbstractChosen.prototype.include_option_in_results=function(a){return this.is_multiple&&!this.display_selected_options&&a.selected?!1:!this.display_disabled_options&&a.disabled?!1:a.empty?!1:!0},AbstractChosen.prototype.search_results_touchstart=function(a){return this.touch_started=!0,this.search_results_mouseover(a)},AbstractChosen.prototype.search_results_touchmove=function(a){return this.touch_started=!1,this.search_results_mouseout(a)},AbstractChosen.prototype.search_results_touchend=function(a){return this.touch_started?this.search_results_mouseup(a):void 0},AbstractChosen.prototype.outerHTML=function(a){var b;return a.outerHTML?a.outerHTML:(b=document.createElement("div"),b.appendChild(a),b.innerHTML)},AbstractChosen.browser_is_supported=function(){return"Microsoft Internet Explorer"===window.navigator.appName?document.documentMode>=8:/iP(od|hone)/i.test(window.navigator.userAgent)?!1:/Android/i.test(window.navigator.userAgent)&&/Mobile/i.test(window.navigator.userAgent)?!1:!0},AbstractChosen.default_multiple_text="Select Some Options",AbstractChosen.default_single_text="Select an Option",AbstractChosen.default_no_result_text="No results match",AbstractChosen}(),a=jQuery,a.fn.extend({chosen:function(b){return AbstractChosen.browser_is_supported()?this.each(function(){var c,d;c=a(this),d=c.data("chosen"),"destroy"===b&&d?d.destroy():d||c.data("chosen",new Chosen(this,b))}):this}}),Chosen=function(c){function Chosen(){return b=Chosen.__super__.constructor.apply(this,arguments)}return d(Chosen,c),Chosen.prototype.setup=function(){return this.form_field_jq=a(this.form_field),this.current_selectedIndex=this.form_field.selectedIndex,this.is_rtl=this.form_field_jq.hasClass("chosen-rtl")},Chosen.prototype.set_up_html=function(){var b,c;return b=["chosen-container"],b.push("chosen-container-"+(this.is_multiple?"multi":"single")),this.inherit_select_classes&&this.form_field.className&&b.push(this.form_field.className),this.is_rtl&&b.push("chosen-rtl"),c={"class":b.join(" "),style:"width: "+this.container_width()+";",title:this.form_field.title},this.form_field.id.length&&(c.id=this.form_field.id.replace(/[^\w]/g,"_")+"_chosen"),this.container=a("<div />",c),this.is_multiple?this.container.html('<ul class="chosen-choices"><li class="search-field"><input type="text" value="'+this.default_text+'" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chosen-drop"><ul class="chosen-results"></ul></div>'):this.container.html('<a class="chosen-single chosen-default" tabindex="-1"><span>'+this.default_text+'</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text" autocomplete="off" /></div><ul class="chosen-results"></ul></div>'),this.form_field_jq.hide().after(this.container),this.dropdown=this.container.find("div.chosen-drop").first(),this.search_field=this.container.find("input").first(),this.search_results=this.container.find("ul.chosen-results").first(),this.search_field_scale(),this.search_no_results=this.container.find("li.no-results").first(),this.is_multiple?(this.search_choices=this.container.find("ul.chosen-choices").first(),this.search_container=this.container.find("li.search-field").first()):(this.search_container=this.container.find("div.chosen-search").first(),this.selected_item=this.container.find(".chosen-single").first()),this.results_build(),this.set_tab_index(),this.set_label_behavior(),this.form_field_jq.trigger("chosen:ready",{chosen:this})},Chosen.prototype.register_observers=function(){var a=this;return this.container.bind("mousedown.chosen",function(b){a.container_mousedown(b)}),this.container.bind("mouseup.chosen",function(b){a.container_mouseup(b)}),this.container.bind("mouseenter.chosen",function(b){a.mouse_enter(b)}),this.container.bind("mouseleave.chosen",function(b){a.mouse_leave(b)}),this.search_results.bind("mouseup.chosen",function(b){a.search_results_mouseup(b)}),this.search_results.bind("mouseover.chosen",function(b){a.search_results_mouseover(b)}),this.search_results.bind("mouseout.chosen",function(b){a.search_results_mouseout(b)}),this.search_results.bind("mousewheel.chosen DOMMouseScroll.chosen",function(b){a.search_results_mousewheel(b)}),this.search_results.bind("touchstart.chosen",function(b){a.search_results_touchstart(b)}),this.search_results.bind("touchmove.chosen",function(b){a.search_results_touchmove(b)}),this.search_results.bind("touchend.chosen",function(b){a.search_results_touchend(b)}),this.form_field_jq.bind("chosen:updated.chosen",function(b){a.results_update_field(b)}),this.form_field_jq.bind("chosen:activate.chosen",function(b){a.activate_field(b)}),this.form_field_jq.bind("chosen:open.chosen",function(b){a.container_mousedown(b)}),this.form_field_jq.bind("chosen:close.chosen",function(b){a.input_blur(b)}),this.search_field.bind("blur.chosen",function(b){a.input_blur(b)}),this.search_field.bind("keyup.chosen",function(b){a.keyup_checker(b)}),this.search_field.bind("keydown.chosen",function(b){a.keydown_checker(b)}),this.search_field.bind("focus.chosen",function(b){a.input_focus(b)}),this.search_field.bind("cut.chosen",function(b){a.clipboard_event_checker(b)}),this.search_field.bind("paste.chosen",function(b){a.clipboard_event_checker(b)}),this.is_multiple?this.search_choices.bind("click.chosen",function(b){a.choices_click(b)}):this.container.bind("click.chosen",function(a){a.preventDefault()})},Chosen.prototype.destroy=function(){return a(this.container[0].ownerDocument).unbind("click.chosen",this.click_test_action),this.search_field[0].tabIndex&&(this.form_field_jq[0].tabIndex=this.search_field[0].tabIndex),this.container.remove(),this.form_field_jq.removeData("chosen"),this.form_field_jq.show()},Chosen.prototype.search_field_disabled=function(){return this.is_disabled=this.form_field_jq[0].disabled,this.is_disabled?(this.container.addClass("chosen-disabled"),this.search_field[0].disabled=!0,this.is_multiple||this.selected_item.unbind("focus.chosen",this.activate_action),this.close_field()):(this.container.removeClass("chosen-disabled"),this.search_field[0].disabled=!1,this.is_multiple?void 0:this.selected_item.bind("focus.chosen",this.activate_action))},Chosen.prototype.container_mousedown=function(b){return this.is_disabled||(b&&"mousedown"===b.type&&!this.results_showing&&b.preventDefault(),null!=b&&a(b.target).hasClass("search-choice-close"))?void 0:(this.active_field?this.is_multiple||!b||a(b.target)[0]!==this.selected_item[0]&&!a(b.target).parents("a.chosen-single").length||(b.preventDefault(),this.results_toggle()):(this.is_multiple&&this.search_field.val(""),a(this.container[0].ownerDocument).bind("click.chosen",this.click_test_action),this.results_show()),this.activate_field())},Chosen.prototype.container_mouseup=function(a){return"ABBR"!==a.target.nodeName||this.is_disabled?void 0:this.results_reset(a)},Chosen.prototype.search_results_mousewheel=function(a){var b;return a.originalEvent&&(b=-a.originalEvent.wheelDelta||a.originalEvent.detail),null!=b?(a.preventDefault(),"DOMMouseScroll"===a.type&&(b=40*b),this.search_results.scrollTop(b+this.search_results.scrollTop())):void 0},Chosen.prototype.blur_test=function(){return!this.active_field&&this.container.hasClass("chosen-container-active")?this.close_field():void 0},Chosen.prototype.close_field=function(){return a(this.container[0].ownerDocument).unbind("click.chosen",this.click_test_action),this.active_field=!1,this.results_hide(),this.container.removeClass("chosen-container-active"),this.clear_backstroke(),this.show_search_field_default(),this.search_field_scale()},Chosen.prototype.activate_field=function(){return this.container.addClass("chosen-container-active"),this.active_field=!0,this.search_field.val(this.search_field.val()),this.search_field.focus()},Chosen.prototype.test_active_click=function(b){var c;return c=a(b.target).closest(".chosen-container"),c.length&&this.container[0]===c[0]?this.active_field=!0:this.close_field()},Chosen.prototype.results_build=function(){return this.parsing=!0,this.selected_option_count=null,this.results_data=SelectParser.select_to_array(this.form_field),this.is_multiple?this.search_choices.find("li.search-choice").remove():this.is_multiple||(this.single_set_selected_text(),this.disable_search||this.form_field.options.length<=this.disable_search_threshold?(this.search_field[0].readOnly=!0,this.container.addClass("chosen-container-single-nosearch")):(this.search_field[0].readOnly=!1,this.container.removeClass("chosen-container-single-nosearch"))),this.update_results_content(this.results_option_build({first:!0})),this.search_field_disabled(),this.show_search_field_default(),this.search_field_scale(),this.parsing=!1},Chosen.prototype.result_do_highlight=function(a){var b,c,d,e,f;if(a.length){if(this.result_clear_highlight(),this.result_highlight=a,this.result_highlight.addClass("highlighted"),d=parseInt(this.search_results.css("maxHeight"),10),f=this.search_results.scrollTop(),e=d+f,c=this.result_highlight.position().top+this.search_results.scrollTop(),b=c+this.result_highlight.outerHeight(),b>=e)return this.search_results.scrollTop(b-d>0?b-d:0);if(f>c)return this.search_results.scrollTop(c)}},Chosen.prototype.result_clear_highlight=function(){return this.result_highlight&&this.result_highlight.removeClass("highlighted"),this.result_highlight=null},Chosen.prototype.results_show=function(){return this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field_jq.trigger("chosen:maxselected",{chosen:this}),!1):(this.container.addClass("chosen-with-drop"),this.results_showing=!0,this.search_field.focus(),this.search_field.val(this.search_field.val()),this.winnow_results(),this.form_field_jq.trigger("chosen:showing_dropdown",{chosen:this}))},Chosen.prototype.update_results_content=function(a){return this.search_results.html(a)},Chosen.prototype.results_hide=function(){return this.results_showing&&(this.result_clear_highlight(),this.container.removeClass("chosen-with-drop"),this.form_field_jq.trigger("chosen:hiding_dropdown",{chosen:this})),this.results_showing=!1},Chosen.prototype.set_tab_index=function(){var a;return this.form_field.tabIndex?(a=this.form_field.tabIndex,this.form_field.tabIndex=-1,this.search_field[0].tabIndex=a):void 0},Chosen.prototype.set_label_behavior=function(){var b=this;return this.form_field_label=this.form_field_jq.parents("label"),!this.form_field_label.length&&this.form_field.id.length&&(this.form_field_label=a("label[for='"+this.form_field.id+"']")),this.form_field_label.length>0?this.form_field_label.bind("click.chosen",function(a){return b.is_multiple?b.container_mousedown(a):b.activate_field()}):void 0},Chosen.prototype.show_search_field_default=function(){return this.is_multiple&&this.choices_count()<1&&!this.active_field?(this.search_field.val(this.default_text),this.search_field.addClass("default")):(this.search_field.val(""),this.search_field.removeClass("default"))},Chosen.prototype.search_results_mouseup=function(b){var c;return c=a(b.target).hasClass("active-result")?a(b.target):a(b.target).parents(".active-result").first(),c.length?(this.result_highlight=c,this.result_select(b),this.search_field.focus()):void 0},Chosen.prototype.search_results_mouseover=function(b){var c;return c=a(b.target).hasClass("active-result")?a(b.target):a(b.target).parents(".active-result").first(),c?this.result_do_highlight(c):void 0},Chosen.prototype.search_results_mouseout=function(b){return a(b.target).hasClass("active-result")?this.result_clear_highlight():void 0},Chosen.prototype.choice_build=function(b){var c,d,e=this;return c=a("<li />",{"class":"search-choice"}).html("<span>"+b.html+"</span>"),b.disabled?c.addClass("search-choice-disabled"):(d=a("<a />",{"class":"search-choice-close","data-option-array-index":b.array_index}),d.bind("click.chosen",function(a){return e.choice_destroy_link_click(a)}),c.append(d)),this.search_container.before(c)},Chosen.prototype.choice_destroy_link_click=function(b){return b.preventDefault(),b.stopPropagation(),this.is_disabled?void 0:this.choice_destroy(a(b.target))},Chosen.prototype.choice_destroy=function(a){return this.result_deselect(a[0].getAttribute("data-option-array-index"))?(this.show_search_field_default(),this.is_multiple&&this.choices_count()>0&&this.search_field.val().length<1&&this.results_hide(),a.parents("li").first().remove(),this.search_field_scale()):void 0},Chosen.prototype.results_reset=function(){return this.reset_single_select_options(),this.form_field.options[0].selected=!0,this.single_set_selected_text(),this.show_search_field_default(),this.results_reset_cleanup(),this.form_field_jq.trigger("change"),this.active_field?this.results_hide():void 0},Chosen.prototype.results_reset_cleanup=function(){return this.current_selectedIndex=this.form_field.selectedIndex,this.selected_item.find("abbr").remove()},Chosen.prototype.result_select=function(a){var b,c;return this.result_highlight?(b=this.result_highlight,this.result_clear_highlight(),this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field_jq.trigger("chosen:maxselected",{chosen:this}),!1):(this.is_multiple?b.removeClass("active-result"):this.reset_single_select_options(),c=this.results_data[b[0].getAttribute("data-option-array-index")],c.selected=!0,this.form_field.options[c.options_index].selected=!0,this.selected_option_count=null,this.is_multiple?this.choice_build(c):this.single_set_selected_text(c.text),(a.metaKey||a.ctrlKey)&&this.is_multiple||this.results_hide(),this.search_field.val(""),(this.is_multiple||this.form_field.selectedIndex!==this.current_selectedIndex)&&this.form_field_jq.trigger("change",{selected:this.form_field.options[c.options_index].value}),this.current_selectedIndex=this.form_field.selectedIndex,this.search_field_scale())):void 0},Chosen.prototype.single_set_selected_text=function(a){return null==a&&(a=this.default_text),a===this.default_text?this.selected_item.addClass("chosen-default"):(this.single_deselect_control_build(),this.selected_item.removeClass("chosen-default")),this.selected_item.find("span").text(a)},Chosen.prototype.result_deselect=function(a){var b;return b=this.results_data[a],this.form_field.options[b.options_index].disabled?!1:(b.selected=!1,this.form_field.options[b.options_index].selected=!1,this.selected_option_count=null,this.result_clear_highlight(),this.results_showing&&this.winnow_results(),this.form_field_jq.trigger("change",{deselected:this.form_field.options[b.options_index].value}),this.search_field_scale(),!0)},Chosen.prototype.single_deselect_control_build=function(){return this.allow_single_deselect?(this.selected_item.find("abbr").length||this.selected_item.find("span").first().after('<abbr class="search-choice-close"></abbr>'),this.selected_item.addClass("chosen-single-with-deselect")):void 0},Chosen.prototype.get_search_text=function(){return this.search_field.val()===this.default_text?"":a("<div/>").text(a.trim(this.search_field.val())).html()},Chosen.prototype.winnow_results_set_highlight=function(){var a,b;return b=this.is_multiple?[]:this.search_results.find(".result-selected.active-result"),a=b.length?b.first():this.search_results.find(".active-result").first(),null!=a?this.result_do_highlight(a):void 0},Chosen.prototype.no_results=function(b){var c;return c=a('<li class="no-results">'+this.results_none_found+' "<span></span>"</li>'),c.find("span").first().html(b),this.search_results.append(c),this.form_field_jq.trigger("chosen:no_results",{chosen:this})},Chosen.prototype.no_results_clear=function(){return this.search_results.find(".no-results").remove()},Chosen.prototype.keydown_arrow=function(){var a;return this.results_showing&&this.result_highlight?(a=this.result_highlight.nextAll("li.active-result").first())?this.result_do_highlight(a):void 0:this.results_show()},Chosen.prototype.keyup_arrow=function(){var a;return this.results_showing||this.is_multiple?this.result_highlight?(a=this.result_highlight.prevAll("li.active-result"),a.length?this.result_do_highlight(a.first()):(this.choices_count()>0&&this.results_hide(),this.result_clear_highlight())):void 0:this.results_show()},Chosen.prototype.keydown_backstroke=function(){var a;return this.pending_backstroke?(this.choice_destroy(this.pending_backstroke.find("a").first()),this.clear_backstroke()):(a=this.search_container.siblings("li.search-choice").last(),a.length&&!a.hasClass("search-choice-disabled")?(this.pending_backstroke=a,this.single_backstroke_delete?this.keydown_backstroke():this.pending_backstroke.addClass("search-choice-focus")):void 0)},Chosen.prototype.clear_backstroke=function(){return this.pending_backstroke&&this.pending_backstroke.removeClass("search-choice-focus"),this.pending_backstroke=null},Chosen.prototype.keydown_checker=function(a){var b,c;switch(b=null!=(c=a.which)?c:a.keyCode,this.search_field_scale(),8!==b&&this.pending_backstroke&&this.clear_backstroke(),b){case 8:this.backstroke_length=this.search_field.val().length;break;case 9:this.results_showing&&!this.is_multiple&&this.result_select(a),this.mouse_on_container=!1;break;case 13:a.preventDefault();break;case 38:a.preventDefault(),this.keyup_arrow();break;case 40:a.preventDefault(),this.keydown_arrow()}},Chosen.prototype.search_field_scale=function(){var b,c,d,e,f,g,h,i,j;if(this.is_multiple){for(d=0,h=0,f="position:absolute; left: -1000px; top: -1000px; display:none;",g=["font-size","font-style","font-weight","font-family","line-height","text-transform","letter-spacing"],i=0,j=g.length;j>i;i++)e=g[i],f+=e+":"+this.search_field.css(e)+";";return b=a("<div />",{style:f}),b.text(this.search_field.val()),a("body").append(b),h=b.width()+25,b.remove(),c=this.container.outerWidth(),h>c-10&&(h=c-10),this.search_field.css({width:h+"px"})}},Chosen}(AbstractChosen)}.call(this);

/**
 * Web Font Loader v1.6.27
 * (c) Adobe Systems, Google.
 * License: Apache 2.0
 * */
(function(){function aa(a,b,c){return a.call.apply(a.bind,arguments)}function ba(a,b,c){if(!a)throw Error();if(2<arguments.length){var d=Array.prototype.slice.call(arguments,2);return function(){var c=Array.prototype.slice.call(arguments);Array.prototype.unshift.apply(c,d);return a.apply(b,c)}}return function(){return a.apply(b,arguments)}}function p(a,b,c){p=Function.prototype.bind&&-1!=Function.prototype.bind.toString().indexOf("native code")?aa:ba;return p.apply(null,arguments)}var q=Date.now||function(){return+new Date};function ca(a,b){this.a=a;this.m=b||a;this.c=this.m.document}var da=!!window.FontFace;function t(a,b,c,d){b=a.c.createElement(b);if(c)for(var e in c)c.hasOwnProperty(e)&&("style"==e?b.style.cssText=c[e]:b.setAttribute(e,c[e]));d&&b.appendChild(a.c.createTextNode(d));return b}function u(a,b,c){a=a.c.getElementsByTagName(b)[0];a||(a=document.documentElement);a.insertBefore(c,a.lastChild)}function v(a){a.parentNode&&a.parentNode.removeChild(a)}
    function w(a,b,c){b=b||[];c=c||[];for(var d=a.className.split(/\s+/),e=0;e<b.length;e+=1){for(var f=!1,g=0;g<d.length;g+=1)if(b[e]===d[g]){f=!0;break}f||d.push(b[e])}b=[];for(e=0;e<d.length;e+=1){f=!1;for(g=0;g<c.length;g+=1)if(d[e]===c[g]){f=!0;break}f||b.push(d[e])}a.className=b.join(" ").replace(/\s+/g," ").replace(/^\s+|\s+$/,"")}function y(a,b){for(var c=a.className.split(/\s+/),d=0,e=c.length;d<e;d++)if(c[d]==b)return!0;return!1}
    function z(a){if("string"===typeof a.f)return a.f;var b=a.m.location.protocol;"about:"==b&&(b=a.a.location.protocol);return"https:"==b?"https:":"http:"}function ea(a){return a.m.location.hostname||a.a.location.hostname}
    function A(a,b,c){function d(){k&&e&&f&&(k(g),k=null)}b=t(a,"link",{rel:"stylesheet",href:b,media:"all"});var e=!1,f=!0,g=null,k=c||null;da?(b.onload=function(){e=!0;d()},b.onerror=function(){e=!0;g=Error("Stylesheet failed to load");d()}):setTimeout(function(){e=!0;d()},0);u(a,"head",b)}
    function B(a,b,c,d){var e=a.c.getElementsByTagName("head")[0];if(e){var f=t(a,"script",{src:b}),g=!1;f.onload=f.onreadystatechange=function(){g||this.readyState&&"loaded"!=this.readyState&&"complete"!=this.readyState||(g=!0,c&&c(null),f.onload=f.onreadystatechange=null,"HEAD"==f.parentNode.tagName&&e.removeChild(f))};e.appendChild(f);setTimeout(function(){g||(g=!0,c&&c(Error("Script load timeout")))},d||5E3);return f}return null};function C(){this.a=0;this.c=null}function D(a){a.a++;return function(){a.a--;E(a)}}function F(a,b){a.c=b;E(a)}function E(a){0==a.a&&a.c&&(a.c(),a.c=null)};function G(a){this.a=a||"-"}G.prototype.c=function(a){for(var b=[],c=0;c<arguments.length;c++)b.push(arguments[c].replace(/[\W_]+/g,"").toLowerCase());return b.join(this.a)};function H(a,b){this.c=a;this.f=4;this.a="n";var c=(b||"n4").match(/^([nio])([1-9])$/i);c&&(this.a=c[1],this.f=parseInt(c[2],10))}function fa(a){return I(a)+" "+(a.f+"00")+" 300px "+J(a.c)}function J(a){var b=[];a=a.split(/,\s*/);for(var c=0;c<a.length;c++){var d=a[c].replace(/['"]/g,"");-1!=d.indexOf(" ")||/^\d/.test(d)?b.push("'"+d+"'"):b.push(d)}return b.join(",")}function K(a){return a.a+a.f}function I(a){var b="normal";"o"===a.a?b="oblique":"i"===a.a&&(b="italic");return b}
    function ga(a){var b=4,c="n",d=null;a&&((d=a.match(/(normal|oblique|italic)/i))&&d[1]&&(c=d[1].substr(0,1).toLowerCase()),(d=a.match(/([1-9]00|normal|bold)/i))&&d[1]&&(/bold/i.test(d[1])?b=7:/[1-9]00/.test(d[1])&&(b=parseInt(d[1].substr(0,1),10))));return c+b};function ha(a,b){this.c=a;this.f=a.m.document.documentElement;this.h=b;this.a=new G("-");this.j=!1!==b.events;this.g=!1!==b.classes}function ia(a){a.g&&w(a.f,[a.a.c("wf","loading")]);L(a,"loading")}function M(a){if(a.g){var b=y(a.f,a.a.c("wf","active")),c=[],d=[a.a.c("wf","loading")];b||c.push(a.a.c("wf","inactive"));w(a.f,c,d)}L(a,"inactive")}function L(a,b,c){if(a.j&&a.h[b])if(c)a.h[b](c.c,K(c));else a.h[b]()};function ja(){this.c={}}function ka(a,b,c){var d=[],e;for(e in b)if(b.hasOwnProperty(e)){var f=a.c[e];f&&d.push(f(b[e],c))}return d};function N(a,b){this.c=a;this.f=b;this.a=t(this.c,"span",{"aria-hidden":"true"},this.f)}function O(a){u(a.c,"body",a.a)}function P(a){return"display:block;position:absolute;top:-9999px;left:-9999px;font-size:300px;width:auto;height:auto;line-height:normal;margin:0;padding:0;font-variant:normal;white-space:nowrap;font-family:"+J(a.c)+";"+("font-style:"+I(a)+";font-weight:"+(a.f+"00")+";")};function Q(a,b,c,d,e,f){this.g=a;this.j=b;this.a=d;this.c=c;this.f=e||3E3;this.h=f||void 0}Q.prototype.start=function(){var a=this.c.m.document,b=this,c=q(),d=new Promise(function(d,e){function k(){q()-c>=b.f?e():a.fonts.load(fa(b.a),b.h).then(function(a){1<=a.length?d():setTimeout(k,25)},function(){e()})}k()}),e=new Promise(function(a,d){setTimeout(d,b.f)});Promise.race([e,d]).then(function(){b.g(b.a)},function(){b.j(b.a)})};function R(a,b,c,d,e,f,g){this.v=a;this.B=b;this.c=c;this.a=d;this.s=g||"BESbswy";this.f={};this.w=e||3E3;this.u=f||null;this.o=this.j=this.h=this.g=null;this.g=new N(this.c,this.s);this.h=new N(this.c,this.s);this.j=new N(this.c,this.s);this.o=new N(this.c,this.s);a=new H(this.a.c+",serif",K(this.a));a=P(a);this.g.a.style.cssText=a;a=new H(this.a.c+",sans-serif",K(this.a));a=P(a);this.h.a.style.cssText=a;a=new H("serif",K(this.a));a=P(a);this.j.a.style.cssText=a;a=new H("sans-serif",K(this.a));a=
        P(a);this.o.a.style.cssText=a;O(this.g);O(this.h);O(this.j);O(this.o)}var S={D:"serif",C:"sans-serif"},T=null;function U(){if(null===T){var a=/AppleWebKit\/([0-9]+)(?:\.([0-9]+))/.exec(window.navigator.userAgent);T=!!a&&(536>parseInt(a[1],10)||536===parseInt(a[1],10)&&11>=parseInt(a[2],10))}return T}R.prototype.start=function(){this.f.serif=this.j.a.offsetWidth;this.f["sans-serif"]=this.o.a.offsetWidth;this.A=q();la(this)};
    function ma(a,b,c){for(var d in S)if(S.hasOwnProperty(d)&&b===a.f[S[d]]&&c===a.f[S[d]])return!0;return!1}function la(a){var b=a.g.a.offsetWidth,c=a.h.a.offsetWidth,d;(d=b===a.f.serif&&c===a.f["sans-serif"])||(d=U()&&ma(a,b,c));d?q()-a.A>=a.w?U()&&ma(a,b,c)&&(null===a.u||a.u.hasOwnProperty(a.a.c))?V(a,a.v):V(a,a.B):na(a):V(a,a.v)}function na(a){setTimeout(p(function(){la(this)},a),50)}function V(a,b){setTimeout(p(function(){v(this.g.a);v(this.h.a);v(this.j.a);v(this.o.a);b(this.a)},a),0)};function W(a,b,c){this.c=a;this.a=b;this.f=0;this.o=this.j=!1;this.s=c}var X=null;W.prototype.g=function(a){var b=this.a;b.g&&w(b.f,[b.a.c("wf",a.c,K(a).toString(),"active")],[b.a.c("wf",a.c,K(a).toString(),"loading"),b.a.c("wf",a.c,K(a).toString(),"inactive")]);L(b,"fontactive",a);this.o=!0;oa(this)};
    W.prototype.h=function(a){var b=this.a;if(b.g){var c=y(b.f,b.a.c("wf",a.c,K(a).toString(),"active")),d=[],e=[b.a.c("wf",a.c,K(a).toString(),"loading")];c||d.push(b.a.c("wf",a.c,K(a).toString(),"inactive"));w(b.f,d,e)}L(b,"fontinactive",a);oa(this)};function oa(a){0==--a.f&&a.j&&(a.o?(a=a.a,a.g&&w(a.f,[a.a.c("wf","active")],[a.a.c("wf","loading"),a.a.c("wf","inactive")]),L(a,"active")):M(a.a))};function pa(a){this.j=a;this.a=new ja;this.h=0;this.f=this.g=!0}pa.prototype.load=function(a){this.c=new ca(this.j,a.context||this.j);this.g=!1!==a.events;this.f=!1!==a.classes;qa(this,new ha(this.c,a),a)};
    function ra(a,b,c,d,e){var f=0==--a.h;(a.f||a.g)&&setTimeout(function(){var a=e||null,k=d||null||{};if(0===c.length&&f)M(b.a);else{b.f+=c.length;f&&(b.j=f);var h,m=[];for(h=0;h<c.length;h++){var l=c[h],n=k[l.c],r=b.a,x=l;r.g&&w(r.f,[r.a.c("wf",x.c,K(x).toString(),"loading")]);L(r,"fontloading",x);r=null;if(null===X)if(window.FontFace){var x=/Gecko.*Firefox\/(\d+)/.exec(window.navigator.userAgent),ya=/OS X.*Version\/10\..*Safari/.exec(window.navigator.userAgent)&&/Apple/.exec(window.navigator.vendor);
        X=x?42<parseInt(x[1],10):ya?!1:!0}else X=!1;X?r=new Q(p(b.g,b),p(b.h,b),b.c,l,b.s,n):r=new R(p(b.g,b),p(b.h,b),b.c,l,b.s,a,n);m.push(r)}for(h=0;h<m.length;h++)m[h].start()}},0)}function qa(a,b,c){var d=[],e=c.timeout;ia(b);var d=ka(a.a,c,a.c),f=new W(a.c,b,e);a.h=d.length;b=0;for(c=d.length;b<c;b++)d[b].load(function(b,d,c){ra(a,f,b,d,c)})};function sa(a,b){this.c=a;this.a=b}function ta(a,b,c){var d=z(a.c);a=(a.a.api||"fast.fonts.net/jsapi").replace(/^.*http(s?):(\/\/)?/,"");return d+"//"+a+"/"+b+".js"+(c?"?v="+c:"")}
    sa.prototype.load=function(a){function b(){if(f["__mti_fntLst"+d]){var c=f["__mti_fntLst"+d](),e=[],h;if(c)for(var m=0;m<c.length;m++){var l=c[m].fontfamily;void 0!=c[m].fontStyle&&void 0!=c[m].fontWeight?(h=c[m].fontStyle+c[m].fontWeight,e.push(new H(l,h))):e.push(new H(l))}a(e)}else setTimeout(function(){b()},50)}var c=this,d=c.a.projectId,e=c.a.version;if(d){var f=c.c.m;B(this.c,ta(c,d,e),function(e){e?a([]):(f["__MonotypeConfiguration__"+d]=function(){return c.a},b())}).id="__MonotypeAPIScript__"+
        d}else a([])};function ua(a,b){this.c=a;this.a=b}ua.prototype.load=function(a){var b,c,d=this.a.urls||[],e=this.a.families||[],f=this.a.testStrings||{},g=new C;b=0;for(c=d.length;b<c;b++)A(this.c,d[b],D(g));var k=[];b=0;for(c=e.length;b<c;b++)if(d=e[b].split(":"),d[1])for(var h=d[1].split(","),m=0;m<h.length;m+=1)k.push(new H(d[0],h[m]));else k.push(new H(d[0]));F(g,function(){a(k,f)})};function va(a,b,c){a?this.c=a:this.c=b+wa;this.a=[];this.f=[];this.g=c||""}var wa="//fonts.googleapis.com/css";function xa(a,b){for(var c=b.length,d=0;d<c;d++){var e=b[d].split(":");3==e.length&&a.f.push(e.pop());var f="";2==e.length&&""!=e[1]&&(f=":");a.a.push(e.join(f))}}
    function za(a){if(0==a.a.length)throw Error("No fonts to load!");if(-1!=a.c.indexOf("kit="))return a.c;for(var b=a.a.length,c=[],d=0;d<b;d++)c.push(a.a[d].replace(/ /g,"+"));b=a.c+"?family="+c.join("%7C");0<a.f.length&&(b+="&subset="+a.f.join(","));0<a.g.length&&(b+="&text="+encodeURIComponent(a.g));return b};function Aa(a){this.f=a;this.a=[];this.c={}}
    var Ba={latin:"BESbswy","latin-ext":"\u00e7\u00f6\u00fc\u011f\u015f",cyrillic:"\u0439\u044f\u0416",greek:"\u03b1\u03b2\u03a3",khmer:"\u1780\u1781\u1782",Hanuman:"\u1780\u1781\u1782"},Ca={thin:"1",extralight:"2","extra-light":"2",ultralight:"2","ultra-light":"2",light:"3",regular:"4",book:"4",medium:"5","semi-bold":"6",semibold:"6","demi-bold":"6",demibold:"6",bold:"7","extra-bold":"8",extrabold:"8","ultra-bold":"8",ultrabold:"8",black:"9",heavy:"9",l:"3",r:"4",b:"7"},Da={i:"i",italic:"i",n:"n",normal:"n"},
        Ea=/^(thin|(?:(?:extra|ultra)-?)?light|regular|book|medium|(?:(?:semi|demi|extra|ultra)-?)?bold|black|heavy|l|r|b|[1-9]00)?(n|i|normal|italic)?$/;
    function Fa(a){for(var b=a.f.length,c=0;c<b;c++){var d=a.f[c].split(":"),e=d[0].replace(/\+/g," "),f=["n4"];if(2<=d.length){var g;var k=d[1];g=[];if(k)for(var k=k.split(","),h=k.length,m=0;m<h;m++){var l;l=k[m];if(l.match(/^[\w-]+$/)){var n=Ea.exec(l.toLowerCase());if(null==n)l="";else{l=n[2];l=null==l||""==l?"n":Da[l];n=n[1];if(null==n||""==n)n="4";else var r=Ca[n],n=r?r:isNaN(n)?"4":n.substr(0,1);l=[l,n].join("")}}else l="";l&&g.push(l)}0<g.length&&(f=g);3==d.length&&(d=d[2],g=[],d=d?d.split(","):
        g,0<d.length&&(d=Ba[d[0]])&&(a.c[e]=d))}a.c[e]||(d=Ba[e])&&(a.c[e]=d);for(d=0;d<f.length;d+=1)a.a.push(new H(e,f[d]))}};function Ga(a,b){this.c=a;this.a=b}var Ha={Arimo:!0,Cousine:!0,Tinos:!0};Ga.prototype.load=function(a){var b=new C,c=this.c,d=new va(this.a.api,z(c),this.a.text),e=this.a.families;xa(d,e);var f=new Aa(e);Fa(f);A(c,za(d),D(b));F(b,function(){a(f.a,f.c,Ha)})};function Ia(a,b){this.c=a;this.a=b}Ia.prototype.load=function(a){var b=this.a.id,c=this.c.m;b?B(this.c,(this.a.api||"https://use.typekit.net")+"/"+b+".js",function(b){if(b)a([]);else if(c.Typekit&&c.Typekit.config&&c.Typekit.config.fn){b=c.Typekit.config.fn;for(var e=[],f=0;f<b.length;f+=2)for(var g=b[f],k=b[f+1],h=0;h<k.length;h++)e.push(new H(g,k[h]));try{c.Typekit.load({events:!1,classes:!1,async:!0})}catch(m){}a(e)}},2E3):a([])};function Ja(a,b){this.c=a;this.f=b;this.a=[]}Ja.prototype.load=function(a){var b=this.f.id,c=this.c.m,d=this;b?(c.__webfontfontdeckmodule__||(c.__webfontfontdeckmodule__={}),c.__webfontfontdeckmodule__[b]=function(b,c){for(var g=0,k=c.fonts.length;g<k;++g){var h=c.fonts[g];d.a.push(new H(h.name,ga("font-weight:"+h.weight+";font-style:"+h.style)))}a(d.a)},B(this.c,z(this.c)+(this.f.api||"//f.fontdeck.com/s/css/js/")+ea(this.c)+"/"+b+".js",function(b){b&&a([])})):a([])};var Y=new pa(window);Y.a.c.custom=function(a,b){return new ua(b,a)};Y.a.c.fontdeck=function(a,b){return new Ja(b,a)};Y.a.c.monotype=function(a,b){return new sa(b,a)};Y.a.c.typekit=function(a,b){return new Ia(b,a)};Y.a.c.google=function(a,b){return new Ga(b,a)};var Z={load:p(Y.load,Y)};"function"===typeof define&&define.amd?define(function(){return Z}):"undefined"!==typeof module&&module.exports?module.exports=Z:(window.WebFont=Z,window.WebFontConfig&&Y.load(window.WebFontConfig));}());


/*
 *  Remodal - v1.0.1
 *  Responsive, lightweight, fast, synchronized with CSS animations, fully customizable modal window plugin with declarative configuration and hash tracking.
 *  http://vodkabears.github.io/remodal/
 *
 *  Made by Ilya Makarov
 *  Under MIT License
 */
!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(c){return b(a,c)}):"object"==typeof exports?b(a,require("jquery")):b(a,a.jQuery||a.Zepto)}(this,function(a,b){"use strict";function c(a){if(v&&"none"===a.css("animation-name")&&"none"===a.css("-webkit-animation-name")&&"none"===a.css("-moz-animation-name")&&"none"===a.css("-o-animation-name")&&"none"===a.css("-ms-animation-name"))return 0;var b,c,d,e,f=a.css("animation-duration")||a.css("-webkit-animation-duration")||a.css("-moz-animation-duration")||a.css("-o-animation-duration")||a.css("-ms-animation-duration")||"0s",g=a.css("animation-delay")||a.css("-webkit-animation-delay")||a.css("-moz-animation-delay")||a.css("-o-animation-delay")||a.css("-ms-animation-delay")||"0s",h=a.css("animation-iteration-count")||a.css("-webkit-animation-iteration-count")||a.css("-moz-animation-iteration-count")||a.css("-o-animation-iteration-count")||a.css("-ms-animation-iteration-count")||"1";for(f=f.split(", "),g=g.split(", "),h=h.split(", "),e=0,c=f.length,b=Number.NEGATIVE_INFINITY;c>e;e++)d=parseFloat(f[e])*parseInt(h[e],10)+parseFloat(g[e]),d>b&&(b=d);return d}function d(){if(b(document.body).height()<=b(window).height())return 0;var a,c,d=document.createElement("div"),e=document.createElement("div");return d.style.visibility="hidden",d.style.width="100px",document.body.appendChild(d),a=d.offsetWidth,d.style.overflow="scroll",e.style.width="100%",d.appendChild(e),c=e.offsetWidth,d.parentNode.removeChild(d),a-c}function e(){var a,c,e=b("html"),f=p+"-is-locked";e.hasClass(f)||(c=b(document.body),a=parseInt(c.css("padding-right"),10)+d(),c.css("padding-right",a+"px"),e.addClass(f))}function f(){var a,c,e=b("html"),f=p+"-is-locked";e.hasClass(f)&&(c=b(document.body),a=parseInt(c.css("padding-right"),10)-d(),c.css("padding-right",a+"px"),e.removeClass(f))}function g(a,b,c,d){a.$bg.removeClass(p+"-is-"+t.CLOSING+" "+p+"-is-"+t.OPENING+" "+p+"-is-"+t.CLOSED+" "+p+"-is-"+t.OPENED).addClass(p+"-is-"+b),a.$overlay.removeClass(p+"-is-"+t.CLOSING+" "+p+"-is-"+t.OPENING+" "+p+"-is-"+t.CLOSED+" "+p+"-is-"+t.OPENED).addClass(p+"-is-"+b),a.$wrapper.removeClass(p+"-is-"+t.CLOSING+" "+p+"-is-"+t.OPENING+" "+p+"-is-"+t.CLOSED+" "+p+"-is-"+t.OPENED).addClass(p+"-is-"+b),a.$modal.removeClass(p+"-is-"+t.CLOSING+" "+p+"-is-"+t.OPENING+" "+p+"-is-"+t.CLOSED+" "+p+"-is-"+t.OPENED).addClass(p+"-is-"+b),a.state=b,!c&&a.$modal.trigger({type:b,reason:d},[{reason:d}])}function h(a,d,e){var f=0,g=function(a){a.target===this&&f++},h=function(a){a.target===this&&0===--f&&(b.each(["$bg","$overlay","$wrapper","$modal"],function(a,b){e[b].off(q+" "+r)}),d())};b.each(["$bg","$overlay","$wrapper","$modal"],function(a,b){e[b].on(q,g).on(r,h)}),a(),0===c(e.$bg)&&0===c(e.$overlay)&&0===c(e.$wrapper)&&0===c(e.$modal)&&(b.each(["$bg","$overlay","$wrapper","$modal"],function(a,b){e[b].off(q+" "+r)}),d())}function i(a){a.state!==t.CLOSED&&(b.each(["$bg","$overlay","$wrapper","$modal"],function(b,c){a[c].off(q+" "+r)}),a.$bg.removeClass(a.settings.modifier),a.$overlay.removeClass(a.settings.modifier).hide(),a.$wrapper.hide(),f(),g(a,t.CLOSED,!0))}function j(a){var b,c,d,e,f={};for(a=a.replace(/\s*:\s*/g,":").replace(/\s*,\s*/g,","),b=a.split(","),e=0,c=b.length;c>e;e++)b[e]=b[e].split(":"),d=b[e][1],("string"==typeof d||d instanceof String)&&(d="true"===d||("false"===d?!1:d)),("string"==typeof d||d instanceof String)&&(d=isNaN(d)?d:+d),f[b[e][0]]=d;return f}function k(){var a,c,d=location.hash.replace("#","");if(d){try{c=b("[data-"+o+"-id="+d.replace(new RegExp("/","g"),"\\/")+"]")}catch(e){}c&&c.length&&(a=b[o].lookup[c.data(o)],a&&a.settings.hashTracking&&a.open())}else m&&m.state===t.OPENED&&m.settings.hashTracking&&m.close()}function l(a,c){var d=b(document.body),e=this;e.settings=b.extend({},s,c),e.index=b[o].lookup.push(e)-1,e.state=t.CLOSED,e.$overlay=b("."+p+"-overlay"),e.$overlay.length||(e.$overlay=b("<div>").addClass(p+"-overlay "+p+"-is-"+t.CLOSED).hide(),d.append(e.$overlay)),e.$bg=b("."+p+"-bg").addClass(p+"-is-"+t.CLOSED),e.$modal=a,e.$modal.addClass(p+"-is-initialized "+p+" "+e.settings.modifier+" "+p+"-is-"+t.CLOSED),e.$wrapper=b("<div>").addClass(p+"-wrapper "+e.settings.modifier+" "+p+"-is-"+t.CLOSED).hide().append(e.$modal),d.append(e.$wrapper),e.$wrapper.on("click."+p,"[data-"+o+'-action="close"]',function(a){a.preventDefault(),e.close()}),e.$wrapper.on("click."+p,"[data-"+o+'-action="cancel"]',function(a){a.preventDefault(),e.$modal.trigger(u.CANCELLATION),e.settings.closeOnCancel&&e.close(u.CANCELLATION)}),e.$wrapper.on("click."+p,"[data-"+o+'-action="confirm"]',function(a){a.preventDefault(),e.$modal.trigger(u.CONFIRMATION),e.settings.closeOnConfirm&&e.close(u.CONFIRMATION)}),e.$wrapper.on("click."+p,function(a){var c=b(a.target);c.hasClass(p+"-wrapper")&&e.settings.closeOnOutsideClick&&e.close()})}var m,n,o="remodal",p=a.REMODAL_GLOBALS&&a.REMODAL_GLOBALS.NAMESPACE||o,q=b.map(["animationstart","webkitAnimationStart","MSAnimationStart","oAnimationStart"],function(a){return a+"."+p}).join(" "),r=b.map(["animationend","webkitAnimationEnd","MSAnimationEnd","oAnimationEnd"],function(a){return a+"."+p}).join(" "),s=b.extend({hashTracking:!0,closeOnConfirm:!0,closeOnCancel:!0,closeOnEscape:!0,closeOnOutsideClick:!0,modifier:""},a.REMODAL_GLOBALS&&a.REMODAL_GLOBALS.DEFAULTS),t={CLOSING:"closing",CLOSED:"closed",OPENING:"opening",OPENED:"opened"},u={CONFIRMATION:"confirmation",CANCELLATION:"cancellation"},v=function(){var a=document.createElement("div").style;return void 0!==a.animationName||void 0!==a.WebkitAnimationName||void 0!==a.MozAnimationName||void 0!==a.msAnimationName||void 0!==a.OAnimationName}();l.prototype.open=function(){var a,c=this;c.state!==t.OPENING&&c.state!==t.CLOSING&&(a=c.$modal.attr("data-"+o+"-id"),a&&c.settings.hashTracking&&(n=b(window).scrollTop(),location.hash=a),m&&m!==c&&i(m),m=c,e(),c.$bg.addClass(c.settings.modifier),c.$overlay.addClass(c.settings.modifier).show(),c.$wrapper.show().scrollTop(0),h(function(){g(c,t.OPENING)},function(){g(c,t.OPENED)},c))},l.prototype.close=function(a){var c=this;c.state!==t.OPENING&&c.state!==t.CLOSING&&(c.settings.hashTracking&&c.$modal.attr("data-"+o+"-id")===location.hash.substr(1)&&(location.hash="",b(window).scrollTop(n)),h(function(){g(c,t.CLOSING,!1,a)},function(){c.$bg.removeClass(c.settings.modifier),c.$overlay.removeClass(c.settings.modifier).hide(),c.$wrapper.hide(),f(),g(c,t.CLOSED,!1,a)},c))},l.prototype.getState=function(){return this.state},l.prototype.destroy=function(){var a,c=b[o].lookup;i(this),this.$wrapper.remove(),delete c[this.index],a=b.grep(c,function(a){return!!a}).length,0===a&&(this.$overlay.remove(),this.$bg.removeClass(p+"-is-"+t.CLOSING+" "+p+"-is-"+t.OPENING+" "+p+"-is-"+t.CLOSED+" "+p+"-is-"+t.OPENED))},b[o]={lookup:[]},b.fn[o]=function(a){var c,d;return this.each(function(e,f){d=b(f),null==d.data(o)?(c=new l(d,a),d.data(o,c.index),c.settings.hashTracking&&d.attr("data-"+o+"-id")===location.hash.substr(1)&&c.open()):c=b[o].lookup[d.data(o)]}),c},b(document).ready(function(){b(document).on("click","[data-"+o+"-target]",function(a){a.preventDefault();var c=a.currentTarget,d=c.getAttribute("data-"+o+"-target"),e=b("[data-"+o+"-id="+d+"]");b[o].lookup[e.data(o)].open()}),b(document).find("."+p).each(function(a,c){var d=b(c),e=d.data(o+"-options");e?("string"==typeof e||e instanceof String)&&(e=j(e)):e={},d[o](e)}),b(document).on("keyup."+p,function(a){m&&m.settings.closeOnEscape&&m.state===t.OPENED&&27===a.keyCode&&m.close()}),b(window).on("hashchange."+p,k)})});

/**!
 * wp-color-picker-alpha
 *
 * Overwrite Automattic Iris for enabled Alpha Channel in wpColorPicker
 * Only run in input and is defined data alpha in true
 *
 * Version: 2.1.2
 * https://github.com/kallookoo/wp-color-picker-alpha
 * Licensed under the GPLv2 license.
 */
!function(t){var o="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAAHnlligAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAHJJREFUeNpi+P///4EDBxiAGMgCCCAGFB5AADGCRBgYDh48CCRZIJS9vT2QBAggFBkmBiSAogxFBiCAoHogAKIKAlBUYTELAiAmEtABEECk20G6BOmuIl0CIMBQ/IEMkO0myiSSraaaBhZcbkUOs0HuBwDplz5uFJ3Z4gAAAABJRU5ErkJggg==",r='<div class="wp-picker-holder" />',e='<div class="wp-picker-container" />',i='<input type="button" class="button button-small" />',a=void 0!==wpColorPickerL10n.current;if(a)n='<a tabindex="0" class="wp-color-result" />';else var n='<button type="button" class="button wp-color-result" aria-expanded="false"><span class="wp-color-result-text"></span></button>',l="<label></label>",s='<span class="screen-reader-text"></span>';Color.fn.toString=function(){if(this._alpha<1)return this.toCSS("rgba",this._alpha).replace(/\s+/g,"");var t=parseInt(this._color,10).toString(16);return this.error?"":(t.length<6&&(t=("00000"+t).substr(-6)),"#"+t)},t.widget("wp.wpColorPicker",t.wp.wpColorPicker,{_create:function(){if(t.support.iris){var p=this,c=p.element;if(t.extend(p.options,c.data()),"hue"===p.options.type)return p._createHueOnly();p.close=t.proxy(p.close,p),p.initialValue=c.val(),c.addClass("wp-color-picker"),a?(c.hide().wrap(e),p.wrap=c.parent(),p.toggler=t(n).insertBefore(c).css({backgroundColor:p.initialValue}).attr("title",wpColorPickerL10n.pick).attr("data-current",wpColorPickerL10n.current),p.pickerContainer=t(r).insertAfter(c),p.button=t(i).addClass("hidden")):(c.parent("label").length||(c.wrap(l),p.wrappingLabelText=t(s).insertBefore(c).text(wpColorPickerL10n.defaultLabel)),p.wrappingLabel=c.parent(),p.wrappingLabel.wrap(e),p.wrap=p.wrappingLabel.parent(),p.toggler=t(n).insertBefore(p.wrappingLabel).css({backgroundColor:p.initialValue}),p.toggler.find(".wp-color-result-text").text(wpColorPickerL10n.pick),p.pickerContainer=t(r).insertAfter(p.wrappingLabel),p.button=t(i)),p.options.defaultColor?(p.button.addClass("wp-picker-default").val(wpColorPickerL10n.defaultString),a||p.button.attr("aria-label",wpColorPickerL10n.defaultAriaLabel)):(p.button.addClass("wp-picker-clear").val(wpColorPickerL10n.clear),a||p.button.attr("aria-label",wpColorPickerL10n.clearAriaLabel)),a?c.wrap('<span class="wp-picker-input-wrap" />').after(p.button):(p.wrappingLabel.wrap('<span class="wp-picker-input-wrap hidden" />').after(p.button),p.inputWrapper=c.closest(".wp-picker-input-wrap")),c.iris({target:p.pickerContainer,hide:p.options.hide,width:p.options.width,mode:p.options.mode,palettes:p.options.palettes,change:function(r,e){p.options.alpha?(p.toggler.css({"background-image":"url("+o+")"}),a?p.toggler.html('<span class="color-alpha" />'):(p.toggler.css({position:"relative"}),0==p.toggler.find("span.color-alpha").length&&p.toggler.append('<span class="color-alpha" />')),p.toggler.find("span.color-alpha").css({width:"30px",height:"24px",position:"absolute",top:0,left:0,"border-top-left-radius":"2px","border-bottom-left-radius":"2px",background:e.color.toString()})):p.toggler.css({backgroundColor:e.color.toString()}),t.isFunction(p.options.change)&&p.options.change.call(this,r,e)}}),c.val(p.initialValue),p._addListeners(),p.options.hide||p.toggler.click()}},_addListeners:function(){var o=this;o.wrap.on("click.wpcolorpicker",function(t){t.stopPropagation()}),o.toggler.click(function(){o.toggler.hasClass("wp-picker-open")?o.close():o.open()}),o.element.on("change",function(r){(""===t(this).val()||o.element.hasClass("iris-error"))&&(o.options.alpha?(a&&o.toggler.removeAttr("style"),o.toggler.find("span.color-alpha").css("backgroundColor","")):o.toggler.css("backgroundColor",""),t.isFunction(o.options.clear)&&o.options.clear.call(this,r))}),o.button.on("click",function(r){t(this).hasClass("wp-picker-clear")?(o.element.val(""),o.options.alpha?(a&&o.toggler.removeAttr("style"),o.toggler.find("span.color-alpha").css("backgroundColor","")):o.toggler.css("backgroundColor",""),t.isFunction(o.options.clear)&&o.options.clear.call(this,r)):t(this).hasClass("wp-picker-default")&&o.element.val(o.options.defaultColor).change()})}}),t.widget("a8c.iris",t.a8c.iris,{_create:function(){if(this._super(),this.options.alpha=this.element.data("alpha")||!1,this.element.is(":input")||(this.options.alpha=!1),void 0!==this.options.alpha&&this.options.alpha){var o=this,r=o.element,e=t('<div class="iris-strip iris-slider iris-alpha-slider"><div class="iris-slider-offset iris-slider-offset-alpha"></div></div>').appendTo(o.picker.find(".iris-picker-inner")),i={aContainer:e,aSlider:e.find(".iris-slider-offset-alpha")};void 0!==r.data("custom-width")?o.options.customWidth=parseInt(r.data("custom-width"))||0:o.options.customWidth=100,o.options.defaultWidth=r.width(),(o._color._alpha<1||-1!=o._color.toString().indexOf("rgb"))&&r.width(parseInt(o.options.defaultWidth+o.options.customWidth)),t.each(i,function(t,r){o.controls[t]=r}),o.controls.square.css({"margin-right":"0"});var a=o.picker.width()-o.controls.square.width()-20,n=a/6,l=a/2-n;t.each(["aContainer","strip"],function(t,r){o.controls[r].width(l).css({"margin-left":n+"px"})}),o._initControls(),o._change()}},_initControls:function(){if(this._super(),this.options.alpha){var t=this;t.controls.aSlider.slider({orientation:"vertical",min:0,max:100,step:1,value:parseInt(100*t._color._alpha),slide:function(o,r){t._color._alpha=parseFloat(r.value/100),t._change.apply(t,arguments)}})}},_change:function(){this._super();var t=this,r=t.element;if(this.options.alpha){var e=t.controls,i=parseInt(100*t._color._alpha),a=t._color.toRgb(),n=["rgb("+a.r+","+a.g+","+a.b+") 0%","rgba("+a.r+","+a.g+","+a.b+", 0) 100%"],l=t.options.defaultWidth,s=t.options.customWidth,p=t.picker.closest(".wp-picker-container").find(".wp-color-result");e.aContainer.css({background:"linear-gradient(to bottom, "+n.join(", ")+"), url("+o+")"}),p.hasClass("wp-picker-open")&&(e.aSlider.slider("value",i),t._color._alpha<1?(e.strip.attr("style",e.strip.attr("style").replace(/rgba\(([0-9]+,)(\s+)?([0-9]+,)(\s+)?([0-9]+)(,(\s+)?[0-9\.]+)\)/g,"rgb($1$3$5)")),r.width(parseInt(l+s))):r.width(l))}(r.data("reset-alpha")||!1)&&t.picker.find(".iris-palette-container").on("click.palette",".iris-palette",function(){t._color._alpha=1,t.active="external",t._change()})},_addInputListeners:function(t){var o=this,r=function(r){var e=new Color(t.val()),i=t.val();t.removeClass("iris-error"),e.error?""!==i&&t.addClass("iris-error"):e.toString()!==o._color.toString()&&("keyup"===r.type&&i.match(/^[0-9a-fA-F]{3}$/)||o._setOption("color",e.toString()))};t.on("change",r).on("keyup",o._debounce(r,100)),o.options.hide&&t.on("focus",function(){o.show()})}})}(jQuery),

/**
 * @license
 * Fuse - Lightweight fuzzy-search
 *
 * Copyright (c) 2012-2016 Kirollos Risk <kirollos@gmail.com>.
 * All Rights Reserved. Apache Software License 2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
!function(t){"use strict";function e(){console.log.apply(console,arguments)}function s(t,e){var s;this.list=t,this.options=e=e||{};for(s in r)r.hasOwnProperty(s)&&("boolean"==typeof r[s]?this.options[s]=s in e?e[s]:r[s]:this.options[s]=e[s]||r[s])}function n(t,e,s){var o,r,h,a,c,p;if(e){if(h=e.indexOf("."),h!==-1?(o=e.slice(0,h),r=e.slice(h+1)):o=e,a=t[o],null!==a&&void 0!==a)if(r||"string"!=typeof a&&"number"!=typeof a)if(i(a))for(c=0,p=a.length;c<p;c++)n(a[c],r,s);else r&&n(a,r,s);else s.push(a)}else s.push(t);return s}function i(t){return"[object Array]"===Object.prototype.toString.call(t)}function o(t,e){e=e||{},this.options=e,this.options.location=e.location||o.defaultOptions.location,this.options.distance="distance"in e?e.distance:o.defaultOptions.distance,this.options.threshold="threshold"in e?e.threshold:o.defaultOptions.threshold,this.options.maxPatternLength=e.maxPatternLength||o.defaultOptions.maxPatternLength,this.pattern=e.caseSensitive?t:t.toLowerCase(),this.patternLen=t.length,this.patternLen<=this.options.maxPatternLength&&(this.matchmask=1<<this.patternLen-1,this.patternAlphabet=this._calculatePatternAlphabet())}var r={id:null,caseSensitive:!1,include:[],shouldSort:!0,searchFn:o,sortFn:function(t,e){return t.score-e.score},getFn:n,keys:[],verbose:!1,tokenize:!1,matchAllTokens:!1,tokenSeparator:/ +/g,minMatchCharLength:1,findAllMatches:!1};s.VERSION="2.6.0",s.prototype.set=function(t){return this.list=t,t},s.prototype.search=function(t){this.options.verbose&&e("\nSearch term:",t,"\n"),this.pattern=t,this.results=[],this.resultMap={},this._keyMap=null,this._prepareSearchers(),this._startSearch(),this._computeScore(),this._sort();var s=this._format();return s},s.prototype._prepareSearchers=function(){var t=this.options,e=this.pattern,s=t.searchFn,n=e.split(t.tokenSeparator),i=0,o=n.length;if(this.options.tokenize)for(this.tokenSearchers=[];i<o;i++)this.tokenSearchers.push(new s(n[i],t));this.fullSeacher=new s(e,t)},s.prototype._startSearch=function(){var t,e,s,n,i=this.options,o=i.getFn,r=this.list,h=r.length,a=this.options.keys,c=a.length,p=null;if("string"==typeof r[0])for(s=0;s<h;s++)this._analyze("",r[s],s,s);else for(this._keyMap={},s=0;s<h;s++)for(p=r[s],n=0;n<c;n++){if(t=a[n],"string"!=typeof t){if(e=1-t.weight||1,this._keyMap[t.name]={weight:e},t.weight<=0||t.weight>1)throw new Error("Key weight has to be > 0 and <= 1");t=t.name}else this._keyMap[t]={weight:1};this._analyze(t,o(p,t,[]),p,s)}},s.prototype._analyze=function(t,s,n,o){var r,h,a,c,p,l,u,f,d,g,m,y,v,k,S,b=this.options,M=!1;if(void 0!==s&&null!==s){h=[];var _=0;if("string"==typeof s){if(r=s.split(b.tokenSeparator),b.verbose&&e("---------\nKey:",t),this.options.tokenize){for(k=0;k<this.tokenSearchers.length;k++){for(f=this.tokenSearchers[k],b.verbose&&e("Pattern:",f.pattern),d=[],y=!1,S=0;S<r.length;S++){g=r[S],m=f.search(g);var L={};m.isMatch?(L[g]=m.score,M=!0,y=!0,h.push(m.score)):(L[g]=1,this.options.matchAllTokens||h.push(1)),d.push(L)}y&&_++,b.verbose&&e("Token scores:",d)}for(c=h[0],l=h.length,k=1;k<l;k++)c+=h[k];c/=l,b.verbose&&e("Token score average:",c)}u=this.fullSeacher.search(s),b.verbose&&e("Full text score:",u.score),p=u.score,void 0!==c&&(p=(p+c)/2),b.verbose&&e("Score average:",p),v=!this.options.tokenize||!this.options.matchAllTokens||_>=this.tokenSearchers.length,b.verbose&&e("Check Matches",v),(M||u.isMatch)&&v&&(a=this.resultMap[o],a?a.output.push({key:t,score:p,matchedIndices:u.matchedIndices}):(this.resultMap[o]={item:n,output:[{key:t,score:p,matchedIndices:u.matchedIndices}]},this.results.push(this.resultMap[o])))}else if(i(s))for(k=0;k<s.length;k++)this._analyze(t,s[k],n,o)}},s.prototype._computeScore=function(){var t,s,n,i,o,r,h,a,c,p=this._keyMap,l=this.results;for(this.options.verbose&&e("\n\nComputing score:\n"),t=0;t<l.length;t++){for(n=0,i=l[t].output,o=i.length,a=1,s=0;s<o;s++)r=i[s].score,h=p?p[i[s].key].weight:1,c=r*h,1!==h?a=Math.min(a,c):(n+=c,i[s].nScore=c);1===a?l[t].score=n/o:l[t].score=a,this.options.verbose&&e(l[t])}},s.prototype._sort=function(){var t=this.options;t.shouldSort&&(t.verbose&&e("\n\nSorting...."),this.results.sort(t.sortFn))},s.prototype._format=function(){var t,s,n,i,o,r=this.options,h=r.getFn,a=[],c=this.results,p=r.include;for(r.verbose&&e("\n\nOutput:\n\n",c),i=r.id?function(t){c[t].item=h(c[t].item,r.id,[])[0]}:function(){},o=function(t){var e,s,n,i,o,r=c[t];if(p.length>0){if(e={item:r.item},p.indexOf("matches")!==-1)for(n=r.output,e.matches=[],s=0;s<n.length;s++)i=n[s],o={indices:i.matchedIndices},i.key&&(o.key=i.key),e.matches.push(o);p.indexOf("score")!==-1&&(e.score=c[t].score)}else e=r.item;return e},s=0,n=c.length;s<n;s++)i(s),t=o(s),a.push(t);return a},o.defaultOptions={location:0,distance:100,threshold:.6,maxPatternLength:32},o.prototype._calculatePatternAlphabet=function(){var t={},e=0;for(e=0;e<this.patternLen;e++)t[this.pattern.charAt(e)]=0;for(e=0;e<this.patternLen;e++)t[this.pattern.charAt(e)]|=1<<this.pattern.length-e-1;return t},o.prototype._bitapScore=function(t,e){var s=t/this.patternLen,n=Math.abs(this.options.location-e);return this.options.distance?s+n/this.options.distance:n?1:s},o.prototype.search=function(t){var e,s,n,i,o,r,h,a,c,p,l,u,f,d,g,m,y,v,k,S,b,M,_,L=this.options;if(t=L.caseSensitive?t:t.toLowerCase(),this.pattern===t)return{isMatch:!0,score:0,matchedIndices:[[0,t.length-1]]};if(this.patternLen>L.maxPatternLength){if(v=t.match(new RegExp(this.pattern.replace(L.tokenSeparator,"|"))),k=!!v)for(b=[],e=0,M=v.length;e<M;e++)_=v[e],b.push([t.indexOf(_),_.length-1]);return{isMatch:k,score:k?.5:1,matchedIndices:b}}for(i=L.findAllMatches,o=L.location,n=t.length,r=L.threshold,h=t.indexOf(this.pattern,o),S=[],e=0;e<n;e++)S[e]=0;for(h!=-1&&(r=Math.min(this._bitapScore(0,h),r),h=t.lastIndexOf(this.pattern,o+this.patternLen),h!=-1&&(r=Math.min(this._bitapScore(0,h),r))),h=-1,m=1,y=[],p=this.patternLen+n,e=0;e<this.patternLen;e++){for(a=0,c=p;a<c;)this._bitapScore(e,o+c)<=r?a=c:p=c,c=Math.floor((p-a)/2+a);for(p=c,l=Math.max(1,o-c+1),u=i?n:Math.min(o+c,n)+this.patternLen,f=Array(u+2),f[u+1]=(1<<e)-1,s=u;s>=l;s--)if(g=this.patternAlphabet[t.charAt(s-1)],g&&(S[s-1]=1),0===e?f[s]=(f[s+1]<<1|1)&g:f[s]=(f[s+1]<<1|1)&g|((d[s+1]|d[s])<<1|1)|d[s+1],f[s]&this.matchmask&&(m=this._bitapScore(e,s-1),m<=r)){if(r=m,h=s-1,y.push(h),!(h>o))break;l=Math.max(1,2*o-h)}if(this._bitapScore(e+1,o)>r)break;d=f}return b=this._getMatchedIndices(S),{isMatch:h>=0,score:0===m?.001:m,matchedIndices:b}},o.prototype._getMatchedIndices=function(t){for(var e,s=[],n=-1,i=-1,o=0,r=t.length;o<r;o++)e=t[o],e&&n===-1?n=o:e||n===-1||(i=o-1,i-n+1>=this.options.minMatchCharLength&&s.push([n,i]),n=-1);return t[o-1]&&o-1-n+1>=this.options.minMatchCharLength&&s.push([n,o-1]),s},"object"==typeof exports?module.exports=s:"function"==typeof define&&define.amd?define(function(){return s}):t.Fuse=s}(this);
libs/better-framework/assets/js/pretty-photo.js000064400000125513151214002550015711 0ustar00/**
 * Class: prettyPhoto
 * Use: Lightbox clone for jQuery
 * Author: Stephane Caron (http://www.no-margin-for-errors.com)
 * Version: 3.1.6
 **/
(function($) {

    // if it was added before
    if ( $.fn.prettyPhoto ) {
        return;
    }

    $.prettyPhoto = {version: '3.1.6'};

    $.fn.prettyPhoto = function(pp_settings) {
        pp_settings = jQuery.extend({
            hook: 'rel', /* the attribute tag to use for prettyPhoto hooks. default: 'rel'. For HTML5, use "data-rel" or similar. */
            animation_speed: 'fast', /* fast/slow/normal */
            ajaxcallback: function() {},
            slideshow: 5000, /* false OR interval time in ms */
            autoplay_slideshow: false, /* true/false */
            opacity: 0.80, /* Value between 0 and 1 */
            show_title: true, /* true/false */
            allow_resize: true, /* Resize the photos bigger than viewport. true/false */
            allow_expand: true, /* Allow the user to expand a resized image. true/false */
            default_width: 500,
            default_height: 344,
            counter_separator_label: '/', /* The separator for the gallery counter 1 "of" 2 */
            theme: 'pp_default', /* light_rounded / dark_rounded / light_square / dark_square / facebook */
            horizontal_padding: 20, /* The padding on each side of the picture */
            hideflash: false, /* Hides all the flash object on a page, set to TRUE if flash appears over prettyPhoto */
            wmode: 'opaque', /* Set the flash wmode attribute */
            autoplay: true, /* Automatically start videos: True/False */
            modal: false, /* If set to true, only the close button will close the window */
            deeplinking: true, /* Allow prettyPhoto to update the url to enable deeplinking. */
            overlay_gallery: true, /* If set to true, a gallery will overlay the fullscreen image on mouse over */
            overlay_gallery_max: 30, /* Maximum number of pictures in the overlay gallery */
            keyboard_shortcuts: true, /* Set to false if you open forms inside prettyPhoto */
            changepicturecallback: function(){}, /* Called everytime an item is shown/changed */
            callback: function(){}, /* Called when prettyPhoto is closed */
            ie6_fallback: true,
            markup: '<div class="pp_pic_holder"> ' +
                        '<div class="ppt">&nbsp;</div> ' +
                        '<div class="pp_top"> ' +
                            '<div class="pp_left"></div> ' +
                            '<div class="pp_middle"></div> ' +
                            '<div class="pp_right"></div> ' +
                        '</div> ' +
                        '<div class="pp_content_container"> ' +
                            '<div class="pp_left"> ' +
                            '<div class="pp_right"> ' +
                                '<div class="pp_content"> ' +
                                    '<div class="pp_loaderIcon"></div> ' +
                                    '<div class="pp_fade"> ' +
                                        '<a href="#" class="pp_expand" title="Expand the image">Expand</a> ' +
                                        '<div class="pp_hoverContainer"> ' +
                                            '<a class="pp_next" href="#">next</a> ' +
                                            '<a class="pp_previous" href="#">previous</a> ' +
                                        '</div> ' +
                                        '<div id="pp_full_res"></div> ' +
                                        '<div class="pp_details"> ' +
                                            '<div class="pp_nav"> ' +
                                                '<a href="#" class="pp_arrow_previous">Previous</a> ' +
                                                '<p class="currentTextHolder">0/0</p> ' +
                                                '<a href="#" class="pp_arrow_next">Next</a> ' +
                                            '</div> ' +
                                            '<p class="pp_description"></p> ' +
                                            '<div class="pp_social">{pp_social}</div> ' +
                                            '<a class="pp_close" href="#">Close</a> ' +
                                        '</div> ' +
                                    '</div> ' +
                                '</div> ' +
                            '</div> ' +
                            '</div> ' +
                        '</div> ' +
                        '<div class="pp_bottom"> ' +
                            '<div class="pp_left"></div> ' +
                            '<div class="pp_middle"></div> ' +
                            '<div class="pp_right"></div> ' +
                        '</div> ' +
                    '</div> ' +
                '<div class="pp_overlay"></div>',
            gallery_markup: '<div class="pp_gallery"> ' +
                                '<a href="#" class="pp_arrow_previous">Previous</a> ' +
                                '<div> ' +
                                    '<ul> ' +
                                        '{gallery} ' +
                                    '</ul> ' +
                                '</div> ' +
                                '<a href="#" class="pp_arrow_next">Next</a> ' +
                            '</div>',
            image_markup: '<img id="fullResImage" src="{path}" />',
            flash_markup: '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="{width}" height="{height}"><param name="wmode" value="{wmode}" /><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="{path}" /><embed src="{path}" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="{width}" height="{height}" wmode="{wmode}"></embed></object>',
            quicktime_markup: '<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab" height="{height}" width="{width}"><param name="src" value="{path}"><param name="autoplay" value="{autoplay}"><param name="type" value="video/quicktime"><embed src="{path}" height="{height}" width="{width}" autoplay="{autoplay}" type="video/quicktime" pluginspage="http://www.apple.com/quicktime/download/"></embed></object>',
            iframe_markup: '<iframe src ="{path}" width="{width}" height="{height}" frameborder="no"></iframe>',
            inline_markup: '<div class="pp_inline">{content}</div>',
            custom_markup: '',
            social_tools: '<div class="twitter"><a href="http://twitter.com/share" class="twitter-share-button" data-count="none">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div><div class="facebook"><iframe src="//www.facebook.com/plugins/like.php?locale=en_US&href={location_href}&amp;layout=button_count&amp;show_faces=true&amp;width=500&amp;action=like&amp;font&amp;colorscheme=light&amp;height=23" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:500px; height:23px;" allowTransparency="true"></iframe></div>' /* html or false to disable */
        }, pp_settings);

        // Global variables accessible only by prettyPhoto
        var matchedObjects = this, percentBased = false, pp_dimensions, pp_open,

        // prettyPhoto container specific
            pp_contentHeight, pp_contentWidth, pp_containerHeight, pp_containerWidth,

        // Window size
            windowHeight = $(window).height(), windowWidth = $(window).width(),

        // Global elements
            pp_slideshow;

        doresize = true, scroll_pos = _get_scroll();

        // Window/Keyboard events
        $(window).unbind('resize.prettyphoto').bind('resize.prettyphoto',function(){ _center_overlay(); _resize_overlay(); });

        if(pp_settings.keyboard_shortcuts) {
            $(document).unbind('keydown.prettyphoto').bind('keydown.prettyphoto',function(e){
                if(typeof $pp_pic_holder != 'undefined'){
                    if($pp_pic_holder.is(':visible')){
                        switch(e.keyCode){
                            case 37:
                                $.prettyPhoto.changePage('previous');
                                e.preventDefault();
                                break;
                            case 39:
                                $.prettyPhoto.changePage('next');
                                e.preventDefault();
                                break;
                            case 27:
                                if(!settings.modal)
                                    $.prettyPhoto.close();
                                e.preventDefault();
                                break;
                        };
                    };
                };
            });
        };

        /**
         * Initialize prettyPhoto.
         */
        $.prettyPhoto.initialize = function() {

            settings = pp_settings;

            if(settings.theme == 'pp_default') settings.horizontal_padding = 16;

            // Find out if the picture is part of a set
            theRel = $(this).attr(settings.hook);
            galleryRegExp = /\[(?:.*)\]/;
            isSet = (galleryRegExp.exec(theRel)) ? true : false;

            // Put the SRCs, TITLEs, ALTs into an array.
            pp_images = (isSet) ? jQuery.map(matchedObjects, function(n, i){ if($(n).attr(settings.hook).indexOf(theRel) != -1) return $(n).attr('href'); }) : $.makeArray($(this).attr('href'));
            pp_titles = (isSet) ? jQuery.map(matchedObjects, function(n, i){ if($(n).attr(settings.hook).indexOf(theRel) != -1) return ($(n).find('img').attr('alt')) ? $(n).find('img').attr('alt') : ""; }) : $.makeArray($(this).find('img').attr('alt'));
            pp_descriptions = (isSet) ? jQuery.map(matchedObjects, function(n, i){ if($(n).attr(settings.hook).indexOf(theRel) != -1) return ($(n).attr('title')) ? $(n).attr('title') : ""; }) : $.makeArray($(this).attr('title'));

            if(pp_images.length > settings.overlay_gallery_max) settings.overlay_gallery = false;

            set_position = jQuery.inArray($(this).attr('href'), pp_images); // Define where in the array the clicked item is positionned
            rel_index = (isSet) ? set_position : $("a["+settings.hook+"^='"+theRel+"']").index($(this));

            _build_overlay(this); // Build the overlay {this} being the caller

            if(settings.allow_resize)
                $(window).bind('scroll.prettyphoto',function(){ _center_overlay(); });


            $.prettyPhoto.open();

            return false;
        }


        /**
         * Opens the prettyPhoto modal box.
         * @param image {String,Array} Full path to the image to be open, can also be an array containing full images paths.
         * @param title {String,Array} The title to be displayed with the picture, can also be an array containing all the titles.
         * @param description {String,Array} The description to be displayed with the picture, can also be an array containing all the descriptions.
         */
        $.prettyPhoto.open = function(event) {
            if(typeof settings == "undefined"){ // Means it's an API call, need to manually get the settings and set the variables
                settings = pp_settings;
                pp_images = $.makeArray(arguments[0]);
                pp_titles = (arguments[1]) ? $.makeArray(arguments[1]) : $.makeArray("");
                pp_descriptions = (arguments[2]) ? $.makeArray(arguments[2]) : $.makeArray("");
                isSet = (pp_images.length > 1) ? true : false;
                set_position = (arguments[3])? arguments[3]: 0;
                _build_overlay(event.target); // Build the overlay {this} being the caller
            }

            if(settings.hideflash) $('object,embed,iframe[src*=youtube],iframe[src*=vimeo]').css('visibility','hidden'); // Hide the flash

            _checkPosition($(pp_images).size()); // Hide the next/previous links if on first or last images.

            $('.pp_loaderIcon').show();

            if(settings.deeplinking)
                setHashtag();

            // Rebuild Facebook Like Button with updated href
            if(settings.social_tools){
                facebook_like_link = settings.social_tools.replace('{location_href}', encodeURIComponent(location.href));
                $pp_pic_holder.find('.pp_social').html(facebook_like_link);
            }

            // Fade the content in
            if($ppt.is(':hidden')) $ppt.css('opacity',0).show();
            $pp_overlay.show().fadeTo(settings.animation_speed,settings.opacity);

            // Display the current position
            $pp_pic_holder.find('.currentTextHolder').text((set_position+1) + settings.counter_separator_label + $(pp_images).size());

            // Set the description
            if(typeof pp_descriptions[set_position] != 'undefined' && pp_descriptions[set_position] != ""){
                $pp_pic_holder.find('.pp_description').show().html(unescape(pp_descriptions[set_position]));
            }else{
                $pp_pic_holder.find('.pp_description').hide();
            }

            // Get the dimensions
            movie_width = ( parseFloat(getParam('width',pp_images[set_position])) ) ? getParam('width',pp_images[set_position]) : settings.default_width.toString();
            movie_height = ( parseFloat(getParam('height',pp_images[set_position])) ) ? getParam('height',pp_images[set_position]) : settings.default_height.toString();

            // If the size is % based, calculate according to window dimensions
            percentBased=false;
            if(movie_height.indexOf('%') != -1) { movie_height = parseFloat(($(window).height() * parseFloat(movie_height) / 100) - 150); percentBased = true; }
            if(movie_width.indexOf('%') != -1) { movie_width = parseFloat(($(window).width() * parseFloat(movie_width) / 100) - 150); percentBased = true; }

            // Fade the holder
            $pp_pic_holder.fadeIn(function(){
                // Set the title
                (settings.show_title && pp_titles[set_position] != "" && typeof pp_titles[set_position] != "undefined") ? $ppt.html(unescape(pp_titles[set_position])) : $ppt.html('&nbsp;');

                imgPreloader = "";
                skipInjection = false;

                // Inject the proper content
                switch(_getFileType(pp_images[set_position])){
                    case 'image':
                        imgPreloader = new Image();

                        // Preload the neighbour images
                        nextImage = new Image();
                        if(isSet && set_position < $(pp_images).size() -1) nextImage.src = pp_images[set_position + 1];
                        prevImage = new Image();
                        if(isSet && pp_images[set_position - 1]) prevImage.src = pp_images[set_position - 1];

                        $pp_pic_holder.find('#pp_full_res')[0].innerHTML = settings.image_markup.replace(/{path}/g,pp_images[set_position]);

                        imgPreloader.onload = function(){
                            // Fit item to viewport
                            pp_dimensions = _fitToViewport(imgPreloader.width,imgPreloader.height);

                            _showContent();
                        };

                        imgPreloader.onerror = function(){
                            alert('Image cannot be loaded. Make sure the path is correct and image exist.');
                            $.prettyPhoto.close();
                        };

                        imgPreloader.src = pp_images[set_position];
                        break;

                    case 'youtube':
                        pp_dimensions = _fitToViewport(movie_width,movie_height); // Fit item to viewport

                        // Regular youtube link
                        movie_id = getParam('v',pp_images[set_position]);

                        // youtu.be link
                        if(movie_id == ""){
                            movie_id = pp_images[set_position].split('youtu.be/');
                            movie_id = movie_id[1];
                            if(movie_id.indexOf('?') > 0)
                                movie_id = movie_id.substr(0,movie_id.indexOf('?')); // Strip anything after the ?

                            if(movie_id.indexOf('&') > 0)
                                movie_id = movie_id.substr(0,movie_id.indexOf('&')); // Strip anything after the &
                        }

                        movie = 'http://www.youtube.com/embed/'+movie_id;
                        (getParam('rel',pp_images[set_position])) ? movie+="?rel="+getParam('rel',pp_images[set_position]) : movie+="?rel=1";

                        if(settings.autoplay) movie += "&autoplay=1";

                        toInject = settings.iframe_markup.replace(/{width}/g,pp_dimensions['width']).replace(/{height}/g,pp_dimensions['height']).replace(/{wmode}/g,settings.wmode).replace(/{path}/g,movie);
                        break;

                    case 'vimeo':
                        pp_dimensions = _fitToViewport(movie_width,movie_height); // Fit item to viewport

                        movie_id = pp_images[set_position];
                        var regExp = /http(s?):\/\/(www\.)?vimeo.com\/(\d+)/;
                        var match = movie_id.match(regExp);

                        movie = 'http://player.vimeo.com/video/'+ match[3] +'?title=0&amp;byline=0&amp;portrait=0';
                        if(settings.autoplay) movie += "&autoplay=1;";

                        vimeo_width = pp_dimensions['width'] + '/embed/?moog_width='+ pp_dimensions['width'];

                        toInject = settings.iframe_markup.replace(/{width}/g,vimeo_width).replace(/{height}/g,pp_dimensions['height']).replace(/{path}/g,movie);
                        break;

                    case 'quicktime':
                        pp_dimensions = _fitToViewport(movie_width,movie_height); // Fit item to viewport
                        pp_dimensions['height']+=15; pp_dimensions['contentHeight']+=15; pp_dimensions['containerHeight']+=15; // Add space for the control bar

                        toInject = settings.quicktime_markup.replace(/{width}/g,pp_dimensions['width']).replace(/{height}/g,pp_dimensions['height']).replace(/{wmode}/g,settings.wmode).replace(/{path}/g,pp_images[set_position]).replace(/{autoplay}/g,settings.autoplay);
                        break;

                    case 'flash':
                        pp_dimensions = _fitToViewport(movie_width,movie_height); // Fit item to viewport

                        flash_vars = pp_images[set_position];
                        flash_vars = flash_vars.substring(pp_images[set_position].indexOf('flashvars') + 10,pp_images[set_position].length);

                        filename = pp_images[set_position];
                        filename = filename.substring(0,filename.indexOf('?'));

                        toInject =  settings.flash_markup.replace(/{width}/g,pp_dimensions['width']).replace(/{height}/g,pp_dimensions['height']).replace(/{wmode}/g,settings.wmode).replace(/{path}/g,filename+'?'+flash_vars);
                        break;

                    case 'iframe':
                        pp_dimensions = _fitToViewport(movie_width,movie_height); // Fit item to viewport

                        frame_url = pp_images[set_position];
                        frame_url = frame_url.substr(0,frame_url.indexOf('iframe')-1);

                        toInject = settings.iframe_markup.replace(/{width}/g,pp_dimensions['width']).replace(/{height}/g,pp_dimensions['height']).replace(/{path}/g,frame_url);
                        break;

                    case 'ajax':
                        doresize = false; // Make sure the dimensions are not resized.
                        pp_dimensions = _fitToViewport(movie_width,movie_height);
                        doresize = true; // Reset the dimensions

                        skipInjection = true;
                        $.get(pp_images[set_position],function(responseHTML){
                            toInject = settings.inline_markup.replace(/{content}/g,responseHTML);
                            $pp_pic_holder.find('#pp_full_res')[0].innerHTML = toInject;
                            _showContent();
                        });

                        break;

                    case 'custom':
                        pp_dimensions = _fitToViewport(movie_width,movie_height); // Fit item to viewport

                        toInject = settings.custom_markup;
                        break;

                    case 'inline':
                        // to get the item height clone it, apply default width, wrap it in the prettyPhoto containers , then delete
                        myClone = $(pp_images[set_position]).clone().append('<br clear="all" />').css({'width':settings.default_width}).wrapInner('<div id="pp_full_res"><div class="pp_inline"></div></div>').appendTo($('body')).show();
                        doresize = false; // Make sure the dimensions are not resized.
                        pp_dimensions = _fitToViewport($(myClone).width(),$(myClone).height());
                        doresize = true; // Reset the dimensions
                        $(myClone).remove();
                        toInject = settings.inline_markup.replace(/{content}/g,$(pp_images[set_position]).html());
                        break;
                };

                if(!imgPreloader && !skipInjection){
                    $pp_pic_holder.find('#pp_full_res')[0].innerHTML = toInject;

                    // Show content
                    _showContent();
                };
            });

            return false;
        };


        /**
         * Change page in the prettyPhoto modal box
         * @param direction {String} Direction of the paging, previous or next.
         */
        $.prettyPhoto.changePage = function(direction){
            currentGalleryPage = 0;

            if(direction == 'previous') {
                set_position--;
                if (set_position < 0) set_position = $(pp_images).size()-1;
            }else if(direction == 'next'){
                set_position++;
                if(set_position > $(pp_images).size()-1) set_position = 0;
            }else{
                set_position=direction;
            };

            rel_index = set_position;

            if(!doresize) doresize = true; // Allow the resizing of the images
            if(settings.allow_expand) {
                $('.pp_contract').removeClass('pp_contract').addClass('pp_expand');
            }

            _hideContent(function(){ $.prettyPhoto.open(); });
        };


        /**
         * Change gallery page in the prettyPhoto modal box
         * @param direction {String} Direction of the paging, previous or next.
         */
        $.prettyPhoto.changeGalleryPage = function(direction){
            if(direction=='next'){
                currentGalleryPage ++;

                if(currentGalleryPage > totalPage) currentGalleryPage = 0;
            }else if(direction=='previous'){
                currentGalleryPage --;

                if(currentGalleryPage < 0) currentGalleryPage = totalPage;
            }else{
                currentGalleryPage = direction;
            };

            slide_speed = (direction == 'next' || direction == 'previous') ? settings.animation_speed : 0;

            slide_to = currentGalleryPage * (itemsPerPage * itemWidth);

            $pp_gallery.find('ul').animate({left:-slide_to},slide_speed);
        };


        /**
         * Start the slideshow...
         */
        $.prettyPhoto.startSlideshow = function(){
            if(typeof pp_slideshow == 'undefined'){
                $pp_pic_holder.find('.pp_play').unbind('click').removeClass('pp_play').addClass('pp_pause').click(function(){
                    $.prettyPhoto.stopSlideshow();
                    return false;
                });
                pp_slideshow = setInterval($.prettyPhoto.startSlideshow,settings.slideshow);
            }else{
                $.prettyPhoto.changePage('next');
            };
        }


        /**
         * Stop the slideshow...
         */
        $.prettyPhoto.stopSlideshow = function(){
            $pp_pic_holder.find('.pp_pause').unbind('click').removeClass('pp_pause').addClass('pp_play').click(function(){
                $.prettyPhoto.startSlideshow();
                return false;
            });
            clearInterval(pp_slideshow);
            pp_slideshow=undefined;
        }


        /**
         * Closes prettyPhoto.
         */
        $.prettyPhoto.close = function(){
            if($pp_overlay.is(":animated")) return;

            $.prettyPhoto.stopSlideshow();

            $pp_pic_holder.stop().find('object,embed').css('visibility','hidden');

            $('div.pp_pic_holder,div.ppt,.pp_fade').fadeOut(settings.animation_speed,function(){ $(this).remove(); });

            $pp_overlay.fadeOut(settings.animation_speed, function(){

                if(settings.hideflash) $('object,embed,iframe[src*=youtube],iframe[src*=vimeo]').css('visibility','visible'); // Show the flash

                $(this).remove(); // No more need for the prettyPhoto markup

                $(window).unbind('scroll.prettyphoto');

                clearHashtag();

                settings.callback();

                doresize = true;

                pp_open = false;

                delete settings;
            });
        };

        /**
         * Set the proper sizes on the containers and animate the content in.
         */
        function _showContent(){
            $('.pp_loaderIcon').hide();

            // Calculate the opened top position of the pic holder
            projectedTop = scroll_pos['scrollTop'] + ((windowHeight/2) - (pp_dimensions['containerHeight']/2));
            if(projectedTop < 0) projectedTop = 0;

            $ppt.fadeTo(settings.animation_speed,1);

            // Resize the content holder
            $pp_pic_holder.find('.pp_content')
                .animate({
                    height:pp_dimensions['contentHeight'],
                    width:pp_dimensions['contentWidth']
                },settings.animation_speed);

            // Resize picture the holder
            $pp_pic_holder.animate({
                'top': projectedTop,
                'left': ((windowWidth/2) - (pp_dimensions['containerWidth']/2) < 0) ? 0 : (windowWidth/2) - (pp_dimensions['containerWidth']/2),
                width:pp_dimensions['containerWidth']
            },settings.animation_speed,function(){
                $pp_pic_holder.find('.pp_hoverContainer,#fullResImage').height(pp_dimensions['height']).width(pp_dimensions['width']);

                $pp_pic_holder.find('.pp_fade').fadeIn(settings.animation_speed); // Fade the new content

                // Show the nav
                if(isSet && _getFileType(pp_images[set_position])=="image") { $pp_pic_holder.find('.pp_hoverContainer').show(); }else{ $pp_pic_holder.find('.pp_hoverContainer').hide(); }

                if(settings.allow_expand) {
                    if(pp_dimensions['resized']){ // Fade the resizing link if the image is resized
                        $('a.pp_expand,a.pp_contract').show();
                    }else{
                        $('a.pp_expand').hide();
                    }
                }

                if(settings.autoplay_slideshow && !pp_slideshow && !pp_open) $.prettyPhoto.startSlideshow();

                settings.changepicturecallback(); // Callback!

                pp_open = true;
            });

            _insert_gallery();
            pp_settings.ajaxcallback();
        };

        /**
         * Hide the content...DUH!
         */
        function _hideContent(callback){
            // Fade out the current picture
            $pp_pic_holder.find('#pp_full_res object,#pp_full_res embed').css('visibility','hidden');
            $pp_pic_holder.find('.pp_fade').fadeOut(settings.animation_speed,function(){
                $('.pp_loaderIcon').show();

                callback();
            });
        };

        /**
         * Check the item position in the gallery array, hide or show the navigation links
         * @param setCount {integer} The total number of items in the set
         */
        function _checkPosition(setCount){
            (setCount > 1) ? $('.pp_nav').show() : $('.pp_nav').hide(); // Hide the bottom nav if it's not a set.
        };

        /**
         * Resize the item dimensions if it's bigger than the viewport
         * @param width {integer} Width of the item to be opened
         * @param height {integer} Height of the item to be opened
         * @return An array containin the "fitted" dimensions
         */
        function _fitToViewport(width,height){
            resized = false;

            _getDimensions(width,height);

            // Define them in case there's no resize needed
            imageWidth = width, imageHeight = height;

            if( ((pp_containerWidth > windowWidth) || (pp_containerHeight > windowHeight)) && doresize && settings.allow_resize && !percentBased) {
                resized = true, fitting = false;

                while (!fitting){
                    if((pp_containerWidth > windowWidth)){
                        imageWidth = (windowWidth - 200);
                        imageHeight = (height/width) * imageWidth;
                    }else if((pp_containerHeight > windowHeight)){
                        imageHeight = (windowHeight - 200);
                        imageWidth = (width/height) * imageHeight;
                    }else{
                        fitting = true;
                    };

                    pp_containerHeight = imageHeight, pp_containerWidth = imageWidth;
                };



                if((pp_containerWidth > windowWidth) || (pp_containerHeight > windowHeight)){
                    _fitToViewport(pp_containerWidth,pp_containerHeight)
                };

                _getDimensions(imageWidth,imageHeight);
            };

            return {
                width:Math.floor(imageWidth),
                height:Math.floor(imageHeight),
                containerHeight:Math.floor(pp_containerHeight),
                containerWidth:Math.floor(pp_containerWidth) + (settings.horizontal_padding * 2),
                contentHeight:Math.floor(pp_contentHeight),
                contentWidth:Math.floor(pp_contentWidth),
                resized:resized
            };
        };

        /**
         * Get the containers dimensions according to the item size
         * @param width {integer} Width of the item to be opened
         * @param height {integer} Height of the item to be opened
         */
        function _getDimensions(width,height){
            width = parseFloat(width);
            height = parseFloat(height);

            // Get the details height, to do so, I need to clone it since it's invisible
            $pp_details = $pp_pic_holder.find('.pp_details');
            $pp_details.width(width);
            detailsHeight = parseFloat($pp_details.css('marginTop')) + parseFloat($pp_details.css('marginBottom'));

            $pp_details = $pp_details.clone().addClass(settings.theme).width(width).appendTo($('body')).css({
                'position':'absolute',
                'top':-10000
            });
            detailsHeight += $pp_details.height();
            detailsHeight = (detailsHeight <= 34) ? 36 : detailsHeight; // Min-height for the details
            $pp_details.remove();

            // Get the titles height, to do so, I need to clone it since it's invisible
            $pp_title = $pp_pic_holder.find('.ppt');
            $pp_title.width(width);
            titleHeight = parseFloat($pp_title.css('marginTop')) + parseFloat($pp_title.css('marginBottom'));
            $pp_title = $pp_title.clone().appendTo($('body')).css({
                'position':'absolute',
                'top':-10000
            });
            titleHeight += $pp_title.height();
            $pp_title.remove();

            // Get the container size, to resize the holder to the right dimensions
            pp_contentHeight = height + detailsHeight;
            pp_contentWidth = width;
            pp_containerHeight = pp_contentHeight + titleHeight + $pp_pic_holder.find('.pp_top').height() + $pp_pic_holder.find('.pp_bottom').height();
            pp_containerWidth = width;
        }

        function _getFileType(itemSrc){
            if (itemSrc.match(/youtube\.com\/watch/i) || itemSrc.match(/youtu\.be/i)) {
                return 'youtube';
            }else if (itemSrc.match(/vimeo\.com/i)) {
                return 'vimeo';
            }else if(itemSrc.match(/\b.mov\b/i)){
                return 'quicktime';
            }else if(itemSrc.match(/\b.swf\b/i)){
                return 'flash';
            }else if(itemSrc.match(/\biframe=true\b/i)){
                return 'iframe';
            }else if(itemSrc.match(/\bajax=true\b/i)){
                return 'ajax';
            }else if(itemSrc.match(/\bcustom=true\b/i)){
                return 'custom';
            }else if(itemSrc.substr(0,1) == '#'){
                return 'inline';
            }else{
                return 'image';
            };
        };

        function _center_overlay(){
            if(doresize && typeof $pp_pic_holder != 'undefined') {
                scroll_pos = _get_scroll();
                contentHeight = $pp_pic_holder.height(), contentwidth = $pp_pic_holder.width();

                projectedTop = (windowHeight/2) + scroll_pos['scrollTop'] - (contentHeight/2);
                if(projectedTop < 0) projectedTop = 0;

                if(contentHeight > windowHeight)
                    return;

                $pp_pic_holder.css({
                    'top': projectedTop,
                    'left': (windowWidth/2) + scroll_pos['scrollLeft'] - (contentwidth/2)
                });
            };
        };

        function _get_scroll(){
            if (self.pageYOffset) {
                return {scrollTop:self.pageYOffset,scrollLeft:self.pageXOffset};
            } else if (document.documentElement && document.documentElement.scrollTop) { // Explorer 6 Strict
                return {scrollTop:document.documentElement.scrollTop,scrollLeft:document.documentElement.scrollLeft};
            } else if (document.body) {// all other Explorers
                return {scrollTop:document.body.scrollTop,scrollLeft:document.body.scrollLeft};
            };
        };

        function _resize_overlay() {
            windowHeight = $(window).height(), windowWidth = $(window).width();

            if(typeof $pp_overlay != "undefined") $pp_overlay.height($(document).height()).width(windowWidth);
        };

        function _insert_gallery(){
            if(isSet && settings.overlay_gallery && _getFileType(pp_images[set_position])=="image") {
                itemWidth = 52+5; // 52 beign the thumb width, 5 being the right margin.
                navWidth = (settings.theme == "facebook" || settings.theme == "pp_default") ? 50 : 30; // Define the arrow width depending on the theme

                itemsPerPage = Math.floor((pp_dimensions['containerWidth'] - 100 - navWidth) / itemWidth);
                itemsPerPage = (itemsPerPage < pp_images.length) ? itemsPerPage : pp_images.length;
                totalPage = Math.ceil(pp_images.length / itemsPerPage) - 1;

                // Hide the nav in the case there's no need for links
                if(totalPage == 0){
                    navWidth = 0; // No nav means no width!
                    $pp_gallery.find('.pp_arrow_next,.pp_arrow_previous').hide();
                }else{
                    $pp_gallery.find('.pp_arrow_next,.pp_arrow_previous').show();
                };

                galleryWidth = itemsPerPage * itemWidth;
                fullGalleryWidth = pp_images.length * itemWidth;

                // Set the proper width to the gallery items
                $pp_gallery
                    .css('margin-left',-((galleryWidth/2) + (navWidth/2)))
                    .find('div:first').width(galleryWidth+5)
                    .find('ul').width(fullGalleryWidth)
                    .find('li.selected').removeClass('selected');

                goToPage = (Math.floor(set_position/itemsPerPage) < totalPage) ? Math.floor(set_position/itemsPerPage) : totalPage;

                $.prettyPhoto.changeGalleryPage(goToPage);

                $pp_gallery_li.filter(':eq('+set_position+')').addClass('selected');
            }else{
                $pp_pic_holder.find('.pp_content').unbind('mouseenter mouseleave');
            }
        }

        function _build_overlay(caller){
            // Inject Social Tool markup into General markup
            if(settings.social_tools)
                facebook_like_link = settings.social_tools.replace('{location_href}', encodeURIComponent(location.href));

            settings.markup = settings.markup.replace('{pp_social}','');

            $('body').append(settings.markup); // Inject the markup

            $pp_pic_holder = $('.pp_pic_holder') , $ppt = $('.ppt'), $pp_overlay = $('div.pp_overlay'); // Set my global selectors

            // Inject the inline gallery!
            if(isSet && settings.overlay_gallery) {
                currentGalleryPage = 0;
                toInject = "";
                for (var i=0; i < pp_images.length; i++) {
                    if(!pp_images[i].match(/\b(jpg|jpeg|png|gif)\b/gi)){
                        classname = 'default';
                        img_src = '';
                    }else{
                        classname = '';
                        img_src = pp_images[i];
                    }
                    toInject += "<li class='"+classname+"'><a href='#'><img src='" + img_src + "' width='50' alt='' /></a></li>";
                };

                toInject = settings.gallery_markup.replace(/{gallery}/g,toInject);

                $pp_pic_holder.find('#pp_full_res').after(toInject);

                $pp_gallery = $('.pp_pic_holder .pp_gallery'), $pp_gallery_li = $pp_gallery.find('li'); // Set the gallery selectors

                $pp_gallery.find('.pp_arrow_next').click(function(){
                    $.prettyPhoto.changeGalleryPage('next');
                    $.prettyPhoto.stopSlideshow();
                    return false;
                });

                $pp_gallery.find('.pp_arrow_previous').click(function(){
                    $.prettyPhoto.changeGalleryPage('previous');
                    $.prettyPhoto.stopSlideshow();
                    return false;
                });

                $pp_pic_holder.find('.pp_content').hover(
                    function(){
                        $pp_pic_holder.find('.pp_gallery:not(.disabled)').fadeIn();
                    },
                    function(){
                        $pp_pic_holder.find('.pp_gallery:not(.disabled)').fadeOut();
                    });

                itemWidth = 52+5; // 52 beign the thumb width, 5 being the right margin.
                $pp_gallery_li.each(function(i){
                    $(this)
                        .find('a')
                        .click(function(){
                            $.prettyPhoto.changePage(i);
                            $.prettyPhoto.stopSlideshow();
                            return false;
                        });
                });
            };


            // Inject the play/pause if it's a slideshow
            if(settings.slideshow){
                $pp_pic_holder.find('.pp_nav').prepend('<a href="#" class="pp_play"><i class="fa fa-play"></i></a>')
                $pp_pic_holder.find('.pp_nav .pp_play').click(function(){
                    $.prettyPhoto.startSlideshow();
                    return false;
                });
            }

            $pp_pic_holder.attr('class','pp_pic_holder ' + settings.theme); // Set the proper theme

            $pp_overlay
                .css({
                    'opacity':0,
                    'height':$(document).height(),
                    'width':$(window).width()
                })
                .bind('click',function(){
                    if(!settings.modal) $.prettyPhoto.close();
                });

            $('a.pp_close').bind('click',function(){ $.prettyPhoto.close(); return false; });


            if(settings.allow_expand) {
                $('a.pp_expand').bind('click',function(e){
                    // Expand the image
                    if($(this).hasClass('pp_expand')){
                        $(this).removeClass('pp_expand').addClass('pp_contract');
                        doresize = false;
                    }else{
                        $(this).removeClass('pp_contract').addClass('pp_expand');
                        doresize = true;
                    };

                    _hideContent(function(){ $.prettyPhoto.open(); });

                    return false;
                });
            }

            $pp_pic_holder.find('.pp_previous, .pp_nav .pp_arrow_previous').bind('click',function(){
                $.prettyPhoto.changePage('previous');
                $.prettyPhoto.stopSlideshow();
                return false;
            });

            $pp_pic_holder.find('.pp_next, .pp_nav .pp_arrow_next').bind('click',function(){
                $.prettyPhoto.changePage('next');
                $.prettyPhoto.stopSlideshow();
                return false;
            });

            _center_overlay(); // Center it
        };

        if(!pp_alreadyInitialized && getHashtag()){
            pp_alreadyInitialized = true;

            // Grab the rel index to trigger the click on the correct element
            hashIndex = getHashtag();
            hashRel = hashIndex;
            hashIndex = hashIndex.substring(hashIndex.indexOf('/')+1,hashIndex.length-1);
            hashRel = hashRel.substring(0,hashRel.indexOf('/'));

            // Little timeout to make sure all the prettyPhoto initialize scripts has been run.
            // Useful in the event the page contain several init scripts.
            setTimeout(function(){ $("a["+pp_settings.hook+"^='"+hashRel+"']:eq("+hashIndex+")").trigger('click'); },50);
        }

        return this.unbind('click.prettyphoto').bind('click.prettyphoto',$.prettyPhoto.initialize); // Return the jQuery object for chaining. The unbind method is used to avoid click conflict when the plugin is called more than once
    };

    function getHashtag(){
        var url = location.href;
        hashtag = (url.indexOf('#prettyPhoto') !== -1) ? decodeURI(url.substring(url.indexOf('#prettyPhoto')+1,url.length)) : false;
        if(hashtag){  hashtag = hashtag.replace(/<|>/g,''); }
        return hashtag;
    };

    function setHashtag(){
        if(typeof theRel == 'undefined') return; // theRel is set on normal calls, it's impossible to deeplink using the API
        location.hash = theRel + '/'+rel_index+'/';
    };

    function clearHashtag(){
        if ( location.href.indexOf('#prettyPhoto') !== -1 ) location.hash = "prettyPhoto";
    }

    function getParam(name,url){
        name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
        var regexS = "[\\?&]"+name+"=([^&#]*)";
        var regex = new RegExp( regexS );
        var results = regex.exec( url );
        return ( results == null ) ? "" : results[1];
    }

})(jQuery);

var pp_alreadyInitialized = false; // Used for the deep linking to make sure not to call the same function several times.libs/better-framework/assets/js/tinymce-addon.js000064400000034241151214002560015764 0ustar00var BetterStudio_TinyMCE_View = {

    settings: {},
    fetchShortcodes: [],
    shortcodeCounter: 0,
    fetchAllQueue: 0,
    repeaterPrefix: 'bf-metabox-option', // Repeater Fields Input Prefix

    init: function (jQuery) {

        var view = this;

        BF_TinyMCE_View.shortcodes &&
        BF_TinyMCE_View.shortcodes.forEach(function (args) {
            view.registerView(args);
        });

        this.$ = jQuery;
    },

    initEditModal: function ($modal) {

        var self = this;

        var $context = self.$('.tinymce-addon-fields', $modal);
        if (!$context.length) {
            return;
        }

        function hideAllTabs() {
            $context.children('.group').hide();
        }

        function showOnCompatible($target) {
            $target.find(':input:first').trigger('force-change');
        }

        // Show first
        hideAllTabs();
        $context.children('.group:first').show();
        self.$(".tabs-wrapper li:first").addClass('active-tab');


        // Handle Tabs
        self.$(".bf-tab-item-a", $context).on('click', function () {
            var $li = self.$(this).closest('li'),
                targetSection = $li.data('go'),
                ID = "bf-tmv-" + targetSection;

            // Set Active Tab
            $li.addClass('active-tab');
            $li.siblings('li').removeClass('active-tab');

            var $target = self.$("#" + ID, $context);
            hideAllTabs();
            $target.fadeIn(500);
            showOnCompatible($target);
        });

    },

    setSettings: function (args) {

        if (!args) {
            return;
        }

        if (args.shortcode) {
            this.settings[args.shortcode] = args.settings;
        }
    },

    getSettings: function (shortcode) {

        return this.settings[shortcode];
    },


    /**
     * Register TinyMCE View
     *
     * @param {Object} args configuration object {
     *
     * }
     */
    registerView: function (args) {

        var self = this;

        args = _.extend({}, {
            extend: {},
        }, args);

        if (args.settings) {
            self.setSettings(args);
        }

        wp.mce.views.register(args.shortcode, _.extend({}, self.viewsBaseClass(args), args.extend));
    },

    doShortcode: function (shortcode, viewObject) {
        var view = this;


        clearTimeout(view.fetchAllQueue);
        view.fetchAllQueue = setTimeout(function () {
            view.fetchAllShortcodes.call(view);
        });

        view.fetchShortcodes.push({
            query: {
                shortcode: shortcode,
                id: view.shortcodeCounter,
            },
            id: view.shortcodeCounter,
            view: viewObject
        });
        view.shortcodeCounter++;
    },

    fetchAllShortcodes: function () {
        var view = this,
            data2send = _.pluck(view.fetchShortcodes, 'query'),
            doShortcodePerStep = parseInt(BF_TinyMCE_View.doshortcode_steps || 5);


        var steps = _.groupBy(data2send, function (d, index) { // chunk data
                return Math.floor(index / doShortcodePerStep);
            }),
            finalStep = Better_Framework._length(steps);

        var r, data, doneRequests = 0;

        for (var idx in steps) {

            data = steps[idx];

            wp.ajax.post('bf_ajax', {
                reqID: 'fetch-mce-view-shortcode',
                nonce: better_framework_loc.nonce,
                shortcodes: data,

                post_id: wp.media.view.settings.post.id
            })
                .done(function (response) {

                    _.each(response, function (output, id) {

                        var shortcode = _.findWhere(view.fetchShortcodes, {id: parseInt(id)});

                        if (shortcode && shortcode.view) {

                            if (output.type === 'no-items') {
                                shortcode.view.setError("[" + shortcode.view.shortcode.tag + "]<br/>" + output.message, 'no-alt');
                            } else {
                                shortcode.view.render(output);
                            }
                        }
                    });
                }).always(function () {
                if (++doneRequests === finalStep) {
                    view.fetchShortcodes = [];
                    view.shortcodeCounter = 0;
                }
            });
        }
    },

    viewsBaseClass: function (args) {

        var self = this;

        if (wp.mce.bsShortcodes) {
            return wp.mce.bsShortcodes;
        }


        var formatInputs = function (inputs) {

            var formatted = {};

            for (var key in inputs) {

                if ('object' === typeof inputs[key]) {

                    formatted[key] = '';

                    for (var k in inputs[key]) {

                        if (!inputs[key][k] || 'undefined' === typeof inputs[key][k].__VALUE__) {
                            continue;
                        }

                        if (inputs[key][k].__VALUE__ != '' && inputs[key][k].__VALUE__ != '0') {

                            formatted[key] += k + ',';
                        }
                    }

                } else {

                    formatted[key] = inputs[key];
                }
            }


            return formatted;
        };

        wp.mce.bsShortcodes = {

            args: {},

            initialize: function () {
                var view = this;

                self.doShortcode(view.shortcode.string(), view);
            },
            shortcode_data: {},

            edit: function (data, update) {

                var view = this;

                var shortcode_data = wp.shortcode.next(view.shortcode.tag, data),
                    values = shortcode_data.shortcode.attrs.named;

                values.innercontent = shortcode_data.shortcode.content;

                var buttons = {
                    custom_event: {
                        label: BS_Shortcode_loc.save,
                        type: 'primary',
                        clicked: function () {

                            var modal = this,
                                inputs = {};

                            var html = self.$(".bs-modal-body", this.$modal).clone();
                            self.$(".mce-field", this.$modal).each(function () {

                                if (this.type === 'radio' && !this.checked) {
                                    return;
                                }

                                /**
                                 * Collect input values
                                 */
                                var arraySequence = this.name.match(/\[(.*?)\]/g);
                                if (arraySequence) {
                                    var pointer,
                                        k = this.name.match(/^(.*?)(?=\[)/)[1];

                                    if (typeof inputs[k] === 'undefined') {
                                        inputs[k] = {};
                                    }

                                    pointer = inputs[k];

                                    for (var i = 0; i < arraySequence.length; i++) {
                                        k = arraySequence[i].substr(0, arraySequence[i].length - 1).substr(1);

                                        if (typeof pointer[k] === 'undefined') {
                                            pointer[k] = {};
                                        }

                                        pointer = pointer[k];
                                    }

                                    if (pointer)
                                        pointer.__VALUE__ = this.value;

                                } else {
                                    inputs[this.name] = this.value;
                                }
                            }).promise().done(function () {

                                var settings = self.getSettings(view.shortcode.tag);

                                var subShortcodes = '';
                                if (settings.sub_shortcodes) {

                                    var key, _shortcodeName;
                                    var contentKey;

                                    for (key in settings.sub_shortcodes) {

                                        if (!inputs[key]) {
                                            continue;
                                        }

                                        _shortcodeName = settings.sub_shortcodes[key];

                                        _.each(inputs[key], function (attrs) {

                                            attrs = _.mapObject(attrs, function (value) {
                                                if (typeof value === 'object' && '__VALUE__' in value) {
                                                    return value.__VALUE__;
                                                }
                                                return value;
                                            });

                                            if (typeof settings.extra.shortcode_content_fields[key] === 'string')
                                                contentKey = settings.extra.shortcode_content_fields[key];
                                            else
                                                contentKey = '';

                                            var content = '';

                                            if (contentKey && typeof attrs[contentKey] != 'undefined') {
                                                content = attrs[contentKey];
                                                delete attrs[contentKey];
                                            }

                                            subShortcodes += "\n\t";
                                            subShortcodes += wp.shortcode.string({
                                                tag: _shortcodeName,
                                                content: content,
                                                attrs: attrs,
                                                type: 'close'
                                            });
                                        });

                                        delete inputs[key];
                                    }
                                }

                                if (subShortcodes) {
                                    subShortcodes += "\n";
                                }

                                var attrs = formatInputs(inputs);

                                if (values.id && 'undefined' === typeof attrs.id) {
                                    attrs.id = values.id;
                                }

                                if ('undefined' !== typeof attrs._content && !subShortcodes) {

                                    subShortcodes = attrs._content;
                                    delete attrs._content;
                                }

                                update(wp.shortcode.string({
                                    tag: view.shortcode.tag,
                                    attrs: attrs,
                                    type: 'open',
                                    content: subShortcodes,
                                }), false);

                                modal.close_modal('tinymce');
                            });
                        }
                    },
                    close_modal: {
                        type: 'secondary',
                        action: 'close',
                        label: better_framework_loc.translation.reset_panel.button_no,
                        focus: true
                    }
                };

                var editorModal = self.$.bs_modal({
                    modalId: 'es-modal',
                    skin: 'loading',
                    content: {
                        header: 'Loading...',
                        title: 'Loading...',
                        body: ''
                    },

                    buttons: buttons,
                    events: {
                        before_append_html: function () {
                            var zIndex = 1.55e5;
                            this.$overlay.css('z-index', zIndex);
                            this.$modal.css('z-index', zIndex + 1);
                        },
                        after_append_html: function () {
                            self.initEditModal(this.$modal);
                        }
                    }
                });

                wp.ajax.post('bf_ajax', {
                    action: 'bf_ajax',
                    reqID: 'fetch-mce-view-fields',
                    nonce: better_framework_loc.nonce,
                    shortcode: view.shortcode.tag,
                    shortcode_content: shortcode_data.shortcode.content,
                    //shortcode_attrs: shortcode_data.shortcode.attrs,
                    shortcode_values: values
                }).done(function (data) {

                    editorModal.change_skin({
                        skin: 'skin-1',
                        animations: {
                            //body: 'bs-animate bs-fadeInLeft'
                        },

                        content: {
                            header: (function (t) {

                                var _settings = self.getSettings(view.shortcode.tag);
                                var name = _settings.name || '';

                                if (data.settings) {
                                    _settings.extra = data.settings;
                                    self.setSettings({
                                        settings: _settings,
                                        shortcode: view.shortcode.tag
                                    });
                                }

                                return t.toString().replace('%shortcode%', name);
                            })(BF_TinyMCE_View.l10n.modal.header),
                            title: '',
                            body: data.output
                        },
                        buttons: buttons
                    })
                });
            }
        };

        return wp.mce.bsShortcodes;
    }
};

jQuery(function () {
    BetterStudio_TinyMCE_View.init(jQuery);
})libs/better-framework/assets/js/gutenberg.fields.js000064400000004472151214002560016463 0ustar00!function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n={};t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=0)}([function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(1);n.n(r)},function(e,t,n){wp.element.BF_Repeater=n(2)},function(e,t){function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!==typeof t&&"function"!==typeof t?e:t}function o(e,t){if("function"!==typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var i=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),a=function(e){function t(e){n(this,t);var o=r(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return o.state={items:[]},o}return o(t,e),i(t,[{key:"shouldComponentUpdate",value:function(e,t){return this.state!==t}},{key:"appendItem",value:function(){var e=this.state.items.concat([1]);this.setState({items:e})}},{key:"render",value:function(){var e=this,t=this.state.items.map(function(t){return wp.element.createElement("div",{className:"bf-repeater-item",key:t},e.props.children)});return wp.element.createElement("div",{class:"bf-controls bf-nonrepeater-controls bf-controls-repeater-option no-desc bf-clearfix"},wp.element.createElement("div",{className:"bf-repeater-items-container bf-clearfix"},t),wp.element.createElement("button",{className:"bf-clone-repeater-item bf-button bf-main-button",onClick:this.appendItem.bind(this)},"Add New Inline Related Post"))}}]),t}(wp.element.Component);e.exports=a}]);libs/better-framework/assets/js/bs-modal.js000064400000063355151214002560014737 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */


(function ($) {
    "use strict";

    var prevModalZIndex = 0,
        activeModalsId  = [];
    var BS_Modal        = function (options) {
        function _return_true() {
            return true;
        }

        this.options = $.extend(true, {
            template: 'default',
            skin: 'skin-1',

            initialZIndex: 0,
            show: true,
            /**
             * {Obejct} Mustache View Object
             * @see {@link https://github.com/janl/mustache.js#usage}
             */
            content: {},
            close_button: true,  //Display Modal Window Close Button?
            button_position: 'right',
            animations: {
                delay: 600,
                open: 'bs-animate bs-fadeInDown',
                close: 'bs-animate bs-fadeOutUp'
            },

            /**
             * List of Buttons to Generate
             * buttons: {
             *   BUTTON_ID : {
             *       type: primary|secondary|normal,
             *       action: close|yes|normal,
             *       clicked: Callback Call After Button Clicked,
             *       label: Button Label,
             *       btn_classes: List of Button Classes as HTML Separated by space,
             *       href: Button Link href Value
             *   }
             * }
             */
            buttons: {},

            events: {
                //Event Fire Before click (on every thing) in Modal Section
                before_click: _return_true,
                //Event Fire After Click (on every thing) in Modal Section
                clicked: _return_true,
                handle_keyup: function (e, obj, _continue) {
                    return _continue;
                }
            },

            styles: {
                modal: '',
                container: ''
            },

            modalId: 'modal-'+Math.floor(Math.random() * 999), // Set Random Modal ID
            modalClass: '',
            destroyHtml: true, // Remove modal html after it closed
            is_vertical_center: true // if set true, make modal window center vertically
        }, options);

        // $modal HTML element object used in some methods
        this.$modal = false;
        // $overlay HTML element object used in some methods
        this.$overlay = false;
        //Timer setTimeout return numbers
        this.timerTimeouts = [];
        //document body jQuery object
        this.$document = false;
        //Modal Unique ID
        this.modalID = false;

        this.visible = false;

        this.init(); //Start Modal!
    };
    BS_Modal.prototype  = {

        /**
         * List of Modal Templates
         *
         * templates = {
         *  templateName: Mustache Template String
         *  ,
         *  ...
         * }
         */
        templates: {
            'default': '\n<div class="bs-modal-default"  {{#inline_style}} style="{{inline_style}}" {{/inline_style}}>\n    {{#close_button}}\n    <a href="#" class="bs-close-modal">\n        <i class="fa fa-times" aria-hidden="true"></i>\n    </a>\n    {{/close_button}}\n    <div class="bs-modal-header-wrapper bs-modal-clearfix">\n        <h2 class="bs-modal-header">\n            {{#icon}}\n            <i class="fa {{icon}}"></i>\n            {{/icon}}\n\n            {{header}}\n        </h2>\n    </div>\n\n    <div class="bs-modal-body">\n        {{{bs_body}}}\n    </div>\n\n    {{#bs_buttons}}\n    <div class="bs-modal-bottom bs-modal-buttons-{{btn_position}} bs-modal-clearfix">\n        {{{bs_buttons}}}\n    </div>\n    {{/bs_buttons}}\n</div>',
            'single_image': '\n<div class="bs-modal-default" {{#inline_style}} style="{{inline_style}}" {{/inline_style}}>\n    {{#close_button}}\n    <a href="#" class="bs-close-modal">\n        <i class="fa fa-times" aria-hidden="true"></i>\n    </a>\n    {{/close_button}}\n    <div class="bs-modal-header-wrapper bs-modal-clearfix">\n        <h2 class="bs-modal-header">\n            {{#icon}}\n            <i class="fa {{icon}}"></i>\n            {{/icon}}\n\n            {{header}}\n        </h2>\n    </div>\n\n    <div class="bs-modal-body bf-clearfix">\n        \n        <div class="bs-modal-image bf-clearfix" {{#image_align}} style="float:{{image_align}}"{{/image_align}}>\n\n            <img src="{{image_src}}" {{#image_style}} style="{{image_style}}"{{/image_style}}/>\n            \n            {{#image_caption}}\n            <div class="bs-modal-image-caption">\n                {{image_caption}}\n            </div>\n            {{/image_caption}}\n        </div>\n        {{{bs_body}}}\n    </div>\n\n    {{#bs_buttons}}\n    <div class="bs-modal-bottom bs-modal-buttons-left bs-modal-clearfix">\n        {{{bs_buttons}}}\n        \n        {{#checkbox}}\n        <div class="bs-modal-checkbox">\n            <input type="checkbox" name="include_content" class="toggle-content" value="1" checked="checked"> <label class="checkbox-label">{{checkbox_label}}</label>\n        </div>\n        {{/checkbox}}\n    </div>\n    {{/bs_buttons}}\n</div>'
        },

        /**
         * List of Modal Skins
         *
         * Skins = {
         *  skinName: Mustache Template String
         *  ,
         *  ...
         * }
         */
        skins: {
            'skin-1': '<div class="bs-modal-description">\n   {{#title}} <h3 class="bs-modal-title">{{title}}</h3>\n   {{/title}} \n    {{{body}}}\n</div>',
            'loading': ' <div class="bs-modal-loading bs-modal-loading-1">\n    <img src="data:image/false;base64,R0lGODlhIAAIAPEAALy8vHh4eP///wAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hhPcHRpbWl6ZWQgd2l0aCBlemdpZi5jb20AIfkEBQsAAQAsAAAAACAACAAAAiGEb6GBuNyiWxK8Wq/UuHFPdaCSheLxTeSJmiPEWq4KNwUAIfkEBQsAAAAsAAAAAAgACAAAAgaMj6nL7V0AIfkEBQsAAgAsAAAAABQACAAAAhuEb6IS7Y3QYs/FM6u9IOvAdcsHcp4WnlU6fgUAIfkEBQsAAgAsDAAAABQACAAAAhuEb6IS7Y3QYs/FM6u9IOvAdcsHcp4WnlU6fgUAOw==" />\n\n     <div class="bs-modal-loading-heading">\n         <h4>{{loading_heading}}</h4>\n     </div>\n </div>\n',
            'loading-2': ' <div class="bs-modal-loading">\n     <div class="la-line-scale-pulse-out-rapid la-2x">\n         <div></div>\n         <div></div>\n         <div></div>\n         <div></div>\n         <div></div>\n     </div>\n     \n     <div class="bs-modal-loading-heading">\n         <h4>{{loading_heading}}</h4>\n     </div>\n</div>\n',
            success: ' <div class="bs-modal-success">\n     \n     <i class="fa fa-thumbs-o-up" aria-hidden="true"></i>\n     \n     <div class="bs-modal-bs-modal-success-heading">\n         <h4>{{success_heading}}</h4>\n     </div>\n</div>\n'
        },

        /**
         * HTML Structure of Button
         * @see {@link this.generate_buttons}
         */
        button_struct: '<a {{#href}}href="{{href}}"{{/href}} {{#btn_classes}}class="{{btn_classes}}"{{/btn_classes}} id="{{id}}">{{{label}}}</a>',

        /**
         * Display Debug Console Messages
         * @param {*} message
         */
        debug: function (message) {
            console.error(message);
        },


        get_html: function (templateName, skinName, replacement) {

            if (typeof this.templates[ templateName ] === 'undefined') {
                this.debug('invalid template name');

                return false;
            }

            if (typeof this.skins[ skinName ] === 'undefined') {
                this.debug('invalid skin');

                return false;
            }
            var template = Mustache.parse(this.templates[ templateName ]);
            Mustache.parse(this.skins[ skinName ]);

            var body_content            = Mustache.render(this.skins[ skinName ], replacement),
                template_replace_object = {
                    bs_body: body_content,
                    bs_buttons: this.generate_buttons(),
                    close_button: this.options.close_button,
                    inline_style: this.options.styles.modal,
                    btn_position: this.options.button_position
                };

            this.handle_event('prepare_html', this,templateName, skinName, replacement);

            return Mustache.render(this.templates[ templateName ], $.extend(replacement, template_replace_object));
        },

        before_append_html: function (context) {
            this.handle_event('before_append_html', this, context);
        },
        /**
         *  This function will fire after modal HTML changed
         */

        after_append_html: function (context) {
            if (this.options.is_vertical_center) {
                this.make_vertical_center();
            }

            this.$modal.focus();

            this.handle_event('after_append_html', this, context);
        },

        /**
         * Fire after modal closed
         */
        after_close_modal: function () {
            // unbind resize event
            $(window).off('resize.bs-modal');

            activeModalsId.pop();
        },

        has_button: function () {

            return typeof this.options.buttons === 'object';
        },

        /**
         * Generate Modal Body HTML Codes. Prepare Skin HTML Output and Append to {{{bs_body}}} Section of Template.
         *
         * @returns {boolean} true on Success, false on Failure
         */
        append_html: function () {
            this.before_append_html('modal');

            var htmlOutput = this.get_html(this.options.template, this.options.skin, this.options.content);

            if (typeof htmlOutput !== 'string')
                return htmlOutput;

            this.$modal.html(htmlOutput);

            this.after_append_html('modal');

            return true;
        },

        /**
         * Generate Buttons HTML Code
         *
         * @returns {String} Button HTML Codes on Success, Empty String on Failure
         */
        generate_buttons: function () {
            if (!this.has_button())
                return '';

            Mustache.parse(this.button_struct);

            var html_output = '';

            for (var btn_id in this.options.buttons) {

                html_output += "\n";
                html_output += Mustache.render(this.button_struct, this.get_button_replacement_object(btn_id));
            }

            return html_output;
        },

        /**
         * Generate Mustache View Object used to Render Button HTML
         * @see {@link this.button_struct}
         *
         * @param button_id {String} Property Name of Option, buttons Object
         * @see {@link this.options.buttons}
         * @see {@link https://github.com/janl/mustache.js#usage}
         *
         * @returns {Object} Mustache View Object on Success, Empty Object on Failure
         */
        get_button_replacement_object: function (button_id) {
            if (typeof this.options.buttons[ button_id ] !== 'object') {
                this.debug('invalid button id');

                return {};
            }

            var obj = $.extend({focus: false}, this.options.buttons[ button_id ]);

            delete obj.clicked;

            obj.id = button_id;

            if (typeof obj.btn_classes !== 'string') {
                obj.btn_classes = '';
            }
            if ($.inArray(obj.type, [ 'primary', 'secondary' ]) !== -1) {
                obj.btn_classes += ' bs-modal-btn-' + obj.type;
            }

            if (obj.focus) {
                obj.btn_classes += ' bs-modal-btn-focus';
            }

            return obj;
        },

        /**
         * Close & Remove active Modal
         */
        close_modal: function (who_called) {

            this.visible   = false;
            var self       = this,
                who_called = who_called || 'callback';

            self.handle_event('modal_close', this, who_called);

            for (var i = 0; i < this.timerTimeouts.length; i++) {
                clearTimeout(this.timerTimeouts[ i ]);
            }

            self.$modal
                .removeClass(this.options.animations.open)
                .addClass(this.options.animations.close)
                .delay(this.options.animations.delay)
                .queue(function (n) {

                    self.$modal
                        .hide()
                        .removeClass(self.options.animations.close);

                    if (self.options.destroyHtml) {
                        self.$modal.remove();
                    } else {
                        self.$modal.clearQueue();
                    }
                    n();
                });

            self.$overlay.fadeOut(this.options.animations.delay, function () {
                if (self.options.destroyHtml) {
                    self.find().remove();
                }
                self.$document.removeClass('modal-open').removeClass('modal-open-vc');

                // remove keyup event when modal closed
                self.keyup_unbind();

                // handle after click global event
                self.handle_event('modal_closed', this, who_called);
            });

            self.after_close_modal();
        },


        /**
         * unbind keyup event
         */
        keyup_unbind: function () {

            if (this.options.destroyHtml) {
                this.$document.off('keyup.bs-modal-' + this.getModalID());
            }
        },
        /**
         * handle modal events. (EX: before_click event)
         * Fire Registered callback for event
         *
         * @param event {String} event name
         * @param el    {object} Active HTML Element Object
         * @returns     {*}      Return Fired Callback Results
         */
        handle_event: function (event, el) {
            var args = Array.prototype.slice.call(arguments, 2);

            if (typeof this.options.events[ event ] === 'function')
                return this.options.events[ event ].apply(this, [ el, this.options ].concat(args));
        },

        /**
         * Handle Timer Callback - Fire Registered Callback After Specified Delay
         *
         * @param timer_object. Timer Object. @see {@link this.options.timer}
         *   timer_object = {
         *      callback: function to fire.
         *      delay: delay to fire callback
         *  }
         *
         */
        handle_timer: function (timer_object) {
            var self = this;

            this.timerTimeouts.push(
                setTimeout(function () {
                    timer_object.callback.call(self, self.option);
                }, timer_object.delay)
            );

        },

        /**
         * Refresh Modal Content inside modal events
         * @param options {
             *   template:  {String} New Modal Template,
             *   skin:      {String} New Modal Skin,
             *   content:   {Obejct} Mustache View Object,
             *   animations:{Object} Animation Settings
             * }
         * @returns {*}
         */
        change_skin: function (options, deep) {
            deep = typeof deep === 'boolean' ? deep : true;

            var settings = $.extend(deep, {
                template: this.options.template,
                skin: this.options.skin,
                content: this.options.content,
                animations: {
                    open: false,
                    body: false,
                    delay: 20
                },
                buttons: {},
                styles: {},
            }, options);

            /**
             * set new button value
             * @see {@link this.generate_buttons}
             *
             * @type {Object}
             */
            this.options.buttons = settings.buttons;


            /***
             *
             */
            if (settings.styles.container) {
                var replacement = {inline_style: settings.styles.container},
                    wrapper     = Mustache.render('<div class="bs-modal" {{#inline_style}} style="{{inline_style}}" {{/inline_style}}></div>\n', replacement);

                this.$modal[ 0 ].outerHTML = wrapper;
                this.$modal                = this.find('.bs-modal')
                                                 .css('z-index', prevModalZIndex + 1)
                                                 .show();
                this.afterWrapperHtmlGenerated();
            }

            var htmlOutput = this.get_html(settings.template, settings.skin, settings.content);

            if (typeof htmlOutput !== 'string')
                return htmlOutput;

            this.$modal
                .html(htmlOutput)
                .removeClass(this.options.animations.open)
                .delay(20)
                .queue(function (n) {
                    if (settings.animations.open) {
                        $(this)
                            .addClass(settings.animations.open)
                    }
                    n();
                })
                .removeClass(function (idx, css) {

                    return (css.match(/(^|\s)skin-\S+/g) || []).join(' ');
                })
                .addClass('skin-' + settings.skin)
                .find('.bs-modal-body')
                .addClass(settings.animations.body);

            if (typeof settings.timer === 'object') {
                //start timer after modal open effect finished
                this.handle_timer(settings.timer);
            }

            this.after_append_html('change_skin');
            this.handle_event('modal_loaded', this);
        },

        make_vertical_center: function () {
            var self = this;
            $(window).on('resize.bs-modal', function () {

                if (!self.isModalLast()) {
                    return false;
                }

                var mh = self.$modal.innerHeight(),
                    wh = window.innerHeight;

                if (wh > mh) {
                    var top = Math.ceil((wh - mh) / 2);
                } else {
                    var top = 35; // default top margin
                }

                self.$modal.css('top', top);
            }).trigger('resize.bs-modal');
        },

        getModalID: function () {
            return this.modalID;
        },
        setModalID: function (ID) {
            this.modalID = ID;
        },

        setActiveModalId: function (ID) {
            activeModalsId.push(ID);
        },

        getActiveModalId: function () {
            if (activeModalsId.length) {
                return activeModalsId[ activeModalsId.length - 1 ];
            }

            return 0;
        },

        /**
         * Check is current modal last opened
         * @returns {boolean}
         */
        isModalLast: function () {
            return this.getActiveModalId() === this.getModalID();
        },

        find: function (selector) {
            var $context = this.$document.find('#' + this.getModalID());

            if (selector) {
                return $(selector, $context);
            }

            return $context;
        },

        _fixModalZindex: function () {

        },

        show: function () {
            var self = this;

            if(self.$document.find('.vc_ui-panel.vc_active .vc_ui-panel-window-inner').length) {
                self.$document.addClass('modal-alongside-vc-panel');
            }

            this.$overlay
                .fadeIn(this.options.animations.open, function () {
                    self.$document.addClass('modal-open');
                });

            this.$modal
                .addClass(self.options.animations.open)
                .addClass('skin-' + self.options.skin)
                .show().delay(self.options.animations.delay).queue(function (n) {

                if (typeof self.options.timer === 'object') {
                    //start timer after modal open effect finished
                    self.handle_timer(self.options.timer);
                }

                n();
            });

            this.setActiveModalId(this.getModalID());
            this.visible = true;
            this.handle_event('modal_show', this);
        },
        /**
         * Initial Modal - Generate Modal Html Output and Handle Events
         */
        init: function () {

            this.$document = $(document.body);
            var self       = this;

            this.setModalID(this.options.modalId);
            this.setActiveModalId(this.getModalID());

            var generateModalHtml = this.find().length === 0;

            if (generateModalHtml) { //  append modal html elements if needed
                var replacement = {
                    inline_style: this.options.styles.container,
                    modal_id: this.getModalID(),
                    modal_class: this.options.modalClass
                };
                this.$document
                    .append(Mustache.render('<div id="{{modal_id}}"{{#modal_class}} class="{{modal_class}}"{{/modal_class}}>\n    <div class="bs-modal-overlay"></div>\n        <div class="bs-modal" {{#inline_style}} style="{{inline_style}}" {{/inline_style}}>\n    </div>\n</div>', replacement));
            }

            // $modal and $overlay used in some methods
            this.$modal   = this.find('.bs-modal');
            this.$overlay = this.find('.bs-modal-overlay');

            /**
             * Fix Modal Overlay Z-index
             */
            if (prevModalZIndex) {

                prevModalZIndex = Math.max(prevModalZIndex, this.options.initialZIndex);
                prevModalZIndex++;

                this.$overlay.css('z-index', prevModalZIndex);
                this.$modal.css('z-index', prevModalZIndex + 1);

            } else if(this.options.initialZIndex) {

                this.$overlay.css('z-index', this.options.initialZIndex);
                this.$modal.css('z-index', this.options.initialZIndex+1);

                prevModalZIndex = this.options.initialZIndex;

            }else{
                prevModalZIndex = parseInt(this.$modal.css('z-index'));
            }


            if (generateModalHtml) {
                self.afterWrapperHtmlGenerated();
            }

            //close modal when user pressed esc key, if close button was enabled
            //and prevent opening another modal when user presses enter key
            if (this.options.close_button) {

                /**
                 * 27   => escape
                 * 13   => enter
                 */
                this.$document.on('keyup.bs-modal-' + this.getModalID(), function (e) {

                    if (!self.handle_event('handle_keyup', e, self.isModalLast())) {

                        return false;
                    }

                    if(e.target.tagName === "TEXTAREA") {
                        return false;
                    }

                    if (self.options.close_button && e.which === 27) {

                        self.close_modal('esc');
                    } else if (e.which === 13) {

                        //call primary button event
                        if (self.has_button()) {
                            var $btn_context  = self.$modal
                                                    .find('.bs-modal-bottom');
                            var $btn_selector = $(".bs-modal-btn-focus", $btn_context);
                            if (!$btn_selector.length) {
                                $btn_selector = $(".bs-modal-btn-primary", $btn_context);
                            }

                            $btn_selector.trigger('click');
                        }

                        self.keyup_unbind();
                    }
                });
            }

            if (this.options.show) {

                self.show();
            }


            if (generateModalHtml) {
                self.append_html();
            }

            this.handle_event('modal_loaded', this);
        },

        afterWrapperHtmlGenerated: function () {
            var self = this;

            //handle click events
            this.$modal.on('click', 'a', function (e) {

                //handle before click global event
                if (self.handle_event('before_click', this)) {

                    var $this = $(this), id = $this.attr('id');

                    //link with bs-close-modal is close button
                    if ($this.hasClass('bs-close-modal')) {

                        e.preventDefault();
                        self.close_modal('btn');

                    } else if (id && typeof self.options.buttons[ id ] === 'object') {
                        var btn = self.options.buttons[ id ];

                        // Handle buttons actions
                        switch (btn.action) {
                            case 'close':

                                self.close_modal('link');
                                break;
                        }

                        if (typeof btn.clicked === 'function') {

                            btn.clicked.call(self);
                        }

                    }

                    // handle after click global event
                    self.handle_event('clicked', this)
                }
            });
        }

    };


    /**
     * Register bs_modal jQuery function
     *
     * @param options options object.
     * @returns {jQuery}
     */
    $.bs_modal = function (options) {

        return new BS_Modal(options);
    };

    $.bs_modal_template = function (name, html) {

        if (html) {

            BS_Modal.prototype.templates[name] = html;
        } else {

            return BS_Modal.prototype.templates[name];
        }
    };

})(jQuery);
libs/better-framework/assets/js/gutenberg.js000064400000026467151214002560015226 0ustar00(function () {

    var catExistsCache= {};

    function bfGutenbergBlock() {

        this.element = window.wp && window.wp.element;
        this.blocks = window.wp && window.wp.blocks;
        this.prefix = 'better-studio/';
        this.props = {};
        this.attributes = {};
        //
        this.blockFields = {};
        this.shortcode = {};
        this.liveTemplate = {};
        this.liveTemplateAttributes = {};
    }

    bfGutenbergBlock.prototype.registerBlockType = function (shortcode, blockFields, liveTemplate, liveTemplateAttributes) {

        this.shortcode = shortcode;
        this.blockFields = blockFields;
        this.liveTemplate = liveTemplate;
        this.liveTemplateAttributes = liveTemplateAttributes;

        var blockID = this.shortcode.block_id || this.shortcode.id.replace(/_/g, '-');
        var category = this.shortcode.category || 'betterstudio';

        if (this.bfGutenbergCatExists(category)) {

            this.blocks.registerBlockType(this.prefix + blockID, {
                title: this.shortcode.name || this.shortcode.id,
                icon: this.blockIcon(),
                category: category,
                edit: this.editBlock.bind(this),
                save: this.saveBlock.bind(this),

                attributes: this.blockAttributes(this.shortcode.id)
            });
        }

    };

    bfGutenbergBlock.prototype.saveBlock = function (props) {

        return null;
    };

    bfGutenbergBlock.prototype.bfGutenbergCatExists = function (category) {

        if (typeof catExistsCache[category] === "undefined") {

            catExistsCache[category] = false;

            var cats = this.blocks.getCategories() || [];

            for (var i = 0; i < cats.length; i++) {

                if (cats[i].slug === category) {

                    catExistsCache[category] = true;
                    break;
                }
            }
        }

        return catExistsCache[category];
    };

    bfGutenbergBlock.prototype.blockAttributes = function (blockId) {

        if (!this.blockFields) {
            return [];
        }

        var attributes = {},
            findDeep = function (field) {

                if (field.id && field.attribute) {
                    attributes[field.id] = field.attribute;
                }

                field.children && field.children.forEach(function (field2) {

                    findDeep(field2);
                });
            };

        this.blockFields.forEach(findDeep);

        if (this.liveTemplateAttributes) {

            attributes = Object.assign(attributes, this.liveTemplateAttributes);
        }

        return attributes;
    };

    bfGutenbergBlock.prototype.editBlock = function (props) {

        var id = props.name.replace(this.prefix, '');

        if (!id || id === props.name) {
            return [];
        }

        if (props.isSelected || !this.props.name) {
            this.props = props;
        }

        var edit = [
            this.buildBlockFields()
        ];

        if (!this.liveTemplate) {

            var isBlockDisabled = !this.shortcode.click_able,
                previewElement = this.element.createElement(
                    this.getComponent('ServerSideRender'),
                    {
                        block: props.name,
                        attributes: props.attributes,
                        key: 'D2'
                    }
                );

            if (isBlockDisabled) {

                previewElement = this.element.createElement(
                    this.getComponent('Disabled'),
                    {
                        key: 'D1'
                    },
                    previewElement
                )
            }

            edit.push(previewElement);
        }

        return edit;
    };

    bfGutenbergBlock.prototype.buildElement = function (fields, parentField) {

        var children = [], self = this;

        fields.forEach(function (field) {

            if (field.children) {

                children.push(self.buildElement(field.children, field));

            } else if (Array.isArray(field)) {

                children.push(self.buildElement(field, parentField));

            } else {

                children.push(self.createElement(field));
            }
        });

        return self.createElement(parentField, children);
    };

    bfGutenbergBlock.prototype.createElement = function (field, childElements) {

        var inner = [];

        if (childElements && childElements.length) {
            inner = childElements;
        } else if (field.args && field.args.innerText) {
            inner = field.args.innerText;
        }

        var params = [this.getComponent(field.component), this.componentArgs(field)].concat(inner);

        return this.element.createElement.apply(this.element, params);
    };

    bfGutenbergBlock.prototype.componentArgs = function (field) {

        var args = field.args || {};

        if (field.component === 'Fragment' || field.component.match(/tag_(.+)/)) {
            return args;
        }

        var self = this;

        var prepareClassName = function (currentClasses, appendClass) {

            currentClasses = currentClasses || '';
            currentClasses += ' ';

            var attr = BF_Gutenberg.extraAttributes[field.id];

            if (attr && attr.enum) {

                attr.enum.forEach(function (className) {

                    if (className) {

                        currentClasses = currentClasses.replace(
                            new RegExp('\\b' + className + '\\s+', 'g'),
                            ''
                        );
                    }
                });
            } else if (appendClass === 1) {

                appendClass = field.id;

            } else if (appendClass === 0) {

                currentClasses = currentClasses.replace(
                    new RegExp('\\b' + field.id + '\\s+', 'g'),
                    ''
                );

                appendClass = '';
            }

            currentClasses = currentClasses.trim() + ' ' + appendClass;

            if (field.fixed_class && !currentClasses.match(new RegExp('\\b' + field.fixed_class + '\\s+', 'g'))) {

                currentClasses += ' ' + field.fixed_class;
            }

            return currentClasses.trim();
        };

        if (!args.onChange)
            args.onChange = function (value) {

                var fieldId = field.action === 'add_class' ? 'className' : field.id;

                var attributes = {};
                attributes[fieldId] = field.action === 'add_class' ? prepareClassName(self.props.attributes[fieldId], value) : value;

                self.props.setAttributes(attributes);
            };

        var value = this.props.attributes[field.id];

        args.value = typeof value === 'undefined' ? field.std : value;

        return args;
    };

    bfGutenbergBlock.prototype.buildBlockFields = function () {

        var elements = [
            {
                id: 'inspector',
                component: 'InspectorControls',
                args: {key: 'inspector'},
                children: [
                    {
                        id: 'bf_edit_panel',
                        component: 'BF_Edit_Panel',
                        args: {
                            type: 'edit-panel',
                        },
                        key: 'bf_edit_panel',
                        children: this.blockFields
                    }
                ]
            }
        ];

        if (this.liveTemplate) {
            elements.push(this.liveTemplate);
        }

        return this.buildElement(elements, {
            id: 'block_fragment',
            component: 'Fragment',
            args: {key: 'block_fragment'},
        });
    };

    bfGutenbergBlock.prototype.getComponent = function (component) {

        var match = component.match(/tag_(.+)/);

        if (match) {
            return match[1];
        }

        if (wp.editor[component]) {

            return wp.editor[component];
        }

        if (wp.components[component]) {
            return wp.components[component];
        }

        if (wp.element[component]) {
            return wp.element[component];
        }
    };

    bfGutenbergBlock.prototype.blockIcon = function () {

        if (this.shortcode.icon_url) {

            return this.element.createElement(
                'img', {src: this.shortcode.icon_url}
            )
        }

        return this.shortcode.icon || '';
    };


    var gutenbergCompatibility = {

        init: function () {

            this.registerBlocks();
            this.registerSharedFields();
        },

        registerBlocks: function () {

            if (!BF_Gutenberg || !BF_Gutenberg.blocks) {
                return;
            }

            var generator;

            for (var id in BF_Gutenberg.blocks) {

                generator = new bfGutenbergBlock();
                generator.registerBlockType(
                    BF_Gutenberg.blocks[id],
                    BF_Gutenberg.blockFields[id],
                    BF_Gutenberg.liveEdit[id] && BF_Gutenberg.liveEdit[id]['template'],
                    BF_Gutenberg.liveEdit[id] && BF_Gutenberg.liveEdit[id]['attributes']
                );
            }
        },

        registerSharedFields: function () {

            if (!wp.hooks || !wp.hooks.addFilter) {
                return;
            }

            if (!wp.compose || !wp.compose.createHigherOrderComponent) {
                return;
            }

            if (!BF_Gutenberg.stickyFields) {
                return;
            }
            var generator = new bfGutenbergBlock();

            wp.hooks.addFilter('editor.BlockEdit', 'betterstudio/shared_settings', wp.compose.createHigherOrderComponent(function (BlockEdit) {

                return function (props) {

                    generator.props = props;
                    generator.attributes = props.attributes;

                    var validFields = BF_Gutenberg.stickyFields.filter(function (field) {

                        if (field.exclude_blocks && field.exclude_blocks.indexOf(props.name) > -1) {
                            return false;
                        }


                        if (field.include_blocks) {

                            return field.include_blocks.indexOf(props.name) > -1;
                        }

                        return true;
                    });

                    if (!validFields) {

                        return generator.element.createElement(
                            BlockEdit,
                            props
                        );
                    }

                    var hookedElements = generator.buildElement(validFields, {
                            id: 'inspector',
                            component: 'InspectorControls',
                            args: {key: 'inspector'}
                        }
                    );

                    return generator.element.createElement(
                        generator.getComponent('Fragment'),
                        {
                            key: 'E1'
                        },
                        hookedElements,

                        generator.element.createElement(
                            BlockEdit,
                            props
                        )
                    );
                };
            }));
        }
    };


    gutenbergCompatibility.init();
})();libs/better-framework/assets/js/mustache.min.js000064400000022450151214002560015623 0ustar00(function defineMustache(global,factory){if(typeof exports==="object"&&exports&&typeof exports.nodeName!=="string"){factory(exports)}else if(typeof define==="function"&&define.amd){define(["exports"],factory)}else{global.Mustache={};factory(global.Mustache)}})(this,function mustacheFactory(mustache){var objectToString=Object.prototype.toString;var isArray=Array.isArray||function isArrayPolyfill(object){return objectToString.call(object)==="[object Array]"};function isFunction(object){return typeof object==="function"}function typeStr(obj){return isArray(obj)?"array":typeof obj}function escapeRegExp(string){return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}function hasProperty(obj,propName){return obj!=null&&typeof obj==="object"&&propName in obj}var regExpTest=RegExp.prototype.test;function testRegExp(re,string){return regExpTest.call(re,string)}var nonSpaceRe=/\S/;function isWhitespace(string){return!testRegExp(nonSpaceRe,string)}var entityMap={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};function escapeHtml(string){return String(string).replace(/[&<>"'`=\/]/g,function fromEntityMap(s){return entityMap[s]})}var whiteRe=/\s*/;var spaceRe=/\s+/;var equalsRe=/\s*=/;var curlyRe=/\s*\}/;var tagRe=/#|\^|\/|>|\{|&|=|!/;function parseTemplate(template,tags){if(!template)return[];var sections=[];var tokens=[];var spaces=[];var hasTag=false;var nonSpace=false;function stripSpace(){if(hasTag&&!nonSpace){while(spaces.length)delete tokens[spaces.pop()]}else{spaces=[]}hasTag=false;nonSpace=false}var openingTagRe,closingTagRe,closingCurlyRe;function compileTags(tagsToCompile){if(typeof tagsToCompile==="string")tagsToCompile=tagsToCompile.split(spaceRe,2);if(!isArray(tagsToCompile)||tagsToCompile.length!==2)throw new Error("Invalid tags: "+tagsToCompile);openingTagRe=new RegExp(escapeRegExp(tagsToCompile[0])+"\\s*");closingTagRe=new RegExp("\\s*"+escapeRegExp(tagsToCompile[1]));closingCurlyRe=new RegExp("\\s*"+escapeRegExp("}"+tagsToCompile[1]))}compileTags(tags||mustache.tags);var scanner=new Scanner(template);var start,type,value,chr,token,openSection;while(!scanner.eos()){start=scanner.pos;value=scanner.scanUntil(openingTagRe);if(value){for(var i=0,valueLength=value.length;i<valueLength;++i){chr=value.charAt(i);if(isWhitespace(chr)){spaces.push(tokens.length)}else{nonSpace=true}tokens.push(["text",chr,start,start+1]);start+=1;if(chr==="\n")stripSpace()}}if(!scanner.scan(openingTagRe))break;hasTag=true;type=scanner.scan(tagRe)||"name";scanner.scan(whiteRe);if(type==="="){value=scanner.scanUntil(equalsRe);scanner.scan(equalsRe);scanner.scanUntil(closingTagRe)}else if(type==="{"){value=scanner.scanUntil(closingCurlyRe);scanner.scan(curlyRe);scanner.scanUntil(closingTagRe);type="&"}else{value=scanner.scanUntil(closingTagRe)}if(!scanner.scan(closingTagRe))throw new Error("Unclosed tag at "+scanner.pos);token=[type,value,start,scanner.pos];tokens.push(token);if(type==="#"||type==="^"){sections.push(token)}else if(type==="/"){openSection=sections.pop();if(!openSection)throw new Error('Unopened section "'+value+'" at '+start);if(openSection[1]!==value)throw new Error('Unclosed section "'+openSection[1]+'" at '+start)}else if(type==="name"||type==="{"||type==="&"){nonSpace=true}else if(type==="="){compileTags(value)}}openSection=sections.pop();if(openSection)throw new Error('Unclosed section "'+openSection[1]+'" at '+scanner.pos);return nestTokens(squashTokens(tokens))}function squashTokens(tokens){var squashedTokens=[];var token,lastToken;for(var i=0,numTokens=tokens.length;i<numTokens;++i){token=tokens[i];if(token){if(token[0]==="text"&&lastToken&&lastToken[0]==="text"){lastToken[1]+=token[1];lastToken[3]=token[3]}else{squashedTokens.push(token);lastToken=token}}}return squashedTokens}function nestTokens(tokens){var nestedTokens=[];var collector=nestedTokens;var sections=[];var token,section;for(var i=0,numTokens=tokens.length;i<numTokens;++i){token=tokens[i];switch(token[0]){case"#":case"^":collector.push(token);sections.push(token);collector=token[4]=[];break;case"/":section=sections.pop();section[5]=token[2];collector=sections.length>0?sections[sections.length-1][4]:nestedTokens;break;default:collector.push(token)}}return nestedTokens}function Scanner(string){this.string=string;this.tail=string;this.pos=0}Scanner.prototype.eos=function eos(){return this.tail===""};Scanner.prototype.scan=function scan(re){var match=this.tail.match(re);if(!match||match.index!==0)return"";var string=match[0];this.tail=this.tail.substring(string.length);this.pos+=string.length;return string};Scanner.prototype.scanUntil=function scanUntil(re){var index=this.tail.search(re),match;switch(index){case-1:match=this.tail;this.tail="";break;case 0:match="";break;default:match=this.tail.substring(0,index);this.tail=this.tail.substring(index)}this.pos+=match.length;return match};function Context(view,parentContext){this.view=view;this.cache={".":this.view};this.parent=parentContext}Context.prototype.push=function push(view){return new Context(view,this)};Context.prototype.lookup=function lookup(name){var cache=this.cache;var value;if(cache.hasOwnProperty(name)){value=cache[name]}else{var context=this,names,index,lookupHit=false;while(context){if(name.indexOf(".")>0){value=context.view;names=name.split(".");index=0;while(value!=null&&index<names.length){if(index===names.length-1)lookupHit=hasProperty(value,names[index]);value=value[names[index++]]}}else{value=context.view[name];lookupHit=hasProperty(context.view,name)}if(lookupHit)break;context=context.parent}cache[name]=value}if(isFunction(value))value=value.call(this.view);return value};function Writer(){this.cache={}}Writer.prototype.clearCache=function clearCache(){this.cache={}};Writer.prototype.parse=function parse(template,tags){var cache=this.cache;var tokens=cache[template];if(tokens==null)tokens=cache[template]=parseTemplate(template,tags);return tokens};Writer.prototype.render=function render(template,view,partials){var tokens=this.parse(template);var context=view instanceof Context?view:new Context(view);return this.renderTokens(tokens,context,partials,template)};Writer.prototype.renderTokens=function renderTokens(tokens,context,partials,originalTemplate){var buffer="";var token,symbol,value;for(var i=0,numTokens=tokens.length;i<numTokens;++i){value=undefined;token=tokens[i];symbol=token[0];if(symbol==="#")value=this.renderSection(token,context,partials,originalTemplate);else if(symbol==="^")value=this.renderInverted(token,context,partials,originalTemplate);else if(symbol===">")value=this.renderPartial(token,context,partials,originalTemplate);else if(symbol==="&")value=this.unescapedValue(token,context);else if(symbol==="name")value=this.escapedValue(token,context);else if(symbol==="text")value=this.rawValue(token);if(value!==undefined)buffer+=value}return buffer};Writer.prototype.renderSection=function renderSection(token,context,partials,originalTemplate){var self=this;var buffer="";var value=context.lookup(token[1]);function subRender(template){return self.render(template,context,partials)}if(!value)return;if(isArray(value)){for(var j=0,valueLength=value.length;j<valueLength;++j){buffer+=this.renderTokens(token[4],context.push(value[j]),partials,originalTemplate)}}else if(typeof value==="object"||typeof value==="string"||typeof value==="number"){buffer+=this.renderTokens(token[4],context.push(value),partials,originalTemplate)}else if(isFunction(value)){if(typeof originalTemplate!=="string")throw new Error("Cannot use higher-order sections without the original template");value=value.call(context.view,originalTemplate.slice(token[3],token[5]),subRender);if(value!=null)buffer+=value}else{buffer+=this.renderTokens(token[4],context,partials,originalTemplate)}return buffer};Writer.prototype.renderInverted=function renderInverted(token,context,partials,originalTemplate){var value=context.lookup(token[1]);if(!value||isArray(value)&&value.length===0)return this.renderTokens(token[4],context,partials,originalTemplate)};Writer.prototype.renderPartial=function renderPartial(token,context,partials){if(!partials)return;var value=isFunction(partials)?partials(token[1]):partials[token[1]];if(value!=null)return this.renderTokens(this.parse(value),context,partials,value)};Writer.prototype.unescapedValue=function unescapedValue(token,context){var value=context.lookup(token[1]);if(value!=null)return value};Writer.prototype.escapedValue=function escapedValue(token,context){var value=context.lookup(token[1]);if(value!=null)return mustache.escape(value)};Writer.prototype.rawValue=function rawValue(token){return token[1]};mustache.name="mustache.js";mustache.version="2.2.1";mustache.tags=["{{","}}"];var defaultWriter=new Writer;mustache.clearCache=function clearCache(){return defaultWriter.clearCache()};mustache.parse=function parse(template,tags){return defaultWriter.parse(template,tags)};mustache.render=function render(template,view,partials){if(typeof template!=="string"){throw new TypeError('Invalid template! Template should be a "string" '+'but "'+typeStr(template)+'" was given as the first '+"argument for mustache#render(template, view, partials)")}return defaultWriter.render(template,view,partials)};mustache.to_html=function to_html(template,view,partials,send){var result=mustache.render(template,view,partials);if(isFunction(send)){send(result)}else{return result}};mustache.escape=escapeHtml;mustache.Scanner=Scanner;mustache.Context=Context;mustache.Writer=Writer});
libs/better-framework/assets/js/selector-modal.js000064400000070760151214002560016151 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */


(function ($) {
    "use strict";


    /**
     * Init modal
     *
     * @param {Object} options
     * @constructor
     */
    var BsSelectorModal = function (options, bsModal) {

        this.options = $.extend(true, {
            itemBeforeHtml: '<li class="bssm-item {{class}}"{{#type}} data-item-type="{{type}}"{{/type}}{{#cat}} data-item-cat="{{cat}}"{{/cat}} data-item-id="{{id}}">',
            itemInnerHtml: '',
            itemAfterHtml: '</li>',

            modalHtml: false,
            id: 'modal-' + Math.ceil(Math.random() * 1e3),

            bsModal: bsModal || {},
            content: {},

            items: {},
            itemsGroupSize: 6,

            fuse: {
                keys: ["name"],
                tokenize: true,
                matchAllTokens: true,
                threshold: 0.3
            },

            searchDelay: 300,
            overlayClickCloseModal: true,
            searchAutoFocus: true,
            selectedItemId: 0,
            modalClass: '',

            categories: {},
            types: {},

            inactivateTypes: [],
            inactivateCats: [],

            noSidebar: false,

            /**
             * @property {callback} events.show_item Fire when a item must show
             * @property {callback} events.hide_item Fire when a item must hide
             *
             * @property {callback} events.modal_content [Filter] Generate bsModal options.content object
             * @property {callback} events.scrollIntoView  Fire when item into scrolled into view
             * @property {callback} events.after_append_html
             * @property {callback} events.item_select
             * @property {callback} events.item_click
             */
            events: {
                show_item: function (el) {
                    el.style.display = 'inline-block';
                },

                hide_item: function (el) {
                    el.style.display = 'none';
                }
            }

        }, options);

        if (!this.options.modalHtml) {

            var categories_template = '';

            if (this._length(this.options.categories)) {
                categories_template = '<div class="bssm-categories">\n    <h4 class="title"><span>{{filter_cat_title}}</span></h4>\n\n    <ul class="bssm-filter-items bf-radio-group">\n\n        {{#count_all}}\n        <li>\n            <div class="bf-radio-field" data-current-state="active" data-name="all"><span style="display: inline-block;"><i class="fa fa-circle" aria-hidden="true"></i></span></div>\n            <span class="name bf-radio-toggle" data-id="{{key}}">{{all_l10n}}</span><span class="length">({{count_all}})</span>\n        </li>\n        {{/count_all}}\n        \n        {{#filter_cats}}\n        <li>\n            <div class="bf-radio-field" data-current-state="deactivate" data-name="{{key}}"><span><i class="fa fa-circle" aria-hidden="true"></i></span></div>\n            <span class="name bf-radio-toggle" data-id="{{key}}">{{value}}</span><span class="length">({{count}})</span>\n        </li>\n        {{/filter_cats}}\n\n    </ul>\n</div>\n';
            }

            var types_template = '';

            if (this._length(this.options.types)) {
                types_template = '\n<div class="bssm-types">\n    <h4 class="title"><span>{{filter_type_title}}</span></h4>\n\n    <ul class="bssm-filter-items bf-radio-group">\n\n        {{#count_all}}\n        <li>\n            <div class="bf-radio-field" data-current-state="active" data-name="all"><span style="display: inline-block;"><i class="fa fa-circle" aria-hidden="true"></i></span></div>\n            <span class="name bf-radio-toggle" data-id="{{key}}">{{all_l10n}}</span><span class="length">({{count_all}})</span>\n        </li>\n        {{/count_all}}\n\n        {{#filter_types}}\n        <li>\n            <div class="bf-radio-field" data-current-state="deactivate" data-name="{{key}}"><span><i class="fa fa-circle" aria-hidden="true"></i></span></div>\n            <span class="name bf-radio-toggle" data-id="{{key}}">{{value}}</span>{{#count}}<span class="length">({{count}})</span>{{/count}}\n        </li>\n        {{/filter_types}}\n    </ul>\n</div>\t';
            }

            this.options.modalHtml = '<div class="bs-modal-default bs-selector-modal ' + this.options.modalClass + '" {{#inline_style}} style="{{inline_style}}" {{/inline_style}}>\n{{#close_button}}\n<a href="#" class="bs-close-modal">\n    <i class="fa fa-times" aria-hidden="true"></i>\n</a>\n{{/close_button}}\n<div class="bs-modal-header-wrapper bs-modal-clearfix">\n    <h2 class="bs-modal-header">\n        {{#icon}}\n        <i class="fa {{icon}}"></i>\n        {{/icon}}\n\n        {{{header}}}\n    </h2>\n</div>\n\n<div class="bs-modal-body">\n    <!--{{{bs_body}}}-->\n\n    <input type="hidden" name="item" class="bssm-input">\n\n    <div class="bssm-content {{content_class}}">\n        <ul class="bssm-list">\n            {{#items}}\n                '
                + this.options.itemBeforeHtml + this.options.itemInnerHtml + this.options.itemAfterHtml +
                '        \n            {{/items}}\n        </ul>\n    </div>\n    <div class="bssm-sidebar">\n        <div class="bssm-search">\n            <input type="text" class="bssm-search-input" value="" placeholder="{{search}}" autofocus>\n            <i class="fa fa-search"></i>\n        </div>\n\n        <div class="bssm-filter">\n            \n            ' + categories_template + types_template +
                '              </div>\n\n     \n    </div>\n</div>';
        }
        this.bsModal     = false;
        this.$allItems   = false;
        this.$itemsCache = {};

        this._scrollIntoView = [];
        this._visibleItems   = [];
        this.selectedItem    = false;

        this.initialized = false;

        this.fuse = new Fuse(this.options.items, this.options.fuse);

        this.init();
    };

    BsSelectorModal.prototype = {

        /**
         * Initialize Modal
         */
        init: function () {
            var self = this;

            self.initialized = true;

            $.bs_modal_template(this.options.id, this.options.modalHtml);

            var bsModalOptions = {
                modalId: this.options.id,
                buttons: this.options.buttons,
                destroyHtml: false,
                modalClass: this.options.modalClass,
                show: false,
                styles: {
                    container: 'width: 1060px;max-width:100%'
                },
                template: this.options.id,

                content: self._getModalContent(),

                events: {
                    before_append_html: function () {

                    },
                    after_append_html: function () {
                        self.bsModal = this;

                        self.options.noSidebar && self.bsModal.$modal.addClass('no-sidebar');

                        self.updateItemsList();
                        self._bindEvents();

                        self._clearSearchResults();
                        self._updateSidebarCheckboxStatus();

                        self.handleEvent('after_append_html', '');

                    },
                    /**
                     * Update Input Value
                     */
                    modal_closed: function () {

                        self._clearSearchResults();
                        self._updateSidebarCheckboxStatus('dont-refresh-items');
                        self._showHide(self.$allItems, true);

                        self.handleEvent('modal_closed', '');

                        self.initialized = false;
                    },


                    modal_loaded: function () {

                        if (self.options.searchAutoFocus) {

                            /**
                             * Auto focus on 'search' field
                             */
                            $('input.bssm-search-input', this.$modal).focus();
                        }

                        self.handleEvent('modal_loaded', '');
                    },

                    modal_show: function () {
                        self.handleEvent('modal_show', '');

                        if (self.initialized) {
                            self.scrollIntoView(0, self.options.itemsGroupSize);
                        }
                    }
                }

            };

            $.bs_modal($.extend(true, bsModalOptions, self.options.bsModal));
        },

        show: function () {
            this.bsModal.show();
        },
        updateItemsList: function () {
            this.$allItems = $(".bssm-item", this.bsModal.$modal);
        },

        /**
         *
         * Bind Events
         *
         * @private
         */
        _bindEvents: function () {
            var self = this;

            var $context = this.bsModal.$modal;

            /**
             *
             * @param {jQuery|array} _visibleItems
             */
            function updateVisibleItems(_visibleItems) {
                self._visibleItems = _visibleItems;
            }

            updateVisibleItems(self.$allItems);

            var $itemsContainer = $(".bssm-list", $context),
                $itemsList      = $itemsContainer.find('.bssm-item');

            self._cacheItems($itemsList);

            function handleFilters() {

                function getActiveItems(type) {
                    var activeItems  = [],
                        activeFilter = $(".bssm-" + type + " .bf-radio-field[data-current-state='active']", $context).data('name');


                    if (activeFilter) {

                        if (activeFilter === 'all') {

                            var idx = type === 'categories' ? 'filter_cats' : "filter_" + type;

                            if (self.bsModal.options.content[idx]) {
                                self.bsModal.options.content[idx].forEach(function (o) {

                                    activeItems.push(o.key);
                                });
                            }
                        } else {

                            activeItems.push(activeFilter);
                        }
                    }

                    return activeItems;
                }

                var checkList = {};

                if (self._length(self.options.types)) {
                    checkList.itemType = getActiveItems('types');
                }

                if (self._length(self.options.categories)) {
                    checkList.itemCat = getActiveItems('categories');
                }

                return self._filterItems(function () {

                    return (function (el) {
                        var value, _break,
                            itemValue,
                            data = self.$(el).data(); // cat & type props encoded as json already

                        for (var x in checkList) {
                            value     = checkList[x];

                            if( typeof data[x] ===  "undefined" || data[x] === '' ){
                                continue;
                            }

                            itemValue = self.json_decode(data[x]);
                            if (typeof itemValue === "string") {
                                itemValue = [itemValue];
                            }

                            if (typeof value === "string") {
                                value = [value];
                            }

                            var found = false;
                            for (var i = 0; i < itemValue.length; i++) {

                                if ($.inArray(itemValue[i], value) > -1) {

                                    found = true;
                                    break;
                                }
                            }

                            if (!found) {
                                return false;
                            }
                        }

                        return true;
                    })(this);
                });
            }


            function itemsScrollIntoView() {

                var singleItemHeight = $itemsList.outerHeight(true);

                /**
                 * Detect how many items show in each row
                 */
                function getItemsInSingleRow() {
                    var maxWidth   = $itemsContainer.width(),
                        itemsWidth = $itemsContainer.find('.bssm-item').outerWidth(true);

                    return Math.max(1, Math.floor(maxWidth / itemsWidth));
                }

                function getCurrentActiveItemsBlockNumber() {
                    var numberOfRows = self.options.itemsGroupSize / getItemsInSingleRow();

                    return Math.ceil($itemsContainer.scrollTop() / (singleItemHeight * numberOfRows));
                }

                var block = getCurrentActiveItemsBlockNumber();

                if (block) {
                    var currentBlock = (block * self.options.itemsGroupSize ); // - 1;

                    self.scrollIntoView(currentBlock, currentBlock + self.options.itemsGroupSize);
                }

            }

            function handleItemSearch(e, status) {

                /**
                 * Escape: 27
                 * Space: 32
                 */
                if ($.inArray(e.which, [32, 27]) !== -1) {
                    return;
                }
                clearTimeout(_searchTimeout);

                var searchQuery = $.trim(this.value),
                    $parent     = $(this).parent(),
                    $i          = $parent.find('i.fa');

                $parent[searchQuery ? 'addClass' : 'removeClass']('active');

                if (searchQuery) {

                    $i.addClass('fa-times-circle')
                        .removeClass('fa-search');
                } else {

                    $i.removeClass('fa-times-circle')
                        .addClass('fa-search');
                }

                if (status === 'change-icon') {
                    return;
                }

                _searchTimeout = setTimeout(function () {

                    $(".bssm-filter-items .bf-radio-field[data-name='all']", $context).trigger('click', ['search']); // reset filters

                    if (searchQuery) {

                        var visibleItemsIds = [];

                        self.fuse.search(searchQuery).forEach(function (found) {
                            visibleItemsIds.push(found.id);
                        });

                        var found, _visibleItems = [];
                        for (var i = 0; i < self.$allItems.length; i++) {

                            found = visibleItemsIds.indexOf(
                                    self.get_attr(self.$allItems[i], 'itemId')
                                ) !== -1;

                            if (found) {
                                _visibleItems.push(self.$allItems[i]);
                            }

                        }

                        self._showHide(self.$allItems, false);
                        self._showHide(_visibleItems, true);

                        updateVisibleItems(_visibleItems);
                    } else {
                        self.$allItems.show();
                        updateVisibleItems(self.$allItems);
                    }

                }, self.options.searchDelay);
            }


            if (self.eventExists('item_click')) {

                $itemsContainer.on("click",".bssm-item", function () {
                    self.handleEvent('item_click', this);
                });
            }

            $itemsContainer.on("click",".bssm-item", function () {

                var $item = self.$(this);

                self.markAsSelected($item);

                self.handleEvent('item_select', this, $item.data('item-id'));
            });

            var _searchTimeout;

            $(".bssm-search", $context).each(function () {
                var $this = $(this);

                // Event for Search item
                $('.bssm-search-input', $this).on('keyup', handleItemSearch);


                $this.on('click', '.fa-times-circle', function () {
                    var $input = $('.bssm-search-input', $this);
                    $input.val('');
                    $input.trigger('keyup');
                });

            });


            // Event to Handle Filter by type & category

            $(".bssm-sidebar .bf-radio-group", $context).on('bf-radio-change', function (e, status, flag) {
                if (flag !== 'dont-refresh-items') {

                    if (flag !== 'search') {
                        $(".bssm-search-input", $context).val('').trigger('keyup', ['change-icon']);
                    }

                    var $foundItems = handleFilters();

                    self._showHide(self.$allItems, false);
                    self._showHide($foundItems, true);
                    updateVisibleItems($foundItems);
                }
            });


            if (self.eventExists('scrollIntoView')) {

                $itemsContainer.on('scroll', function () {
                    itemsScrollIntoView();
                });
            }

            if (self.options.overlayClickCloseModal) {

                self.bsModal.find(".bs-modal-overlay").on('click', function () {
                    self.bsModal.close_modal();
                });
            }
        },

        /**
         * Trigger 'scroll into view' event of elements from start to end range
         *
         * @param {number} start
         * @param {number} end
         * @private
         */

        scrollIntoView: function (start, end) {
            var self  = this,
                items = self._visibleItems.slice(start, end);

            var results = [], id;

            for (var i = 0; i < items.length; i++) {

                id = self.get_attr(items[i], 'itemId');

                if (self._scrollIntoView.indexOf(id) === -1) {

                    self._scrollIntoView.push(id);
                    results.push(items[i]);
                }
            }

            if (results.length) {
                self.handleEvent('scrollIntoView', results, start, end);
            }

        },


        getSelectedItem: function () {

            return this.selectedItem;
        },

        setSelectedItem: function (element, id) {

            this.selectedItem = [element, id];
        },

        markAsSelected: function ($item) {
            this.$allItems.removeClass('bssm-selected');
            $item.addClass('bssm-selected');

            this.setSelectedItem($item, $item.data('item-id'));
        },

        json_encode: function (data) {
            data = JSON.stringify(data);

            return data.replace(/"/g, '\\"').replace(/'/g, "\\'");

        },

        json_decode: function (data) {
            data = data.replace(/\\"/g, '"').replace(/\\'/g, "'");
            return JSON.parse(data);
        },
        /**
         * Generate BSModal content option bsModal.options.content
         * @returns object
         * @private
         */
        _getModalContent: function () {
            var self = this,
                data;

            var results = self.options.content,
                o       = self.options;

            // Fill items with json encoded cat & type attributes
            results.items = [];

            self.options.items.forEach(function (item) {

                var _item = $.extend({},item);

                if (_item.cat) {
                    _item.cat = self.json_encode(item.cat);
                }

                if (_item.type) {
                    _item.type = self.json_encode(item.type);
                }

                results.items.push(_item);
            });

            var itemsCount_all = self._length(self.options.items);
            var itemsCount = 0;

            // remove no category items from all count
            for (var i = 0; i < itemsCount_all; i++) {

                if ( typeof self.options.items[i] === 'object' &&
                    self.options.items[i]['id'] !== "default") {
                    itemsCount++;
                }
            }

            function appendCountProperty(data, count) {
                var c;

                for (var i = 0; i < data.length; i++) {
                    c = data[i].key;

                    if (typeof count[c] !== 'undefined') {
                        data[i].count = String(count[c]);
                    } else {
                        data[i].count = '0';
                    }
                }

                return data;
            }

            function _countKey(key) {

                var _results = {}, k;

                for (var i = 0; i < itemsCount_all; i++) {

                    if(typeof self.options.items[i] !== 'object') {
                        continue;
                    }

                    k = self.options.items[i][key];

                    if (_results[k])
                        _results[k]++;
                    else
                        _results[k] = 1;

                }

                return _results;
            }

            data                = self._prepareObjectForMustache(o.categories);
            results.filter_cats = appendCountProperty(data, _countKey('cat'));

            data                 = self._prepareObjectForMustache(o.types);
            results.filter_types = appendCountProperty(data, _countKey('type'));

            results.count_all = itemsCount;

            // results.ch = '<div class="bf-checkbox-multi-state" data-current-state="active">\n    <input type="hidden"\n           class="bf-checkbox-status"\n           value="active">\n\n    <span data-state="none"></span>\n    <span data-state="active" class="bf-checkbox-active" style="display: inline-block;">\n        <i class="fa fa-check" aria-hidden="true"></i>\n    </span>\n</div>'

            return this.handleEvent('modal_content', results);
        },


        _updateSidebarCheckboxStatus: function (flag) {
            var self = this;

            $('.bssm-sidebar .name[data-id]', self.bsModal.$modal).each(function () {
                var $this         = $(this),
                    $checkbox     = $this.parent().find('.bf-checkbox-multi-state'),
                    currentStatus = $checkbox.data('current-state');

                // Todo: check inactivateCats

                if ($.inArray($this.data('id'), self.options.inactivateTypes) > -1) {

                    if (currentStatus !== 'none') {
                        $checkbox.trigger('click', [flag]);
                    }
                } else {
                    if (currentStatus !== 'active') {
                        $checkbox.trigger('click', [flag]);
                    }
                }
            });
        },
        /**
         * Todo: add doc
         *
         * @private
         */
        _clearSearchResults: function () {

            //FIXME: remove
            return;

            var self = this;

            $(".bssm-search-input", this.bsModal.$modal).val('');

            self._showHide(self.$allItems, false);

            function filter(attr, values) {
                var el2hide = self._filterItems(function () {
                    return values.indexOf(
                            self.get_attr(this, attr)
                        ) !== -1;
                });

                self._showHide(el2hide, true);
            }

            // update default unchecked types
            if (this.options.inactivateTypes) {
                filter('data-item-type', this.options.inactivateTypes);
            }
            // update default unchecked categories
            if (this.options.inactivateCats) {
                filter('data-item-cat', this.options.inactivateCats);
            }
        },

        /**
         * Filter all Items jquery object
         *
         * @param {callback}
         * @returns {jQuery}
         * @private
         */
        _filterItems: function (callback) {

            return this.$allItems.filter(callback);
        },
        /**
         * Handle modal events.
         * Fire Registered callback for event
         *
         * @param  {String} event
         * @param  {*} retVal return value
         * @returns {*} Return Fired Callback Results
         */
        handleEvent: function (event, retVal) {
            var args = Array.prototype.slice.call(arguments, 1);
            if (typeof this.options.events[event] === 'function')
                return this.options.events[event].apply(this, args);

            return retVal;
        },

        /**
         * Check is any function registered for event
         *
         * @param  {String} event
         */
        eventExists: function (event) {
            return typeof this.options.events[event] === 'function';
        },

        /**
         * Get cached jQuery element
         *
         * @param {Element}
         * @returns {jQuery}
         */
        $: function (el) {
            if (el.dataset.itemId) {

                var id = el.dataset.itemId;

                if (!( id in this.$itemsCache )) {

                    this.$itemsCache[el.dataset.itemId] = $(el, this.$modal);
                }

                return this.$itemsCache[el.dataset.itemId];
            }

            return $(el, this.$modal);
        },

        selectItem: function (itemId) {

            if (!( itemId in this.$itemsCache )) {

                this.$itemsCache[itemId] = $('.bssm-item[data-item-id="' + itemId + '"]', this.bsModal.$modal);
            }

            return this.$itemsCache[itemId];
        },

        /**
         * Show/ hide items element
         *
         * @param {Array}  elements array of elements
         * @param {Boolean} show
         * @private
         */

        _showHide: function (elements, show) {

            var event = show ? 'show_item' : 'hide_item';

            for (var i = 0; i < elements.length; i++) {

                if (elements[i]) {
                    this.handleEvent(event, elements[i]);
                }
            }
        },
        /**
         * Get Element Attirubute
         *
         * @param {Element} el
         * @param {String} attr
         * @returns {*}
         */
        get_attr: function (el, attr) {

            if (el.dataset) {
                return el.dataset[attr];
            }

            return this.$(el, this.bsModal.$modal).attr(attr);
        },

        /**
         * Convert Key-Value paired object to array
         *
         * @param obj
         *  {
         *   Key: value
         *  }
         *  to
         *     [
         *      {
         *          key:key,
         *          value:value
         *      }
         *     ]
         *
         * @private
         */
        _prepareObjectForMustache: function (obj) {
            var results = [];
            for (var k in obj) {

                results.push({
                    key: k,
                    value: obj[k]
                });
            }

            return results;
        },

        _cacheItems: function (items) {
            this.$itemsCache = {};

            var $item, id;
            for (var i = 0; i < items.length; i++) {
                $item = $(items[i]);

                id = $item.data('item-id');


                this.$itemsCache[id] = $item;
            }

        },
        _length: function (object) {
            if (!object) {
                return 0;
            }

            if (Object.keys) {
                return Object.keys(object).length;
            }

            var count = 0, i;

            for (i in object) {
                if (object.hasOwnProperty(i)) {
                    count++;
                }
            }

            return count;
        },


    };

    /**
     * Register bs_selector_modal jQuery function
     *
     * @param {Object} options Options
     * @param {Object} bsModalOptions override BsModal options
     *
     * @returns {BsSelectorModal} Selector modal object
     */
    $.bs_selector_modal = function (options, bsModalOptions) {

        return new BsSelectorModal(options, bsModalOptions);
    }
})(jQuery);
libs/better-framework/assets/js/widgets.min.js000064400000001401151214002560015451 0ustar00/**
 * BetterFramework Widgets & Shortcodes
 * Copyright 2014 BetterStudio
 * @license BetterStudio
 */
!function(e){e.betterNewsTicker=function(t,i){var n=this;n.$el=e(t),n.el=t,n.$el.data("betterNewsTicker",n),n.init=function(){n.options=e.extend({},e.betterNewsTicker.defaultOptions,i),n.options=e.extend({},n.$el.data(),i),n.$el.find("li.active").length||!n.$el.find("li:first").addClass("active"),window.setInterval(function(){var e=n.$el.find("li.active");e.fadeOut(function(){var t=e.next();t.length||(t=n.$el.find("li:first")),t.addClass("active").fadeIn(),e.removeClass("active")})},n.options.time)},n.init()},e.betterNewsTicker.defaultOptions={time:2e4},e.fn.betterNewsTicker=function(t){return this.each(function(){new e.betterNewsTicker(this,t)})}}(jQuery);libs/better-framework/assets/js/selector-modal.min.js000064400000027333151214002560016731 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */
!function(m){"use strict";var s=function(t,e){if(this.options=m.extend(!0,{itemBeforeHtml:'<li class="bssm-item {{class}}"{{#type}} data-item-type="{{type}}"{{/type}}{{#cat}} data-item-cat="{{cat}}"{{/cat}} data-item-id="{{id}}">',itemInnerHtml:"",itemAfterHtml:"</li>",modalHtml:!1,id:"modal-"+Math.ceil(1e3*Math.random()),bsModal:e||{},content:{},items:{},itemsGroupSize:6,fuse:{keys:["name"],tokenize:!0,matchAllTokens:!0,threshold:.3},searchDelay:300,overlayClickCloseModal:!0,searchAutoFocus:!0,selectedItemId:0,modalClass:"",categories:{},types:{},inactivateTypes:[],inactivateCats:[],noSidebar:!1,events:{show_item:function(t){t.style.display="inline-block"},hide_item:function(t){t.style.display="none"}}},t),!this.options.modalHtml){var s="";this._length(this.options.categories)&&(s='<div class="bssm-categories">\n    <h4 class="title"><span>{{filter_cat_title}}</span></h4>\n\n    <ul class="bssm-filter-items bf-radio-group">\n\n        {{#count_all}}\n        <li>\n            <div class="bf-radio-field" data-current-state="active" data-name="all"><span style="display: inline-block;"><i class="fa fa-circle" aria-hidden="true"></i></span></div>\n            <span class="name bf-radio-toggle" data-id="{{key}}">{{all_l10n}}</span><span class="length">({{count_all}})</span>\n        </li>\n        {{/count_all}}\n        \n        {{#filter_cats}}\n        <li>\n            <div class="bf-radio-field" data-current-state="deactivate" data-name="{{key}}"><span><i class="fa fa-circle" aria-hidden="true"></i></span></div>\n            <span class="name bf-radio-toggle" data-id="{{key}}">{{value}}</span><span class="length">({{count}})</span>\n        </li>\n        {{/filter_cats}}\n\n    </ul>\n</div>\n');var i="";this._length(this.options.types)&&(i='\n<div class="bssm-types">\n    <h4 class="title"><span>{{filter_type_title}}</span></h4>\n\n    <ul class="bssm-filter-items bf-radio-group">\n\n        {{#count_all}}\n        <li>\n            <div class="bf-radio-field" data-current-state="active" data-name="all"><span style="display: inline-block;"><i class="fa fa-circle" aria-hidden="true"></i></span></div>\n            <span class="name bf-radio-toggle" data-id="{{key}}">{{all_l10n}}</span><span class="length">({{count_all}})</span>\n        </li>\n        {{/count_all}}\n\n        {{#filter_types}}\n        <li>\n            <div class="bf-radio-field" data-current-state="deactivate" data-name="{{key}}"><span><i class="fa fa-circle" aria-hidden="true"></i></span></div>\n            <span class="name bf-radio-toggle" data-id="{{key}}">{{value}}</span>{{#count}}<span class="length">({{count}})</span>{{/count}}\n        </li>\n        {{/filter_types}}\n    </ul>\n</div>\t'),this.options.modalHtml='<div class="bs-modal-default bs-selector-modal '+this.options.modalClass+'" {{#inline_style}} style="{{inline_style}}" {{/inline_style}}>\n{{#close_button}}\n<a href="#" class="bs-close-modal">\n    <i class="fa fa-times" aria-hidden="true"></i>\n</a>\n{{/close_button}}\n<div class="bs-modal-header-wrapper bs-modal-clearfix">\n    <h2 class="bs-modal-header">\n        {{#icon}}\n        <i class="fa {{icon}}"></i>\n        {{/icon}}\n\n        {{{header}}}\n    </h2>\n</div>\n\n<div class="bs-modal-body">\n    \x3c!--{{{bs_body}}}--\x3e\n\n    <input type="hidden" name="item" class="bssm-input">\n\n    <div class="bssm-content {{content_class}}">\n        <ul class="bssm-list">\n            {{#items}}\n                '+this.options.itemBeforeHtml+this.options.itemInnerHtml+this.options.itemAfterHtml+'        \n            {{/items}}\n        </ul>\n    </div>\n    <div class="bssm-sidebar">\n        <div class="bssm-search">\n            <input type="text" class="bssm-search-input" value="" placeholder="{{search}}" autofocus>\n            <i class="fa fa-search"></i>\n        </div>\n\n        <div class="bssm-filter">\n            \n            '+s+i+"              </div>\n\n     \n    </div>\n</div>"}this.bsModal=!1,this.$allItems=!1,this.$itemsCache={},this._scrollIntoView=[],this._visibleItems=[],this.selectedItem=!1,this.initialized=!1,this.fuse=new Fuse(this.options.items,this.options.fuse),this.init()};s.prototype={init:function(){var t=this;t.initialized=!0,m.bs_modal_template(this.options.id,this.options.modalHtml);var e={modalId:this.options.id,buttons:this.options.buttons,destroyHtml:!1,modalClass:this.options.modalClass,show:!1,styles:{container:"width: 1060px;max-width:100%"},template:this.options.id,content:t._getModalContent(),events:{before_append_html:function(){},after_append_html:function(){t.bsModal=this,t.options.noSidebar&&t.bsModal.$modal.addClass("no-sidebar"),t.updateItemsList(),t._bindEvents(),t._clearSearchResults(),t._updateSidebarCheckboxStatus(),t.handleEvent("after_append_html","")},modal_closed:function(){t._clearSearchResults(),t._updateSidebarCheckboxStatus("dont-refresh-items"),t._showHide(t.$allItems,!0),t.handleEvent("modal_closed",""),t.initialized=!1},modal_loaded:function(){t.options.searchAutoFocus&&m("input.bssm-search-input",this.$modal).focus(),t.handleEvent("modal_loaded","")},modal_show:function(){t.handleEvent("modal_show",""),t.initialized&&t.scrollIntoView(0,t.options.itemsGroupSize)}}};m.bs_modal(m.extend(!0,e,t.options.bsModal))},show:function(){this.bsModal.show()},updateItemsList:function(){this.$allItems=m(".bssm-item",this.bsModal.$modal)},_bindEvents:function(){var c=this,n=this.bsModal.$modal;function o(t){c._visibleItems=t}o(c.$allItems);var l,r=m(".bssm-list",n),d=r.find(".bssm-item");function t(){var t=d.outerHeight(!0);var e,s,i,a=(i=c.options.itemsGroupSize/(e=r.width(),s=r.find(".bssm-item").outerWidth(!0),Math.max(1,Math.floor(e/s))),Math.ceil(r.scrollTop()/(t*i)));if(a){var n=a*c.options.itemsGroupSize;c.scrollIntoView(n,n+c.options.itemsGroupSize)}}function s(t,e){if(-1===m.inArray(t.which,[32,27])){clearTimeout(l);var i=m.trim(this.value),s=m(this).parent(),a=s.find("i.fa");s[i?"addClass":"removeClass"]("active"),i?a.addClass("fa-times-circle").removeClass("fa-search"):a.removeClass("fa-times-circle").addClass("fa-search"),"change-icon"!==e&&(l=setTimeout(function(){if(m(".bssm-filter-items .bf-radio-field[data-name='all']",n).trigger("click",["search"]),i){var e=[];c.fuse.search(i).forEach(function(t){e.push(t.id)});for(var t=[],s=0;s<c.$allItems.length;s++)-1!==e.indexOf(c.get_attr(c.$allItems[s],"itemId"))&&t.push(c.$allItems[s]);c._showHide(c.$allItems,!1),c._showHide(t,!0),o(t)}else c.$allItems.show(),o(c.$allItems)},c.options.searchDelay))}}c._cacheItems(d),c.eventExists("item_click")&&r.on("click",".bssm-item",function(){c.handleEvent("item_click",this)}),r.on("click",".bssm-item",function(){var t=c.$(this);c.markAsSelected(t),c.handleEvent("item_select",this,t.data("item-id"))}),m(".bssm-search",n).each(function(){var e=m(this);m(".bssm-search-input",e).on("keyup",s),e.on("click",".fa-times-circle",function(){var t=m(".bssm-search-input",e);t.val(""),t.trigger("keyup")})}),m(".bssm-sidebar .bf-radio-group",n).on("bf-radio-change",function(t,e,s){if("dont-refresh-items"!==s){"search"!==s&&m(".bssm-search-input",n).val("").trigger("keyup",["change-icon"]);var i=function(){function t(t){var e=[],s=m(".bssm-"+t+" .bf-radio-field[data-current-state='active']",n).data("name");if(s)if("all"===s){var i="categories"===t?"filter_cats":"filter_"+t;c.bsModal.options.content[i]&&c.bsModal.options.content[i].forEach(function(t){e.push(t.key)})}else e.push(s);return e}var l={};return c._length(c.options.types)&&(l.itemType=t("types")),c._length(c.options.categories)&&(l.itemCat=t("categories")),c._filterItems(function(){return function(t){var e,s,i=c.$(t).data();for(var a in l)if(e=l[a],void 0!==i[a]&&""!==i[a]){"string"==typeof(s=c.json_decode(i[a]))&&(s=[s]),"string"==typeof e&&(e=[e]);for(var n=!1,o=0;o<s.length;o++)if(-1<m.inArray(s[o],e)){n=!0;break}if(!n)return!1}return!0}(this)})}();c._showHide(c.$allItems,!1),c._showHide(i,!0),o(i)}}),c.eventExists("scrollIntoView")&&r.on("scroll",function(){t()}),c.options.overlayClickCloseModal&&c.bsModal.find(".bs-modal-overlay").on("click",function(){c.bsModal.close_modal()})},scrollIntoView:function(t,e){for(var s,i=this,a=i._visibleItems.slice(t,e),n=[],o=0;o<a.length;o++)s=i.get_attr(a[o],"itemId"),-1===i._scrollIntoView.indexOf(s)&&(i._scrollIntoView.push(s),n.push(a[o]));n.length&&i.handleEvent("scrollIntoView",n,t,e)},getSelectedItem:function(){return this.selectedItem},setSelectedItem:function(t,e){this.selectedItem=[t,e]},markAsSelected:function(t){this.$allItems.removeClass("bssm-selected"),t.addClass("bssm-selected"),this.setSelectedItem(t,t.data("item-id"))},json_encode:function(t){return(t=JSON.stringify(t)).replace(/"/g,'\\"').replace(/'/g,"\\'")},json_decode:function(t){return t=t.replace(/\\"/g,'"').replace(/\\'/g,"'"),JSON.parse(t)},_getModalContent:function(){var t,a=this,s=a.options.content,e=a.options;s.items=[],a.options.items.forEach(function(t){var e=m.extend({},t);e.cat&&(e.cat=a.json_encode(t.cat)),e.type&&(e.type=a.json_encode(t.type)),s.items.push(e)});for(var n=a._length(a.options.items),i=0,o=0;o<n;o++)"object"==typeof a.options.items[o]&&"default"!==a.options.items[o].id&&i++;function l(t,e){for(var s,i=0;i<t.length;i++)void 0!==e[s=t[i].key]?t[i].count=String(e[s]):t[i].count="0";return t}function c(t){for(var e,s={},i=0;i<n;i++)"object"==typeof a.options.items[i]&&(s[e=a.options.items[i][t]]?s[e]++:s[e]=1);return s}return t=a._prepareObjectForMustache(e.categories),s.filter_cats=l(t,c("cat")),t=a._prepareObjectForMustache(e.types),s.filter_types=l(t,c("type")),s.count_all=i,this.handleEvent("modal_content",s)},_updateSidebarCheckboxStatus:function(i){var a=this;m(".bssm-sidebar .name[data-id]",a.bsModal.$modal).each(function(){var t=m(this),e=t.parent().find(".bf-checkbox-multi-state"),s=e.data("current-state");-1<m.inArray(t.data("id"),a.options.inactivateTypes)?"none"!==s&&e.trigger("click",[i]):"active"!==s&&e.trigger("click",[i])})},_clearSearchResults:function(){return},_filterItems:function(t){return this.$allItems.filter(t)},handleEvent:function(t,e){var s=Array.prototype.slice.call(arguments,1);return"function"==typeof this.options.events[t]?this.options.events[t].apply(this,s):e},eventExists:function(t){return"function"==typeof this.options.events[t]},$:function(t){return t.dataset.itemId?(t.dataset.itemId in this.$itemsCache||(this.$itemsCache[t.dataset.itemId]=m(t,this.$modal)),this.$itemsCache[t.dataset.itemId]):m(t,this.$modal)},selectItem:function(t){return t in this.$itemsCache||(this.$itemsCache[t]=m('.bssm-item[data-item-id="'+t+'"]',this.bsModal.$modal)),this.$itemsCache[t]},_showHide:function(t,e){for(var s=e?"show_item":"hide_item",i=0;i<t.length;i++)t[i]&&this.handleEvent(s,t[i])},get_attr:function(t,e){return t.dataset?t.dataset[e]:this.$(t,this.bsModal.$modal).attr(e)},_prepareObjectForMustache:function(t){var e=[];for(var s in t)e.push({key:s,value:t[s]});return e},_cacheItems:function(t){var e,s;this.$itemsCache={};for(var i=0;i<t.length;i++)s=(e=m(t[i])).data("item-id"),this.$itemsCache[s]=e},_length:function(t){if(!t)return 0;if(Object.keys)return Object.keys(t).length;var e,s=0;for(e in t)t.hasOwnProperty(e)&&s++;return s}},m.bs_selector_modal=function(t,e){return new s(t,e)}}(jQuery);libs/better-framework/assets/js/element-query.min.js000064400000004653151214002560016613 0ustar00/**
 * getEmPixels
 * Author: Tyson Matanich (http://matanich.com), 2013
 * License: MIT
 **/
(function(n,t){"use strict";var i="!important;",r="position:absolute"+i+"visibility:hidden"+i+"width:1em"+i+"font-size:1em"+i+"padding:0"+i;window.getEmPixels=function(u){var f,e,o;return u||(u=f=n.createElement("body"),f.style.cssText="font-size:1em"+i,t.insertBefore(f,n.body)),e=n.createElement("i"),e.style.cssText=r,u.appendChild(e),o=e.clientWidth,f?t.removeChild(f):u.removeChild(e),o}})(document,document.documentElement);

/**
 * elementQuery
 * Author: Tyson Matanich (http://matanich.com), 2013
 * License: MIT
 **/
(function(n,t,i){"use strict";var e=n.Sizzle||jQuery.find,r={},o=function(n,t,u,o,s){if(n=f(n),n!=""){var h;o||s||(h=/^([0-9]*.?[0-9]+)(px|em)$/.exec(u),h!=null&&(o=Number(h[1]),o+""!="NaN"&&(s=h[2]))),s&&(e.compile&&e.compile(n),r[n]===i&&(r[n]={}),r[n][t]===i&&(r[n][t]={}),r[n][t][u]=[o,s])}},h=function(n,t){var i,r,f;for(i in n)for(r in n[i])if(typeof n[i][r]=="string")o(i,r,n[i][r]);else if(typeof n[i][r]=="object")for(f=0;f<n[i][r].length;f++)o(i,r,n[i][r][f]);t==!0&&u()},f=function(n){if(n==null)return"";var t="".trim;return t&&!t.call(" ")?t.call(n):(n+"").replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")},s=function(n,t){var i=n.getAttribute(t);return i?(" "+i+" ").replace(/[\t\r\n]/g," "):" "},c=function(n,t,i){var r,u;n.nodeType===1&&(r=f(i),r!=""&&(u=s(n,t),u.indexOf(" "+r+" ")<0&&n.setAttribute(t,f(u+r))))},l=function(n,t,i){var u,r,e;if(n.nodeType===1&&(u=f(i),u!="")){for(r=s(n,t),e=!1;r.indexOf(" "+u+" ")>=0;)r=r.replace(" "+u+" "," "),e=!0;e&&n.setAttribute(t,f(r))}},u=function(){var o,h,i,s,a,u,f,v;for(o in r)if(a=e(o),a.length>0)for(h=0;h<a.length;h++){u=a[h];for(i in r[o])for(s in r[o][i])f=r[o][i][s][0],r[o][i][s][1]=="em"&&(f=f*(n.getEmPixels?getEmPixels(u):16)),i=="min-width"&&u.offsetWidth>=f||i=="max-width"&&u.offsetWidth<=f||i=="min-height"&&u.offsetHeight>=f||i=="max-height"&&u.offsetHeight<=f?c(u,i,s):l(u,i,s)}!n.addEventListener&&n.attachEvent&&(v=t.documentElement.className,t.documentElement.className=" "+v,t.documentElement.className=v)};n.elementQuery=function(n,t){!n||typeof n!="object"||n.cssRules||n.rules?n||t||u():h(n,t)},n.elementQuery.selectors=function(){},n.addEventListener?(n.addEventListener("resize",u,!1),n.addEventListener("DOMContentLoaded",u,!1),n.addEventListener("load",u,!1)):n.attachEvent&&(n.attachEvent("onresize",u),n.attachEvent("onload",u))})(this,document,undefined);libs/better-framework/assets/js/respond.min.js000064400000010765151214002560015472 0ustar00/**
 *  Respond.js v1.4.2: min/max-width media query polyfill
 * Copyright 2014 Scott Jehl
 * Licensed under MIT
 * http://j.mp/respondjs
 **/

!function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='&shy;<style media="'+a+'"> #mq-test-1 { width: 42px; }</style>',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){v(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))},g=function(a){return a.replace(c.regex.minmaxwh,"").match(c.regex.other)};if(c.ajax=f,c.queue=d,c.unsupportedmq=g,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,comments:/\/\*[^*]*\*+([^/][^*]*\*+)*\//gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\(\s*min\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,maxw:/\(\s*max\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,minmaxwh:/\(\s*m(in|ax)\-(height|width)\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/gi,other:/\([^\)]*\)/g},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var h,i,j,k=a.document,l=k.documentElement,m=[],n=[],o=[],p={},q=30,r=k.getElementsByTagName("head")[0]||l,s=k.getElementsByTagName("base")[0],t=r.getElementsByTagName("link"),u=function(){var a,b=k.createElement("div"),c=k.body,d=l.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=k.createElement("body"),c.style.background="none"),l.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&l.insertBefore(c,l.firstChild),a=b.offsetWidth,f?l.removeChild(c):c.removeChild(b),l.style.fontSize=d,e&&(c.style.fontSize=e),a=j=parseFloat(a)},v=function(b){var c="clientWidth",d=l[c],e="CSS1Compat"===k.compatMode&&d||k.body[c]||d,f={},g=t[t.length-1],p=(new Date).getTime();if(b&&h&&q>p-h)return a.clearTimeout(i),i=a.setTimeout(v,q),void 0;h=p;for(var s in m)if(m.hasOwnProperty(s)){var w=m[s],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?j||u():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?j||u():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(n[w.rules]))}for(var C in o)o.hasOwnProperty(C)&&o[C]&&o[C].parentNode===r&&r.removeChild(o[C]);o.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=k.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,r.insertBefore(E,g.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(k.createTextNode(F)),o.push(E)}},w=function(a,b,d){var e=a.replace(c.regex.comments,"").replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var h=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},i=!f&&d;b.length&&(b+="/"),i&&(f=1);for(var j=0;f>j;j++){var k,l,o,p;i?(k=d,n.push(h(a))):(k=e[j].match(c.regex.findStyles)&&RegExp.$1,n.push(RegExp.$2&&h(RegExp.$2))),o=k.split(","),p=o.length;for(var q=0;p>q;q++)l=o[q],g(l)||m.push({media:l.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:n.length-1,hasquery:l.indexOf("(")>-1,minw:l.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:l.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}v()},x=function(){if(d.length){var b=d.shift();f(b.href,function(c){w(c,b.href,b.media),p[b.href]=!0,a.setTimeout(function(){x()},0)})}},y=function(){for(var b=0;b<t.length;b++){var c=t[b],e=c.href,f=c.media,g=c.rel&&"stylesheet"===c.rel.toLowerCase();e&&g&&!p[e]&&(c.styleSheet&&c.styleSheet.rawCssText?(w(c.styleSheet.rawCssText,e,f),p[e]=!0):(!/^([a-zA-Z:]*\/\/)/.test(e)&&!s||e.replace(RegExp.$1,"").split("/")[0]===a.location.host)&&("//"===e.substring(0,2)&&(e=a.location.protocol+e),d.push({href:e,media:f})))}x()};y(),c.update=y,c.getEmValue=u,a.addEventListener?a.addEventListener("resize",b,!1):a.attachEvent&&a.attachEvent("onresize",b)}}(this);libs/better-framework/assets/js/better-fonts-manager.js000064400000143722151214002560017262 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */


var Better_Fonts_Manager = (function ($) {
    "use strict";

    return {

        init: function () {

            switch (better_fonts_manager_loc.type) {

                // Setup Panel
                case 'panel':

                    this.setup_panel_fonts_manager();

                    //Setup General fields
                    this.setup_field_typography();
                    this.setup_field_font_selector();

                    this.attach_events();

                    $(".bf-section[data-id='font_stacks']").on('keyup', 'input[name$="[id]"]', function () {
                        var $this = $(this),
                            $wrapper = $this.closest('.bf-repeater-item');

                        $wrapper.find('.bf-repeater-item-title .handle-repeater-title-label')
                            .text('Font Stack: ' + $this.val());

                    }).find('input[name$="[id]"]').keyup();

                    break;

                // Setup Widgets
                case 'widgets':

                    break;

                // Setup Metaboxes
                case 'metabox':
                    break;

                // Setup Menus
                case 'menus':

                    break;

            }

        },

        load_google_fonts: {},
        load_theme_fonts: {},
        load_custom_fonts: {},
        load_google_ea_fonts: {},

        attach_events: function () {
            var self = this;
            $(document).on('bf-ajax-tab-loaded', function (e, target) {
                self.setup_panel_fonts_manager(target);

                //Setup General fields
                self.setup_field_typography(target);
            });

        },

        _length: function (object) {
            if (!object) {
                return 0;
            }

            if (Object.keys) {
                return Object.keys(object).length;
            }

            var count = 0, i;

            for (i in object) {
                if (object.hasOwnProperty(i)) {
                    count++;
                }
            }

            return count;
        },

        ajax: function (action, data, success_callback) {
            return $.ajax({
                    type: 'POST',
                    dataType: 'json',
                    url: better_framework_loc.bf_ajax_url,
                    data: $.extend(true, {
                        action: 'bf_ajax',
                        reqID: action,
                        type: better_framework_loc.type,
                        panelID: $('#bf-panel-id').val(),
                        nonce: better_framework_loc.nonce,
                        lang: better_framework_loc.lang,
                        data: []
                    }, data),
                    success: success_callback,
                    error: function () {
                        Better_Framework.panel_loader('error');
                    }
                }
            );
        },

        getFontSelectorFontsList: function () {

            var self = this, font;

            var results = [],
                lbl = better_fonts_manager_loc.labels;

            for (var type in better_fonts_manager_loc.fonts) {

                for (var fontID in better_fonts_manager_loc.fonts[type]) {
                    font = better_fonts_manager_loc.fonts[type][fontID];
                    var styleCount = font.variants ? self._length(font.variants) : 1,
                        cat = font.category ? font.category : 'serif';

                    results.push({
                        type_label: lbl.types[type] ? lbl.types[type] : type,
                        type: type.replace('fonts', 'font'),
                        cat: cat,
                        name: font.name ? font.name : fontID,
                        styles: lbl.style.replace('%s', styleCount),
                        id: fontID,
                    });

                }
            }

            return results;
        },

        loadFonts: function (type, fontFamilies, fontloading, fontactive) {

            switch (type) {

                case 'google_font':
                    WebFont.load({
                        google: {
                            families: fontFamilies,
                            text: better_fonts_manager_loc.labels.preview_text
                        },
                        fontloading: fontloading,
                        fontactive: fontactive,
                        fontinactive: fontactive,
                        classes: false
                    });

                    break;

                case 'google_ea_font':
                case 'custom_font':
                case 'theme_font':

                    var qVar = type.replace(/\-+/g, '_') + "_id";

                    fontFamilies.forEach(function (fontfamily) {

                        WebFont.load({
                            custom: {
                                families: fontfamily,
                                urls: [better_fonts_manager_loc.admin_fonts_css_url + '&' + qVar + "=" + fontfamily]
                            },

                            fontloading: fontloading,
                            fontactive: fontactive,
                            fontinactive: fontactive,
                            classes: false
                        })
                    });

                    break;

                default:
                    return false;
                    break;
            }

            return true;
        },

        /**
         * Initialize font selector modal
         */
        setup_field_font_selector: function () {

            var self = this,
                autoCloseDelay = 150,
                $context;

            var fonts = self.getFontSelectorFontsList(),
                $fontSelectorEl;


            function openCustomFontModal(mainModal, selectorModal) {
                var wpMediaFrameClosed = false;

                function catchWpMediaFrameStatus(modalObj) {
                    modalObj.$modal
                        .find('.bf-media-upload-btn')
                        .on('click', function () {
                            var $btn = $(this);
                            setTimeout(function () {

                                wp.media.frame.on('close', function () {
                                    wpMediaFrameClosed = true;
                                });

                                wp.media.frame.on('select', function () {
                                    $('.input', $btn.parent())
                                        .val(wp.media.frame.state().get('selection').first().toJSON().url)
                                        .trigger('keyup');
                                });

                            }, 100);
                        });
                }

                function overlayClickCloseModal(modalObj) {
                    modalObj.find(".bs-modal-overlay").on('click', function () {
                        modalObj.close_modal();
                    })
                }

                function isWpMediaFrameClosed() {
                    return wpMediaFrameClosed;
                }


                function handleAddCustomFontBtn(addFontModal) {

                    function generateSingleFontHtml() {
                        var name = $('.font-name', addFontModal.$modal).val();

                        var o = selectorModal.options,
                            l = better_fonts_manager_loc.labels;

                        var replacement = {
                            type: 'custom_font',
                            cat: 'serif',
                            id: name,
                            name: name,
                            styles: 1,
                            preview_text: l.preview_text,
                            type_label: l.filter_types.custom_font
                        };

                        return Mustache.render(o.itemBeforeHtml + o.itemInnerHtml + o.itemAfterHtml, replacement);
                    }

                    var singleFontItem = generateSingleFontHtml(name);


                    var ajaxData = $.extend(better_fonts_manager_loc.add_font, {
                        args: $('.form', addFontModal.$modal).serialize()
                    });


                    // Display loading..
                    addFontModal.change_skin({
                        skin: 'loading',
                        template: 'default',
                        animations: {
                            body: 'bs-animate bs-fadeInLeft'
                        }
                    });

                    self.ajax('ajax_action', ajaxData, function (data) {

                        var fontsList = $('.bssm-list', selectorModal.bsModal.$modal);

                        if (data.new_font_id) {
                            fontsList
                                .find('.bf-font-family')
                                .val(data.new_font_id);
                        }

                        // Append new custom font to main modal
                        if (singleFontItem) {
                            fontsList.prepend(singleFontItem);
                            selectorModal.markAsSelected(fontsList.find(':first'));
                            selectorModal.updateItemsList();
                        }


                        addFontModal.close_modal();


                        setTimeout(function () {
                            mainModal.close_modal();
                        }, autoCloseDelay + addFontModal.options.animations.delay);
                    });
                }

                function handleCustomFontInteractiveFields(modalObj) {

                    var _isPrimaryBtnActive = false,
                        $modal = modalObj.$modal;

                    function togglePrimaryBtnDisable(inputValue) {
                        if (inputValue && !_isPrimaryBtnActive) {
                            $modal.find('.bs-modal-btn-primary').removeClass('disabled');
                            _isPrimaryBtnActive = true;
                        } else if (!inputValue && _isPrimaryBtnActive) {

                            if (!$modal.find('.input-section:not(.empty)').length) {
                                $modal.find('.bs-modal-btn-primary').addClass('disabled');
                                _isPrimaryBtnActive = false;
                            }
                        }
                    }

                    /**
                     * Auto focus on 'Font Name' field
                     */
                    $modal.find('input.font-name').focus();

                    /**
                     * Trigger upload buttons active/deactivate style
                     */
                    $modal
                        .find(':input')
                        .on('keyup', function () {
                            var $this = $(this),
                                value = $.trim($this.val());

                            $this.parent()[value === '' ? 'addClass' : 'removeClass']('empty');

                            if ($this.hasClass('font-url-input')) {
                                togglePrimaryBtnDisable(value);
                            }
                        });
                }


                $.bs_modal_template('upload-font', '<div class="bs-modal-default bs-font-selector-modal bs-font-upload-modal" {{#inline_style}} style="{{inline_style}}"\n     {{/inline_style}}>\n{{#close_button}}\n<a href="#" class="bs-close-modal">\n    <i class="fa fa-times" aria-hidden="true"></i>\n</a>\n{{/close_button}}\n<div class="bs-modal-header-wrapper bs-modal-clearfix">\n    <h2 class="bs-modal-header">\n        {{#icon}}\n        <i class="fa {{icon}}"></i>\n        {{/icon}}\n\n        {{header}}\n    </h2>\n</div>\n\n<div class="bs-modal-body">\n\n    <form class="form">\n\n        <div class="bf-section-container">\n            <label for="custom-font-name">{{font_name}}</label>\n            <input type="text" class="font-name input" name="font-name" value="" id="custom-font-name" autofocus>\n\n        </div>\n\n\n        <div class="bf-clearfix bf-choose-fonts">\n            <div class="bf-section-container font-woff">\n                <label for="custom-font-woff">{{font_woff}}</label>\n                <div class="input-section empty">\n\n                    <input type="text" value="" id="custom-font-woff" name="fonts[woff]" class="input font-url-input">\n                    <a class="bf-media-upload-btn bssm-button" \n                       data-mediatitle="{{upload_woff}}"\n                       data-mediasettings=\'{"type":["font/woff","font/woff2"]}\'\n                       data-buttontext="{{upload_woff}}">\n                        {{upload_woff}}\n                    </a>\n                </div>\n            </div>\n\n\t        <div class="bf-section-container font-woff2">\n\t\t        <label for="custom-font-woff2">{{font_woff2}}</label>\n\t\t        <div class="input-section empty">\n\n\t\t\t        <input type="text" value="" id="custom-font-woff2" name="fonts[woff2]" class="input font-url-input">\n\t\t\t        <a class="bf-media-upload-btn bssm-button"\n\t\t\t           data-mediatitle="{{upload_woff2}}"\n\t\t\t           data-mediasettings=\'{"type":["font/woff","font/woff2"]}\'\n\t\t\t           data-buttontext="{{upload_woff}}">\n\t\t\t\t        {{upload_woff}}\n\t\t\t        </a>\n\t\t        </div>\n\t        </div>\n\t        \n            <div class="bf-section-container font-ttf">\n                <label for="custom-font-ttf">{{font_ttf}}</label>\n                <div class="input-section empty">\n\n                    <input type="text" value="" id="custom-font-ttf" name="fonts[ttf]" class="input font-url-input">\n                    <a class="bf-media-upload-btn bssm-button" \n                       data-mediatitle="{{upload_ttf}}"\n                       data-mediasettings=\'{"type":["font/ttf"]}\'\n                       data-buttontext="{{upload_ttf}}">\n                        {{upload_ttf}}\n                    </a>\n                </div>\n            </div>\n\n\n            <div class="bf-section-container font-svg">\n                <label for="custom-font-svg">{{font_svg}}</label>\n                <div class="input-section empty">\n\n                    <input type="text" value="" id="custom-font-svg" name="fonts[svg]" class="input font-url-input">\n                    <a class="bf-media-upload-btn bssm-button" \n                       data-mediatitle="{{upload_svg}}"\n                       data-mediasettings=\'{"type":["font/svg"]}\'\n                       data-buttontext="{{upload_svg}}">\n                        {{upload_svg}}\n                    </a>\n                </div>\n            </div>\n\n\n            <div class="bf-section-container font-eot">\n                <label for="custom-font-eot">{{font_eot}}</label>\n\n                <div class="input-section empty">\n\n                    <input type="text" value="" id="custom-font-eot" name="fonts[eot]" class="input font-url-input">\n                    <a class="bf-media-upload-btn bssm-button" \n                       data-mediatitle="{{upload_eot}}"\n                       data-mediasettings=\'{"type":["font/eot"]}\'\n                       data-buttontext="{{upload_eot}}">\n                        {{upload_eot}}\n                    </a>\n                </div>\n\n            </div>\n\n\t        <div class="bf-section-container font-otf">\n\t\t        <label for="custom-font-otf">{{font_otf}}</label>\n\n\t\t        <div class="input-section empty">\n\n\t\t\t        <input type="text" value="" id="custom-font-otf" name="fonts[otf]" class="input font-url-input">\n\t\t\t        <a class="bf-media-upload-btn bssm-button"\n\t\t\t           data-mediatitle="{{upload_otf}}"\n\t\t\t           data-mediasettings=\'{"type":["font/otf"]}\'\n\t\t\t           data-buttontext="{{upload_otf}}">\n\t\t\t\t        {{upload_otf}}\n\t\t\t        </a>\n\t\t        </div>\n\n\t        </div>\n        </div>\n\n        {{{bs_buttons}}}\n    </form>\n</div>');
                $.bs_modal({
                    styles: {
                        container: 'max-width:555px'
                    },
                    template: 'upload-font',
                    content: $.extend(mainModal.options.content, {
                        header: 'Upload Custom Font',
                        icon: 'fa-upload'
                    }),
                    buttons: {
                        add_font: {
                            label: better_fonts_manager_loc.labels.add_font,
                            type: 'primary',
                            btn_classes: 'bssm-button add-font-btn disabled',
                            clicked: function () {
                                /**
                                 * Handle Add Custom Font Button
                                 */

                                handleAddCustomFontBtn(this);
                            }
                        }
                    },
                    events: {

                        after_append_html: function () {
                            handleCustomFontInteractiveFields(this);
                            catchWpMediaFrameStatus(this);
                            overlayClickCloseModal(this);
                        },

                        handle_keyup: function (e, obj, _continue) {
                            /**
                             * Enter:
                             *  e.which = 27
                             */
                            if (_continue && e.which === 27 && isWpMediaFrameClosed()) {
                                wpMediaFrameClosed = false;
                                return false;
                            }

                            return _continue;
                        }
                    }
                });
            }

            function moveFontUp($fontEL) {
                $fontEL.show();
                $fontEL.prependTo($fontEL.parent());
            }


            function scrollToTop($wrapper) {
                $wrapper.animate({scrollTop: 0}, 0);
            }


            var fontLoading = function (ff) {
                    $('.bssm-preview[data-font-family="' + ff + '"]', $context).css('font-size', '0')
                },
                fontLoaded = function (ff) {
                    $('.bssm-preview[data-font-family="' + ff + '"]', $context)
                        .delay(40).queue(function (n) {
                        $(this).css('font-size', '22px').addClass('bs-animate bs-fadeInUp');
                        n();
                    })
                };

            function fetchFonts(elements) {

                var loadFonts = [],
                    modal = this;
                elements.forEach(function (el) {
                    var $font = modal.$(el);

                    var id = $font.data('item-id'),
                        type = $font.data('item-type');

                    loadFonts[type] = loadFonts[type] || [];
                    loadFonts[type].push(id);

                    $font.find('.bssm-preview')
                        .data('font-family', id)
                        .attr('data-font-family', id)
                        .css('font-family', id);


                });

                for (var fontType in loadFonts) {
                    self.loadFonts(fontType, loadFonts[fontType], fontLoading, fontLoaded);
                }
            }

            var modalObject;
            $(document).on("click", ".bf-font-selector", function () {
                $fontSelectorEl = $(this);

                var loc = $.extend({
                    header: better_fonts_manager_loc.labels.choose_font + ' {{btn}}'
                }, better_fonts_manager_loc.labels);

                modalObject = modalObject || $.bs_selector_modal({
                        id: 'font-selector-modal',
                        modalClass: 'bssm-style-1',

                        itemInnerHtml: '<div class="bssm-preview">\n    {{preview_text}}\n</div>\n<div class="bssm-info">\n    <span class="bssm-name">{{name}}</span>\n    <span class="bssm-type">{{type_label}}</span>\n    <span class="bssm-styles">{{styles}}</span>\n</div>',
                        content: loc,

                        items: fonts,
                        itemsGroupSize: 9,

                        categories: better_fonts_manager_loc.labels.filter_cats,
                        types: better_fonts_manager_loc.labels.filter_types,

                        inactivateTypes: ['google_ea_font'],

                        events: {
                            scrollIntoView: fetchFonts,

                            after_append_html: function () {
                                $context = this.bsModal.$modal;
                            },

                            item_select: function (selected, itemId) {

                                var modal = this;
                                setTimeout(function () {
                                    modal.bsModal.close_modal();
                                }, autoCloseDelay);

                            },
                            modal_closed: function () {
                                var selected = this.getSelectedItem();
                                if (!selected) {
                                    return;
                                }

                                var selectedElement = selected[0],
                                    selectedId = selected[1];

                                moveFontUp(selectedElement);


                                $fontSelectorEl.parent()
                                    .find('.bf-font-family')
                                    .val(selectedId);

                                $fontSelectorEl.text(selectedId);
                                self.refresh_typography($fontSelectorEl.closest('.bf-section-container'), 'family');
                            },

                            modal_show: function () {

                                var selected = $fontSelectorEl.parent()
                                    .find('.bf-font-family')
                                    .val();

                                var $selectedFont = this.selectItem(selected);

                                if ($selectedFont.length) {

                                    this.markAsSelected($selectedFont);
                                    moveFontUp($selectedFont);
                                    scrollToTop($selectedFont.parent());

                                    fetchFonts.call(this, [$selectedFont[0]]);
                                }

                            },
                        },
                    }, {
                        buttons: {
                            upload_font: {
                                label: better_fonts_manager_loc.labels.upload_font,
                                type: 'primary',
                                icon: 'upload',
                                btn_classes: 'bssm-button',
                                clicked: function () {
                                    openCustomFontModal(this, modalObject);
                                }
                            }
                        },
                        events: {

                            prepare_html: function (el, options, templateName) {

                                this.options.content.header =
                                    this.options.content.header.replace('{{btn}}', this.generate_buttons());
                            }
                        },

                        initialZIndex: 15000
                    });

                modalObject.show();
            });
        },

        /**
         * Setup Fonts Manager Panel
         ******************************************/
        setup_panel_fonts_manager: function (context) {

            // change all default fields font id
            $('.bf-section[data-id=custom_fonts] .bf-repeater-item', context).each(function (i) {

                var text = $(this).find('.better-custom-fonts-id input').val();

                text = text.replace('%i%', i + 1);

                $(this).find('.better-custom-fonts-id input').val(text);
            });

            // change new fonts id
            $('.bf-section[data-id=custom_fonts]', context).on('repeater_item_added', function () {

                var count = $(this).find('.bf-repeater-items-container').find('>*').size();

                var text = $(this).find('.bf-repeater-item:last-child .better-custom-fonts-id input').val();

                text = text.replace('%i%', count);

                $(this).find('.bf-repeater-item:last-child .better-custom-fonts-id input').val(text);
            });

        },


        /**
         * Setup Typography Field
         ******************************************/
        setup_field_typography: function (context) {

            // Init preview in page load
            $('.bf-section-typography-option', context).each(function () {
                Better_Fonts_Manager.refresh_typography($(this).closest(".bf-section-container"), 'first-time');
            });

            if (Object.keys(Better_Fonts_Manager.load_google_fonts).length > 0) {
                WebFont.load({
                    google: {
                        families: Object.keys(Better_Fonts_Manager.load_google_fonts).map(function (key) {
                            return Better_Fonts_Manager.load_google_fonts[key]
                        })
                    }
                });
            }

            if (Object.keys(Better_Fonts_Manager.load_custom_fonts).length > 0) {
                $.each(Better_Fonts_Manager.load_custom_fonts, function (key, value) {
                    WebFont.load({
                        custom: value
                    });
                });
            }

            if (Object.keys(Better_Fonts_Manager.load_google_ea_fonts).length > 0) {
                $.each(Better_Fonts_Manager.load_google_ea_fonts, function (key, value) {
                    WebFont.load({
                        custom: value
                    });
                });
            }

            if (Object.keys(Better_Fonts_Manager.load_theme_fonts).length > 0) {
                $.each(Better_Fonts_Manager.load_theme_fonts, function (key, value) {
                    WebFont.load({
                        custom: value
                    });
                });
            }

            // Prepare active field in page load
            $('.bf-section-typography-option .typo-enable-container input[type=hidden]', context).each(function () {

                $(this).closest(".bf-section-typography-option").addClass('have-enable-field');

                if ($(this).attr("value") === '1') {
                    $(this).closest(".bf-section-typography-option").addClass('enable-field');
                } else {
                    $(this).closest(".bf-section-typography-option").addClass('disable-field');
                }

            });

            // Active field on change
            $(".bf-section-typography-option .typo-enable-container .cb-enable", context).click(function () {

                $(this).closest(".bf-section-typography-option").addClass('enable-field').removeClass('disable-field');

            });

            $(".bf-section-typography-option .typo-enable-container .cb-disable", context).click(function () {
                $(this).closest(".bf-section-typography-option").addClass('disable-field').removeClass('enable-field');
            });

            // When Font Variant Changes
            $('.bf-section-container .font-variants', context).on('change', function (evt, params) {
                Better_Fonts_Manager.refresh_typography($(this).closest(".bf-section-container"), 'variant');
            });

            // When Font Size Changes
            $('.bf-section-container .font-size', context).on('change', function (evt, params) {
                Better_Fonts_Manager.refresh_typography($(this).closest(".bf-section-container"), 'size');
            });

            // When Line Height Changes
            $('.bf-section-container .line-height', context).on('change', function (evt, params) {
                Better_Fonts_Manager.refresh_typography($(this).closest(".bf-section-container"), 'height');
            });

            // When Letter Spacing Changes
            $('.bf-section-container .letter-spacing', context).on('change', function (evt, params) {
                Better_Fonts_Manager.refresh_typography($(this).closest(".bf-section-container"), 'letter-spacing');
            });

            // When Align Changes
            $(' .bf-section-container .text-align-container select', context).on('change', function (evt, params) {
                Better_Fonts_Manager.refresh_typography($(this).closest(".bf-section-container"), 'align');
            });

            // When Color Changes
            $(' .bf-section-container .text-color-container .bf-color-picker', context).on('change', function (evt, params) {
                Better_Fonts_Manager.refresh_typography($(this).closest(".bf-section-container"), 'color');
            });

            // When Transform Changes
            $(' .bf-section-container .text-transform', context).on('change', function (evt, params) {
                Better_Fonts_Manager.refresh_typography($(this).closest(".bf-section-container"), 'transform');
            });


            // Preview Tab
            $('.typography-preview .preview-tab .tab', context).on('click', function () {

                if ($(this).hasClass('current')) {
                    return false;
                } else {

                    $(this).closest('.preview-tab').find('.current').removeClass('current');
                    $(this).closest('.typography-preview').find('.preview-text.current').removeClass('current');

                    $(this).addClass('current');

                    $(this).closest('.typography-preview').find('.preview-text.' + $(this).data('tab')).addClass('current');
                }

            });

        },

        // Used for refreshing typography preview
        refresh_typography_field: function ($parent, type, _css, first_time) {

            switch (type) {
                case  'size':
                    _css.fontSize = $parent.find('.font-size').val() + 'px';
                    break;

                case 'height':
                    if ($parent.find('.line-height').val() != '')
                        _css.lineHeight = $parent.find('.line-height').val() + 'px';
                    else
                        delete _css.lineHeight;
                    break;

                case 'letter-spacing':
                    if ($parent.find('.letter-spacing').val() != '')
                        _css.letterSpacing = $parent.find('.letter-spacing').val();
                    else
                        delete _css.letterSpacing;
                    break;

                case 'align':
                    _css.textAlign = $parent.find('.text-align-container select option:selected').val();
                    break;

                case 'color':
                    _css.color = $parent.find('.text-color-container .bf-color-picker').val();
                    break;

                case 'transform':
                    _css.textTransform = $parent.find('.text-transform').val();
                    break;

                case 'family':
                    _css.fontFamily = "'" + this.getSelectedFontId($parent) + "', sans-serif";
                    break;

                case 'variant':
                    var variant = $parent.find('.font-variants option:selected').val();

                    if (typeof variant == 'undefined')
                        break;

                    if (variant.match(/([a-zA-Z].*)/i) != null) {
                        var style = variant.match(/([a-zA-Z].*)/i);
                        if (style[0] == 'regular')
                            _css.fontStyle = 'normal';
                        else
                            _css.fontStyle = style[0];
                    } else {
                        delete _css.fontStyle;
                    }

                    if (variant.match(/\d*(\s*)/i) != null) {
                        var size = variant.match(/\d*(\s*)/i);
                        _css.fontWeight = size[0];
                    } else {
                        delete _css.fontWeight;
                    }

                    break;

                case 'load-font':


                    var selected_font_id = this.getSelectedFontId($parent),
                        selected_font = Better_Fonts_Manager.get_font(selected_font_id),
                        selected_variant = $parent.find('.font-variants option:selected').val();

                    switch (selected_font.type) {

                        case 'google-font':

                            if (first_time == 'first-time') {
                                Better_Fonts_Manager.load_google_fonts[selected_font_id + ':' + selected_variant] = selected_font_id + ':' + selected_variant;
                            } else {
                                WebFont.load({
                                    google: {
                                        families: [selected_font_id + ':' + selected_variant]
                                    }
                                });
                            }
                            _css.fontFamily = "'" + selected_font_id + "', sans-serif";
                            break;

                        case 'google-ea-font':

                            _css.fontFamily = "'" + selected_font_id + "', sans-serif";

                            if (first_time == 'first-time') {
                                Better_Fonts_Manager.load_google_ea_fonts[selected_font_id] = {
                                    families: [selected_font_id],
                                    urls: [better_fonts_manager_loc.admin_fonts_css_url + '&' + 'google_ea_font_id=' + selected_font_id]
                                };
                            } else {
                                if (typeof Better_Fonts_Manager.load_google_ea_fonts[selected_font_id] == "undefined") {
                                    WebFont.load({
                                        custom: {
                                            families: [selected_font_id],
                                            urls: [better_fonts_manager_loc.admin_fonts_css_url + '&' + 'google_ea_font_id=' + selected_font_id]
                                        }
                                    });
                                    Better_Fonts_Manager.load_google_ea_fonts[selected_font_id] = {
                                        families: [selected_font_id],
                                        urls: [better_fonts_manager_loc.admin_fonts_css_url + '&' + 'google_ea_font_id=' + selected_font_id]
                                    };
                                }
                            }

                            break;

                        case 'custom-font':

                            _css.fontFamily = "'" + selected_font_id + "', sans-serif";

                            if (first_time == 'first-time') {
                                Better_Fonts_Manager.load_custom_fonts[selected_font_id] = {
                                    families: [selected_font_id],
                                    urls: [better_fonts_manager_loc.admin_fonts_css_url + '&' + 'custom_font_id=' + selected_font_id]
                                };
                            } else {
                                if (typeof Better_Fonts_Manager.load_custom_fonts[selected_font_id] == "undefined") {
                                    WebFont.load({
                                        custom: {
                                            families: [selected_font_id],
                                            urls: [better_fonts_manager_loc.admin_fonts_css_url + '&' + 'custom_font_id=' + selected_font_id]
                                        }
                                    });
                                    Better_Fonts_Manager.load_custom_fonts[selected_font_id] = {
                                        families: [selected_font_id],
                                        urls: [better_fonts_manager_loc.admin_fonts_css_url + '&' + 'custom_font_id=' + selected_font_id]
                                    };
                                }
                            }

                            break;

                        case 'theme-font':

                            _css.fontFamily = "'" + selected_font_id + "', sans-serif";

                            if (first_time == 'first-time') {
                                Better_Fonts_Manager.load_theme_fonts[selected_font_id] = {
                                    families: [selected_font_id],
                                    urls: [better_fonts_manager_loc.admin_fonts_css_url + '&' + 'theme_font_id=' + selected_font_id]
                                };
                            } else {
                                if (typeof Better_Fonts_Manager.load_theme_fonts[selected_font_id] == "undefined") {
                                    WebFont.load({
                                        custom: {
                                            families: [selected_font_id],
                                            urls: [better_fonts_manager_loc.admin_fonts_css_url + '&' + 'theme_font_id=' + selected_font_id]
                                        }
                                    });
                                    Better_Fonts_Manager.load_theme_fonts[selected_font_id] = {
                                        families: [selected_font_id],
                                        urls: [better_fonts_manager_loc.admin_fonts_css_url + '&' + 'theme_font_id=' + selected_font_id]
                                    };
                                }
                            }


                            break;

                        case 'font-stack':

                            _css.fontFamily = "'" + selected_font_id + "', sans-serif";

                            break;

                    }

            }
            return _css;

        },

        getSelectedFontId: function ($context) {
            return $('.bf-font-family', $context).val()
        },

        // Used for refreshing all styles of typography field
        refresh_typography: function ($parent, type) {
            type = typeof type !== 'undefined' ? type : 'all';


            var $preview = $parent.find('.typography-preview .preview-text');

            var _css = $preview.css([
                "fontSize", "lineHeight", "textAlign", "fontFamily", "fontStyle", "fontWeight", "textTransform", "color", "letterSpacing"
            ]);

            switch (type) {

                case 'size':
                    _css = Better_Fonts_Manager.refresh_typography_field($parent, 'size', _css);
                    break;

                case 'height':
                    _css = Better_Fonts_Manager.refresh_typography_field($parent, 'height', _css);
                    break;

                case 'letter-spacing':
                    _css = Better_Fonts_Manager.refresh_typography_field($parent, 'letter-spacing', _css);
                    break;

                case 'transform':
                    _css = Better_Fonts_Manager.refresh_typography_field($parent, 'transform', _css);
                    break;

                case 'align':
                    _css = Better_Fonts_Manager.refresh_typography_field($parent, 'align', _css);
                    break;

                case 'color':
                    _css = Better_Fonts_Manager.refresh_typography_field($parent, 'color', _css);
                    break;

                case 'variant':

                    _css = Better_Fonts_Manager.refresh_typography_field($parent, 'variant', _css);

                    var selected_font_id = this.getSelectedFontId($parent),
                        selected_font = Better_Fonts_Manager.get_font(selected_font_id),
                        selected_variant = $parent.find('.font-variants option:selected').val();

                    if (selected_variant == 'regular')
                        selected_variant = '';
                    else
                        selected_variant = ':' + selected_variant;

                    switch (selected_font.type) {

                        case 'google-font':

                            // load new font
                            WebFont.load({
                                google: {
                                    families: [selected_font_id + selected_variant]
                                }
                            });

                            _css.fontFamily = "'" + selected_font_id + "', sans-serif";

                            break;

                        case 'theme-font':
                        case 'custom-font':
                        case 'font-stack':

                            _css.fontFamily = "'" + selected_font_id + "', sans-serif";

                            break;

                    }

                    break;

                case 'family':

                    var selected_font_id = this.getSelectedFontId($parent),
                        selected_font = Better_Fonts_Manager.get_font(selected_font_id),
                        selected_font_variants = Better_Fonts_Manager.get_font_variants(selected_font),
                        selected_font_subsets = Better_Fonts_Manager.get_font_subsets(selected_font);

                    // load and adds variants
                    $parent.find('.font-variants option').remove();
                    var selected = false,
                        _selected = '';

                    // generate variant options
                    $.each(selected_font_variants, function (index, element) {

                        if (element['id'] == '400' || element['id'] == 'regular') {
                            selected = element['id'];
                        }

                        $parent.find('.font-variants').append('<option value="' + element['id'] + '" ' + ( element['id'] == selected ? ' selected' : '' ) + '>' + element['name'] + '</option>');

                    });

                    // select first if 400 is not available in font variants
                    if (selected == false)
                        $parent.find('.font-variants option:first-child').attr('selected', 'selected');

                    // load and adds subsets
                    $parent.find('.font-subsets option').remove();

                    // generate subset options
                    $.each(selected_font_subsets, function (index, element) {

                        // select latin as default subset
                        if (element['id'] == 'latin' || element['id'] == 'unknown') {
                            $parent.find('.font-subsets').append('<option value="' + element['id'] + '" selected>' + element['name'] + '</option>');
                        }
                        else {
                            $parent.find('.font-subsets').append('<option value="' + element['id'] + '">' + element['name'] + '</option>');
                        }

                    });

                    _css = Better_Fonts_Manager.refresh_typography_field($parent, 'load-font', _css);

                    _css = Better_Fonts_Manager.refresh_typography_field($parent, 'variant', _css);

                    _css = Better_Fonts_Manager.refresh_typography_field($parent, 'family', _css);

                    break;


                case 'first-time':

                    $parent.find('.load-preview-texts').remove();

                    _css = Better_Fonts_Manager.refresh_typography_field($parent, 'load-font', _css, 'first-time');

                    _css = Better_Fonts_Manager.refresh_typography_field($parent, 'family', _css);

                    _css = Better_Fonts_Manager.refresh_typography_field($parent, 'size', _css);

                    _css = Better_Fonts_Manager.refresh_typography_field($parent, 'height', _css);

                    _css = Better_Fonts_Manager.refresh_typography_field($parent, 'letter-spacing', _css);

                    _css = Better_Fonts_Manager.refresh_typography_field($parent, 'transform', _css);

                    _css = Better_Fonts_Manager.refresh_typography_field($parent, 'align', _css);

                    _css = Better_Fonts_Manager.refresh_typography_field($parent, 'variant', _css);

                    $parent.find('.typography-preview').css('display', 'block');

            }

            delete _css.lineHeight;

            $preview.attr('style', '');
            $preview.css(_css);
        },


        // Used for getting font information's
        get_font: function (font_id) {

            // Custom Fonts
            if (typeof better_fonts_manager_loc.fonts.theme_fonts[font_id] != "undefined") {

                return better_fonts_manager_loc.fonts.theme_fonts[font_id];

            }// Custom Fonts
            else if (typeof better_fonts_manager_loc.fonts.font_stacks[font_id] != "undefined") {

                return better_fonts_manager_loc.fonts.font_stacks[font_id];

            }
            // Font Stacks
            else if (typeof better_fonts_manager_loc.fonts.custom_fonts[font_id] != "undefined") {

                return better_fonts_manager_loc.fonts.custom_fonts[font_id];

            }
            // Google Fonts
            else if (typeof better_fonts_manager_loc.fonts.google_fonts[font_id] != "undefined") {

                return better_fonts_manager_loc.fonts.google_fonts[font_id];

            }
            // Google EA Fonts
            else if (typeof better_fonts_manager_loc.fonts.google_ea_fonts[font_id] != "undefined") {

                return better_fonts_manager_loc.fonts.google_ea_fonts[font_id];

            }

            return false;
        },


        // full list of default variants array
        get_default_variants: function () {

            return [
                {
                    "id": "100",
                    "name": better_fonts_manager_loc.texts.variant_100
                },

                {
                    "id": "300",
                    "name": better_fonts_manager_loc.texts.variant_300
                },
                {
                    "id": "400",
                    "name": better_fonts_manager_loc.texts.variant_400
                },
                {
                    "id": "500",
                    "name": better_fonts_manager_loc.texts.variant_500
                },
                {
                    "id": "700",
                    "name": better_fonts_manager_loc.texts.variant_700
                },
                {
                    "id": "900",
                    "name": better_fonts_manager_loc.texts.variant_900
                },
                {
                    "id": "100italic",
                    "name": better_fonts_manager_loc.texts.variant_100italic
                },
                {
                    "id": "300italic",
                    "name": better_fonts_manager_loc.texts.variant_300italic
                },
                {
                    "id": "400italic",
                    "name": better_fonts_manager_loc.texts.variant_400italic
                },
                {
                    "id": "500italic",
                    "name": better_fonts_manager_loc.texts.variant_500italic
                },

                {
                    "id": "700italic",
                    "name": better_fonts_manager_loc.texts.variant_700italic
                },
                {
                    "id": "900italic",
                    "name": better_fonts_manager_loc.texts.variant_900italic
                }
            ];

        },


        // Used for font variants
        get_font_variants: function (font) {

            // load font if font name is input
            if (typeof font == 'string') {

                font = Better_Fonts_Manager.get_font(font);

                if (font == false) {

                    return Better_Fonts_Manager.get_default_variants();
                }

            }

            switch (font.type) {

                case 'google-ea-font':
                case 'google-font':

                    return font.variants;
                    break;

                case 'theme-font':
                case 'font-stack':
                case 'custom-font':

                    return Better_Fonts_Manager.get_default_variants();

                    break;

            }

            return false;

        },


        // Used for font variants
        get_font_subsets: function (font) {

            // load font if font name is input
            if (typeof font == 'string') {

                font = Better_Fonts_Manager.get_font(font);

                if (font == false) {

                    return [
                        {
                            "id": "unknown",
                            "name": better_fonts_manager_loc.texts.subset_unknown
                        }
                    ];
                }

            }

            switch (font.type) {

                case 'google-font':

                    return font.subsets;
                    break;

                case 'google-ea-font':
                case 'theme-font':
                case 'font-stack':
                case 'custom-font':

                    return [
                        {
                            "id": "unknown",
                            "name": better_fonts_manager_loc.texts.subset_unknown
                        }
                    ];

                    break;

            }

            return false;

        }

    };

})(jQuery);

// load when ready
jQuery(function ($) {
    Better_Fonts_Manager.init();
});libs/better-framework/assets/js/color-picker.js000064400000033400151214002560015616 0ustar00
/**!
 * wp-color-picker-alpha
 *
 * Overwrite Automattic Iris for enabled Alpha Channel in wpColorPicker
 * Only run in input and is defined data alpha in true
 *
 * Version: 1.2.2
 * https://github.com/23r9i0/wp-color-picker-alpha
 * Copyright (c) 2015 Sergio P.A. (23r9i0).
 * Licensed under the GPLv2 license.
 */

( function ($) {

    // Variable for some backgrounds ( grid )
    var image = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAAHnlligAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAHJJREFUeNpi+P///4EDBxiAGMgCCCAGFB5AADGCRBgYDh48CCRZIJS9vT2QBAggFBkmBiSAogxFBiCAoHogAKIKAlBUYTELAiAmEtABEECk20G6BOmuIl0CIMBQ/IEMkO0myiSSraaaBhZcbkUOs0HuBwDplz5uFJ3Z4gAAAABJRU5ErkJggg==',
        // html stuff for wpColorPicker copy of the original color-picker.js
        _aefore = '<a tabindex="0" class="wp-color-result" />',
        _after = '<div class="wp-picker-holder" />',
        _wrap = '<div class="wp-picker-container" />',
        _button = '<input type="button" class="button button-small" />';

    /**
     * Overwrite Color
     * for enable support rbga
     */
    Color.fn.toString = function () {
        if (this._alpha < 1)
            return this.toCSS('rgba', this._alpha).replace(/\s+/g, '');

        var hex = parseInt(this._color, 10).toString(16);

        if (this.error)
            return '';

        if (hex.length < 6)
            hex = ( '00000' + hex ).substr(-6);

        return '#' + hex;
    };

    /**
     * Overwrite wpColorPicker
     */
    $.widget('wp.bsWpColorPicker', $.wp.wpColorPicker, {
        _create: function () {
            // bail early for unsupported Iris.
            if (!$.support.iris)
                return;
            var self = this;

            self.toggler = self.element;
            self.element.wrap(_wrap);
            self.wrap = self.element.closest('.bs-color-picker-wrapper');
            var el = self.wrap.find('.bs-color-picker-value').addClass('wp-color-picker');
            self.element = el;
            self.win = $(window);

            $.extend(self.options, el.data());
            self.options.hide = false;
            self.options.autoOpen = false;

            // keep close bound so it can be attached to a body listener
            self.close = $.proxy(self.close, self);

            self.initialValue = el.val();

            // Set up HTML structure, hide things
            self.pickerContainer = $(_after).insertAfter(el);
            self.button = $(_button);

            if (self.options.defaultColor) {
                self.button.addClass('wp-picker-default').val(wpColorPickerL10n.defaultString);
            } else {
                self.button.addClass('wp-picker-clear').val(wpColorPickerL10n.clear);
            }

            el.appendTo(self.pickerContainer).wrap('<span class="wp-picker-input-wrap" />').after(self.button);

            el.iris({
                target: self.pickerContainer,
                hide: self.options.hide,
                width: self.options.width,
                mode: self.options.mode,
                palettes: self.options.palettes,
                change: function (event, ui) {
                    if (self.options.alpha) {
                        self.toggler.css({'background-image': 'url(' + image + ')'}).html('<span />');
                        self.toggler.find('span').css({
                            'width': '100%',
                            'height': '100%',
                            'position': 'absolute',
                            'top': 0,
                            'left': 0,
                            'border-top-left-radius': '3px',
                            'border-bottom-left-radius': '3px',
                            'background': ui.color.toString()
                        });
                    } else {
                        self.toggler.css({backgroundColor: ui.color.toString()});
                    }

                    // Check for a custom cb
                    if ($.isFunction(self.options.change))
                        self.options.change.call(this, event, ui);
                }
            });

            el.val(self.initialValue);
            self._addListeners();
            if(! self.options.hide ) {
                self.toggler.addClass('wp-picker-open');
                self.wrap.addClass('wp-picker-active')
                    .addClass('bs-color-picker-ready');
                this.element.css('display', 'inline-block');
                $( 'body' ).trigger( 'click.wpcolorpicker' ).on( 'click.wpcolorpicker', self.close );
            }
        },
        _init:function() {
            this.element.focus();
            //TODO: remove following throw! This is shame but jQUI works unusual! if we don't throw ER it will not work properly :)) hahaa
            throw '';
        },
        _addListeners: function () {
            var self = this;

            // prevent any clicks inside this widget from leaking to the top and closing it
            self.wrap.on('click.wpcolorpicker', function (e) {
                e.stopPropagation();
            });
            self.pickerContainer.on('click.wpcolorpicker', function (e) {
                e.stopPropagation();
            });

            self.toggler.on('click', function (el) {
                if (self.toggler.hasClass('wp-picker-open')) {
                    self.close();
                } else {
                    self.open();
                }
            });

            self.element.on('change', function (event) {
                // Empty or Error = clear
                if ($(this).val() === '' || self.element.hasClass('iris-error')) {
                    if (self.options.alpha) {
                        self.toggler.removeAttr('style');
                        self.toggler.find('span').css('backgroundColor', '');
                    } else {
                        self.toggler.css('backgroundColor', '');
                    }

                    // fire clear callback if we have one
                    if ($.isFunction(self.options.clear))
                        self.options.clear.call(this, event);
                }
            });

            // open a keyboard-focused closed picker with space or enter
            self.element.on('keyup', function (event) {
                if (event.keyCode === 13 || event.keyCode === 32) {
                    event.preventDefault();
                    self.toggler.trigger('click').next().focus();
                }
            });

            self.button.on('click', function (event) {
                if ($(this).hasClass('wp-picker-clear')) {
                    self.element.val('');
                    if (self.options.alpha) {
                        self.toggler.removeAttr('style');
                        self.toggler.find('span').css('backgroundColor', '');
                    } else {
                        self.toggler.css('backgroundColor', '');
                    }

                    if ($.isFunction(self.options.clear))
                        self.options.clear.call(this, event);

                } else if ($(this).hasClass('wp-picker-default')) {
                    self.element.val(self.options.defaultColor).change();
                }
            });
        },

        open: function() {
            this.element.css('display','inline-block').iris( 'toggle' ).focus();
            this.button.removeClass( 'hidden' );
            this.wrap.addClass( 'wp-picker-active' );
            this.toggler.addClass( 'wp-picker-open' );
            $( 'body' ).trigger( 'click.wpcolorpicker' ).on( 'click.wpcolorpicker', this.close );
        }
    });

    /**
     * Overwrite iris
     */
    $.widget('a8c.iris', $.a8c.iris, {
        _create: function () {
            this._super();

            // Global option for check is mode rbga is enabled
            this.options.alpha = true;

            if (typeof this.options.alpha !== 'undefined' && this.options.alpha) {
                var self = this,
                    el = self.element,
                    _html = '<div class="iris-strip iris-slider iris-alpha-slider"><div class="iris-slider-offset iris-slider-offset-alpha"></div></div>',
                    aContainer = $(_html).appendTo(self.picker.find('.iris-picker-inner')),
                    aSlider = aContainer.find('.iris-slider-offset-alpha'),
                    controls = {
                        aContainer: aContainer,
                        aSlider: aSlider
                    };

                if (typeof el.data('custom-width') !== 'undefined') {
                    self.options.customWidth = parseInt(el.data('custom-width')) || 0;
                } else {
                    self.options.customWidth = 100;
                }

                // Set default width for input reset
                self.options.defaultWidth = el.width();

                // Push new controls
                $.each(controls, function (k, v) {
                    self.controls[ k ] = v;
                });

                // Change size strip and add margin for sliders
                self.controls.square.css({'margin-right': '0'});
                var emptyWidth = ( self.picker.width() - self.controls.square.width() - 20 ),
                    stripsMargin = ( emptyWidth / 6 ),
                    stripsWidth = Math.ceil( ( emptyWidth / 2 ) - stripsMargin );

                $.each([ 'aContainer', 'strip' ], function (k, v) {
                    self.controls[ v ].width(stripsWidth).css({'margin-left': Math.floor(stripsMargin) + 'px'});
                });


                // Add new slider
                self._initControls();

                // For updated widget
                self._change_alpha();
            }
        },
        _initControls: function () {
            this._super();

            if (this.options.alpha) {
                var self = this,
                    controls = self.controls;

                controls.aSlider.slider({
                    orientation: 'vertical',
                    min: 0,
                    max: 100,
                    step: 1,
                    value: parseInt(self._color._alpha * 100),
                    slide: function (event, ui) {
                        // Update alpha value
                        self._color._alpha = parseFloat(ui.value / 100);
                        self._change.apply(self, arguments);
                    }
                });
            }
        },
        _change_alpha: function() {
            var self = this,
                el = self.element;

            if (this.options.alpha) {
                var controls = self.controls,
                    alpha = parseInt(self._color._alpha * 100),
                    color = self._color.toRgb(),
                    gradient = [
                        'rgb(' + color.r + ',' + color.g + ',' + color.b + ') 0%',
                        'rgba(' + color.r + ',' + color.g + ',' + color.b + ', 0) 100%'
                    ],
                    defaultWidth = self.options.defaultWidth,
                    customWidth = self.options.customWidth,
                    target = self.picker.closest('.wp-picker-container').find('.wp-color-result');

                // Generate background slider alpha, only for CSS3 old browser fuck!! :)
                controls.aContainer.css({'background': 'linear-gradient(to bottom, ' + gradient.join(', ') + '), url(' + image + ')'});

                if (target.hasClass('wp-picker-open')) {
                    // Update alpha value
                    controls.aSlider.slider('value', alpha);

                    /**
                     * Disabled change opacity in default slider Saturation ( only is alpha enabled )
                     * and change input width for view all value
                     */
                    if (self._color._alpha < 1) {
                        controls.strip.attr('style', controls.strip.attr('style').replace(/rgba\(([0-9]+,)(\s+)?([0-9]+,)(\s+)?([0-9]+)(,(\s+)?[0-9\.]+)\)/g, 'rgb($1$3$5)'));
                        el.width(parseInt(defaultWidth + customWidth));
                    } else {
                        el.width(defaultWidth);
                    }
                }
            }

            var reset = el.data('reset-alpha') || false;

            if (reset) {
                self.picker.find('.iris-palette-container').on('click.palette', '.iris-palette', function () {
                    self._color._alpha = 1;
                    self.active = 'external';
                    self._change();
                });
            }
        },
        _change: function () {
            this._super();

            this._change_alpha();
        },
        _addInputListeners: function (input) {
            var self = this,
                debounceTimeout = 100,
                callback = function (event) {
                    var color = new Color(input.val()),
                        val = input.val();

                    input.removeClass('iris-error');
                    // we gave a bad color
                    if (color.error) {
                        // don't error on an empty input
                        if (val !== '')
                            input.addClass('iris-error');
                    } else {
                        if (color.toString() !== self._color.toString()) {
                            // let's not do this on keyup for hex shortcodes
                            if (!( event.type === 'keyup' && val.match(/^[0-9a-fA-F]{3}$/) ))
                                self._setOption('color', color.toString());
                        }
                    }
                };

            input.on('change', callback).on('keyup', self._debounce(callback, debounceTimeout));

            // If we initialized hidden, show on first focus. The rest is up to you.
            if (self.options.hide) {
                input.on('focus', function () {
                    self.show();
                });
            }
        }
    });
}(jQuery) );


libs/better-framework/assets/js/admin-scripts.js000064400000553551151214002560016020 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */




var bf_ignore_reload_notice = false,
    Better_Framework = (function($) {
    "use strict";

    // module
    return {
        loaded: false,
        _interactive_fields_cache: {},
        _doingAjax: false,
        _cuurentAjax: false,
        radioCheckboxInitialized: false,

        init: function(){

            var $context = $(document.body);

            if(better_framework_loc.type === 'panel') {
                $context = $("#bf-panel");
            } else if(better_framework_loc.type === 'widgets') {
                $context = $("#widgets-right,body.widgets_access .widget-inside");
            }

            // Setup General fields
            this.setup_fields($context);

            this.setup_select_popup_field();

            this.handle_editor();

            this.handle_notices();

            this.error_copy();

            this.admin_notice_fix();

            this.setup_deferred_panel_fields();

            this.vc_modifications();


            switch( better_framework_loc.type ){

                // Setup Widgets
                case 'widgets':

                    // Setup fields after ajax request on widgets page
                    this.setup_widget_fields();
                    this.sort_widgets();
                    break;

                // Setup Panel
                case 'panel':

                    this.setup_panel_tabs();
                    this.panel_save_action();
                    this.panel_reset_action();
                    this.panel_sticky_header();
                    this.panel_import_export();
                    this.change_panel_data_notice();
                    break;

                // Setup Meta Boxes
                case 'metabox':
                    this.set_metabox();

                    // Metabox Filter For Post Format
                    this.metabox_filter_postformat();

                    // Metabox Fields Filter For Post Format
                    this.metabox_field_filter_postformat();

                    this.setup_fields_for_vc();

                    this.setup_interactive_fields_for_vc();

                    this.change_metabox_data_notice();

                    this.vc_editor_fix();

                    break;

                // Setup Taxonomy Meta Boxes
                case 'taxonomy':

                    this.taxonomy_page_reload_status();

                    this.set_metabox();

                    this.change_metabox_data_notice();

                    break;

                // Setup User Meta Boxes
                case 'users':

                    this.set_metabox();

                    break;

                // Setup Menus
                case 'menus':

                    this.menus_collect_fields_before_save();
                    this.init_mega_menus();
                    break;

            }


            this.pageBuilderCompatibility.init();

            $(document).trigger('bf-loaded');

            this.loaded = true;
        },

        /**
         *
         * @param {function} successCallback Callback function for success ajax response
         * @param {Object} args settings object
         * @private
         * @return {jqXHR}
         */
        _ajax: function (successCallback, data, args,failCallback) {
            var self        = this;
            self._doingAjax = true;

            var ajaxParams = $.extend(
                {
                    action: 'bf_ajax',
                    nonce: better_framework_loc.nonce,
                    panelID  : $('#bf-panel-id').val()
                },
                data
            );

            return $.ajax({
                        url: ajaxurl,
                        type: 'POST',
                        dataType: 'json',
                        data: ajaxParams,
                    })
                    .done(function (response) {

                        if (response.result && response.result.is_error) {
                            response.result.error_message += "\n\n";
                            response.result.error_message += JSON.stringify(ajaxParams);
                            console.error(response.result.error_message, response.result.error_code);
                            var modal = self._show_error(response.result.error_message, response.result.error_code),
                                $info = modal.$modal.find('.bs-pages-error-section textarea');


                            $info.height($info[ 0 ].scrollHeight);
                            modal.make_vertical_center();

                            response.status = 'error';
                        }


                        self._doingAjax = false;
                        successCallback.apply(this, arguments);
                    }).fail(function(e,code,msg) {

                    self._show_error(msg, code);

                    if(failCallback)
                        failCallback.call(this, arguments);
                });
        },

        _show_error: function (error_message, error_code) {
            var self = this,
                loc  = jQuery.extend({}, better_framework_loc.on_error);

            if (error_message && error_code) {
                loc.body = loc.display_error
                              .replace('%ERROR_CODE%', error_code)
                              .replace('%ERROR_MSG%', error_message);
            }

            return $.bs_modal({
                content: loc,

                buttons: {
                    close_modal: {
                        label: loc.button_ok,
                        type: 'primary',
                        action: 'close'
                    },
                }
            });
        },


        deferred_panel_field: function(settings) {

            var self = this;

            var config = $.extend({

                activeDeferredClass: 'bf-ajax-section',
                loadDeferredClass: 'bf-ajax-section-loaded',
                clickEventClass: '',

                allowMultipleAjax: false,

                getSectionID: function ($section) {

                    return $section.attr('id');
                },
                getSectionInner: function ($section) {
                    return $section.children('.container');
                },
                successAjaxCallback: function (res, $inner, $section, sectionID) {

                    $inner.html(res.out);

                    $(document).trigger(config.loadDeferredClass, [ $inner,$section, sectionID]);

                    $section.addClass(config.loadDeferredClass);
                },

                beforeAjaxCallback: function () {

                },

                afterAjaxCallback: function () {

                },
                errorAjaxCallback: function ($inner, $section, sectionID) {
                    $inner.html(better_framework_loc.on_error.again);
                },

                ajaxData: function ($inner, $section, sectionID) {

                    var data = {
                        reqID: 'fetch-deferred-field',
                        sectionID: sectionID
                    };

                    var objectID    = 0,
                        haveMetabox = true;

                    switch (better_framework_loc.type) {

                        case 'metabox':

                            objectID = $('#post_ID').val();
                            break;

                        case 'taxonomy':

                            objectID = $('input[name="tag_ID"]').val();

                            if(!objectID) {
                                data.taxonomy =  $('input[name="taxonomy"]').val();
                            }

                            break;

                        case 'users':

                            objectID = $('input[name="user_id"]').val();
                            break;

                        default:
                            haveMetabox = false;
                    }

                    if (haveMetabox) { // it's metabox

                        data.metabox   = true;
                        data.object_id = objectID;
                        data.type      = better_framework_loc.type;

                        var $mb         = $section.closest(".bf-metabox-wrap");
                        data.metabox_id = $mb.data('metabox-id') || $mb.data('id');
                    }

                    return data;
                },

            }, settings);


            var xhr;


            return {

                init: function () {

                    var _ = this;

                    if (config.clickEventClass) {

                        var $els = $('.' + config.activeDeferredClass + ' .' + config.clickEventClass);
                        $els.off('click.bs-deferred').on('click.bs-deferred', function () {

                            var $section = $(this).closest('.' + config.activeDeferredClass);

                            _.fire($section);
                        });
                    }

                    return _;
                },

                fire: function ($section) {

                    var _ = this;

                    if (!$section.hasClass(config.activeDeferredClass)) {
                        return;
                    }

                    if ($section.hasClass(config.loadDeferredClass)) {
                        return;
                    }

                    var $inner    = config.getSectionInner($section),
                        sectionID = config.getSectionID($section);

                    if (!$inner || !sectionID) {
                        throw new Error("invalid 'deferred panel field' config.");
                    }

                    $inner.html(better_framework_loc.loading).fadeIn(10);

                    if (!config.allowMultipleAjax && xhr) {
                        xhr.abort();
                    }

                    config.beforeAjaxCallback($inner, $section, sectionID);

                    xhr = self._ajax(function (res) {
                            var result = config.successAjaxCallback(res, $inner, $section, sectionID)
                            config.afterAjaxCallback($inner, $section, sectionID);

                            return result;
                        },
                        config.ajaxData($inner, $section, sectionID), {},
                        function () {
                            return config.errorAjaxCallback($inner, $section, sectionID)
                        }
                    );

                    return _;
                }
            };
        },

        setup_deferred_panel_fields: function() {

            var self = this;

            /**
             * Setup ajax group fields
             */

            var ajaxGroups = self.deferred_panel_field({

                activeDeferredClass: 'bf-ajax-group',
                loadDeferredClass: 'bf-ajax-group-loaded',
                clickEventClass: 'fields-group-title-container',

                allowMultipleAjax: true,

                getSectionID: function ($group) {

                    return $group.attr('id').replace(/^fields\-group\-/, '');
                },
                getSectionInner: function ($group) {
                    return $(".bf-group-inner", $group);
                },
                afterAjaxCallback: function ($inner) {
                    $inner.css('min-height', '0');
                    self.setup_deferred_panel_fields();

                    $inner.find(':input:first').trigger('force-change');

                    Better_Framework.setup_field_color_picker($inner);
                },
                beforeAjaxCallback: function ($inner) {
                    $inner.css('min-height', '100px');
                }
            }).init();

            // Auto load opened groups
            $('.bf-ajax-group.open').each(function() {
                ajaxGroups.fire($(this));
            });

            /**
             * Setup ajax tabs
             */

            var ajaxTabs = self.deferred_panel_field({

                activeDeferredClass: 'bf-ajax-tab',
                loadDeferredClass: 'bf-ajax-tab-loaded',
                clickEventClass: 'bf-tab-item-a',

                getSectionID: function ($li) {
                    return $li.data('go');
                },
                getSectionInner: function ($li) {
                    var tab_id = $li.data('go');

                    if (better_framework_loc.type === 'panel') {

                        return $('#bf-group-' + tab_id);
                    } else {

                        var $metaboxWrapper = $li.closest('.bf-metabox-wrap'),
                            metaboxID       = $metaboxWrapper.data("id");

                        return $("#bf-metabox-" + metaboxID + "-" + tab_id, $metaboxWrapper);
                    }
                },
                beforeAjaxCallback: function ($inner, $li) {

                    $inner.parent().children('.group').hide(); // Hide Active tab content
                    $inner.fadeIn(500); // Display New tab content

                    $li.closest('ul').find('.active_tab').removeClass('active_tab'); // Remove active class
                    $li.find('.bf-tab-item-a').addClass('active_tab'); // Add active class

                },
                afterAjaxCallback: function ($inner) {
                    self.init_term_select($inner);

                    self.setup_interactive_fields_for_bf($inner);
                    self.setup_deferred_panel_fields();

                    Better_Framework.setup_field_color_picker($inner);
                }
            }).init();
        },
        /**
         * Panel
         ******************************************/

        // Setup panel tabs
        setup_panel_tabs: function(){


            var self = this;

            $('#bf-main #bf-content').css( 'min-height',  $('#bf-main #bf-nav').height() + 50 );


            // TODO: Vahid shit! Refactor this

            var panelID = $('#bf-panel-id').val();

            var _bf_current_tab = $.cookie( 'bf_current_tab_of_' + panelID  );

            function bf_show_first_tab(){
                $('#bf-nav').find('li:first').find('a:first').addClass("active_tab");

                $('#bf_options_form').find( '#bf-group-' + $('#bf-nav').find('li:first').data("go") ).show(function(){
                    var elems = Array.prototype.slice.call(document.querySelectorAll('.js-switch'));
                    elems.forEach(function(html) {
                        var switchery = new Switchery(html);
                    });
                } );
            }

            if( typeof _bf_current_tab == 'undefined' ){
                bf_show_first_tab();
            }
            else
            {
                var _curret_ = $.cookie( 'bf_current_tab_of_' + panelID  );

                if($('#bf-nav').find("li[data-go='"+_curret_+"']").hasClass('bf-ajax-tab')) {
                    bf_show_first_tab();
                } else {

                    if (!$('#bf_options_form').find('#bf-group-' + _curret_).exist() || !$('#bf-nav').find("a[data-go='" + _curret_ + "']").exist()) {
                        bf_show_first_tab();
                        $.removeCookie('bf_current_tab_of_' + panelID);
                    }

                    $('#bf_options_form').find('#bf-group-' + _curret_).show();
                    $('#bf-nav').find("a[data-go='" + _curret_ + "']").addClass("active_tab");
                    if ($('#bf-nav').find("a[data-go='" + _curret_ + "']").is(".bf-tab-subitem-a")) {
                        $('#bf-nav').find("a[data-go='" + _curret_ + "']").closest(".has-children").addClass("child_active");
                    }
                }
            }

            $('#bf-nav').find('a').click( function(e){
                e.preventDefault();
                if( $(this).hasClass('active_tab') )
                    return false;

                var _this = $(this);
                var _hasNotGroup = ( ( _this.parent().hasClass('has-children') ) && ( ! $('#bf_options_form').find( '#bf-group-' + _this.data("go") ).find(">*").exist() ) );
                var _isChild = ! _this.parent().hasClass('has-children');

                if( _hasNotGroup ){
                    var _clicked = _this.siblings('ul.sub-nav').find('a:first');
                    var _target = $('#bf_options_form').find( '#bf-group-' + _clicked.data("go") );
                } else {
                    var _clicked = _this;
                    var _target = $('#bf_options_form').find( '#bf-group-' + _clicked.data("go") );
                }

                var $parent = _this.parent();

                function displayTab() {
                    $('#bf-nav').find('a').removeClass("active_tab");
                    $('#bf-nav').find('ul.sub-nav').find('a').removeClass("active_tab");
                    $('#bf-nav').find('li').removeClass("child_active");

                    $('#bf_options_form').find('>div').hide();
                    _target.fadeIn(500);

                    _clicked.addClass("active_tab");

                    if( $parent.hasClass('has-children') || $parent.parent().hasClass('sub-nav') ){
                        _clicked.closest('.has-children').addClass("child_active");
                    }

                    $('body,html').animate({
                        scrollTop: 0
                    }, 400);
                }

                function initShowOn() {

                    if( ! _this.data('show-on-initialized')) {
                        self.setup_interactive_fields_for_bf(_target);
                        _this.data('show-on-initialized',true);
                    }

                    _target.find(':input:first').trigger('force-change');
                }

                var isTabAjax = $parent.hasClass('bf-ajax-tab') &&
                                ! $parent.hasClass('bf-ajax-tab-loaded');

                if(! isTabAjax) {

                    initShowOn();
                    displayTab();
                    $.cookie( 'bf_current_tab_of_' + panelID, _clicked.data("go"), { expires: 7 });

                    return false;
                }
            });
        },
        _get_metabox_data:function() {
            return $('.bf-metabox-container').bf_serialize();
        },
        change_metabox_data_notice: function () {
            var self = this,
                default_values = this._get_metabox_data();

            $('.bf-metabox-container').on('change bf-changed', ':input', function() {
                var changed = default_values !== self._get_metabox_data();
                if( changed ) {
                    bf_ignore_reload_notice = false;
                    $(window).on('beforeunload.bs-admin', function(e) {
                        if(! bf_ignore_reload_notice)
                            return true;
                    });
                } else {
                    self.turn_refresh_notice_off();
                }
            });

            $("#post,#edittag").on('submit', function() {
                self.turn_refresh_notice_off();
            });
        },
        /**
         *
         * @private
         */
        _get_panel_data:function() {
            var _serialized = $('#bf-content').bf_serialize();

            return _serialized;
        },
        turn_refresh_notice_off: function() {
            $(window).off('beforeunload.bs-admin');
        },
        change_panel_data_notice:function() {
            var self = this,
                default_values = this._get_panel_data();

            $('#bf-content').on('change bf-changed', ':input', function() {
                var changed = default_values !== self._get_panel_data();

                $("#bf-panel .bf-options-change-notice")
                    [changed ? 'addClass' : 'removeClass' ]('bf-option-changed')
                    [changed ? 'fadeIn' : 'fadeOut' ](300);

                if( changed ) {
                    bf_ignore_reload_notice = false;
                    $(window).on('beforeunload.bs-admin', function(e) {
                        if(! bf_ignore_reload_notice)
                            return true;
                    });
                } else {
                    self.turn_refresh_notice_off();
                }
            });
        },

        taxonomy_page_reload_status: function() {
            $(document).ajaxSuccess(function (e, xhr, settings) {
                var data = $.unserialize(settings.data);
                if(data.action === 'add-tag') {
                    bf_ignore_reload_notice  = true;
                }
            });
        },
        /**
         * @see _get_panel_data
         */
        handle_editor:function($context) {
            var self = this;

            jQuery(document).ready(function($) {
                self._init_editor();
            }).on('bf-ajax-tab-loaded', function(e,target) {
                self._init_editor(target);
            }).on('tinymce-editor-init', function() {

                // Fix Bug: tinymce update textarea filed with delay
                // This event change textarea field value immediately
                tinymce.activeEditor.on('change', function() {

                    if(! this.container) {
                        return ;
                    }
                    var container = this.container.closest('.bf-section-container');

                    if(container) {
                        $("textarea.wp-editor-area",container).html(this.getContent());
                    }
                });
            });

            if($context && $context.length) {
                self._init_editor($context);
            }
        },
        _init_editor: function (context) {

            $('.bf-editor-wrapper', context).each(function() {
                var $wrapper  = $(this),
                    $editor   = $wrapper.find('.bf-editor'),
                    $textarea = $wrapper.find('.bf-editor-field'),
                    have_ace = typeof ace === "object";

                if( have_ace ) {

                    $textarea.hide();

                    $editor.css('min-height', '100px');
                    var
                        lang = $editor.data('lang'),
                        max_lines = $editor.data('max-lines'),
                        min_lines = $editor.data('min-lines'),
                        theme = $editor.data('theme'),
                        editor = ace.edit($editor[0]),
                        session = editor.getSession();

                    editor.setOptions({
                        maxLines: max_lines,
                        minLines: min_lines,
                        mode: "ace/mode/" + lang
                    });

                    if (theme)
                        editor.setTheme("ace/theme/"+theme);

                    session.setUseWorker(false);

                    editor.getSession().setValue($textarea.val());

                    session.on('change', function (e, EditSession) {
                        $textarea
                            .val(editor.getSession().getValue())
                            .trigger('bf-changed');

                        $textarea[0].dispatchEvent(new Event('input'));
                    });

                } else {
                    $editor.remove();
                    $textarea.show();
                }
            });
        },
        handle_notices: function () {
            var wrapper = '.bf-notice-wrapper';
            $(wrapper).on('click', '.bf-notice-dismiss', function () {
                var $this = $(this),
                    $wrapper = $this.closest(wrapper),
                    data = $this.data();

                $wrapper.slideUp(300);

                setTimeout( function () {
                    $wrapper.remove();
                }, 300 );

                if (data) {
                    $.ajax({
                        url: ajaxurl,
                        type: 'post',
                        data: $.extend({action: 'bf-notice-dismiss'}, data)
                    });
                }
            });
        },

        _getVar: function(varName) {

            if (!varName) {
                return;
            }

            if (varName.indexOf('.') == -1) {

                return window[ varName ];
            }

            var _v = varName.split('.');
            var current = window[ _v[ 0 ] ];
            _v     = _v.splice(1);

            var len = _v.length-1;

            for (var i = 0; i <= len; i++) {

                if(typeof current[_v[i]] !== 'object' && i !== len) {
                    return ;
                }

                current = current[_v[i]];
            }

            return current;
        },
        /**
         * Handle pre defined style modal
         */
        setup_select_popup_field: function () {

            var self = this;

            function getData() {

                var $this = $(this),
                    $section = $this.closest('.bf-section-container');

                if($section.length === 0) {
                    $section = $this;
                }

                var data = JSON.parse($section.find('.select-popup-data').text());

                if (typeof data === "undefined") {
                    return false;
                }

                var obj,
                    heading = $this.closest('.bf-section').find('.bf-heading').text();

                var modal_loc = better_framework_loc.fields.select_popup;

                if (data.texts) {
                    [
                        [ 'modal_button', 'btn_label' ],
                        [ 'modal_current', 'btn_label_active' ],
                        [ 'modal_title', 'header' ]
                    ].forEach(function (replacement) {
                        var optKey   = replacement[ 0 ],
                            modalKey = replacement[ 1 ];

                        if (data.texts[ optKey ]) {
                            modal_loc[ modalKey ] = data.texts[ optKey ];
                        }
                    });
                }
                if (modal_loc.header.indexOf('%%name%%') !== -1) {
                    modal_loc.header = modal_loc.header.replace('%%name%%', heading);
                }

                var modal2_loc = better_framework_loc.fields.select_popup_confirm;

                if (data.confirm_texts) {
                    modal2_loc = $.extend(modal2_loc, data.confirm_texts);
                }
                if (modal2_loc.header.indexOf('%%name%%') !== -1) {
                    modal2_loc.header = modal2_loc.header.replace('%%name%%', heading);
                }
                if(data.column_class) {
                    modal_loc.content_class = data.column_class;
                }

                var items = [],
                    cats  = {},
                    types = {};

                var opts = data.options;
                for (var id in opts) {
                    obj    = opts[ id ];
                    obj.id = id;

                    if (typeof obj.cat !== "undefined") {

                        obj.cat.forEach(function(cat) {
                            cats[ cat ] = modal_loc.categories[ cat ] || cat;
                        });
                    }

                    if (typeof obj.type !== "undefined") {

                        obj.type.forEach(function(type) {
                            types[ type ] = modal_loc.types[ type ] || type;
                        });
                    }

                    var badges = [];
                    if(obj.badges) {
                        obj.badges.forEach(function (badge) {
                            var badgeObj   = {};
                            badgeObj.badge = badge;

                            badges.push(badgeObj);
                        });
                    }
                    obj.badges = badges;

                    items.push(obj);
                }

                //  [ Modal data, General data, Main Modal Localization, Confirm Modal Localization ]
                return [
                    {
                        items: items,
                        cats: cats,
                        types: types,
                    },
                    data,
                    modal_loc,
                    modal2_loc
                ];
            }

            $(document.body).on('click', '.better-select-popup,.select-popup-field', function (e) {

                e.preventDefault();

                var initialZIndex = 0,
                    $select    = $(this),
                    activeItem = $select.find('input.select-value').val(),
                    data       = getData.call(this);

                // FIX nested bs-modal z-index issue
                var $parentModal = $select.closest('.bs-modal');

                if($parentModal.length) {
                    initialZIndex = parseInt($parentModal.css('z-index'));
                } else {

                    initialZIndex =1.3e5;
                }
                if (data[ 0 ]) {

                    $.bs_selector_modal({
                        bsModal: {
                            destroyHtml: true,
                            show: true
                        },

                        id: 'better-select-popup-modal',
                        modalClass: 'pds-modal',

                        itemInnerHtml: '<div class="bf-item-container">\n\n    <figure>\n        <img src="{{img}}"\n             alt="{{label}}"\n             class="bs-style-thumbnail" data-current-image="{{current_img}}">\n         <div class="bf-item-badges">\n\n         {{#badges}}\n        <div class="bf-item-badge">\n            {{badge}}\n        </div>\n         {{/badges}}\n         </div>\n    </figure>\n\n    <footer class="bf-item-footer bf-clearfix">\n        <span class="bf-item-title">\n            {{label}}\n        </span>\n\n        <div class="bf-item-buttons">\n            <span class="bf-toggle-item-status">\n                <a href="#" target="_blank"\n                   class="bf-btn-secondary bf-btn-dark">{{btn_label}}</a>\n            </span>\n        </div>\n    </footer>\n</div>',

                        content: data[ 2 ],

                        items: data[ 0 ].items,

                        categories: data[ 0 ].cats,
                        types: data[ 0 ].types,
                        itemsGroupSize: 9,

                        fuse: {
                            keys: [ 'label' ]
                        },

                        events: {
                            scrollIntoView: function (elements) {
                                var modal = this;

                                elements.forEach(function (el) {
                                    modal.$(el).find('.bf-item-container').addClass('bs-animate bs-fadeInUp');
                                });
                            },

                            after_append_html: function () {
                                var modal = this;

                                function getBody() {
                                    var out = '';

                                    if (data[ 3 ].list_items) {

                                        out += '<div class="pdsm-notice-list"><ul class="styled">';

                                        data[ 3 ].list_items.forEach(function (lbl) {
                                            out += '<li>' + lbl + '</li>';
                                        });

                                        out += '</ul></div>';
                                    }

                                    if (data[ 3 ].notice) {

                                        out += '<div class="pdsm-notice">';
                                        out += data[ 3 ].notice;
                                        out += '</div>';
                                    }

                                    return out;
                                }

                                function setItemAsActive($item) {

                                    $item.addClass('active');
                                    var $btn = $(".bf-toggle-item-status a", $item);

                                    $btn.attr('class', 'bf-btn-primary disabled').html(data[ 2 ].btn_label_active);
                                    $btn.parent().removeClass('bf-toggle-item-status');
                                    $btn.on('click', function (e) {
                                        e.preventDefault();
                                    });
                                }

                                function setValue(id,label) {

                                    var $input = $select.find('input.select-value');
                                    $input.val(id).change();
                                    $select.find('.active-item-label').html(label);

                                    $input[0].dispatchEvent(new Event('input'));

                                }
                                function setImage(src) {
                                    $select.find('.select-popup-selected-image img').attr('src', src);
                                }

                                setItemAsActive(modal.selectItem(activeItem));

                                modal.bsModal.$modal.on('click', '.bssm-item:not(.disabled)', function (e) {

                                    var $this = $(this);

                                    if ($this.hasClass('active')) {
                                        modal.bsModal.close_modal();

                                        return;
                                    }

                                    var $selectedItem = $this.closest('.bssm-item'),
                                        selectedItemId  = $selectedItem.data('item-id'),
                                        $selectedItemImg = $selectedItem.find('figure img'),
                                        selectedItemTitle = $selectedItem.find('.bf-item-title').text();

                                    var selectedItemImg = $selectedItemImg.data('current-image') ||
                                        $selectedItemImg.attr('src');
                                    e.preventDefault();

                                   if (!data[ 1 ].confirm_changes) {

                                       var e = $.Event('select-popup-select');
                                       $select.trigger(e, [ this, modal.bsModal ]);

                                       if (! e.isDefaultPrevented()) {
                                           modal.bsModal.close_modal();
                                           setValue(selectedItemId,selectedItemTitle);
                                           setImage(selectedItemImg);
                                       }
                                       $select.trigger('select-popup-selectd', [ this, modal.bsModal ])

                                        return;
                                    }

                                    $.bs_modal({
                                        modalId: 'better-select-popup-confirm-modal',
                                        modalClass: 'pds-confirm-modal',
                                        content: $.extend({
                                            image_align: $('body').hasClass('rtl') ? 'left' : 'right',
                                            image_style: 'margin-left:10px;width:240px',
                                            image_src: $selectedItem.find('.bs-style-thumbnail').attr('src'),
                                            image_caption: data[ 3 ].caption.replace('%s', $selectedItem.find('.bf-item-title').text()),

                                            body: getBody()
                                        }, data[ 3 ]),

                                        buttons: {
                                            confirm: {
                                                label: data[ 3 ].button_ok,
                                                type: 'primary',
                                                clicked: function () {

                                                    setValue(selectedItemId,selectedItemTitle);
                                                    setImage(selectedItemImg);

                                                    var e = $.Event('select-popup-confirm');
                                                    $select.trigger(e, [ this, modal.bsModal ]);

                                                    if (e.isDefaultPrevented()) {
                                                        return;
                                                    }

                                                    var delay = Math.floor(this.options.animations.delay / 2);
                                                    this.close_modal();
                                                    setTimeout(function () {
                                                        modal.bsModal.close_modal();
                                                    }, delay);
                                                }
                                            },
                                            close_modal: {
                                                btn_classes: 'bs-modal-button-aside',
                                                label: data[ 3 ].button_cancel,
                                                action: 'close',
                                                type: 'secondary',
                                                focus: true
                                            }
                                        },

                                        template: 'single_image',

                                        styles: {
                                            container: 'width: 615px;max-width:100%'
                                        },
                                        animations: {
                                            body: 'bs-animate bs-fadeInLeft'
                                        }
                                    });

                                }).on('click','.bf-toggle-item-status a.disabled', function(){
                                    return false;
                                });

                                $select.trigger('select-popup-loaded', [ data, modal ]);
                            }
                        }

                    }, {
                        initialZIndex:initialZIndex
                    });
                }
            });
        },
        // Panel save ajax action
        panel_save_action: function(){

            var self = this;
            $(document).on( 'click', '.bf-save-button', function(e){

                e.preventDefault();

                var $this = $(this);

                if( $this.data('confirm') != '' && ! confirm( $this.data('confirm') ) )
                    return false;

                Better_Framework.panel_loader('loading');

                $.ajax({
                    type: 'POST',
                    dataType: 'json',
                    url: better_framework_loc.bf_ajax_url,
                    data:{
                        action   : 'bf_ajax',
                        reqID    : 'save_admin_panel_options',
                        type     : better_framework_loc.type,
                        panelID  : $('#bf-panel-id').val(),
                        nonce    : better_framework_loc.nonce,
                        lang     : better_framework_loc.lang,
                        data   	 : self._get_panel_data()
                    },
                    success: function(data, textStatus, XMLHttpRequest){

                        var event = $this.data('event');

                        if(event) {
                            $(document).trigger(event,[data,$this]);
                        }

                        if( data.status == 'succeed' ) {

                            $("#bf-panel .bf-options-change-notice")
                                .removeClass('bf-option-changed')
                                .slideUp();
                            self.turn_refresh_notice_off();

                            if( typeof data.msg != 'undefined' ){
                                Better_Framework.panel_loader('succeed',data.msg);
                            }else{
                                Better_Framework.panel_loader('succeed');
                            }
                        } else {
                            if( typeof data.msg != 'undefined' ){
                                Better_Framework.panel_loader('error',data.msg);
                            }else{
                                Better_Framework.panel_loader('error');
                            }
                            Better_Framework.panel_loader('error',data.msg);
                        }

                        if( typeof data.refresh != 'undefined' && data.refresh ){

                            if( data.status == 'succeed' ){
                                self.reload_location(1000);
                            }else{
                                self.reload_location(1500);
                            }

                        }
                    },
                    error: function(MLHttpRequest, textStatus, errorThrown){
                        Better_Framework.panel_loader('error');
                    }
                });

            });
        },


        // Panel Options Import & Export
        panel_import_export: function(){

            var self = this;
            // Export Button
            $(document).on( 'click', '#bf-download-export-btn', function(){

                var _go = $(this).attr('href');

                var _file_name =  $(this).data('file_name');
                var _panel_id =  $(this).data('panel_id');

                $().redirect(_go,{
                    'bf-export' :   1,
                    'nonce'     :   better_framework_loc.nonce,
                    'file_name' :   _file_name,
                    'panel_id'  :   _panel_id,
                    lang        :   better_framework_loc.lang
                });

                return false;

            });

            // Import
            var bf_import_submit;
            $('.bf-import-file-input').fileupload({
                limitMultiFileUploads: 1,
                url: better_framework_loc.bf_ajax_url,
                autoUpload: false,
                replaceFileInput: false,
                formData: {
                    nonce  : better_framework_loc.nonce,
                    action : 'bf_ajax',
                    type   : better_framework_loc.type,
                    reqID  : 'import',
                    'panel-id': $('.bf-import-file-input').data('panel_id'),
                    lang        :   better_framework_loc.lang
                },
                add: function (e, data) {
                    bf_import_submit = function () {
                        return data.submit();
                    };
                },
                start: function (e) {
                    Better_Framework.panel_loader('loading');
                },
                done: function (e, data) {

                    var result = JSON.parse( data.result );

                    if( result.status == 'succeed' ) {
                        if( typeof result.msg != 'undefined' ){
                            Better_Framework.panel_loader('succeed',result.msg);
                        }else{
                            Better_Framework.panel_loader('succeed');
                        }
                    } else {
                        if( typeof result.msg != 'undefined' ){
                            Better_Framework.panel_loader('error',result.msg);
                        }else{
                            Better_Framework.panel_loader('error');
                        }
                    }

                    if( typeof result.refresh != 'undefined' && result.refresh ){

                        if( data.status == 'succeed' ){
                            self.reload_location(1000);
                        }else{
                            self.reload_location(1500);
                        }

                    }

                },
                error: function(MLHttpRequest, textStatus, errorThrown){
                    Better_Framework.panel_loader('error');
                },
                progressall: function (e, data) {
                    var progress = parseInt( data.loaded / data.total * 100, 10);
                },
                drop: function (e, data) {
                    return false;
                }
            });

            $('.bf-import-upload-btn').click( function(){

                if( typeof bf_import_submit != "undefined" ){

                    if( confirm( better_framework_loc.translation.import_panel.prompt ) == true ){
                        bf_import_submit();
                    }

                }

                return false;
            });

        },


        // Ajax Action Field
        setup_ajax_action: function(){
            var self = this;

            $(document).on( 'click', '.bf-ajax_action-field-container .bf-action-button', function(e){

                var $this = $(this);

                e.preventDefault();

                Better_Framework.panel_loader('loading');

                var _confirm_msg =  $(this).data('confirm');

                if( typeof  _confirm_msg  != "undefined" )
                    if( ! confirm( _confirm_msg ) ){
                        Better_Framework.panel_loader( 'hide' );
                        return false;
                    }


                var data = {
                    action: 'bf_ajax',
                    reqID: 'ajax_action',
                    type: better_framework_loc.type,
                    panelID: $('#bf-panel-id').val(),
                    lang: better_framework_loc.lang,
                    nonce: better_framework_loc.nonce,
                    callback: $this.data('callback'),
                    bf_call_token: $this.data('token')
                };

                $(document).trigger('ajax-action-field-data', [data]);

                $.ajax({
                    type: 'POST',
                    dataType: 'json',
                    url: better_framework_loc.bf_ajax_url,
                    data:data,
                    success: function(data, textStatus, XMLHttpRequest){


                        var event = $this.data('event');

                        if(event) {
                            $(document).trigger(event,[data,$this]);
                        }

                        if( data.status == 'succeed' ) {
                            if( typeof data.msg != 'undefined' ){
                                Better_Framework.panel_loader('succeed',data.msg);
                            }else{
                                Better_Framework.panel_loader('succeed');
                            }
                        } else {
                            if( typeof data.msg != 'undefined' ){
                                Better_Framework.panel_loader('error',data.msg);
                            }else{
                                Better_Framework.panel_loader('error');
                            }
                        }

                        if( typeof data.refresh != 'undefined' && data.refresh ){

                            if( data.status == 'succeed' ){

                                self.reload_location(1000);

                            }else{
                                self.reload_location(1500);
                            }

                        }
                    },
                    error: function(MLHttpRequest, textStatus, errorThrown){
                        Better_Framework.panel_loader('error');
                    }
                });

            });
        },

        /**
         * Refresh page without unload notice
         *
         * @param delay
         */
        reload_location: function (delay) {
            this.turn_refresh_notice_off();
            if(delay) {
                setTimeout( function() {
                    location.reload();
                }, delay );
            } else {
                location.reload();
            }
        },
        // Panel Ajax Reset Action
        panel_reset_action: function(){

            var _this = this;
            $(document).on( 'click', '.bf-reset-button', function(){

                $.bs_modal({
                    content: {
                        header: better_framework_loc.translation.reset_panel.header,
                        title: better_framework_loc.translation.reset_panel.title,
                        body: better_framework_loc.translation.reset_panel.body
                    },
                    styles: {
                        container: 'overflow:visible;max-width: 460px;'
                    },
                    buttons: {
                        custom_event: {
                            label: better_framework_loc.translation.reset_panel.button_yes,
                            type: 'primary',
                            clicked: function() {
                                var self = this;
                                self.change_skin( {
                                    skin:'loading',
                                    animations:{
                                        body:'bs-animate bs-fadeInLeft'
                                    },
                                    content: {
                                        loading_heading: better_framework_loc.translation.reset_panel.resetting
                                    }
                                });

                                $.ajax({
                                    type: 'POST',
                                    dataType: 'json',
                                    url: better_framework_loc.bf_ajax_url,
                                    data:{
                                        action 	 : 'bf_ajax',
                                        reqID  	 : 'reset_options_panel',
                                        panelID  : $('#bf-panel-id').val(),
                                        lang     : better_framework_loc.lang,
                                        type	 : 'panel',
                                        nonce    : better_framework_loc.nonce,
                                        to_reset : $('.bf-reset-options-frame-tabs').bf_serialize()
                                    },
                                    success: function(data, textStatus, XMLHttpRequest){

                                        if( data.status == 'succeed' ){
                                            self.change_skin( {
                                                skin:'success',
                                                animations:{
                                                    body: 'bs-animate bs-fadeInLeft'
                                                },
                                                content: {
                                                    success_heading: data.msg
                                                },
                                                timer: {
                                                    delay: 2000,
                                                    callback: function () {
                                                        this.close_modal();
                                                    }
                                                }
                                            });
                                            _this.reload_location(1000);
                                        } else {
                                            if( typeof data.msg != 'undefined' ){
                                                Better_Framework.panel_loader('error',data.msg);
                                            }else{
                                                Better_Framework.panel_loader('error');
                                            }
                                        }

                                    },
                                    error: function(MLHttpRequest, textStatus, errorThrown){
                                        alert( 'An error occurred!' );
                                    }
                                });
                            }
                        },
                        close_modal: {
                            type: 'secondary',
                            action: 'close',
                            label: better_framework_loc.translation.reset_panel.button_no,
                            focus: true
                        }
                    }
                });
            });

        },


        // Panel loader
        // status: loading, succeed, error
        panel_loader: function( status, message ){

            var $bf_loading = $('.bf-loading');

            message = typeof message !== 'undefined' ? message : '';

            if( status == 'loading'){

                $bf_loading.removeClass().addClass('bf-loading in-loading');

                if( message != '' ){
                    $bf_loading.find('.message').html(message);
                    $bf_loading.addClass('with-message');
                }

            }
            else if(status == 'error'){

                $bf_loading.removeClass().addClass('bf-loading not-loaded');

                if( message != '' ){
                    $bf_loading.find('.message').html(message);
                    $bf_loading.addClass('with-message');
                }

                setTimeout(function(){
                    $bf_loading.removeClass('not-loaded');
                    $bf_loading.find('.message').html('');
                    $bf_loading.removeClass('with-message');
                },1500);

            }else if(status == 'succeed'){

                $bf_loading.removeClass().addClass('bf-loading loaded');

                if( message != '' ){
                    $bf_loading.find('.message').html(message);
                    $bf_loading.addClass('with-message');
                }

                setTimeout(function(){
                    $bf_loading.removeClass('loaded');
                    $bf_loading.find('.message').html('');
                    $bf_loading.removeClass('with-message');
                },1000);

            }else if( status == 'hide' ){

                setTimeout(function(){
                    $bf_loading.removeClass(' in-loading');
                    $bf_loading.find('.message').html('');
                    $bf_loading.removeClass('with-message');
                },500 );
            }

        },


        // Setup sticky header
        panel_sticky_header: function(){

            var $main_menu = $('#bf-panel .bf-page-header');

            var main_menu_offset_top = 110 ;

            var sticky_func = function(){

                if( $(window).scrollTop() > main_menu_offset_top )
                    $main_menu.addClass('sticky').parent().addClass('sticky');
                else
                    $main_menu.removeClass('sticky').parent().removeClass('sticky');

            };

            sticky_func();

            $( window ).scroll( function(){
                sticky_func();
            } );
        },


        process_filter_field: function( field_id, field_value ){

            $( '.bf-section-container[data-filter-field=\'' + field_id + '\']').each( function(){

                if( $(this).data( 'filter-field-value' ) == field_value ){
                    $(this).fadeIn('200');
                }else{
                    $(this).css({'display':'none'});
                }

            });

        },



        /**
         * Meta Box
         ******************************************/

        set_metabox: function(){
            var self = this;

            // todo refactor this and remove cookie
            $('.bf-metabox-wrap').each( function(i,o){
                var $metaboxWrap = $(this);

                var _metabox__id = $metaboxWrap.data("id");

                var current_box_cookie = $.cookie( 'bf_metabox_current_tab_' + _metabox__id  );

                function bf_show_first_tab( tab ){
                    tab.find('li:first').find('a:first').addClass("active_tab");

                    tab.siblings('.bf-metabox-container').find( '#bf-metabox-' + _metabox__id + "-" + tab.find('li:first').data("go") ).fadeIn(500);
                }
                var isTabAjax = $('.bf-metabox-tabs', this).find("li[data-go='"+current_box_cookie+"']").hasClass('bf-ajax-tab');
                if( typeof current_box_cookie == 'undefined' || isTabAjax ){
                    bf_show_first_tab( $(this).find('.bf-metabox-tabs') );
                }
                else {
                    if( ! $(this).find( '#bf-metabox-' + _metabox__id + "-" + current_box_cookie ).exist() || ! $(this).find(".bf-metabox-tabs").find("a[data-go='"+current_box_cookie+"']").exist() ){
                        bf_show_first_tab( $(this).find('>.bf-metabox-tabs') );
                        $.removeCookie('bf_metabox_current_tab_' + _metabox__id);
                        return;
                    }

                    $(this).find( '#bf-metabox-' + _metabox__id + "-" + current_box_cookie ).fadeIn();
                    $(this).find(".bf-metabox-tabs").find("a[data-go='"+current_box_cookie+"']").addClass("active_tab");
                    if( $(this).find(".bf-metabox-tabs").find("a[data-go='"+current_box_cookie+"']").is(".bf-tab-subitem-a") ){
                        $(this).find(".bf-metabox-tabs").find("a[data-go='"+current_box_cookie+"']").closest(".has-children").addClass("child_active");
                    }
                }

                $(this).find('.bf-metabox-tabs').find('a').click( function(e){
                    e.preventDefault();

                    var _this = $(this);

                    if( _this.hasClass( 'active_tab' ) ){
                        return false;
                    }

                    var _metabox_wrap = $(this).closest(".bf-metabox-wrap");
                    var _metabox_nav = _metabox_wrap.find(".bf-metabox-tabs");
                    if( typeof _metabox__id == 'undefined' )
                        var _metabox__id = _metabox_wrap.data("id");

                    var _hasNotGroup = (
                    ( _this.parent().hasClass('has-children') )
                    &&
                    ( ! _metabox_wrap.find( '#bf-metabox-' + _metabox__id + "-" + _this.data("go") ).find(">*").exist() )
                    );

                    //var _isChild = ! _this.parent().hasClass('has-children');

                    if( _hasNotGroup ){
                        var _clicked = _this.siblings('ul.sub-nav').find('a:first');
                        var _target = _metabox_wrap.find( '#bf-metabox-' + _metabox__id + "-" + _clicked.data("go") );
                    } else {
                        var _clicked = _this;
                        var _target = _metabox_wrap.find( '#bf-metabox-' + _metabox__id + "-" + _clicked.data("go") );
                    }

                    var $parent = _this.parent();

                    function displayTab() {
                        _metabox_nav.find('a').removeClass("active_tab");
                        _metabox_nav.find('ul.sub-nav').find('a').removeClass("active_tab");
                        _metabox_nav.find('li').removeClass("child_active");

                        _metabox_wrap.find(".bf-metabox-container").find('>div').hide();
                        _target.fadeIn(500);

                        _clicked.addClass("active_tab");

                        if( $parent.hasClass('has-children') || $parent.parent().hasClass('sub-nav') ){

                            _clicked.closest('.has-children').addClass("child_active");
                        }
                    }

                    var isTabAjax = $parent.hasClass('bf-ajax-tab') &&
                                    ! $parent.hasClass('bf-ajax-tab-loaded');

                    if(! isTabAjax) {

                        displayTab();
                        $.cookie( 'bf_metabox_current_tab_' + _metabox__id, _clicked.data("go"), { expires: 7 });

                        return false;
                    }
                });

                $(this).find( '.bf-metabox-container.bf-with-tabs').css( 'min-height',  $(this).find('.bf-metabox-tabs').height() + 50 );

            });


        },

        // Advanced filter for filter metaboxes for post format's
        metabox_filter_postformat: function(){

            var _current_format = $('#post-formats-select input[type=radio][name=post_format]:checked').attr('value');
            if( parseInt( _current_format ) ==0 )
                _current_format='standard';

            $('.bf-metabox-wrap').each(function(){
                if(typeof  $(this).data('bf_pf_filter') == 'undefined' || $(this).data('bf_pf_filter') == '')
                    return 1;

                var _metabox_id = '#bf_'+$(this).data('id'),
                    __metabox_id = 'bf_'+$(this).data('id'),

                    _formats = $(this).data('bf_pf_filter').split(',');

                if($.inArray(_current_format,_formats)== -1)
                    $(_metabox_id).hide();
                else
                    $(_metabox_id).show();
            });

            $('#post-formats-select input[type=radio][name=post_format]').change(function(){
                Better_Framework.metabox_filter_postformat();
            });

        },


        // Advanced filter for filter metabox fields for post format's
        metabox_field_filter_postformat: function(){

            var _current_format = $('#post-formats-select input[type=radio][name=post_format]:checked').attr('value');
            if(parseInt(_current_format)==0)
                _current_format='standard';

            $('.bf-field-post-format-filter').each(function(){

                if(typeof  $(this).data('bf_pf_filter') == 'undefined' || $(this).data('bf_pf_filter') == '')
                    return 1;

                var _formats = $(this).data('bf_pf_filter').split(',');

                if( $.inArray( _current_format, _formats ) == -1 )
                    $(this).hide();
                else
                    $(this).show();
            });


            $('#post-formats-select input[type=radio][name=post_format]').change(function(){
                Better_Framework.metabox_field_filter_postformat();
            });

        },

        vc_editor_fix:function() {
            $(document).ajaxSuccess(function (e, xhr, settings) {

                var _data = $.unserialize(settings.data);

                if (_data.action == "wpb_show_edit_form" || _data.action == "vc_edit_form") {
                    var $context = $("#vc_ui-panel-edit-element");

                        $('.bf-css-edit-switch', $context)
                        .closest('.vc_column')
                        .addClass('bf-css-edit-switch-container')

                            $('.bf-vc-third-col',$context)
                                .closest('.vc_column')
                                .addClass('bf-vc-third-column')


                }
            });
        },

        _length: function (object) {
            if (!object) {
                return 0;
            }

            if (Object.keys) {
                return Object.keys(object).length;
            }

            var count = 0, i;

            for (i in object) {
                if (object.hasOwnProperty(i)) {
                    count++;
                }
            }

            return count;
        },

        _interactive_field_change: function (e, options) {

            var settings = $.extend({
                el:false,
                ID: false,
                $container: false,
                inputWrapperSelector: false,
                inputParamsSelector: false,
                parentSelector: false,
                paramDataName: 'param-name',
                paramSettingsName: 'param-settings',
                filterDataCallback: false
            }, options);

            if(! settings.el) {
                throw new Error('Invalid Element');
            }

            var $this         = $(settings.el),
                self          = this,
                $row          = $this.closest(settings.parentSelector),
                columns_value = {};

            if( settings.$container) {
                if (self._interactive_fields_cache[settings.ID]) {
                    columns_value = self._interactive_fields_cache[settings.ID];
                } else {

                    var cache = {};

                    $(settings.inputWrapperSelector, settings.$container).each(function () {
                        var $col       = $(this),
                            $inputs    = $col.find(':input'),
                            param_name = $col.data(settings.paramDataName);

                        cache[param_name] = $inputs.length > 1 ? $inputs.filter(':checked').val() : $inputs.val();
                    });

                    columns_value = cache;
                }
            }

            $row.find(settings.inputWrapperSelector).each(function () {
                var $col        = $(this);

                var $paramsWrapper = settings.inputParamsSelector ? $(settings.inputParamsSelector,$col) : $col;
                var _settings   = $paramsWrapper.data(settings.paramSettingsName),
                    $inputs     = $col.find(':input'),
                    param_name  = $paramsWrapper.data(settings.paramDataName),
                    param_value = $inputs.length > 1 ? $inputs.filter(':checked').val() : $inputs.val();

                if( settings.filterDataCallback ) {
                    var filtered = settings.filterDataCallback(param_name,param_value,$row,$inputs);

                    columns_value[ filtered[0] ] = filtered[1];
                } else {
                    columns_value[ param_name ] = param_value;
                }

                if (!_settings || !self._length(_settings)) {
                    return;
                }

                if ('always_show' in _settings && _settings.always_show)
                    return;

                var action = e.type === 'force-change' ? 'hide' : 'slideUp';
                if (_settings.show_on instanceof Array) {

                    var length = _settings.show_on.length;

                    for (var i = 0; i < length; i++) {
                        var array_values = typeof _settings.show_on[ i ] === 'string' ? [ _settings.show_on[ i ] ] : _settings.show_on[ i ],
                            condition    = true;

                        for (var j = 0; j < array_values.length; j++) {

                            var split = array_values[ j ].match(/(.*?)(\!?\=)(.*)/);

                            if (!split) {
                                continue;
                            }

                            var _param_value = split[ 3 ],
                                _param_name  = split[ 1 ],
                                operator     = split[ 2 ];

                            if (typeof columns_value[ _param_name ] === 'undefined') {

                                condition = false;
                            } else {

                                switch (operator) {
                                    case '=':
                                        condition = columns_value[ _param_name ] == _param_value;
                                        break;
                                    case '!=':
                                        condition = columns_value[ _param_name ] != _param_value;
                                        break;
                                }

                            }

                            if (!condition) {
                                break;
                            }
                        }

                        if (condition) {
                            action = e.type === 'force-change' ? 'show' : 'slideDown';
                            break;
                        }
                    }

                    if(action === 'slideDown') {

                        $col.stop()[ action ](function() {
                            $(this).css('height', 'auto');
                        });

                    } else {

                        $col.stop()[ action ]();
                    }
                }
            });

            self._interactive_fields_cache[settings.ID] = columns_value;
        },

        setup_interactive_fields_for_bf: function ($context) {

            if($context && $context[0] === document.body) {
                $context  = undefined;
            }

            var self = this,
                $wrapper = $context,
                parentSelector = '.group,.tinymce-addon-fields',
                inputWrapperSelector = '.bf-section-container,.fields-group';

            var widgetParentSelector = function() {
                return $(document.body).hasClass('widgets_access') ? '.widget-inside' : '.widget';
            };

            var widgetShowOnFix = function() {

                // Fix: show_on initialization on widgets page
                setTimeout(function() {
                    $("#widgets-right .widget-inside").each(function(){
                        $(":input:first",this).trigger('force-change');
                    });
                });

                // Fix: Init show_on after widget saved
                $(document).on( 'widget-updated', function(e,$widget) {
                    $(".widget-inside :input:first",$widget).trigger('force-change');
                });
            }

            if($context && ($context.hasClass('widget') || better_framework_loc.type === 'widgets')) {

                parentSelector = widgetParentSelector();
                widgetShowOnFix();

            } else if($context && better_framework_loc.type === 'panel'){

                parentSelector = "#bf_options_form";

            } else{

                switch(better_framework_loc.type) {

                    case 'widgets':

                        parentSelector = widgetParentSelector();
                        $wrapper       = $("#widgets-right",$context);
                        widgetShowOnFix();

                        break;

                    case 'metabox':
                    case 'users':

                        if(! $context) {

                            $wrapper = $(".bf-metabox-wrap");
                            parentSelector = '.bf-metabox-wrap';
                        }
                        break;

                    case 'menus':

                        $wrapper = $(".menu-item-settings>.fields-group",$context);
                        parentSelector = '.fields-group';
                        inputWrapperSelector = '.bf-menu-custom-field,.bf-section-container';
                        break;

                    case 'taxonomy':

                        if(! $context || !$context.hasClass('group')) {

                            $wrapper = $(".bf-metabox-container>.group:visible",$context);
                        }

                        break;

                    default:

                        parentSelector = "#bf_options_form";

                        if ($("#bf_options_form>.group").length > 0) {
                            $wrapper = $("#bf_options_form>.group:visible",$context);
                        } else {
                            $wrapper = $("#bf-panel",$context);
                        }
                }
            }

            if($wrapper.data('show-on-initialized')) {
                return ;
            }

            var $containers = $wrapper.closest('.bf-tax-meta-wrap,.postbox,.widget,#bf-main,.menu-item');


            if ($containers.length) {

                $containers.each(function () {
                    var $container = $(this),
                        ID         = $container.data('show-on-id');

                    if ( ! ID ) {
                        ID = 'show-on-' + Math.ceil(Math.random() * 1e5);
                        $container.attr('data-show-on-id', ID);
                        $container.data('show-on-id', ID);
                    }

                    $($wrapper.selector, $container).on('change force-change', ':input, .bf-repeater-item :input:first', function (e) {

                        self._interactive_field_change(e, {
                            el: this,
                            ID: ID,
                            $container: $container,
                            inputWrapperSelector: inputWrapperSelector,
                            parentSelector: parentSelector
                        })
                    });
                });
            } else {

                $wrapper.on('change force-change', ':input, .bf-repeater-item :input:first', function (e) {

                    self._interactive_field_change(e,{
                        el:this,
                        inputWrapperSelector: inputWrapperSelector,
                        parentSelector: parentSelector
                    })
                });
            }

            $wrapper.find(':hidden:first').trigger('force-change');

            $wrapper.find(':input[type!=hidden]:first')
                .trigger('force-change');

            $wrapper.find('.bf-repeater-item :input:first')
                .trigger('force-change');

            if(parentSelector === '.group') {

                setTimeout(function() {
                    $(".group:visible :input:first",$wrapper ).trigger('force-change');
                },100);
              }

            $wrapper.on('bf-ajax-tab-loaded', function(e,$target) {
                $target.find(':input:first')
                       .trigger('force-change');
            });


            $wrapper.on('repeater_item_added', '.bf-section', function(e,$repeater) {
                $(this).find(':input:first').trigger('force-change');
            });


            $wrapper.data('show-on-initialized',true);
        },

        /**
         * Visual Composer
         ******************************************/

        setup_interactive_fields_for_vc: function () {
            var self = this;

            $(document).ajaxSuccess(function (e, xhr, settings) {

                var _data = $.unserialize(settings.data);

                if (_data.action == "wpb_show_edit_form" || _data.action == "vc_edit_form") {
                    var $wrapper = $("#vc_ui-panel-edit-element")
                        .find('.bf-interactive-fields');

                    $wrapper
                        .on('change force-change', ':input', function (e) {
                            self._interactive_field_change(e,{
                                el:this,
                                ID: false,
                                containerSelector: false,
                                inputWrapperSelector: '.vc_column',
                                parentSelector:  '.vc_row',
                                paramDataName: 'vc-shortcode-param-name',
                                paramSettingsName: 'param_settings'
                            });
                        });

                    //auto trigger event
                    var match,
                        classes       = $wrapper.attr('class'),
                        $form_wrapper = $("#vc_ui-panel-edit-element"),
                        _regex        = /bf-filter-field-([^\s]+)/gi;

                    while (match = _regex.exec(classes)) {
                        var el_name = match[ 1 ];

                        $form_wrapper
                            .find('.bf-interactive-fields [name=' + el_name + ']')
                            .trigger('force-change');
                    }
                }
            });
        },


        // Setup fields when VC create new popup window
        setup_fields_for_vc: function(){

            jQuery(document).ajaxSuccess(function(e, xhr, settings) {

                var _data = $.unserialize(settings.data);

                if(_data.reqID === 'fetch-mce-view-fields') {

                    var $context = $("#es-modal .bs-modal-body");

                } else {

                    var $context = $('.vc_ui-panel-window-inner:visible');
                }

                if( _data.action == "wpb_show_edit_form" || _data.action == "vc_edit_form" ||
                    _data.reqID === 'fetch-mce-view-fields' ) {
                    // TODO do this for just new elements

                    Better_Framework.setup_field_color_picker($context);
                    Better_Framework.setup_field_switch();
                    Better_Framework.setup_field_slider();
                    Better_Framework.setup_field_ajax_select();
                    Better_Framework.setup_vc_field_sorter();
                    Better_Framework.setup_vc_term_select();

                }

                if(_data.reqID === 'fetch-mce-view-fields') {
                    Better_Framework.setup_interactive_fields_for_bf($("#es-modal .bs-modal-body"));
                }
            });

            Better_Framework.set_up_vc_field_image_radio();
        },


        // Setup Sorter field
        setup_vc_field_sorter: function(){

            $( ".bf-vc-sorter-list" ).sortable({
                placeholder: "placeholder-item",
                cancel: "li.disable-item"
            });

            $('.bf-section-container.vc-input .bf-vc-sorter-list li input').on('change', function(evt, params) {

                if( typeof $(this).attr('checked') != "undefined" ){
                    $(this).closest('li').addClass('checked-item');
                }else{
                    $(this).closest('li').removeClass('checked-item');
                }

            });

            $('.bf-section-container.vc-input .bf-vc-sorter-checkbox-list li input, .bf-vc-sorter-list').on('change', function(evt, params) {

                var $parent = $(this).closest('.bf-section-container.vc-input'),
                $input = $parent.find('input.wpb_vc_param_value');

                rearrange_bf_vc_sorter_checkbox( $parent, $input );

            });

            $('.bf-vc-sorter-list').on('sortupdate', function(evt, params) {
                var $parent = $(this).closest('.bf-section-container.vc-input'),
                    $input = $parent.find('input.wpb_vc_param_value');

                rearrange_bf_vc_sorter_checkbox( $parent, $input );

            });

            function rearrange_bf_vc_sorter_checkbox( $parent, $input ){
                var _val = '';
                $('.bf-section-container.vc-input .bf-vc-sorter-checkbox-list li input[type=checkbox]:checked').each( function(){
                    if( _val.length == 0 ){
                        _val = $(this).attr( 'name' );
                    }else{
                        _val = _val + ',' + $(this).attr( 'name' );
                    }
                });
                $input.attr( 'value', _val );
            }
        },


        /**
         * Setup Visual Composer Image Radio Field
         */
        set_up_vc_field_image_radio: function(){

            $(document).on( 'click', '.vc-bf-image-radio-option', function(e){

                $(this).parent().find('input[type=hidden]').val( $(this).data( 'id' ) );

                // Remove checked class from field options and add checked class to clicked option
                $(this).siblings().removeClass('checked').end().addClass('checked');

                // Prevent Browser Default Behavior
                e.preventDefault();
            });

        },

        setup_checkbox_radio_fields: function($context) {

            $context = $context || $(document);

            function changeStateAttr($el,state) {

                $el.attr('data-current-state', state)
                   .data('current-state', state);
            }

            if (!this.radioCheckboxInitialized) {

                $(document).on('click', '.bf-checkbox-multi-state:not(.disabled)', function (e) {
                    e.preventDefault();

                    var $wrapper   = $(this),
                        $firstEl   = $('[data-state]:not(.disabled):first', $wrapper),
                        state      = $wrapper.data('current-state'),
                        $currentEL = $wrapper.find('[data-state=' + state + ']');

                    if (!$currentEL.length) {
                        $currentEL = $firstEl;
                    }

                    function getNextEl() {
                        var $next = $currentEL.next('[data-state]:not(.disabled)');
                        if (!$next.length) {
                            $next = $firstEl;
                        }

                        return $next;
                    }

                    var $nextEl   = getNextEl(),
                        nextState = $nextEl.data('state');

                    $currentEL.css('display', 'none');
                    $nextEl.css('display', 'inline-block');

                    changeStateAttr($wrapper,nextState);

                    $wrapper.trigger('bf-checkbox-change', [ nextState ].concat(Array.prototype.slice.call(arguments, 1)) );
                });


                $(document).on('click', '.bf-radio-field:not(.disabled)', function (e) {
                    e.preventDefault();
                    e.stopPropagation();

                    var $this = $(this);

                    if($this.data('current-state') === 'active') {
                        return ;
                    }

                    var $group = $(this).closest('.bf-radio-group'),
                        $d    = $group.find('[data-current-state="active"]'); // deactivate

                    changeStateAttr($d,'deactivate');
                    $d.children('span').hide();


                    changeStateAttr($this,'active');
                    $this.children('span').show();

                    $group.trigger('bf-radio-change', [ $this.data('name') ].concat(Array.prototype.slice.call(arguments, 1)) );
                }).on('click', '.bf-radio-toggle', function() {
                    $('.bf-radio-field:not(.disabled)',$(this).parent()).click();
                });

                this.radioCheckboxInitialized = true;
            }

            /**
             * Init Checkboxes
             */
            $('.bf-checkbox-multi-state', $context).each(function () {
                var $this = $(this),
                    state = $this.data('current-state');

                $('[data-state=' + state + ']', $this).css('display', 'inline-block');
            });
        },
        /**
         * Setup Term Select Field
         */
        setup_term_select: function ($context) {
            this.init_term_select($context || $(document));
        },
        setup_vc_term_select:function (){
            this.setup_term_select(
                $("#vc_ui-panel-edit-element")
            );
        },
        init_term_select: function ($context) {

            var config = {
              autoCheckParent: false // Check parent term if all childrens was checked
            };

            function getTermIdByInputName(inputName) {
                return inputName.toString().match(/\[(\d+)\]$/i)[ 1 ];
            }

            /**
             * Display Primary link only when more than one root term are active
             */
            function canCreatePrimaryLink($container) {
                var $checked = $container.parent()
                                         .find('.bf-field-term-select-wrapper>ul>li>.bf-checkbox-multi-state[data-current-state="active"]');

                return $checked.length >= 2;
            }

            function toggleShowPrimaryClass($el, addClass) {

                $el[ addClass ? 'addClass' : 'removeClass' ]
                ('bf-field-term-show-primary-label');
            }

            function createPrimaryLink($labelContainer, termID) {

                if (!termID) {
                    var $input = $labelContainer.prevAll('.bf-checkbox-multi-state')
                                                .find('.bf-checkbox-status');
                    if (!$labelContainer.length) {
                        return false;
                    }
                    termID = getTermIdByInputName($input.attr('name'));
                }

                if (!termID) {
                    return false;
                }

                var $primaryEL = $labelContainer.find(".bf-make-term-primary");
                if (!$primaryEL.length || $primaryEL.attr('class') !== 'bf-make-term-primary') {

                    if ($primaryEL.length) {
                        $primaryEL.remove();
                    }

                    var $el = $('<em/>', {
                        'class': 'bf-make-term-primary'
                    }).html('<a href="#" data-term-id="' + termID + '">'+better_framework_loc.term_select.make_primary+'</a>');

                    $el.appendTo($labelContainer);

                    return true;
                }

                return false;
            }

            function initCheckboxes($context) {
                $('.bf-checkbox-multi-state', $context).each(function () {
                    var $this        = $(this),
                        state        = $this.data('current-state'),
                        $currentMark = $('[data-state="' + state + '"]', $this);

                    $currentMark.css('display', 'inline-block');
                    $('[data-state]:not(.disabled)', $this).not($currentMark).css('display', 'none');
                });
            }

            function updateCheckboxStatesList($context, validStatus) {
                $('[data-state]', $context).each(function () {
                    var $this    = $(this),
                        state    = $this.data('state'),
                        isEnable = $.inArray(state, validStatus) > -1;

                    $this[ isEnable ? 'removeClass' : 'addClass' ]('disabled');
                })
            }

            function changeCheckboxState(status, $checkboxEL, $context) {
                $context = $context || $checkboxEL.parent();

                $checkboxEL.attr('data-current-state', status)
                           .data('current-state', status)
                           .find('.bf-checkbox-status')
                           .val(status);

                $checkboxEL.trigger('bf-checkbox-change', []);
                initCheckboxes($context);

                return true;

            }

            function changeChildrenState($childUlWrapper, status) {
                if (!status) {
                    return false;
                }

                if ($childUlWrapper.length) {
                    var $childs = $childUlWrapper.find('.bf-checkbox-multi-state');

                    return changeCheckboxState(status, $childs, $childUlWrapper);
                }

                return false;
            }

            function updateCollectIdFlag($context, flag) {
                $('.bf-checkbox-multi-state', $context)
                    [ flag == 'collect' ? "removeClass" : 'addClass' ]('bf-checkbox-skip-collect-active-term-id');
            }

            function canCollectTermAsDeactivated(checkboxStatusEL) {
                return checkboxStatusEL.parentElement.dataset.currentState === 'deactivate';
            }

            function canCollectTermAsActivated(checkboxStatusEL, $checkboxContainer) {

                return checkboxStatusEL.parentElement.dataset.currentState === 'active' && (function ($container) {
                        return !$container.hasClass('bf-checkbox-skip-collect-active-term-id');
                    })($checkboxContainer || $(checkboxStatusEL).closest('.bf-checkbox-multi-state'));
            }

            function isTermPrimary($labelContainer) {
                return $labelContainer.find('.bf-make-term-primary')
                                      .hasClass('bf-is-term-primary');
            }

            function isAllChildsActive($childrenUL) {
                return $childrenUL.length && !$('.bf-checkbox-multi-state[data-current-state!="active"]', $childrenUL).length;
            }

            function scrollToFirstActiveCheckbox($context) {
                var topMargin      = 40,
                    $catsContainer = $('.bf-field-term-select-wrapper', $context);

                if ($catsContainer.length) {
                    var $firstChecked = $('.bf-checkbox-multi-state[data-current-state="active"]:first', $catsContainer);

                    if ($firstChecked.length) {
                        var firstCheckPos = $firstChecked.offset().top - $catsContainer.offset().top - topMargin;
                        $catsContainer.animate({scrollTop: "+=" + firstCheckPos}, 300);
                    }
                }
            }

            $('.bf-checkbox-multi-state', $context).on('bf-checkbox-change', function (e, state, calledFrom) {
                var $this       = $(this),
                    $container  = $this.closest('.bf-field-term-select-wrapper'),
                    termsIdList = [];


                var $clickedCheckBox  = $this.closest('.bf-checkbox-multi-state'),
                    $childrenUL       = $clickedCheckBox.nextAll('.children'),
                    childStateChanged = calledFrom === 'auto-check-childs' || changeChildrenState($childrenUL, state === 'deactivate' ? 'none' : state);

                /**
                 * Check parent term if all children terms was checked
                 */
                if (config.autoCheckParent && state === 'active' && calledFrom !== 'auto-check-childs') {
                    var $parentChilds = $clickedCheckBox.closest('ul.children');
                    if (isAllChildsActive($parentChilds)) {
                        var $EL = $parentChilds.prevAll('.bf-checkbox-multi-state');
                        changeCheckboxState('active', $EL);
                        $EL.trigger('bf-checkbox-change', [ state, 'auto-check-childs' ]);

                        return;
                    }
                }

                if (childStateChanged && state === 'active') {
                    $childrenUL.addClass('bf-checkbox-dual-state');
                    $childrenUL.find('ul.children').addClass('bf-checkbox-dual-state');

                    updateCheckboxStatesList(
                        $childrenUL,
                        [ 'active', 'deactivate' ]
                    );

                    updateCollectIdFlag(
                        $childrenUL,
                        'dont-collect'
                    );
                } else if (state !== 'active') {
                    updateCheckboxStatesList(
                        $childrenUL.closest('ul.children').removeClass('bf-checkbox-dual-state'),
                        [ 'none', 'active', 'deactivate' ]
                    );

                    updateCollectIdFlag(
                        $childrenUL,
                        'collect'
                    );
                }

                var canCreateLink = canCreatePrimaryLink($container);

                toggleShowPrimaryClass($container, canCreateLink);

                $('.bf-checkbox-status', $container).each(function () {
                    var termID     = getTermIdByInputName(this.name),
                        $this      = $(this),
                        status     = 'none',
                        $container = $this.closest('.bf-checkbox-multi-state'),
                        isTermRoot = $this.closest('ul.children', $container).length === 0,
                        $label     = $container.next('.label');

                    if (canCollectTermAsDeactivated(this)) {
                        termsIdList.push("-" + termID);
                        status = 'deactivate';
                    }
                    else if (canCollectTermAsActivated(this, $container)) {

                        status = 'active';
                        if (isTermPrimary($label)) {
                            termsIdList.unshift("+" + termID);
                        } else {
                            termsIdList.push(termID);
                        }
                    }
                    $label.attr('data-status', status)
                          .data('status', status);

                    /**
                     * Append Make Primary label if needed
                     */
                    if (canCreateLink && isTermRoot && !$container.hasClass('bf-checkbox-primary-term')) {
                        if (this.value === 'active') {
                            createPrimaryLink($label, termID);
                        } else {
                            //$label.find(".bf-make-term-primary").remove();
                        }
                    }

                    /**
                     * Append Excluded label if needed
                     */
                    if (this.value === 'deactivate') {
                        if (!$label.find('.bf-excluded-term').length) {

                            var $el = $('<em/>', {
                                'class': 'bf-excluded-term'
                            }).text(better_framework_loc.term_select.excluded);

                            $el.appendTo($label);
                        }
                    } else {
                        $label.find('.bf-excluded-term').remove();
                    }
                }).promise().done(function () {

                    $container.nextAll('.bf-term-select-value').val(termsIdList.join(','))
                        .change()[0].dispatchEvent(new Event('input'));
                });
            });

            /**
             * Handle Make Primary Action
             */
            $context.on('click', '.bf-make-term-primary a', function (e) {

                e.preventDefault();

                var $this      = $(this),
                    termID     = $this.data('term-id'),
                    $container = $this.closest('.bf-field-term-select-wrapper'),
                    $vcInputEL = $container.siblings('.bf-term-select-value');

                /**
                 * Regenerate terms id and mark primary term with a + sign
                 */
                var termsIdList = [ "+" + termID ],
                    canCreateLink = canCreatePrimaryLink($container);

                toggleShowPrimaryClass($container, canCreateLink);

                $('.bf-checkbox-status', $container).each(function () {
                    var _termID = getTermIdByInputName(this.name);

                    if (_termID == termID) {
                        return;
                    }

                    if (canCollectTermAsDeactivated(this)) {
                        termsIdList.push("-" + _termID);
                    } else if (canCollectTermAsActivated(this)) {
                        termsIdList.push(_termID);

                    }

                }).promise().done(function () {
                    $vcInputEL.val(termsIdList.join(',')).change();
                });

                if (canCreateLink) {
                    $('.bf-is-term-primary', $container).each(function () {
                        createPrimaryLink($(this).parent());
                    });
                }

                var $label = $this.parent();

                $label.addClass('bf-is-term-primary')
                      .html('Primary');

                /**
                 * Mark term as primary
                 */
                $('.bf-checkbox-multi-state', $container).removeClass('bf-checkbox-primary-term');
                $label.closest('.label').prevAll('.bf-checkbox-multi-state').addClass('bf-checkbox-primary-term');
            });

            /**
             * Init Checkboxes
             */
            $('.bf-checkbox-multi-state', $context).each(function () {
                var $this = $(this),
                    state = $this.data('current-state');

                $('[data-state=' + state + ']', $this).css('display', 'inline-block');

                /**
                 * Initial 'Collect ID' Flag
                 */
                var $childrenUL = $this.nextAll('.children');
                if ($childrenUL.length) {
                    if (isAllChildsActive($childrenUL)) {
                        updateCollectIdFlag(
                            $childrenUL,
                            'dont-collect'
                        );

                        $childrenUL.addClass('bf-checkbox-dual-state');
                        updateCheckboxStatesList(
                            $childrenUL,
                            [ 'active', 'deactivate' ]
                        );
                    }
                }
            });

            initCheckboxes($context);

            var $container = $('.bf-field-term-select-wrapper', $context);
            toggleShowPrimaryClass($container, canCreatePrimaryLink($container));

            jQuery('.vc_ui-tabs-line-trigger[data-vc-ui-element-target]', $context).one('click', function () {
                var target = $(this).data('vc-ui-element-target');
                setTimeout(function () {
                    scrollToFirstActiveCheckbox($(target));
                }, 100);
            });
            scrollToFirstActiveCheckbox($context);
            /**
             * Auto Scroll to checked element
             */
        },
        // Setup Switchery check box field
        setup_vc_field_switchery: function(){

            $('.bf-section-container.vc-input .js-switch').each( function(){

                if( $(this).prop( 'checked' ) ){
                    $(this).val( 1 );
                }else{
                    $(this).val( 0 );
                }

                new Switchery( this );

                $(this).on('change', function() {

                    if( $(this).prop( 'checked' ) ){
                        $(this).val( 1 );
                    }else{
                        $(this).val( 0 );
                    }

                });

            });
        },


        /**
         * Widgets
         ******************************************/

        // Setup widgets fields after ajax submit
        setup_widget_fields: function(){

            /**
             * Keep Widget Group State After Widget Settings Saved
             */
            function saveGroupStatus($context) {
                $( ".widget-content", $context ).on( 'click', '.fields-group-title-container', function() {
                    var $this   = $(this),
                        $_group = $this.closest('.fields-group'),
                        groupID = $_group.attr('id').match('^fields\-group\-(.+)$')[ 1 ],
                        isOpen  = !$_group.hasClass('bf-open');

                    var $form    = $this.closest('form'),
                        inoutVal = isOpen ? 'open' : 'close',
                        $input   = $('input[name="_group_status[' + groupID + ']"]', $form);

                    if ($input.length) {
                        $input.val(inoutVal);
                    } else {
                        $('<input />', {
                            type: 'hidden',
                            name: '_group_status[' + groupID + ']',
                        }).val(inoutVal).appendTo($form);
                    }
                });
            }

            jQuery(document).ajaxSuccess(function(e, xhr, settings) {

                var _data = $.unserialize(settings.data);

                if( _data.action == "save-widget" ){
                    var wID = _data['widget-id' ],
                        $widget = $("input.widget-id[value='"+wID+"']").closest('.widget');

                    saveGroupStatus($widget);
                }
            });

           var $document = $(document);

            $document.on('widget-updated widget-added', function(e,$widget) {

                // TODO do this for just new elements
                Better_Framework.setup_fields($widget);
                Better_Framework.setup_field_image_select();

            });

            // Clone Repeater Item by click
            // TODO refactor this
            $(document).on( 'click', '.bf-widget-clone-repeater-item', function(e){


                e.preventDefault();
                var //name_format = undefined === $(this).data( 'name-format' ) ? '$1[$2][$3][$4][$5]' : $(this).data( 'name-format'),
                    _html = $(this).siblings('script').html();

                if(! _html) {
                    return ;
                }
                var $inside = $(this).closest('.widget-inside'),
                    widgetBaseName = '';

                if($inside.length) {

                    var widgetIdBase  = $inside.find('input.id_base').val(),
                        widgetNumber = $inside.find('input.multi_number').val();

                    if(! widgetBaseName && better_framework_loc.page_builder.indexOf('Elementor') > -1 ) {

                        widgetNumber = 'REPLACE_TO_ID';
                    }

                    widgetBaseName = "widget-"+widgetIdBase+"["+widgetNumber+"]";

                } else {


                    var $wrapper = $(this).closest('.bf-controls'),
                        inputName = $(":input:first",$wrapper).attr('name');

                    if(inputName) {

                        var match = inputName.match(/(.*?)\[\d+\]\[.*?\]$/);

                        if(match && match[1]) {
                            widgetBaseName = match[1];
                        }
                    }
                }

                if(! widgetBaseName) {
                    return ;
                }

                var _new = $(this).siblings('.bf-repeater-items-container').find('>*').size();
                var new_num = _new + 1;

                $(this).siblings('.bf-repeater-items-container').append(
                    _html.replace(/\|_to_clone_(.*?)-num-(.*?)\|/g,widgetBaseName + '[$1]['+new_num+'][$2]')
                );
                // bf_color_picker_plugin( $(this).siblings('.bf-repeater-items-container').find('.bf-color-picker') );
                // bf_date_picker_plugin( $(this).siblings('.bf-repeater-items-container').find('.bf-date-picker-input') );
                // bf_image_upload_plugin( $(this).siblings('.bf-repeater-items-container').find('.bf-image-upload-choose-file') );
            });

            saveGroupStatus();
        },
        sort_widgets: function() {

            return ;
            var $widgets = $("#widget-list"),
                widgets_count = $widgets.find('.widget').length - 1;

            $widgets.find(".bf-widget-position").sort(function (a, b) {
                if (parseInt(a.value) <= parseInt(b.value)) {
                    return -1;
                }
                return 1;
            }).each(function (index) {
                var $this = $(this),
                    $widget = $this.closest('.widget'),
                    position = Math.min($this.val(), widgets_count) + 1,
                    $target = $widgets.find('.widget:nth-child(' + position + ')');


                $widget.insertAfter($target);
            });
        },

        /**
         * Menus
         ******************************************/

        // Advanced trick for sending all extra fields inside one field for enabling user to add huge bunch of menu items
        // and our to add menu fields without worry about variable limitation
        menus_collect_fields_before_save: function(){

            // Temp variable for collecting all fields to one place.
            var betterMenuItems = {};

            $('form#update-nav-menu').submit(function( e ){

                // disable extra fields for preventing send them to server
                $('*[name^="bf-m-i["]').attr("disabled", "disabled");

                // Iterate all extra fields
                $('*[name^="bf-m-i["]').each(function(){

                    var raw_name = $(this).attr('name'),
                        type = '',
                        post_id = '',
                        field_id = '';

                    if( raw_name.indexOf('[img]') > 0 ){
                        post_id = raw_name.replace( /(bf-m-i\[)(.*)(\]\[)([0-9]*)(\]\[)(.*)(\])/g, "$4" );
                        field_id = raw_name.replace( /(bf-m-i\[)(.*)(\]\[)([0-9]*)(\]\[)(.*)(\])/g, "$2" );
                        type = 'img';
                    }
                    else if( raw_name.indexOf('[icon]') > 0 ){
                        post_id = raw_name.replace( /(bf-m-i\[)(.*)(\]\[)([0-9]*)(\]\[)(.*)(\])/g, "$4" );
                        field_id = raw_name.replace( /(bf-m-i\[)(.*)(\]\[)([0-9]*)(\]\[)(.*)(\])/g, "$2" );
                        type = 'icon';
                    }
                    else if( raw_name.indexOf('[type]') > 0 ){
                        post_id = raw_name.replace( /(bf-m-i\[)(.*)(\]\[)([0-9]*)(\]\[)(.*)(\])/g, "$4" );
                        field_id = raw_name.replace( /(bf-m-i\[)(.*)(\]\[)([0-9]*)(\]\[)(.*)(\])/g, "$2" );
                        type = 'type';
                    }
                    else if( raw_name.indexOf('[width]') > 0 ){
                        post_id = raw_name.replace( /(bf-m-i\[)(.*)(\]\[)([0-9]*)(\]\[)(.*)(\])/g, "$4" );
                        field_id = raw_name.replace( /(bf-m-i\[)(.*)(\]\[)([0-9]*)(\]\[)(.*)(\])/g, "$2" );
                        type = 'width';
                    }
                    else if( raw_name.indexOf('[height]') > 0 ){
                        post_id = raw_name.replace( /(bf-m-i\[)(.*)(\]\[)([0-9]*)(\]\[)(.*)(\])/g, "$4" );
                        field_id = raw_name.replace( /(bf-m-i\[)(.*)(\]\[)([0-9]*)(\]\[)(.*)(\])/g, "$2" );
                        type = 'height';
                    }
                    else{
                        post_id = raw_name.replace(/(bf-m-i\[)(.*)(\]\[)([0-9]*)(\])/g, "$4");
                        field_id = raw_name.replace(/(bf-m-i\[)(.*)(\]\[)([0-9]*)(\])/g, "$2");
                        type = 'normal';
                    }

                    if( typeof betterMenuItems[post_id] == "undefined" ){
                        betterMenuItems[post_id] = {};
                    }

                    if( type == 'img' || type == 'type' || type == 'icon' || type == 'width' || type == 'height' ){

                        if( typeof betterMenuItems[post_id][field_id] == "undefined" ){
                            betterMenuItems[post_id][field_id] = {};
                        }
                        betterMenuItems[post_id][field_id][type] = $(this).val();

                    }else{
                        betterMenuItems[post_id][field_id] = $(this).val();
                    }

                });

                $(this).append( '<input type="hidden" name="bf-m-i" value="' + encodeURI( JSON.stringify( betterMenuItems ) ) + '" />' );
            });

        },


        /**
         * General Fields For All Sections
         ******************************************/

        // Setup General Fields
        setup_fields: function($context) {

            Better_Framework.setup_fields_group();

            Better_Framework.setup_field_with_prefix_or_postfix();

            Better_Framework.setup_field_switch();

            Better_Framework.setup_field_slider();
            Better_Framework.setup_field_sorter();

            Better_Framework.setup_field_color_picker($context);

            this.pre_defined_styles();

            Better_Framework.setup_field_image_radio();
            Better_Framework.setup_field_image_checkbox();
            Better_Framework.setup_field_image_select();

            Better_Framework.setup_field_date_picker();

            Better_Framework.setup_field_media_uploader();
            Better_Framework.setup_field_media_image();
            Better_Framework.setup_field_background_image();

            Better_Framework.setup_field_ajax_select();
            Better_Framework.setup_checkbox_radio_fields($context);

            Better_Framework.setup_term_select($context);

            Better_Framework.setup_field_border();

            Better_Framework.setup_field_repeater();

            Better_Framework.setup_ajax_action();

            this.handle_editor($context);

            $(document).on('bf-loaded', function() {

                Better_Framework.setup_interactive_fields_for_bf($context);
            });

            $(document).on('menu-item-added', function(e,$menuMarkup) {

                Better_Framework.setup_interactive_fields_for_bf($menuMarkup);
                Better_Framework.setup_fields($menuMarkup);

            });
        },


        // Setup Fields Group
        setup_fields_group: function(){

            $( document )
                .off( 'click', '.fields-group-title-container' )
                .on( 'click', '.fields-group-title-container', function() {

                var $_group = $(this).closest( '.fields-group'),
                    $_button = $(this).find( '.collapse-button' );

                if( $_group.hasClass( 'bf-open' ) ){

                    $_group.children('.bf-group-inner').slideUp(400);

                    $_group.removeClass('bf-open').addClass('bf-close');
                    $_button.find('.fa').removeClass('fa-minus').addClass('fa-plus');

                }else{

                    $_group.removeClass('bf-close').addClass('bf-open');
                    $_button.find('.fa').removeClass('fa-plus').addClass('fa-minus');

                    $_group.children('.bf-group-inner').slideDown(400);

                }

            });

        },


        // TODO Refactor This
        setup_field_repeater: function(){

            // Add jQuery UI Sortable to Repeater Items
            $('.bf-repeater-items-container').sortable({
                revert: true,
                cursor: 'move',
                delay: 150,
                handle: ".bf-repeater-item-title",
                start: function( event, ui ) {
                    ui.item.addClass('drag-start');
                },
                beforeStop: function( event, ui ) {
                    ui.item.removeClass('drag-start');
                }
            });

            // Remove Repeater Item
            $(document)
                .off( 'click', '.bf-remove-repeater-item-btn')
                .on( 'click', '.bf-remove-repeater-item-btn', function( e ){

                var $section =  $(this).closest('.bf-section');

                if($(".bf-repeater-items-container>.bf-repeater-item",$section).length === 1){

                    alert("Can not remove last item!");
                    return ;
                }

                if( confirm( 'Are you sure?' ) ){

                    /**
                     * Append hidden input before remove last item
                     */
                    if ($('.bf-repeater-item:visible', $section).length === 1) {
                        var inputName = $(':input:first', $section).attr('name').toString().match(/([^\[]+)/)[ 0 ]

                        var $placeholder = $('<input>',{
                            'class': 'placeholder-input',
                            'name': inputName + '[]',
                            'type': 'hidden'
                        });
                        $section.append($placeholder);
                    }

                    $(this).closest('.bf-repeater-item').slideUp( function(){

                        $(this).remove();

                        // Event for when item removed
                        $section.trigger( 'after_repeater_item_removed' );
                    });
                }

                e.preventDefault();

            });

            // Collapse
            $(document).off('click', '.handle-repeater-item')
                .on( 'click', '.handle-repeater-item', function(){
                $(this).toggleClass('bf-closed').closest('.bf-repeater-item').find('.repeater-item-container').slideToggle(400);
            });

            // Clone Repeater Item by click
            $(document).on( 'click', '.bf-clone-repeater-item', function(e){
                e.preventDefault();

                var $this = $(this);
                var $repeater_items_container = $(this).siblings('.bf-repeater-items-container'),
                    name_format = undefined === $(this).data( 'name-format' ) ? '$1[$2][$3]' : $(this).data( 'name-format'),
                    _html = $this.siblings('script').html(),
                    count = $repeater_items_container.find('>*').size(),
                    index = count + 1;

                // Retrieve script tags

                if(! _html) {
                    return ;
                }

                _html = _html.replace(/<\s*\!\-\-\s*SCRIPT\s*TAG\s*START\s*--\s*>\s*<\s*div\s*((.|\n)*)style=(([^>]+))/ig,'<script $1') // open script tag
                        .replace(/<\s*\/\s*div\s*>\s*<\s*\!\-\-\s*SCRIPT\s*TAG\s*END\s*--\s*>/ig,'</script>');  // open script tag
                $repeater_items_container.append(
                    _html
                        .replace( /([\"\'])(\|)(_to_clone_)(.+)?(-)(num)(-)(.+)?(\|)/g, '$1$2$3$4$5'+index+'$7$8$9') // panel and widget
                        .replace( /[\"\'](\|)(_to_clone_)(.+)?-child-(.+)?-(\d+)-(.+)\|/g, '"'+name_format+'' ) // metabox
                        .replace( /[\"\']\|_to_clone_(.+)?-(\d+)-(.+)\|/g, '"'+name_format+'' ) // metabox
                );

                // Event for when new item added
                $this.closest('.bf-section').trigger('repeater_item_added',[$repeater_items_container]);

                // Remove temporary placeholder input
                $repeater_items_container.closest('.bf-section').find('input.placeholder-input').remove();
            });

        },

        setup_field_border: function(){

            $('.bf-section-border-option').each(function(){
                refresh_border( $(this).closest(".bf-section-container"), 'first-time');
            });


            // When all changed
            $('.bf-section-container .single-border.border-all select, .bf-section-container .single-border.border-all input').on('change', function(evt, params) {
                refresh_border( $(this).closest(".bf-section-container"), 'all');
            });
            $('.bf-section-container .single-border.border-all input.bf-color-picker').on('change', function() {
                refresh_border( $(this).closest(".bf-section-container"), 'all');
            });

            // When top border changed
            $('.bf-section-container .single-border.border-top select, .bf-section-container .single-border.border-top input').on('change', function(evt, params) {
                refresh_border( $(this).closest(".bf-section-container"), 'top');
            });

            // When right border changed
            $('.bf-section-container .single-border.border-right select, .bf-section-container .single-border.border-right input').on('change', function(evt, params) {
                refresh_border( $(this).closest(".bf-section-container"), 'right');
            });

            // When bottom border changed
            $('.bf-section-container .single-border.border-bottom select, .bf-section-container .single-border.border-bottom input').on('change', function(evt, params) {
                refresh_border( $(this).closest(".bf-section-container"), 'bottom');
            });

            // When left border changed
            $('.bf-section-container .single-border.border-left select, .bf-section-container .single-border.border-left input').on('change', function(evt, params) {
                refresh_border( $(this).closest(".bf-section-container"), 'left');
            });


            // Used for refreshing all styles of border field
            function refresh_border( $parent, type ){
                type = typeof type !== 'undefined' ? type : 'all';

                var $preview = $parent.find('.border-preview .preview-box');

                var _css = $preview.css([]);

                switch ( type ){

                    case 'top':
                        _css = refresh_border_field( $parent, 'top', _css);
                        break;

                    case 'right':
                        _css = refresh_border_field( $parent, 'right', _css);
                        break;

                    case 'bottom':
                        _css = refresh_border_field( $parent, 'bottom', _css);
                        break;

                    case 'left':
                        _css = refresh_border_field( $parent, 'left', _css);
                        break;

                    case 'all':
                        _css = refresh_border_field( $parent, 'all', _css);
                        break;

                    case 'first-time':

                        if( $parent.find('.single-border.border-all').length ){
                            _css = refresh_border_field( $parent, 'all', _css);
                        }else{

                            if( $parent.find('.single-border.border-top').length ){
                                _css = refresh_border_field( $parent, 'top', _css);
                            }

                            if( $parent.find('.single-border.border-right').length ){
                                _css = refresh_border_field( $parent, 'right', _css);
                            }

                            if( $parent.find('.single-border.border-bottom').length ){
                                _css = refresh_border_field( $parent, 'bottom', _css);
                            }

                            if( $parent.find('.single-border.border-left').length ){
                                _css = refresh_border_field( $parent, 'left', _css);
                            }

                        }

                }

                $preview.css( _css );
            }

            // Used for refreshing border preview
            function refresh_border_field( $parent, type, _css ){

                switch ( type ){

                    case  'top':
                        _css.borderTopWidth = $parent.find('.single-border.border-top .border-width input').val() +'px';
                        _css.borderTopStyle = $parent.find('.single-border.border-top select option:selected').val();
                        _css.borderTopColor = $parent.find('.single-border.border-top .bf-color-picker').val();
                        break;

                    case  'right':
                        _css.borderRightWidth = $parent.find('.single-border.border-right .border-width input').val() +'px';
                        _css.borderRightStyle = $parent.find('.single-border.border-right select option:selected').val();
                        _css.borderRightColor = $parent.find('.single-border.border-right .bf-color-picker').val();
                        break;

                    case  'bottom':
                        _css.borderBottomWidth = $parent.find('.single-border.border-bottom .border-width input').val() +'px';
                        _css.borderBottomStyle = $parent.find('.single-border.border-bottom select option:selected').val();
                        _css.borderBottomColor = $parent.find('.single-border.border-bottom .bf-color-picker').val();
                        break;

                    case  'left':
                        _css.borderLeftWidth = $parent.find('.single-border.border-left .border-width input').val() +'px';
                        _css.borderLeftStyle = $parent.find('.single-border.border-left select option:selected').val();
                        _css.borderLeftColor = $parent.find('.single-border.border-left .bf-color-picker').val();
                        break;

                    case 'all':
                        _css.borderWidth = $parent.find('.single-border.border-all .border-width input').val() +'px';
                        _css.borderStyle = $parent.find('.single-border.border-all select option:selected').val();
                        _css.borderColor = $parent.find('.single-border.border-all .bf-color-picker').val();
                        break;

                }

                return _css;

            }


        },

        // Setup Image Select Field
        setup_field_image_select: function(){

            // Open Close Select Options Box
            var $doc = $(document);

            $doc.off('click.image-select', '.better-select-image').off('click.image-select');

            $doc.on('click.image-select', '.better-select-image' ,function(e){
                var $_target = $(e.target);

                if ( $_target.hasClass('selected-option') || $_target.hasClass('select-options')  ) {
                    // close All Other open boxes
                    $(this).toggleClass('bf-opened');
                    return;
                }

            });

            // Close Everywhere clicked
            $doc.on('click.image-select',function( e ){
                if (e.target.class !== 'better-select-image' && $(e.target).parents('.better-select-image').length === 0) {
                    $('.better-select-image').each(function(){
                        if($(this).hasClass('bf-opened')){
                            $(this).removeClass('bf-opened');
                        }
                    });
                }
            });
            // Select when clicked
            $doc.on('click.image_select', '.better-select-image .image-select-option' ,function(e){
                var $this = $(this);
                var $parent = $this.closest('.better-select-image');
                var $input = $parent.find('input[type=hidden]');
                var $selected_label = $parent.find('.selected-option');

                if($this.hasClass('selected')){
                    e.preventDefault();
                    $parent.find('.select-options').toggleClass('bf-opened');
                }
                else{
                    $input.attr('value',$this.data('value')).trigger('change');
                    $parent.find('.image-select-option.selected').removeClass('selected');
                    $this.addClass('selected');
                    $selected_label.html($this.data('label'));
                    $parent.toggleClass('bf-opened');
                }
            });
        },


        // Setup input fields prefix and postfix
        setup_field_with_prefix_or_postfix: function(){

            $(document).on('click', '.bf-prefix-suffix', function(){
                $(this).siblings(':input').focus();
            })


            $('.bf-field-with-prefix-or-suffix').each(function(){
                if( $(this).find('.bf-prefix').exist() )
                    $(this).find(':input').css( 'padding-left', ( $(this).find('.bf-prefix').width() + 15 ) );
                if( $(this).find('.bf-suffix').exist() )
                    $(this).find(':input').css( 'padding-right', ( $(this).find('.bf-suffix').width() + 15 ) );
            });
        },

        // Setup Switch check box field
        setup_field_switch: function() {

            var $doc = $(document);

            if ($doc.data('bf-switch-init')) {
                return;
            }

            $doc.on('click', ".cb-enable", function () {
                var parent = $(this).parents('.bf-switch');
                $('.cb-disable', parent).removeClass('selected');
                $(this).addClass('selected');

                $('.checkbox', parent).attr('value', 1).trigger('change')[0].dispatchEvent(new Event('input'));
            });

            $doc.on('click', ".cb-disable", function () {
                var parent = $(this).parents('.bf-switch');
                $('.cb-enable', parent).removeClass('selected');
                $(this).addClass('selected');

                $('.checkbox', parent).attr('value', 0).trigger('change')[0].dispatchEvent(new Event('input'));
            });


            $doc.data('bf-switch-init', true);
        },

        // Set up Slider filed
        setup_field_slider: function(){

            var selector = '';

            // prepare selector
            if( better_framework_loc.type == 'widgets' ){
                selector = '#widgets-right .bf-slider-slider,#elementor-panel .bf-slider-slider';
            }
            else{
                selector = '.bf-slider-slider';
            }

            $(selector).each( function(){

                var _min = $(this).data('min');
                var _max = $(this).data('max');
                var _step = $(this).data('step');
                var _animate = $(this).data('animation') == 'enable' ? true : false;
                var _dimension = ' ' + $(this).data('dimension');
                var _val = $(this).data('val');
                var _this = $(this);

                $(this).slider({
                    range: 'min',
                    animate: _animate,
                    value: _val,
                    step: _step,
                    min: _min,
                    max: _max,
                    slide: function( event, ui ) {
                        _this.find(".ui-slider-handle").html( '<span>'+ui.value+_dimension+'</span>' );
                        _this.siblings('.bf-slider-input').val( ui.value ).change();
                    },
                    create: function( event, ui ) {
                        _this.find(".ui-slider-handle").html( '<span>'+_val+_dimension+'</span>' );
                    }
                });

                $(this).removeClass('not-prepared');

            });
        },

        error_copy: function() {

            $(document).on('click', '.bs-pages-error-copy', function (e) {
                e.preventDefault();
                var $this = $(this),
                    $modal = $this.closest('.bs-modal');

                $('.bs-pages-error-section textarea',$modal).focus().select();

                if (document.execCommand('copy')) {
                    var orgLabel = $this.html();
                    $this.html($this.data('copied'));
                    $this.delay(750).queue(function (n) {
                        $this.html(orgLabel);
                        n();
                    });
                }
            });
        },
        // Setup color picker fields
        setup_field_color_picker: function($context){

            var fixWidgetBtn = function(event) {

                if(better_framework_loc.type !== "widgets") {
                    return ;
                }

                if(! event.originalEvent) {
                    return ;
                }

                $(this).closest('.widget-inside').find('.widget-control-save').prop( 'disabled', false ).val( better_framework_loc.translation.widgets.save );
            };

            var initColorPicker = function($context) {

                $('.bs-color-picker-value', $context).wpColorPicker({
                    change: function( event, ui ) {

                        fixWidgetBtn.call(this,event);

                        if(better_framework_loc.page_builder.indexOf('Elementor') > -1) {

                            // fix elementor save issue
                            setTimeout(function() {
                                $(event.target).change()
                            });
                        }
                    },
                    clear: function(event, ui) {

                        fixWidgetBtn.call(this,event);

                    }
                });
            };

            // FIX: performance

            initColorPicker($context);

            $context.on('repeater_item_added', '.bf-section', function(e,$repeater) {

                initColorPicker(
                    $repeater.find('.bf-repeater-item:last-child')
                );
            });

            return ;

            var $doc = $(document.body);

            if($doc.data('color-picker-init')) {
                return ;
            }

            $doc.on('click', '.bs-color-picker-wrapper:not(.bs-clicked) .bs-wp-picker-container', function (e) {
                e.preventDefault();

                var $this = $(this).closest('.bs-color-picker-wrapper');
                $this.addClass('bs-clicked');
                $this.find('.bs-color-picker-value').wpColorPicker().wpColorPicker('open');

            });


            $doc.on('click', '.bs-color-picker-wrapper .bs-wp-picker-container', function (e) {
                e.preventDefault();

                var $this = $(this);

                setTimeout(function () {

                    var $wrapper = $this.closest('.bs-color-picker-wrapper');

                    // Close another color picker before opening another one
                    var $maybeOpenColorPickers = $(".bs-color-picker-wrapper.bs-clicked").not($wrapper);

                    $maybeOpenColorPickers.each(function () {

                        var $this  = $(this),
                            isOpen = $this.find(".wp-picker-container:visible .iris-picker").is(":visible");

                        if (isOpen) {

                            $('.bs-color-picker-value', this).wpColorPicker('close');
                        }
                    });
                });

            });

            $doc.data('color-picker-init',true);
        },

        // Setup Sorter field
        setup_field_sorter: function(){

            // Sorters in Widgets Page
            if( better_framework_loc.type == 'widgets' ){
                $( "#widgets-right .bf-sorter-list" ).sortable({
                    placeholder: "placeholder-item",
                    cancel: "li.disable-item"
                });
            }
            // Sorters Everywhere
            else{
                $( ".bf-sorter-list" ).sortable({
                    placeholder: "placeholder-item",
                    cancel: "li.disable-item"
                });
            }

            var sorterUpdated = function(evt, params) {

                var $this = (this);

                if( typeof $this.attr('checked') != "undefined" ){
                    $this.closest('li').addClass('checked-item');
                }else{
                    $this.closest('li').removeClass('checked-item');
                }

            };

            $( ".bf-sorter-list" ).sortable({
                placeholder: "placeholder-item",
                cancel: "li.disable-item"
            });

            $('.bf-section-container li input')
                .off('change', sorterUpdated)
                .on('change', sorterUpdated);


            jQuery(document).on('bf-component-did-mount', function(e,target) {

                $( ".bf-sorter-list" ).sortable({
                    placeholder: "placeholder-item",
                    cancel: "li.disable-item"
                });

                $('.bf-section-container li input')
                    .off('change', sorterUpdated)
                    .on('change', sorterUpdated);

            });
        },

        // Setup image radio
        setup_field_image_radio: function(){

            $(document).on( 'click', '.bf-image-radio-option', function(e){

                var $this = $(this);

                var $parent = $this.parent();
                // Uncheck all radio button for this field
                $parent.find(':radio').prop("checked", false);

                // Checked the clicked radio button
                // Fires change for third party code usage
                var $checked = $this.find(':radio');
                $checked.prop("checked", true).change();

                // Remove checked class from field options and add checked class to clicked option
                $this.siblings().removeClass('checked').end().addClass('checked');

                // Prevent Browser Default Bahavior
                e.preventDefault();

                $this.closest('.image-radio-field')

                $parent.find('.image-radio-value')
                    .val($checked.val()).change()
                    [0].dispatchEvent(new Event('input'));
            });

        },

        // Setup Background Field
        setup_field_background_image: function(){

            $('body').on( 'click', '.bf-background-image-upload-btn' ,function() {

                var _this = $(this);

                var media_title = _this.attr('data-mediaTitle');
                var media_button = _this.attr('data-mediaButton');

                // prepare uploader
                var custom_uploader;

                if (custom_uploader) {
                    custom_uploader.open();
                    return;
                }

                custom_uploader = wp.media.frames.file_frame = wp.media({
                    title: media_title,
                    button: {
                        text: media_button
                    },
                    multiple: false,
                    library: { type : 'image'}
                });

                // when select pressed in uploader popup
                custom_uploader.on('select', function() {

                    var attachment = custom_uploader.state().get('selection').first().toJSON();

                    _this.siblings('.bf-background-image-preview').find("img").attr( "src", attachment.url );

                    var $input = _this.siblings('.bf-background-image-input');
                    $input.val( attachment.url ).change();
                    $input[0].dispatchEvent(new Event('input'));

                    _this.siblings('.bf-background-image-preview').show(100);
                    _this.siblings('.bf-background-image-uploader-select-container').removeClass('hidden').show(100);
                    _this.siblings('.bf-background-image-remove-btn').show(100);


                });

                // open media poup
                custom_uploader.open();

                return false;
            });
            $('body').on( 'click', '.bf-background-image-remove-btn' ,function() {
                var _this = $(this),
                    $input = _this.siblings('.bf-background-image-input');

                $input.val('').change();
                $input[0].dispatchEvent(new Event('input'));

                // hide remove button, select and preview
                _this.hide( 100 );
                _this.siblings('.bf-background-image-uploader-select-container').addClass('hidden').hide( 100 );
                _this.siblings('.bf-background-image-preview').hide( 100 );

            });
        },

        // Setup Date Picker Field
        setup_field_date_picker: function(){

            $('.bf-date-picker-input').each( function(){

                var _date_format = $(this).data('date-format');
                $(this).datepicker({ dateFormat: _date_format });

            });


        },

        // Setup Image Checkbox field
        setup_field_image_checkbox: function(){

            // Image Checkbox Codes
            $(document).on( 'click', '.bf-image-checkbox-option', function(e){
                var _this = $(this);
                var _checkbox = _this.find(':checkbox');

                // If checkbox is check uncheck it and remove checked class from it

                if ( _checkbox.is(':checked') ) {
                    _checkbox.prop( 'checked', false );
                    _this.removeClass('checked');
                }
                else {
                    _checkbox.prop( 'checked', true );
                    _this.addClass('checked');
                }

                // Prevent Browser Default Bahavior
                e.preventDefault();
            });

            $('.is-sortable .bf-controls-image_checkbox-option').sortable({
                helper: 'clone',
                revert: true,
                forcePlaceholderSize: true,
                opacity: 0.5
            });

        },

        // Setup Media Uploader Field
        setup_field_media_uploader: function(){

            $('body').on( 'click', '.bf-media-upload-btn' ,function() {


                var _this = $(this),
                    custom_uploader,
                    options = _this.data('mediasettings') || {};

                if (custom_uploader) {
                    custom_uploader.open();
                    return;
                }

                var library = {
                    title:     _this.data('mediatitle'),
                    //library:   wp.media.query({ type:  ['font/woff'] }),
                    multiple:  false,
                    date:      false
                };

                if(options.type) {
                    library.library = wp.media.query({ type:  options.type });
                }

                custom_uploader = wp.media.frames.file_frame = wp.media({
                    button: {
                        text: _this.data('buttontext')
                    },
                    states: [
                        new wp.media.controller.Library(library)
                    ]
                });

                custom_uploader.on('select', function() {
                    var attachment = custom_uploader.state().get('selection').first().toJSON();

                    if(options.type && $.inArray(attachment.mime, options.type ) === -1 ) {
                        return false;
                    }

                    _this.siblings(':input').val( attachment.url );
                    custom_uploader.state().get('selection').each( function(i,o){
                    });
                });
                custom_uploader.open();
                return false;
            });

        },

        // Setup Media Image upload field
        setup_field_media_image: function(){

            var _media_image_selector = '.bf-media-image-upload-btn';

            $(document).off('click', _media_image_selector).on( 'click', _media_image_selector ,function( e ) {
                var _this = $(this),
                    $_input = _this.siblings(':input');

                var custom_uploader;

                var media_title = _this.data('media-title');
                var media_button_text = _this.data('button-text');

                custom_uploader = wp.media.frames.file_frame = wp.media({
                    title: media_title,
                    button: {
                        text: media_button_text
                    },
                    multiple: false
                });

                custom_uploader.on('select', function() {

                    $_input.removeClass('bf-invalid-value');

                    var attachment = custom_uploader.state().get('selection').first().toJSON();

                    if( _this.hasClass( 'bf-media-type-id' ) ){
                        $_input.val( attachment.id ).trigger('change');
                    }else{
                        $_input.val( attachment.url ).trigger('change');
                    }

                    $_input.change();

                    $_input[0].dispatchEvent(new Event('input'));

                    var preview = '';

                    if( typeof _this.data('size') != "undefined" ){

                        var var_name = _this.data('size');

                        if( typeof attachment.sizes[var_name] != "undefined" ){
                            preview = attachment.sizes[var_name].url;
                        }else{
                            preview = attachment.url;
                        }

                    }else{
                        preview = attachment.url;
                    }

                    _this.siblings('.bf-media-image-remove-btn').show();
                    _this.siblings('.bf-media-image-preview').find('img').attr( 'src', preview );
                    _this.siblings('.bf-media-image-preview').show();

                    // Global change event
                    _this.trigger( 'bf-media-image-changed', {
                        'type': _this.hasClass( 'bf-media-type-id' ) ? 'id' : 'src',
                        'name': $_input.attr('name'),
                        'attachment': attachment
                    } );

                    // field Global change event
                    _this.trigger( 'bf-media-image-changed:' + $_input.attr('name'), {
                        'type': _this.hasClass( 'bf-media-type-id' ) ? 'id' : 'src',
                        'name': $_input.attr('name'),
                        'attachment': attachment
                    } );

                });

                custom_uploader.open();

                return false;
            });

            $(document).off('keyup', '.bf-media-image-input').on('keyup', '.bf-media-image-input', function (e) {
                var _this = $(this),
                    $_input = $(this);

                var link_regex = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/;

                if (!link_regex.test($_input.val())) {
                    $_input.addClass('bf-invalid-value');

                    _this.siblings('.bf-media-image-remove-btn').hide();
                    _this.siblings('.bf-media-image-preview').find('img').attr('src', '');
                    _this.siblings('.bf-media-image-preview').hide();

                    return false;
                } else {
                    $_input.removeClass('bf-invalid-value');
                }

                var preview = '';

                _this.siblings('.bf-media-image-remove-btn').show();
                _this.siblings('.bf-media-image-preview').find('img').attr('src', $_input.val());
                _this.siblings('.bf-media-image-preview').show();

                // Global change event
                _this.trigger('bf-media-image-changed', {
                    'type': 'src',
                    'name': $_input.attr('name'),
                    'attachment': $_input.val()
                });

                // field Global change event
                _this.trigger('bf-media-image-changed:' + $_input.attr('name'), {
                    'type': 'src',
                    'name': $_input.attr('name'),
                    'attachment': $_input.val()
                });

            });

            $(document).on( 'click', '.bf-media-image-remove-btn' ,function() {
                var _this = $(this);

                var $input = _this.siblings('.bf-media-image-input').val( '' ).change();

                $input[0].dispatchEvent(new Event('input'));

                // hide remove button, select and preview
                _this.hide();
                _this.siblings('.bf-media-image-preview').hide();

            });

        },

        pre_defined_styles: function(el){

            $("#bf-panel .select-popup-field.style").on('select-popup-confirm', function(e,modal) {

                $('.bf-save-button').click();
                modal.change_skin({skin: 'loading', template: 'default'});

                return false;
            });
        },

        // Setup Ajax Select Field
        setup_field_ajax_select: function(){

            // TODO : Vahid Shit! Refactor this

            function bf_ajax_generate_options_object( _that ){
                var _object_ = {};
                _object_.preloader 	    = _that.siblings('.bf-search-loader');
                _object_.static_parent  = _that.closest('.bf-ajax_select-field-container');
                _object_.field_controls = _that.closest('.bf-ajax_select-field-container');
                _object_.controls_box   = _that.siblings('.bf-ajax-suggest-controls');
                _object_.hidden_field   = _that.siblings('input[type=hidden]');
                _object_.result_box	    = _that.siblings('.bf-ajax-suggest-search-results');
                _object_._this	    	= _that;
                return _object_;
            };

            var bf_ajax_input_timeOut  = null;

            var bf_ajax_input_interval = 850;

            $(document)
                .off( 'keyup.ajaxselect', '.bf-ajax-suggest-input')
                .on( 'keyup.ajaxselect', '.bf-ajax-suggest-input', function(e){

                var _this   =   $(e.target),
                    _s      =   bf_ajax_generate_options_object( _this );

                _this.appendHTML = function( html ){
                    _s.result_box.append(html);
                };

                _this.removeResults = function(){
                    _s.result_box.find('li').remove();
                };

                _this.generateResultItems = function( json ){

                    var result = '';

                    $.each( $.parseJSON(json), function(i,o){
                        result += '<li class="ui-state-default" data-id="'+i+'">'+o+' <i class="del fa fa-remove"></i></li>';
                    });

                    return result;
                };

                _this.get = function( key, callback ){

                    var is_repeater = _this.parent().is('.bf-repeater-controls-option'),
                        form_data   = {
                            action 		     : 'bf_ajax',
                            reqID  	 	     : 'ajax_field',
                            type	 	     : better_framework_loc.type,
                            field_ID 	     : _s.hidden_field.attr('name'),
                            nonce 	 	     : better_framework_loc.nonce,
                            key   	         : key,
                            is_repeater      : is_repeater ? 1 : 0,
                            callback         : _s.hidden_field.data('callback'),
                            bf_call_token    : _s.hidden_field.data('token'),
                            exclude          : _s.hidden_field.val()
                        },
                        result;

                    if( is_repeater )
                        form_data.repeater_id = _this.closest('.bf-nonrepeater-section').data('id');

                    $.ajax({
                        type	 : 'POST',
                        dataType : 'html',
                        url		 : better_framework_loc.bf_ajax_url,
                        data	 : form_data,
                        success  : function(data, textStatus, XMLHttpRequest){
                            callback(data);
                        },
                        error: function(MLHttpRequest, textStatus, errorThrown){
                            callback(false);
                        }
                    });
                };

                clearTimeout( bf_ajax_input_timeOut );

                bf_ajax_input_timeOut = setTimeout(function() {

                    _s.preloader.addClass('loader');

                    _this.get( _this[0].value, function(data){

                        _s.preloader.removeClass('loader');

                        if( data === false ){
                            alert( 'Something Wrong Happend!' );
                            return;
                        }

                        _s.controls_box.sortable({

                            update: function(event, ui){
                                var _this = ui.item, value = '', _s_ = bf_ajax_generate_options_object( _this.parent().siblings('.bf-ajax-suggest-input') );

                                _s_.controls_box.find('li:not(".ui-sortable-placeholder")').each( function(){
                                    value += $(this).data('id') + ','
                                });

                                _s_.hidden_field.val( value.replace( ',,', ',' ).replace( /^,+/ ,'' ).replace( /,+$/, '' ) );
                                _s_.hidden_field.change();

                                _s_.hidden_field[0].dispatchEvent(new Event('input'));

                            }

                        });

                        if( data == -1 ){
                            return;
                        }

                        _this.removeResults(); // Remove Current Results

                        var HTML = _this.generateResultItems( data ); // Generate HTML tags from JSON

                        _this.appendHTML( HTML ); // Append The HTMLs

                        _s.result_box.fadeIn();

                    })

                }, bf_ajax_input_interval);
            });

            $(document)
                .off('blur.ajaxselect', '.bf-ajax-suggest-input')
                .on( 'blur.ajaxselect', '.bf-ajax-suggest-input', function(){

                var _s = bf_ajax_generate_options_object($(this));

                _s.result_box.fadeOut();

            });

            $(document)
                .off('focus.ajaxselect', '.bf-ajax-suggest-input')
                .on( 'focus.ajaxselect', '.bf-ajax-suggest-input', function(){

                var _s = bf_ajax_generate_options_object($(this));

                if( _s.result_box.find('li').size() > 0 )
                    _s.result_box.fadeIn();

            });

            $(document)
                .off('click.ajaxselect', '.bf-ajax-suggest-search-results li')
                .on( 'click.ajaxselect', '.bf-ajax-suggest-search-results li', function(e){
                var _this   = $( e.target ),
                    _s      = bf_ajax_generate_options_object( _this.parent().siblings('.bf-ajax-suggest-input') );

                _s.result_box.fadeOut();

                if( _s.controls_box.find('li[data-id="'+_this.data('id')+'"]').exist() )
                    return true;

                var value = _s.hidden_field.val() === undefined ? [] : _s.hidden_field.val().split(',');

                value.push( _this.data('id') );

                _s.controls_box.append( e.target.outerHTML );

                _s.hidden_field.val($.array_unique( value ).join(',').replace(',,',',').replace(/^,+/,'').replace(/,+$/,''));
                _s.hidden_field.change();

                _s.hidden_field[0].dispatchEvent(new Event('input'));


                $(this).remove();

                return false;

            });

            $(document)
                .off('click.ajaxselect', '.bf-ajax-suggest-controls li .del')
                .on( 'click.ajaxselect', '.bf-ajax-suggest-controls li .del', function(e){

                if( confirm('Are You Sure?') ){
                    var _new,
                        _this = $(e.target).parent(),
                        _array,
                        ID = _this.data('id'),
                        _s = bf_ajax_generate_options_object( _this.parent().siblings('.bf-ajax-suggest-input') );

                    _this.remove();

                    _array = _s.hidden_field.val().split(',');

                    _new = $.grep( _array, function(value) {
                        return value != ID;
                    });

                    _s.hidden_field.val( _new.join( ',' ).replace( ',,', ',' ).replace( /^,+/, '' ).replace( /,+$/, '' ) ).change();

                    _s.hidden_field[0].dispatchEvent(new Event('input'));

                }
            });

            $('.bf-ajax-suggest-controls').sortable({
                update: function(event, ui){
                    var _this   =   ui.item,
                        value   =   '',
                        _s_     =   bf_ajax_generate_options_object( _this.parent().siblings('.bf-ajax-suggest-input') );

                    _s_.controls_box.find('li:not(".ui-sortable-placeholder")').each( function(){
                        value += $(this).data('id') + ','
                    });

                    _s_.hidden_field.val( value.replace( ',,', ',' ).replace( /^,+/ ,'' ).replace( /,+$/, '' ) );
                    _s_.hidden_field.change();

                    _s.hidden_field[0].dispatchEvent(new Event('input'));
                }
            });
        },
        init_mega_menus: function() {

            function sanitizeDepthValue(value) {
                if (typeof value === 'string') {
                    value = parseInt(value);
                }
                var t = typeof value;
                if(t === 'number' || t === 'object') {
                    return value;
                }
            }

            function getSelectPopupData($el) {
                var data = $(".select-popup-data", $el).text();

                if (data)
                    return JSON.parse(data);

                return false;
            }
            function wpMenuItemTrigger($item) {
                var currentDepth = parseInt($item.menuItemDepth());

                $(".better-select-popup-mega-menu", $item).each(function () {
                    var $select      = $(this),
                        currentValue = $(".select-value", $select).val(),
                        data         = getSelectPopupData($select);


                    if (typeof data[ currentValue ] !== 'undefined' && typeof data[ currentValue ].depth !== 'undefined') {
                        var supportedDepth = sanitizeDepthValue(data[ currentValue ].depth);

                        if (supportedDepth === -1) { // any depth supported!
                            return;
                        }

                        var showNotice = false;
                        if (typeof supportedDepth === 'object') {
                            showNotice = !( supportedDepth[ 0 ] <= currentDepth &&
                                            supportedDepth[ 1 ] >= currentDepth  );
                        } else {
                            showNotice = supportedDepth !== currentDepth;
                        }

                        $select.next('.mega-menu-depth-notice')[ showNotice ? 'show' : 'hide' ]();

                    }
                });
            }

            function wpMenuItemsTrigger($item) {
                wpMenuItemTrigger($item); // sorted item

                var children = $item.childMenuItems();

                if (children && children.length) {
                    children.each(function () {
                        wpMenuItemTrigger($(this));
                    });
                }
            }

            // Register an event for after item sorted
            wpNavMenu.menuList.on('sortstop', function (e, ui) {
                setTimeout(function () { // low priority
                    wpMenuItemsTrigger(ui.item);
                }, 100);
            });


            // Init WP Menu Items
            wpNavMenu.menuList.children('.menu-item-depth-0').each(function() {
                wpMenuItemsTrigger($(this));
            });

            $("#menu-to-edit").on('select-popup-loaded','.menu-item .better-select-popup-mega-menu', function(e,data,modal) {

                var $selectPopup  = $(this),
                    popupSettings = getSelectPopupData($selectPopup),
                    currentDepth  = parseInt($selectPopup.closest('.menu-item').menuItemDepth());

                if(! popupSettings) {
                    return ;
                }

                var bsModal = modal.bsModal;
                data[ 0 ].items.forEach(function (item,i) {

                    if(popupSettings[item.id ] &&
                       typeof popupSettings[item.id ].depth !== 'undefined') {

                        var supportedDepth = sanitizeDepthValue(popupSettings[item.id ].depth),
                            isValid = true;

                        if (typeof supportedDepth === 'object') {
                            isValid = supportedDepth[ 0 ] <= currentDepth &&
                                            supportedDepth[ 1 ] >= currentDepth ;
                        } else if(supportedDepth !== -1) {
                            isValid = supportedDepth === currentDepth;
                        }

                        var $itemInModal =  $(".bssm-item[data-item-id='"+item.id+"']",bsModal.$modal);
                        $(".bf-toggle-item-status>a",$itemInModal)[isValid ? 'removeClass' : 'addClass']('disabled');
                    }
                });

            }).on('select-popup-selectd','.menu-item .better-select-popup-mega-menu', function() {
               var $selectedItem  = $(this).closest('.menu-item');

                wpMenuItemTrigger($selectedItem);
            });
        },

        admin_notice_fix: function () {

            // collapse long notices
            $(".bf-notice-wrapper").each(function () {
                var $notice = $(this);

                var label = $notice.data('show-all') || better_framework_loc.translation.show_all;
                if ($notice.height() > 150) {
                    $(".bf-notice-text-container", $notice)
                        .append(
                            '<div class="bf-notice-message-collapse">'
                            + '<a class="bf-notice-message-toggle title" href="#">' + label + '</a></div>')
                        .addClass('bf-close');
                }
            }).on('click', '.bf-notice-message-toggle', function () {

                var animTime = 50,
                    $this    = $(this);

                var $content = $(this).closest('.bf-notice-wrapper');

                $('.bf-notice-text', $content).css('max-height', 'none');

                $content.css('max-height', '3000px').delay(animTime).queue(function (n) {
                    $content.find('.bf-notice-text-container').removeClass('bf-close').css('max-height', 'none');

                    $this.closest('.bf-notice-message-collapse').remove();

                    n();
                });

                return false;
            });
        },

        vc_modifications:function() {

            // FIX: visual composer have trouble with shortcodes that contain content attribute
            if(typeof vc  === 'object' && vc.shortcodes) {

                vc.shortcodes.on('stringify', function (e, options) {

                    // options is wp.shortcode.string first argument
                    if (options && options.attrs && options.tag) {

                        if(options.tag.substr(0,3) === 'bs-') {

                            if(options.attrs.content_) {
                              options.attrs.content = options.attrs.content_;

                                delete options.attrs.content_;
                            } else if(options.content) {
                                // if shortcode contain content in it, type of the shortcode (options.type) must change to any string except 'single' or 'self-close' otherwise the content will be lose!
                                // @see wp.shortcode.string
                                options.type = 'full';
                            }
                        }
                    }
                });
            }
        },

        pageBuilderCompatibility: {

            init: function () {

                if (
                    better_framework_loc.page_builder.indexOf('KCP') > -1
                    ||
                    better_framework_loc.page_builder.indexOf('KC') > -1
                ) { // isKingComposer

                    this.kingComposer.init();

                }
                if (better_framework_loc.page_builder.indexOf('Elementor') > -1) {

                    this.elementor.init();

                }
                if (better_framework_loc.page_builder.indexOf('SiteOrigin') > -1) {

                    this.siteOrigin.init();

                }
                if (better_framework_loc.page_builder.indexOf('Gutenberg') > -1) {

                    this.gutenberg.init();
                }
            },

            kingComposer: {

                loadedFields : [],

                init: function() {

                    if(! window.kc || ! window.kc.backbone) {
                        return ;
                    }

                    var main = this;

                    window.kc.backbone.settings = function( e, atts,p ) {

                        if (e === undefined)
                            return;


                        var el = ( typeof( e.tagName ) != 'undefined' ) ? e : this;

                        var mid = kc.get.model(el),
                            data = kc.storage[mid],
                            popup = kc.tools.popup;

                        if (kc.maps[data.name] === undefined)
                            return false;

                        var map = $().extend({}, kc.maps['_std']);
                        map = $().extend(map, kc.maps[data.name]);


                        if (map.title === undefined)
                            map.title = map.name + ' Settings';

                        var attz = {
                            title: map.title,
                            width: map.pop_width,
                            scrollBack: false,
                            scrollTo: false,
                            class: data.name + '_wrpop kc-elm-settings-popup',
                        };

                        if (atts !== undefined)
                            attz = $.extend(attz, atts);

                        var pop = popup.render(el, attz);

                        var fixPopupWidth = function() {
                            var totalWidth = 40;
                            pop.find('.kc-pop-tabs>li').each(function() {
                                totalWidth+= this.width ? this.with : this.offsetWidth;
                            }).promise().done(function() {

                                if(popup.el.width()<totalWidth)
                                popup.el.width(totalWidth);
                            });
                        };

                        var triggerLoadedEvent = function() {

                            $(document).trigger('bf-kc-tab-loaded', [pop.find('.form-active')]);
                        };

                        pop.data({model: mid, callback: kc.backbone.save});

                        var renderPopup = function () {

                            var form = $('<form class="fields-edit-form kc-pop-tab form-active"></form>'),
                                tab_icon = 'et-puzzle';

                            if (map.params[0] !== undefined) {

                                kc.params.fields.render(form, map.params, data.args);

                            } else {

                                for (var n in map.params) {


                                    popup.add_tab(pop, {
                                        title: n,
                                        class: 'kc-tab-general-' + kc.tools.esc_slug(n),
                                        cfg: n + '|' + mid + '|' + data.name,
                                        callback: kc.params.fields.tabs
                                    });
                                }

                                pop.find('.m-p-wrap>.kc-pop-tabs>li').first().trigger('click');

                            }

                            pop.find('.m-p-body').append(form);

                             /***  /
                            /**** /	Add presets tab for every element
                           /*****/

                            popup.add_tab(pop, {

                                title: 'Presets',
                                class: 'kc-tab-general-presets',
                                cfg: 'presets|' + mid + '|' + data.name,

                                callback: kc.backbone.presets
                            });
                        };

                        kc.ui.fix_position_popup(pop);

                        function appendTemplate(templateId, html) {

                            var elementId = 'tmpl-kc-field-type-' + templateId + '-template',
                                element = document.getElementById(elementId);

                            element && element.remove();

                            var template = document.createElement('script');
                            template.id = elementId;
                            template.type = 'text/html';
                            template.appendChild(document.createTextNode(html));

                            document.body.appendChild(template);

                            return true;
                        }

                        data.deferred = main.getDeferredFieldsType(data.name);

                        if ('kc_wp_widget' === data.name) {

                            // load widgets kc_admin_footer()

                        } else if (data.deferred) {

                            var ajaxData = {
                                token: $("#bf_kc_ajax_field").val(),
                                shortcode: data.name,
                            };

                            if('always' === data.deferred) {
                                var shortcodeArgs = {};
                                for (var key in data.args) {
                                    if (data.args.hasOwnProperty(key)) {
                                        shortcodeArgs[key] = data.args[key];
                                    }
                                }
                                ajaxData.shortcode_atts = shortcodeArgs;
                            }

                            // Append Loading
                            pop.find('.m-p-body').append('<div class="bs-modal-loading">\n\t<div class="la-line-scale-pulse-out-rapid la-2x">\n\t\t<div></div>\n\t\t<div></div>\n\t\t<div></div>\n\t\t<div></div>\n\t\t<div></div>\n\t</div>\n</div>\n')

                            var ajax = wp.ajax.post('bf_load_kc_fields', ajaxData);

                            ajax.done(function (res) {

                                // Remove loading
                                pop.find('.bs-modal-loading').remove();

                                res.global_fields && res.global_fields.forEach(function (tpl) {

                                    appendTemplate(tpl.id, tpl.html);

                                    if (kc_param_types_support.indexOf(tpl.id) === -1)
                                        kc_param_types_support.push(tpl.id);
                                });

                                res.dedicated_fields && res.dedicated_fields.forEach(function (tpl) {

                                    appendTemplate(tpl.id, '<div class="bf-deferred-kc-field {{data.name}}"></div>');

                                    if (kc_param_types_support.indexOf(tpl.id) === -1)
                                        kc_param_types_support.push(tpl.id);
                                });

                                main.mapFieldsLoaded(data.name);

                                renderPopup.call(this);

                                var initDynamicFields = function () {

                                    res.dedicated_fields && res.dedicated_fields.forEach(function (tpl) {

                                        pop.find('.bf-deferred-kc-field.' + tpl.name).replaceWith(tpl.html);
                                    })
                                };

                                var setupFields = function(){

                                    var $context = pop.find('.form-active');

                                    Better_Framework.setup_field_color_picker($context);
                                    Better_Framework.setup_field_switch();
                                    Better_Framework.setup_field_slider();
                                    Better_Framework.setup_field_ajax_select();
                                    //  Better_Framework.setup_vc_field_sorter();
                                    Better_Framework.setup_term_select(
                                        $context
                                    );
                                    //  $(document).trigger('bf-ajax-tab-loaded', [$context])

                                };

                                pop.find(".kc-pop-tabs>li").one('click', function () {

                                    setTimeout(function () {

                                        initDynamicFields();
                                        setupFields();

                                        var $tab = pop.find('.form-active');

                                        main.setupShowOn($tab);

                                        $(":input:first", $tab).trigger('force-change');

                                        triggerLoadedEvent();
                                    });
                                });

                                setTimeout(function () {
                                    initDynamicFields();
                                    fixPopupWidth();

                                    setupFields();
                                    triggerLoadedEvent();
                                });

                            });

                        } else {

                            renderPopup.call(this);
                            setTimeout(function() {
                                fixPopupWidth();
                                triggerLoadedEvent();
                            });
                        }

                        return pop;
                    };

                    window.kc.ui.verify_tmpl = function(refresh) {

                        var cfg = $().extend( kc.cfg, kc.backbone.stack.get('KC_Configs') );

                        if( cfg.version != kc_version || refresh || localStorage['KC_TMPL_CACHE'] === undefined || localStorage['KC_TMPL_CACHE'] === ''){

                            if( !refresh) kc.msg( 'KingComposer is initializing', 'loading' );

                            $.post(

                                kc_ajax_url, {
                                    'action': 'bf_kc_tmpl_storage',
                                    'security': kc_ajax_nonce
                                },

                                function (result) {

                                    $('#kc-preload').remove();

                                    if( result != -1 && result != 0 ){

                                        kc.ui.upgrade_notice( parseFloat(cfg.version) );

                                        cfg.version = kc_version;

                                        localStorage.clear();

                                        kc.backbone.stack.set( 'KC_Configs', cfg );
                                        kc.backbone.stack.set( 'KC_TMPL_CACHE', result );

                                        kc.init();

                                    }
                                }
                            );

                        }else if( !kc.ui.check_tmpl() ){
                            return false;
                        } else return true;
                    }
                },

                getDeferredFieldsType: function(map) {

                    if (!kc_maps[map]) {
                        return false;
                    }

                    if (kc_maps[map].always_fetch_fields) {
                        return 'always';
                    }

                    if (!kc_maps[map].deferred_fields) {
                        return false;
                    }

                    var def = kc_maps[map].deferred_fields;

                    for (var i = 0; i < def.length; i++) {

                        if (!this.isFieldLoaded(def[i])) {
                            return 'once';
                        }
                    }

                    return false;
                },

                isFieldLoaded: function(field) {

                    return this.loadedFields.indexOf(field) > -1;
                },

                mapFieldsLoaded: function(map) {

                    if(! kc_maps[map] || ! kc_maps[map].deferred_fields) {
                        return false;
                    }

                    var self = this;

                    kc_maps[map].deferred_fields.forEach(function(field) {

                        self.loadedFields.push(field);
                    });
                },

                setupShowOn: function($wrapper){

                    $wrapper.on('change force-change', ':input', function(e){

                        Better_Framework._interactive_field_change(e,{
                            el:this,
                            ID: false,
                            containerSelector: false,
                            inputWrapperSelector: '.kc-param-row',
                            inputParamsSelector: '.bf-section-container',
                            parentSelector:  '.kc-pop-tab',
                        });
                    });
                }
            },

            elementor: {

                init: function() {

                    var self = this;

                    var interval = setInterval(function() {

                        if(! window.elementorFrontend) {
                            return ;
                        }

                        if( !elementorFrontend.hooks || !elementorFrontend.hooks.addAction) {
                            return ;
                        }

                        clearInterval(interval);

                        self.bindEvents();

                    },100);
                },

                bindEvents: function() {

                    if(! better_framework_loc.shortcodes_id) {
                        return ;
                    }

                    var self = this;

                    better_framework_loc.shortcodes_id.forEach( function(widgetId) {

                        elementor.hooks.addAction( 'panel/widgets/wp-widget-' + widgetId + '/controls/wp_widget/loaded', function( view ) {
                            self.widgetLoaded(view);
                        } );
                    });
                },

                widgetLoaded: function(view) {

                    Better_Framework.setup_fields(view.$el);
                }
            },

            siteOrigin: {

                init: function () {

                    this.bindEvents();

                    Better_Framework.setup_widget_fields();
                    Better_Framework.sort_widgets();

                },

                bindEvents: function() {

                    var self = this;

                    $(document).ajaxSuccess(function (e, xhr, settings) {
                        var data = $.unserialize(settings.data);

                        if(data.action === 'so_panels_widget_form') {

                            var $scope = $(".so-panels-dialog-wrapper .so-content");

                            self.widgetLoaded($scope);
                        }
                    });
                },

                widgetLoaded: function($scope) {

                    Better_Framework.setup_fields($scope);
                }
            },

            gutenberg: {

                init: function () {

                    var self = this;

                    $(document).on('bf-component-did-mount', function (e) {

                        var scope = e.detail.parentElement;

                        if(! scope) {
                            return ;
                        }

                        var $scope = $(scope);

                        if(! $scope.data('component-initialized')){

                            Better_Framework._init_editor(scope);
                            self.intTermSelect($scope);

                            $scope.data('component-initialized',true);
                        }
                    });

                    this.setupShowOn();
                },

                setupShowOn: function(){

                    $(document).on('bf-edit-gutenberg-block', function (e) {

                        var $scope = $(e.detail);

                        $scope.on('change force-change', ':input', function (e) {

                            Better_Framework._interactive_field_change(e,{
                                el:this,
                                inputWrapperSelector: '.bf-section-container',
                                parentSelector: '.bf-edit-gutenberg-block'
                            })
                        });

                        $scope.find(':hidden:first').trigger('force-change');
                    });


                    // if(! wp.hooks ||! wp.hooks.addFilter) {
                    //     return ;
                    // }
                    //
                    // wp.hooks.addFilter('editor.BlockEdit', 'betterstudio/textsettings', function (BlockEdit) {
                    //
                    //     return BlockEdit;
                    //     return function (props) {
                    //         return wp.element.createElement(BlockEdit, props);
                    //     };
                    // });
                },

                intTermSelect: function ($scope) {

                    var list = [];

                    var $fields = $(".bf-field-term-select-deferred", $scope);

                    $fields.each(function () {

                        var $this = $(this);

                        list.push({
                            taxonomy: $this.data('taxonomy'),
                            value: $this.closest('.bf-term-select-field').find('.bf-term-select-value').val()
                        });

                    }).promise().done(function () {

                        if (list.length === 0) {
                            return;
                        }

                        $.ajax({
                            type: 'POST',
                            dataType: 'json',
                            url: better_framework_loc.bf_ajax_url,
                            data: {
                                action: 'bf_ajax',
                                reqID: 'term_select_items',
                                nonce: better_framework_loc.nonce,
                                data: list
                            },
                            success: function (res) {

                                res.data.forEach(function (markup, index) {

                                    $($fields.get(index)).html('<ul>' + markup + '</ul>')
                                        .removeClass('bf-field-term-select-deferred')
                                        .removeClass('loading');
                                });

                                Better_Framework.init_term_select($scope);
                            },
                            error: function (MLHttpRequest) {
                            }
                        });
                    });
                }
            }
        }
    };

})(jQuery);

// load when ready

jQuery(function($) {

    Better_Framework.init();
});


jQuery(window).load(function() {

    if(! Better_Framework.loaded) {

        Better_Framework.init();
    }
});


/**
 * Plugins and 3rd Party Libraries
 */

jQuery(function($) {
    $.unserialize = function(serializedString){
        var str = decodeURI(serializedString);
        var pairs = str.split('&');
        var obj = {}, p, idx, val;
        for (var i=0, n=pairs.length; i < n; i++) {
            p = pairs[i].split('=');
            idx = p[0];

            if (idx.indexOf("[]") == (idx.length - 2)) {
                // Eh um vetor
                var ind = idx.substring(0, idx.length-2)
                if (obj[ind] === undefined) {
                    obj[ind] = [];
                }
                obj[ind].push(p[1]);
            }
            else {
                obj[idx] = p[1];
            }
        }
        return obj;
    };
});


(function(d){d.fn.redirect=function(a,b,c){void 0!==c?(c=c.toUpperCase(),"GET"!=c&&(c="POST")):c="POST";if(void 0===b||!1==b)b=d().parse_url(a),a=b.url,b=b.params;var e=d("<form></form");e.attr("method",c);e.attr("action",a);for(var f in b)a=d("<input />"),a.attr("type","hidden"),a.attr("name",f),a.attr("value",b[f]),a.appendTo(e);d("body").append(e);e.submit()};d.fn.parse_url=function(a){if(-1==a.indexOf("?"))return{url:a,params:{}};var b=a.split("?"),a=b[0],c={},b=b[1].split("&"),e={},d;for(d in b){var g= b[d].split("=");e[g[0]]=g[1]}c.url=a;c.params=e;return c}})(jQuery);

(function($) {
    String.prototype.sprintf = function(format){
        var formatted = this;
        for (var i = 0; i < arguments.length; i++) {
            var regexp = new RegExp('%'+i, 'gi');
            formatted = formatted.replace(regexp, arguments[i]);
        }
        return formatted;
    };
})(jQuery);// Custom Plugins

(function($) {
    $.array_unique = function (inputArr) {
        // Removes duplicate values from array
        var key = '',
            tmp_arr2 = [],
            val = '';

        var __array_search = function (needle, haystack) {
            var fkey = '';
            for (fkey in haystack) {
                if (haystack.hasOwnProperty(fkey)) {
                    if ((haystack[fkey] + '') === (needle + '')) {
                        return fkey;
                    }
                }
            }
            return false;
        };

        for (key in inputArr) {
            if (inputArr.hasOwnProperty(key)) {
                val = inputArr[key];
                if (false === __array_search(val, tmp_arr2)) {
                    tmp_arr2[key] = val;
                }
            }
        }

        return tmp_arr2;
    };

    $.removeFromArray = function(arr) {
        var what, a = arguments, L = a.length, ax;
        while (L > 1 && arr.length) {
            what = a[--L];
            while ((ax= arr.indexOf(what)) !== -1) {
                arr.splice(ax, 1);
            }
        }
        return arr;
    }

    // Custom Serializer
    $.fn.bf_serialize = function (asObject) {
        var results = {}, value;

        $(this).find(':input').each(function () {
            var $this = $(this),
                name = $this.attr('name');
            if (name && !this.disabled) {
                var type = $this.attr('type'),
                    name = encodeURIComponent(name);

                if ($this.is(':radio,:checkbox')) {
                    value = this.checked ? this.value : '';
                }
                else if($this.is("select[multiple]")){

                    results[ name ] = [];

                    $this.find('option:selected').each( function (i) {
                        var $_this = $(this),
                            _val = encodeURIComponent($_this.val());

                        results[ name ][_val] = _val;
                    });
                    return 0;
                }
                else{
                    value = this.value;
                }

                if (typeof results[ name ] === 'undefined' || value) {
                    results[ name ] = encodeURIComponent(value);
                }
            }
        });


        if(asObject) {
            return results;
        }
        var strOutput = '';
        for(var k in results) {

            if( Array.isArray(results[k]) ){

                for(var d in results[k]) {
                    strOutput += k + '[]=' + results[k][d] + '&';
                }

            }else{
                strOutput += k + '=' + results[k] + '&';
            }

        }

        return strOutput;
    }

    // Elemnt Exist Check Plugin
    $.fn.exist = function() {
        return this.size() > 0;
    }
})(jQuery);

// Update query string : http://stackoverflow.com/questions/5999118/add-or-update-query-string-parameter
function UpdateQueryString(key, value, url) {
    if (!url) url = window.location.href;
    var re = new RegExp("([?|&])" + key + "=.*?(&|#|$)(.*)", "gi");

    if (re.test(url)) {
        if (typeof value !== 'undefined' && value !== null)
            return url.replace(re, '$1' + key + "=" + value + '$2$3');
        else {
            var hash = url.split('#');
            url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, '');
            if (typeof hash[1] !== 'undefined' && hash[1] !== null)
                url += '#' + hash[1];
            return url;
        }
    }
    else {
        if (typeof value !== 'undefined' && value !== null) {
            var separator = url.indexOf('?') !== -1 ? '&' : '?',
                hash = url.split('#');
            url = hash[0] + separator + key + '=' + value;
            if (typeof hash[1] !== 'undefined' && hash[1] !== null)
                url += '#' + hash[1];
            return url;
        }
        else
            return url;
    }
}


// res : http://stackoverflow.com/questions/1766299/make-search-input-to-filter-through-list-jquery
// custom css expression for a case-insensitive contains()
(function($) {
    jQuery.expr[':'].Contains = function(a,i,m){
        return (a.textContent || a.innerText || "").toUpperCase().indexOf(m[3].toUpperCase())>=0;
    };
})(jQuery);
libs/better-framework/assets/js/pretty-photo.min.js000064400000050701151214002570016471 0ustar00!function(a){function b(){var a=location.href;return hashtag=a.indexOf("#prettyPhoto")!==-1&&decodeURI(a.substring(a.indexOf("#prettyPhoto")+1,a.length)),hashtag&&(hashtag=hashtag.replace(/<|>/g,"")),hashtag}function c(){"undefined"!=typeof theRel&&(location.hash=theRel+"/"+rel_index+"/")}function d(){location.href.indexOf("#prettyPhoto")!==-1&&(location.hash="prettyPhoto")}function e(a,b){a=a.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]");var c="[\\?&]"+a+"=([^&#]*)",d=new RegExp(c),e=d.exec(b);return null==e?"":e[1]}a.fn.prettyPhoto||(a.prettyPhoto={version:"3.1.6"},a.fn.prettyPhoto=function(f){function r(){a(".pp_loaderIcon").hide(),projectedTop=scroll_pos.scrollTop+(o/2-i.containerHeight/2),projectedTop<0&&(projectedTop=0),$ppt.fadeTo(settings.animation_speed,1),$pp_pic_holder.find(".pp_content").animate({height:i.contentHeight,width:i.contentWidth},settings.animation_speed),$pp_pic_holder.animate({top:projectedTop,left:p/2-i.containerWidth/2<0?0:p/2-i.containerWidth/2,width:i.containerWidth},settings.animation_speed,function(){$pp_pic_holder.find(".pp_hoverContainer,#fullResImage").height(i.height).width(i.width),$pp_pic_holder.find(".pp_fade").fadeIn(settings.animation_speed),isSet&&"image"==w(pp_images[set_position])?$pp_pic_holder.find(".pp_hoverContainer").show():$pp_pic_holder.find(".pp_hoverContainer").hide(),settings.allow_expand&&(i.resized?a("a.pp_expand,a.pp_contract").show():a("a.pp_expand").hide()),!settings.autoplay_slideshow||q||j||a.prettyPhoto.startSlideshow(),settings.changepicturecallback(),j=!0}),A(),f.ajaxcallback()}function s(b){$pp_pic_holder.find("#pp_full_res object,#pp_full_res embed").css("visibility","hidden"),$pp_pic_holder.find(".pp_fade").fadeOut(settings.animation_speed,function(){a(".pp_loaderIcon").show(),b()})}function t(b){b>1?a(".pp_nav").show():a(".pp_nav").hide()}function u(a,b){if(resized=!1,v(a,b),imageWidth=a,imageHeight=b,(n>p||m>o)&&doresize&&settings.allow_resize&&!h){for(resized=!0,fitting=!1;!fitting;)n>p?(imageWidth=p-200,imageHeight=b/a*imageWidth):m>o?(imageHeight=o-200,imageWidth=a/b*imageHeight):fitting=!0,m=imageHeight,n=imageWidth;(n>p||m>o)&&u(n,m),v(imageWidth,imageHeight)}return{width:Math.floor(imageWidth),height:Math.floor(imageHeight),containerHeight:Math.floor(m),containerWidth:Math.floor(n)+2*settings.horizontal_padding,contentHeight:Math.floor(k),contentWidth:Math.floor(l),resized:resized}}function v(b,c){b=parseFloat(b),c=parseFloat(c),$pp_details=$pp_pic_holder.find(".pp_details"),$pp_details.width(b),detailsHeight=parseFloat($pp_details.css("marginTop"))+parseFloat($pp_details.css("marginBottom")),$pp_details=$pp_details.clone().addClass(settings.theme).width(b).appendTo(a("body")).css({position:"absolute",top:-1e4}),detailsHeight+=$pp_details.height(),detailsHeight=detailsHeight<=34?36:detailsHeight,$pp_details.remove(),$pp_title=$pp_pic_holder.find(".ppt"),$pp_title.width(b),titleHeight=parseFloat($pp_title.css("marginTop"))+parseFloat($pp_title.css("marginBottom")),$pp_title=$pp_title.clone().appendTo(a("body")).css({position:"absolute",top:-1e4}),titleHeight+=$pp_title.height(),$pp_title.remove(),k=c+detailsHeight,l=b,m=k+titleHeight+$pp_pic_holder.find(".pp_top").height()+$pp_pic_holder.find(".pp_bottom").height(),n=b}function w(a){return a.match(/youtube\.com\/watch/i)||a.match(/youtu\.be/i)?"youtube":a.match(/vimeo\.com/i)?"vimeo":a.match(/\b.mov\b/i)?"quicktime":a.match(/\b.swf\b/i)?"flash":a.match(/\biframe=true\b/i)?"iframe":a.match(/\bajax=true\b/i)?"ajax":a.match(/\bcustom=true\b/i)?"custom":"#"==a.substr(0,1)?"inline":"image"}function x(){if(doresize&&"undefined"!=typeof $pp_pic_holder){if(scroll_pos=y(),contentHeight=$pp_pic_holder.height(),contentwidth=$pp_pic_holder.width(),projectedTop=o/2+scroll_pos.scrollTop-contentHeight/2,projectedTop<0&&(projectedTop=0),contentHeight>o)return;$pp_pic_holder.css({top:projectedTop,left:p/2+scroll_pos.scrollLeft-contentwidth/2})}}function y(){return self.pageYOffset?{scrollTop:self.pageYOffset,scrollLeft:self.pageXOffset}:document.documentElement&&document.documentElement.scrollTop?{scrollTop:document.documentElement.scrollTop,scrollLeft:document.documentElement.scrollLeft}:document.body?{scrollTop:document.body.scrollTop,scrollLeft:document.body.scrollLeft}:void 0}function z(){o=a(window).height(),p=a(window).width(),"undefined"!=typeof $pp_overlay&&$pp_overlay.height(a(document).height()).width(p)}function A(){isSet&&settings.overlay_gallery&&"image"==w(pp_images[set_position])?(itemWidth=57,navWidth="facebook"==settings.theme||"pp_default"==settings.theme?50:30,itemsPerPage=Math.floor((i.containerWidth-100-navWidth)/itemWidth),itemsPerPage=itemsPerPage<pp_images.length?itemsPerPage:pp_images.length,totalPage=Math.ceil(pp_images.length/itemsPerPage)-1,0==totalPage?(navWidth=0,$pp_gallery.find(".pp_arrow_next,.pp_arrow_previous").hide()):$pp_gallery.find(".pp_arrow_next,.pp_arrow_previous").show(),galleryWidth=itemsPerPage*itemWidth,fullGalleryWidth=pp_images.length*itemWidth,$pp_gallery.css("margin-left",-(galleryWidth/2+navWidth/2)).find("div:first").width(galleryWidth+5).find("ul").width(fullGalleryWidth).find("li.selected").removeClass("selected"),goToPage=Math.floor(set_position/itemsPerPage)<totalPage?Math.floor(set_position/itemsPerPage):totalPage,a.prettyPhoto.changeGalleryPage(goToPage),$pp_gallery_li.filter(":eq("+set_position+")").addClass("selected")):$pp_pic_holder.find(".pp_content").unbind("mouseenter mouseleave")}function B(b){if(settings.social_tools&&(facebook_like_link=settings.social_tools.replace("{location_href}",encodeURIComponent(location.href))),settings.markup=settings.markup.replace("{pp_social}",""),a("body").append(settings.markup),$pp_pic_holder=a(".pp_pic_holder"),$ppt=a(".ppt"),$pp_overlay=a("div.pp_overlay"),isSet&&settings.overlay_gallery){currentGalleryPage=0,toInject="";for(var c=0;c<pp_images.length;c++)pp_images[c].match(/\b(jpg|jpeg|png|gif)\b/gi)?(classname="",img_src=pp_images[c]):(classname="default",img_src=""),toInject+="<li class='"+classname+"'><a href='#'><img src='"+img_src+"' width='50' alt='' /></a></li>";toInject=settings.gallery_markup.replace(/{gallery}/g,toInject),$pp_pic_holder.find("#pp_full_res").after(toInject),$pp_gallery=a(".pp_pic_holder .pp_gallery"),$pp_gallery_li=$pp_gallery.find("li"),$pp_gallery.find(".pp_arrow_next").click(function(){return a.prettyPhoto.changeGalleryPage("next"),a.prettyPhoto.stopSlideshow(),!1}),$pp_gallery.find(".pp_arrow_previous").click(function(){return a.prettyPhoto.changeGalleryPage("previous"),a.prettyPhoto.stopSlideshow(),!1}),$pp_pic_holder.find(".pp_content").hover(function(){$pp_pic_holder.find(".pp_gallery:not(.disabled)").fadeIn()},function(){$pp_pic_holder.find(".pp_gallery:not(.disabled)").fadeOut()}),itemWidth=57,$pp_gallery_li.each(function(b){a(this).find("a").click(function(){return a.prettyPhoto.changePage(b),a.prettyPhoto.stopSlideshow(),!1})})}settings.slideshow&&($pp_pic_holder.find(".pp_nav").prepend('<a href="#" class="pp_play"><i class="fa fa-play"></i></a>'),$pp_pic_holder.find(".pp_nav .pp_play").click(function(){return a.prettyPhoto.startSlideshow(),!1})),$pp_pic_holder.attr("class","pp_pic_holder "+settings.theme),$pp_overlay.css({opacity:0,height:a(document).height(),width:a(window).width()}).bind("click",function(){settings.modal||a.prettyPhoto.close()}),a("a.pp_close").bind("click",function(){return a.prettyPhoto.close(),!1}),settings.allow_expand&&a("a.pp_expand").bind("click",function(b){return a(this).hasClass("pp_expand")?(a(this).removeClass("pp_expand").addClass("pp_contract"),doresize=!1):(a(this).removeClass("pp_contract").addClass("pp_expand"),doresize=!0),s(function(){a.prettyPhoto.open()}),!1}),$pp_pic_holder.find(".pp_previous, .pp_nav .pp_arrow_previous").bind("click",function(){return a.prettyPhoto.changePage("previous"),a.prettyPhoto.stopSlideshow(),!1}),$pp_pic_holder.find(".pp_next, .pp_nav .pp_arrow_next").bind("click",function(){return a.prettyPhoto.changePage("next"),a.prettyPhoto.stopSlideshow(),!1}),x()}f=jQuery.extend({hook:"rel",animation_speed:"fast",ajaxcallback:function(){},slideshow:5e3,autoplay_slideshow:!1,opacity:.8,show_title:!0,allow_resize:!0,allow_expand:!0,default_width:500,default_height:344,counter_separator_label:"/",theme:"pp_default",horizontal_padding:20,hideflash:!1,wmode:"opaque",autoplay:!0,modal:!1,deeplinking:!0,overlay_gallery:!0,overlay_gallery_max:30,keyboard_shortcuts:!0,changepicturecallback:function(){},callback:function(){},ie6_fallback:!0,markup:'<div class="pp_pic_holder"> <div class="ppt">&nbsp;</div> <div class="pp_top"> <div class="pp_left"></div> <div class="pp_middle"></div> <div class="pp_right"></div> </div> <div class="pp_content_container"> <div class="pp_left"> <div class="pp_right"> <div class="pp_content"> <div class="pp_loaderIcon"></div> <div class="pp_fade"> <a href="#" class="pp_expand" title="Expand the image">Expand</a> <div class="pp_hoverContainer"> <a class="pp_next" href="#">next</a> <a class="pp_previous" href="#">previous</a> </div> <div id="pp_full_res"></div> <div class="pp_details"> <div class="pp_nav"> <a href="#" class="pp_arrow_previous">Previous</a> <p class="currentTextHolder">0/0</p> <a href="#" class="pp_arrow_next">Next</a> </div> <p class="pp_description"></p> <div class="pp_social">{pp_social}</div> <a class="pp_close" href="#">Close</a> </div> </div> </div> </div> </div> </div> <div class="pp_bottom"> <div class="pp_left"></div> <div class="pp_middle"></div> <div class="pp_right"></div> </div> </div> <div class="pp_overlay"></div>',gallery_markup:'<div class="pp_gallery"> <a href="#" class="pp_arrow_previous">Previous</a> <div> <ul> {gallery} </ul> </div> <a href="#" class="pp_arrow_next">Next</a> </div>',image_markup:'<img id="fullResImage" src="{path}" />',flash_markup:'<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="{width}" height="{height}"><param name="wmode" value="{wmode}" /><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="{path}" /><embed src="{path}" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="{width}" height="{height}" wmode="{wmode}"></embed></object>',quicktime_markup:'<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab" height="{height}" width="{width}"><param name="src" value="{path}"><param name="autoplay" value="{autoplay}"><param name="type" value="video/quicktime"><embed src="{path}" height="{height}" width="{width}" autoplay="{autoplay}" type="video/quicktime" pluginspage="http://www.apple.com/quicktime/download/"></embed></object>',iframe_markup:'<iframe src ="{path}" width="{width}" height="{height}" frameborder="no"></iframe>',inline_markup:'<div class="pp_inline">{content}</div>',custom_markup:"",social_tools:'<div class="twitter"><a href="http://twitter.com/share" class="twitter-share-button" data-count="none">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div><div class="facebook"><iframe src="//www.facebook.com/plugins/like.php?locale=en_US&href={location_href}&amp;layout=button_count&amp;show_faces=true&amp;width=500&amp;action=like&amp;font&amp;colorscheme=light&amp;height=23" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:500px; height:23px;" allowTransparency="true"></iframe></div>'},f);var i,j,k,l,m,n,q,g=this,h=!1,o=a(window).height(),p=a(window).width();return doresize=!0,scroll_pos=y(),a(window).unbind("resize.prettyphoto").bind("resize.prettyphoto",function(){x(),z()}),f.keyboard_shortcuts&&a(document).unbind("keydown.prettyphoto").bind("keydown.prettyphoto",function(b){if("undefined"!=typeof $pp_pic_holder&&$pp_pic_holder.is(":visible"))switch(b.keyCode){case 37:a.prettyPhoto.changePage("previous"),b.preventDefault();break;case 39:a.prettyPhoto.changePage("next"),b.preventDefault();break;case 27:settings.modal||a.prettyPhoto.close(),b.preventDefault()}}),a.prettyPhoto.initialize=function(){return settings=f,"pp_default"==settings.theme&&(settings.horizontal_padding=16),theRel=a(this).attr(settings.hook),galleryRegExp=/\[(?:.*)\]/,isSet=!!galleryRegExp.exec(theRel),pp_images=isSet?jQuery.map(g,function(b,c){if(a(b).attr(settings.hook).indexOf(theRel)!=-1)return a(b).attr("href")}):a.makeArray(a(this).attr("href")),pp_titles=isSet?jQuery.map(g,function(b,c){if(a(b).attr(settings.hook).indexOf(theRel)!=-1)return a(b).find("img").attr("alt")?a(b).find("img").attr("alt"):""}):a.makeArray(a(this).find("img").attr("alt")),pp_descriptions=isSet?jQuery.map(g,function(b,c){if(a(b).attr(settings.hook).indexOf(theRel)!=-1)return a(b).attr("title")?a(b).attr("title"):""}):a.makeArray(a(this).attr("title")),pp_images.length>settings.overlay_gallery_max&&(settings.overlay_gallery=!1),set_position=jQuery.inArray(a(this).attr("href"),pp_images),rel_index=isSet?set_position:a("a["+settings.hook+"^='"+theRel+"']").index(a(this)),B(this),settings.allow_resize&&a(window).bind("scroll.prettyphoto",function(){x()}),a.prettyPhoto.open(),!1},a.prettyPhoto.open=function(b){return"undefined"==typeof settings&&(settings=f,pp_images=a.makeArray(arguments[0]),pp_titles=arguments[1]?a.makeArray(arguments[1]):a.makeArray(""),pp_descriptions=arguments[2]?a.makeArray(arguments[2]):a.makeArray(""),isSet=pp_images.length>1,set_position=arguments[3]?arguments[3]:0,B(b.target)),settings.hideflash&&a("object,embed,iframe[src*=youtube],iframe[src*=vimeo]").css("visibility","hidden"),t(a(pp_images).size()),a(".pp_loaderIcon").show(),settings.deeplinking&&c(),settings.social_tools&&(facebook_like_link=settings.social_tools.replace("{location_href}",encodeURIComponent(location.href)),$pp_pic_holder.find(".pp_social").html(facebook_like_link)),$ppt.is(":hidden")&&$ppt.css("opacity",0).show(),$pp_overlay.show().fadeTo(settings.animation_speed,settings.opacity),$pp_pic_holder.find(".currentTextHolder").text(set_position+1+settings.counter_separator_label+a(pp_images).size()),"undefined"!=typeof pp_descriptions[set_position]&&""!=pp_descriptions[set_position]?$pp_pic_holder.find(".pp_description").show().html(unescape(pp_descriptions[set_position])):$pp_pic_holder.find(".pp_description").hide(),movie_width=parseFloat(e("width",pp_images[set_position]))?e("width",pp_images[set_position]):settings.default_width.toString(),movie_height=parseFloat(e("height",pp_images[set_position]))?e("height",pp_images[set_position]):settings.default_height.toString(),h=!1,movie_height.indexOf("%")!=-1&&(movie_height=parseFloat(a(window).height()*parseFloat(movie_height)/100-150),h=!0),movie_width.indexOf("%")!=-1&&(movie_width=parseFloat(a(window).width()*parseFloat(movie_width)/100-150),h=!0),$pp_pic_holder.fadeIn(function(){switch(settings.show_title&&""!=pp_titles[set_position]&&"undefined"!=typeof pp_titles[set_position]?$ppt.html(unescape(pp_titles[set_position])):$ppt.html("&nbsp;"),imgPreloader="",skipInjection=!1,w(pp_images[set_position])){case"image":imgPreloader=new Image,nextImage=new Image,isSet&&set_position<a(pp_images).size()-1&&(nextImage.src=pp_images[set_position+1]),prevImage=new Image,isSet&&pp_images[set_position-1]&&(prevImage.src=pp_images[set_position-1]),$pp_pic_holder.find("#pp_full_res")[0].innerHTML=settings.image_markup.replace(/{path}/g,pp_images[set_position]),imgPreloader.onload=function(){i=u(imgPreloader.width,imgPreloader.height),r()},imgPreloader.onerror=function(){alert("Image cannot be loaded. Make sure the path is correct and image exist."),a.prettyPhoto.close()},imgPreloader.src=pp_images[set_position];break;case"youtube":i=u(movie_width,movie_height),movie_id=e("v",pp_images[set_position]),""==movie_id&&(movie_id=pp_images[set_position].split("youtu.be/"),movie_id=movie_id[1],movie_id.indexOf("?")>0&&(movie_id=movie_id.substr(0,movie_id.indexOf("?"))),movie_id.indexOf("&")>0&&(movie_id=movie_id.substr(0,movie_id.indexOf("&")))),movie="http://www.youtube.com/embed/"+movie_id,e("rel",pp_images[set_position])?movie+="?rel="+e("rel",pp_images[set_position]):movie+="?rel=1",settings.autoplay&&(movie+="&autoplay=1"),toInject=settings.iframe_markup.replace(/{width}/g,i.width).replace(/{height}/g,i.height).replace(/{wmode}/g,settings.wmode).replace(/{path}/g,movie);break;case"vimeo":i=u(movie_width,movie_height),movie_id=pp_images[set_position];var b=/http(s?):\/\/(www\.)?vimeo.com\/(\d+)/,c=movie_id.match(b);movie="http://player.vimeo.com/video/"+c[3]+"?title=0&amp;byline=0&amp;portrait=0",settings.autoplay&&(movie+="&autoplay=1;"),vimeo_width=i.width+"/embed/?moog_width="+i.width,toInject=settings.iframe_markup.replace(/{width}/g,vimeo_width).replace(/{height}/g,i.height).replace(/{path}/g,movie);break;case"quicktime":i=u(movie_width,movie_height),i.height+=15,i.contentHeight+=15,i.containerHeight+=15,toInject=settings.quicktime_markup.replace(/{width}/g,i.width).replace(/{height}/g,i.height).replace(/{wmode}/g,settings.wmode).replace(/{path}/g,pp_images[set_position]).replace(/{autoplay}/g,settings.autoplay);break;case"flash":i=u(movie_width,movie_height),flash_vars=pp_images[set_position],flash_vars=flash_vars.substring(pp_images[set_position].indexOf("flashvars")+10,pp_images[set_position].length),filename=pp_images[set_position],filename=filename.substring(0,filename.indexOf("?")),toInject=settings.flash_markup.replace(/{width}/g,i.width).replace(/{height}/g,i.height).replace(/{wmode}/g,settings.wmode).replace(/{path}/g,filename+"?"+flash_vars);break;case"iframe":i=u(movie_width,movie_height),frame_url=pp_images[set_position],frame_url=frame_url.substr(0,frame_url.indexOf("iframe")-1),toInject=settings.iframe_markup.replace(/{width}/g,i.width).replace(/{height}/g,i.height).replace(/{path}/g,frame_url);break;case"ajax":doresize=!1,i=u(movie_width,movie_height),doresize=!0,skipInjection=!0,a.get(pp_images[set_position],function(a){toInject=settings.inline_markup.replace(/{content}/g,a),$pp_pic_holder.find("#pp_full_res")[0].innerHTML=toInject,r()});break;case"custom":i=u(movie_width,movie_height),toInject=settings.custom_markup;break;case"inline":myClone=a(pp_images[set_position]).clone().append('<br clear="all" />').css({width:settings.default_width}).wrapInner('<div id="pp_full_res"><div class="pp_inline"></div></div>').appendTo(a("body")).show(),doresize=!1,i=u(a(myClone).width(),a(myClone).height()),doresize=!0,a(myClone).remove(),toInject=settings.inline_markup.replace(/{content}/g,a(pp_images[set_position]).html())}imgPreloader||skipInjection||($pp_pic_holder.find("#pp_full_res")[0].innerHTML=toInject,r())}),!1},a.prettyPhoto.changePage=function(b){currentGalleryPage=0,"previous"==b?(set_position--,set_position<0&&(set_position=a(pp_images).size()-1)):"next"==b?(set_position++,set_position>a(pp_images).size()-1&&(set_position=0)):set_position=b,rel_index=set_position,doresize||(doresize=!0),settings.allow_expand&&a(".pp_contract").removeClass("pp_contract").addClass("pp_expand"),s(function(){a.prettyPhoto.open()})},a.prettyPhoto.changeGalleryPage=function(a){"next"==a?(currentGalleryPage++,currentGalleryPage>totalPage&&(currentGalleryPage=0)):"previous"==a?(currentGalleryPage--,currentGalleryPage<0&&(currentGalleryPage=totalPage)):currentGalleryPage=a,slide_speed="next"==a||"previous"==a?settings.animation_speed:0,slide_to=currentGalleryPage*(itemsPerPage*itemWidth),$pp_gallery.find("ul").animate({left:-slide_to},slide_speed)},a.prettyPhoto.startSlideshow=function(){"undefined"==typeof q?($pp_pic_holder.find(".pp_play").unbind("click").removeClass("pp_play").addClass("pp_pause").click(function(){return a.prettyPhoto.stopSlideshow(),!1}),q=setInterval(a.prettyPhoto.startSlideshow,settings.slideshow)):a.prettyPhoto.changePage("next")},a.prettyPhoto.stopSlideshow=function(){$pp_pic_holder.find(".pp_pause").unbind("click").removeClass("pp_pause").addClass("pp_play").click(function(){return a.prettyPhoto.startSlideshow(),!1}),clearInterval(q),q=void 0},a.prettyPhoto.close=function(){$pp_overlay.is(":animated")||(a.prettyPhoto.stopSlideshow(),$pp_pic_holder.stop().find("object,embed").css("visibility","hidden"),a("div.pp_pic_holder,div.ppt,.pp_fade").fadeOut(settings.animation_speed,function(){a(this).remove()}),$pp_overlay.fadeOut(settings.animation_speed,function(){settings.hideflash&&a("object,embed,iframe[src*=youtube],iframe[src*=vimeo]").css("visibility","visible"),a(this).remove(),a(window).unbind("scroll.prettyphoto"),d(),settings.callback(),doresize=!0,j=!1,delete settings}))},!pp_alreadyInitialized&&b()&&(pp_alreadyInitialized=!0,hashIndex=b(),hashRel=hashIndex,hashIndex=hashIndex.substring(hashIndex.indexOf("/")+1,hashIndex.length-1),hashRel=hashRel.substring(0,hashRel.indexOf("/")),setTimeout(function(){a("a["+f.hook+"^='"+hashRel+"']:eq("+hashIndex+")").trigger("click")},50)),this.unbind("click.prettyphoto").bind("click.prettyphoto",a.prettyPhoto.initialize)})}(jQuery);var pp_alreadyInitialized=!1;libs/better-framework/assets/js/gutenberg.min.js000064400000007666151214002570016011 0ustar00!function(){function e(){this.element=window.wp&&window.wp.element,this.blocks=window.wp&&window.wp.blocks,this.prefix="better-studio/",this.props={},this.attributes={},this.blockFields={},this.shortcode={}}e.prototype.registerBlockType=function(e,t){this.shortcode=e,this.blockFields=t;var i=this.shortcode.block_id||this.shortcode.id.replace(/_/g,"-");this.blocks.registerBlockType(this.prefix+i,{title:this.shortcode.name||this.shortcode.id,icon:this.blockIcon(),category:this.shortcode.category||"betterstudio",edit:this.editBlock.bind(this),save:this.saveBlock.bind(this),attributes:this.blockAttributes(this.shortcode.id)})},e.prototype.saveBlock=function(){return null},e.prototype.blockAttributes=function(){if(!this.blockFields)return[];var e={},t=function(i){i.id&&i.attribute&&(e[i.id]=i.attribute),i.children&&i.children.forEach(function(e){t(e)})};return this.blockFields.forEach(t),e},e.prototype.editBlock=function(e){var t=e.name.replace(this.prefix,"");if(!t||t===e.name)return[];!e.isSelected&&this.props.name||(this.props=e);var i=!this.shortcode.click_able,n=this.element.createElement(this.getComponent("ServerSideRender"),{block:e.name,attributes:e.attributes,key:"D2"});return i&&(n=this.element.createElement(this.getComponent("Disabled"),{key:"D1"},n)),[this.buildBlockFields(),n]},e.prototype.buildElement=function(e,t){var i=[],n=this;return e.forEach(function(e){e.children?i.push(n.buildElement(e.children,e)):Array.isArray(e)?i.push(n.buildElement(e,t)):i.push(n.createElement(e))}),n.createElement(t,i)},e.prototype.createElement=function(e,t){var i=[this.getComponent(e.component),this.componentArgs(e)].concat(t||[]);return this.element.createElement.apply(this.element,i)},e.prototype.componentArgs=function(e){var t=e.args||{};if("Fragment"===e.component)return t;var i=this,n=function(t,i){t=t||"",t+=" ";var n=BF_Gutenberg.extraAttributes[e.id];return n&&n["enum"]?n["enum"].forEach(function(e){t=t.replace(new RegExp("\\b"+e+"\\s+","g"),"")}):1===i?i=e.id:0===i&&(i=""),t=t.trim()+" "+i,e.fixed_class&&!t.match(new RegExp("\\b"+e.fixed_class+"\\s+","g"))&&(t+=" "+e.fixed_class),t};t.onChange||(t.onChange=function(t){var o="add_class"===e.action?"className":e.id,r={};r[o]="add_class"===e.action?n(i.props.attributes[o],t):t,i.props.setAttributes(r)});var o=this.props.attributes[e.id];return t.value="undefined"==typeof o?e.std:o,t},e.prototype.buildBlockFields=function(){return this.buildElement([{id:"inspector",component:"InspectorControls",args:{key:"inspector"},children:[{id:"bf_edit_panel",component:"BF_Edit_Panel",args:{type:"edit-panel"},key:"bf_edit_panel",children:this.blockFields}]}],{id:"block_fragment",component:"Fragment",args:{key:"block_fragment"}})},e.prototype.getComponent=function(e){return wp.editor[e]?wp.editor[e]:wp.components[e]?wp.components[e]:wp.element[e]?wp.element[e]:void 0},e.prototype.blockIcon=function(){return this.shortcode.icon_url?this.element.createElement("img",{src:this.shortcode.icon_url}):this.shortcode.icon||""};var t={init:function(){this.registerBlocks(),this.registerSharedFields()},registerBlocks:function(){if(BF_Gutenberg&&BF_Gutenberg.blocks){var t;for(var i in BF_Gutenberg.blocks)t=new e,t.registerBlockType(BF_Gutenberg.blocks[i],BF_Gutenberg.blockFields[i])}},registerSharedFields:function(){if(wp.hooks&&wp.hooks.addFilter&&wp.compose&&wp.compose.createHigherOrderComponent&&BF_Gutenberg.stickyFields){var t=new e;wp.hooks.addFilter("editor.BlockEdit","betterstudio/shared_settings",wp.compose.createHigherOrderComponent(function(e){return function(i){t.props=i,t.attributes=i.attributes;var n=BF_Gutenberg.stickyFields.filter(function(e){return e.exclude_blocks&&e.exclude_blocks.indexOf(i.name)>-1?!1:e.include_blocks?e.include_blocks.indexOf(i.name)>-1:!0});if(!n)return t.element.createElement(e,i);var o=t.buildElement(n,{id:"inspector",component:"InspectorControls",args:{key:"inspector"}});return t.element.createElement(t.getComponent("Fragment"),{key:"E1"},o,t.element.createElement(e,i))}}))}}};t.init()}();libs/better-framework/assets/img/color-picker/custom_hsb_b.png000064400000002111151214002570020571 0ustar00�PNG


IHDR>B�C�	pHYs�� cHRMz-�����RqE�f9!�'�V�IDATx��{HA��;wz�^(�,|���$>�E"I�W�A D��= (��RY�E�T���H
F�8-�����{���폵m��no�Fw�cv�73ߛ����gO5��bw�C��R�,2�#�Q:dw��b�qH'����
(�H��apHW��n)Mд�h��-ͪ�B��
Y��Q:q�K4ܴ�l���)��n��
��1QU8
��$�ʷ�[u�|9;'���X��	`X�#[(c��Ԃ��̬����wm��1���*ܖ�=:mx�w�ÇJ3R��hz��(*���ia���V鼪\C���S����-����."�6���^UU��NL���0���S����7h^�u��L
�k#�Y����9����d��WHg}�LEy�!�v�_4�o�_���������5+�+�)�eʲ��K#�I�e����$� �cpJ_Μ�Y���L��O���5"��u9�#?�v���Y/�p�{�&q�TTV�%'.,,�,l���ӧm��2�P��t���H����F��ü�J��L�Y����c��_Ig�`�@��HAJ�S����*��􋯲����t���J�G��Ĕm�:���6���F&�ŠQ��������P��7���y���@�|LD��cw�Ȓ ��ۣ�Bw����v���Z�U*վ��5�.TU�o����CzpDw�O����@���@�����$����0��$���!" O�	q1&˨�	Pf�ٝ2%]�o[�D���#_"@�H�D�ñ�%j�F�D@�	S*Ш���I�l��"I>�\<)�D$)k"���r�\�P~��ce�0Wk�\�>Ε��~�"�,Ӛ��ޕ�%�aΝ>�n�{�"���;
���={�_)k"�������&a�|��z�-������[�|�
��(C"0d�����c5��(R:A�ͺl���7���H���R��IEND�B`�libs/better-framework/assets/img/color-picker/custom_rgb_g.png000064400000002055151214002570020603 0ustar00�PNG


IHDR>B�C�	pHYs�� cHRMz-�����RqE�f9!�'�V�IDATx��]HSa��ǜ�����u�(�D�$�7A7vXY�iid	Yx!�i���eA�R�t	� !I�����#77���;];7�B;�x^����y����y���������6����`��!'}n^C���v����	�z��l�o��c���:�Qƣ��J?8�?0��	��x$?�o�1pP���}�h�C��ӧNܟ����݇�N1\Kg���Hv�N����iڋ�]���ʎiu��&n��!�h�L��j�T:�jWJ<dg�~�dg��|ئY\ZҪ���X��f���92|gsCMHP I�L׫�$��(�����8vv�u�O�b"ef�uxt��f�/;W�L��ʖ�<�~�SkGt�F�U6�rt��b�[��%�J�L�r�D�Iq��E2�ט�O�P�=xb_Y����"f�5�[�A1a�K_5�����N�;�������DQq�Bi���~|�KLKN�^��R0���#S��u�_�O�[}�tQ��R�Z^ޝ���T���ն����z���!�_���&����7�OC���?M��f�����t�c#5��8���cs��~U��RT���̜9�a�`bfN�'+9�}C@K�����ҕ
�@^N&G��{�" ���{"�����@" ��I�{��$���lC"&�R͠x��͡�yJz��^�~�&�Ё\�'P��a�p,�I�P%��Ղ��u��P%�3V[u����q^����@Meѕ�� 8��v�����VW2N^��Mk��:��"Jyh����40�,[��)�����-O]a�A�5�>�׷���q��F��^'4�w���%��#���K'���#��D���Α�D`b��fWݛ�fGU:�yZu����D"�=���)�TIEND�B`�libs/better-framework/assets/img/color-picker/colorpicker_select.gif000064400000000116151214002570021761 0ustar00GIF89a�������!�,��h�X�F��Y��}����%pZt<P�(F;libs/better-framework/assets/img/color-picker/colorpicker_rgb_b.png000064400000001712151214002570021577 0ustar00�PNG


IHDR>B�C�	pHYs�� cHRMz-�����RqE�f9!�'�VPIDATx��AKA���l�⚰�ƃQj֘�x1x�P��݃�!�� H������)Ғ����/F�n��d�=�n7٘
�Ig��0nf�����C�`0��<�V��r<����Q�>88�˲@aq��xhE�8�#q�UUq����5&�@ �H�G�x���=����f���������;��F�T*u{{������8==m�cVt+U&��$�av~j�}���a�Px�q}}}�`���������n��&U6�C�p�:;�Z�>r~~�\.{�����D"Q*���u�W&�d(t�ϣvhb�.0�0���(j�ƲlOO����i7�e�.
5�zS�d2��f=,�qa!�O�;��*wq���ɺ����g�����QA�puU3{���X(��\\^Zg60kkk�J��������p^�PE"[��S`l�DBQ���.�a���eY��|Lg��0�wF���R�w||�����mڬS;��@ @"�c�N��q^�]UUZ���0�S�~S,r�~��L�:�)Ir�]F�}����K��0^����a➉F]#����<�����F��5�p��k\#�F`&��Z]P���F�X�)��]�������%�LI҇��RGG�G�I�h�L#P�Th5���V�L#�u�aJEEQ��,˱Xlvv�ާ�fmmm�E�0W}gg���777�0z���76����%����%��x��\#P}Z���=�X]]����*����� ���͇Dk6���`ii�"��T���
O�5z=(MF���#�F���Ft�q�$������?-kگO���2h��IEND�B`�libs/better-framework/assets/img/color-picker/custom_hsb_h.png000064400000001712151214002570020605 0ustar00�PNG


IHDR>B�C�	pHYs�� cHRMz-�����RqE�f9!�'�VPIDATx��]HA���3{���)h"��w�� A�C��D>�$���كP/%!D�`AB�D�C>B!� �E��E���yz��nsm{{�]����gf�fo~�ٙ�13_|��m�-��6�ڮ(/�=�}�$I@a`���B�{�؋m��㢘߿�<���ץ�T�M��T,�)=��<~������f�.�g)ItI�5��.-��4�;qq�]=Fot�\�ǝ�d�X���'��<!dY���}6�v8��Fc��+T
.�hr�OyԳc`Y&�Ɂ��l������0�0G��\�o��R���O٦���g��
䴊F�,�p˪�S��L�{�����	h�CV@�?ŕP�:�t��Ĵ'=�Ë� I�XDL$dy7�S�Oy\2�Ĵ7��h� T�DŽi��ᬫ^���Z.�w�U*a���]�-�#�����\���ڏ���6
m���p$��Q`tI�g-B���R��N�}�Vt{������
 HzeE��'��R�>2�6�]�'�t%k�����9դ���iL#`#�wd7It��F�4�0���4C�cT�ښ*��A#PYQ�i��f�����2�u~��e�����k´~౹t�q��Yh5���ք�p�V#����`���s㲺�J�[�"MQ�i*F@3F�UOFwW+tw�"U����[����D�{�S`8�6��{��i\#�Iׯ���݇��oY��x}K^ߒ�h�舎)��ߐU�l��tfK��_�U���o�u�q��z$��x��1�P�0��77G���o��z�)F���<�k�_9��9�t����IEND�B`�libs/better-framework/assets/img/color-picker/custom_background.png000064400000003574151214002570021651 0ustar00�PNG


IHDRd�8��	pHYs�� cHRMz-�����RqE�f9!�'�VIDATx����ow���qv�v%J�kpH� 'ĉ#B��
	��p�ąn��)�D�R	�
�B�(T����&]{8t�����g6��}iyl볳/}5;����4��$W��O���i�'IUU����j��$�K�eN/�~�w��:,6�1�˱�hp����1&�e��&�dNK�8ɟ��.�<�V�4�I�[��?x���g�>52�%8sf��7_�����˃$�]l��7��G�p~3�^�`jK������}��V�������|~(�K�����܂x}`4edA@�
4<��O����?����ڬs}w'�'�����a������\����~�3s����,�,��$w�=���N㇏��7L��$9q�����/{�������$��~�����;�z�������3l�S��yU���T+��k�˞3sY�)(�t�I��[fx�!ȃ*�~�H�̊'i:�_!��� �J�A�2��A�2��AAA���d�BA��Q�])�!����AAA�c� #�P�Q�}�‘"�Џ� #� � ��R2�e%Y��"�Џ� #Ȱ:A�#��Ղ� CF�"�Џ� #�P�Z�d(�Q���a}$�2�cj}� � � C�D�d(�,�OA�"L_b��6��Lr���ܷ6ks9�\����0�䮏Ӻ��s��D��p.VȬ��K\!��n��k�s95Af���n��ƈ Cw��|�ddV�$>�	A�"̒T�o�A�~LAAAAF��� � � � � #� � ��yA���\e�222�,�222+�.7�:2���Zr�a�;Pdz2�s2�d�0dZFF� Cj#@��c#@�A�A��e�� CjAF��cAF�A�A��e�n�l;2B�[!2��A+ddd�3J��a���:�{�1"���X�dX� � CF��"�ЏZ�d(�X�d(Ùy��z��2�db�� C��� Cfq��Ŭ�A�LA��Y!o#��� �ʘ��
�/#��M��2a*�222�̒T�o�A��VȂ� C&�� �22�̌A�rV� �P�� �`��-�t{c�2B�[!2��2�V� ��\��� h`�2�a=�u�@�d��8NX � � � �2�d�02�06Zj#@����'�0dZjAF���t�_ۑ"�Џ� #� � � �2���. �P@��AAF�A�[AA����堞!���� 2���A�2�=M�:�3�(2�=�Z"#� � ��\�]�� � � � #� � ��yA�zC�
cD�A�d�V�/#��M�3�d(�,I�a��d��T�dddd� � � � � �2fb2�a�no�UF� C?��� � � C�D�dx�����3}6�Zs�[�V���<(>�[�u�&�u���[����9��J>�h/o���^��s��x"(?��wwr�ރ��������Ή��η_K��|���)���,��?���Fn޸fr��07�{� ���D�  �������l0d�K�w0�p��$OZ�?.6\\lxk��7~�׿���f�4�K+�nmzR5Ms%ɍņ�$�N�8��,GI�L�$O�R%I�4?L�iF/�AUU>^���L^|�
��{[5M���J�sq�+�ei��%yTU���ʜ�MR��IEND�B`�libs/better-framework/assets/img/color-picker/custom_rgb_b.png000064400000001760151214002570020600 0ustar00�PNG


IHDR>B�C�	pHYs�� cHRMz-�����RqE�f9!�'�VvIDATx��kHA��vg�z}P�Yx���]J�)�H�"��oՇ!
D�A=>He�aVTPA�)0C���qZ��U�w�C�����ڲ�]��7C;̇ٹٛ��;�S��=>�[�&j���KMI��>��a���.u�h5�苁@t߮ې&�طIQ*tF�*2���f�m4T��"�N�
�6ڒ�>��؜�o�hk}��>Fjt�\�-��C�J~�幺��@`��i:���i�p�‚_Rt�����>
���!� �w���Ө��YΚ���j��Zˀ����M:�=82�,�#�8=�T���/�9]��Ô/Cg#�B�>>ky�t�q{�=V��~��z��o�CӔeC+W��3V�$�޹ٙA���}�r!β�)/[8����Bj�籏-ٹ�l���[��SU]�����,X��s�.O�FH/�nؘ��Q����?
E�"M=޹��4b��0�DI�ҾM�hW��:���D
���i�k�>�zzj2���l5��C����^�G%%+4�Hh�wI����'$����!�6ڲ�l_ZJ��7��֪P(����]HUZdx�7=:# uY�,��F@6����l��h������2e#����d�m�c5�,.�Q#��;�s��w�kH�z�#�t,�F���p5T\<�GE�(�yp��H�|�;\x	Ii#���s��1��s��=���s��хڣ\����J��u�O�;�5�w��9y�k\��#!��[M/��=}�߉����@���Z���j�+��ɫ�t���+	]#W�sD�����~�cj�$��!���Ŋ����_g�B����IEND�B`�libs/better-framework/assets/img/color-picker/colorpicker_hsb_s.png000064400000002223151214002570021620 0ustar00�PNG


IHDR>B�C�	pHYs�� cHRMz-�����RqE�f9!�'�VIDATx��AH�`�_jtU�m3��-��kWw� �������٫ǂ(�(x�(6l@v�ւ�0��Z�iSj��j�v�h�&%�ܾ.�'�����'}�����f�Z�08A�������҂�N�
���:�Z�q�#Q?!à�GGG�|S��귬���J�Kk���qhh�$�L&�L&��`��+>��g��yyIӴ^�hjjZ[[�
�օ��Ѩ��e��{&#f2������`��rmmm��0�^��z���X�w��t
�����E����������Ǐ�x|}}�P(HÐ���Ñ����v�ϊ�X,,��	�P(�L&�f�������t���BS__�N��6BWwo$̮��x@Q�'�-,,x<���U��Dz�(����7e�V*����>��f4�߻��a���$_(����~#��1�'��8%�J�677�LNf�Y��N��چa�+vA���p
S�\.��Օt I����F�1���$i6��


HWӲ���q����vvv�J���,�qV�U�x*,[0
.��eY�oJ�Χ��3�q�߽뷷���u�ZgF�m5i2YJg=M���1n1�w�Q�Y�t�kD@[D�I��קXa[�
!��F�1"�Z�D���j��k�%xٶmff��tvuu
{�����D�]�W��LEՈ@��
(�j����A�����D��+��ᄁ.I�D@��#B��z�ݭɶ��˗������v��b[�ɮ���UJ:���/_�|��P/Pd��%YW'��rZ%��&�uu�Z��3�H~��$I�����{zz�1U�^T �J�j"P�볳�0===11�
"��l�����?�`�>::*������(���w�"�H �z�>�okk���Qq�qqq�?��U�e���Ǜ\ZZ*^T5ֆ�����a�E��ۛ�ߗ�T�F�Պt5m6e����%���z�@Eo�*$��ZG^0J+�z���z���'���̏F��\�i�IEND�B`�libs/better-framework/assets/img/color-picker/colorpicker_indic.gif000064400000000126151214002570021571 0ustar00GIF89a#	�999[[[���!�,#	'L��˝�q��h��\E�m�f�86!xN�S~�k�L�P�;libs/better-framework/assets/img/color-picker/colorpicker_submit.png000064400000001730151214002570022027 0ustar00�PNG


IHDR,�7ߧ	pHYs�� cHRMz-�����RqE�f9!�'�V^IDATx���o�Tǿ�:����du���ml��(HmⅇIH�3H �!�`��4V����*(�Sˠ��h�Ʊc;q���iH�*A��v��+���9��)�ˊ�`��}�)�R�VGF�E��8��t\clh��t���èP����O��ܶY�o�w�G�fߝ�/)�,<��ō���.���XCj�f:�4^>z��w���D7�jW�M�T����j=n�I67�f����n-�D���:8b��p
�V7o�n|9����c��O��5���i�A��dB.BT�i&��A�lM�*{��\_-|��t�] l��\,7�����]L1��C��N$DB�i��*e6fC�W"�"�$I���a�	m�D�ɺnd�3D·Tr<8�<Is�~I��&;	,�	�����J�
8G�aI����g��u��&4��I ��k�n��`8���9B6��7y���D`	����ư�`/�Je�)m�C���J}�m=���@�B�,������xX�Ǔ����Q·����H�n���H " <V���zW�=�`�{P�4�$!G!��u�ۿ՚$�N�D�ie*���n�[ʵ�T�B�RJ���;�N���q�q�O��L��LG=��ƶ=�Z�D�1Ji�,}`�<�!��.D�*@��g��I'�����a�(��}\�N����##��]_][q���W?q��
nq�S�v`����\$��J��k\����Y�7�!�1x���'�[K�R���Re�?���ϐ(r�����G{�Q˪�?X?�H
.�d򟷃o<9�5h�|hQ��1�#^j���l�4�~����h;��IEND�B`�libs/better-framework/assets/img/color-picker/colorpicker_rgb_g.png000064400000002055151214002570021605 0ustar00�PNG


IHDR>B�C�	pHYs�� cHRMz-�����RqE�f9!�'�V�IDATx���O�@�_��l�Q�
D�JP6цx"��ƻwc$�Dc��
.�Q^��t���!\�Ґ�T�ȩ�*���-�P�;�4�Kd���N��Sb``��i0[�@�4](L'������&�V�Y��$����w� �����%"�^��P՛���C#�kz}xxxdd�����L&spp�d�;Т�a��e�H$R*���������ǧ���栖�͕L&��I�Ūe������������4M�����k�ө�y�p �����q�H$CC��x����0���q�x��u�˭��oo%IR�����h��'� .��f'B�������{�����*㛛�<�7��U~���׉�+������l�l����2d�Y��N��\y�J�C+�,�2DQ�y>[IRų�s��].ğ@_�P,ND���kvvv��8��E���p��d��h�a�i�),�>>>�ʲ�t:{{{m6[2�L�R�oPo�v��iZS�v��T����� �������@|7��`˲�$�8���U�J���9Y��m�_/��u�J��m5�ru{<��~�ϓ�ϏD�t�G��0�T�D��#�q���''�t��B-"�"��Q��T�EZD�E�&�[����h4�'��i}IU"E}C]�D����i�N5
���>��h������}^��jSv���ֆ)
?OLԙ���_"`�4�%
IǓ�J%���o5�&
UO"`�u|����h4*W�D@����lll�����Ȓ�\_����.���XI��� 	��^%W��B~
�XL!E5Iz������annN3�$�7"��J�x<n`L����pffft���T���������F���%
=9bH>��!���0F��ҟ��/x~���(�4K�,�IJ�IEND�B`�libs/better-framework/assets/img/color-picker/select.png000064400000000772151214002570017414 0ustar00�PNG


IHDR$$���gAMA��7��tEXtSoftwareAdobe ImageReadyq�e<�IDATx��J�@�w7�zIR"��\� ^��<x�<����Ƀ"����61�fa)�q�v�o�I`��K�m�
R�}|AchW؍Oh�@� �}H�	�a����R)N	#�61��I��A7�R�!���� b��8���� &a
����u-ʲUU�%��7���(���t[�T�j�1U	�y^w��9�[��.�8�גƭѯ}�0҆��Q%6,�r@�9�m���Ӯz��H$I�zh���,� 
���{eVAY�w�4��Ⳣ����3��sc6k���f3��H6�ѹbKD�cQ�A�0T�\#=���̆s�l�B�=�
���
���؎�(�r�W���Fo�\��Ȗ9dGd�2���+�0]w��G�w-��*��iIEND�B`�libs/better-framework/assets/img/color-picker/colorpicker_overlay.png000064400000024163151214002570022212 0ustar00�PNG


IHDR��<q�	pHYs�� cHRMz-�����RqE�f9!�'�V'�IDATx��}ˎ�H��'��O�;��8�n��]ݕY���=�%����G��	 �N:��(TU36w�/3��f�03���=��;�����~�6w/�W=�x��1����/��Ǣ��?����w��Z��ݽ����ݿ}����/���cf�k��yO�l@" �NԳz����1������yvq���	������羭��ێ���x<�������w���������O?�_��W��{�z|�I�ـ�s�^<��/\�o���N?�o23�������9?v<����o��v�׏}v�l;��k�|>�|�������n���n7��������������O?�d߾}�/��~h�ffm�ဵ�V���玁
�=���*�}�\<���m>����y�G�7�FrV@��t����|Zm��ǣ=��~���v󏏏������[���_�?�����~���x<ڗ�ʉ��'o
�l��r���D�֎�B�Y������6xlj��[km�[k��[�=E�#R��s~шR;�|�P}�۞�g���n;�ׯ_�_������/��/��ׯ_�|�X00)��&g!��'^I�M�a$
�����FA�9��A�0��c��N�6����1����{��`rw{<X�|>}�v����f��}����o�����_��ׯ��o�Y�}
��"m�"[��Ơ��;������DT��.V�x$���.`"�4ԙ��l��0B��߾�6��{?"5�~������G���h���}�������v���(RT��g"N�H�*��|� ����ZÓ�5Ë#z��GPf�r׊����xF,�Q�����v5@5�ۮ�����n����߿��~��}||��~���n��=�ffZcU�5�d+�-�눎<H *�NQ��D^�K�G�"!�u�/�K��f`���D���A�#za�T�k�����,pD,����o߾
!o?~��������B�\�/Ѥ8�>�t�I�(�)@�1[!������������`�u�k��&��d{;�aې�Lh������]S���@��*�ҷo���Ƕ�,�P�O�ZHRs�e�8�82�ޏGQ��=ff�X�������5p�t�ð$]u��a:DKa誝�l���=�϶G�v��ۮ�NT��?>>��LJ=���x�9bM��,J������"ꋲ1�G�|y�sax$Е4h�)�@6n�T�^"1b#��
����s�d�
-��@�j�Gd��}�Vv��~����
St�}�}�����w{<G��h��Q��*TK"Oh��좗��v�����Ӷ�MFzP��5sS�Ȁ�J.hn�7�Q��@C a&��WuP�n�nXv�����n�f��qd�>�}g<�l+�rHApB��w���V�Ĝ(�� m��y�.p�����.2-�c�'��` 
Z���(��jiD)ܶ!���ȵ�Qhi������^U�'WЭ��鲢�hԗ��B^�u��X�����N���9���L��F���yl{>��ލpD��	�t������G�~��}�am�A���ܽ��p��
(-�x�K�4��2��2%�ڶ�"�iT�@�}���F�F�"�a�2���F&xh�����Y�6"�0��n���4k�k�
�h�E� �EŔ�'��2NU�'"�JG=+�2x��CJB����L�-��U�u� ��糹{�[_���w
�n����G�C[�v���㱡E1>c����P�'ODm���E82�h�(̃�E��Q�K�:	E�38��r�o?aK�U�R贳wH��=w��n�gv�mGGO3�ӈU�`�Xf!о��������6p�L���U��m��9eyG$��&��N;���kX
���uw;�`
=����k��;,3�XQ	�R��,"	cRQ!�)O��)@����3��1�&g��4�ɻ�lLOI���d۾�@��+w}�g�f�X{�r���v��|h*���_T�4L�ݡ���kG��[����? ���8#�Ho�5�_�w�O�1,n�s��9��)���1��x�H���]C
��9���a3�#���[?x,V�;+\|��)5��������ђP�ɑOR+�L8JBC���1a\�1�t��uA�܈g�#�	�ĻC̠����N����x����چ��#�6�8�[�Gd�8S�L_)�[=�����>�@�IE}L�D/�dZ2H&��Eܣ��ln"5"-np��F��ζSZC��f.�:P��l��@����ڧ�аU`��]�\Y-P����b����XD�.�9�O�u������X7����5�6a1t0EdR����3{�c����b��lXƹD,��*-& ����	�y@��vn�����-���LX�썢ՠx鼣݀�
�g�86�=�O7����w�����n%��в�D�
�g�5�0d%�T�RJD�"�;�Aq�j��Y��p����V��^���d��8*�Z�@� Zu(� TH�x�6R��ms�t#J�N��l7�"V5Z8<q�#�5u�@S��P�(#�*Bg�S�7z���aL\ �D�뤫:Lv8m����N���~�󎴈%p폒��O�!۔���r?Ȳ��|X`G\�������D6AiFB����'��hnP|�%{
s�^XXv���|�
���N��C�t���U0�8�g��R84�N��j=0��v���i��M�k�C�UuY�ԥ�"�	m��a��	�=���>���T$�腦(D�Fkc*�#
RacZܩ�-���pS�f�ᙍ����J:E�j�%�E49�L��Y!�'},��p������@@�Jc��@��� ?�A7<*]��5�t48��cB����,U��-�`�3���ל3*�8��M�<�#09�H���]�����;e��Ơ��!
��wJ�}+�*����7�f�g y2�!r�#�D�πv��ٞ�RN��M4����|��
߇Zꤹ�y�PP����9b���X�@��%�����E��d�KDc�8�dQ�А��ȧ�P�x�����-�
w0cI��y�P�p�g�ǧȆ�rІ ��-3�
��E�8��R$ps�E�VMQ��3-e��oA����T�h�
B�c	�c���@���z<�
�B@�吕��i׋��o���
K`"1	�W(ς�x<�@�KwL�J<�=��N�I���_����@?&��Qc96�
�Bz6�Kl���jRk��ԗ�1b��L�c�h�zG�z�Ƶ�H^��W��B�-�����:E/��^�ҡ�}2A��"'*<(
#����"��ʓ!z\W�Th�aE[*��Id5^@�m�Ǯ��Y�rǸ�X��� ���eC\�1Џ�h8���MQ!f������A6���e*3�ͳ�	�����ߝ��_i�
LM��ɅQ{�ƭ�#�p�QYQ4��*�E��1�m:��6t��:�~Fd":D�w�n�v#��ìG�l{��G+�X�nSǁQLE=W�-�2@�l��A��z�R�m����h8�(��N��������/�n'Kt��4ee h鼾����at�EKJ�`���'�ECF�lZ��p�h�E��ٮ4V���%��'�+���,���!-����=���/�28z
�I��]�j:լw*�<�Gh,~���KE��(ϕ�N�K1��C�O�
&Y��>�-8�']6>o\;��M�$�)�T��s�5�|P�Ǿ`-�FF��.��`�K1�q=�X���L�'����)Z��p�M�1�l#��:��ha�������V`%��r���1���-�R!;�{A��y�Hg@o��Z
^ +D��~,SV��
�n8�)D&����h����q��mI�-1�^�͠�"W�K�0�\��)]ҟRB?������*� X�m�P&Ӗ�F���G�A���(=-��qS7O�R�<3k�Fs
G�_&��}hI���*5Mt0��2�h!w%��~��}hU ���'��2��5v�wW�a�)���w�I7:��z܏�XР�¨}f���Ӛ�C�W�;j��/Sӟ�x�F>��FEh���D�TD��ͭ2�)rC F,#?
��Fm����c��X���[�)�J��ªa�lR
��|Iwx,�G݂�>K(2+�\��w��DGe�Epй�텓�ԇ�9fw�q���o@<���+[��&�S�y���o.V�Jg	�Ղ�:���3��v"a4�4D	��ĥ�"�=�	t���++�?���:i����嗒Ɗ"�,�]�h#�.��q�R�V�z�Df�4��ų��~g �����_JC��͖�(��o��ċ�?0�rU�%�U�b!���q�fU�˥�=˨QD3~=r�MѢz��e[�B����s�$a`��g����85�m^\��[�
��6n���'&��K�����eQ	���B��ډ��r׉�N�-�a�qQ
��(²H��DԊ���
�LP�e����6�z�g�l!3T�~�@g�!�L�p%��mKT&xq�	8����؆��.Zv����B��N�w��wvij�?��")�t2Xt�(Mh0��i�k��*�D�L��pו����J��~�קcPM����p1J�|��ײ¤�8�F��d��ɢ�該E��b���)�b@�8Lw��$̐9�O2�솓>"Q��{�Uo6A�NEg��O9�X��΢Rd+g=����dLŇ�2|,�271���u��XLbf�)+B�#�mF��O�����t|��]|��� �;􈱏��;���R;�J7j���>�����yf��� ��B����QD ��<�#�`�7A��,��>�g�b�r�۳Yb(�!+OŻ�J	(egFwB�](�#�j+N"]4�>�=a?�@��㠮�n�����oՋ%����D�|Js�ֆ��Zk�0J��ڦ��<�͕�l	��|��b�5�w�%�{d �;�����Dֈ�}�hE�N�nJ7�~��"(W+�^�U�D�V��ɱ�br�b_T��h��rDwJ�� ���&��_I�������@fsԼ5����_��x�m�fS-�yc*Ã�+'�����NL�\-c4�b+�ڠ>7�Ґ�,�MQ!��,����NY������x<� �-�XK!\p6�5g�(@N��(Z�:8w���-���1Ȯpe0�/w�����uМQ��tZ��0�~n�Uc2Fkf�F=@�k�E5���0sY�OL�p�$�*ۦPd-��Dq*�=V��Ș�2�S�%{��=���	���~��f�(���ΞP��D{E̳w������M�jL�8E���qvJ�Ǚ��ԹɈ�~�_e+�ь4�%�TC�l{EO������6�{u0?�0Bی�5
�bE?��Զ2�V�V
՜'�;�XɶhMv�Hc��~
��5�&�B����&:�`�{�P�G*�#^�^�j?�(1�7E�*�E���x�>��%�̢�d��ĊW�)�Q��`�8�� ��Ep�_)+��%���(�3xO�В��j^�"Z���-��҉��q��v>�2R�T��4��|�-�0!u�+T�@���%�Qa����xʒ������Me��p��-0_�M��-1 �YOD��e��F��7���]�8�-�iw��l�2��6��H'ꑖ,Y�u�j����3�wU�F�_L���&<fe/y��ӞQe�
�"t
�Œ~*S�Z���?18-�J&X}���`�e�2�X�i/�(J�356���.�Ok��V�����F(�O��P�G�w(��΅���Wy�ٕݨ3!W��
��h�0�����Kt/KY
6J:aV8�h��Q��Y��T;�Xa�k�r�W��S�$�(2f ��f`/�U�+�B�zO�d���;�yM�#��l7$�x�(Ri�����4�3$�eډV=.�� �-j��`V�N*V�
\u5�?g#o�ĉ��7���
oN��9��RTr��l`?��Ra$h+�*x.�f��t����:����&/�KL�P�/S�g�-�za*�$�x�YB-�.��R��&��q��'��l=��=&S]��&GDuœ
+��H1�G�:
�t1�X�me�u��p��d����9��d��	,/X�
�4b�MD��{�yI�P�n�;��V#�'kh}f�R����*UR��F�I����nVt��(%�tYR�dj�Yc}2�JK�>��:;~��M�w�M�(�]-�X�UO�ǐ��%`������j!�i��B*���ꕩ�dC�Ya�_"��y���?�I�Y�BV�ylaVX�l�w)+��#V� ;8�(ȟ�Wk�'����&��+Y����`F��3"�hFlϫM&̎!��g�&@���fT�sX+	�3�K�N��|Mh���7�hq��x��uE��O�z�� Ц&a&�
��r0��#T�
�͟i)5���k����N�
�����M���^^�2=�֢�MO2Ė	v1�T�a�zE�O(�o�b�`�tX+�s�TdkB�7�X�b!D�'h��k��fٜ�[�U�lE�&f�dV��	���EQw�O�ξ)-4Z4Ϗ�Zq�i�ZxT�vI�y�>40>�ܧ����"U�"�I�i+�D'>���z[�6'��W:(�4�DHh�e�h�HmM��1ۘ"eO���7a��I�Z�X��zۣ��6Y�-j9��X�(�K,�i�tqP����7��2U�fžu���R��Aj)�\�
���U��W����ļ�6�e�� BJ�4)V��6�t2�b*z�^t�΂�wJ����A�=���v�e-�Wg�>OfXK��NT�9a��=�>�4+)LPZ��/YetQr�h益^��w����WT��X3A��f�(�6�d�9k:Z=&Zbe�ЫcbI��SY��R�$d�*�<e�&Q�iʅ�m���Q�w�瓜N,-�q�W�z�QǢ�Z�z*g�,d&
��9�|�h�˹`-��U;2�����
������kfk7$��m3�fW��dDÅɯ���,]�F�L
DS�x�R�.���@�^G;g���J��Z���5���_(	��8Oуh�p�_Ф�l!��c�{DϢYvO�Sv&tXD�
%�)Sm��E�� #Tm2ao�tyJ^�E���,p��[d'���B������G<����yc*���5.&����*�ú�.�N���Mp��欹X̟R�ly�dA��|�
��2���w|����螏!��V@i
V֜wFz�t%�@�3��l.���}E�d���,�yT
j�ꘒD�_���X��zQ��%
�ƾ�X
�
e���]�d�h2�E���L�pE?�>�y��ѨS�����EM��}Z��eǝ�d��z�Pq��H_5��j�H�!g�����#Q*{�YD��Ƿ�Mo(`��{/�y���@�:�.�ɨ�d1�J�t�}�qߡN�������,-��71W����O��<�곓I!a�gn�?'��ﭘi�p|ȶ�C�,�6��&�k��U�JѬ|/53(�
-��G��٬���$_�^��.Sn{E�MZ�\]P�B�G�Z��J����V�eBPg�d	(�+�Q����ی����D�Db�ה�?��!-��e SQ���7ZcE��Bs�55Hg'M%	0�����-GQ�)}eĪ�@�2[i;�!�@��'� �VDP9he*�k�V(YdjI�Xpn�d�/�����+m�\$�y��-"��@EdR��g]�}�
S�8�Gݤ.����W��:Ӌae���m�?��
�eV�ߣD�4�XIʀ������0/����PFyr��х���/��_h��Syy���tX�ӂw�پ!eV��Jɕ��J�E'��.���k*��2�7j�.��(����E�@���g|"+��a�
g6�D?��W�6Ŭ-�@፞"A��%��0ZK��W�dt2D'"��.�l`����+��l-�J��o��W,��+�lE�M�HQ��U5��'��
�t�^�
{�̬e+�2Z4���_�&F���4��^����+HdG��^���&\w|�6�;�u=�5����=�J����z�������E��`�̙��>�F�r���"���l
���#��DGU谪�T.�%��ʺ]�M�h��,J{��0KQM}{!�:�ƒ�W�_��PHeL��p�M�Q���U�Z:�8g�|a��-���)3�+����Ӷf�V�����[���.�,���MZTA�T�-/�dbo�j݄�q��aAy2c��MR�D�l2EҤ���i�}f���)jܣ�����1��+~^�K�,�t)�R`�8��~<��������)5.�E�9�����x
=�Y����P��b|�W(�{Р�N'+b��m��auֱP�_�W{`�)�	�W5��F�Y��$�_)���=3oy��||�9��t2���"`XD��Kg�T#Ҥ�d�$[a2oa���@�zQD4i3�U���e�3���6�dz�eBޮ�<Xt��&4e%:[��C\�>
*!H��}�e1�1��|�L��" -(�_�u����dK��%�/Pn����8�-Qq��T8I�/Ae����"M�&�&�/�G�3�:V��O����#u2�(ri*L��Y�����}��ϙb+`+g��M���-�2�X��ݐ
�Qk&�+Wz���+ؽxRձ�z������XV�*�|a�Px�Sa�E�Y��3Z�P�������g� �
�K_�%F�hW�|J�����#�}e@���
�_�����f����xi��u�&+��uC�V�OG)8�J�����8���U�M��>�=	0��fc ��<��,�i`³�f����T�ZxU�\8QK't!�J�D�H\���.+)����l@�\��"�b�dWځ^��޸H8��Qh!BթpS��V"Bpu�/��V(��}�`	������2$��c*\LC3:{gP�NiJ������@�]t�Z�@����T z���\��5=��R��{��!�|��Iy%b�V��=�գ��)����;Sd9�´��Up-��g
�*�^y>�g_�/]�o�]K��X�K�McU��QW��{f���"�(L��|���lN�hsq˶7:�X�.x��� 
��k�w�f�M2�}h��lQ�칭R�*(�z�'w�0K�<�2�b��U>Wz���PUw�������MѤ��*W[�*MN���W�X*������ը��S�J�:-n�Ԧ��T}M|�W�Sy
�%j�M���Dp���t|*₶�����\��h��,�T8��)�@+��/_4+�\��b7�i�Z8��'=;q�;�����YuP���juLVAN�^5��<Vƫͼ�҈�
��Q&g�0 �Z~��Ty_������<��W*�]�#eV��m���vq׳m�6c�]|�a����m��'�x�|�9���$RD�d�M�D�e�+���O"Pd	�Ve�\�q�����joQ�SI���OٖxN+����fQ�N�U�`(��zw�*W�96��.^h�c���L�5��7�]0��Rz��\��d:�
�ϸ.�x2���U�g¥}^k+z��"wj�V'F,�
��>�]�?��U9a�h�)�x����˱
��`�L-j��X�O�*�y�V.·�j�+�ݱ�������+����
@�yO,��֬�o�XFh{�x��
��+'�j���W�ȗ�j���һ�l�9~�V������7�gH���ᕈ�IѰ,Z����WZ��r�@���>���Łm+��d|>=��@z�sg�j_�
�W�+I�����W�1�����l3?�}��������HW��K������~>��_�o�x=)��{zIEND�B`�libs/better-framework/assets/img/color-picker/colorpicker_hex.png000064400000001024151214002570021304 0ustar00�PNG


IHDRH,I�i\	pHYs�� cHRMz-�����RqE�f9!�'�V�IDATx�옱k�@ƿ$f�bA�"�I'�F�����T���P܊�\�b�p ׋R�@_�M�ޏ���}^�$Q���R"���~������ x�	!nx�����v��C��L���ȍ���w�f��eL3k�W��V+�Xw�ɬM�:��E����t�Z�
Cj`�
[a���h2��<�sm��v̬M��]Z��-CZ�P�*�ss��/�I���w�cz����H�
�ݱK����e�6���t���LC���G1�2�0�r{��x<����O0��0����13�]Y�n�/����C�R5��#����X��	s�:Tϣ�K�\JED��TeV�R*�R�'�5��RQE�Rq�r{��s�a�1��1�`��|$���9�վ��VIEND�B`�libs/better-framework/assets/img/color-picker/colorpicker_hsb_h.png000064400000001764151214002570021616 0ustar00�PNG


IHDR>B�C�	pHYs�� cHRMz-�����RqE�f9!�'�VzIDATx���J�@��iRmkQj��Fkm�"�S����'
.���Q�Ev��+���ŋ�x��Ma,^��F�&�������ΰ�e&���~�3�����h4
���(|4���c=�������8V�y�Ù��EQH����!�T*�I�.t���E��n���]Q������‚-�4:�7��G���F���􄻓���`��hXsH�[�:??�v�QU�g���6�tMk��͇�H8l&�BD�M��$@�R�e���y�u�y���r���<��a�a�f
s��L�,�vff��e
9�L�Ӫ��&��f�
�X�L��sppP�V�@�{{�a��$E�ܐ..p#;;�@�1����H$��a��Q�L2��+��V%	w��=��2T0�\����d2��:z�,���H$244����>;;k�Z###f�q��������lT�x���8ν`dY!
�C777�X,6���077��tH<����x<���RӴ���ѩx_g]QV���X2�`��^瓉D�Ra}>���[F���7��?%����)!��B�7������F�����F�j#�>���ZM|��V���f�J�΄�Y붥S�펾X(0���}y�������S���j&W�0::J����?--�I�~rB��t���W��i��6�F��j�j<g�^#��
����X,��?��m3��F���o�K��J%:�F@{��eg��o����̀�X��[[[Ν������!nlnn��0��EQE���-�}���GGG�N����6���`mm�Q0T�����U�z����^#�7G
����)������G/��9����s����:=D�p=IEND�B`�libs/better-framework/assets/img/color-picker/colorpicker_rgb_r.png000064400000002052151214002570021615 0ustar00�PNG


IHDR>B�C�	pHYs�� cHRMz-�����RqE�f9!�'�V�IDATx��AKA���ec�kX!����K���"�*�A��Y�����,
/UR�Q4mL�b���lt����˺�&A�t��1�a�
�g�������6�
�fǑ6�-��N��� �d2�����&�J'I�#Q���PI���SD�].WUUO��6j������)�.B4��߯��'�$a4��x677������s�\ p:����s����g' /���x��������h���*�0��ժ8�-��U?	��b=^�zv�Ţ~���q8f�������ekk��yb�jSTu�l2���lW׃X�Џ����+�������d��v��De��X�-L�ʙ�������������\�c��J�ow���:��^�\?ON>ml���:�β>(�dr�q�L�g7��FS�-#���p6�};4���)�4`�KOOx�^���绽�ՌbY6��4-RZ[[EQL��mmm�EQH��zUj�(���BӑJ�h��X,r���(�V��X,��V5&	��W(P���h�U���;s�$��U�t,��F��q�Q���Ϟ�3��_d2d;�|��'���oc�W��?
��H L��lo#����AD"��*���h����O5B����M�A����EQy�onn�c�?P%���%��5�ӤNEQ��i2�>I�D�?$����2bZmȬ�v;�D���30P�!�K�2M|�@M��$�(�T~��Դ�x����/�T��� =��� h�L���c;;�C!����}u���`0�`P#_" �?�������$קU��/(�b}bbB߈/P�������1��T(�%06&�\YYQ�&IR���(���(-X�k���_" U{�Ǘ�tsĐ�t�JG0�~�Ɛ^������
�9A�3��r���IEND�B`�libs/better-framework/assets/img/color-picker/slider.png000064400000000473151214002570017415 0ustar00�PNG


IHDRL}8vgAMA��7��tEXtSoftwareAdobe ImageReadyq�e<�IDATx���;�0�PP��8��b����(���C�~JF[��q�R,��ڬ[�^����ֵy�>�Y����1�(
�B�P(
�/���9���r˽Ź %Q(
�B�P(�+�b�B�P(
�B��V�9W�7J��]��(
�B�P(�ҕX@�P(
�B�P�*���}/DI
�B�P(J��c�s�KvTK,�w+[�2"��IEND�B`�libs/better-framework/assets/img/color-picker/custom_hsb_s.png000064400000002220151214002570020613 0ustar00�PNG


IHDR>B�C�	pHYs�� cHRMz-�����RqE�f9!�'�VIDATx��mHSQǟ�{6ݚ��X1��-{�T�
#(���
?A/� d�E��!��a���R}H�("!2�UV[V7�����9�vo���潊r����pv�3��Ξ=�9�i�v;�q a>^DZ|��q\bb��G��\�x����R
@0�z4DK����o��yR���nN�����N���q�:5]�'�������eـ.�<߲e}!��)\a¬���e٢�����g�ך�6��.��2cQdt�z}���nwyyynn.;�ibz�.0��8��}����J����I��������8:�
Oh��RUU���5/-o٢��WS�����P��uuX�Ќ���46�M����������v�ܳ*7=�appH�
c0��8Q �����yaZZYY��{�J6oo��jF�һ
�4-����ixUZZZ���>�As�fR%�K8��gGG�^"3�L����jj���}(���u�⌆i<�Wo?�56�M���eY��t2�|aފ�t���^W���)��11r����C���|���`2��t��ƣp)5��>M��8��>��!T:��#���=M��I��"8�~]�ҍF�̵�X��q3�v��\R���L�sg�B}.WVF����]Q"�."��]Qe˗�*H�d*����3J�D�"����a�*%�\������뤈�T�X�\��(7��QZZZ\\��@e�nL�,���M�ʋ�-�'m흪$�fS���D`vR�'�Q㵚u�O�P"��y�G�e���Kh��Pc�Xr��V�S+��b�Jt�	�:	D��)�Dӡq��^�KD�D��>'��3Gw���W%̩�W�؁�/4��hE?ӳ�����1��f�PR���}�H|m��z�������o�T�ߎ'�.ߌ�D�h<.Z��ȃ����&H��^�
����%ڑG���ݰr���G�D��s$��{�Ljק�Z�ˈ*�G��!�]���g9�'
��k�IEND�B`�libs/better-framework/assets/img/color-picker/custom_indic.gif000064400000000126151214002570020567 0ustar00GIF89a#	���Θ�����!�,#	'L��˝�q��h��\E�m�f�86!xN�S~�k�L�P�;libs/better-framework/assets/img/color-picker/colorpicker_background.png000064400000003551151214002570022646 0ustar00�PNG


IHDRd�8��tEXtSoftwareAdobe ImageReadyq�e<IDATx���Ok[W��seŭ��u�!�	�w���ݵPJ��B)���Yf�U�E)�f�ݏ(�B�"�"�IIđ���3wB�I��>�>D�㼾�qr%_7��"�i��ˍ�v�z)�	O�z׷���=op
r� ��q�bN�ꇸ��-w��1��xe���]^�8�q7���z/�=s؈�q}קq�S�S�S��[�O7o�p?loo��ݿ�����,�OA�m��;�n�
�?>45�
�����1�wZA�Mu��s��nW�6(56���
���A�A�Pw�vvv��A�:��=��h4
��l�c_�0��e��	���p����Q�kf.��\^9�b�&�s+�c��p�_�~�����N]5ʿ��Ư}��巟��u����/�P��}x�֓w�<�o��W�n���yӄ?����繑�53�
^������ƞ��IF�;�|<8O��%�.7,2�o�AAF��R�2�up�A�J�AAA��~��11F��!2���r�f��vȂ� � � Ù� #�P�t
9��.�!�e�AAA��� #�P�t
y+�c#D���� #� � ���d갓yZύA�2z�� C��� C
N��qu3�d���#� � ��2d�0ޅ� C��'�q�:�ۇ��������6�����9w�k4���,�I�vsYm.v�\z��!�f�0}�em���z�wCF��
SAF�A�A��e"�2�!]Cn2�_!�eLAAAAF��� � � � C� ������1"�P&�9/�5�� C=AAAF�A�A�
9�A�a� C!O�b�3��EF������U�2�u�	2���-;F� C�F� Cz>Ʊ1"�PG��ƈ C�t
9�g8	2���� Cz�� � � CK���s��#D���Y�d�@_�d�CAAF��>�E����}�4���A�:�AAA���̳zn�2��d��d�=�;�;�� C![d�0d�0�� C5;dAF��AF��A�����A�
LA�:LAAA��t
��8~a�2��!2��2�v� ��23��!� C&>ƶ1"�P�Y�d( ]C�ya.� �k�2��!�
�2�v� ��B�sn�1BJ��1���#�2��.X � � � �2T�/�2�a�d�C�d�<A>2F�A�:�kȹ?��{cD�!_/��z222�W_�d�C���s{�#D���� #� � � �2�䭌㏍AAAF�AAA�R9礞!���� 2��A�:l=�+㕹�"#�P��AAA����2222���?d7DF�A�A�A�d��D�d��,�&�"�P�T�dddd~!� � � �P2�/#��&�� C�7��0�!�eLAAA��� #�p����C��
ӣn�Z�˶���A�A~2���A�}xhzlD:�V5��\�v-|�;E>����{�G�Q8888�2l"��[���1�x^6����i���9��y6���phrT�ٳgᛯ�6��u�@�dA���~�������j6#5v>���>j=���|���w���mml���h=�(�a�F\\>�R\����r���o'�<���t�ؿ��F��in�]�\�ql�g���fp�1^68���ĝ�~��%�W��^lJ
�㸾�
���L��J��IEND�B`�libs/better-framework/assets/img/color-picker/custom_submit.png000064400000001745151214002570021033 0ustar00�PNG


IHDR,�7ߧ	pHYs�� cHRMz-�����RqE�f9!�'�VkIDATx���o�dƟׯ�ĉ���F�-EaK����A�KӺ��l7\��
��2�&6:iRA��-�JW5ݔ�~�i;�'�.�.Hk�G�ͱ���9���D�XҰ�}^�X�:B�=[�g�X�ea�0󟷈�'fgf<KS�;qT$O
�O����}��݂L���k����o�+ߜ	�G({Proo��
�|a���蛻/W*��*�ߘ8�}1��y1� �UC���ȩN�|�˙��8r�/YH$�����k9P	���zjP,��/_Z�nl.��9v�!��h&sw�o_���
4?�x�-@���@dϖ�O�F����؃hZ�n{ef��]%�_��AV�'Q�����R�,�V�?�%�^e0i��S�j�*���$��!ހNy���r%^T:�'�2��2�*p�(��e�5l�jgcg�z�]%'��e�!@a�V��@�!��xzs��ѰO34�����,�5�4�"X�Ȳ�XHh��^�z�w$���܏��	�:�H
$	d�(68��6��v��U�����~��j.�+���A�@H�����╋�}ǻ�9��Y8?z����ϯ�����.��R�)k�����}r��sgw߷w���w!�Pʰ��[�{z:�,�s�n�FBC/���
�4-ǥ^7���<�Ա��a�oV۲,��QM�lm�0L�|l^����}��7���/�l�E6_(�4�ܞ-&������N��B�a��&�la⧱+mD�M�c��-�'�F�,������ۓ���k�scM��	
}�F;�w�N�����b�X,�a�R��F��ȿD�,>H����v��"�IEND�B`�libs/better-framework/assets/img/color-picker/colorpicker_hsb_b.png000064400000001712151214002570021601 0ustar00�PNG


IHDR>B�C�	pHYs�� cHRMz-�����RqE�f9!�'�VPIDATx��AKA���l�⚰�ƃQj֘�x1x�P��݃�!�� H������)Ғ����/F�n��d�=�n7٘
�Ig��0nf�����C�`0��<�V��r<����Q�>88�˲@aq��xhE�8�#q�UUq����5&�@ �H�G�x���=����f���������;��F�T*u{{������8==m�cVt+U&��$�av~j�}���a�Px�q}}}�`���������n��&U6�C�p�:;�Z�>r~~�\.{�����D"Q*���u�W&�d(t�ϣvhb�.0�0���(j�ƲlOO����i7�e�.
5�zS�d2��f=,�qa!�O�;��*wq���ɺ����g�����QA�puU3{���X(��\\^Zg60kkk�J��������p^�PE"[��S`l�DBQ���.�a���eY��|Lg��0�wF���R�w||�����mڬS;��@ @"�c�N��q^�]UUZ���0�S�~S,r�~��L�:�)Ir�]F�}����K��0^����a➉F]#����<�����F��5�p��k\#�F`&��Z]P���F�X�)��]�������%�LI҇��RGG�G�I�h�L#P�Th5���V�L#�u�aJEEQ��,˱Xlvv�ާ�fmmm�E�0W}gg���777�0z���76����%����%��x��\#P}Z���=�X]]����*����� ���͇Dk6���`ii�"��T���
O�5z=(MF���#�F���Ft�q�$������?-kگO���2h��IEND�B`�libs/better-framework/assets/img/color-picker/blank.gif000064400000000061151214002570017174 0ustar00GIF89a��������!�,T;libs/better-framework/assets/img/color-picker/custom_hex.png000064400000001062151214002570020304 0ustar00�PNG


IHDRH,I�i\	pHYs�� cHRMz-�����RqE�f9!�'�V�IDATx���KAǿ����L"<E�a!:������;<B�!���P�`F
�+mc��m�����i��v����f��7��Tkw�P�bш��t3ӊ�5�Z&��3��|i�#x2c��ا�{Pj~�U��UQ�E�_{����Ṋ���}O��� �]j&�f����2�ws<�2YwQJ��50�B��#$���1�R�P*x0�Fp��ڌ�SˏU)�w�?t`�vrbZ��Y��>��<�x�Y�,��Wȃ
��o��G��'�|�
3܊uߔ��@��3�`�����&6���C�X4������7���%q��hZ�K�����J��N$ˋ�0�*���*���k�Ri��ʬ8����j�J�T�����-�R��J@��3�`�T�tj���U� �%�J�����=w��X$,ݫIEND�B`�libs/better-framework/assets/img/color-picker/custom_rgb_r.png000064400000001772151214002570020623 0ustar00�PNG


IHDR>B�C�	pHYs�� cHRMz-�����RqE�f9!�'�V�IDATx��]HA��vg�ӳ�#/1���<?�.̊D
|{,��D���#{�|�L+�PJ������!
AB8(���N/�<�L����a�c������3���;?������,�KN�Z$�epqɩLOC�63�@ �l,t�gH�\ƌ���uU�V��ǿO3Rq7a�b��������J��r
H2�XL�C�u5'��VI��ޞ.��LD���}�h�{��X���(g[Ɩ�����S5�ͮ-�q�<���U�U�&P��|�l��&�~��b����x?�n���L'O��Y�
ˇU��QsA����|���u������75])�S�&~$j�҉���X�{�V�^m~߫�ׯ�,�vLLN��ө��ʐ�9MI2�Pa�Xժ̊#��m��ə�m�D*�I�,ܵ��;��cUe�
e�>�X����臌f愹pQ���}�>O��D,�ן'(O����O:=3�&wǬ}���R�R6�	:�n�����t��_�|�>�r�N#��@<��qvW�@����~U�d��c�Ϲ�͎z�R�6���B���y#��Ǒ1V�v�Y4�u,q��7�F�7\1l��F ����F�7���F�m�I#�Ve�F`���l��x�������~���
��s��8D���1�X���j�Մq�:��c�����XG��8D��E�2y�R��QF"M����MmX�`47��jqZp��������4U��#@ЦiK����5puI�?w����}�������g�^:{<t��F��?�|�p����]#@�/Iݏ^F��`\��k���9h�Ƨ��ğ�!�*:�1�:g��`ͧR����Sz��>�IEND�B`�libs/better-framework/assets/img/color-picker/select2.png000064400000001006151214002570017465 0ustar00�PNG


IHDR$$���	pHYs�� cHRMz-�����RqE�f9!�'�V�IDATx��J�@E�K�*Ԥ-���q�_�•��ʅ_Խ+���A	�ibAM���`[�iZȅ�<�̙��Kr����-�h���;�@ "�q��Q�"`$"�c
E�`��(sM�p	��2�'0.�7��Z�Dk}�ͤ�(����$I��T������ֆ��)��1p��x[�H���$���
TsI��Vϭ�qp<�B�Z�?�_}b`��X�Q�
S	T�@%P	Tm;���\���c�@<<>��n�~��9@�*PκOf��
4��C�W迌E}f�Ƙ�ʹRI�~��ݮ�*?�h�H$�]��f��4�.�(Wń
'���
8ZS�p����6ˇN�c"��Na�<4*&�:���ֺ
�Dd�2ć����<�/y�ķPdIEND�B`�libs/better-framework/assets/img/better-studio-menu-logo.png000064400000001664151214002570020237 0ustar00�PNG


IHDR�atEXtSoftwareAdobe ImageReadyq�e<#iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.5-c014 79.151481, 2013/03/13-12:09:15        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmpMM:DocumentID="xmp.did:B013829F6B6D11E4BD52C2D66E99A052" xmpMM:InstanceID="xmp.iid:B013829E6B6D11E4BD52C2D66E99A052" xmp:CreatorTool="Adobe Photoshop CC (Macintosh)"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:48ED78875AF411E4A8D3C67005C0FA2D" stRef:documentID="xmp.did:48ED78885AF411E4A8D3C67005C0FA2D"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>f�s'IDATx�b���?��B�Qp@���@ Z�42 ��-?�Q�nIEND�B`�libs/better-framework/assets/img/chosen-sprite@2x.png000064400000001076151214002570016677 0ustar00�PNG


IHDRhJ`��?PLTE������FFF���FFF���������������������FFF������������������FFF�<بtRNS���00x�`��`O�B����IDATX���ъ� ����XM��u�]�f���7���
V��ԹQh���T��ܤ��$�*ue)��*uFZ��DuL�;&=:���n�I��q��́�@n��&ܛ�ĦKu5h��%쥦gb�� �������z���$�+�;�%��$M��Rl���'�^j���I�����^J��*Vv.Ks�l�.gۮ�K�s��S$B��J}Y
��J��C";&Q���I��i��[w�a8�s��+茗��3����{���;j�G�j�A�%@��Z�(���4��y'��
nw��fU���ݑ�2+�p��S��	Q8��>N;���J����u��9����w����<��3!��v-kZ>v���T)9f&K�G�~���_)
7���I�"��M*���eMIEND�B`�libs/better-framework/assets/img/bs-notice-logo.png000064400000001137151214002570016361 0ustar00�PNG


IHDR�$�D	E�PLTE��������������������������������������������������������������������������������������������������������������������������������� ���+tRNS���
ؑ81�����(⺉|f�˲��R?#�Ý��-ZIf�"F_IDATX���n�0Ec��5��$M���+��Ui:R�7!t/X�Hc��b�<��0}�JO\��,8�Ͷ NZ`����O��B��y�̂�,�98�S���;]~��5�Wo�.�DfP!N�>���.�\�iEI�8Q{��|��#�"�1���Z�\JnDm�Y��5LZ�Q�
s��+��X(J
j��[��b���>�K����>�L:��Ld�j���ɉx�h�O�\bg4��6�Y�ܱ�J��wg+�`:�D@-�p��b�
�:��T�Iu褊-L�D��0��Vo[���P��tq��_��Rs�A`�\|�X,��Q|~�NPb�<3IEND�B`�libs/better-framework/assets/img/chosen-sprite.png000064400000001021151214002570016313 0ustar00�PNG


IHDR4%:,:��PLTEFFF������www������������������������FFF������FFFFFFFFF���������������������FFF������FFF|||FFFFFF������FFFFFFFFFFFFFFF���FFF���FFF��
*tRNS�4�
�����`W7.3���ï�LB9��w0ý�pcZ?��+-�IDAT8���n�0E���0��>��7��%�mA��=�D|��Hn������8J�4Dp^.�`�@�d��ڞԟ��'kM0���"�7��<4��4]���)oli Y���>���y_*�u�
����r��嵞�>W-K�I}oRˇ��'AZ�>,ţ�Փt2۩d���5j���/���O�/�oq}��:s��B	�!�0�����T�ܤ;zB�p�
�5�}W�)������z
|�B��nu�uƢ1�K[s�^д�m�����FS�IEND�B`�libs/better-framework/assets/img/preloader.gif000064400000003471151214002570015501 0ustar00GIF89a����������FFFzzzXXX$$$���������666hhh!�NETSCAPE2.0!�Created with ajaxload.info!�	
,w  	!�DB�A��H���¬��a��D���@ ^�A�X��P�@�"U���Q#	��B�\;���1�o�:2$v@
$|,3

�_#
d�53�"s5e!!�	
,v  i@e9�DA�A�����/�`ph$�Ca%@ ���pH���x�F��uS��x#�
�.�݄�Yf�L_"
p
3B�W��]|L
\6�{|z�8�7[7!!�	
,x  �e9�DE"������2r,��qP���j��`�8��@8bH, *��0-�
�mFW��9�LP�E3+
(�B"
f�{�*BW_/�
@_$��~Kr�7Ar7!!�	
,v  �4e9��!H�"�*��Q�/@���-�4�ép4�R+��-��p�ȧ`�P(�6�᠝�U/� 	*,�)(+/]"lO�/�*Ak���K���]A~66�6!!�	
,l  ie9�"���*���-�80H���=N;���T�E�����q��e��UoK2_WZ�݌V��1jgWe@tuH//w`?��f~#���6��#!!�	
,~  �,e9��"���*
�;pR�%��#0��`� �'�c�(��J@@���/1�i4��`�V��B�V
u}�"caNi/]))�-Lel	mi}
me[+!!�	
,y  Ie9��"M�6�*¨"7E͖��@G((L&�pqj@Z����� ��%@�w�Z) �pl(
���ԭ�q�u*R&c	`))(s_J��>_\'Gm7�$+!!�	
,w  Ie9�*,� (�*�(�B5[1� �Z��Iah!G��exz��J0�e�6��@V|U��4��Dm��%$͛�p
	\Gx		
}@+|=+
1�-	Ea5l)+!!�	
,y  )�䨞'A�K����ڍ,�����E\(l���&;5 ��5D���0��3�a�0-���-�����ÃpH4V	%
i
p[R"|	��#
�	6iZwcw*!!�	
,y  )�䨞,K�*�����0�a�;׋аY8�b`4�n�¨Bb�b�x�,������������(	Ƚ� %
>

2*�i*	/:�+$v*!!�	
,u  )�䨞l[�$�
�Jq[��q3�`Q[�5��:���IX!0�rAD8Cv����HPfi��iQ���AP@pC
%D
PQ46�
iciNj0w
�)#!!�	
,y  )��.q��
,G�Jr(�J�8�C��*���B�,����&<
�����h�W~-��`�,	����,�>;

8RN<,�<1T]
�c��'
qk$
@)#!;libs/better-framework/assets/img/pretty-photo-loader.gif000064400000014273151214002570017450 0ustar00GIF89a�dfd���������|z|��̤�����trt��Ĝ����섆���Ԭ��lnl��������䄂���Ԭ�����ljl���������|~|��̤����tvt��Ĝ����쌊���ܴ��!�NETSCAPE2.0!�	,�@��"<���p�Z���0�<��s�� .�)���:�%���@˃H��5�#|��V[~tx~N�
M[}�pD�}[��$��g����$�#���O

$#n��O\KVu!Zg$C
��D$	 �D	
V�PG��A��� D*8	H��B��
J���@B.VH@(��,
	!�	,�@��"<B��	�C��@<���p��%b��.O�����*�zHټ'BRRE]#���"]�
�QD_�_��D��
#O��j##��D���D�!�D�ʈ��Q

!P��$��ㄚ
�C$!	̄�"�:�h���}
p��
D�
J����b�} Qb9����@���Gِ !�	,�ljl���������|~|��̤�����tvt��Ĝ����쌊���Ԭ��trt��������䄆������lnl��������䄂���̬����|z|��Ĥ����쌎���ܴ���N�"<@B��Њ�Ca(��|�D(I�!xh-p/�Y("."�j4`S
Q"SR�POT�#��C�$""PB�R��
aS�a!����D!��n�
�̻
 	���#�����!m����	D�##�Dꑸ0�ܦm��7e	.@�`��
��2��	P��`8R�2l� r����!�	,�@��"<p#‡*��¡�H�l6���Ө3�\�\��ґ
#F9�)p0��RZ(#q~a$
#S��#B
�$aRP"bb�~�
Cn�P�!

�D��n�!!���""���a ��R�"QP��%	�aP�C%�_��`���!	[��X�n�$�C�B����ѐ "8X$AJ�,

P`�_!�	,�@��"<p*��F`(�P��BQ0�
��a�D(&3a'��������@0
A8�b�h-$

R$�!S�
!

�`�	!%�QaD�a�����Bʗ�O�S�o� %_P���%%O��D"B_��C�����O��R(@H���nBh��	� 
p�@�〉�ĒP�$��
H|�
(4X9�B!�	,�ljl���������|~|��̤�����tvt��Ĝ����쌊���Ԭ��trt��������䄆������lnl��������䄂���̬����|z|��Ĥ����쌎���ܴ����N�"<4H���Њ�2	DX�FCm�Dh"��\�	��!��(B�|(��B�� HBT 

 #�p�$  S�!#p`paD�C$
Q��$$���ҕS���	����P��!	O���q��`���$�P`�k�B<IT`Æ�X�@�j6�i0"�G	"����(d��/"2Pٲ�� !�	,�ljl���������|~|��̤�����tvt��Ĝ����쌊���Ԭ��trt��������䄆������lnl��������䄂���̬����|z|��Ĥ����쌎���ܴ����N�"<4.&B��Њ�2�("�@�``(C"�`�"�-c2��B
�r��a�!\��aS#$!R�D$$S�C�CQba
	���p
��DS�		���a��	��y#����O�PC�	#pƯ	��`�^zTđ�xFX �Ex�2���!Â�!.��BcG�B���jʁ$H�h�\� !�	,�ljl���������|~|��̤�����tvt��Ĝ����쌊���Ԭ��trt��������䄆������lnl��������䄂���̬����|z|��Ĥ����쌎���ܴ����N�"� E��Š�2"@ %F RP��"�C�j�"F`H�PH�!�5
�4cr�f.pQS_	!`SDSlmP�Q$ 		�D��D
	������RĠ�l#؃P�l
O���
���a<�b�A	�U��0FȐ�@B!0�j��,a�Ȉ'�4I9�b�~�(�I2��
A!�	,�@��"�@�N��i�B�Ԣ�8*��!�P�a�R*g��H$�=$���H��Z HD5	rQS!##	"S�!#	�ano�$  �Q��%Eo�D$��D�aR������

��T#

�PS�!"w��PC� F�nb���#v���@�Y@O�@\\�+<�у���;�Q���p�c'���'B���!�	,�ljl���������|~|��̤�����tvt��Ĝ����쌊���Ԭ��trt��������䄆������lnl��������䄂���̬����|z|��Ĥ����쌎���ܴ����N�"�d6�#���h%�J���E��QrIf
 �"1$p�g4P.�H�=\
	BR
_RD
���}"v�OmP#

�D��_#�#!�m�#Ȓ��Q!u���"�O�m����!�� ��鵤����RB,"�s4X��C���!��-��ѡ��<|�b�M�0|PV+!�	,�@��"�,(�����e�%!�@��qF���8��n�JaH4R8�BS�!�J��z�hP�BR%$D$$

R�!"�$"_l_S

��mC��mD�_!t����S����"���Q##""O��	�ܭ�P�""��B���l���$�i�0"�ߊPp�?| �朇/<���V�$�@��
!
tje!!�	,�@��"�,H�BD������I��>5
�P�j�eH4�H�F"0��c=<�$"BRFDR���m�"$s��mC !�P�l�!
����S�
����
"���Q!"����%��O�}#k�^m%#�O%D�%�JhX BB��F�� �a"�
�lA�T�!U�> l9��N��!�	,�@��"�,
N�Ӑ����@jP(�B"�D���j-@	C���X��h8	L �4"BRF	{%^p�nR_	���C%$"�`nP"��o�"�D�Q!����"�!���Q

��O�nO��S
}���B%!~#�%##_�АKC���&�@� @@`��		+�RE �D 7�Kf
>|a����A!�	,�@��"�4��r�(-P�q@�R(��	u���P%HC�Q#Ѹ���QN��҅\r�GDz\DQjB"�Qi]"�}jiO%% �"N�~DF~C��R���P�G���i�!N�~! ��
!$x�j

� ��$]6`�  
��R�>���� ��P`��6Pd��:tR
!2C�!�	,�ljl���������|~|��̤�����tvt��Ĝ����쌊���Ԭ��trt��������䄆������lnl��������䄂���̬����|z|��Ĥ����쌎���ܴ���N�"�B�� �	��h�H*���}R��Q�B����"�Xكe�1��PZ	56hz|RB	^g{]w		IPP�D##��D	�|g]Q�
�������g$$ h�hQ
{O{$�دB	 $CD��  #]�T"DP�Ձ|h� B@C"tDd�4��6f6p�1	
U!�	,�ljl���������|~|��̤�����tvt��Ĝ����쌊���Ԭ��trt��������䄆������lnl��������䄂���̬����|z|��Ĥ����쌎���ܴ����N�"B�b*+P�ḔH2��aHtNC��u0I�ީ�()�a��qʡ�àA�,*[Q�B#�x\x���rwO
�]D�x������	��#��Q	��!
vQw#g�N�$��B$C� �xx$$�r` p�0�	
&0�! �D���"�A�݆9@�A@hP�R!�	,�@��""�Bt(-P��\,$�EZ<��H�D�,�DK墝���t.B-��\QR_ �Q|i
!RB\�OR��
��h�$��Q ���h"		C��	m�N�	!�v	C��%%���7"C-p(��>0�`  C!�P��C4�((��!B��J���'T��Z� !�	,�@��"<=���ȴ8=�͢(�.D�'QX�:H�A�Xh�OO�rAL��D�tlD��ܚ5Y}�B$ i��$"�B[iC
$��CO

Z�Z��$��}�#�}�%L��  
#o�G� 	 ���	{#Y�D0`����(� �J�P��(0СB)h�@�!:tt@�Q����D���;libs/better-framework/assets/css/admin-plugins.css000064400000066051151214002570016335 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */


/*
------------------------------------------------------------------------------------------------------------------------
1. BASIC STYLE
------------------------------------------------------------------------------------------------------------------------
*/

.mCustomScrollbar{ -ms-touch-action: none; touch-action: none; /* MSPointer events - direct all pointer events to js */ }
.mCustomScrollbar.mCS_no_scrollbar{ -ms-touch-action: auto; touch-action: auto; }

.mCustomScrollBox{ /* contains plugin's markup */
    position: relative;
    overflow: hidden;
    height: 100%;
    max-width: 100%;
    outline: none;
    direction: ltr;
}

.mCSB_container{ /* contains the original content */
    overflow: hidden;
    width: auto;
    height: auto;
}



/*
------------------------------------------------------------------------------------------------------------------------
2. VERTICAL SCROLLBAR
y-axis
------------------------------------------------------------------------------------------------------------------------
*/

.mCSB_inside > .mCSB_container{ margin-right: 5px; }

.mCSB_container.mCS_no_scrollbar_y.mCS_y_hidden{ margin-right: 0; } /* non-visible scrollbar */

.mCS-dir-rtl > .mCSB_inside > .mCSB_container{ /* RTL direction/left-side scrollbar */
    margin-right: 0;
    margin-left: 30px;
}

.mCS-dir-rtl > .mCSB_inside > .mCSB_container.mCS_no_scrollbar_y.mCS_y_hidden{ margin-left: 0; } /* RTL direction/left-side scrollbar */

.mCSB_scrollTools{ /* contains scrollbar markup (draggable element, dragger rail, buttons etc.) */
    position: absolute;
    width: 16px;
    height: auto;
    left: auto;
    top: 0;
    right: -3px;
    bottom: 0;
}

.mCSB_outside + .mCSB_scrollTools{ right: -26px; } /* scrollbar position: outside */

.mCS-dir-rtl > .mCSB_inside > .mCSB_scrollTools,
.mCS-dir-rtl > .mCSB_outside + .mCSB_scrollTools{ /* RTL direction/left-side scrollbar */
    right: auto;
    left: 0;
}

.mCS-dir-rtl > .mCSB_outside + .mCSB_scrollTools{ left: -26px; } /* RTL direction/left-side scrollbar (scrollbar position: outside) */

.mCSB_scrollTools .mCSB_draggerContainer{ /* contains the draggable element and dragger rail markup */
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    height: auto;
}

.mCSB_scrollTools a + .mCSB_draggerContainer{ margin: 20px 0; }

.mCSB_scrollTools .mCSB_draggerRail{
    width: 2px;
    height: 100%;
    margin: 0 auto;
    -webkit-border-radius: 16px; -moz-border-radius: 16px; border-radius: 16px;
}

.mCSB_scrollTools .mCSB_dragger{ /* the draggable element */
    cursor: pointer;
    width: 100%;
    height: 30px; /* minimum dragger height */
    z-index: 1;
}

.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ /* the dragger element */
    position: relative;
    width: 4px;
    height: 100%;
    margin: 0 auto;
    -webkit-border-radius: 16px; -moz-border-radius: 16px; border-radius: 16px;
    text-align: center;
}

.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar,
.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{ width: 12px; /* auto-expanded scrollbar */ }

.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail,
.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{ width: 8px; /* auto-expanded scrollbar */ }

.mCSB_scrollTools .mCSB_buttonUp,
.mCSB_scrollTools .mCSB_buttonDown{
    display: block;
    position: absolute;
    height: 20px;
    width: 100%;
    overflow: hidden;
    margin: 0 auto;
    cursor: pointer;
}

.mCSB_scrollTools .mCSB_buttonDown{ bottom: 0; }

/*
------------------------------------------------------------------------------------------------------------------------
3. HORIZONTAL SCROLLBAR
x-axis
------------------------------------------------------------------------------------------------------------------------
*/

.mCSB_horizontal.mCSB_inside > .mCSB_container{
    margin-right: 0;
    margin-bottom: 30px;
}

.mCSB_horizontal.mCSB_outside > .mCSB_container{ min-height: 100%; }

.mCSB_horizontal > .mCSB_container.mCS_no_scrollbar_x.mCS_x_hidden{ margin-bottom: 0; } /* non-visible scrollbar */

.mCSB_scrollTools.mCSB_scrollTools_horizontal{
    width: auto;
    height: 16px;
    top: auto;
    right: 0;
    bottom: 0;
    left: 0;
}

.mCustomScrollBox + .mCSB_scrollTools.mCSB_scrollTools_horizontal,
.mCustomScrollBox + .mCSB_scrollTools + .mCSB_scrollTools.mCSB_scrollTools_horizontal{ bottom: -26px; } /* scrollbar position: outside */

.mCSB_scrollTools.mCSB_scrollTools_horizontal a + .mCSB_draggerContainer{ margin: 0 20px; }

.mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_draggerRail{
    width: 100%;
    height: 2px;
    margin: 7px 0;
}

.mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_dragger{
    width: 30px; /* minimum dragger width */
    height: 100%;
    left: 0;
}

.mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_dragger .mCSB_dragger_bar{
    width: 100%;
    height: 4px;
    margin: 6px auto;
}

.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded .mCSB_dragger_bar,
.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_dragger .mCSB_dragger_bar{
    height: 12px; /* auto-expanded scrollbar */
    margin: 2px auto;
}

.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger.mCSB_dragger_onDrag_expanded + .mCSB_draggerRail,
.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerContainer:hover .mCSB_draggerRail{
    height: 8px; /* auto-expanded scrollbar */
    margin: 4px 0;
}

.mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonLeft,
.mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonRight{
    display: block;
    position: absolute;
    width: 20px;
    height: 100%;
    overflow: hidden;
    margin: 0 auto;
    cursor: pointer;
}

.mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonLeft{ left: 0; }

.mCSB_scrollTools.mCSB_scrollTools_horizontal .mCSB_buttonRight{ right: 0; }



/*
------------------------------------------------------------------------------------------------------------------------
4. VERTICAL AND HORIZONTAL SCROLLBARS
yx-axis
------------------------------------------------------------------------------------------------------------------------
*/

.mCSB_container_wrapper{
    position: absolute;
    height: auto;
    width: auto;
    overflow: hidden;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin-right: 30px;
    margin-bottom: 30px;
}

.mCSB_container_wrapper > .mCSB_container{
    padding-right: 30px;
    padding-bottom: 30px;
}

.mCSB_vertical_horizontal > .mCSB_scrollTools.mCSB_scrollTools_vertical{ bottom: 20px; }

.mCSB_vertical_horizontal > .mCSB_scrollTools.mCSB_scrollTools_horizontal{ right: 20px; }

/* non-visible horizontal scrollbar */
.mCSB_container_wrapper.mCS_no_scrollbar_x.mCS_x_hidden + .mCSB_scrollTools.mCSB_scrollTools_vertical{ bottom: 0; }

/* non-visible vertical scrollbar/RTL direction/left-side scrollbar */
.mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden + .mCSB_scrollTools ~ .mCSB_scrollTools.mCSB_scrollTools_horizontal,
.mCS-dir-rtl > .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_scrollTools.mCSB_scrollTools_horizontal{ right: 0; }

/* RTL direction/left-side scrollbar */
.mCS-dir-rtl > .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_scrollTools.mCSB_scrollTools_horizontal{ left: 20px; }

/* non-visible scrollbar/RTL direction/left-side scrollbar */
.mCS-dir-rtl > .mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden + .mCSB_scrollTools ~ .mCSB_scrollTools.mCSB_scrollTools_horizontal{ left: 0; }

.mCS-dir-rtl > .mCSB_inside > .mCSB_container_wrapper{ /* RTL direction/left-side scrollbar */
    margin-right: 0;
    margin-left: 30px;
}

.mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden > .mCSB_container{
    padding-right: 0;
    -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box;
}

.mCSB_container_wrapper.mCS_no_scrollbar_x.mCS_x_hidden > .mCSB_container{
    padding-bottom: 0;
    -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box;
}

.mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_container_wrapper.mCS_no_scrollbar_y.mCS_y_hidden{
    margin-right: 0; /* non-visible scrollbar */
    margin-left: 0;
}

/* non-visible horizontal scrollbar */
.mCustomScrollBox.mCSB_vertical_horizontal.mCSB_inside > .mCSB_container_wrapper.mCS_no_scrollbar_x.mCS_x_hidden{ margin-bottom: 0; }

/*
------------------------------------------------------------------------------------------------------------------------
5. TRANSITIONS
------------------------------------------------------------------------------------------------------------------------
*/

.mCSB_scrollTools,
.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar,
.mCSB_scrollTools .mCSB_buttonUp,
.mCSB_scrollTools .mCSB_buttonDown,
.mCSB_scrollTools .mCSB_buttonLeft,
.mCSB_scrollTools .mCSB_buttonRight{
    -webkit-transition: opacity .2s ease-in-out, background-color .2s ease-in-out;
    -moz-transition: opacity .2s ease-in-out, background-color .2s ease-in-out;
    -o-transition: opacity .2s ease-in-out, background-color .2s ease-in-out;
    transition: opacity .2s ease-in-out, background-color .2s ease-in-out;
}

.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_dragger_bar, /* auto-expanded scrollbar */
.mCSB_scrollTools_vertical.mCSB_scrollTools_onDrag_expand .mCSB_draggerRail,
.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_dragger_bar,
.mCSB_scrollTools_horizontal.mCSB_scrollTools_onDrag_expand .mCSB_draggerRail{
    -webkit-transition: width .2s ease-out .2s, height .2s ease-out .2s,
    margin-left .2s ease-out .2s, margin-right .2s ease-out .2s,
    margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s,
    opacity .2s ease-in-out, background-color .2s ease-in-out;
    -moz-transition: width .2s ease-out .2s, height .2s ease-out .2s,
    margin-left .2s ease-out .2s, margin-right .2s ease-out .2s,
    margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s,
    opacity .2s ease-in-out, background-color .2s ease-in-out;
    -o-transition: width .2s ease-out .2s, height .2s ease-out .2s,
    margin-left .2s ease-out .2s, margin-right .2s ease-out .2s,
    margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s,
    opacity .2s ease-in-out, background-color .2s ease-in-out;
    transition: width .2s ease-out .2s, height .2s ease-out .2s,
    margin-left .2s ease-out .2s, margin-right .2s ease-out .2s,
    margin-top .2s ease-out .2s, margin-bottom .2s ease-out .2s,
    opacity .2s ease-in-out, background-color .2s ease-in-out;
}

/* theme: "dark" */

.mCS-dark.mCSB_scrollTools .mCSB_draggerRail{ background-color: #000; background-color: rgba(0,0,0,0.15); }

.mCS-dark.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ background-color: #000; background-color: rgba(0,0,0,0.75); }

.mCS-dark.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ background-color: rgba(0,0,0,0.85); }

.mCS-dark.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar,
.mCS-dark.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ background-color: rgba(0,0,0,0.9); }

.mCS-dark.mCSB_scrollTools .mCSB_buttonUp{ background-position: -80px 0; }

.mCS-dark.mCSB_scrollTools .mCSB_buttonDown{ background-position: -80px -20px; }

.mCS-dark.mCSB_scrollTools .mCSB_buttonLeft{ background-position: -80px -40px; }

.mCS-dark.mCSB_scrollTools .mCSB_buttonRight{ background-position: -80px -56px; }


/* Chosen v1.1.0 | (c) 2011-2013 by Harvest | MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md */
.chosen-container{position:relative;display:inline-block;vertical-align:middle;font-size:13px;zoom:1;*display:inline;-webkit-user-select:none;-moz-user-select:none;user-select:none}.chosen-container .chosen-drop{position:absolute;top:100%;left:-9999px;z-index:1010;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:100%;border:1px solid #aaa;border-top:0;background:#fff;box-shadow:0 4px 5px rgba(0,0,0,.15)}.chosen-container.chosen-with-drop .chosen-drop{left:0}.chosen-container a{cursor:pointer}.chosen-container-single .chosen-single{position:relative;display:block;overflow:hidden;padding:0 0 0 8px;height:23px;border:1px solid #aaa;border-radius:5px;background-color:#fff;background:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#fff),color-stop(50%,#f6f6f6),color-stop(52%,#eee),color-stop(100%,#f4f4f4));background:-webkit-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background:-moz-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background:-o-linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background:linear-gradient(top,#fff 20%,#f6f6f6 50%,#eee 52%,#f4f4f4 100%);background-clip:padding-box;box-shadow:0 0 3px #fff inset,0 1px 1px rgba(0,0,0,.1);color:#444;text-decoration:none;white-space:nowrap;line-height:24px}.chosen-container-single .chosen-default{color:#999}.chosen-container-single .chosen-single span{display:block;overflow:hidden;margin-right:26px;text-overflow:ellipsis;white-space:nowrap}.chosen-container-single .chosen-single-with-deselect span{margin-right:38px}.chosen-container-single .chosen-single abbr{position:absolute;top:6px;right:26px;display:block;width:12px;height:12px;background:url(../img/chosen-sprite.png) -42px 1px no-repeat;font-size:1px}.chosen-container-single .chosen-single abbr:hover{background-position:-42px -10px}.chosen-container-single.chosen-disabled .chosen-single abbr:hover{background-position:-42px -10px}.chosen-container-single .chosen-single div{position:absolute;top:0;right:0;display:block;width:18px;height:100%}.chosen-container-single .chosen-single div b{display:block;width:100%;height:100%;background:url(../img/chosen-sprite.png) no-repeat 0 2px}.chosen-container-single .chosen-search{position:relative;z-index:1010;margin:0;padding:3px 4px;white-space:nowrap}.chosen-container-single .chosen-search input[type=text]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin:1px 0;padding:4px 20px 4px 5px;width:100%;height:auto;outline:0;border:1px solid #aaa;background:#fff url(../img/chosen-sprite.png) no-repeat 100% -20px;background:url(../img/chosen-sprite.png) no-repeat 100% -20px;font-size:1em;font-family:sans-serif;line-height:normal;border-radius:0}.chosen-container-single .chosen-drop{margin-top:-1px;border-radius:0 0 4px 4px;background-clip:padding-box}.chosen-container-single.chosen-container-single-nosearch .chosen-search{position:absolute;left:-9999px}.chosen-container .chosen-results{position:relative;overflow-x:hidden;overflow-y:auto;margin:0 4px 4px 0;padding:0 0 0 4px;max-height:240px;-webkit-overflow-scrolling:touch}.chosen-container .chosen-results li{display:none;margin:0;padding:5px 6px;list-style:none;line-height:15px;-webkit-touch-callout:none}.chosen-container .chosen-results li.active-result{display:list-item;cursor:pointer}.chosen-container .chosen-results li.disabled-result{display:list-item;color:#ccc;cursor:default}.chosen-container .chosen-results li.highlighted{background-color:#3875d7;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#3875d7),color-stop(90%,#2a62bc));background-image:-webkit-linear-gradient(#3875d7 20%,#2a62bc 90%);background-image:-moz-linear-gradient(#3875d7 20%,#2a62bc 90%);background-image:-o-linear-gradient(#3875d7 20%,#2a62bc 90%);background-image:linear-gradient(#3875d7 20%,#2a62bc 90%);color:#fff}.chosen-container .chosen-results li.no-results{display:list-item;background:#f4f4f4}.chosen-container .chosen-results li.group-result{display:list-item;font-weight:700;cursor:default}.chosen-container .chosen-results li.group-option{padding-left:15px}.chosen-container .chosen-results li em{font-style:normal;text-decoration:underline}.chosen-container-multi .chosen-choices{position:relative;overflow:hidden;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin:0;padding:0;width:100%;height:auto!important;height:1%;border:1px solid #aaa;background-color:#fff;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(1%,#eee),color-stop(15%,#fff));background-image:-webkit-linear-gradient(#eee 1%,#fff 15%);background-image:-moz-linear-gradient(#eee 1%,#fff 15%);background-image:-o-linear-gradient(#eee 1%,#fff 15%);background-image:linear-gradient(#eee 1%,#fff 15%);cursor:text}.chosen-container-multi .chosen-choices li{float:left;list-style:none}.chosen-container-multi .chosen-choices li.search-field{margin:0;padding:0;white-space:nowrap}.chosen-container-multi .chosen-choices li.search-field input[type=text]{margin:1px 0;padding:5px;height:15px;outline:0;border:0!important;background:transparent!important;box-shadow:none;color:#666;font-size:100%;font-family:sans-serif;line-height:normal;border-radius:0}.chosen-container-multi .chosen-choices li.search-field .default{color:#999}.chosen-container-multi .chosen-choices li.search-choice{position:relative;margin:3px 0 3px 5px;padding:3px 20px 3px 5px;border:1px solid #aaa;border-radius:3px;background-color:#e4e4e4;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#f4f4f4),color-stop(50%,#f0f0f0),color-stop(52%,#e8e8e8),color-stop(100%,#eee));background-image:-webkit-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-moz-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-o-linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:linear-gradient(#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-clip:padding-box;box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05);color:#333;line-height:13px;cursor:default}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close{position:absolute;top:4px;right:3px;display:block;width:12px;height:12px;background:url(../img/chosen-sprite.png) -42px 1px no-repeat;font-size:1px}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover{background-position:-42px -10px}.chosen-container-multi .chosen-choices li.search-choice-disabled{padding-right:5px;border:1px solid #ccc;background-color:#e4e4e4;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#f4f4f4),color-stop(50%,#f0f0f0),color-stop(52%,#e8e8e8),color-stop(100%,#eee));background-image:-webkit-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-moz-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:-o-linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);background-image:linear-gradient(top,#f4f4f4 20%,#f0f0f0 50%,#e8e8e8 52%,#eee 100%);color:#666}.chosen-container-multi .chosen-choices li.search-choice-focus{background:#d4d4d4}.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close{background-position:-42px -10px}.chosen-container-multi .chosen-results{margin:0;padding:0}.chosen-container-multi .chosen-drop .result-selected{display:list-item;color:#ccc;cursor:default}.chosen-container-active .chosen-single{border:1px solid #5897fb;box-shadow:0 0 5px rgba(0,0,0,.3)}.chosen-container-active.chosen-with-drop .chosen-single{border:1px solid #aaa;-moz-border-radius-bottomright:0;border-bottom-right-radius:0;-moz-border-radius-bottomleft:0;border-bottom-left-radius:0;background-image:-webkit-gradient(linear,50% 0,50% 100%,color-stop(20%,#eee),color-stop(80%,#fff));background-image:-webkit-linear-gradient(#eee 20%,#fff 80%);background-image:-moz-linear-gradient(#eee 20%,#fff 80%);background-image:-o-linear-gradient(#eee 20%,#fff 80%);background-image:linear-gradient(#eee 20%,#fff 80%);box-shadow:0 1px 0 #fff inset}.chosen-container-active.chosen-with-drop .chosen-single div{border-left:0;background:transparent}.chosen-container-active.chosen-with-drop .chosen-single div b{background-position:-18px 2px}.chosen-container-active .chosen-choices{border:1px solid #5897fb;box-shadow:0 0 5px rgba(0,0,0,.3)}.chosen-container-active .chosen-choices li.search-field input[type=text]{color:#111!important}.chosen-disabled{opacity:.5!important;cursor:default}.chosen-disabled .chosen-single{cursor:default}.chosen-disabled .chosen-choices .search-choice .search-choice-close{cursor:default}.chosen-rtl{text-align:right}.chosen-rtl .chosen-single{overflow:visible;padding:0 8px 0 0}.chosen-rtl .chosen-single span{margin-right:0;margin-left:26px;direction:rtl}.chosen-rtl .chosen-single-with-deselect span{margin-left:38px}.chosen-rtl .chosen-single div{right:auto;left:3px}.chosen-rtl .chosen-single abbr{right:auto;left:26px}.chosen-rtl .chosen-choices li{float:right}.chosen-rtl .chosen-choices li.search-field input[type=text]{direction:rtl}.chosen-rtl .chosen-choices li.search-choice{margin:3px 5px 3px 0;padding:3px 5px 3px 19px}.chosen-rtl .chosen-choices li.search-choice .search-choice-close{right:auto;left:4px}.chosen-rtl.chosen-container-single-nosearch .chosen-search,.chosen-rtl .chosen-drop{left:9999px}.chosen-rtl.chosen-container-single .chosen-results{margin:0 0 4px 4px;padding:0 4px 0 0}.chosen-rtl .chosen-results li.group-option{padding-right:15px;padding-left:0}.chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div{border-right:0}.chosen-rtl .chosen-search input[type=text]{padding:4px 5px 4px 20px;background:#fff url(../img/chosen-sprite.png) no-repeat -30px -20px;background:url(../img/chosen-sprite.png) no-repeat -30px -20px;direction:rtl}.chosen-rtl.chosen-container-single .chosen-single div b{background-position:6px 2px}.chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b{background-position:-12px 2px}@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-resolution:144dpi){.chosen-rtl .chosen-search input[type=text],.chosen-container-single .chosen-single abbr,.chosen-container-single .chosen-single div b,.chosen-container-single .chosen-search input[type=text],.chosen-container-multi .chosen-choices .search-choice .search-choice-close,.chosen-container .chosen-results-scroll-down span,.chosen-container .chosen-results-scroll-up span{background-image:url(../img/chosen-sprite@2x.png)!important;background-size:52px 37px!important;background-repeat:no-repeat!important}}


/***
    BS Color Picker
**/
.bs-color-picker-wrapper  {
    position: relative;
}
.bs-color-picker-wrapper > .bs-color-picker-value{
    display: none !important;
}
.bs-color-picker-wrapper.bs-clicked .bs-wp-picker-container{
    display: none;
}
.bs-color-picker-wrapper .wp-picker-input-wrap label{
    display: block;
}
.bs-color-picker-wrapper .wp-picker-open+.wp-picker-input-wrap{
    display: block;
    padding: 10px;
    border: 1px solid #ddd;
    background: #fff;
    width: 257px;
    box-sizing: border-box;
    margin-bottom: -7px;
    position: relative;
}
.bs-color-picker-wrapper .wp-picker-input-wrap .wp-picker-clear{
    position: absolute;
    right: 10px;
    top: 10px;
    z-index: 1;
    height: 30px;
    border: 1px solid #d9d9d9;
    box-shadow: none;
    text-transform: uppercase;
    padding: 0 13px;
    border-radius: 0;
    transform: none !important;
}
.bs-color-picker-wrapper .wp-picker-input-wrap .bs-color-picker-value{
    width: 100% !important;
    height: 30px !important;
}
.bs-color-picker-wrapper .wp-picker-container .iris-picker{
    border-top: 1px dashed #e8e8e8
}
.bs-color-picker-wrapper .wp-picker-container .wp-color-result{
    height: 30px !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    padding: 0 0 0 50px !important;
    border-color: #ccc !important;
    margin: 0;
    box-sizing: border-box;
}
.bs-color-picker-wrapper .wp-picker-container .wp-color-result.wp-color-result:after, /* WP < 4.9 compatibility */
.bs-color-picker-wrapper .wp-picker-container .wp-color-result-text{
    height: 28px !important;
    line-height: 28px !important;
    background: #fff !important;
    display: inline-block !important;
    padding: 0 8px !important;
    border-left: 1px solid #ccc !important;
    font-size: 12px !important;
}
.bs-color-picker-wrapper .wp-picker-container.bs-wp-picker-container .wp-color-result.wp-color-result:after{
    display: none !important;
}
.bs-color-picker-wrapper .wp-picker-container .wp-color-result .color-alpha{
    width: 50px !important;
    height: 28px !important;
    border-radius: 0 !important;
    background: transparent;
}


/***
    RTL FIX
**/
.rtl .bs-color-picker-wrapper .wp-color-result {
    padding: 0 45px 0 0;
}
.rtl .bs-color-picker-wrapper .button.wp-picker-clear {
    padding: 6px 3px 12px !important;
    margin: 0 7px 0 0;
    float: left;
}
.rtl .bs-color-picker-wrapper  .wp-picker-clear {
    margin: 5px 10px 5px 0;
}
.rtl .chosen-container .chosen-drop {
    right:-9999px;
    left: auto;
}
.rtl .chosen-container.chosen-with-drop .chosen-drop {
    right:0;
    left: auto;
}
.rtl .chosen-container-single .chosen-single {
    padding:0 8px 0 0;
}
.rtl .chosen-container-single .chosen-single span {
    margin-left:26px;
    margin-right: auto;
    margin-top: 3px;
}
.rtl .chosen-container-single .chosen-single-with-deselect span {
    margin-left:38px;
    margin-right: auto;
}
.rtl .chosen-container-single .chosen-single abbr {
    left:26px;
    right: auto;
}
.rtl .chosen-container-single .chosen-single div {
    left:0;
    right: auto;
}
.rtl .chosen-container-single .chosen-search input[type=text] {
    padding:4px 5px 4px 20px;
}
.rtl .chosen-container-single.chosen-container-single-nosearch .chosen-search {
    right:-9999px;
    left: auto;
}
.rtl .chosen-container .chosen-results {
    margin:0 0 4px 4px;
    padding:0 4px 0 0;
}
.rtl .chosen-container .chosen-results li.group-option {
    padding-right:15px;
    padding-left: 0;
}
.rtl .chosen-container-multi .chosen-choices li {
    float:right;
}
.rtl .chosen-container-multi .chosen-choices li.search-choice {
    margin:3px 5px 3px 0;
    padding:3px 5px 3px 20px;
}
.rtl .chosen-container-multi .chosen-choices li.search-choice .search-choice-close {
    left:3px;
    right: auto;
}
.rtl .chosen-container-multi .chosen-choices li.search-choice-disabled {
    padding-left:5px;
    padding-right: 0;
}
.rtl .chosen-container-active.chosen-with-drop .chosen-single {
    -moz-border-radius-bottomleft:0;
    border-bottom-left-radius:0;
    -moz-border-radius-bottomright:0;
    border-bottom-right-radius:0;
}
.rtl .chosen-container-active.chosen-with-drop .chosen-single div {
    border-right:0;
    border-left: none;
}libs/better-framework/assets/css/pretty-photo.css000064400000024632151214002570016243 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */


/* ----------------------------------
    Default Theme
----------------------------------- */

div.pp_default .pp_top,
div.pp_default .pp_top .pp_middle,
div.pp_default .pp_top .pp_left,
div.pp_default .pp_top .pp_right,
div.pp_default .pp_bottom,
div.pp_default .pp_bottom .pp_left,
div.pp_default .pp_bottom .pp_middle,
div.pp_default .pp_bottom .pp_right { height: 13px; }

div.pp_default .pp_top .pp_left {  } /* Top left corner */
div.pp_default .pp_top .pp_middle {  } /* Top pattern/color */
div.pp_default .pp_top .pp_right {  } /* Top right corner */

div.pp_default .pp_content .ppt { color: #f8f8f8; }
div.pp_default .pp_content_container { background-color: #fff; padding: 16px 10px 10px 10px; }
div.pp_default .pp_content_container .pp_left { padding-left: 13px; }
div.pp_default .pp_content_container .pp_right { padding-right: 13px; }
div.pp_default .pp_content { background-color: #fff; margin: auto; }
div.pp_default .pp_next:hover { cursor: pointer; }

div.pp_default .pp_previous .fa,
div.pp_default .pp_next .fa{
    width: 34px;
    height: 34px;
    background-color: #fff;
    color: #5F5F5F;
    position: absolute;
    top: 50%;
    margin-top: -12px;
    right: 0;
    opacity: 0;
    -webkit-transition: all .3s ease;
    -moz-transition: all .3s ease;
    -o-transition: all .3s ease;
    transition: all .3s ease;
    text-align: center;
    line-height: 34px;
    -ms-transform: scale(.93,.93);
    -webkit-transform: scale(.93,.93);
    transform: scale(.93,.93);
}
div.pp_default .pp_next:hover .fa{
    right: 15px;
    opacity: 1;
    -ms-transform: scale(1,1);
    -webkit-transform: scale(1,1);
    transform: scale(1,1);
}
div.pp_default .pp_previous .fa{
    right: initial;
    left: 0;

}
div.pp_default .pp_previous:hover .fa{
    left: 15px;
    opacity: 1;
    -ms-transform: scale(1,1);
    -webkit-transform: scale(1,1);
    transform: scale(1,1);
}
div.pp_default .pp_previous:hover { cursor: pointer; } /* Previous button */

div.pp_default .pp_close,
div.pp_default .pp_contract,
div.pp_default .pp_expand{
    display: inline-block;
    font-family: FontAwesome;
    font-style: normal;
    font-weight: normal;
    line-height: 1;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

div.pp_default .pp_close,
div.pp_default .pp_contract ,
div.pp_default .pp_expand {
    cursor: pointer;
    width: 30px;
    height: 30px;
    background-color: #fff;
    line-height: 27px;
    text-align: center;
    color: #5F5F5F;
    text-decoration: none;
    opacity: .9;
    border: 2px solid #5F5F5F;
}
div.pp_default .pp_expand:before{
    content: "\f065";
}
div.pp_default .pp_contract:before{
    content: "\f066";
}

div.pp_default .pp_contract:hover ,
div.pp_default .pp_expand:hover {
    opacity: 1;
}

div.pp_default a.pp_arrow_previous,
div.pp_default a.pp_arrow_next,
div.pp_default .pp_nav .pp_play,
div.pp_default .pp_nav .pp_pause{
    background-color: #E4E4E4;
    color: #5F5F5F;
    width: 28px;
    height: 28px;
    text-align: center;
    line-height: 28px;
    text-decoration: none;
}
div.pp_default .pp_close:before{
    content: "\f00d";
}
div.pp_default .pp_close:hover{
    color: #e42a30;
}
div.pp_default .pp_nav .pp_pause,
div.pp_default .pp_nav .pp_play{
    width: 34px;
    height: 34px;
    line-height: 34px;
    font-size: 18px;
}
div.pp_default .pp_nav .pp_pause .fa-play:before{
    content: "\f04c";
}
div.pp_default a.pp_arrow_previous,
div.pp_default a.pp_arrow_next{
    padding-left: 0;
    margin-top: 6px !important;
    margin-right: 4px;
}
div.pp_default .pp_gallery a.pp_arrow_previous{
    margin-right: 10px;
    margin-top: 3px !important;
}
div.pp_default .pp_gallery a.pp_arrow_next{
    margin-left: 10px;
    margin-top: 3px !important;
}

div.pp_default #pp_full_res .pp_inline { color: #000; }
div.pp_default .pp_gallery ul li a {
    border: 2px solid #E4E4E4;
}
div.pp_default .pp_gallery ul li a:hover,
div.pp_default .pp_gallery ul li.selected a {
    border-color: #999;
}
div.pp_default .pp_social { margin-top: 7px; }

div.pp_default .pp_gallery a.pp_arrow_previous,
div.pp_default .pp_gallery a.pp_arrow_next { position: static; left: auto; }

div.pp_default .pp_details { position: relative; }
div.pp_default a.pp_arrow_previous,

div.pp_default .pp_content_container .pp_details { margin-top: 3px; }
div.pp_default .pp_content_container .pp_gallery ~ .pp_details { margin-top: 55px; }
div.pp_default .pp_nav { clear: none; height: 30px; width: 110px; position: relative; }
div.pp_default .pp_nav .currentTextHolder{
    font-family: Georgia;
    font-style: italic;
    color: #999;
    font-size: 12px;
    left: 105px;
    line-height: 25px;
    margin: 0;
    padding: 0 0 0 10px;
    position: absolute;
    top: 6px;
}

div.pp_default .pp_close:hover, div.pp_default .pp_nav .pp_play:hover, div.pp_default .pp_nav .pp_pause:hover, div.pp_default .pp_arrow_next:hover, div.pp_default .pp_arrow_previous:hover { opacity:0.7; }

div.pp_default .pp_description {
    font-size: 12px;
    line-height: 14px;
    margin: 16px 10px 5px 180px;
}
div.pp_default .pp_loaderIcon { background: url(../img/pretty-photo-loader.gif) center center no-repeat; } /* Loader icon */


/* ------------------------------------------------------------------------
	DO NOT CHANGE
------------------------------------------------------------------------- */

div.pp_pic_holder a:focus { outline:none; }

div.pp_overlay {
    background: #000;
    display: none;
    left: 0;
    position: absolute;
    top: 0;
    width: 100%;
    z-index: 99999;
}

div.pp_pic_holder {
    display: none;
    position: absolute;
    width: 100px;
    z-index: 999999;
    -webkit-box-shadow: 0 0 0 6px rgba(0, 0, 0, 0.2);
    -moz-box-shadow: 0 0 0 6px rgba(0, 0, 0, 0.2);
    -ms-box-shadow: 0 0 0 6px rgba(0, 0, 0, 0.2);
    box-shadow: 0 0 0 6px rgba(0, 0, 0, 0.2);
}


.pp_top {
    height: 20px;
    position: relative;
}
* html .pp_top { padding: 0 20px; }

.pp_top .pp_left {
    height: 20px;
    left: 0;
    position: absolute;
    width: 20px;
}
.pp_top .pp_middle {
    height: 20px;
    left: 20px;
    position: absolute;
    right: 20px;
}
* html .pp_top .pp_middle {
    left: 0;
    position: static;
}

.pp_top .pp_right {
    height: 20px;
    left: auto;
    position: absolute;
    right: 0;
    top: 0;
    width: 20px;
}

.pp_content { height: 40px; min-width: 40px; }
* html .pp_content { width: 40px; }

.pp_fade { display: none; }

.pp_content_container {
    position: relative;
    text-align: left;
    width: 100%;
}

.pp_content_container .pp_left { padding-left: 20px; }
.pp_content_container .pp_right { padding-right: 20px; }

.pp_content_container .pp_details {
    float: left;
    margin: 10px 0 2px 0;
}
.pp_description {
    display: none;
    margin: 0;
}

.pp_social { float: left; margin: 0; }
.pp_social .facebook { float: left; margin-left: 5px; width: 55px; overflow: hidden; }
.pp_social .twitter { float: left; }

.pp_nav {
    clear: right;
    float: left;
    margin: 3px 10px 0 0;
}

.pp_nav p {
    float: left;
    margin: 2px 4px;
    white-space: nowrap;
}

.pp_nav .pp_play,
.pp_nav .pp_pause {
    float: left;
    margin-right: 4px;
}

a.pp_arrow_previous,
a.pp_arrow_next {
    display: block;
    float: left;
    height: 15px;
    margin-top: 3px;
    overflow: hidden;
    width: 14px;
}

.pp_hoverContainer {
    position: absolute;
    top: 0;
    width: 100%;
    z-index: 2000;
}

.pp_gallery {
    display: block !important;
    opacity: 1 !important;
    position: absolute;
    left: 50%;
    padding-top: 15px;
}

.pp_gallery div {
    float: left;
    overflow: hidden;
    position: relative;
}

.pp_gallery ul {
    float: left;
    height: 35px;
    margin: 0 0 0 5px;
    padding: 0;
    position: relative;
    white-space: nowrap;
}

.pp_gallery ul a {
    border: 1px #000 solid;
    border: 1px rgba(0,0,0,0.5) solid;
    display: block;
    float: left;
    height: 33px;
    overflow: hidden;
}

.pp_gallery ul a:hover,
.pp_gallery li.selected a { border-color: #fff; }

.pp_gallery ul a img { border: 0; }

.pp_gallery li {
    display: block;
    float: left;
    margin: 0 3px 0 0;
    padding: 0;
}

.pp_gallery li.default a {
    display: block;
    height: 33px;
    width: 50px;
}

.pp_gallery li.default a img { display: none; }

.pp_gallery .pp_arrow_previous,
.pp_gallery .pp_arrow_next {
    margin-top: 7px !important;
}

a.pp_next {
    display: block;
    float: right;
    height: 100%;
    width: 49%;
}

a.pp_previous {
    display: block;
    float: left;
    height: 100%;
    width: 49%;
}

/*div.pp_default .pp_close,*/
a.pp_expand,
a.pp_contract {
    cursor: pointer;
    display: none;
    height: 20px;
    position: absolute;
    right: 60px;
    top: 25px;
    width: 20px;
    z-index: 20000;
}

a.pp_close {
    display: block;
    position: absolute;
    right: 25px;
    top: 25px;
    z-index: 4000;
}

.pp_bottom {
    height: 20px;
    position: relative;
}
* html .pp_bottom { padding: 0 20px; }

.pp_bottom .pp_left {
    height: 20px;
    left: 0;
    position: absolute;
    width: 20px;
}
.pp_bottom .pp_middle {
    height: 20px;
    left: 20px;
    position: absolute;
    right: 20px;
}
* html .pp_bottom .pp_middle {
    left: 0;
    position: static;
}

.pp_bottom .pp_right {
    height: 20px;
    left: auto;
    position: absolute;
    right: 0;
    top: 0;
    width: 20px;
}

.pp_loaderIcon {
    display: block;
    height: 24px;
    left: 50%;
    margin: -12px 0 0 -12px;
    position: absolute;
    top: 50%;
    width: 24px;
}

#pp_full_res {
    line-height: 1 !important;
}

#pp_full_res .pp_inline {
    text-align: left;
}

#pp_full_res .pp_inline p { margin: 0 0 15px 0; }

div.ppt {
    background-color: #fff;
    display: none !important;
    font-size: 17px;
    margin: 0;
    z-index: 9999;
    padding: 10px 10px 0px 15px;
    width: 100% !important;
}libs/better-framework/assets/css/font-awesome.min.css000064400000074701151214002570016755 0ustar00/*!
 *  Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
 *  License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
 */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}

/** i is for important - used for locations that font name should be defined in high priority **/
.fai {
    font: normal normal normal 14px/1 FontAwesome !important;
}libs/better-framework/assets/css/codemirror-pack.css000064400000016177151214002600016645 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */


/* BASICS */

.CodeMirror {
  /* Set height, width, borders, and global font properties here */
  font-family: monospace;
  height: 300px;
}
.CodeMirror-scroll {
  /* Set scrolling behaviour here */
  overflow: auto;
}

/* PADDING */

.CodeMirror-lines {
  padding: 4px 0; /* Vertical padding around content */
}
.CodeMirror pre {
  padding: 0 4px; /* Horizontal padding of content */
}

.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
  background-color: white; /* The little square between H and V scrollbars */
}

/* GUTTER */

.CodeMirror-gutters {
  border-right: 1px solid #ddd;
  background-color: #f7f7f7;
  white-space: nowrap;
}
.CodeMirror-linenumbers {}
.CodeMirror-linenumber {
  padding: 0 3px 0 5px;
  min-width: 20px;
  text-align: right;
  color: #999;
}

/* CURSOR */

.CodeMirror div.CodeMirror-cursor {
  border-left: 1px solid black;
  z-index: 3;
}
/* Shown when moving in bi-directional text */
.CodeMirror div.CodeMirror-secondarycursor {
  border-left: 1px solid silver;
}
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
  width: auto;
  border: 0;
  background: #7e7;
  z-index: 1;
}
/* Can style cursor different in overwrite (non-insert) mode */
.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {}

.cm-tab { display: inline-block; }

/* DEFAULT THEME */

.cm-s-default .cm-keyword {color: #708;}
.cm-s-default .cm-atom {color: #219;}
.cm-s-default .cm-number {color: #164;}
.cm-s-default .cm-def {color: #00f;}
.cm-s-default .cm-variable {color: black;}
.cm-s-default .cm-variable-2 {color: #05a;}
.cm-s-default .cm-variable-3 {color: #085;}
.cm-s-default .cm-property {color: black;}
.cm-s-default .cm-operator {color: black;}
.cm-s-default .cm-comment {color: #a50;}
.cm-s-default .cm-string {color: #a11;}
.cm-s-default .cm-string-2 {color: #f50;}
.cm-s-default .cm-meta {color: #555;}
.cm-s-default .cm-error {color: #f00;}
.cm-s-default .cm-qualifier {color: #555;}
.cm-s-default .cm-builtin {color: #30a;}
.cm-s-default .cm-bracket {color: #997;}
.cm-s-default .cm-tag {color: #170;}
.cm-s-default .cm-attribute {color: #00c;}
.cm-s-default .cm-header {color: blue;}
.cm-s-default .cm-quote {color: #090;}
.cm-s-default .cm-hr {color: #999;}
.cm-s-default .cm-link {color: #00c;}

.cm-negative {color: #d44;}
.cm-positive {color: #292;}
.cm-header, .cm-strong {font-weight: bold;}
.cm-em {font-style: italic;}
.cm-link {text-decoration: underline;}

.cm-invalidchar {color: #f00;}

div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}

/* STOP */

/* The rest of this file contains styles related to the mechanics of
   the editor. You probably shouldn't touch them. */

.CodeMirror {
  line-height: 1;
  position: relative;
  overflow: hidden;
  background: white;
  color: black;
  border: 1px solid rgb(230, 230, 230)
}

.CodeMirror-scroll {
  /* 30px is the magic margin used to hide the element's real scrollbars */
  /* See overflow: hidden in .CodeMirror */
  margin-bottom: -30px; margin-right: -30px;
  padding-bottom: 30px; padding-right: 30px;
  height: 100%;
  outline: none; /* Prevent dragging from highlighting the element */
  position: relative;
}
.CodeMirror-sizer {
  position: relative;
}

/* The fake, visible scrollbars. Used to force redraw during scrolling
   before actuall scrolling happens, thus preventing shaking and
   flickering artifacts. */
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
  position: absolute;
  z-index: 6;
  display: none;
}
.CodeMirror-vscrollbar {
  right: 0; top: 0;
  overflow-x: hidden;
  overflow-y: scroll;
}
.CodeMirror-hscrollbar {
  bottom: 0; left: 0;
  overflow-y: hidden;
  overflow-x: scroll;
}
.CodeMirror-scrollbar-filler {
  right: 0; bottom: 0;
}
.CodeMirror-gutter-filler {
  left: 0; bottom: 0;
}

.CodeMirror-gutters {
  position: absolute; left: 0; top: 0;
  padding-bottom: 30px;
  z-index: 3;
}
.CodeMirror-gutter {
  white-space: normal;
  height: 100%;
  padding-bottom: 30px;
  margin-bottom: -32px;
  display: inline-block;
  /* Hack to make IE7 behave */
  *zoom:1;
  *display:inline;
}
.CodeMirror-gutter-elt {
  position: absolute;
  cursor: default;
  z-index: 4;
}

.CodeMirror-lines {
  cursor: text;
  line-height: 22px;
}
.CodeMirror pre {
  /* Reset some styles that the rest of the page might have set */
  -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
  border-width: 0;
  background: transparent;
  font-family: inherit;
  font-size: inherit;
  margin: 0;
  white-space: pre;
  word-wrap: normal;
  line-height: inherit;
  color: inherit;
  z-index: 2;
  position: relative;
  overflow: visible;
}
.CodeMirror-wrap pre {
  word-wrap: break-word;
  white-space: pre-wrap;
  word-break: normal;
}
.CodeMirror-linebackground {
  position: absolute;
  left: 0; right: 0; top: 0; bottom: 0;
  z-index: 0;
}

.CodeMirror-linewidget {
  position: relative;
  z-index: 2;
  overflow: auto;
}

.CodeMirror-widget {
  display: inline-block;
}

.CodeMirror-wrap .CodeMirror-scroll {
  overflow-x: hidden;
}

.CodeMirror-measure {
  position: absolute;
  width: 100%; height: 0px;
  overflow: hidden;
  visibility: hidden;
}
.CodeMirror-measure pre { position: static; }

.CodeMirror div.CodeMirror-cursor {
  position: absolute;
  visibility: hidden;
  border-right: none;
  width: 0;
}
.CodeMirror-focused div.CodeMirror-cursor {
  visibility: visible;
}

.CodeMirror-selected { background: #d9d9d9; }
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }

.cm-searching {
  background: #ffa;
  background: rgba(255, 255, 0, .4);
}

/* IE7 hack to prevent it from returning funny offsetTops on the spans */
.CodeMirror span { *vertical-align: text-bottom; }

@media print {
  /* Hide the cursor when printing */
  .CodeMirror div.CodeMirror-cursor {
    visibility: hidden;
  }
}




.CodeMirror-hints {
  position: absolute;
  z-index: 10;
  overflow: hidden;
  list-style: none;

  margin: 0;
  padding: 2px;

  -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
  -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
  box-shadow: 2px 3px 5px rgba(0,0,0,.2);
  border-radius: 3px;
  border: 1px solid silver;

  background: white;
  font-size: 90%;
  font-family: monospace;

  max-height: 20em;
  overflow-y: auto;
}

.CodeMirror-hint {
  margin: 0;
  padding: 0 4px;
  border-radius: 2px;
  max-width: 19em;
  overflow: hidden;
  white-space: pre;
  color: black;
  cursor: pointer;
}

.CodeMirror-hint-active {
  background: #08f;
  color: white;
}
libs/better-framework/assets/css/better-studio-admin-icon.css000064400000011341151214002600020356 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */


/*

    Better Studio Admin Icon
    v1.1

*/

@font-face {
    font-family: "Better Studio Admin Icons";
    src:url("../fonts/better-studio-admin-icons.eot");
    src:url("../fonts/better-studio-admin-icons.eot?#iefix") format("embedded-opentype"),
    url("../fonts/better-studio-admin-icons.woff") format("woff"),
    url("../fonts/better-studio-admin-icons.ttf") format("truetype"),
    url("../fonts/better-studio-admin-icons.svg#better-studio-admin-icons") format("svg");
    font-weight: normal;
    font-style: normal;

}

[data-icon]:before {
    font-family: "better-studio-admin-icons" !important;
    content: attr(data-icon);
    font-style: normal !important;
    font-weight: normal !important;
    font-variant: normal !important;
    text-transform: none !important;
    speak: none;
    line-height: 1;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

[class^="bsai-"]:before,
[class*=" bsai-"]:before {
    font-family: "Better Studio Admin Icons" !important;
    font-style: normal !important;
    font-weight: normal !important;
    font-variant: normal !important;
    text-transform: none !important;
    speak: none;
    line-height: 1;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    vertical-align: middle;
}


.bsai-betterstudio:before {
    content: "\e000";
}
.bsai-header:before {
    content: "\e001";
}
.bsai-footer:before {
    content: "\e002";
}
.bsai-sidebar:before {
    content: "\e003";
}
.bsai-page-text:before {
    content: "\e004";
}
.bsai-link:before {
    content: "\e005";
}
.bsai-archive:before {
    content: "\e006";
}
.bsai-arrow-bottom:before {
    content: "\e007";
}
.bsai-arrow-top:before {
    content: "\e008";
}
.bsai-export:before {
    content: "\e009";
}
.bsai-download:before {
    content: "\e00a";
}
.bsai-image:before {
    content: "\e00b";
}
.bsai-slider:before {
    content: "\e00c";
}
.bsai-slider-new:before {
    content: "\e00d";
}
.bsai-paint:before {
    content: "\e00e";
}
.bsai-paint1:before {
    content: "\e00f";
}
.bsai-paint2:before {
    content: "\e010";
}
.bsai-images:before {
    content: "\e011";
}
.bsai-share-alt:before {
    content: "\e012";
}
.bsai-share:before {
    content: "\e013";
}
.bsai-typography:before {
    content: "\e014";
}
.bsai-global:before {
    content: "\e015";
}
.bsai-gears:before {
    content: "\e016";
}
.bsai-css3:before {
    content: "\e017";
}
.bsai-js:before {
    content: "\e018";
}
.bsai-analytics:before {
    content: "\e019";
}
.bsai-refresh:before {
    content: "\e01a";
}
.bsai-goal:before {
    content: "\e01b";
}
.bsai-save:before {
    content: "\e01c";
}
.bsai-add:before {
    content: "\e01d";
}
.bsai-delete:before {
    content: "\e01e";
}
.bsai-save-clean:before {
    content: "\e01f";
}
.bsai-reset:before {
    content: "\e020";
}
.bsai-reset-clean:before {
    content: "\e021";
}
.bsai-verdict:before {
    content: "\e022";
}
.bsai-404:before {
    content: "\e023";
}
.bsai-list-bullet:before {
    content: "\e024";
}
.bsai-analytics1:before {
    content: "\e025";
}
.bsai-title:before {
    content: "\e026";
}
.bsai-advertise:before {
    content: "\e027";
}
.bsai-comment:before {
    content: "\e028";
}
.bsai-pin:before {
    content: "\e029";
}
.bsai-sitemap:before {
    content: "\e02a";
}
.bsai-woo:before {
    content: "\e02b";
}
.bsai-key:before {
    content: "\e02c";
}
.bsai-bbpress:before {
    content: "\e02d";
}
.bsai-translation:before {
    content: "\e02e";
}
.bsai-database:before {
    content: "\e02f";
}
.bsai-font:before {
    content: "\e030";
}
.bsai-export-import:before {
    content: "\e031";
}
.bsai-advertise2:before {
    content: "\e033";
}
.bsai-gear:before {
    content: "\e032";
}
.bsai-publisher:before {
    content: "\e034";
}
.bsai-typekit:before {
    content: "\e035";
}
.bsai-check:before {
    content: "\e036";
}
.bsai-skyscraper:before {
    content: "\e037";
}
.bsai-checked-grid:before {
    content: "\e038";
}
.bsai-newsletter-pack:before {
    content: "\e039";
}
.bsai-inject:before {
    content: "\e03a";
}
libs/better-framework/assets/css/bs-modal.css000064400000045734151214002600015263 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */


/**
        =>Animations
            -> Animation keyFrames
            -> Animation Classes
            -> load-awesome Loading
            -> Main Loading

        =>BS-Modal Styles
*/


/**
 * =>Animations
 **/
@-webkit-keyframes line-scale-pulse-out-rapid {
    0% {
        -webkit-transform: scaley(1);
        transform: scaley(1);
    }
    80% {
        -webkit-transform: scaley(.3);
        transform: scaley(.3);
    }
    90% {
        -webkit-transform: scaley(1);
        transform: scaley(1);
    }
}
@-moz-keyframes line-scale-pulse-out-rapid {
    0% {
        -moz-transform: scaley(1);
        transform: scaley(1);
    }
    80% {
        -moz-transform: scaley(.3);
        transform: scaley(.3);
    }
    90% {
        -moz-transform: scaley(1);
        transform: scaley(1);
    }
}
@-o-keyframes line-scale-pulse-out-rapid {
    0% {
        -o-transform: scaley(1);
        transform: scaley(1);
    }
    80% {
        -o-transform: scaley(.3);
        transform: scaley(.3);
    }
    90% {
        -o-transform: scaley(1);
        transform: scaley(1);
    }
}
@keyframes line-scale-pulse-out-rapid {
    0% {
        -webkit-transform: scaley(1);
        -moz-transform: scaley(1);
        -o-transform: scaley(1);
        transform: scaley(1);
    }
    80% {
        -webkit-transform: scaley(.3);
        -moz-transform: scaley(.3);
        -o-transform: scaley(.3);
        transform: scaley(.3);
    }
    90% {
        -webkit-transform: scaley(1);
        -moz-transform: scaley(1);
        -o-transform: scaley(1);
        transform: scaley(1);
    }
}
@-webkit-keyframes bs-fadeInLeft {
    from {
        opacity: 0;
        -webkit-transform: translate3d(-10%, 0, 0);
        transform: translate3d(-10%, 0, 0);
    }

    to {
        opacity: 1;
        -webkit-transform: none;
        transform: none;
    }
}
@keyframes bs-fadeInLeft {
    from {
        opacity: 0;
        -webkit-transform: translate3d(-10%, 0, 0);
        transform: translate3d(-10%, 0, 0);
    }

    to {
        opacity: 1;
        -webkit-transform: none;
        transform: none;
    }
}
@-webkit-keyframes bs-fadeInRight {
    from {
        opacity: 0;
        -webkit-transform: translate3d(10%, 0, 0);
        transform: translate3d(10%, 0, 0);
    }

    to {
        opacity: 1;
        -webkit-transform: none;
        transform: none;
    }
}
@keyframes bs-fadeInRight {
    from {
        opacity: 0;
        -webkit-transform: translate3d(10%, 0, 0);
        transform: translate3d(10%, 0, 0);
    }

    to {
        opacity: 1;
        -webkit-transform: none;
        transform: none;
    }
}
@-webkit-keyframes bs-fadeInDown {
    from {
        opacity: 0;
        -webkit-transform: translate3d(0, -10%, 0);
        transform: translate3d(0, -10%, 0);
    }

    to {
        opacity: 1;
        -webkit-transform: none;
        transform: none;
    }
}
@-webkit-keyframes bs-fadeOutUp {
  from {
    opacity: 1;
  }

  to {
    opacity: 0;
    -webkit-transform: translate3d(0, -10%, 0);
    transform: translate3d(0, -10%, 0);
  }
}

@keyframes bs-fadeOutUp {
  from {
    opacity: 1;
  }

  to {
    opacity: 0;
    -webkit-transform: translate3d(0, -10%, 0);
    transform: translate3d(0, -10%, 0);
  }
}

@keyframes bs-fadeInDown {
    from {
        opacity: 0;
        -webkit-transform: translate3d(0, -10%, 0);
        transform: translate3d(0, -10%, 0);
    }

    to {
        opacity: 1;
        -webkit-transform: none;
        transform: none;
    }
}
@-webkit-keyframes bs-fadeInUp {
    from {
        opacity: 0;
        -webkit-transform: translate3d(0, 10%, 0);
        transform: translate3d(0, 10%, 0);
    }

    to {
        opacity: 1;
        -webkit-transform: none;
        transform: none;
    }
}
@keyframes bs-fadeInUp {
    from {
        opacity: 0;
        -webkit-transform: translate3d(0, 10%, 0);
        transform: translate3d(0, 10%, 0);
    }

    to {
        opacity: 1;
        -webkit-transform: none;
        transform: none;
    }
}

.bs-animate {
    -webkit-animation-duration: 0.6s;
    animation-duration: 0.6s;
    -webkit-animation-fill-mode: both;
    animation-fill-mode: both;
}
.bs-fadeInLeft {
    -webkit-animation-name: bs-fadeInLeft;
    animation-name: bs-fadeInLeft;
}
.bs-fadeInRight {
    -webkit-animation-name: bs-fadeInRight;
    animation-name: bs-fadeInRight;
}
.bs-fadeInDown {
    -webkit-animation-name: bs-fadeInDown;
    animation-name: bs-fadeInDown;
}
.bs-fadeInUp {
    -webkit-animation-name: bs-fadeInUp;
    animation-name: bs-fadeInUp;
}
.bs-fadeOutUp {
  -webkit-animation-name: bs-fadeOutUp;
  animation-name: bs-fadeOutUp;
}


.la-line-scale-pulse-out-rapid,
.la-line-scale-pulse-out-rapid > div {
    position: relative;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}

.la-line-scale-pulse-out-rapid {
    display: block;
    font-size: 0;
    color: #00a0d2;
    margin: 10px auto;
    text-align: center;
}

.la-line-scale-pulse-out-rapid.la-dark {
    color: #333;
}

.la-line-scale-pulse-out-rapid > div {
    display: inline-block;
    float: none;
    background-color: currentColor;
    border: 0 solid currentColor;
}

.la-line-scale-pulse-out-rapid {
    width: 40px;
    height: 32px;
}

.la-line-scale-pulse-out-rapid > div {
    width: 4px;
    height: 32px;
    margin: 2px;
    margin-top: 0;
    margin-bottom: 0;
    border-radius: 0;
    -webkit-animation: line-scale-pulse-out-rapid .9s infinite cubic-bezier(.11, .49, .38, .78);
    -moz-animation: line-scale-pulse-out-rapid .9s infinite cubic-bezier(.11, .49, .38, .78);
    -o-animation: line-scale-pulse-out-rapid .9s infinite cubic-bezier(.11, .49, .38, .78);
    animation: line-scale-pulse-out-rapid .9s infinite cubic-bezier(.11, .49, .38, .78);
}

.la-line-scale-pulse-out-rapid > div:nth-child(3) {
    -webkit-animation-delay: -.9s;
    -moz-animation-delay: -.9s;
    -o-animation-delay: -.9s;
    animation-delay: -.9s;
}

.la-line-scale-pulse-out-rapid > div:nth-child(2),
.la-line-scale-pulse-out-rapid > div:nth-child(4) {
    -webkit-animation-delay: -.65s;
    -moz-animation-delay: -.65s;
    -o-animation-delay: -.65s;
    animation-delay: -.65s;
}

.la-line-scale-pulse-out-rapid > div:nth-child(1),
.la-line-scale-pulse-out-rapid > div:nth-child(5) {
    -webkit-animation-delay: -.4s;
    -moz-animation-delay: -.4s;
    -o-animation-delay: -.4s;
    animation-delay: -.4s;
}

.la-line-scale-pulse-out-rapid.la-sm {
    width: 20px;
    height: 16px;
}

.la-line-scale-pulse-out-rapid.la-sm > div {
    width: 2px;
    height: 16px;
    margin: 1px;
    margin-top: 0;
    margin-bottom: 0;
}

.la-line-scale-pulse-out-rapid.la-2x {
    width: 80px;
    height: 64px;
}

.la-line-scale-pulse-out-rapid.la-2x > div {
    width: 8px;
    height: 64px;
    margin: 4px;
    margin-top: 0;
    margin-bottom: 0;
}

.la-line-scale-pulse-out-rapid.la-3x {
    width: 120px;
    height: 96px;
}

.la-line-scale-pulse-out-rapid.la-3x > div {
    width: 12px;
    height: 96px;
    margin: 0 6px;
}

/**
 * -> Main Loading
 **/

.bs-loading,
.bs-loading > div {
    position: relative;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}
.bs-loading {
    display: block;
    font-size: 0;
    color: #333;
    margin: 0 auto;
    line-height: 4px;
}
.bs-loading > div {
    display: inline-block;
    float: none;
    background-color: #00a0d2;
}
.bs-loading {
    width: 54px;
    height: 54px;
}
.bs-loading > div {
    width: 10px;
    height: 10px;
    margin: 4px;
    border-radius: 100%;
    -webkit-animation-name: bs-loading-keyframe;
    -moz-animation-name: bs-loading-keyframe;
    -o-animation-name: bs-loading-keyframe;
    animation-name: bs-loading-keyframe;
    -webkit-animation-iteration-count: infinite;
    -moz-animation-iteration-count: infinite;
    -o-animation-iteration-count: infinite;
    animation-iteration-count: infinite;
}
.bs-loading > div:nth-child(1) {
    -webkit-animation-duration: .65s;
    -moz-animation-duration: .65s;
    -o-animation-duration: .65s;
    animation-duration: .65s;
    -webkit-animation-delay: .03s;
    -moz-animation-delay: .03s;
    -o-animation-delay: .03s;
    animation-delay: .03s;
}
.bs-loading > div:nth-child(2) {
    -webkit-animation-duration: 1.02s;
    -moz-animation-duration: 1.02s;
    -o-animation-duration: 1.02s;
    animation-duration: 1.02s;
    -webkit-animation-delay: .09s;
    -moz-animation-delay: .09s;
    -o-animation-delay: .09s;
    animation-delay: .09s;
}
.bs-loading > div:nth-child(3) {
    -webkit-animation-duration: 1.06s;
    -moz-animation-duration: 1.06s;
    -o-animation-duration: 1.06s;
    animation-duration: 1.06s;
    -webkit-animation-delay: -.69s;
    -moz-animation-delay: -.69s;
    -o-animation-delay: -.69s;
    animation-delay: -.69s;
}
.bs-loading > div:nth-child(4) {
    -webkit-animation-duration: 1.5s;
    -moz-animation-duration: 1.5s;
    -o-animation-duration: 1.5s;
    animation-duration: 1.5s;
    -webkit-animation-delay: -.41s;
    -moz-animation-delay: -.41s;
    -o-animation-delay: -.41s;
    animation-delay: -.41s;
}
.bs-loading > div:nth-child(5) {
    -webkit-animation-duration: 1.6s;
    -moz-animation-duration: 1.6s;
    -o-animation-duration: 1.6s;
    animation-duration: 1.6s;
    -webkit-animation-delay: .04s;
    -moz-animation-delay: .04s;
    -o-animation-delay: .04s;
    animation-delay: .04s;
}
.bs-loading > div:nth-child(6) {
    -webkit-animation-duration: .84s;
    -moz-animation-duration: .84s;
    -o-animation-duration: .84s;
    animation-duration: .84s;
    -webkit-animation-delay: .07s;
    -moz-animation-delay: .07s;
    -o-animation-delay: .07s;
    animation-delay: .07s;
}
.bs-loading > div:nth-child(7) {
    -webkit-animation-duration: .68s;
    -moz-animation-duration: .68s;
    -o-animation-duration: .68s;
    animation-duration: .68s;
    -webkit-animation-delay: -.66s;
    -moz-animation-delay: -.66s;
    -o-animation-delay: -.66s;
    animation-delay: -.66s;
}
.bs-loading > div:nth-child(8) {
    -webkit-animation-duration: .93s;
    -moz-animation-duration: .93s;
    -o-animation-duration: .93s;
    animation-duration: .93s;
    -webkit-animation-delay: -.76s;
    -moz-animation-delay: -.76s;
    -o-animation-delay: -.76s;
    animation-delay: -.76s;
}
.bs-loading > div:nth-child(9) {
    -webkit-animation-duration: 1.24s;
    -moz-animation-duration: 1.24s;
    -o-animation-duration: 1.24s;
    animation-duration: 1.24s;
    -webkit-animation-delay: -.76s;
    -moz-animation-delay: -.76s;
    -o-animation-delay: -.76s;
    animation-delay: -.76s;
}
@-webkit-keyframes bs-loading-keyframe {
    0% {
        opacity: 1;
        -webkit-transform: scale(1);
        transform: scale(1);
    }
    50% {
        opacity: .35;
        -webkit-transform: scale(.45);
        transform: scale(.45);
    }
    100% {
        opacity: 1;
        -webkit-transform: scale(1);
        transform: scale(1);
    }
}
@-moz-keyframes bs-loading-keyframe {
    0% {
        opacity: 1;
        -moz-transform: scale(1);
        transform: scale(1);
    }
    50% {
        opacity: .35;
        -moz-transform: scale(.45);
        transform: scale(.45);
    }
    100% {
        opacity: 1;
        -moz-transform: scale(1);
        transform: scale(1);
    }
}
@-o-keyframes bs-loading-keyframe {
    0% {
        opacity: 1;
        -o-transform: scale(1);
        transform: scale(1);
    }
    50% {
        opacity: .35;
        -o-transform: scale(.45);
        transform: scale(.45);
    }
    100% {
        opacity: 1;
        -o-transform: scale(1);
        transform: scale(1);
    }
}
@keyframes bs-loading-keyframe {
    0% {
        opacity: 1;
        -webkit-transform: scale(1);
        -moz-transform: scale(1);
        -o-transform: scale(1);
        transform: scale(1);
    }
    50% {
        opacity: .35;
        -webkit-transform: scale(.45);
        -moz-transform: scale(.45);
        -o-transform: scale(.45);
        transform: scale(.45);
    }
    100% {
        opacity: 1;
        -webkit-transform: scale(1);
        -moz-transform: scale(1);
        -o-transform: scale(1);
        transform: scale(1);
    }
}

/**
 * =>BS-Modal Styles
 **/
.bs-modal * {
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}
.bs-modal-clearfix:before,
.bs-modal-clearfix:after {
    content: "";
    display: table;
}
.bs-modal-clearfix:after {
    clear: both;
}
.bs-modal-clearfix {
    zoom: 1;
}

.bs-modal {
    background: white;
    display: none;
    font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
    overflow: hidden;
    position: fixed;
    max-width: 800px;
    width:100%;
    z-index: 99999;
    right: 0;
    left: 0;
    margin: 0 auto;
    top: 25%;

    -webkit-box-shadow: 0px 3px 10px 0px rgba(0, 0, 0, 0.33);
    -moz-box-shadow: 0px 3px 10px 0px rgba(0, 0, 0, 0.33);
    box-shadow: 0px 3px 10px 0px rgba(0, 0, 0, 0.33);
}
.modal-alongside-vc-panel .bs-modal-overlay {
    z-index:100107;
}
.modal-alongside-vc-panel .bs-modal {
    z-index:100108;
}
.bs-modal-bottom {
    border-top: 1px solid #e0e0e0;
    background: #f9f9f9;
    min-height: 58px;
    padding: 10px 20px;
    text-align: right;
}
.bs-modal-bottom a {
    cursor: pointer;
    margin: 5px 10px 0 0;
    vertical-align: middle;
    display: inline-block;
    text-decoration: none;
    float: right;
}
.bs-modal-buttons-left.bs-modal-bottom a {
    margin:5px 0 0 10px;
}
.bs-modal-buttons-left {
    text-align: left;
}
.bs-modal-buttons-left a{
    float: left;
}
.bs-modal-button-aside.bs-modal-button-aside {
    float: right;
}
.bs-modal-bottom a:first-child{
    margin-right: 0;
}
.bs-modal-bottom.bs-modal-buttons-left a:first-child{
    margin-left: 0;
}
.bs-modal-bottom,.bs-modal-header {
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}
.bs-modal-header {
    margin: 0;
    padding: 0 20px;
    height: 56px;
    line-height: 56px;
    font-size: 16px;
    color: #343434;
    font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.bs-modal-header .fa {
    vertical-align: middle;
    margin-right: 16px;
    font-size: 18px;
}
.bs-modal-header-wrapper{
    position: relative;
}
.bs-modal-header-wrapper:after {
    display: inline-block;
    content: ' ';
    height: 9px;
    background: -moz-linear-gradient(top, #e4e4e4 0%, transparent 100%);
    background: -webkit-linear-gradient(top, #e4e4e4 0%, transparent 100%);
    background: linear-gradient(to bottom, #e4e4e4 0%, transparent 100%);
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
}
.bs-modal-header .bssm-button {
    float: right;
    margin: 14px 40px 0 20px;
    line-height: 26px;
    font-size: 12px;
    padding: 0px 10px;
}
.bs-modal-description {
    min-height: 100px;
}
.bs-modal-title {
    color: #343434;
    font-size: 15px;
    font-weight: 600;
    margin: 0 0 15px;
}
.bs-modal-btn-primary,.bs-modal-btn-secondary {
    background: #00a0d2;
    border:1px solid #0073aa;
    -webkit-border-radius:2px;
    -moz-border-radius:2px;
    border-radius:2px;
    color: #fff;
    padding: 5px 13px;
    font-size: 14px;
}
.bs-modal-btn-primary:hover,.bs-modal-btn-secondary:hover {
    background: #00AAD2;
    border-color: #0073b4;
    color: #fff;
}
.bs-modal-btn-secondary {
    background-color: #f7f7f7;
    border-color: #CCC;
    color: #555;
    font-weight: 600;
}

.bs-modal-btn-secondary:hover {
    background-color: #f7f7ff;
    border-color: #ccccd6;
    color: #555;
}


.bs-modal-overlay {
    background: rgba(0, 0, 0, 0.7);
    bottom: 0;
    display: none;
    left: 0;
    position: fixed;
    right: 0;
    top: 0;
    z-index: 10000;
}

.bs-modal .bs-close-modal {
    background: #fff;
    border-radius: 50%;
    border: 1px solid #CCCCCC;
    -webkit-transition: all .07s ease;
    -moz-transition: all .07s ease;
    -o-transition: all .07s ease;
    transition: all .07s ease;
    color: #ababab;
    height: 24px;
    line-height: 22px;
    text-align: center;
    position: absolute;
    right: 20px;
    top: 16px;
    vertical-align: middle;
    width: 24px;
    z-index: 1;
}
.bs-modal .bs-close-modal:hover,
.bs-modal .bs-close-modal:focus{
    color: #FD3434;
    border-color: #FD3434;
}
.bs-modal-middle {
    vertical-align: middle;
}
.bs-modal-inside-right {
    display: inline-block;
    margin-left: 25px;
    font-size: 15px;
}
.bs-modal-inside-left {
    display: inline-block;
    margin-right: 25px;
    font-size: 15px;
}
.bs-modal-loading {
    text-align: center;
}
.bs-modal-loading-1 img {
    margin-top: 25px;
}
.bs-modal-loading-heading,.bs-modal-success  {
    text-align: center;
}

.bs-modal-success .fa {
    font-size: 30px;
}

.bs-modal-body{
    padding: 20px;
    overflow: auto;
    max-height: 540px;
}
.bs-modal-body ul.styled {
    list-style: inherit;
    list-style-position: inside;
    margin: 0 0 15px 10px;
    padding: 0;
}
.bs-modal-body ul.styled li{
    margin-bottom: 4px;
}
.modal-open {
    overflow: hidden;
}
.bs-modal-checkbox {
    vertical-align: middle;
    margin:10px 0 0 20px;
    display: inline-block;
}
.bs-modal-checkbox label{
    vertical-align: initial;
}

.bs-modal-body img{
    max-width: 100%;
    height: auto;
}
.bs-modal-image {
    text-align: center;
}
.bs-modal-image-caption {
    font-weight: bold;
    margin-top: 5px;
}


/**
 * RTL FIX
 **/
.rtl .bs-modal {
    left: 0;
    right: 0;
}
.rtl .bs-modal-bottom {
    text-align: right;
}
.rtl .bs-modal-bottom a {
    margin: 5px 0 0 10px;
    float: right;
}
.rtl .bs-modal-buttons-right.bs-modal-bottom a {
    margin:5px 10px 0 0;
}
.rtl .bs-modal-buttons-right {
    text-align: right;
}
.rtl .bs-modal-buttons-right a {
    float: right;
}
.rtl .bs-modal-button-aside.bs-modal-button-aside {
    float: left;
    margin: 5px 0 0;
}
.rtl .bs-modal-bottom a:first-child {
    margin-left: 0;
    margin-right: auto;
}
.rtl .bs-modal-bottom.bs-modal-buttons-right a:first-child {
    margin-right: 0;
    margin-left: auto;
}
.rtl .bs-modal-header .fa {
    margin-left: 16px;
    margin-right: auto;
}
.rtl .bs-modal-header-wrapper:after {
    right: 0;
    left: 0;
}
.rtl .bs-modal-overlay {
    right: 0;
    left: 0;
}
.rtl .bs-modal .bs-close-modal {
    left: 20px;
    right: auto;
}
.rtl .bs-modal-inside-left {
    margin-right: 25px;
    margin-left: auto;
}
.rtl .bs-modal-inside-right {
    margin-left: 25px;
    margin-right: auto;
}
.rtl .bs-modal-body ul.styled {
    margin: 0 10px 15px 0;
}
.rtl .bs-modal-checkbox {
    margin:10px 20px 0 0;
}
libs/better-framework/assets/css/slick.css000064400000003461151214002600014661 0ustar00/* Slider */
.bs-slider-slider
{
    position: relative;

    display: block;
    box-sizing: border-box;

    -webkit-user-select: none;
       -moz-user-select: none;
        -ms-user-select: none;
            user-select: none;

    -webkit-touch-callout: none;
    -khtml-user-select: none;
    -ms-touch-action: pan-y;
        touch-action: pan-y;
    -webkit-tap-highlight-color: transparent;
}

.bs-slider-list
{
    position: relative;

    display: block;
    overflow: hidden;

    margin: 0;
    padding: 0;
}
.bs-slider-list:focus
{
    outline: none;
}
.bs-slider-list.dragging
{
    cursor: pointer;
    cursor: hand;
}

.bs-slider-slider .bs-slider-track,
.bs-slider-slider .bs-slider-list
{
    -webkit-transform: translate3d(0, 0, 0);
       -moz-transform: translate3d(0, 0, 0);
        -ms-transform: translate3d(0, 0, 0);
         -o-transform: translate3d(0, 0, 0);
            transform: translate3d(0, 0, 0);
}

.bs-slider-track
{
    position: relative;
    top: 0;
    left: 0;

    display: block;
}
.bs-slider-track:before,
.bs-slider-track:after
{
    display: table;

    content: '';
}
.bs-slider-track:after
{
    clear: both;
}
.bs-slider-loading .bs-slider-track
{
    visibility: hidden;
}

.bs-slider-slide
{
    display: none;
    float: left;

    height: 100%;
    min-height: 1px;
}
[dir='rtl'] .bs-slider-slide
{
    float: right;
}
.bs-slider-slide img
{
    display: block;
}
.bs-slider-slide.bs-slider-loading img
{
    display: none;
}
.bs-slider-slide.dragging img
{
    pointer-events: none;
}
.bs-slider-initialized .bs-slider-slide
{
    display: block;
}
.bs-slider-loading .bs-slider-slide
{
    visibility: hidden;
}
.bs-slider-vertical .bs-slider-slide
{
    display: block;

    height: auto;

    border: 1px solid transparent;
}
.bs-slider-arrow.bs-slider-hidden {
    display: none;
}
libs/better-framework/assets/css/font-awesome-ie7.min.css000064400000110220151214002600017414 0ustar00.fa-large{font-size:1.3333333333333333em;margin-top:-4px;padding-top:3px;margin-bottom:-4px;padding-bottom:3px;vertical-align:middle;}
.nav [class^="icon-"],.nav [class*=" icon-"]{vertical-align:inherit;margin-top:-4px;padding-top:3px;margin-bottom:-4px;padding-bottom:3px;}.nav [class^="icon-"].fa-large,.nav [class*=" icon-"].fa-large{vertical-align:-25%;}
.nav-pills [class^="icon-"].fa-large,.nav-tabs [class^="icon-"].fa-large,.nav-pills [class*=" icon-"].fa-large,.nav-tabs [class*=" icon-"].fa-large{line-height:.75em;margin-top:-7px;padding-top:5px;margin-bottom:-5px;padding-bottom:4px;}
.btn [class^="icon-"].pull-left,.btn [class*=" icon-"].pull-left,.btn [class^="icon-"].pull-right,.btn [class*=" icon-"].pull-right{vertical-align:inherit;}
.btn [class^="icon-"].fa-large,.btn [class*=" icon-"].fa-large{margin-top:-0.5em;}
a [class^="icon-"],a [class*=" icon-"]{cursor:pointer;}
.fa-glass{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf000;');}
.fa-music{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf001;');}
.fa-search{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf002;');}
.fa-envelope-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf003;');}
.fa-heart{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf004;');}
.fa-star{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf005;');}
.fa-star-empty{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf006;');}
.fa-user{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf007;');}
.fa-film{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf008;');}
.fa-th-large{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf009;');}
.fa-th{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf00a;');}
.fa-th-list{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf00b;');}
.fa-ok{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf00c;');}
.fa-remove{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf00d;');}
.fa-zoom-in{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf00e;');}
.fa-zoom-out{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf010;');}
.fa-off{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf011;');}
.fa-power-off{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf011;');}
.fa-signal{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf012;');}
.fa-cog{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf013;');}
.fa-gear{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf013;');}
.fa-trash{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf014;');}
.fa-home{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf015;');}
.fa-file-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf016;');}
.fa-time{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf017;');}
.fa-road{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf018;');}
.fa-download-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf019;');}
.fa-download{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf01a;');}
.fa-upload{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf01b;');}
.fa-inbox{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf01c;');}
.fa-play-circle{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf01d;');}
.fa-repeat{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf01e;');}
.fa-rotate-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf01e;');}
.fa-refresh{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf021;');}
.fa-list-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf022;');}
.fa-lock{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf023;');}
.fa-flag{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf024;');}
.fa-headphones{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf025;');}
.fa-volume-off{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf026;');}
.fa-volume-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf027;');}
.fa-volume-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf028;');}
.fa-qrcode{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf029;');}
.fa-barcode{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf02a;');}
.fa-tag{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf02b;');}
.fa-tags{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf02c;');}
.fa-book{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf02d;');}
.fa-bookmark{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf02e;');}
.fa-print{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf02f;');}
.fa-camera{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf030;');}
.fa-font{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf031;');}
.fa-bold{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf032;');}
.fa-italic{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf033;');}
.fa-text-height{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf034;');}
.fa-text-width{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf035;');}
.fa-align-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf036;');}
.fa-align-center{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf037;');}
.fa-align-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf038;');}
.fa-align-justify{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf039;');}
.fa-list{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf03a;');}
.fa-indent-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf03b;');}
.fa-indent-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf03c;');}
.fa-facetime-video{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf03d;');}
.fa-picture{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf03e;');}
.fa-pencil{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf040;');}
.fa-map-marker{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf041;');}
.fa-adjust{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf042;');}
.fa-tint{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf043;');}
.fa-edit{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf044;');}
.fa-share{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf045;');}
.fa-check{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf046;');}
.fa-move{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf047;');}
.fa-step-backward{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf048;');}
.fa-fast-backward{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf049;');}
.fa-backward{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf04a;');}
.fa-play{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf04b;');}
.fa-pause{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf04c;');}
.fa-stop{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf04d;');}
.fa-forward{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf04e;');}
.fa-fast-forward{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf050;');}
.fa-step-forward{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf051;');}
.fa-eject{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf052;');}
.fa-chevron-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf053;');}
.fa-chevron-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf054;');}
.fa-plus-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf055;');}
.fa-minus-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf056;');}
.fa-remove-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf057;');}
.fa-ok-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf058;');}
.fa-question-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf059;');}
.fa-info-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf05a;');}
.fa-screenshot{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf05b;');}
.fa-remove-circle{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf05c;');}
.fa-ok-circle{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf05d;');}
.fa-ban-circle{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf05e;');}
.fa-arrow-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf060;');}
.fa-arrow-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf061;');}
.fa-arrow-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf062;');}
.fa-arrow-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf063;');}
.fa-share-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf064;');}
.fa-mail-forward{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf064;');}
.fa-resize-full{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf065;');}
.fa-resize-small{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf066;');}
.fa-plus{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf067;');}
.fa-minus{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf068;');}
.fa-asterisk{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf069;');}
.fa-exclamation-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf06a;');}
.fa-gift{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf06b;');}
.fa-leaf{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf06c;');}
.fa-fire{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf06d;');}
.fa-eye-open{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf06e;');}
.fa-eye-close{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf070;');}
.fa-warning-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf071;');}
.fa-plane{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf072;');}
.fa-calendar{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf073;');}
.fa-random{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf074;');}
.fa-comment{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf075;');}
.fa-magnet{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf076;');}
.fa-chevron-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf077;');}
.fa-chevron-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf078;');}
.fa-retweet{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf079;');}
.fa-shopping-cart{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf07a;');}
.fa-folder-close{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf07b;');}
.fa-folder-open{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf07c;');}
.fa-resize-vertical{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf07d;');}
.fa-resize-horizontal{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf07e;');}
.fa-bar-chart{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf080;');}
.fa-twitter-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf081;');}
.fa-facebook-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf082;');}
.fa-camera-retro{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf083;');}
.fa-key{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf084;');}
.fa-cogs{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf085;');}
.fa-gears{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf085;');}
.fa-comments{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf086;');}
.fa-thumbs-up-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf087;');}
.fa-thumbs-down-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf088;');}
.fa-star-half{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf089;');}
.fa-heart-empty{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf08a;');}
.fa-signout{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf08b;');}
.fa-linkedin-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf08c;');}
.fa-pushpin{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf08d;');}
.fa-external-link{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf08e;');}
.fa-signin{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf090;');}
.fa-trophy{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf091;');}
.fa-github-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf092;');}
.fa-upload-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf093;');}
.fa-lemon{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf094;');}
.fa-phone{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf095;');}
.fa-check-empty{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf096;');}
.fa-unchecked{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf096;');}
.fa-bookmark-empty{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf097;');}
.fa-phone-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf098;');}
.fa-twitter{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf099;');}
.fa-facebook{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf09a;');}
.fa-github{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf09b;');}
.fa-unlock{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf09c;');}
.fa-credit-card{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf09d;');}
.fa-rss{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf09e;');}
.fa-hdd{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0a0;');}
.fa-bullhorn{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0a1;');}
.fa-bell{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0a2;');}
.fa-certificate{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0a3;');}
.fa-hand-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0a4;');}
.fa-hand-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0a5;');}
.fa-hand-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0a6;');}
.fa-hand-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0a7;');}
.fa-circle-arrow-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0a8;');}
.fa-circle-arrow-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0a9;');}
.fa-circle-arrow-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0aa;');}
.fa-circle-arrow-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0ab;');}
.fa-globe{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0ac;');}
.fa-wrench{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0ad;');}
.fa-tasks{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0ae;');}
.fa-filter{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0b0;');}
.fa-briefcase{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0b1;');}
.fa-fullscreen{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0b2;');}
.fa-group{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c0;');}
.fa-link{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c1;');}
.fa-cloud{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c2;');}
.fa-beaker{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c3;');}
.fa-cut{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c4;');}
.fa-copy{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c5;');}
.fa-paper-clip{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c6;');}
.fa-paperclip{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c6;');}
.fa-save{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c7;');}
.fa-sign-blank{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c8;');}
.fa-reorder{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c9;');}
.fa-list-ul{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0ca;');}
.fa-list-ol{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0cb;');}
.fa-strikethrough{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0cc;');}
.fa-underline{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0cd;');}
.fa-table{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0ce;');}
.fa-magic{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0d0;');}
.fa-truck{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0d1;');}
.fa-pinterest{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0d2;');}
.fa-pinterest-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0d3;');}
.fa-google-plus-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0d4;');}
.fa-google-plus{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0d5;');}
.fa-money{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0d6;');}
.fa-caret-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0d7;');}
.fa-caret-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0d8;');}
.fa-caret-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0d9;');}
.fa-caret-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0da;');}
.fa-columns{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0db;');}
.fa-sort{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0dc;');}
.fa-sort-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0dd;');}
.fa-sort-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0de;');}
.fa-envelope{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e0;');}
.fa-linkedin{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e1;');}
.fa-undo{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e2;');}
.fa-rotate-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e2;');}
.fa-legal{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e3;');}
.fa-dashboard{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e4;');}
.fa-comment-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e5;');}
.fa-comments-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e6;');}
.fa-bolt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e7;');}
.fa-sitemap{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e8;');}
.fa-umbrella{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e9;');}
.fa-paste{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0ea;');}
.fa-lightbulb{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0eb;');}
.fa-exchange{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0ec;');}
.fa-cloud-download{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0ed;');}
.fa-cloud-upload{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0ee;');}
.fa-user-md{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0f0;');}
.fa-stethoscope{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0f1;');}
.fa-suitcase{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0f2;');}
.fa-bell-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0f3;');}
.fa-coffee{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0f4;');}
.fa-food{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0f5;');}
.fa-file-text-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0f6;');}
.fa-building{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0f7;');}
.fa-hospital{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0f8;');}
.fa-ambulance{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0f9;');}
.fa-medkit{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0fa;');}
.fa-fighter-jet{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0fb;');}
.fa-beer{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0fc;');}
.fa-h-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0fd;');}
.fa-plus-sign-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0fe;');}
.fa-double-angle-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf100;');}
.fa-double-angle-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf101;');}
.fa-double-angle-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf102;');}
.fa-double-angle-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf103;');}
.fa-angle-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf104;');}
.fa-angle-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf105;');}
.fa-angle-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf106;');}
.fa-angle-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf107;');}
.fa-desktop{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf108;');}
.fa-laptop{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf109;');}
.fa-tablet{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf10a;');}
.fa-mobile-phone{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf10b;');}
.fa-circle-blank{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf10c;');}
.fa-quote-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf10d;');}
.fa-quote-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf10e;');}
.fa-spinner{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf110;');}
.fa-circle{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf111;');}
.fa-reply{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf112;');}
.fa-mail-reply{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf112;');}
.fa-github-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf113;');}
.fa-folder-close-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf114;');}
.fa-folder-open-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf115;');}
.fa-expand-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf116;');}
.fa-collapse-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf117;');}
.fa-smile{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf118;');}
.fa-frown{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf119;');}
.fa-meh{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf11a;');}
.fa-gamepad{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf11b;');}
.fa-keyboard{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf11c;');}
.fa-flag-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf11d;');}
.fa-flag-checkered{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf11e;');}
.fa-terminal{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf120;');}
.fa-code{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf121;');}
.fa-reply-all{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf122;');}
.fa-mail-reply-all{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf122;');}
.fa-star-half-empty{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf123;');}
.fa-star-half-full{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf123;');}
.fa-location-arrow{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf124;');}
.fa-crop{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf125;');}
.fa-code-fork{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf126;');}
.fa-unlink{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf127;');}
.fa-question{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf128;');}
.fa-info{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf129;');}
.fa-exclamation{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf12a;');}
.fa-superscript{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf12b;');}
.fa-subscript{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf12c;');}
.fa-eraser{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf12d;');}
.fa-puzzle-piece{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf12e;');}
.fa-microphone{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf130;');}
.fa-microphone-off{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf131;');}
.fa-shield{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf132;');}
.fa-calendar-empty{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf133;');}
.fa-fire-extinguisher{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf134;');}
.fa-rocket{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf135;');}
.fa-maxcdn{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf136;');}
.fa-chevron-sign-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf137;');}
.fa-chevron-sign-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf138;');}
.fa-chevron-sign-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf139;');}
.fa-chevron-sign-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf13a;');}
.fa-html5{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf13b;');}
.fa-css3{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf13c;');}
.fa-anchor{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf13d;');}
.fa-unlock-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf13e;');}
.fa-bullseye{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf140;');}
.fa-ellipsis-horizontal{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf141;');}
.fa-ellipsis-vertical{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf142;');}
.fa-rss-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf143;');}
.fa-play-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf144;');}
.fa-ticket{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf145;');}
.fa-minus-sign-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf146;');}
.fa-check-minus{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf147;');}
.fa-level-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf148;');}
.fa-level-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf149;');}
.fa-check-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf14a;');}
.fa-edit-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf14b;');}
.fa-external-link-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf14c;');}
.fa-share-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf14d;');}
.fa-compass{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf14e;');}
.fa-collapse{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf150;');}
.fa-collapse-top{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf151;');}
.fa-expand{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf152;');}
.fa-eur{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf153;');}
.fa-euro{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf153;');}
.fa-gbp{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf154;');}
.fa-usd{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf155;');}
.fa-dollar{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf155;');}
.fa-inr{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf156;');}
.fa-rupee{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf156;');}
.fa-jpy{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf157;');}
.fa-yen{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf157;');}
.fa-cny{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf158;');}
.fa-renminbi{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf158;');}
.fa-krw{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf159;');}
.fa-won{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf159;');}
.fa-btc{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf15a;');}
.fa-bitcoin{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf15a;');}
.fa-file{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf15b;');}
.fa-file-text{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf15c;');}
.fa-sort-by-alphabet{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf15d;');}
.fa-sort-by-alphabet-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf15e;');}
.fa-sort-by-attributes{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf160;');}
.fa-sort-by-attributes-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf161;');}
.fa-sort-by-order{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf162;');}
.fa-sort-by-order-alt{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf163;');}
.fa-thumbs-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf164;');}
.fa-thumbs-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf165;');}
.fa-youtube-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf166;');}
.fa-youtube{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf167;');}
.fa-xing{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf168;');}
.fa-xing-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf169;');}
.fa-youtube-play{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf16a;');}
.fa-dropbox{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf16b;');}
.fa-stackexchange{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf16c;');}
.fa-instagram{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf16d;');}
.fa-flickr{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf16e;');}
.fa-adn{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf170;');}
.fa-bitbucket{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf171;');}
.fa-bitbucket-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf172;');}
.fa-tumblr{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf173;');}
.fa-tumblr-sign{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf174;');}
.fa-long-arrow-down{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf175;');}
.fa-long-arrow-up{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf176;');}
.fa-long-arrow-left{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf177;');}
.fa-long-arrow-right{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf178;');}
.fa-apple{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf179;');}
.fa-windows{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf17a;');}
.fa-android{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf17b;');}
.fa-linux{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf17c;');}
.fa-dribbble{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf17d;');}
.fa-skype{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf17e;');}
.fa-foursquare{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf180;');}
.fa-trello{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf181;');}
.fa-female{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf182;');}
.fa-male{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf183;');}
.fa-gittip{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf184;');}
.fa-sun{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf185;');}
.fa-moon{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf186;');}
.fa-archive{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf187;');}
.fa-bug{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf188;');}
.fa-vk{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf189;');}
.fa-weibo{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf18a;');}
.fa-renren{*zoom:expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf18b;');}
libs/better-framework/assets/css/bs-icons.css000064400000010575151214002600015275 0ustar00@font-face {
    font-family: "bs-icons";
    src:url("../fonts/bs-icons.eot");
    src:url("../fonts/bs-icons.eot?#iefix") format("embedded-opentype"),
    url("../fonts/bs-icons.woff") format("woff"),
    url("../fonts/bs-icons.ttf") format("truetype"),
    url("../fonts/bs-icons.svg#bs-icons") format("svg");
    font-weight: normal;
    font-style: normal;
}

[class^="bsfi-"],
[class*=" bsfi-"] {
    display: inline-block;
    font: normal normal normal 14px/1 "bs-icons";
    font-size: inherit;
    text-rendering: auto;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

[class^="bsfii"],
[class*=" bsfii"] {
    font: normal normal normal 14px/1 "bs-icons" !important;
}

/* Icons */
.bsfi-facebook:before {
    content: "\b000";
}
.bsfi-twitter:before {
    content: "\b001";
}
.bsfi-dribbble:before {
    content: "\b002";
}
.bsfi-vimeo:before {
    content: "\b003";
}
.bsfi-rss:before {
    content: "\b004";
}
.bsfi-github:before {
    content: "\b005";
}
.bsfi-vk:before {
    content: "\b006";
}
.bsfi-delicious:before {
    content: "\b007";
}
.bsfi-soundcloud:before {
    content: "\b009";
}
.bsfi-behance:before {
    content: "\b00a";
}
.bsfi-pinterest:before {
    content: "\b00b";
}
.bsfi-vine:before {
    content: "\b00c";
}
.bsfi-steam:before {
    content: "\b00d";
}
.bsfi-flickr:before {
    content: "\b00e";
}
.bsfi-forrst:before {
    content: "\b010";
}
.bsfi-mailchimp:before {
    content: "\b011";
}
.bsfi-tumblr:before {
    content: "\b013";
}
.bsfi-500px:before {
    content: "\b014";
}
.bsfi-members:before {
    content: "\b015";
}
.bsfi-comments:before {
    content: "\b016";
}
.bsfi-posts:before {
    content: "\b017";
}
.bsfi-instagram:before {
    content: "\b018";
}
.bsfi-whatsapp:before {
    content: "\b019";
}
.bsfi-line:before {
    content: "\b01a";
}
.bsfi-blackberry:before {
    content: "\b01b";
}
.bsfi-viber:before {
    content: "\b01c";
}
.bsfi-skype:before {
    content: "\b01d";
}
.bsfi-gplus:before {
    content: "\b01e";
}
.bsfi-telegram:before {
    content: "\b01f";
}
.bsfi-apple:before {
    content: "\b020";
}
.bsfi-android:before {
    content: "\b021";
}
.bsfi-fire-1:before {
    content: "\b022";
}
.bsfi-fire-2:before {
    content: "\b023";
}
.bsfi-publisher:before {
    content: "\b024";
}
.bsfi-betterstudio:before {
    content: "\b025";
}
.bsfi-fire-3:before {
    content: "\b026";
}
.bsfi-fire-4:before {
    content: "\b027";
}
.bsfi-disqus:before {
    content: "\b028";
}
.bsfi-better-amp:before {
    content: "\b029";
}
.bsfi-ok-ru:before {
    content: "\b030";
}
.bsfi-linkedin:before {
    content: "\b012";
}
.bsfi-snapchat:before {
    content: "\b031";
}
.bsfi-comments-1:before {
    content: "\b032";
}
.bsfi-comments-2:before {
    content: "\b033";
}
.bsfi-comments-3:before {
    content: "\b034";
}
.bsfi-calender:before {
    content: "\b035";
}
.bsfi-comments-4:before {
    content: "\b036";
}
.bsfi-comments-5:before {
    content: "\b037";
}
.bsfi-comments-6:before {
    content: "\b038";
}
.bsfi-comments-7:before {
    content: "\b039";
}
.bsfi-quote-1:before {
    content: "\b040";
}
.bsfi-quote-2:before {
    content: "\b041";
}
.bsfi-quote-3:before {
    content: "\b042";
}
.bsfi-quote-4:before {
    content: "\b043";
}
.bsfi-quote-5:before {
    content: "\b044";
}
.bsfi-quote-6:before {
    content: "\b045";
}
.bsfi-quote-7:before {
    content: "\b046";
}
.bsfi-youtube:before {
    content: "\b008";
}
.bsfi-envato:before {
    content: "\b00f";
}
.bsfi-arrow3-n:before {
    content: "\b047";
}
.bsfi-arrow3-s:before {
    content: "\b048";
}
.bsfi-arrow-n:before {
    content: "\b049";
}
.bsfi-arrow-ne:before {
    content: "\b050";
}
.bsfi-arrow-s:before {
    content: "\b051";
}
.bsfi-arrow-se:before {
    content: "\b052";
}
.bsfi-arrow2-n:before {
    content: "\b053";
}
.bsfi-arrow2-s:before {
    content: "\b054";
}
.bsfi-map-marker:before {
    content: "\b055";
}
.bsfi-arrow3-e:before {
    content: "\b056";
}
.bsfi-arrow-e:before {
    content: "\b057";
}
.bsfi-arrow-up-down:before {
    content: "\b058";
}
.bsfi-arrow2-e:before {
    content: "\b059";
}
.bsfi-arrow-left-right:before {
    content: "\b060";
}
.bsfi-bell:before {
    content: "\b061";
}


/* alias */
.bsfi-google:before {
    content: "\b01e";
}
.bsfi-bbm:before {
    content: "\b01b";
}
.bsfi-appstore:before {
    content: "\b020";
}
.bsfi-bs:before {
    content: "\b025";
}
.bsfi-ok_ru:before {
    content: "\b030";
}
libs/better-framework/assets/css/bs-modal.min.css000064400000033031151214002600016030 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */
.bs-loading,.bs-loading>div,.bs-modal *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box}.bs-modal,.bs-modal-header{font-family:"Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif}.bs-modal-bottom a,.bs-modal-checkbox,.bs-modal-header .fa,.bs-modal-middle{vertical-align:middle}@-webkit-keyframes line-scale-pulse-out-rapid{0%,90%{-webkit-transform:scaley(1);transform:scaley(1)}80%{-webkit-transform:scaley(.3);transform:scaley(.3)}}@-moz-keyframes line-scale-pulse-out-rapid{0%,90%{-moz-transform:scaley(1);transform:scaley(1)}80%{-moz-transform:scaley(.3);transform:scaley(.3)}}@-o-keyframes line-scale-pulse-out-rapid{0%,90%{-o-transform:scaley(1);transform:scaley(1)}80%{-o-transform:scaley(.3);transform:scaley(.3)}}@keyframes line-scale-pulse-out-rapid{0%,90%{-webkit-transform:scaley(1);-moz-transform:scaley(1);-o-transform:scaley(1);transform:scaley(1)}80%{-webkit-transform:scaley(.3);-moz-transform:scaley(.3);-o-transform:scaley(.3);transform:scaley(.3)}}@-webkit-keyframes bs-fadeInLeft{from{opacity:0;-webkit-transform:translate3d(-10%,0,0);transform:translate3d(-10%,0,0)}to{opacity:1;-webkit-transform:none;transform:none}}@keyframes bs-fadeInLeft{from{opacity:0;-webkit-transform:translate3d(-10%,0,0);transform:translate3d(-10%,0,0)}to{opacity:1;-webkit-transform:none;transform:none}}@-webkit-keyframes bs-fadeInRight{from{opacity:0;-webkit-transform:translate3d(10%,0,0);transform:translate3d(10%,0,0)}to{opacity:1;-webkit-transform:none;transform:none}}@keyframes bs-fadeInRight{from{opacity:0;-webkit-transform:translate3d(10%,0,0);transform:translate3d(10%,0,0)}to{opacity:1;-webkit-transform:none;transform:none}}@-webkit-keyframes bs-fadeInDown{from{opacity:0;-webkit-transform:translate3d(0,-10%,0);transform:translate3d(0,-10%,0)}to{opacity:1;-webkit-transform:none;transform:none}}@-webkit-keyframes bs-fadeOutUp{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,-10%,0);transform:translate3d(0,-10%,0)}}@keyframes bs-fadeOutUp{from{opacity:1}to{opacity:0;-webkit-transform:translate3d(0,-10%,0);transform:translate3d(0,-10%,0)}}@keyframes bs-fadeInDown{from{opacity:0;-webkit-transform:translate3d(0,-10%,0);transform:translate3d(0,-10%,0)}to{opacity:1;-webkit-transform:none;transform:none}}@-webkit-keyframes bs-fadeInUp{from{opacity:0;-webkit-transform:translate3d(0,10%,0);transform:translate3d(0,10%,0)}to{opacity:1;-webkit-transform:none;transform:none}}@keyframes bs-fadeInUp{from{opacity:0;-webkit-transform:translate3d(0,10%,0);transform:translate3d(0,10%,0)}to{opacity:1;-webkit-transform:none;transform:none}}.bs-animate{-webkit-animation-duration:.6s;animation-duration:.6s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.bs-fadeInLeft{-webkit-animation-name:bs-fadeInLeft;animation-name:bs-fadeInLeft}.bs-fadeInRight{-webkit-animation-name:bs-fadeInRight;animation-name:bs-fadeInRight}.bs-fadeInDown{-webkit-animation-name:bs-fadeInDown;animation-name:bs-fadeInDown}.bs-fadeInUp{-webkit-animation-name:bs-fadeInUp;animation-name:bs-fadeInUp}.bs-fadeOutUp{-webkit-animation-name:bs-fadeOutUp;animation-name:bs-fadeOutUp}.la-line-scale-pulse-out-rapid,.la-line-scale-pulse-out-rapid>div{position:relative;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.la-line-scale-pulse-out-rapid{display:block;font-size:0;color:#00a0d2;margin:10px auto;text-align:center;width:40px;height:32px}.la-line-scale-pulse-out-rapid.la-dark{color:#333}.la-line-scale-pulse-out-rapid>div{display:inline-block;float:none;background-color:currentColor;border:0 solid currentColor;width:4px;height:32px;margin:0 2px;border-radius:0;-webkit-animation:line-scale-pulse-out-rapid .9s infinite cubic-bezier(.11,.49,.38,.78);-moz-animation:line-scale-pulse-out-rapid .9s infinite cubic-bezier(.11,.49,.38,.78);-o-animation:line-scale-pulse-out-rapid .9s infinite cubic-bezier(.11,.49,.38,.78);animation:line-scale-pulse-out-rapid .9s infinite cubic-bezier(.11,.49,.38,.78)}.la-line-scale-pulse-out-rapid>div:nth-child(3){-webkit-animation-delay:-.9s;-moz-animation-delay:-.9s;-o-animation-delay:-.9s;animation-delay:-.9s}.la-line-scale-pulse-out-rapid>div:nth-child(2),.la-line-scale-pulse-out-rapid>div:nth-child(4){-webkit-animation-delay:-.65s;-moz-animation-delay:-.65s;-o-animation-delay:-.65s;animation-delay:-.65s}.la-line-scale-pulse-out-rapid>div:nth-child(1),.la-line-scale-pulse-out-rapid>div:nth-child(5){-webkit-animation-delay:-.4s;-moz-animation-delay:-.4s;-o-animation-delay:-.4s;animation-delay:-.4s}.la-line-scale-pulse-out-rapid.la-sm{width:20px;height:16px}.la-line-scale-pulse-out-rapid.la-sm>div{width:2px;height:16px;margin:0 1px}.la-line-scale-pulse-out-rapid.la-2x{width:80px;height:64px}.la-line-scale-pulse-out-rapid.la-2x>div{width:8px;height:64px;margin:0 4px}.la-line-scale-pulse-out-rapid.la-3x{width:120px;height:96px}.la-line-scale-pulse-out-rapid.la-3x>div{width:12px;height:96px;margin:0 6px}.bs-loading,.bs-loading>div{position:relative;box-sizing:border-box}.bs-loading{display:block;font-size:0;color:#333;margin:0 auto;line-height:4px;width:54px;height:54px}.bs-loading>div{display:inline-block;float:none;background-color:#00a0d2;width:10px;height:10px;margin:4px;border-radius:100%;-webkit-animation-name:bs-loading-keyframe;-moz-animation-name:bs-loading-keyframe;-o-animation-name:bs-loading-keyframe;animation-name:bs-loading-keyframe;-webkit-animation-iteration-count:infinite;-moz-animation-iteration-count:infinite;-o-animation-iteration-count:infinite;animation-iteration-count:infinite}.bs-loading>div:nth-child(1){-webkit-animation-duration:.65s;-moz-animation-duration:.65s;-o-animation-duration:.65s;animation-duration:.65s;-webkit-animation-delay:.03s;-moz-animation-delay:.03s;-o-animation-delay:.03s;animation-delay:.03s}.bs-loading>div:nth-child(2){-webkit-animation-duration:1.02s;-moz-animation-duration:1.02s;-o-animation-duration:1.02s;animation-duration:1.02s;-webkit-animation-delay:.09s;-moz-animation-delay:.09s;-o-animation-delay:.09s;animation-delay:.09s}.bs-loading>div:nth-child(3){-webkit-animation-duration:1.06s;-moz-animation-duration:1.06s;-o-animation-duration:1.06s;animation-duration:1.06s;-webkit-animation-delay:-.69s;-moz-animation-delay:-.69s;-o-animation-delay:-.69s;animation-delay:-.69s}.bs-loading>div:nth-child(4){-webkit-animation-duration:1.5s;-moz-animation-duration:1.5s;-o-animation-duration:1.5s;animation-duration:1.5s;-webkit-animation-delay:-.41s;-moz-animation-delay:-.41s;-o-animation-delay:-.41s;animation-delay:-.41s}.bs-loading>div:nth-child(5){-webkit-animation-duration:1.6s;-moz-animation-duration:1.6s;-o-animation-duration:1.6s;animation-duration:1.6s;-webkit-animation-delay:.04s;-moz-animation-delay:.04s;-o-animation-delay:.04s;animation-delay:.04s}.bs-loading>div:nth-child(6){-webkit-animation-duration:.84s;-moz-animation-duration:.84s;-o-animation-duration:.84s;animation-duration:.84s;-webkit-animation-delay:.07s;-moz-animation-delay:.07s;-o-animation-delay:.07s;animation-delay:.07s}.bs-loading>div:nth-child(7){-webkit-animation-duration:.68s;-moz-animation-duration:.68s;-o-animation-duration:.68s;animation-duration:.68s;-webkit-animation-delay:-.66s;-moz-animation-delay:-.66s;-o-animation-delay:-.66s;animation-delay:-.66s}.bs-loading>div:nth-child(8){-webkit-animation-duration:.93s;-moz-animation-duration:.93s;-o-animation-duration:.93s;animation-duration:.93s;-webkit-animation-delay:-.76s;-moz-animation-delay:-.76s;-o-animation-delay:-.76s;animation-delay:-.76s}.bs-loading>div:nth-child(9){-webkit-animation-duration:1.24s;-moz-animation-duration:1.24s;-o-animation-duration:1.24s;animation-duration:1.24s;-webkit-animation-delay:-.76s;-moz-animation-delay:-.76s;-o-animation-delay:-.76s;animation-delay:-.76s}@-webkit-keyframes bs-loading-keyframe{0%,100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}50%{opacity:.35;-webkit-transform:scale(.45);transform:scale(.45)}}@-moz-keyframes bs-loading-keyframe{0%,100%{opacity:1;-moz-transform:scale(1);transform:scale(1)}50%{opacity:.35;-moz-transform:scale(.45);transform:scale(.45)}}@-o-keyframes bs-loading-keyframe{0%,100%{opacity:1;-o-transform:scale(1);transform:scale(1)}50%{opacity:.35;-o-transform:scale(.45);transform:scale(.45)}}@keyframes bs-loading-keyframe{0%,100%{opacity:1;-webkit-transform:scale(1);-moz-transform:scale(1);-o-transform:scale(1);transform:scale(1)}50%{opacity:.35;-webkit-transform:scale(.45);-moz-transform:scale(.45);-o-transform:scale(.45);transform:scale(.45)}}.bs-modal *{box-sizing:border-box}.bs-modal-clearfix:after,.bs-modal-clearfix:before{content:"";display:table}.bs-modal-clearfix:after{clear:both}.bs-modal-clearfix{zoom:1}.bs-modal{background:#fff;display:none;overflow:hidden;position:fixed;max-width:800px;width:100%;z-index:99999;right:0;left:0;margin:0 auto;top:25%;-webkit-box-shadow:0 3px 10px 0 rgba(0,0,0,.33);-moz-box-shadow:0 3px 10px 0 rgba(0,0,0,.33);box-shadow:0 3px 10px 0 rgba(0,0,0,.33)}.modal-alongside-vc-panel .bs-modal-overlay{z-index:100107}.modal-alongside-vc-panel .bs-modal{z-index:100108}.bs-modal-bottom{border-top:1px solid #e0e0e0;background:#f9f9f9;min-height:58px;padding:10px 20px;text-align:right}.bs-modal-bottom a{cursor:pointer;margin:5px 10px 0 0;display:inline-block;text-decoration:none;float:right}.bs-modal-buttons-left.bs-modal-bottom a{margin:5px 0 0 10px}.bs-modal-buttons-left{text-align:left}.bs-modal-image,.bs-modal-loading,.bs-modal-loading-heading,.bs-modal-success{text-align:center}.bs-modal-buttons-left a{float:left}.bs-modal-button-aside.bs-modal-button-aside,.rtl .bs-modal-bottom a,.rtl .bs-modal-buttons-right a{float:right}.bs-modal-bottom a:first-child{margin-right:0}.bs-modal-bottom.bs-modal-buttons-left a:first-child{margin-left:0}.bs-modal-bottom,.bs-modal-header{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bs-modal-header{margin:0;padding:0 20px;height:56px;line-height:56px;font-size:16px;color:#343434}.bs-modal-header .fa{margin-right:16px;font-size:18px}.bs-modal-header-wrapper{position:relative}.bs-modal-header-wrapper:after{display:inline-block;content:' ';height:9px;background:-moz-linear-gradient(top,#e4e4e4 0,transparent 100%);background:-webkit-linear-gradient(top,#e4e4e4 0,transparent 100%);background:linear-gradient(to bottom,#e4e4e4 0,transparent 100%);position:absolute;top:100%;left:0;right:0}.bs-modal-header .bssm-button{float:right;margin:14px 40px 0 20px;line-height:26px;font-size:12px;padding:0 10px}.bs-modal-description{min-height:100px}.bs-modal-title{color:#343434;font-size:15px;font-weight:600;margin:0 0 15px}.bs-modal-btn-primary,.bs-modal-btn-secondary{background:#00a0d2;border:1px solid #0073aa;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;color:#fff;padding:5px 13px;font-size:14px}.bs-modal-btn-primary:hover,.bs-modal-btn-secondary:hover{background:#00AAD2;border-color:#0073b4;color:#fff}.bs-modal-btn-secondary{background-color:#f7f7f7;border-color:#CCC;color:#555;font-weight:600}.bs-modal-btn-secondary:hover{background-color:#f7f7ff;border-color:#ccccd6;color:#555}.bs-modal-overlay{background:rgba(0,0,0,.7);bottom:0;display:none;left:0;position:fixed;right:0;top:0;z-index:10000}.bs-modal .bs-close-modal{background:#fff;border-radius:50%;border:1px solid #CCC;-webkit-transition:all .07s ease;-moz-transition:all .07s ease;-o-transition:all .07s ease;transition:all .07s ease;color:#ababab;height:24px;line-height:22px;text-align:center;position:absolute;right:20px;top:16px;vertical-align:middle;width:24px;z-index:1}.rtl .bs-modal,.rtl .bs-modal-header-wrapper:after,.rtl .bs-modal-overlay{right:0;left:0}.bs-modal .bs-close-modal:focus,.bs-modal .bs-close-modal:hover{color:#FD3434;border-color:#FD3434}.bs-modal-inside-right{display:inline-block;margin-left:25px;font-size:15px}.bs-modal-inside-left{display:inline-block;margin-right:25px;font-size:15px}.bs-modal-loading-1 img{margin-top:25px}.bs-modal-success .fa{font-size:30px}.bs-modal-body{padding:20px;overflow:auto;max-height:540px}.bs-modal-body ul.styled{list-style:inherit;list-style-position:inside;margin:0 0 15px 10px;padding:0}.bs-modal-body ul.styled li{margin-bottom:4px}.modal-open{overflow:hidden}.bs-modal-checkbox{margin:10px 0 0 20px;display:inline-block}.bs-modal-checkbox label{vertical-align:initial}.bs-modal-body img{max-width:100%;height:auto}.rtl .bs-modal-bottom,.rtl .bs-modal-buttons-right{text-align:right}.bs-modal-image-caption{font-weight:700;margin-top:5px}.rtl .bs-modal-bottom a{margin:5px 0 0 10px}.rtl .bs-modal-buttons-right.bs-modal-bottom a{margin:5px 10px 0 0}.rtl .bs-modal-button-aside.bs-modal-button-aside{float:left;margin:5px 0 0}.rtl .bs-modal-bottom a:first-child{margin-left:0;margin-right:auto}.rtl .bs-modal-bottom.bs-modal-buttons-right a:first-child{margin-right:0;margin-left:auto}.rtl .bs-modal-header .fa{margin-left:16px;margin-right:auto}.rtl .bs-modal .bs-close-modal{left:20px;right:auto}.rtl .bs-modal-inside-left{margin-right:25px;margin-left:auto}.rtl .bs-modal-inside-right{margin-left:25px;margin-right:auto}.rtl .bs-modal-body ul.styled{margin:0 10px 15px 0}.rtl .bs-modal-checkbox{margin:10px 20px 0 0}libs/better-framework/assets/css/admin-pages.css000064400000023423151214002600015741 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */


/*

1. =>Base
    1.1. =>Main Helpers
    1.2. =>Buttons


2. =>Template Minimal 1


*/


/**
 * 1.1. =>Main Helpers
 **************************************************************/
.bf-clearfix:before,
.bf-clearfix:after {
    content: "";
    display: table;
}
.bf-clearfix:after {
    clear: both;
}
.bf-clearfix {
    zoom: 1;
}

.bf-admin-page{

}

.bf-admin-page.hide-notices .update-nag{
    display: none;
}


/**
 * 1.2. =>Buttons
 **************************************************************/
.bf-button{
    border-radius: 0;
    line-height: normal;
    line-height: 32px;
    display: inline-block;
    border: 1px solid #E2DDDB;
    background: #F5F5F5;
    padding: 0 14px;
    cursor: pointer;
    font-weight: bold;
    color: #4D4D4D;
    outline: none;
    -webkit-transition: all .3s ease;
    -moz-transition: all .3s ease;
    -o-transition: all .3s ease;
    transition: all .3s ease;
    font-size: 13px;
    text-decoration: none;
}
.bf-button:hover{
    border: 1px solid #C0C0C0;
    background: #F0F0F0;
    color: #383838;
    box-shadow: 0 1px 0 rgba(0,0,0,.05);
}
.bf-button.bf-main-button{
    background-color: #2d9ec7;
    border-color: #0074a2;
    color: #fff;
}
.bf-button.bf-main-button:hover{
    background: #288baf;
    border-color: #00435f;
}
.bf-button .fa,
.bf-button .dashicons{
    margin-right: 5px;
}
.bf-button .dashicons {
    margin-top: 5px;
}

.bf-button.large{
    height: 42px;
    margin: 0;
    padding: 0 15px 2px;
    font-size: 18px;
    font-weight: 300;
    line-height: 42px;
}
.bf-button.large-2x{
    height: 52px;
    margin: 0;
    padding: 0 25px 2px;
    font-size: 22px;
    font-weight: 300;
    line-height: 52px;
}
.bf-button.large-3x{
    height: 62px;
    margin: 0;
    padding: 0 35px 2px;
    font-size: 26px;
    font-weight: 300;
    line-height: 62px;
}



/**
 * 2. =>Template Minimal 1
 **************************************************************/
.bf-admin-page.bf-admin-page-template-minimal-1{

}
.bf-admin-page.bf-admin-page-template-minimal-1 .bf-admin-page-wrap{
    margin-top: -16px;
    margin-left: -20px;
}
.bf-admin-page.bf-admin-page-template-minimal-1 .bf-page-header{
    padding: 70px 30px 60px 30px;
    background-color: #fff;
    -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.05);
    box-shadow: 0 1px 3px rgba(0,0,0,0.05);
    margin-bottom: 50px;
    text-align: center;
    border-bottom: 1px solid #e5e5e5;
}
.bf-admin-page.bf-admin-page-template-minimal-1 .bf-page-header .page-title{
    margin: 0 0 15px;
    padding: 0;
    font-size: 46px;
    font-weight: 400;
    letter-spacing: -0.03em;
    line-height: 1.1;
}
.bf-admin-page.bf-admin-page-template-minimal-1 .bf-page-header .page-desc p{
    margin: 0;
    padding: 0;
    font-size: 21px;
    font-weight: 300;
    line-height: 1.3;
    color: #777;
}
.bf-admin-page.bf-admin-page-template-minimal-1 .bf-page-postbox{
    border: 1px solid #e5e5e5;
    background-color: #fff;
    -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.05);
    box-shadow: 0 1px 3px rgba(0,0,0,0.05);
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    width: 100%;
    max-width: 700px;
    margin: 0 auto;
}
.bf-admin-page.bf-admin-page-template-minimal-1 .bf-page-postbox .inside{
    padding: 40px;
}
.bf-admin-page.bf-admin-page-template-minimal-1 .bf-page-postbox .action-section{
    padding: 30px;
    border-top: 1px solid #DFDFDF;
    background-color: #F7F7F7;
    text-align: center;
    margin: 0 -40px -40px -40px;
}


/**
 * =>BF Loading
 **/
.bf-loading-wrapper {
    position: relative;
}
#bf_options_form,
#bf-panel .group,
.bf-loading-wrapper {
    min-height:inherit;
}
.bf-loading-anim,
.bf-loading-anim > div {
    position: relative;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}
.bf-loading-anim {
    display: block;
    font-size: 0;
    color: #333;
}
.bf-loading-anim > div {
    display: inline-block;
    float: none;
    background-color: #0080ce;
}
.bf-loading-anim {
    width: 54px;
    height: 54px;
    position: absolute;
    top: 50%;
    left: 50%;
    margin-top: -27px;
    line-height: 0;
}
.bf-loading-anim > div {
    width: 10px;
    height: 10px;
    margin: 4px;
    border-radius: 100%;
    -webkit-animation-name: bf-loading-keyframe;
    -moz-animation-name: bf-loading-keyframe;
    -o-animation-name: bf-loading-keyframe;
    animation-name: bf-loading-keyframe;
    -webkit-animation-iteration-count: infinite;
    -moz-animation-iteration-count: infinite;
    -o-animation-iteration-count: infinite;
    animation-iteration-count: infinite;
}
.bf-loading-anim > div:nth-child(1) {
    -webkit-animation-duration: .65s;
    -moz-animation-duration: .65s;
    -o-animation-duration: .65s;
    animation-duration: .65s;
    -webkit-animation-delay: .03s;
    -moz-animation-delay: .03s;
    -o-animation-delay: .03s;
    animation-delay: .03s;
}
.bf-loading-anim > div:nth-child(2) {
    -webkit-animation-duration: 1.02s;
    -moz-animation-duration: 1.02s;
    -o-animation-duration: 1.02s;
    animation-duration: 1.02s;
    -webkit-animation-delay: .09s;
    -moz-animation-delay: .09s;
    -o-animation-delay: .09s;
    animation-delay: .09s;
}
.bf-loading-anim > div:nth-child(3) {
    -webkit-animation-duration: 1.06s;
    -moz-animation-duration: 1.06s;
    -o-animation-duration: 1.06s;
    animation-duration: 1.06s;
    -webkit-animation-delay: -.69s;
    -moz-animation-delay: -.69s;
    -o-animation-delay: -.69s;
    animation-delay: -.69s;
}
.bf-loading-anim > div:nth-child(4) {
    -webkit-animation-duration: 1.5s;
    -moz-animation-duration: 1.5s;
    -o-animation-duration: 1.5s;
    animation-duration: 1.5s;
    -webkit-animation-delay: -.41s;
    -moz-animation-delay: -.41s;
    -o-animation-delay: -.41s;
    animation-delay: -.41s;
}
.bf-loading-anim > div:nth-child(5) {
    -webkit-animation-duration: 1.6s;
    -moz-animation-duration: 1.6s;
    -o-animation-duration: 1.6s;
    animation-duration: 1.6s;
    -webkit-animation-delay: .04s;
    -moz-animation-delay: .04s;
    -o-animation-delay: .04s;
    animation-delay: .04s;
}
.bf-loading-anim > div:nth-child(6) {
    -webkit-animation-duration: .84s;
    -moz-animation-duration: .84s;
    -o-animation-duration: .84s;
    animation-duration: .84s;
    -webkit-animation-delay: .07s;
    -moz-animation-delay: .07s;
    -o-animation-delay: .07s;
    animation-delay: .07s;
}
.bf-loading-anim > div:nth-child(7) {
    -webkit-animation-duration: .68s;
    -moz-animation-duration: .68s;
    -o-animation-duration: .68s;
    animation-duration: .68s;
    -webkit-animation-delay: -.66s;
    -moz-animation-delay: -.66s;
    -o-animation-delay: -.66s;
    animation-delay: -.66s;
}
.bf-loading-anim > div:nth-child(8) {
    -webkit-animation-duration: .93s;
    -moz-animation-duration: .93s;
    -o-animation-duration: .93s;
    animation-duration: .93s;
    -webkit-animation-delay: -.76s;
    -moz-animation-delay: -.76s;
    -o-animation-delay: -.76s;
    animation-delay: -.76s;
}
.bf-loading-anim > div:nth-child(9) {
    -webkit-animation-duration: 1.24s;
    -moz-animation-duration: 1.24s;
    -o-animation-duration: 1.24s;
    animation-duration: 1.24s;
    -webkit-animation-delay: -.76s;
    -moz-animation-delay: -.76s;
    -o-animation-delay: -.76s;
    animation-delay: -.76s;
}
@-webkit-keyframes bf-loading-keyframe {
    0% {
        opacity: 1;
        -webkit-transform: scale(1);
        transform: scale(1);
    }
    50% {
        opacity: .35;
        -webkit-transform: scale(.45);
        transform: scale(.45);
    }
    100% {
        opacity: 1;
        -webkit-transform: scale(1);
        transform: scale(1);
    }
}
@-moz-keyframes bf-loading-keyframe {
    0% {
        opacity: 1;
        -moz-transform: scale(1);
        transform: scale(1);
    }
    50% {
        opacity: .35;
        -moz-transform: scale(.45);
        transform: scale(.45);
    }
    100% {
        opacity: 1;
        -moz-transform: scale(1);
        transform: scale(1);
    }
}
@-o-keyframes bf-loading-keyframe {
    0% {
        opacity: 1;
        -o-transform: scale(1);
        transform: scale(1);
    }
    50% {
        opacity: .35;
        -o-transform: scale(.45);
        transform: scale(.45);
    }
    100% {
        opacity: 1;
        -o-transform: scale(1);
        transform: scale(1);
    }
}
@keyframes bf-loading-keyframe {
    0% {
        opacity: 1;
        -webkit-transform: scale(1);
        -moz-transform: scale(1);
        -o-transform: scale(1);
        transform: scale(1);
    }
    50% {
        opacity: .35;
        -webkit-transform: scale(.45);
        -moz-transform: scale(.45);
        -o-transform: scale(.45);
        transform: scale(.45);
    }
    100% {
        opacity: 1;
        -webkit-transform: scale(1);
        -moz-transform: scale(1);
        -o-transform: scale(1);
        transform: scale(1);
    }
}


/**
 * RTL FIX
 **/
.rtl .bf-button .fa,
.rtl .bf-button .dashicons {
    margin-left: 5px;
    margin-right: auto;
}
.rtl .bf-admin-page.bf-admin-page-template-minimal-1 .bf-admin-page-wrap {
    margin-right: -20px;
    margin-left: auto;
}
.rtl .bf-loading-anim {
    right: 50%;
    left: auto;
}
libs/better-framework/assets/css/admin-style.css000064400000422632151214002600016007 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */

/*

1. =>Base
    1.1. =>Main Helpers
    1.2. =>Buttons
    1.3. =>Columns
    1.4. =>General Classes

2. =>General Fields
    2.1. =>Section
    2.2. =>Heading
    2.3. =>Color
    2.4. =>Image Radio Option
    2.5. =>Media Image
    2.6. =>Background Image
    2.7. =>Sorter
    2.8. =>Ajax Select
    2.9. =>Social Counter Sorter
    2.10. =>Image Select
    2.11. =>Icon Select
    2.12. =>Typography
    2.13. =>Social Share Sorter
    2.14. =>Repeater Item
    2.15. =>Border
    2.16. =>Info
    2.17. =>Switch
    2.18. =>Fields Group
    2.19. =>Media
    2.20. =>Code Editor
    2.21. =>Custom Checkbox/Radio Field
    2.22. =>Term Select Field Style
    2.23. =>Selector Modal
    2.24. =>Pre Defined Styles Modal
    2.25. =>Popup Select
    2.26. =>Color Picker

3. =>Admin Panel
    3.1. =>Section
    3.2. =>Panel
    3.3. =>Panel Header
    3.4. =>Panel Main
    3.5. =>Panel Nav
    3.6. =>Panel Content
    3.7. =>Panel Footer
    3.8. =>Typography
    3.9 =>Panel Loading

4. =>Widgets
    4.1. =>General style
    4.2. =>Section
    4.3. =>Ajax Select

5. =>Taxonomies

6. =>Visual Composer
    6.1. =>Color Picker
    6.2. =>Image Radio
    6.3. =>Ajax Select
    6.4. =>Icon Radio
    6.5. =>Heading
    6.6. =>Editor ShortCode
    6.7. =>VC Media Image
    6.8. =>VC Info
    6.9. =>Switch
    6.10. =>Select
    6.11. =>Column

7. =>Menus
    7.1. =>Mega Menu Field
    7.2. =>Menu Badge Field
    7.3. =>WPNav Menu
    7.4. =>Heading
    7.5. =>Color Picker
    7.6. =>Checkbox

8. =>Meta Box
    8.1. =>Section
    8.2. =>Tabs
    8.3. =>Heading


9. =>Font Manager
    9.1. =>Fields

10. =>User Metabox


11. =>Admin Menus

12. =>Notice System

13. =>Last Not Refactored Codes

14. =>TinyMCE Add-On

15. =>KingComposer

16. =>Elementor

17. =>Gutenberg

*/

/**
 * 1.1. =>Main Helpers
 **************************************************************/
.bf-clearfix:before,
.bf-clearfix:after {
    content: "";
    display: table;
}

.bf-clearfix:after {
    clear: both;
}

.bf-clearfix {
    zoom: 1;
}

.bf-clear-right {
    clear: right !important;
}

.bf-clear-left {
    clear: left !important;
}

.clr {
    clear: both;
}

.rtl {
    text-align: right;
    direction: rtl;
}

.ltr {
    text-align: left;
    direction: ltr;
}

.limit-line {
    overflow: hidden;
    white-space: nowrap;
}

.ellipsis {
    text-overflow: ellipsis;
}

.rtl .bf-flip-img-rtl img,
.rtl img.bf-flip-img-rtl {
    -moz-transform: scaleX(-1);
    -o-transform: scaleX(-1);
    -webkit-transform: scaleX(-1);
    transform: scaleX(-1);
    filter: FlipH;
    -ms-filter: "FlipH";
}

/**
 * 1.2. =>Buttons
 **************************************************************/
.bf-button {
    border-radius: 0;
    line-height: normal;
    line-height: 32px;
    display: inline-block;
    border: 1px solid #E2DDDB;
    background: #F5F5F5;
    padding: 0 14px;
    cursor: pointer;
    font-weight: bold;
    color: #4D4D4D;
    outline: none;
    -webkit-transition: all .3s ease;
    -moz-transition: all .3s ease;
    -o-transition: all .3s ease;
    transition: all .3s ease;
    font-size: 13px;
    text-decoration: none;
}

.bf-button:hover {
    border: 1px solid #C0C0C0;
    background: #F0F0F0;
    color: #383838;
    box-shadow: 0 1px 0 rgba(0, 0, 0, .05);
}

.bf-button.bf-main-button {
    background-color: #2d9ec7;
    border-color: #0074a2;
    color: #fff;
}

.bf-button.bf-main-button:hover {
    background: #288baf;
    border-color: #00435f;
}

.bf-button .fa,
.bf-button .dashicons {
    margin-right: 5px;
}

.bf-button .dashicons {
    margin-top: 5px;
}

.bf-button.large {
    height: 42px;
    margin: 0;
    padding: 0 15px 2px;
    font-size: 18px;
    font-weight: 300;
    line-height: 42px;
}

.bf-button.large-2x {
    height: 52px;
    margin: 0;
    padding: 0 20px 2px;
    font-size: 18px;
    font-weight: 300;
    line-height: 52px;
}

.bf-button i[class^="bsai-"] {
    font-size: 16px;
    margin-right: 4px;
}

/**
 * 1.3. =>Columns
 **************************************************************/
.bf-column {
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}

.bf-columns-1 .bf-column {
    width: 100%;
    float: none;
}

/* 2 Column */
.bf-columns-2 .bf-column {
    width: 50%;
    float: left;
}

.bf-columns-2 .bf-column:nth-child(odd) {
    padding-right: 13px;
    clear: left;
}

.bf-columns-2 .bf-column:nth-child(even) {
    padding-left: 13px;
}

/* 3 Column */
.bf-columns-3 .bf-column {
    width: 33.3333%;
    float: left;
}

.bf-columns-3 .bf-column:nth-child( 3n-1 ) {
    padding: 0 6px;
}

.bf-columns-3 .bf-column:nth-child( 3n-2 ) {
    padding-right: 12px;
    clear: left;
}

.bf-columns-3 .bf-column:nth-child( 3n+3  ) {
    padding-left: 12px;
}

/* 4 Column */
.bf-columns-4 .bf-column {
    width: 25%;
    float: left;
}

.bf-columns-4 .bf-column:nth-child(4n-3) {
    padding-left: 0;
    padding-right: 12px;
    clear: left;
}

.bf-columns-4 .bf-column:nth-child(4n+2) {
    padding-left: 6px;
    padding-right: 6px;
}

.bf-columns-4 .bf-column:nth-child(4n+3) {
    padding-left: 6px;
    padding-right: 6px;
}

.bf-columns-4 .bf-column:nth-child(4n+4) {
    padding-right: 0;
    padding-left: 12px;
}

/**
 * 1.4. =>General Classes
 **************************************************************/
.bf-item-container {
    min-width: 180px;
    float: left;
    background: rgb(252, 252, 252);
    -webkit-box-shadow: 0 1px 1px -1px rgba(0, 0, 0, .1);
    box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.1);
    border: 1px solid #ddd;
    font-family: "Open Sans", Helvetica, sans-serif;
    font-size: 15px;
    color: #3b3b3b;
    margin-right: 22px;
    margin-bottom: 36px;
    position: relative;
    overflow: hidden;
}

.bssm-item .bf-item-container {
    margin: 0;
}

.bf-item-container figure {
    display: block;
    margin: 0;
    padding: 0;
    border-bottom: 1px solid rgba(220, 220, 220, 0.53);
    min-height: 170px;
}

.bf-item-container figure img {
    width: 100%;
    display: block;
}

.bf-item-footer {
    background: #FCFCFC;
    position: relative;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    border: 1px solid #fcfcfc;
}

.bf-item-footer .highlight-section {
    z-index: 69;
    max-width: 100%;
    background: rgba(244, 244, 244, .7);
    border: 1px solid rgba(0, 0, 0, .05);
    border-width: 0 0 0 1px;
}

.bf-item-title {
    text-align: left;
    color: #3b3b3b;
    position: absolute;
    font-weight: 600;
    padding: 12px 0 12px 12px;
    font-size: 15px;
    line-height: 28px;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}

.rtl .bf-item-title {
    text-align: right;
    padding: 12px 12px 12px 0;
}

.bf-item-buttons {
    display: block;
    float: right;
    padding: 0;
    margin: 0;
}

.bf-item-buttons a {
    margin: 0 12px 0 0;
    white-space: nowrap;
}

.bf-item-buttons a:last-child {
    margin-right: 0;
}

.bf-item-buttons > span {
    float: right;
    position: relative;
    z-index: 99;
    padding: 12px;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}

.bf-item-buttons > span:last-child {
    margin-left: 0;
}

.rtl .bf-item-buttons {
    float: left;
}

.rtl .bf-item-buttons a {
    margin: 0 12px 0 0;
}

.rtl .bf-item-buttons a:last-child {
    margin-left: 0;
    margin-right: auto;
}

.rtl .bf-item-buttons > span {
    float: left;
    border-width: 0 1px 0 0;
}

.rtl .bf-item-buttons > span:last-child {
    margin-right: 0;
    margin-left: auto;
}

.bf-btn-primary,
.bf-btn-secondary {
    background: #00a0d2;
    color: #fff;
    border: 1px solid #0073aa;

    -webkit-border-radius: 2px;
    -moz-border-radius: 2px;
    border-radius: 2px;
    text-decoration: none;
    padding: 3px 9px;
    font-weight: 600;
    vertical-align: middle;

    font-size: 14px;
    display: inline-block;
}

.bf-btn-primary:hover {
    color: #fff;
    background-color: #28abd2;
    border-color: #1f8eb4;
}

.bf-btn-secondary {
    color: #555;
    border: 1px solid #cccccc;
    background: #f7f7f7;
    vertical-align: top;
}

.bf-btn-secondary.bf-btn-dark {
    background-color: #eee;
    border-color: #cfcfcf;
    color: #3d3d3d;

    box-shadow: none;
}

.bf-btn-secondary.bf-btn-dark:hover {
    background-color: #e9e9e9;
    border-color: #c5c5c5;
}

.bf-item-container.not-active {
    height: 314px;
}

.bf-item-container.not-active .bf-item-footer .bf-item-title {
    position: relative;
    display: block;
    padding: 9px 0 2px;
    text-align: center;
}

.bf-item-container.not-active .bf-item-footer .active-error {
    display: block;
    text-align: center;
    color: #f13838;
    font-size: 12px;
    font-weight: 700;
}

/**
 * 2. =>General Fields
 **************************************************************/
/***** Field Prefix or Suffix ******/
.block-editor .bf-section-container .bf-section {
    padding: 0;
}

.block-editor .bf-heading h3 {
    margin-top: 1em;
    margin-bottom: 0.3em;
}
.bf-field-with-suffix,
.bf-field-with-prefix {
    position: relative;
    display: inline-block;
}

.bf-field-with-prefix input[type=text],
.bf-field-with-suffix input[type=text] {
    max-width: 160px !important;
    display: inline-block !important;
}

.bf-field-with-suffix.bf-field-with-prefix input[type=text] {
    padding-right: 10px !important;
    padding-left: 10px !important;
}

.bf-field-with-prefix,
.bf-field-with-suffix {
    width: 100%;
}

.bf-field-with-prefix span,
.bf-field-with-suffix span {
    display: inline-block;
    cursor: pointer;
    vertical-align: middle;
    font-size: 13px;
    z-index: 6;
    height: 32px;
    line-height: 32px;
    border: 1px solid #d6d6d6;
    color: #7C7C7C;
    background-color: #fff;
    padding: 0 10px;
    font-style: normal;
}

.bf-field-with-prefix span.bf-prefix {
    margin-right: -5px;
    border-right: none;
}

.bf-field-with-suffix span.bf-suffix {
    margin-left: -5px;
    border-left: none;
}

/* text helpers */
.bf-text-right {
    text-align: right;
}

.bf-text-left {
    text-align: left;
}

.bf-explain code {
    padding: 1px 5px;
    margin: 0 1px;
    background: #efefef;
    border: 1px solid #bfbfbf;
    font-size: 12px;
    border-radius: 2px;
    color: #676767;
    white-space: nowrap;
}

/**
 * 2.1. =>Section
 **************************************************************/

.bf-section img {
    max-width: 100%;
    max-height: 300px;
}

.bf-section.full-width select {
    width: 100%;
}

.bf-section-container {
    padding-right: 20px;
    padding-left: 20px;
}

.bf-section-container .bf-section {
    padding-top: 20px;
    padding-bottom: 20px;
    border-bottom: 1px solid #F4F3F3;
}

.bf-section-container:last-child .bf-section {
    border-bottom: none;
}

.bf-section-container.highlight-hover {
    -webkit-transition: all .3s ease;
    -moz-transition: all .3s ease;
    -o-transition: all .3s ease;
    transition: all .3s ease;
}

.bf-section-container.highlight-hover:hover {
    background-color: #FFFEE7;

}

.bf-section-container .bf-section.full-with-both > .bf-controls,
.bf-section-container .bf-section.full-with-controls > .bf-controls {
    float: none !important;
    width: 100% !important;
    clear: both !important;
}

.bf-section-container .bf-section.full-with-both > .bf-explain,
.bf-section-container .bf-section.full-with-both > .bf-heading,
.bf-section-container .bf-section.full-with-heading > .bf-heading {
    float: none !important;
    width: 100% !important;
    padding-right: 0 !important;
}

.bf-section-container .bf-section.full-with-both > .bf-controls input[type=text],
.bf-section-container .bf-section.full-with-both > .bf-controls .bf-select-option-container {
    max-width: 100%;
}

.bf-section-container .bf-section .input-desc {
    font-size: 12px;
    color: #b4b4b4;
    margin-top: 3px;
}

/**
 * 2.2. =>Heading
 **************************************************************/
/* style 1 */
.bf-section-container .bf-section-heading.style-1 {
    margin: 20px -20px 5px;
}

.bf-group-inner .bf-section-container .bf-section-heading.style-1 {
    margin: 20px 0 5px;
}

.bf-section-container .bf-section-heading.style-1 .bf-section-heading-title {
    background-color: #F5F5F5;
    border: 1px solid #D3D3D3;
    position: relative;
    height: 42px;
    line-height: 42px;
    font-size: 15px;
    color: #222222;
    font-weight: bold;
    display: block;
    padding: 0 20px;
    margin-bottom: 0;
}

.bf-section-container .bf-section-heading.style-1 .bf-section-heading-title h3 {
    margin: 0;
    font-size: 15px;
}

.bf-section-container .bf-section-heading.style-1 .bf-section-heading-desc {
    margin-top: 15px;
    padding: 0 20px;
    color: #999;
}

/* style 2 */
.bf-section-container .bf-section-heading.style-2 {
    margin: 5px -20px -5px;
    position: relative;
}

.bf-group-inner .bf-section-container .bf-section-heading.style-2 {
    margin: -10px 0 0;
    background: #fff;
    padding-top: 20px;
    padding-bottom: 10px;
}

.bf-section-container .bf-section-heading.style-2 .bf-section-heading-title {
    position: relative;
    height: 42px;
    line-height: 42px;
    font-size: 15px;
    color: #222222;
    font-weight: bold;
    display: block;
    padding: 0 15px;
    margin-bottom: 0;
    text-align: center;
}

.bf-section-container .bf-section-heading.style-2 .bf-section-heading-title h3 {
    margin: 0;
    font-size: 20px;
    display: inline-block;
    padding: 0 20px;
    background: #fff;
    z-index: 1;
    position: relative;
}

.bf-section-container .bf-section-heading.style-2 .bf-section-heading-title:after {
    content: '';
    display: block;
    height: 3px;
    position: relative;
    top: -50%;
    margin-top: -1.5px;
    left: 0;
    right: 0;
    background: #e2e2e2;
    clear: none;
    z-index: 0;
}

.bf-section-container .bf-section-heading.style-2 .bf-section-heading-desc {
    margin-top: 15px;
    padding: 0 20px;
    color: #999;
    text-align: center;
}

/**
 * 2.3. =>Color
 **************************************************************/
.colorpicker {
    z-index: 999999; /* For conflict on VC and other sections */
}

.bf-section-container .bf-controls-color-option {
    position: relative;
    display: inline-block;
}

.bf-section-container .bf-color-picker {
    width: 130px;
    height: 34px;
    box-shadow: none;
    outline: none;
    -webkit-transition: none;
    -moz-transition: none;
    -ms-transition: none;
    -o-transition: none;
    transition: none;
    padding: 5px 10px;
}

.bf-section-container .bf-color-picker:focus {
    box-shadow: none;
}

.bf-section-container .bf-color-picker-container {
    position: relative;
    width: 132px;
}

.bf-section-container .bf-color-picker-preview {
    width: 24px;
    height: 24px;
    display: inline-block;
    position: absolute;
    right: 5px;
    top: 5px;
    z-index: 1;
}

/**
 * 2.4. =>Image Radio Option
 **************************************************************/
.bf-section-container .bf-controls-image_radio-option input[type=radio] {
    display: none;
}

.bf-section-container.style-floated-left .bf-image-radio-option,
.bf-section-container .style-floated-left .bf-image-radio-option {
    float: left;
    margin-right: 6px;
    margin-bottom: 12px;
}

.bf-section-container .bf-image-radio-option .item-label {
    margin: 5px 0;
    text-align: center;
    font-size: 10px;
}

.bf-section-container .bf-image-radio-option.checked .item-label {
    font-weight: bold;
}

.bf-section-container .bf-image-radio-option img {
    border: 1px solid #e2e2e2;
}

.bf-section-container .bf-image-radio-option.checked img {
    border: 1px solid #0074a2;
}

/**
 * 2.5. =>Media Image
 **************************************************************/
.bf-section-container .bf-section-media_image-option .bf-media-image-upload-btn,
.bf-section-container .bf-section-media_image-option .bf-media-image-remove-btn {
    margin-bottom: 15px;
}

.bf-section-container .bf-section-media_image-option .bf-media-image-remove-btn {
    margin-left: 10px;
}

.bf-section-container .bf-section-media_image-option input[type=text] + .bf-media-image-preview {
    margin-top: 17px;
}

.bf-section-container .bf-section-media_image-option input[type=text] + .bf-media-image-preview:empty {
    margin-top: 0;
}

/**
 * 2.6. =>Background Image
 **************************************************************/
.wpb_edit_form_elements .bf-section-container .bf-background-image-remove-btn,
.bf-section-container .bf-background-image-remove-btn {
    margin-left: 10px;
}

.wpb_edit_form_elements .bf-section-container .bf-background-image-uploader-select,
.bf-section-container .bf-background-image-uploader-select {
    margin: 10px 0;
    width: 100%;
}

.bf-section-container .bf-controls-background_image-option .bf-button {
    margin-bottom: 20px;
}

.bf-section-container .bf-controls-background_image-option .bf-background-image-uploader-select-container {
    margin-bottom: 20px;
}

.bf-section-container .bf-controls-background_image-option .bf-background-image-uploader-select-container.hidden:before,
.bf-section-container .bf-controls-background_image-option .bf-background-image-uploader-select-container.hidden {
    display: none;
}

.better-custom-field-background_image .bf-background-image-preview img {
    max-width: 100%;
}

/**
 * 2.7. =>Sorter
 **************************************************************/
.bf-section-container .ui-slider {
    height: 5px;
    background-color: #FFFFFF;
    position: relative;
    margin: 40px 0 15px;
    border: 1px solid #D9D9D9;
}

.bf-section-container .ui-slider .ui-slider-range {
    height: 5px;
    background-color: #BDECFF;
    position: relative;
    margin: -1px;
    border: 1px solid #2E9DC8;
}

.bf-section-container .ui-slider .ui-slider-range:after {
    content: '';
    width: 12px;
    height: 12px;
    display: inline-block;
    position: absolute;
    right: -7px;
    top: 50%;
    background-color: #FFFFFF;
    border-radius: 50%;
    margin-top: -7px;
    border: 1px solid #2E9DC8;
    cursor: pointer;
}

.bf-section-container .ui-slider .ui-slider-handle {
    position: absolute;
    left: 0 !important;
    top: -28px;
    color: #696969;
    text-decoration: none;
    outline: none;
}

/**
 * 2.8. =>Ajax Select
 **************************************************************/
.bf-ajax_select-field-container {
    position: relative;
}

.bf-ajax_select-field-container input {
    background-color: #fff;
    line-height: 34px;
    border: 1px solid #d9d9d9;
    padding: 0px 36px 0 15px;
    box-shadow: none;
    margin: 0;
}

.bf-ajax_select-field-container span.bf-search-loader {
    position: absolute;
    right: 1px;
    top: 1px;
    border-left: 1px solid #d9d9d9;
    background-color: #fff;
    width: 34px;
    height: 34px;
    text-align: center;
    line-height: 34px;
    color: #7C7C7C;
    font-size: 12px;
    font-weight: bold;
    z-index: 10;
}

.bf-ajax_select-field-container input[type=text] {
    height: 36px !important;
}

.bf-ajax_select-field-container span.bf-search-loader.loader .fa:before {
    content: '\f021';
    -webkit-animation: spin 1.15s linear infinite;
    -moz-animation: spin 1.15s linear infinite;
    animation: spin 1.15s linear infinite;
}

.bf-ajax-suggest-search-results {
    display: none;
    position: absolute;
    top: 36px;
    left: 0px;
    z-index: 99;
    background: rgb(255, 255, 255);
    border: 1px solid rgb(206, 206, 206);
    width: 100%;
    max-height: 310px;
    overflow: auto;
    font-size: 13px;
    margin: -1px 0 0 0;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}

.bf-ajax-suggest-search-results > li {
    height: 35px;
    line-height: 35px;
    border-bottom: 1px solid #F8F8F8;
    margin-bottom: 0;
    cursor: copy;
    padding: 0 10px;
}

.bf-ajax-suggest-search-results > li .del {
    display: none;
}

.bf-ajax-suggest-search-results > li:last-child {
    border-bottom: none;
}

.bf-ajax-suggest-search-results > li:hover {
    background-color: #fdffe6;
}

.bf-ajax-suggest-controls {
    padding: 0px;
    margin: 0;
}

.bf-ajax-suggest-controls > li {
    height: 27px;
    line-height: 27px;
    background: #F5F5F5;
    display: inline-block;
    padding: 0 8px 0 8px;
    margin: 9px 9px 9px 0;
    border: 1px solid #D0D0D0;
    cursor: pointer;
    vertical-align: middle;
    font-size: 13px;
    position: relative;
    -webkit-transition: border .3s ease;
    -moz-transition: border .3s ease;
    -o-transition: border .3s ease;
    transition: border .3s ease;
}

.bf-ajax-suggest-controls > li:hover {
    border: 1px solid #bababa;
}

.bf-ajax-suggest-controls > .ui-state-highlight {
    background-color: whiteSmoke;
    width: 90px;
    border: 1px solid #E2E2E2;
}

.bf-ajax-suggest-controls > li .del {
    margin-left: 8px;
    color: #D80000;
    font-weight: bold;
}

.bf-ajax-suggest-input {
    width: 100%;
}

/**
 * 2.9. =>Social Counter Sorter
 **************************************************************/
.bf-section-container.vc-input .bf-vc-sorter-list,
.better-social-counter-sorter .bf-sorter-list {
    margin: 3px 0;
}

.bf-section-container.vc-input .bf-vc-sorter-list li,
.better-social-counter-sorter .bf-sorter-list li {
    background-color: #ffffff;
    border: 1px dashed #e6e6e6;
    color: #d2d2d2;
    padding: 4px 7px;
    cursor: move;
    position: relative;
    min-height: 17px;
    font-size: 13px;
    -webkit-transition: all .3s ease;
    -moz-transition: all .3s ease;
    -o-transition: all .3s ease;
    transition: all .3s ease;
}

.bf-section-container.vc-input .bf-vc-sorter-list li input {
    margin: -5px 2px 0 5px;
}

.bf-section-container.vc-input .bf-vc-sorter-list li:after,
.better-social-counter-sorter .bf-sorter-list li:after {
    position: absolute;
    right: 7px;
    top: 4px;
    content: 'Disable';
    font-style: italic;
    color: #e0e0e0;
}

.bf-section-container.vc-input .bf-vc-sorter-list li.active-item,
.better-social-counter-sorter .bf-sorter-list li.active-item {
    background-color: #F7F7F7;
    border: 1px solid #CDCDCD;
    color: #8C8C8C;
}

.bf-section-container.vc-input .bf-vc-sorter-list li.placeholder-item,
.better-social-counter-sorter .bf-sorter-list li.placeholder-item {
    background-color: rgb(248, 246, 241);
    border-color: #f8b356;
}

.bf-section-container.vc-input .bf-vc-sorter-list li.placeholder-item:after,
.better-social-counter-sorter .bf-sorter-list li.placeholder-item:after {
    content: '';
}

.bf-section-container.vc-input .bf-vc-sorter-list li.active-item:after,
.better-social-counter-sorter .bf-sorter-list li.active-item:after {
    content: '';
}

.bf-section-container.vc-input .bf-vc-sorter-list li.disable-item label,
.bf-section-container.vc-input .bf-vc-sorter-list li.disable-item input,
.bf-section-container.vc-input .bf-vc-sorter-list li.disable-item,
.better-social-counter-sorter .bf-sorter-list li.disable-item label,
.better-social-counter-sorter .bf-sorter-list li.disable-item input,
.better-social-counter-sorter .bf-sorter-list li.disable-item {
    cursor: not-allowed;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

.bf-section-container.vc-input .input-desc {
    margin-top: 5px;
    font-size: 13px;
    color: #a0a0a0;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item {
    color: #fff;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-facebook {
    background-color: #4a639f;
    border-color: #4a639f;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-twitter {
    background-color: #59c8ff;
    border-color: #59c8ff;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-gplus,
.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-google {
    background-color: #D73D32;
    border-color: #D73D32;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-dribbble {
    background-color: #ea4c89;
    border-color: #ea4c89;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-delicious {
    background-color: #4a79ff;
    border-color: #4a79ff;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-soundcloud {
    background-color: #F50;
    border-color: #F50;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-github {
    background-color: #666666;
    border-color: #666666;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-behance {
    background-color: #3b63fc;
    border-color: #3b63fc;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-youtube {
    background-color: #cc181e;
    border-color: #cc181e;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-vimeo {
    background-color: #46a3e9;
    border-color: #46a3e9;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-instagram {
    background-color: #517FA4;
    border-color: #517FA4;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-linkedin {
    background-color: #0266a0;
    border-color: #0266a0;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-ok_ru {
    background-color: #ee8208;
    border-color: transparent;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-vk {
    background-color: #4E729A;
    border-color: #4E729A;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-vine {
    background-color: #00bf8f;
    border-color: #00bf8f;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-pinterest {
    background-color: #cb2027;
    border-color: #cb2027;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-flickr {
    background-color: #2f44db;
    border-color: #2f44db;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-steam {
    background-color: #666666;
    border-color: #666666;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-rss {
    background-color: #f97410;
    border-color: #f97410;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-forrst {
    background-color: #3b7140;
    border-color: #3b7140;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-mailchimp {
    background-color: #2c9ab7;
    border-color: #2c9ab7;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-envato {
    background-color: #82B440;
    border-color: #82B440;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-posts {
    background-color: #4397CB;
    border-color: #4397CB;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-comments {
    background-color: #36B672;
    border-color: #36B672;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-members {
    background-color: #CA7641;
    border-color: #CA7641;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-telegram {
    background-color: #179cde;
    border-color: #179cde;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-line {
    background-color: #00c400;
    border-color: #00c400;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-viber {
    background-color: #665cac;
    border-color: #665cac;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-bbm {
    background-color: black;
    border-color: black;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-appstore {
    background-color: black;
    border-color: black;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-android {
    background-color: #68b445;
    border-color: #68b445;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-tumblr {
    background-color: #36465d;
    border-color: #36465d;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-ok_ru {
    background-color: #e27e35;
    border-color: #e27e35;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-linkedin {
    background-color: #0266a0;
    border-color: #0266a0;
}

.better-social-counter-sorter .bf-sorter-list li.active-item.checked-item.item-snapchat {
    background-color: #fffc00;
    border-color: #fffc00;
    color: #000;
}

/**
 * 2.10. =>Image Select
 **************************************************************/

.bf-section-container .better-select-image {
    margin-bottom: 10px;
    -webkit-transition: all 0.2s ease;
    -moz-transition: all 0.2s ease;
    -ms-transition: all 0.2s ease;
    -o-transition: all 0.2s ease;
    transition: all 0.2s ease;
}

.bf-section-container .better-select-image.bf-opened .select-options .better-select-image-options,
.bf-section-container .better-select-image.bf-opened {
    box-shadow: 0 0px 13px rgba(51, 51, 51, 0.31);
}

.bf-section-container .better-select-image .select-label {
    padding-right: 8px;
    display: inline-block;
    font-style: italic;
}

.bf-section-container .better-select-image .select-options,
.bf-section-container .better-select-style {
    position: relative;
    width: 100%;
    background-color: #fff;
    display: inline-block;
    height: 36px;
    line-height: 36px;
    border: 1px solid #d9d9d9;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    cursor: pointer;
    -webkit-transition: all 0.2s ease;
    -moz-transition: all 0.2s ease;
    -ms-transition: all 0.2s ease;
    -o-transition: all 0.2s ease;
    transition: all 0.2s ease;
}

.bf-section-container .better-select-style {
    padding: 3px 13px;
    font-size: 13px;
    line-height: 28px;
}

.bf-section-container .better-select-image.bf-opened .select-options .selected-option {
    background-color: #fafafa;

}

.bf-section-container .better-select-image .select-options:after,
.bf-section-container .better-select-style:after {
    color: #aaa;
    content: '\f107';
    border: 0;
    background: 0 0;
    font-family: 'FontAwesome';
    text-align: center;
    font-size: 14px;
    font-weight: bold;
    font-style: normal;
    color: #7C7C7C;
    speak: none;
    display: block;
    padding: 0;
    text-indent: 0;
    position: absolute;
    right: -1px;
    top: -1px;
    width: 34px;
    height: 34px;
    border: 1px solid #d9d9d9;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-decoration: none !important;
    z-index: 3;
    -webkit-transition: all 0.2s ease;
    -moz-transition: all 0.2s ease;
    -ms-transition: all 0.2s ease;
    -o-transition: all 0.2s ease;
    transition: all 0.2s ease;
    line-height: 36px;
}

.bf-section-container .better-select-image:hover .select-options,
.bf-section-container .better-select-image.bf-opened .select-options {
    border-color: #C0C0C0;
}

.bf-section-container .better-select-image.bf-opened .select-options {
    z-index: 99;
}

.bf-section-container .better-select-image.bf-opened .select-options .better-select-image-options {
    border-color: #C0C0C0;
}

.bf-section-container .better-select-image:hover .select-options:after,
.bf-section-container .better-select-image.bf-opened .select-options:after {
    color: #757575;
    border-color: #C0C0C0;
}

.bf-section-container .better-select-image.bf-opened .select-options:after {
    content: '\f106';
}

.bf-section-container .better-select-image .select-options .selected-option {
    display: block;
    font-size: 13px;
    height: 34px;
    line-height: 35px;
    padding: 0 10px;
    background-color: #fff;
    z-index: 2;
    position: relative;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

.bf-section-container .better-select-image .select-options .better-select-image-options {
    background-color: #fafafa;
    border: 1px solid #999;
    position: absolute;
    top: 34px;
    left: -1px;
    right: -1px;
    padding: 0 10px;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    display: none;
    z-index: 1;
}

.bf-section-container .better-select-image.bf-opened .select-options .better-select-image-options {
    display: block;
    cursor: default;
}

.bf-section-container .better-select-image.bf-opened .select-options .better-select-image-options ul {
    margin: 15px 0 0 0;
}

.bf-section-container .better-select-image.bf-opened .select-options .better-select-image-options ul li {
    margin-bottom: 15px;
    width: 100%;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    padding: 5px;
    border: 1px solid #dddddd;
    -webkit-transition: all 0.3s ease;
    -moz-transition: all 0.3s ease;
    -ms-transition: all 0.3s ease;
    -o-transition: all 0.3s ease;
    transition: all 0.3s ease;
    text-align: center;
    background-color: #fff;
}

.bf-section-container .better-select-image.bf-opened .select-options .better-select-image-options ul li img {
    display: block;
    margin: 0 auto 5px auto;
    /* retina.js fixes for hidden images! */
    width: auto !important;
    height: auto !important;
}

.bf-section-container .better-select-image.bf-opened .select-options .better-select-image-options ul li:hover {
    border-color: #c5c5c5;
}

.bf-section-container .better-select-image.bf-opened .select-options .better-select-image-options ul li.selected {
    border-color: #0074a2;
}

/* 2 Column Style */
.bf-section-container .better-select-image.bf-opened .select-options .better-select-image-options ul.grid-2-column li {
    width: 48%;
    float: left;
}

.bf-section-container .better-select-image.bf-opened .select-options .better-select-image-options ul.grid-2-column li:nth-child(odd) {
    margin-right: 4px;
}

.bf-section-container .better-select-image.bf-opened .select-options .better-select-image-options ul.grid-2-column li:nth-child(even) {
    margin-left: 4px;
}

/* 3 Column Style */
.bf-section-container .better-select-image.bf-opened .select-options .better-select-image-options ul.grid-3-column li {
    width: 32.43%;
    float: left;
}

.bf-section-container .better-select-image.bf-opened .select-options .better-select-image-options ul.grid-3-column li:nth-child(3n-1) {
    margin-right: 4px;
    margin-left: 4px;
}

/* 4 Column Style */
.bf-section-container .better-select-image.bf-opened .select-options .better-select-image-options ul.grid-4-column li {
    width: 32.43%;
    float: left;
}

.bf-section-container .better-select-image.bf-opened .select-options .better-select-image-options ul.grid-4-column li {
    margin-right: 4px;
    width: 23.9%;
    float: left;
}

.bf-section-container .better-select-image.bf-opened .select-options .better-select-image-options ul.grid-4-column li:nth-child(16),
.bf-section-container .better-select-image.bf-opened .select-options .better-select-image-options ul.grid-4-column li:nth-child(8),
.bf-section-container .better-select-image.bf-opened .select-options .better-select-image-options ul.grid-4-column li:nth-child(4) {
    margin-right: 0px;
}

/**
 * 2.11. =>Icon Select
 **************************************************************/
.bf-section-container .bf-icon-modal-handler {
    margin-bottom: 10px;
    position: relative;
    width: 100%;
}

.bf-section-container .bf-icon-modal-handler .select-options {
    margin: 0;
    box-shadow: none;
    width: 100%;
    margin: 0;
    border: 1px solid #d6d6d6;
    color: #333333;
    padding: 3px 13px;
    pearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    -o-appearance: none;
    border: 1px solid #d9d9d9;
    box-sizing: border-box;
    -webkit-box-sizing: none;
    -moz-box-sizing: none;
    -o-box-sizing: none;
    display: block;
    font-size: 13px;
    outline: none;
    overflow: ellipsis;
    position: relative;
    text-indent: 0.01px;
    text-overflow: '';
    -webkit-text-overflow: none;
    -moz-text-overflow: none;
    -o-text-overflow: none;
    vertical-align: middle;
    z-index: 1;
    height: 34px;
    cursor: pointer;
    -webkit-transition: all 0.2s ease;
    -moz-transition: all 0.2s ease;
    -ms-transition: all 0.2s ease;
    -o-transition: all 0.2s ease;
    transition: all 0.2s ease;
}

.bf-section-container .bf-icon-modal-handler .select-options .selected-option {
    line-height: 27px;
}

.bf-section-container .bf-icon-modal-handler .select-options .selected-option .text-muted {
    color: #A9A9A9;
    font-style: italic;
    margin-left: 3px;
    display: inline-block;
}

.bf-section-container .bf-icon-modal-handler .select-options .selected-option .bf-icon {
    margin-right: 4px;
    min-width: 22px;
    height: 22px;
    line-height: 22px;
    display: inline-block;
    vertical-align: middle;
    text-align: left;
}

.bf-section-container .bf-icon-modal-handler .select-options .selected-option .bf-icon img {
    max-height: 75% !important;
    vertical-align: top;
}

.bf-section-container .bf-icon-modal-handler .select-options:before {
    color: #aaa;
    content: "\f002";
    border: 0;
    background: #fff 0 0;
    font-family: 'FontAwesome';
    text-align: center;
    font-size: 12px;
    font-weight: normal;
    color: #7C7C7C;
    speak: none;
    display: block;
    padding: 0;
    text-indent: 0;
    position: absolute;
    right: 0px;
    top: 0px;
    width: 32px;
    height: 32px;
    border-left: 1px solid #d9d9d9;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-decoration: none !important;
    z-index: 3;
    -webkit-transition: all 0.2s ease;
    -moz-transition: all 0.2s ease;
    -ms-transition: all 0.2s ease;
    -o-transition: all 0.2s ease;
    transition: all 0.2s ease;
    font-style: normal;
    line-height: 32px;
}

.bf-section-container .bf-icon-modal-handler:hover .select-options:before,
.bf-section-container .bf-icon-modal-handler:hover .select-options {
    border-color: #C2C2C2;
}

/**
 * 2.12. =>Typography
 **************************************************************/
.bf-section-container .typography-desc {
    padding-bottom: 20px;
    color: #A8A8A8;
    font-size: 13px;
}

.bf-section-container .chosen-container {
    margin-bottom: 10px;
}

.bf-section-container .typo-field-container {
    width: 50%;
    margin-bottom: 14px;
    padding: 0 10px;
    float: left;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}

.bf-section-container .typo-field-container:before {
    top: 23px !important;
    right: 10px !important;
}

.bf-section-container .typo-field-container.font-family-container {
    width: 100%;
}

.bf-section-container .typo-field-container label {
    font-size: 13px;
    padding-bottom: 5px;
    display: inline-block;
    font-weight: bold;
}

.bf-section-container .bf-section.bf-section-typography-option .bf-heading {
    width: 100% !important;
    padding: 0 0 10px !important;
}

.bf-section-container .typo-field-container .bf-field-with-prefix input[type=text],
.bf-section-container .typo-field-container .bf-field-with-suffix input[type=text] {
    width: 72.5% !important;
}

.bf-section-container .typo-field-container .bf-field-with-prefix span,
.bf-section-container .typo-field-container .bf-field-with-suffix span {
    width: 20% !important;
    padding: 0 4%;
    text-align: center;
    z-index: 10;
    position: relative;
}

.bf-section-container .typo-field-container .bf-field-with-prefix span {
    border-right: 1px solid #d9d9d9;
}

.bf-section-container .typo-field-container .bf-field-with-suffix span {
    border-left: 1px solid #d9d9d9;
}

.bf-section-container .typo-enable-container {
    margin-bottom: 10px;
}

.bf-section-container .bf-controls-typography-option .bf-color-picker-container {
    width: 100% !important;
}

.bf-section-container .load-preview-texts {
    padding: 0 20px;
    width: 120px;
    display: block;
    margin: 25px auto 0 auto;
    background-color: #f4f4f4;
    font-size: 13px;
    text-align: center;
    height: 30px;
    line-height: 30px;
    text-decoration: none;
    color: #8e8e8e;
    border-radius: 5px;
}

.bf-section-container .load-preview-texts:hover {
    color: #525252;
}

.bf-section-container .typography-preview {
    display: none;
    color: #333;
    font-size: 16px;
    -webkit-font-smoothing: all;
    font-smoothing: all;
    -webkit-font-smoothing: antialiased;
    font-smoothing: antialiased;
}

.bf-section-container .typography-preview .preview-text {
    display: none;
}

.bf-section-container .typography-preview .preview-text.current {
    display: block;
    line-height: 1.34;
}

.bf-section-container .typography-preview .preview-tab {
    padding: 0;
    margin: 0 0 15px 0;
    border-bottom: 1px solid #bababa;
}

.bf-section-container .typography-preview .preview-tab .tab {
    padding: 0;
    margin: 0;
    float: left;
    margin-bottom: -1px;
}

.bf-section-container .typography-preview .preview-tab .tab a {
    padding: 0 10px;
    height: 34px;
    line-height: 34px;
    border: 1px solid #d3d3d3;
    border-bottom: none;
    border-right: none;
    font-size: 13px;
    font-weight: bold;
    color: #8d8d8d;
    text-decoration: none;
    display: block;
    background-color: #fafafa;
    outline: none;
    box-shadow: none;
}

.bf-section-container .typography-preview .preview-tab .tab.current {
    margin-bottom: -1px;
}

.bf-section-container .typography-preview .preview-tab .tab.current a {
    color: #333;
    padding-bottom: 1px;
    border-color: #a8a8a8 !important;
    background-color: #fff;
}

.bf-section-container .typography-preview .preview-tab .tab:last-child a {
    border-right: 1px solid #d3d3d3;
}

.bf-section-container .typography-preview .preview-tab .tab:first-child a {
}

.bf-section-typography-option.have-enable-field .typo-fields-container,
.bf-section-typography-option.have-enable-field .bf-explain {
    position: relative;
}

.bf-section-typography-option.have-enable-field.disable-field .enable-disable,
.bf-section-typography-option.have-enable-field.disable-field .bf-explain:before {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    background-color: #fff;
    background-color: rgba(255, 255, 255, 0.65);
    display: block;
    content: "";
    z-index: 99;
}

.typo-field-container .chosen-container .chosen-results li.group-result {
    display: list-item;
    font-weight: 700;
    cursor: default;
    background: #2D9EC7;
    border: 1px solid #0074A2;
    color: #fff;
    padding: 8px 11px;
    font-size: 13px;
    margin-top: 10px;
}

.typo-field-container .chosen-single {
    border-radius: 0px;
    background: #fff;
    margin: 0;
    box-shadow: none;
    width: 100%;
    margin: 0;
    border: 1px solid #d6d6d6;
    color: #333333;
    padding: 3px 13px;
    pearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    -o-appearance: none;
    border: 1px solid #d9d9d9;
    box-sizing: border-box;
    -webkit-box-sizing: none;
    -moz-box-sizing: none;
    -o-box-sizing: none;
    display: block;
    font-size: 13px;
    outline: none;
    overflow: ellipsis;
    position: relative;
    text-indent: 0.01px;
    text-overflow: '';
    -webkit-text-overflow: none;
    -moz-text-overflow: none;
    -o-text-overflow: none;
    vertical-align: middle;
    z-index: 1;
    height: 34px;
}

.typo-field-container .chosen-container-single .chosen-single div {
    border-left: 1px solid #D6D6D6;
    padding: 0 7px;

    min-width: 35px;
    box-sizing: border-box;
}

.typo-field-container .chosen-container-single.chosen-rtl .chosen-single div {
    border-left: none;
    border-right: 1px solid #D6D6D6;
    left: 0;
}

.typo-field-container .chosen-container-single .chosen-single div b {
    background-position: 5px 6px;
}

.typo-field-container .chosen-container-single.chosen-with-drop .chosen-single div b {
    background-position: -13px 6px;
}

.typo-field-container .chosen-rtl .chosen-search input[type=text] {
    height: 28px !important;
}

.typo-field-container .bs-color-picker-wrapper .wp-color-result {
    height: 32px;
}

.typo-field-container .bs-color-picker-wrapper .wp-color-result:after {
    line-height: 32px;
}

/**
 * 2.13. =>Social Share Sorter
 **************************************************************/
.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list {
    margin: 3px 0;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li {
    background-color: #ffffff;
    color: #d2d2d2;
    padding: 0 12px;
    cursor: move;
    position: relative;
    font-size: 13px;
    min-height: 28px;
    line-height: 28px;
    margin-right: 10px;
    min-width: 130px;
    max-width: 230px;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    border: none;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li {
    width: 200px;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.active-item {
    border: none;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.active-item:after {
    content: '';
    display: none;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li {
    background-color: #bababa;
    color: #5c5c5c;
    -webkit-transition: background-color .3s ease;
    -moz-transition: background-color .3s ease;
    -o-transition: background-color .3s ease;
    transition: background-color .3s ease;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li .bf-icon,
.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li .fa,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li .bf-icon,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li .fa {
    margin-right: 5px;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item {
    color: #fff;
    background: #2D9DCD;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter li.checked-item#bf-sorter-group-item-sites-facebook,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-facebook {
    background-color: #4a639f;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-facebook:hover,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-facebook:hover {
    background-color: #5271b3;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter li.checked-item#bf-sorter-group-item-sites-wordpress,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-wordpress {
    background-color: #0073aa;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-wordpress:hover,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-wordpress:hover {
    background-color: #1083aa;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter li.checked-item#bf-sorter-group-item-sites-disqus,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-disqus {
    background-color: #2e9fff;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-disqus:hover,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-disqus:hover {
    background-color: #3eafff;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-twitter,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-twitter {
    background-color: #59c8ff;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-twitter:hover,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-twitter:hover {
    background-color: #58d1ff;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-google_plus,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-google_plus {
    background-color: #D73D32;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-sorter-list li.checked-item#bf-sorter-group-item-sites-google_plus:hover,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-google_plus:hover {
    background-color: #e64035;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-pinterest,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-pinterest {
    background-color: #cb2027;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-pinterest:hover,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-pinterest:hover {
    background-color: #e32229;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-linkedin,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-linkedin {
    background-color: #0266a0;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-linkedin:hover,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-linkedin:hover {
    background-color: #027ec1;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-tumblr,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-tumblr {
    background-color: #3e5a70;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-tumblr:hover,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-tumblr:hover {
    background-color: #426283;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-email,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-email {
    background-color: #0c151c;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-email:hover,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-email:hover {
    background-color: #152430;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-print,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-print {
    background-color: #0c151c;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-print:hover,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-print:hover {
    background-color: #152430;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter li.checked-item#bf-sorter-group-item-sites-telegram,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-telegram {
    background-color: #179cde;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-telegram:hover,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-telegram:hover {
    background-color: #179cde;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter li.checked-item#bf-sorter-group-item-sites-whatsapp,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-whatsapp {
    background-color: #00ca65;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-whatsapp:hover,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-whatsapp:hover {
    background-color: #00b65b;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter li.checked-item#bf-sorter-group-item-sites-line,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-line {
    background-color: #00b900;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-line:hover,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-line:hover {
    background-color: #008900;
}

.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.item-line .bsfi-line {
    font-size: 18px;
}

.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.item-line .bsfi-bbm:before,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.item-line .bsfi-viber:before,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.item-line .bsfi-line:before {
    vertical-align: middle;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter li.checked-item#bf-sorter-group-item-sites-bbm,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-bbm {
    background-color: #0e0e0e;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-bbm:hover,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-bbm:hover {
    background-color: #373737;
}

.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.item-bbm .fa.fa-bbm {
    font-size: 18px;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter li.checked-item#bf-sorter-group-item-sites-viber,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-viber {
    background-color: #5d54a4;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-viber:hover,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-viber:hover {
    background-color: #424181;
}

.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.item-viber .fa.fa-viber {
    font-size: 18px;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter li.checked-item#bf-sorter-group-item-sites-reddit,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-reddit {
    background-color: #dc3c01;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-reddit:hover,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-reddit:hover {
    background-color: #c43501;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter li.checked-item#bf-sorter-group-item-sites-stumbleupon,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-stumbleupon {
    background-color: #ee4813;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-stumbleupon:hover,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-stumbleupon:hover {
    background-color: #c13b10;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter li.checked-item#bf-sorter-group-item-sites-vk,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-vk {
    background-color: #4c75a3;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-vk:hover,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-vk:hover {
    background-color: #415f84;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter li.checked-item#bf-sorter-group-item-sites-ok-ru,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-ok-ru {
    background-color: #cb6e04;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-ok-ru:hover,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-ok-ru:hover {
    background-color: #b55c04;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter li.checked-item#bf-sorter-group-item-sites-digg,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-digg {
    background-color: #000;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li.checked-item#bf-sorter-group-item-sites-digg:hover,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.checked-item.item-digg:hover {
    background-color: #121212;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter li.placeholder-item,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.placeholder-item {
    background-color: rgb(226, 226, 226);
    border: 1px dashed #a8a8a8;
}

.bf-section-container.vc-input.bs-theme-social-share-sorter li.placeholder-item:after,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.placeholder-item:after {
    content: '';
}

.bf-section-container.vc-input.bs-theme-social-share-sorter li input,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li input {
    margin-right: 10px;
    outline: none;
}

/**
 * 2.14. =>Repeater Item
 **************************************************************/
.bf-repeater-item {
    position: relative;
    background-color: #F5F5F5;
    border: 1px solid #E2DDDB;
    margin-bottom: 15px;
}

.bf-section-repeater-option > .bf-explain {
    margin-bottom: 15px;
}

.bf-repeater-item .bf-remove-repeater-item-btn {
    float: right;
    font-size: 11px;
    color: #a00;
    cursor: pointer;
}

.bf-repeater-item .bf-remove-repeater-item-btn:hover {
    color: red;
}

.bf-repeater-item .bf-remove-repeater-item-btn .dashicons {
    font-size: 15px;
    line-height: 15px;
    vertical-align: middle;
}

.bf-repeater-item .bf-remove-repeater-item-btn .dashicons:before {
    content: "\f182";

}

/* repeator item container */
.bf-repeater-item .repeater-item-container {
    padding: 17px;
    background-color: #FFF;
}

.bf-repeater-item .repeater-item-container .bf-section:last-child {
    margin-bottom: 0;
}

/* repeator item title */
.bf-repeater-item .bf-repeater-item-title {
    position: relative;
    height: 40px;
    padding: 0 55px 0 15px;
    line-height: 40px;
    border-bottom: 1px solid #E2DDDB;
    font-weight: bold;
}

.bf-repeater-item .bf-repeater-item-title h5 {
    margin: 0;
    font-weight: bold;
    font-size: .83em;
    display: block;
    line-height: 40px;
    color: #444;
}

/* repeater item handle */
.bf-repeater-item .bf-repeater-item-title .handle-repeater-item {
    float: right;
    height: 40px;
    width: 40px;
    text-align: center;
    display: inline-block;
    vertical-align: middle;
    cursor: pointer;
    position: absolute;
    right: -1px;
    top: -1px;
    border: 1px solid #E2DDDB;
}

.bf-repeater-item .bf-repeater-item-title .handle-repeater-item:before {
    display: inline-block;
    font: normal normal normal 14px/1 FontAwesome;
    font-size: inherit;
    text-rendering: auto;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    display: inline-block;
    padding: 9px 10px;
    top: 0;
    position: relative;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-decoration: none !important;
    content: "\f068";
}

.bf-repeater-item .bf-repeater-item-title .handle-repeater-item.bf-closed:before {
    content: "\f067";
}

/**
 * 2.15. =>Border
 **************************************************************/
.bf-section-container .single-border {
    margin-bottom: 10px;
    padding-bottom: 10px;
    border-bottom: 1px solid #eee;
}

.bf-section-container .single-border:last-child {
    margin-bottom: 0;
    border-bottom: none;
}

.bf-section-container .single-border .border-label {
    min-width: 100px;
    font-size: 13px;
    display: inline-block;
    color: #7C7C7C;
}

.bf-section-container .single-border input[type=text] {
    width: 37px;
    vertical-align: middle;
}

.bf-section-container .single-border select {
    width: 90px;
}

.bf-section-container .single-border input.bf-color-picker {
    width: 100px;
}

.bf-section-container .single-border .bf-field-with-suffix {
    margin-bottom: 0;
}

.bf-section-container .single-border .bf-color-picker-preview {
    top: 7px;
}

.bf-section-container .border-preview {

}

.bf-section-container .border-preview .preview-box {
    width: 120px;
    height: 110px;
    display: block;
    margin: 15px auto;
    border: 1px solid #eee;
}

/**
 * 2.16. =>Info
 **************************************************************/
.bf-section-container .bf-section-info {
    background-color: #eee;
    border: 1px solid #e0e0e0;
    margin-top: 10px;
}

.bf-section-container .bf-section-info .bf-section-info-title {
    padding: 15px 20px;
    background-color: #e8e8e8;
    border-bottom: 1px solid #e0e0e0;
}

.bf-section-container .bf-section-info .bf-section-info-title h3 {
    padding: 0 !important;
    margin: 0 !important;
    font-size: 13px !important;
    border: none;
}

.bf-section-container .bf-section-info .bf-section-info-title .fa {
    margin-right: 3px;
}

.bf-section-container .bf-section-info .bf-controls-info-option {
    padding: 20px;
}

.bf-section-container .bf-section-info .info-value {
    font-size: 13px;
}

.bf-section-container .bf-section-info .info-value img {
    max-width: 100%;
    height: auto;
}

.bf-section-container .bf-section-info .info-value p {
    margin: 0 0 7px 0;
}

.bf-section-container .bf-section-info .info-value ul {
    list-style: disc;
    padding-left: 20px;
    margin: 0 0 10px 0;
}

.bf-section-container .bf-section-info .info-value ol {
    list-style: decimal;
    padding-left: 20px;
    margin: 0 0 10px 0;
}

.bf-section-container .bf-section-info .info-value a {
    text-decoration: underline;
}

.bf-section-container .bf-section-info.help,
.bf-section-container .bf-section-info.info {
    background-color: #EFFAFF;
    border-color: #bce8f1;
    color: #31708f;
}

.bf-section-container .bf-section-info.help .bf-section-info-title,
.bf-section-container .bf-section-info.info .bf-section-info-title {
    background-color: #E2F5FD;
    border-color: #bce8f1;
    color: #31708f;
}

.bf-section-container .bf-section-info.help .bf-section-info-title h3,
.bf-section-container .bf-section-info.info .bf-section-info-title h3 {
    color: #31708f;
}

.bf-section-container .bf-section-info.warning {
    background-color: #FFFDF4;
    border-color: #F1E0BD;
    color: #8a6d3b;
}

.bf-section-container .bf-section-info.warning .bf-section-info-title {
    background-color: #fcf8e3;
    border-color: #F1E0BD;
    color: #8a6d3b;
}

.bf-section-container .bf-section-info.warning .bf-section-info-title h3 {
    color: #8a6d3b;
}

.bf-section-container .bf-section-info.danger {
    background-color: #FFF4F4;
    border-color: #E9BBC2;
    color: #a94442;
}

.bf-section-container .bf-section-info.danger .bf-section-info-title {
    background-color: #FFE4E4;
    border-color: #ebccd1;
    color: #a94442;
}

.bf-section-container .bf-section-info.danger .bf-section-info-title h3 {
    color: #a94442;
}

/**
 * 2.17. =>Switch
 **************************************************************/
.bf-switch {
    margin: 0;
    color: #fff;
    padding: 2px;
    border: 1px solid #D9D9D9;
    height: 34px;
    display: inline-block;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    border-radius: 33px;
}

.bf-switch .cb-enable,
.bf-switch .cb-disable,
.bf-switch .cb-enable span,
.bf-switch .cb-disable span {
    display: block;
    float: left;
}

.bf-switch .cb-disable span {
    border-radius: 0 33px 33px 0;
}

.bf-switch .cb-enable span {
    border-radius: 33px 0 0 33px;
}

.bf-switch .cb-enable span,
.bf-switch .cb-disable span {
    line-height: 26px;
    display: block;
    font-style: normal;
    font-weight: bold;
    padding: 0 10px;
    font-size: 13px;
    -webkit-transition: all .15s ease;
    -moz-transition: all .15s ease;
    -o-transition: all .15s ease;
    transition: all .15s ease;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    color: #BEBEBE;
    background-color: #F4F4F4;
    border: 1px solid #ECECEC;
}

.bf-switch .cb-enable span {
    border-right-color: transparent;
    -webkit-transition: all .3s ease;
    -moz-transition: all .3s ease;
    -o-transition: all .3s ease;
    transition: all .3s ease;
}

.bf-switch .cb-enable:hover span {
    border-color: #A3CDA4;
    color: #64BD65;
    border-right-color: transparent;
}

.bf-switch .cb-disable span {
    border-left-color: transparent;
    -webkit-transition: all .3s ease;
    -moz-transition: all .3s ease;
    -o-transition: all .3s ease;
    transition: all .3s ease;
}

.bf-switch .cb-disable:hover span {
    border-color: #FF9090;
    color: #FF9090;
    border-left-color: transparent;
}

.bf-switch .cb-disable.selected:hover span,
.bf-switch .cb-disable.selected span {
    color: #FFFFFF;
    background: #FF9090;
    border-color: #F48080;
    text-shadow: 0px 1px 0 #EC7979;
}

.bf-switch .cb-enable.selected:hover span,
.bf-switch .cb-enable.selected span {
    background: #64BD65;
    color: #fff;
    border-color: #55AD56;
    text-shadow: 0px 1px 0 #499D4A;
}

.bf-switch label {
    cursor: pointer;
    padding: 0 !important;
}

.bf-switch input {
    display: none;
}

/**
 * 2.18. =>Fields Group
 **************************************************************/
.fields-group {
    border: 1px solid #D3D3D3;
    margin-bottom: 25px;
    margin-top: 25px;
}

.fields-group:first-child {
    margin-top: 4px;
}

.fields-group .fields-group-title-container {
    background-color: #F5F5F5;
    border-bottom: 1px solid #D3D3D3;
    padding: 0;
    position: relative;
    height: 40px;
    line-height: 40px;
}

.fields-group .fields-group-title-container .fields-group-title {
    font-size: 15px;
    color: #222222;
    font-weight: bold;
    display: block;
    padding: 0 62px 0 20px;
}

.fields-group.collapsible .fields-group-title-container .fields-group-title {
    cursor: pointer;
}

.fields-group.collapsible .fields-group-title-container .collapse-button {
    width: 40px;
    height: 100%;
    line-height: 39px;
    text-align: center;
    font-size: 14px;
    font-weight: bold;
    color: #7C7C7C;
    display: inline-block;
    padding: 0;
    position: absolute;
    right: -1px;
    top: -1px;
    border: 1px solid #d9d9d9;
    -webkit-transition: all 0.2s ease;
    -moz-transition: all 0.2s ease;
    -ms-transition: all 0.2s ease;
    -o-transition: all 0.2s ease;
    transition: all 0.2s ease;
    cursor: pointer;
}

.fields-group.collapsible .fields-group-title-container:hover .collapse-button {
    color: #222222;
}

.fields-group.collapsible .bf-group-inner {
    padding-top: 5px;
    padding-bottom: 5px;
}

.fields-group.collapsible .bf-group-desc {
    padding: 15px 20px;
    color: #939393;
    font-size: 13px;
}

.bf-group-inner .fields-group {
    margin-left: 20px;
    margin-right: 20px;
    margin-top: 15px;
}

/* Blue Style */
.fields-group.blue {
    border-color: #bce8f1;
}

.fields-group.blue .fields-group-title-container .fields-group-title {
    color: #31708f;
}

.fields-group.blue .fields-group-title-container {
    background-color: #E2F5FD;
    border-color: #bce8f1;
}

/* Green Style */
.fields-group.green {
    border-color: #8BE8A9;
}

.fields-group.green .fields-group-title-container .fields-group-title {
    color: #409D5E;
}

.fields-group.green .fields-group-title-container {
    background-color: #C5F7D5;
    border-color: #8BE8A9;
}

.fields-group.bf-widgets .fields-group-title-container {
    height: 40px;
    line-height: 40px;
}

.fields-group.bf-widgets .fields-group-title-container .fields-group-title {
    font-size: 13px;
}

.fields-group.bf-widgets .fields-group-title-container .collapse-button {
    line-height: 41px;
}

.fields-group.bf-widgets .bf-group-inner {
    padding: 5px 15px;
}

.fields-group.bf-widgets .bf-group-inner .bf-section-container:last-child .bf-explain {
    margin-bottom: 10px;
}

/**
 * 2.19. =>Media
 **************************************************************/
.bf-section-container .bf-section.bf-section-media-option .bf-controls input[type=text] {
    width: 65%;
    float: left;
}

.bf-section-container .bf-section.bf-section-media-option .bf-controls .bf-media-upload-btn {
    float: right;
    text-align: center;
}

/**
 * 2.20. =>Code Editor
 **************************************************************/
.bf-editor {
    margin: 0 0 10px;
}

.ace_editor {
    direction: ltr;
    text-align: left;
}

/**
 *   2.21. =>Custom Checkbox/Radio Field
 **************************************************************/
.bf-checkbox-multi-state,
.bf-radio-field {
    width: 18px;
    height: 18px;
    border: 1px solid #d0d0d0;
    overflow: hidden;
    background: #fff;
    margin: 0 5px 0 0;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    text-align: center;
    display: inline-block;
    vertical-align: middle;
    position: relative;
    cursor: pointer;
}

.bf-checkbox-multi-state > span,
.bf-radio-field > span {
    display: none;
    cursor: pointer;
    position: absolute;
    top: 0;
    right: 0;
    left: 0;
    width: 18px;
    line-height: 18px;
    height: 18px;
    text-align: center;
}

.bf-checkbox-multi-state .fa,
.bf-radio-field .fa {
    font-size: 15px;
    font-weight: normal;
    display: inline-block;
}

.bf-checkbox-multi-state[data-current-state="active"] .fa,
.bf-checkbox-multi-state[data-current-state="active"] + .label,
.bf-radio-field .active .fa,
.bf-radio-field .active + .label {
    color: #459d45;
}

.bf-radio-field [data-current-state="deactivate"] .fa,
.bf-checkbox-multi-state[data-current-state="deactivate"] + .label {
    color: #e74141;
}

.bf-checkbox-multi-state[data-current-state="active"] + .label,
.bf-radio-field .active + .label {
    font-family: 'Open Sans';
    font-size: 14px;
    font-weight: 600;
}

.bf-radio-field {
    border-radius: 10px;
}

.bf-radio-field .fa {
    font-size: 12px;
    color: #444;
    width: 10px;
    height: 10px;
    line-height: 12px;
    text-align: center;
    position: absolute;
    top: 50%;
    margin-top: -6px;
    left: 50%;
    margin-left: -6px;
    background: #444;
    border-radius: 50%;
    overflow: hidden;
}

.bf-radio-toggle {
    cursor: pointer;
}

/**
 *   2.22. =>Term Select Field Style
 **************************************************************/
.bf-field-term-select-help {
    padding: 6px 10px;
    text-align: left;
    color: #969696;
    font-size: 13px;
    font-style: italic;
}

.bf-field-term-select-help .active-state {
    color: #459d45;
}

.bf-field-term-select-help .deactivate-state {
    color: #e74141;
}

.bf-field-term-select-help .bf-checkbox-multi-state {
    margin: 0 0 0 9px;
}

.bf-field-term-select-wrapper.loading {
    text-align: center;
}

.bf-field-term-select-wrapper {
    border: 1px solid #dcdcdc;
    padding: 3px 10px 0px 0;
    background: #fbfbfb;
    max-height: 190px;
    overflow-y: scroll;
}

.bf-field-term-select-wrapper ul,
.bf-field-term-select-wrapper li {
    list-style: none;
    position: relative;
}

.bf-field-term-select-wrapper li {
    margin-bottom: 11px;
}

.bf-field-term-select-wrapper li:before {
    content: ' ';
    height: 1px;
    background: #cecece;
    position: absolute;
    left: -22px;
    top: 7px;
    width: 13px;
}

.bf-field-term-select-wrapper li li:last-child:after {
    content: ' ';
    height: 100%;
    background: #fbfbfb;
    position: absolute;
    left: -32px;
    top: 8px;
    width: 20px;
}

.bf-field-term-select-wrapper ul {
    border-left: 1px solid #CECECC;
    padding: 0 0 0 22px;
}

.bf-field-term-select-wrapper > ul {
    border-width: 0;
}

.bf-field-term-select-wrapper ul ul {
    margin-left: 9px;
    padding-top: 6px;
}

.bf-field-term-select-wrapper li .label {
    color: #444;
}

.bf-field-term-select-wrapper .bf-make-term-primary,
.bf-field-term-select-wrapper .bf-excluded-term {
    font-style: italic;
    color: #3c3c3c;
    font-size: 13px;
    margin-left: 15px;
    position: relative;
    opacity: 0.8;
}

.bf-field-term-select-wrapper .bf-excluded-term {
    opacity: 0.6;
}

.bf-field-term-select-wrapper .bf-make-term-primary:before,
.bf-field-term-select-wrapper .bf-excluded-term:before {
    margin-right: 10px;
    content: ' ';
    height: 1px;
    width: 20px;
    background: #cecece;
    display: inline-block;
    position: relative;
    top: -4px;
}

.bf-field-term-select-wrapper span.label .bf-make-term-primary {
    display: none;
}

.bf-field-term-select-wrapper.bf-field-term-show-primary-label
span.label[data-status="active"] .bf-make-term-primary {
    display: inline-block;
}

.bf-field-term-select-deferred {
    min-height: 150px;
}

/**
* 2.23. =>Selector Modal
 **************************************************************/
.bssm-list {
    list-style: none;
    padding: 20px 0 20px 20px;
    font-family: Open Sans;

    max-height: 540px;
    overflow-y: auto;
    position: relative;

    font-size: 0;
    display: inline-block;
    margin: 0;
}

.bssm-item {
    display: inline-block;
    width: 242px;
    text-align: left;
    margin: 0 15px 15px 0;
}

.two-column .bssm-item {
    width: 374px;
}

.two-column .bssm-item .bf-item-container figure {
    min-height: 272px;
}

.four-column .bssm-item {
    width: 180px;
}

.four-column .bssm-item .bf-item-container figure {
    min-height: 130px;
}

.one-column .bssm-item {
    width: auto;
}

.one-column .bssm-item .bf-item-container {
    max-width: 760px;
}

.one-column .bssm-item .bf-item-container figure {
    min-height: 100px;
}

.bssm-style-1 .bssm-item {
    padding: 0;
    margin: 0 22px 22px 0;
    background: #fff;
    border: 1px solid #cecece;
    -webkit-border-radius: 3px;
    -moz-border-radius: 3px;
    border-radius: 3px;
    width: 237px;

    -webkit-transition: all .6s ease;
    -moz-transition: all .6s ease;
    -o-transition: all .6s ease;
    transition: all .6s ease;

    -webkit-box-shadow: 0 1px 1px -1px rgba(0, 0, 0, .1);
    box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.1);

    position: relative;

    cursor: pointer;
}

.bssm-item .bf-item-badges {
    position: absolute;
    top: 0;
    right: 0;
    line-height: 0;
}

.bssm-item .bf-item-badge {
    background: #d54e21;
    display: inline-block;
    padding: 2px 5px;
    color: #fff;
    font-size: 13px;
    font-weight: 700;
    border: 1px solid #d4d4d4;
    border-width: 0 0 1px 1px;
    line-height: 1.6;
}

.bssm-style-1 .bssm-item.bssm-selected,
.bssm-style-1 .bssm-item:not(.bssm-selected):hover {
    border: 1px solid #4c954f;
}

.bssm-style-1 .bssm-selected:before {
    content: '\f00c';
    display: inline-block;
    position: absolute;
    top: 0;
    right: 0;
    display: inline-block;
    color: #fff;
    font: normal normal normal 14px/1 FontAwesome;
    font-size: inherit;
    text-rendering: auto;
    background: #5ca65f;
    border-radius: 0 0 0px 3px;
    padding: 7px;
    -webkit-font-smoothing: antialiased;
    font-size: 12px;
    -moz-osx-font-smoothing: grayscale;
}

.bssm-style-1 .bssm-preview {
    color: #212121;
    font-weight: normal;
    font-size: 22px;
    padding: 13px 13px;
    height: 106px;
    overflow: hidden;
    line-height: 26px;
}

.bssm-style-1 .bssm-info {
    background: #f9f9f9;
    border-top: 1px solid #ddd;
    padding: 13px 13px;
    -webkit-border-radius: 0 0 3px 3px;
    -moz-border-radius: 0 0 3px 3px;
    border-radius: 0 0 3px 3px;
    text-align: left;
    line-height: 0;
}

.bssm-style-1 .bssm-info,
.bssm-style-1 .bssm-info > span {
    -webkit-transition: all .6s ease;
    -moz-transition: all .6s ease;
    -o-transition: all .6s ease;
    transition: all .6s ease;
}

.bssm-selected .bssm-info {
    background: #5ca65f;
    color: #fff;
    border-color: #4c954f;
}

.bssm-style-1 .bssm-item:hover .bssm-info {
    color: #4c954f;
    border-color: #4c954f;
}

.bssm-style-1 .bssm-info > .bssm-name {
    color: #424242;
    font-size: 14px;
    display: block;
    line-height: 14px;
    height: 18px;
    width: 150px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    margin-bottom: 3px;
    font-weight: 600;
}

.bssm-style-1 .bssm-info > .bssm-type {
    color: #ababab;
    font-size: 11px;
    line-height: 11px;
    display: inline-block;
}

.bssm-style-1 .bssm-info > .bssm-styles {
    color: #ababab;
    font-size: 11px;
    line-height: 11px;
    float: right;
}

.bssm-style-1 .bssm-item:hover .bssm-name,
.bssm-style-1 .bssm-item:hover .bssm-type,
.bssm-style-1 .bssm-item:hover .bssm-styles {
    color: #4c954f !important;
}

.bssm-style-1 .bssm-item.bssm-selected .bssm-name,
.bssm-style-1 .bssm-item.bssm-selected .bssm-type,
.bssm-style-1 .bssm-item.bssm-selected .bssm-styles {
    color: #fff !important;
}

.bssm-item:nth-child(3n) {
    margin-right: 0;
}

body.rtl .bssm-item:nth-child(3n) {
    margin-left: 0;
}

.bssm-content {
    background: #eee;
    margin-right: 260px;
    height: 540px;
}

.bs-modal.no-sidebar .bssm-content {
    margin-right: 0;
}

.bs-modal.no-sidebar .bssm-sidebar {
    display: none;
}

.bs-selector-modal .bs-modal-header-wrapper {
    color: #4d4d4d;
    border-bottom: 1px solid #d8d8d8;
}

.bs-selector-modal .bs-modal-header-wrapper:after {
    display: none;
}

.bs-selector-modal .bs-modal-heade {
    height: 50px;
}

.bs-selector-modal .bs-modal-body {
    overflow: hidden;
    padding: 0;
    position: relative;
}

/**
* 2.24. =>Pre Defined Styles Modal
 **************************************************************/
.pds-modal .bf-btn-secondary {
    font-size: 13px;
}

.pds-modal .bf-btn-secondary.disabled,
.pds-modal .bf-btn-secondary[disabled] {
    color: #bbb;
    border-color: #ddd;
    pointer-events: none;
}

.pds-modal .bf-btn-primary {
    font-size: 13px;
    font-weight: normal;
}

.pds-modal .bf-btn-primary.disabled {
    pointer-events: none;
}

.pds-modal .bf-item-title {
    padding: 9px 0 9px 12px;
    font-size: 14px;
}

.pds-modal .bf-item-buttons > span {
    padding: 9px;
}

.pds-modal .bs-modal-header-wrapper:after {
    display: none;
}

.pds-modal .bs-modal-body {
    background: #eee;
    line-height: 1.66;
}

.pds-modal .bs-modal-bottom {
    background: #fff;
    border-width: 0;
}

.pds-modal .bs-modal-title {
    font-size: 15px;
}

.pds-modal .pdsm-notice {
    width: 50%;
    font-weight: bold;
    margin-top: 10px;
    /* clear: both; */
}

.pds-modal .bs-modal-image-caption {
    font-size: 15px;
    margin-top: 10px;
}

.pds-confirm-modal .bs-modal-body {
    line-height: 1.66;
}

/**
* 2.24. =>Pre Defined Styles Modal
 **************************************************************/
.select-popup-field {
    background: #fff;
    border: 1px solid #dedede;
    max-width: 370px;
    position: relative;
}

.select-popup-selected-image {
    width: 145px;
    max-width: 100%;
    float: left;
    position: relative;
    line-height: 0;
}

.select-popup-selected-image:before {
    position: absolute;
    height: 100%;
    right: 0;
    top: 0;

    width: 1px;
    background: #dbdbdb;
    content: ' ';
}

.select-popup-selected-image img {
    max-width: 100%;
    max-height: 130px;
    image-rendering: pixelated;
}

.select-popup-selected-info {
    float: left;
}

.select-popup-selected-image,
.select-popup-selected-info {
    padding: 6px;
    box-sizing: border-box;
}

.select-popup-field .button {
    box-shadow: none;
    background: #2D9ECE;
    border-color: #0074a2;
    color: #fff;
    font-weight: 500;

    -webkit-transition: all .3s ease;
    -moz-transition: all .3s ease;
    -o-transition: all .3s ease;
    transition: all .3s ease;
}

.select-popup-field .button:hover {
    background: #288baf;
    border-color: #00435f;
    color: #fff;
}

.select-popup-field .button:focus {
    outline: none;
}

.select-popup-field .active-item-text {
    color: #9d9d9d;
    font-size: 13px;
    font-weight: 300;
    margin-bottom: 10px;
}

.select-popup-field .active-item-label {
    color: #383838;
    font-weight: 700;
    font-size: 16px;
    margin-bottom: 15px;
}

/**
* Selector Modal Sidebar
*/
.bssm-sidebar {
    width: 260px;
    border-left: 1px solid #cecece;
    position: absolute;
    right: 0;
    top: 0;
    padding: 25px 20px;
    height: 100%;
    background: #fff;
    color: #353535;
    overflow-y: scroll;
}

.bssm-sidebar .title {
    color: #353535;
    font-size: 14px;
    display: block;
    position: relative;
    margin: 0 0 13px;
}

.bssm-sidebar .title span {
    background: #fff;
    padding-right: 12px;
    position: relative;
    z-index: 12;
}

.bssm-sidebar .title:after {
    content: ' ';
    width: 100%;
    height: 1px;
    background: #ebebeb;
    position: absolute;
    left: 0;
    top: 50%;
    z-index: 9;
}

.bssm-search {
    position: relative;
    display: inline-block;
    width: 100%;
    margin-bottom: 20px;
}

.bssm-search .fa {
    position: absolute;
    right: 14px;
    top: 10px;

    content: '\f002';

    display: inline-block;
    font: normal normal normal 14px/1 FontAwesome;
    font-size: inherit;
    text-rendering: auto;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    color: #bdbdbd;
}

.active.bssm-search .fa {
    cursor: pointer;
}

.bssm-search-input {
    border: 1px solid #c9c9c9;
    -webkit-box-shadow: inset 0 0 2px 0 #000;
    -moz-box-shadow: inset 0 0 2px 0 #000;
    box-shadow: inset 0 0 2px 0 #000;
    padding: 0 30px 0 18px;
    line-height: 28px;
    position: relative;
    font-size: 13px;
    border-radius: 23px;
    color: #858585;
    outline: none;
    width: 100%;
}

.bssm-search-input:active, .bssm-search-input:focus {
    border-color: #4c954f !important;
    box-shadow: none !important;
    -webkit-box-shadow: 0 0 2px rgba(76, 149, 79, 0.8) !important;
    box-shadow: 0 0 2px rgba(76, 149, 79, 0.8) !important;
}

.bssm-filter .bssm-categories,
.bssm-filter .bssm-types {
    margin-bottom: 25px;
}

.bssm-filter-items {
    list-style: none;
    margin: 0;
    padding: 0;
}

.bssm-filter-items .bf-checkbox-multi-state {
    display: inline-block;
}

.bs-selector-modal .bf-checkbox-multi-state[data-current-state="active"] .fa,
.bs-selector-modal .bf-checkbox-multi-state[data-current-state="active"] + .label {
    color: #353535;
    margin-left: 1px;
}

.bssm-filter li {
    position: relative;
    margin-bottom: 11px;
    line-height: 20px;
}

.bssm-filter li .name {
    vertical-align: middle;
    display: inline-block;
}

.bssm-filter .length {
    position: absolute;
    top: 0;
    right: 0;
    background: #fff;
    font-size: 12px;
    color: #a9a9a9;
}

.bssm-button {
    background: #5ca65f;
    color: #fff;
    border: 1px solid #4c954f;
    -webkit-border-radius: 19px;
    -moz-border-radius: 19px;
    border-radius: 19px;
    display: inline-block;
    line-height: 34px;
    padding: 0 20px;
    cursor: pointer;
    text-decoration: none;
    font-size: 13px;
}

.bssm-button.disabled {
    background: #e4e4e4;
    border-color: #DEDEE1;
    pointer-events: none;
    color: #909090;
}

.bssm-button:hover {
    background: #4f9852;
}

.bssm-button:hover {
    color: #fff;
    border-color: #509052;
}

.bssm-button:active {
    outline: none;
}

.bssm-button .fa {
    vertical-align: top;
    line-height: 34px;
    margin-right: 5px;
}

.bssm-sidebar-footer {
    position: absolute;
    bottom: 26px;
    text-align: center;
    display: block;
    right: -10px;
    left: -10px;
}

/*
    Upload Font Modal Style
*/
.bs-font-upload-modal .bs-modal-body {
    background: #eee;
}

.bs-font-upload-modal .input {
    display: block;

    background: #fff;
    color: #828282;
    border: 1px solid #d3d3d3;

    -webkit-border-radius: 19px;
    -moz-border-radius: 19px;
    border-radius: 19px;

    line-height: 32px;
    padding: 0 15px;

    width: 100%;
    outline: none;
    -webkit-transition: all .6s ease;
    -moz-transition: all .6s ease;
    -o-transition: all .6s ease;
    transition: all .6s ease;
}

.bs-font-upload-modal .input:focus,
.bs-font-upload-modal .input:active {
    border-color: #4c954f !important;
    box-shadow: none !important;
}

.bs-font-upload-modal label {
    font-weight: bold;
    margin-bottom: 5px;
    display: block;
}

.bs-font-upload-modal .font-woff2,
.bs-font-upload-modal .font-woff,
.bs-font-upload-modal .font-ttf,
.bs-font-upload-modal .font-svg,
.bs-font-upload-modal .font-otf,
.bs-font-upload-modal .font-eot {
    margin-top: 16px;
    width: 50%;
    float: left;
}

.bs-font-upload-modal .input-section {
    position: relative;
}

.bs-font-upload-modal .input-section .bssm-button {
    position: absolute;
    top: 0;
    right: -10px;
    height: 100%;

    border-top-left-radius: 0;
    border-bottom-left-radius: 0;

    padding: 0 15px;
}

.bs-font-upload-modal .input-section.empty .bssm-button {
    background: #e4e4e4;
    border-color: #d5d5d5;
    color: #4a4a4a;
}

.bs-font-upload-modal .bf-choose-fonts {
    margin-bottom: 23px;
}

.bs-font-upload-modal .bf-choose-fonts .input {
    padding-right: 105px;
}

.bs-font-upload-modal .bs-modal-btn-primary {
    display: block;
    text-align: center;
    text-transform: uppercase;
    margin-right: 10px;
    margin-left: 10px;
}

.bs-font-upload-modal .bs-modal-body {
    padding: 20px 10px;
}

/**
 * 2.26. =>Color Picker
 **************************************************************/
.bs-color-picker-wrapper .iris-picker .iris-strip .ui-slider-handle {
    top: auto;
}

.bs-color-picker-wrapper .iris-picker .iris-slider-offset {
    margin: 0;
}

.vc_edit-form-tab .bs-color-picker-wrapper .wp-picker-open + .wp-picker-input-wrap {
    height: 52px;
}

.vc_edit_form_elements .bs-color-picker-wrapper input.wp-color-picker[type=text] {
    padding: 0 10px;
    width: 100% !important;
}

/**
 * 3. =>Admin Panel
 **************************************************************/

#bf-panel input[type=file] {
    background-color: #F5F5F5;
    padding: 5px;
    border: 1px solid #eee;
}

.bf-controls textarea,
#bf-panel textarea {
    width: 100%;
    min-height: 100px;
}

#bf-panel .button {
    padding: 0 10px 1px;
}

/*.bf-admin-panel.hide-notices div.updated,*/
.bf-admin-panel.hide-notices .update-nag {
    display: none;
}

.bf-admin-panel #bf-panel {
}

.bf-admin-panel .panel-wrapper {
    padding: 0;
    margin-left: -20px;
    position: relative;
}

.bf-page-header.sticky {
    position: fixed;
    top: 28px;
    left: 0;
    z-index: 999;
    width: 100%;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}

.bf-page-header .reset-sec {
    -webkit-transition: all .3s ease;
    -moz-transition: all .3s ease;
    -o-transition: all .3s ease;
    transition: all .3s ease;
}

.bf-page-header.sticky .reset-sec {
    margin-top: -47px;
}

.bf-page-header {
    background-color: #fff;
    -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
    margin-bottom: 20px;
    text-align: center;
    border-bottom: 1px solid #e5e5e5;
    -webkit-transition: all .3s ease;
    -moz-transition: all .3s ease;
    -o-transition: all .3s ease;
    transition: height .3s ease, padding-top .3s ease, padding-bottom .3s ease;
}

.bf-page-header .bf-page-header-inner {
    padding: 45px 20px 25px 20px;
    position: relative;
}

.bf-page-header.sticky .bf-page-header-inner {
    padding: 20px 30px 20px 190px;
}

.bf-page-header.sticky .page-title {
    font-size: 30px;
}

.bf-page-header .bf-options-change-notice {
    background: #f10f0f;
    color: #fff;
    white-space: normal;
    padding: 0 5px;
    margin: 0;
    display: inline-block;
    text-align: center;
    line-height: 20px;
    font-size: 12px;
    position: absolute;
    bottom: 25px;
    left: 50%;
    height: 20px;
    width: 146px;
    transform: translateX(-50%);
    -webkit-backface-visibility: hidden;
    text-transform: uppercase;
    font-weight: 600;
}

.bf-page-header .bf-options-change-notice:before {
    content: '';
    width: 8px;
    height: 8px;
    background: #fff;
    border-radius: 50%;
    display: inline-block;
    margin-right: 4px;
}

.bf-page-header.sticky .bf-options-change-notice {
    transform: translateX(0%);
    background: transparent;
    color: #f10f0f;
    font-size: 10px;
    bottom: 3px;
}

.bf-page-header.sticky .bf-options-change-notice:before {
    background: #f10f0f;
}

.bf-page-header .page-title {
    margin: 0 0 15px;
    padding: 0;
    font-size: 46px;
    font-weight: 400;
    letter-spacing: -0.03em;
    line-height: 1.1;
    -webkit-transition: all .3s ease;
    -moz-transition: all .3s ease;
    -o-transition: all .3s ease;
    transition: all .3s ease;
}

.bf-page-header .page-desc p {
    margin: 0;
    padding: 0;
    font-size: 21px;
    font-weight: 300;
    line-height: 1.3;
    color: #777;
}

.bf-page-header-wrapper {
    position: relative;
}

.bf-page-header .page-desc {
    -webkit-transition: all .3s ease;
    -moz-transition: all .3s ease;
    -o-transition: all .3s ease;
    transition: all .3s ease;
}

.bf-page-header.sticky .page-desc {
    opacity: 0;
    visibility: hidden;
    display: none;
}

.sticky #bf-main {
    margin-top: 210px;
}

/**
 * 3.1. =>Section
 **************************************************************/
.bf-section-container.bf-admin-panel .bf-section .bf-heading {
    width: 50%;
    float: left;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    padding: 0 20px 0 0;
}

.bf-section-container.bf-admin-panel .bf-section .bf-heading h3 {
    margin: 0 0 8px !important;
    border-bottom: none;
    font-weight: 600 !important;
    padding: 0px !important;
    font-size: 14px !important;
    line-height: 1.4 !important;
    cursor: default;
    position: relative;
    color: #222222;
}

.bf-section-container.bf-admin-panel .bf-section .bf-heading h3 label {
    cursor: default;
}

.bf-section-container.bf-admin-panel .bf-section .bf-controls {
    width: 50%;
    float: right;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    padding: 0;
}

.bf-section-container .bf-section.full-width-controls .bf-explain,
.bf-section-container .bf-section.full-width-controls .bf-heading,
.bf-section-container .bf-section.full-width-controls .bf-controls {
    width: 100% !important;
}

.bf-section-container.bf-admin-panel .bf-section.width-70 .bf-controls {
    width: 70%;
}

.bf-section-container.bf-admin-panel .bf-section.width-70 .bf-heading,
.bf-section-container.bf-admin-panel .bf-section.width-70 .bf-explain {
    width: 30%;
}

.bf-section-container.bf-admin-panel .bf-section.width-60 .bf-controls {
    width: 60%;
}

.bf-section-container.bf-admin-panel .bf-section.width-60 .bf-heading,
.bf-section-container.bf-admin-panel .bf-section.width-60 .bf-explain {
    width: 40%;
}

.bf-section-container.bf-admin-panel .bf-section .bf-explain {
    color: #939393;
    font-size: 13px;
    width: 50%;
    float: left;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    padding: 0 15px 0 0;
    clear: left;
}

/**
 * 3.2. =>Panel
 **************************************************************/
#bf-panel {
    font-size: 15px;
    position: relative;
}

#bf-panel .fright {
    float: right;
}

#bf-panel .fleft {
    float: left;
}

#bf-panel .group {
    display: none;
}

/**
 * 3.3. =>Panel Header
 **************************************************************/
.bf-header {
    min-height: 70px;
    width: 1060px;
    z-index: 999;
    background-color: #F5F5F5;
    color: #fff;
    -webkit-transition: all .3s ease;
    -moz-transition: all .3s ease;
    -o-transition: all .3s ease;
    transition: all .3s ease;
    border-bottom: 1px solid #C0C0C0;
}

.bf-header .logo-sec {
    float: left;
    position: relative;
    color: #222222;
    padding-top: 26px;
    padding-left: 18px;
}

.bf-header .save-btn-sec {
    padding: 20px;
    float: right;
}

.bf-header .logo-sec {
    display: table;
}

.bf-header .logo {
    padding: 0;
    font-size: 16px;
    margin: 0;
}

.bf-header .logo .version {
    font-size: 7px;
    margin-left: 5px;
    font-weight: normal;
}

.bf-header-wrapper {
    position: relative;
    min-height: 70px;
}

.bf-header.sticky {
    position: fixed;
    top: 28px;
}

/**
 * 3.4. =>Panel Main
 **************************************************************/
#bf-main {
    background: #FFFFFF;
    border: 1px solid #E2E2E2;
    max-width: 1060px;
    margin: 15px auto;
    padding: 20px;
    border-radius: 3px;
}

#bf-panel.panel-without-tab #bf-main {
    max-width: 900px;
}

/**
 * 3.5. =>Panel Nav
 **************************************************************/
#bf-nav {
    width: 25%;
    float: left;
}

#bf-nav > ul {
    margin-top: 0;
    padding-bottom: 20px;
}

#bf-nav.sticky {
    position: fixed;
    top: 102px;
}

#bf-nav > ul > li {
    margin: 0;
}

#bf-nav > ul > li.margin-top-10 {
    margin-top: 10px;
    border-top: 1px solid #E8E8E8;
}

#bf-nav > ul > li.margin-top-20 {
    margin-top: 20px;
    border-top: 1px solid #E8E8E8;
}

#bf-nav > ul > li.margin-top-30 {
    border-top: 1px solid #E8E8E8;
    margin-top: 30px;
}

#bf-nav > ul > li.margin-top-40 {
    margin-top: 40px;
    border-top: 1px solid #E8E8E8;
}

#bf-nav > ul > li.margin-top-50 {
    margin-top: 50px;
    border-top: 1px solid #E8E8E8;
}

#bf-nav > ul > li a {
    position: relative;
    display: block;
    padding: 14px 0 14px 16px;
    font-size: 14px;
    font-weight: 400;
    line-height: 18px;
    color: #444;
    text-decoration: none;
    outline: none;
    background-color: #F9F9F9;
    border-bottom: 1px solid #E8E8E8;
    -webkit-transition: all .3s ease;
    border-left: 1px solid #E8E8E8;
    -moz-transition: all .3s ease;
    -o-transition: all .3s ease;
    transition: all .3s ease;
    box-shadow: none;
}

#bf-nav > ul > li a:hover {
    background-color: #FDFCFC;

}

#bf-nav > ul > li:first-child a {
    border-top: 1px solid #E8E8E8;
}

#bf-nav > ul > li a .bf-icon {
    margin: 0 7px 0 0;
    font-size: 18px;
    vertical-align: middle;
    line-height: 18px;
}

#bf-nav > ul > li a .bf-icon.dashicon {
    margin-top: 0;
    height: auto;
    vertical-align: middle;
    float: none;
}

#bf-nav > ul > li a.active_tab {
    background-color: #fff;
    position: relative;
}

#bf-nav > ul > li.child_active > a:after,
#bf-nav > ul > li a.active_tab:after {
    content: " ";
    right: -1px;
    height: 100%;
    width: 1px;
    position: absolute;
    pointer-events: none;
    top: 0;
    background-color: #fff;
}

#bf-nav > ul > li.child_active > a {
    position: relative;
    background-color: #0074a2;
    color: white;
}

#bf-nav > ul > li > ul.sub-nav > li {
    margin: 0;
}

#bf-nav > ul > li > ul.sub-nav > li a {
    font-size: 13px;
    line-height: 1.2;
    padding: 8px 12px;

}

#bf-nav > ul > li > ul.sub-nav a {
    background-color: #2E2E2E;
}

#bf-nav > ul > li.child_active > ul.sub-nav a.active_tab {
    color: white;
    font-weight: 600;

}

#bf-nav > ul > li.child_active > ul.sub-nav a.active_tab:after {
    display: none;
}

.bf-tab-badge {
    position: absolute;
    right: 10px;
    top: 50%;
    margin-top: -8px;
    color: #fff;
    background-color: #2D9EC7;
    border-color: #2D9EC7;
    font-size: 9px;
    line-height: 16px;
    height: 16px;
    padding: 0 4px;
}

.bf-tab-badge:after {
    left: -10px;
    border: solid 5px rgba(0, 0, 0, 0);
    content: " ";
    height: 0;
    width: 0;
    position: absolute;
    pointer-events: none;
    border-right-color: inherit;
    top: 50%;
    margin-top: -5px;
}

/**
 * 3.6. =>Panel Content
 **************************************************************/
#bf-content {
    padding: 15px;
    width: 75%;
    float: right;
    min-height: 760px;
    background-color: #fff;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    border: 1px solid #E8E8E8;
}

#bf-panel.panel-without-tab #bf-content {
    border: none;
    padding: 20px 0;
    width: 100%;
    float: none;
}

/**
 * 3.7. =>Panel Footer
 **************************************************************/
#bf-panel .bf-footer {
    min-height: 60px;
    background-color: #F5F5F5;
    color: #444;
    border-top: 1px solid #D3D3D3;
}

#bf-panel .bf-footer .reset-sec {
    text-align: center;
    height: 60px;
    width: 220px;
    float: left;
    text-align: center;
}

#bf-panel .bf-footer .btn-sec {
    padding: 15px;
}

/**
 * 3.8. =>Typography
 **************************************************************/

/**
 * 3.9 =>Panel Loading
 **************************************************************/
#bf-panel .bf-loading {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: #636363;
    background-color: rgba(0, 0, 0, 0.41);
    display: none;
    z-index: 99999;
}

#bf-panel .bf-loading .loader {
    width: 300px;
    height: 180px;
    position: absolute;
    top: 50%;
    left: 50%;
    margin-top: -90px;
    margin-left: -150px;
    text-align: center;
}

#bf-panel .bf-loading.not-loaded,
#bf-panel .bf-loading.loaded,
#bf-panel .bf-loading.in-loading {
    display: block;
}

#bf-panel .bf-loading.in-loading .loader {
    color: white;
}

#bf-panel .bf-loading.loaded .loader {
    color: #27c55a;
}

#bf-panel .bf-loading.not-loaded .loader {
    color: #ff0000;
}

#bf-panel .bf-loading .loader .loader-icon {
    font-size: 30px;
    -webkit-transition: all 0.2s ease;
    -moz-transition: all 0.2s ease;
    -ms-transition: all 0.2s ease;
    -o-transition: all 0.2s ease;
    transition: all .2s ease;
    opacity: 0;
    border-radius: 10px;
    background-color: #333;
    background-color: rgba(51, 51, 51, 0.86);
    width: 60px;
    height: 60px;
    line-height: 60px;
    margin-top: 20px;
    display: none;
    position: absolute;
    left: 50%;
    margin-left: -30px;
}

#bf-panel .bf-loading .loader .loader-icon .dashicons,
#bf-panel .bf-loading .loader .loader-icon .dashicons-before:before {
    font-size: 55px;
    line-height: 60px;
    width: 60px;
    height: 60px;
    text-align: center;
}

#bf-panel .bf-loading.in-loading .loader .loader-icon.in-loading-icon,
#bf-panel .bf-loading.in-loading.loader .loader-icon.in-loading-icon {
    opacity: 1;
    display: inline-block;
}

#bf-panel .bf-loading.in-loading .loader .loader-icon.in-loading-icon .dashicons,
#bf-panel .bf-loading.in-loading .loader .loader-icon.in-loading-icon .dashicons-before:before {
    -webkit-animation: spin 1.15s linear infinite;
    -moz-animation: spin 1.15s linear infinite;
    animation: spin 1.15s linear infinite;
    font-size: 30px;
}

#bf-panel .bf-loading.loaded .loader .loader-icon.loaded-icon {
    opacity: 1;
    display: inline-block;
    font-size: 50px;
}

#bf-panel .bf-loading.loaded .loader .loader-icon.loaded .dashicons,
#bf-panel .bf-loading.loaded .loader .loader-icon.loaded .dashicons-before:before {
    width: 57px;
}

#bf-panel .bf-loading.not-loaded .loader .loader-icon.not-loaded-icon {
    opacity: 1;
    display: inline-block;
}

#bf-panel .bf-loading.not-loaded .loader .loader-icon.not-loaded-icon .dashicons,
#bf-panel .bf-loading.not-loaded .loader .loader-icon.not-loaded-icon .dashicons-before:before {
    font-size: 50px;
    line-height: 62px;
}

#bf-panel .bf-loading .loader .message {
    display: none;
    color: #ff0000;
    font-size: 12px;
    line-height: 24px;
    min-width: 100px;
    max-width: 300px;
    left: auto;
    right: auto;
    text-align: center;
    background-color: #333;
    background-color: rgba(51, 51, 51, 0.86);
    border-radius: 5px;
    padding: 4px 20px;
    margin-top: 90px;
}

#bf-panel .bf-loading.with-message .loader .message {
    display: inline-block;
}

#bf-panel .bf-loading.loaded .loader .message {
    color: #27c55a;
}

#bf-panel .bf-loading.in-loading .loader .message {
    color: #fff;
}

@-moz-keyframes spin {
    100% {
        -moz-transform: rotate(360deg);
    }
}

@-webkit-keyframes spin {
    100% {
        -webkit-transform: rotate(360deg);
    }
}

@keyframes spin {
    100% {
        -webkit-transform: rotate(360deg);
        transform: rotate(360deg);
    }
}

/**
 * 3.9 =>Panel Loading
 **************************************************************/
.bf-section-container.bf-admin-panel .bf-section-info {
    margin-top: 15px;
    margin-bottom: 15px;
}

/**
 * 3.10 =>Image Select
 **************************************************************/

/**
 * 4. =>Widgets
 **************************************************************/
.bf-section-container.bf-widgets {
    padding: 0;
}

.bf-section-container.bf-widgets + .fields-group {
    margin-top: 10px;
}

.bf-section-container.bf-widgets .widefat input {
    width: 100%;
}

.bf-section-container.bf-widgets .bf-section-checkbox-option.bf-section .bf-heading {
    border-bottom: none;
    margin-bottom: 0;
}

/**
 * 4.1. =>General style
 **************************************************************/
.bf-section-container.bf-widgets .widefat input {
    width: 100%;
}

.bf-section-container.bf-widgets .widefat input[type=radio],
.bf-section-container.bf-widgets .widefat input[type=checkbox] {
    width: auto;
}

/**
 * 4.2. =>Section
 **************************************************************/
.bf-section-container.bf-widgets .bf-section {
    margin: 0;
    padding-top: 10px;
    padding-bottom: 0;
    border-bottom: none;
}

.bf-section-container.bf-widgets .bf-section .bf-heading {
    margin: 0 0 5px;
    padding-bottom: 5px;
}

.bf-section-container.bf-widgets .bf-section .bf-heading h4 {
    margin: 0;
}

.bf-section-container.bf-widgets .bf-section .bf-control {
    margin-bottom: 10px;
}

.bf-section-container.bf-widgets .bf-section .bf-desc {
    font-size: 12px;
    color: #b4b4b4;
    font-style: italic;
}

.bf-section-container.bf-widgets .bf-section-info {
    margin-bottom: 10px;
}

/**
 * 4.3. =>Ajax Select
 **************************************************************/
.bf-section-container.bf-widgets .bf-ajax-suggest-input {
    width: 100%;
}

.bf-section-container.bf-widgets .bf-ajax-suggest-search-results {
    width: 99.2%;
    top: 14px;
}

.bf-section-container.bf-widgets .bf-ajax_select-field-container span.preloader {
    left: initial;
    top: 7px;
    right: 5px;
}

/**
 * 4.4. =>Heading
 **************************************************************/
.bf-section-container.bf-widgets .bf-section.bf-section-heading-option .bf-heading-heading-option {
    padding: 0;
    margin: 0;
}

.bf-section-container.bf-widgets .bf-section.bf-section-heading-option .bf-heading-heading-option h4 {
    padding: 13px 15px;
    border: 1px solid #cccccc;
    background: #e0e0e0;
    font-size: 12px;
}

/**
 * 5. =>Taxonomies
 **************************************************************/
.bf-tax-meta-wrap {
    position: relative;
    min-width: 255px;
    max-width: 1200px;
    border: 1px solid #e5e5e5;
    -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .04);
    box-shadow: 0 1px 1px rgba(0, 0, 0, .04);
    background: #fff;
    margin: 20px 0;
}

.bf-tax-meta-wrap .bf-tax-metabox-title h3 {
    font-size: 14px;
    padding: 12px;
    margin: 0;
    line-height: 1.4;
    border-bottom: 1px solid #eee;
    background-color: #fff;
}

/**
 * 6. =>Visual Composer
 **************************************************************/
.bf-section-container.vc-input {
    padding: 8px 0 0 0;
}

.bf-css-edit-switch-container + .wpb_el_type_css_editor:before {
    background: #f1f1f1;
    content: '';
    height: 1px;
    width: 100%;
    display: inline-block;
    margin-bottom: 10px;
}

.bf-css-edit-switch-container {
    float: left !important;
    width: 30% !important;
}

.bf-css-edit-switch-container + .bf-css-edit-switch-container {
    padding-top: 0 !important;
}

.vc_shortcode-param .bf-section-container {
    padding-right: 0;
    padding-left: 0;
}

.vc_shortcode-param.vc_wrapper-param-type-bf_info {
    margin-bottom: 10px;
}

.vc_edit_form_elements .vc_shortcode-param:last-child {
    margin-bottom: 25px;
}

/**
 * 6.1. =>Color Picker
 **************************************************************/
.wpb_edit_form_elements .bf-section-container .bf-controls-color-option {
    position: relative;
}

.wpb_edit_form_elements .bf-section-container .bf-color-picker {
    width: 100px;
    padding: 4px 6px;
}

.wpb_edit_form_elements .bf-section-container .bf-color-picker-preview {
    width: 21px;
    height: 21px;
    display: inline-block;
    position: relative;
    left: -26px;
    top: 5px;
}

/**
 * 6.2. =>Image Radio
 **************************************************************/
.bf-section-container.style-floated-left .vc-bf-image-radio-option {
    float: left;
    margin-right: 10px;
    min-height: 96px;
}

.bf-section-container .vc-bf-image-radio-option .item-label {
    margin: 5px 0;
    text-align: center;
}

.bf-section-container .vc-bf-image-radio-option.checked .item-label {
    font-weight: bold;
}

.bf-section-container .vc-bf-image-radio-option img {
    border: 1px solid #e2e2e2;
}

.bf-section-container .vc-bf-image-radio-option.checked img {
    border: 1px solid #0074a2;
}

/**
 * 6.3. =>Ajax Select
 **************************************************************/
.vc_row-fluid .bf-ajax-suggest-search-results {
    position: relative !important;
    top: initial;
    left: initial;
}

.vc_row-fluid .bf-ajax-suggest-controls {
    margin: 5px 0;
}

.vc_row-fluid .bf-ajax_select-field-container span.preloader {
    left: inherit;
    right: 10px;
    top: 10px;
}

/**
 * 6.5. =>Heading
 **************************************************************/
.vc_wrapper-param-type-bf_heading.vc_shortcode-param .wpb_element_label {
    display: none;
}

.vc_wrapper-param-type-bf_heading .bf-section-container {
    padding: 0;
}

.vc_wrapper-param-type-bf_heading .bf-section-heading .bf-section-heading-title {
    height: 44px !important;
    line-height: 44px !important;
    background: #2B4B80 !important;
    color: #fff !important;
    border: 1px solid #2b4b80 !important;
}

.vc_wrapper-param-type-bf_heading .bf-section-heading .bf-section-heading-title h4 {
    margin: 0;
    padding: 0;
    font-size: 14px;
}

.vc_wrapper-param-type-bf_heading .bf-section-heading {
    margin: 0;
}

.vc_wrapper-param-type-bf_heading {
    margin-top: 15px;
}

.vc_wrapper-param-type-bf_heading:first-child {
    margin-top: 0;
}

/**
 * 6.6. =>Editor ShortCode
 **************************************************************/

.wpb_content_element.bf-vc-field .vc_admin_label label {
    font-weight: bold;
    color: #8B8B8B;
}

/**
 * 6.7. =>VC Media Image
 **************************************************************/
.bf-section-container.vc-input .bf-media-image-remove-btn {
    margin-left: 10px;
}

.bf-section-container.vc-input .bf-media-image-preview {
    margin-top: 15px;
}

/**
 * 6.8. =>VC Info
 **************************************************************/
.wpb_el_type_bf_info.vc_shortcode-param .wpb_element_label {
    display: none;
}

.wpb_el_type_bf_info.vc_shortcode-param .bf-controls-vc-info-option {
    padding: 10px;
}

/**
 * 6.9. =>Switch
 **************************************************************/
.bf-section-container.vc-input .bf-switch input[type=checkbox] {
    display: none;
}

/**
 * 6.10. =>Select
 **************************************************************/
.bf-select-option-container select.bf_select_field {
    padding: 3px 13px;
    height: 34px;
    margin: 0;
}

.bf-section-container .bf-section .bf-controls .bf-select-option-container.multiple select,
.bf-select-option-container.multiple select {
    height: 170px;
    overflow: scroll;
    padding: 15px;
}

.bf-section-container .bf-section .bf-controls .bf-select-option-container.multiple:before,
.bf-select-option-container.multiple:before {
    display: none !important;
}

/**
 * 6.11. =>Column
 **************************************************************/
.bf-vc-third-column {
    float: left !important;
    width: 33% !important;
    margin-bottom: 25px;
}

.bf-vc-third-column select.bf_select_field {
    font-size: 13px;
}

/**
 * 7. =>Menus
 **************************************************************/
.menu-item-settings {
    z-index: initial; /* Hack for z-index problem on child and BF select boxes */
}

.bf-section-container.bf-menus {
    padding: 0 !important;
}

.bf-menu-custom-field {
    margin: 0;
    font-size: 13px;
    font-style: italic;
    height: auto;
    min-height: 80px;
}

.bf-menu-custom-field .better-custom-field-label {
    line-height: 35px;
    min-height: 35px;
    display: inline-block;
}

.better-menu-container {
    float: left;
    margin: 15px 0 0;
}

.better-menu-container .better-menu-box-title {
    margin-bottom: 10px;
}

.better-menu-container .better-menu-fields {
    display: none;
}

.bf-section-container.bf-menus .bf-field-with-prefix span,
.bf-section-container.bf-menus .bf-field-with-suffix span {
    margin-top: -3px;
    margin-left: -2px;
}

/**
 * 7.1. =>Mega Menu Field
 **************************************************************/
.menu-item.menu-item-depth-0 .fields-group#fields-group-mega_menu_heading .bf-field-mega_menu_cat,
.menu-item.menu-item-depth-0 .fields-group#fields-group-mega_menu_heading .bf-field-mega_menu {
    display: block;
}

.menu-item .fields-group#fields-group-mega_menu_heading .bf-field-drop_menu_anim {
    width: 360px;
}

.menu-item.menu-item-depth-0 .fields-group#fields-group-mega_menu_heading .bf-field-drop_menu_anim {
    width: 170px;
}

.menu-item.menu-item-depth-0 .fields-group#fields-group-mega_menu_heading .bf-field-mega_menu_cat {
    width: 180px;
    margin-right: 0;
}

/**
 * 7.2. =>Menu Badge Field
 **************************************************************/
.menu-item.menu-item-depth-0 .bf-field-badge_label.description-thin {
    width: 360px !important;
}

.menu-item.menu-item-depth-0 .bf-field-badge_position {
    display: none;
}

.menu-item .bf-field-badge_position {
    margin-top: 1px;
}

/**
 * 7.3. =>WPNav Menu
 **************************************************************/
.menu-item .bf-section-info {
    background-color: #FFFDF4;
    border: 1px solid #F1E0BD;
    color: #8a6d3b;
    margin-top: 10px;
}

.menu-item .bf-section-info-title {
    background-color: #fcf8e3;
    border-color: #F1E0BD;
    color: #896D3B;
}

.menu-item .bf-section-info-title h3 {
    padding: 0 !important;
    margin: 0 !important;
    font-size: 12px !important;

    background-color: #fcf8e3;
    border-bottom: 1px solid #F1E0BD;
    color: #896D3B;
    padding: 10px 15px !important;
}

.menu-item .bf-section-info-title .fa {
    margin-right: 3px;
}

.menu-item .bf-section-info-message {
    padding: 15px;
}

/**
 * 7.4. =>Heading
 **************************************************************/
.bf-section-container.bf-menus .bf-section-heading .bf-section-heading-title {
    padding: 0;
}

.bf-section-container.bf-menus .bf-section-heading .bf-section-heading-title h3 {
    margin: 0 -15px -2px -15px !important;
    font-size: 15px;
}

.bf-section-container.bf-menus .bf-section-heading {
    margin: 10px 0;
}

.bf-group-inner .bf-section-container.bf-menus .bf-section-heading.style-2 {
    margin: 0;
    padding: 0;
}

/**
 * 7.5. =>Color Picker
 **************************************************************/
.bf-section-container.bf-menus input.bf-color-picker {
    width: 100px;
    padding: 4px 6px;
}

/**
 * 7.6 =>Checkbox
 **************************************************************/
.better-custom-field-checkbox .bf-section-container.bf-menus {
    padding-top: 27px;
}

/**
 * 7.6. =>IconSelect
 **************************************************************/
.bf-section-container.bf-menus .bf-select-icon .select-options .better-select-icon-options {
    width: 390px;
}

/**
 * 7.8. =>Group
 **************************************************************/
.menu-item .fields-group {
    border: 1px solid #dddddd;
    margin-top: 10px;
    margin-bottom: 0;
    width: 390px;
    float: left;
}

.menu-item .fields-group .fields-group-title-container {
    height: 34px;
    line-height: 34px;
    background-color: #f5f5f5;
    border-bottom: 1px solid #dddddd;
}

.menu-item .fields-group .bf-group-inner {
    padding: 15px;
}

.menu-item .fields-group .bf-group-inner .description-wide {
    width: 360px;
}

.menu-item .fields-group .bf-group-inner .description-thin {
    width: 170px;
}

.menu-item .fields-group .fields-group-title-container .fields-group-title {
    font-size: 12px;
    padding: 0 62px 0 16px;
    font-weight: 600;
}

.menu-item .fields-group.collapsible .fields-group-title-container .collapse-button {
    width: 40px;
    line-height: 34px;
    border: 1px solid #dddddd;
}

.menu-item .fields-group .bf-group-inner .bf-group-desc {
    padding: 7px 0;
}

.menu-item .bf-background-image-preview {
    margin-top: 15px;
}

.bf-section-container.bf-menus .bf-field-with-prefix input[type=text],
.bf-section-container.bf-menus .bf-field-with-suffix input[type=text] {
    width: 65%;
}

/**
 * 7.9. =>Color
 **************************************************************/
.bf-section-container.bf-menus input[type=text] {
    width: 100%;
    height: 34px;
}

.bf-section-container.bf-menus .bf-color-picker-container {
    width: 100%;
}

.bf-section-container.bf-menus .bf-color-picker {
    width: 100%;
}

.bf-section-container.bf-menus .bf-color-picker-preview {
    top: 6px;
}

/**
 * 7.10. =>Background Image
 **************************************************************/

.bf-menu-custom-field.better-custom-field-background_image .bf-button {
    margin-bottom: 12px;
}

/**
 * 8. =>Meta Box
 **************************************************************/

/**
 * 8.1. =>Section
 **************************************************************/

.bf-section-container.bf-metabox .bf-section .bf-heading {
    width: 34%;
    float: left;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    padding: 0 20px 0 0;
}

.bf-section-container.bf-metabox .bf-section .bf-heading h3 {
    margin: 0 0 8px !important;
    border-bottom: none;
    font-weight: 600 !important;
    padding: 0px !important;
    font-size: 13px !important;
    line-height: 1.4 !important;
    cursor: default;
    position: relative;
    color: #222222;
    -webkit-user-select: initial;
    -moz-user-select: initial;
    -ms-user-select: initial;
    user-select: initial;
}

.bf-section-container.bf-metabox .bf-section .bf-heading label {
    cursor: default;
}

.bf-section-container.bf-metabox .bf-section .bf-heading h3:before {

}

.bf-section-container.bf-metabox .bf-section.no-desc .bf-controls,
.bf-section-container.bf-metabox .bf-section .bf-controls {
    width: 66%;
    float: right;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    padding: 0;
}

.bf-section-container.bf-metabox .bf-section .bf-explain {
    color: #939393;
    font-size: 13px;
    width: 34%;
    float: left;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    padding: 0 15px 0 0;
    clear: left;
}

.bf-section-tree-select select,
.bf-select-option-container select,
.bf-section-container .bf-section .bf-controls textarea,
.bf-section-container .bf-section .bf-controls input[type=text],
.bf-section-container.bf-menus .bf-select-option-container select,
.bf-section-container .bf-section .bf-controls select,
.bf-section-container .bf-section .bf-controls .select-placeholder {
    margin: 0;
    box-shadow: none;
    width: 100%;
    margin: 0;
    border: 1px solid #d6d6d6;
    color: #333333;
    padding: 3px 13px;
    pearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    -o-appearance: none;
    border: 1px solid #d9d9d9;
    box-sizing: border-box;
    -webkit-box-sizing: none;
    -moz-box-sizing: none;
    -o-box-sizing: none;
    display: block;
    font-size: 13px;
    outline: none;
    overflow: ellipsis;
    position: relative;
    text-indent: 0.01px;
    text-overflow: '';
    -webkit-text-overflow: none;
    -moz-text-overflow: none;
    -o-text-overflow: none;
    vertical-align: middle;
    z-index: 1;
    height: 34px;
    -webkit-transition: all .3s ease;
    -moz-transition: all .3s ease;
    -o-transition: all .3s ease;
    transition: all .3s ease;
    border-radius: 0;
}

.bf-section-container .bf-section .bf-controls input[type=text],
.bf-section-container .bf-select-option-container,
.bf-section-container .bf-ajax_select-field-container {
    max-width: 370px;
}

.bf-section-container .bf-controls-term_select-option {
    max-width: 370px;
    float: left !important;
}

body.rtl .bf-section-container .bf-controls-term_select-option {
    float: right !important;
}

.bf-section-tree-select:hover select,
.bf-select-option-container:hover select,
.bf-section-container .bf-section .bf-controls textarea:hover,
.bf-section-container .bf-section .bf-controls input[type=text]:hover,
.bf-section-container .bf-section .bf-controls select:hover,
.bf-section-container .bf-section .bf-controls .select-placeholder:hover {
    border-color: #C2C2C2;
}

.bf-section-container .bf-section .bf-controls select,
.bf-section-container .bf-section .bf-controls .select-placeholder {
    cursor: pointer;
}

.bf-section-container .bf-section .bf-controls .select-placeholder {
    line-height: 27px;
    vertical-align: top;
}

.bf-section-container .bf-section .bf-controls textarea {
    padding: 5px;
}

.bf-section-container .bf-section .bf-controls textarea:focus,
.bf-section-container .bf-section .bf-controls.bf-controls-text-option input[type=text]:focus {
    border-color: #C2C2C2;
    box-shadow: none;
}

.bf-section-tree-select .components-base-control__field,
.bf-section-container .bf-controls-background_image-option .bf-background-image-uploader-select-container,
.bf-section-container .bf-select-option-container {
    position: relative;
}

.bf-section-container .bf-controls-background_image-option .bf-background-image-uploader-select-container:before,
.bf-section-tree-select .components-base-control__field:before,
.bf-section-container .bf-select-option-container:before {
    position: absolute;
    right: 0;
    top: 0;
    width: 34px;
    height: 34px;
    line-height: 34px;
    border: 1px solid #d6d6d6;
    display: inline-block;
    content: '\f107';
    background-color: #fff;
    font-family: 'FontAwesome';
    text-align: center;
    font-size: 14px;
    color: #7C7C7C;
    z-index: 2;
    pointer-events: none;
    -webkit-transition: all .3s ease;
    -moz-transition: all .3s ease;
    -o-transition: all .3s ease;
    transition: all .3s ease;
    box-sizing: border-box;
}

.bf-section-container .bf-controls-background_image-option .bf-background-image-uploader-select-container:hover:before,
.bf-section-container .bf-select-option-container:hover:before {
    border-color: #C2C2C2;
}

.bf-section-container.dir-ltr .bf-section .bf-controls.bf-controls-text-option input[type=text] {
    text-align: left;
    direction: ltr;
}

.bf-section-container.dir-rtl .bf-section .bf-controls.bf-controls-text-option input[type=text] {
    text-align: right;
    direction: rtl;
}

.bf-section-container.dir-ltr .bf-section .bf-controls textarea,
.bf-section-container.dir-ltr .bf-section .bf-controls select,
.bf-section-container.dir-ltr .bf-section .bf-controls .select-placeholder {
    text-align: left;
    direction: ltr;
}

.bf-section-container.dir-rtl .bf-section .bf-controls textarea,
.bf-section-container.dir-rtl .bf-section .bf-controls select,
.bf-section-container.dir-rtl .bf-section .bf-controls .select-placeholder {
    text-align: right;
    direction: rtl;
}

.bf-section-container .bf-section .bf-controls textarea.bf-invalid-value,
.bf-section-container .bf-section .bf-controls input[type=text].bf-invalid-value {
    box-shadow: inset 0 0 3px rgba(255, 0, 0, 0.37);
    border: 1px solid #ffa4a4;
}

/**
 * 8.2. =>Tabs
 **************************************************************/

.postbox-container .postbox .inside.tabbed-metabox {
    margin: 0 !important;
    padding: 0 !important;
}

.bf-metabox-wrap.tabbed-metabox {
    background: #f5f5f5;
}

.bf-metabox-tabs {
    margin: 0;
    padding: 0;
    width: 20%;
    float: left;
    -moz-box-sizing: border-box;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
}

.bf-metabox-tabs li,
.bf-metabox-tabs ul {
    margin: 0;
    padding: 0;
}

.bf-metabox-tabs li {
    background: #f5f5f5;
}

.bf-metabox-tabs > ul > li.margin-top-10 {
    margin-top: 10px;
    border-top: 1px solid #E8E8E8;
}

.bf-metabox-tabs > ul > li.margin-top-20 {
    margin-top: 20px;
    border-top: 1px solid #E8E8E8;
}

.bf-metabox-tabs > ul > li.margin-top-30 {
    border-top: 1px solid #E8E8E8;
    margin-top: 30px;
}

.bf-metabox-tabs > ul > li.margin-top-40 {
    margin-top: 40px;
    border-top: 1px solid #E8E8E8;
}

.bf-metabox-tabs > ul > li.margin-top-50 {
    margin-top: 50px;
    border-top: 1px solid #E8E8E8;
}

.bf-metabox-tabs .bf-tab-item-a {
    cursor: pointer;
    display: block;
    font-size: 13px;
    color: #303030;
    text-decoration: none;
    font-weight: bold;
    padding: 13px;
    border-bottom: 1px solid #e2dddb;
    outline: none;
    position: relative;
    -webkit-transition: all .3s ease;
    -moz-transition: all .3s ease;
    -o-transition: all .3s ease;
    transition: all .3s ease;
    box-shadow: none;
}

.bf-metabox-tabs .bf-tab-item-a .tab-icon {
    margin-right: 6px;
    font-size: 17px;
}

.bf-metabox-tabs .bf-tab-item-a.active_tab:hover,
.bf-metabox-tabs .bf-tab-item-a.active_tab {
    background-color: #fff;
}

.bf-metabox-tabs .bf-tab-item-a:hover {
    background-color: #FDFCFC;
}

.bf-metabox-tabs .bf-tab-item-a.active_tab:after {
    content: '';
    height: 100%;
    width: 1px;
    background: #fff;
    display: inline-block;
    position: absolute;
    right: -1px;
    top: 0;
}

.bf-metabox-container.bf-with-tabs {
    width: 80%;
    float: right;
    background-color: #fff;
    -moz-box-sizing: border-box;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
    padding: 15px 15px;
    border-left: 1px solid #e2dddb;
}

.bf-metabox-container.bf-with-tabs .group {
    display: none;
    min-height: inherit;
}

/**
 * 8.3. =>Heading
 **************************************************************/

/**
 * 9. =>Font Manager
 **************************************************************/
.bf-section-container.better-font-stack-name {
    width: 46%;
    float: left;
    padding-left: 2%;
    padding-right: 2%;
}

.bf-section-container.better-font-stack-stack {
    width: 46%;
    float: right;
    padding-right: 2%;
    padding-left: 2%;
}

/**
 * 9.1. =>Fields
 **************************************************************/
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-otf .bf-controls,
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-eot .bf-controls,
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-svg .bf-controls,
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-ttf .bf-controls,
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-woff2 .bf-controls,
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-woff .bf-controls {
    position: relative;
}

.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-otf .bf-controls input[type=text],
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-eot .bf-controls input[type=text],
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-svg .bf-controls input[type=text],
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-ttf .bf-controls input[type=text],
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-woff .bf-controls input[type=text] {
    width: 100%;
}

.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-otf .bf-controls .bf-media-upload-btn,
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-eot .bf-controls .bf-media-upload-btn,
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-svg .bf-controls .bf-media-upload-btn,
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-ttf .bf-controls .bf-media-upload-btn,
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-woff2 .bf-controls .bf-media-upload-btn,
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-woff .bf-controls .bf-media-upload-btn {
    position: absolute;
    right: 0;
    top: 0;
    z-index: 1;
}

.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-woff,
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-ttf,
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-eot {
    width: 40%;
    float: left;
}

.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-otf,
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-svg,
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-woff2 {
    width: 40%;
    float: right;
}

.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-otf .bf-section,
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-woff2 .bf-section,
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-woff .bf-section,
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-ttf .bf-section,
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-svg .bf-section,
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-eot .bf-section {
    padding-top: 0;
}

.rtl .bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-eot .bf-controls .bf-media-upload-btn,
.rtl .bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-svg .bf-controls .bf-media-upload-btn,
.rtl .bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-ttf .bf-controls .bf-media-upload-btn,
.rtl .bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-woff2 .bf-controls .bf-media-upload-btn,
.rtl .bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-woff .bf-controls .bf-media-upload-btn {
    right: auto;
    left: 0;
}

/**
 * 10. =>User Metabox
 **************************************************************/
.bf-user-meta-wrap {
    position: relative;
    min-width: 255px;
    max-width: 1200px;
    border: 1px solid #e5e5e5;
    -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .04);
    box-shadow: 0 1px 1px rgba(0, 0, 0, .04);
    background: #fff;
    margin: 20px 0;
}

.bf-user-meta-wrap .bf-user-metabox-title h3 {
    font-size: 14px;
    padding: 10px 12px;
    margin: 0 !important;
    line-height: 1.4;
    border-bottom: 1px solid #eee;
    background-color: #fff;
}

/**
 * 11. =>Admin Menus
 **************************************************************/

/**
 * 12. =>Notice System
 **************************************************************/

/***
    Notice Styles
**/
.bf-notice {
    background: #fff;
    -webkit-box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1);
    box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1);
    margin: 5px 0 2px;
    padding: 1px 12px;
    position: relative;
    z-index: 10;
    overflow: hidden;
    font-size: 14px;
    line-height: 1.62;
    display: block;
}

.bf-notice *,
.bf-notice {
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}

.bf-notice-wrapper {
    position: relative;
    overflow: hidden;
    margin-top: 10px;
    clear: both;
    max-height: 200px;
    transition: max-height .3s ease;
}

.bf-notice-container {
    display: table-row;
}

.bf-notice-text-container {
    display: table-cell;
    background: #fff;
    vertical-align: top;
    width: 100%;
    padding-left: 12px;
}

.bf-notice-text {
    max-height: 150px;
    overflow: hidden;
    padding-bottom: 10px;
}

.bf-notice-text:last-child {
    margin-bottom: 0;
}

.bf-notice p {
    margin: 0.5em 0;
    padding: 2px;
}

.bf-notice p:last-child {
    margin-bottom: 0;
}

.bf-notice.bf-notice-has-thumbnail {
    padding: 0;
}

.bf-notice.bf-notice-dismissible {
    padding-right: 40px;
}

.bf-notice .bf-notice-thumbnail {
    vertical-align: middle;
    padding: 0 7px;
    display: table-cell;
    min-height: 36px;
    height: 100%;
}

.bf-notice .bf-notice-thumbnail img {
    vertical-align: middle;
}

.bf-notice-success .bf-notice-thumbnail {
    background: #46b450;
}

.bf-notice-success .title {
    color: #268b30;
}

.bf-notice-no-thumbnail.bf-notice-success {
    border-left: 4px solid #46b450;
}

.bf-notice-warning .bf-notice-thumbnail {
    background: #e2a400;
}

.bf-notice-warning .title {
    color: #e2a400;
}

.bf-notice-no-thumbnail.bf-notice-warning {
    border-left: 4px solid #e2a400;
}

.bf-notice-danger .bf-notice-thumbnail {
    background: #dc3232;
}

.bf-notice-danger .title {
    color: #c82322;
}

.bf-notice-no-thumbnail.bf-notice-danger {
    border-left: 4px solid #dc3232;
}

.bf-notice-dismiss {
    position: absolute;
    top: 0;
    right: 1px;
    border: none;
    margin: 0;
    padding: 9px;
    background: none;
    color: #b4b9be;
    cursor: pointer;
    outline: none !important;
}

.bf-notice-dismiss:before {
    background: none;
    color: #b4b9be;
    content: "\f153";
    display: block;
    font: normal 16px/20px dashicons;
    height: 20px;
    text-align: center;
    width: 20px;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

.bf-notice-wrapper + .panel-wrapper,
.bf-admin-page.bf-admin-page-template-minimal-1 .bf-notice-wrapper + .bf-admin-page-wrap {
    margin-top: 15px;
}

.bf-notice .detail {
    font-size: 13px;
    line-height: 1.4;
    color: #3f3f3f;
}

.bf-notice-text-container.bf-close .detail {
    opacity: 0.85;
}

.bf-notice .detail li {
    list-style: disc outside none;
    margin-left: 22px;
}

.bf-notice-text-container {
    position: relative;
}

.bf-notice-message-collapse {
    background: #fff;
    position: absolute;
    width: 100%;
    bottom: 0;

    padding: 10px 2px;
}

/**************************************************************
 * 13. =>Last Not Refactored Codes
 **************************************************************/

/***** Fields ******/

/*-------------------------------------------------------------------------------------------*/
/* bf Meta Box styles */
/*-------------------------------------------------------------------------------------------*/

.ui-slider {
    height: 5px;
    background-color: #DBDBDB;
    position: relative;
}

.ui-slider .ui-slider-range {
    height: 5px;
    background-color: #1E92C0;
    position: relative;
}

.ui-slider .ui-slider-range:after {
    content: '';
    width: 14px;
    height: 14px;
    display: inline-block;
    position: absolute;
    right: -7px;
    top: 50%;
    background-color: #0074A2;
    border-radius: 50%;
    margin-top: -7px;
}

/**************************************************************
 * 14. =>TinyMCE Add-On
 **************************************************************/

#es-modal .bs-modal-header-wrapper:after {
    display: none;
}

#es-modal .bs-modal-body {
    padding: 0;
}

#es-modal .tinymce-addon-fields .group {
    padding: 0 20px 20px;
}

#es-modal .bs-modal-header-wrapper {
    background: #00a0d2;
    color: #fcfdff;
}

#es-modal .bs-modal-header-wrapper .bs-modal-header {
    color: #ecf0f9;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
    font-weight: normal;
}

#es-modal .tabs-wrapper {
    background: #00a0d2;
    padding: 0 20px;
}

#es-modal .tabs-wrapper ul {
    margin: 0;
}

#es-modal .tabs-wrapper li {
    display: inline-block;
    margin: 0 10px 0 0;
    padding: 10px;
}

#es-modal .tabs-wrapper li:last-child {
    margin-right: 0;
}

#es-modal .tabs-wrapper a {
    color: #fcfdff;
    text-decoration: none;
}

#es-modal .tabs-wrapper .active-tab {
    background: #fff;
    -webkit-border-radius: 4px 4px 0 0;
    -moz-border-radius: 4px 4px 0 0;
    border-radius: 4px 4px 0 0;
}

#es-modal .tabs-wrapper .active-tab a {
    color: #222;
}

#es-modal .tabs-wrapper .active-tab a:focus,
#es-modal .tabs-wrapper .active-tab a:active {
    outline: none !important;
    box-shadow: none;
}

#es-modal .bs-close-modal {
    border-color: #F9D9DB;
    background-color: transparent;
    color: #f7e2e3;
}

/**************************************************************
 * 15. =>KingComposer
 **************************************************************/
/*Make it show_on option friendly*/
.m-p-body .kc-param-row {
    min-height: 0 !important;
}

.m-p-body .kc-param-row.kc-param-row select {
    width: 100%;
    max-width: 100%;
}

.m-p-body .bf-background-image-uploader-select-container:before,
.m-p-body .bf-select-option-container:before {
    height: 33px;
}

/* override king composer styles*/
.icons-list.icons-list.icons-list i {
    width: auto;
    margin: 7px 0 0;
    display: block;
    font-size: 14px;
    background: transparent;
}

/**************************************************************
 * 16. =>Elementor
 **************************************************************/

.elementor-editor-active .wp-picker-container.wp-picker-active {
    left: 0 !important;
    right: 0 !important;
}

.elementor-editor-active .bs-color-picker-wrapper .wp-picker-container .wp-color-result .color-alpha {
    margin: 0;
}

/**************************************************************
 * 17. =>Gutenberg
 **************************************************************/

body.gutenberg-editor-page .edit-post-layout__metaboxes:not(:empty) {
    background: #f1f1f1;
    padding-top: 25px;
    padding-bottom: 25px;
}

body.gutenberg-editor-page #normal-sortables .postbox {
    border: 1px solid #e5e5e5;
    background: #fff;
    margin-bottom: 25px;
}

body.gutenberg-editor-page #normal-sortables .postbox:last-child {
    margin-bottom: 0;
}

body.gutenberg-editor-page .edit-post-meta-boxes-area #poststuff h2.hndle {
    color: #191e23
}

.gutenberg-editor-page .edit-post-sidebar .bf-section-container {
    padding-right: 0;
    padding-left: 0;
}

.gutenberg-editor-page .edit-post-sidebar .bf-explain {
    margin-top: 9px;
    font-style: italic;
    opacity: 0.6;
}

.gutenberg-editor-page .edit-post-sidebar .bf-explain:empty {
    display: none;
}

.gutenberg-editor-page .edit-post-sidebar .bf-section:hover > .bf-explain {
    opacity: 0.9;
}

.gutenberg-editor-page .edit-post-sidebar .bf-heading h3 {
    margin-bottom: 5px;
}

.gutenberg-editor-page .edit-post-sidebar .bf-section-container .bf-section {
    padding-top: 15px;
    padding-bottom: 15px;
}

.gutenberg-editor-page .edit-post-sidebar .bf-repeater-item > .bf-section-container .bf-section {
    padding-bottom: 0;
}

.gutenberg-editor-page .edit-post-sidebar .bf-repeater-item > .bf-section-container:last-child .bf-section {
    padding-bottom: 10px;
}

.gutenberg-editor-page .edit-post-sidebar .select-popup-selected-image,
.gutenberg-editor-page .edit-post-sidebar .select-popup-selected-info {
    padding: 11px;
    box-sizing: border-box;
}

.gutenberg-editor-page .edit-post-sidebar .select-popup-selected-image {
    width: auto;
    max-width: inherit;
    float: none;
    line-height: 0;
    text-align: center;
    border-bottom: 1px solid #dedede;
}

.gutenberg-editor-page .edit-post-sidebar .select-popup-selected-image:before {
    display: none;
}

.gutenberg-editor-page .edit-post-sidebar .select-popup-selected-info {
    float: none;
}

.gutenberg-editor-page .edit-post-sidebar .select-popup-field {
    max-width: 250px;
}

.gutenberg-editor-page .edit-post-sidebar .select-popup-field .active-item-label {
    float: left;
}

.gutenberg-editor-page .edit-post-sidebar .select-popup-field .button {
    float: right;
}

.gutenberg-editor-page .edit-post-sidebar .select-popup-field .active-item-text {
    margin-bottom: 0;
}

.gutenberg-editor-page .edit-post-sidebar .select-popup-field .active-item-label {
    margin-bottom: 6px;
}

.gutenberg-editor-page .edit-post-sidebar .bf-repeater-item {
    padding-left: 10px;
    padding-right: 10px;
    margin-left: -3px;
    margin-right: -3px;
}

.gutenberg-editor-page .edit-post-sidebar .bf-section-bf-image-radio .bf-image-radio-option > label {
    display: none;
}

.editor-block-types-list__item[class*="better-studio"] .editor-block-icon {
    width: 50px;
}

.editor-block-types-list__item[class*="better-studio"] .editor-block-icon .block-editor__container img {
    height: auto;
    max-width: 100%;
    margin-left: auto;
    margin-right: auto;
}

.components-panel .bf-section-container {
    padding-right: 0;
    padding-left: 0;
}libs/better-framework/assets/css/rtl-admin-style.css000064400000066421151214002600016606 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */


/*

1. =>Base
    1.1. =>Main Helpers
    1.2. =>Buttons
    1.3. =>Columns
    1.4. =>General Classes

2. =>General Fields
    2.1. =>Section
    2.2. =>Heading
    2.3. =>Color
    2.4. =>Image Radio Option
    2.5. =>Media Image
    2.6. =>Background Image
    2.7. =>Sorter
    2.8. =>Ajax Select
    2.9. =>Social Counter Sorter
    2.10. =>Image Select
    2.11. =>Icon Select
    2.12. =>Typography
    2.13. =>Social Share Sorter
    2.14. =>Repeater Item
    2.15. =>Border
    2.16. =>Info
    2.17. =>Switch
    2.18. =>Fields Group
    2.19. =>Media
    2.20. =>Code Editor
    2.21. =>Term Select Field Style
    2.22. =>Selector Modal
    2.23. =>Pre Defined Styles Modal
    2.24. =>Popup Select
    2.25. =>Custom Checkbox/Radio Field

3. =>Admin Panel
    3.1. =>Section
    3.2. =>Panel
    3.3. =>Panel Header
    3.4. =>Panel Main
    3.5. =>Panel Nav
    3.6. =>Panel Content
    3.7. =>Panel Footer
    3.8. =>Typography
    3.9 =>Panel Loading

4. =>Widgets
    4.1. =>General style
    4.2. =>Section
    4.3. =>Ajax Select

5. =>Taxonomies

6. =>Visual Composer
    6.1. =>Color Picker
    6.2. =>Image Radio
    6.3. =>Ajax Select
    6.4. =>Icon Radio
    6.5. =>Heading
    6.6. =>Editor ShortCode
    6.7. =>VC Media Image
    6.8. =>VC Info
    6.9. =>Switch
    6.10. =>Select
    6.11. =>Column

7. =>Menus
    7.1. =>Mega Menu Field
    7.2. =>Menu Badge Field
    7.3. =>Heading
    7.4. =>Color Picker
    7.5. =>Checkbox

8. =>Meta Box
    8.1. =>Section
    8.2. =>Tabs
    8.3. =>Heading


9. =>Font Manager
    9.1. =>Fields

10. =>User Metabox


11. =>Admin Menus

12. =>Notice System

9. =>Last Not Refactored Codes

*/

.bf-clear-right{
    clear: left !important;
}
.bf-clear-left{
    clear: right !important;
}

/**
 * 1.2. =>Buttons
 **************************************************************/
.bf-button .fa,
.bf-button .dashicons {
    margin-left: 5px;
    margin-right: auto;
}
.bf-button i[class^="bsai-"] {
    margin-left: 4px;
    margin-right: auto;
}


/**
 * 1.3. =>Columns
 **************************************************************/
.bf-columns-2 .bf-column {
    float: right;
}
.bf-columns-2 .bf-column:nth-child(odd) {
    padding-left: 13px;
    clear: right;
    padding-right: 0;
}
.bf-columns-2 .bf-column:nth-child(even) {
    padding-right: 13px;
    padding-left: 0;
}
/* 3 Column */
.bf-columns-3 .bf-column {
    float: right;
}
.bf-columns-3 .bf-column:nth-child( 3n-2 ) {
    padding-left: 12px;
    clear: right;
    padding-right: 0;
}
.bf-columns-3 .bf-column:nth-child( 3n+3  ) {
    padding-right: 12px;
    padding-left: 0;
}

/* 4 Column */
.bf-columns-4 .bf-column {
    float: right;
}
.bf-columns-4 .bf-column:nth-child(4n-3) {
    padding-right: 0;
    padding-left: 12px;
    clear: right;
}
.bf-columns-4 .bf-column:nth-child(4n+2) {
    padding-right: 6px;
    padding-left: 6px;
}
.bf-columns-4 .bf-column:nth-child(4n+3) {
    padding-right: 6px;
    padding-left: 6px;
}
.bf-columns-4 .bf-column:nth-child(4n+4) {
    padding-left: 0;
    padding-right: 12px;
}


/**
 * 1.4. =>General Classes
 **************************************************************/
.bf-item-container {
    float: right;
    margin-left: 22px;
    margin-right: auto;
}
.bf-item-title {
    text-align: right;
    padding: 12px 12px 12px 0;
}
.bf-item-buttons {
    float: left;
}
.bf-item-buttons a {
    margin: 0 0 0 12px;
}
.bf-item-buttons a:last-child {
    margin-left: 0;
    margin-right: auto;
}
.bf-item-buttons>span {
    float: left;
}
.bf-item-buttons>span:last-child {
    margin-right: 0;
    margin-left: auto;
}


/**
 * 2. =>General Fields
 **************************************************************/
/***** Field Prefix or Suffix ******/
.bf-field-with-suffix.bf-field-with-prefix input[type=text] {
    padding-left: 10px !important;
    padding-right: 10px !important;
}
.bf-field-with-prefix span.bf-prefix {
    margin-left: -5px;
    border-left: none;
    margin-right: auto;
    border-right: none;
}
.bf-field-with-suffix span.bf-suffix {
    margin-right: -5px;
    border-right: none;
    margin-left: auto;
    border-left: none;
}

/* text helpers */
.bf-text-left {
    text-align: left;
}
.bf-text-right {
    text-align: right;
}


/**
 * 2.1. =>Section
 **************************************************************/
.bf-section-container {
    padding-left: 20px;
    padding-right: 20px;
}
.bf-section-container .bf-section.full-with-both > .bf-explain,
.bf-section-container .bf-section.full-with-both > .bf-heading,
.bf-section-container .bf-section.full-with-heading > .bf-heading {
    padding-left: 0 !important;
    padding-right: 0;
}


/**
 * 2.2. =>Heading
 **************************************************************/


/**
 * 2.3. =>Color
 **************************************************************/
.bf-section-container .bf-color-picker-preview {
    left: 5px;
    right: auto;
}


/**
 * 2.4. =>Image Radio Option
 **************************************************************/
.bf-section-container .style-floated-right .bf-image-radio-option {
    float: right;
    margin-left: 6px;
    margin-right: auto;
}


/**
 * 2.5. =>Media Image
 **************************************************************/
.bf-section-container .bf-section-media_image-option .bf-media-image-remove-btn {
    margin-right: 10px;
    margin-left: auto;
}


/**
 * 2.6. =>Background Image
 **************************************************************/
.wpb_edit_form_elements .bf-section-container .bf-background-image-remove-btn,
.bf-section-container .bf-background-image-remove-btn {
    margin-right: 10px;
    margin-left: auto;
}


/**
 * 2.7. =>Sorter
 **************************************************************/
.bf-section-container .ui-slider .ui-slider-range:after {
    left: -7px;
    right: auto;
}
.bf-section-container .ui-slider .ui-slider-handle {
    right: 0 !important;
    left: auto;
}


/**
 * 2.8. =>Ajax Select
 **************************************************************/
.bf-ajax_select-field-container input {
    padding: 0px 15px 0 36px;
}
.bf-ajax_select-field-container span.bf-search-loader {
    left: 1px;
    border-right: 1px solid #d9d9d9;
    right: auto;
    border-left: none;
}
.bf-ajax-suggest-search-results {
    right: 0px;
    left: auto;
}
.bf-ajax-suggest-controls > li {
    margin: 9px 0 9px 9px;
}
.bf-ajax-suggest-controls > li .del {
    margin-right: 8px;
    margin-left: auto;
}


/**
 * 2.9. =>Social Counter Sorter
 **************************************************************/
.bf-section-container.vc-input .bf-vc-sorter-list li input {
    margin: -5px 5px 0 2px;
}
.bf-section-container.vc-input .bf-vc-sorter-list li:after,
.bf-section-container .better-social-counter-sorter .bf-sorter-list li:after {
    left: 7px;
    right: auto;
}


/**
 * 2.10. =>Image Select
 **************************************************************/
.bf-section-container .better-select-image .select-label {
    padding-left: 8px;
    padding-right: 0;
}
.bf-section-container .better-select-image .select-options:after {
    left: -1px;
    right: auto;
}
.bf-section-container .better-select-image .select-options .better-select-image-options {
    right: -1px;
    left: -1px;
}

/* 2 Column Style */
.bf-section-container .better-select-image.opened .select-options .better-select-image-options ul.grid-2-column li {
    float: right;
}
.bf-section-container .better-select-image.opened .select-options .better-select-image-options ul.grid-2-column li:nth-child(odd) {
    margin-left: 4px;
    margin-right: auto;
}
.bf-section-container .better-select-image.opened .select-options .better-select-image-options ul.grid-2-column li:nth-child(even) {
    margin-right: 4px;
    margin-left: auto;
}

/* 3 Column Style */
.bf-section-container .better-select-image.opened .select-options .better-select-image-options ul.grid-3-column li {
    float: right;
}
.bf-section-container .better-select-image.opened .select-options .better-select-image-options ul.grid-3-column li:nth-child(3n-1) {
    margin-left: 4px;
    margin-right: 4px;
}

/* 4 Column Style */
.bf-section-container .better-select-image.opened .select-options .better-select-image-options ul.grid-4-column li {
    float: right;
}
.bf-section-container .better-select-image.opened .select-options .better-select-image-options ul.grid-4-column li {
    margin-left: 4px;
    float: right;
    margin-right: auto;
}
.bf-section-container .better-select-image.opened .select-options .better-select-image-options ul.grid-4-column li:nth-child(16),
.bf-section-container .better-select-image.opened .select-options .better-select-image-options ul.grid-4-column li:nth-child(8),
.bf-section-container .better-select-image.opened .select-options .better-select-image-options ul.grid-4-column li:nth-child(4) {
    margin-left: 0px;
    margin-right: auto;
}


/**
 * 2.11. =>Icon Select
 **************************************************************/
.bf-section-container .bf-icon-modal-handler .select-options .selected-option .text-muted {
    margin-right: 3px;
    margin-left: auto;
}
.bf-section-container .bf-icon-modal-handler .select-options .selected-option .bf-icon {
    margin-left: 4px;
    text-align: right;
    margin-right: auto;
}
.bf-section-container .bf-icon-modal-handler .select-options:before {
    left: 0px;
    border-right: 1px solid #d9d9d9;
    right: auto;
    border-left: none;
}


/**
 * 2.12. =>Typography
 **************************************************************/
.bf-section-container .typo-field-container {
    float: right;
}
.bf-section-container .typo-field-container:before {
    left: 10px !important;
    right: auto !important;
}
.bf-section-container .bf-section.bf-section-typography-option .bf-heading {
    padding: 0 10px 0 !important ;
}
.bf-section-container .typo-field-container .bf-field-with-prefix span {
    border-left: 1px solid #d9d9d9;
    border-right: none;
}
.bf-section-container .typo-field-container .bf-field-with-suffix span {
    border-right: 1px solid #d9d9d9;
}
.bf-section-container .typography-preview .preview-tab .tab {
    float: right;
}
.bf-section-container .typography-preview .preview-tab .tab a {
    border-left: none;
    border-right: none;
}
.bf-section-container .typography-preview .preview-tab .tab:last-child a {
    border-left: 1px solid #d3d3d3;
    border-right: none;
}
.bf-section-typography-option.have-enable-field.disable-field .enable-disable,
.bf-section-typography-option.have-enable-field.disable-field .bf-explain:before {
    right: 0;
    left: auto;
}
.typo-field-container .chosen-container-single .chosen-single div {
    border-right: 1px solid #D6D6D6;
    border-left: none;
}
.typo-field-container .chosen-container-single.chosen-rtl .chosen-single div {
    border-right: none;
    border-left: 1px solid #D6D6D6;
    right: 0;
    left: auto;
}


/**
 * 2.13. =>Social Share Sorter
 **************************************************************/
.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li {
    margin-left: 10px;
    margin-right: 0;
}
.bf-section-container.vc-input.bs-theme-social-share-sorter .bf-vc-sorter-list li .fa,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li .fa {
    margin-left: 5px;
    margin-right: auto;
}
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.item-line .fa.fa-line-it {
    margin-right: -5px;
    margin-left: auto;
}
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.item-bbm .fa.fa-bbm {
    margin-right: -5px;
    margin-left: auto;
}
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li.item-viber .fa.fa-viber {
    margin-right: -5px;
    margin-left: auto;
}
.bf-section-container.vc-input.bs-theme-social-share-sorter li input,
.bf-section-container .bs-theme-social-share-sorter .bf-sorter-list li input {
    margin-left: 10px;
    margin-right: auto;
}


/**
 * 2.14. =>Repeater Item
 **************************************************************/
.bf-repeater-item .bf-remove-repeater-item-btn {
    float: left;
}

/* repeator item title */
.bf-repeater-item .bf-repeater-item-title {
    padding: 0 15px 0 55px;
}

/* repeater item handle */
.bf-repeater-item .bf-repeater-item-title .handle-repeater-item {
    float: left;
    left: -1px;
    right: auto;
}


/**
 * 2.15. =>Border
 **************************************************************/


/**
 * 2.16. =>Info
 **************************************************************/
.bf-section-container .bf-section-info .bf-section-info-title .fa {
    margin-left: 3px;
    margin-right: auto;
}
.bf-section-container .bf-section-info .info-value ul {
    padding-right: 20px;
    padding-left: 0;
}
.bf-section-container .bf-section-info .info-value ol {
    padding-right: 20px;
    padding-left: 0;
}


/**
 * 2.17. =>Switch
 **************************************************************/
.bf-switch .cb-enable,
.bf-switch .cb-disable,
.bf-switch .cb-enable span,
.bf-switch.cb-disable span {
    float: right;
}
.bf-switch .cb-enable span {
    border-left-color: transparent;
}
.bf-switch .cb-enable:hover span {
    border-left-color: transparent;
}
.bf-switch .cb-disable span {
    border-right-color: transparent;
}
.bf-switch .cb-disable:hover span {
    border-right-color: transparent;
}
.bf-switch .cb-disable span {
    border-radius: 33px 0 0 33px;
}
.bf-switch .cb-enable span {
    border-radius: 0 33px 33px 0;
}


/**
 * 2.18. =>Fields Group
 **************************************************************/
.fields-group .fields-group-title-container .fields-group-title {
    padding: 0 20px 0 62px;
}
.fields-group.collapsible .fields-group-title-container .collapse-button {
    left: -1px;
    right: auto;
}


/**
 * 2.19. =>Media
 **************************************************************/
.bf-section-container .bf-section.bf-section-media-option .bf-controls input[type=text] {
    float: right;
}
.bf-section-container .bf-section.bf-section-media-option .bf-controls .bf-media-upload-btn {
    float: left;
}


/**
 * 2.20. =>Code Editor
 **************************************************************/


/**
 *   2.21. =>Term Select Field Style
 **************************************************************/
.bf-checkbox-multi-state {
    margin: 0 0 0 5px;
}
.bf-checkbox-multi-state > span {
    left: 0;
    right: 0;
}
.bf-field-term-select-help {
    text-align: right;
}
.bf-field-term-select-help .bf-checkbox-multi-state {
    margin:0 9px 0 0;
}
.bf-field-term-select-wrapper {
    padding: 3px 0 0px 10px;
}
.bf-field-term-select-wrapper li:before {
    right: -22px;
    left: auto;
}
.bf-field-term-select-wrapper li li:last-child:after {
    right: -32px;
    left: auto;
}
.bf-field-term-select-wrapper ul {
    border-right:1px solid #CECECC;
    padding: 0 22px 0 0;
    border-left: none;
}
.bf-field-term-select-wrapper ul ul {
    margin-right: 9px;
    margin-left: auto;
}
.bf-field-term-select-wrapper .bf-make-term-primary,
.bf-field-term-select-wrapper .bf-excluded-term {
    margin-right: 15px;
    margin-left: auto;
}
.bf-field-term-select-wrapper .bf-make-term-primary:before ,
.bf-field-term-select-wrapper .bf-excluded-term:before {
    margin-left: 10px;
    margin-right: auto;
}


/**
* 2.22. =>Selector Modal
 **************************************************************/
.bssm-list {
    padding: 20px 20px 20px 0;
}
.bssm-item {
    text-align: right;
    margin: 0 0 15px 15px;
}
.bssm-style-1 .bssm-item {
    margin: 0 0 22px 22px;
}
.bssm-style-1 .bssm-selected:before {
    left: 0;
    right: auto;
}
.bssm-style-1 .bssm-info {
    text-align: right;
}
.bssm-style-1 .bssm-info > .bssm-styles {
    float: left;
}
.bssm-content {
    margin-left: 260px;
    margin-right: auto;
}


/**
* 22.23. =>Pre Defined Styles Modal
 **************************************************************/
.pds-modal .bf-item-title {
    padding:9px 12px 9px 0;
}


/**
* 22.24. =>Popup Select
 **************************************************************/
.bf-checkbox-multi-state,
.bf-radio-field {
    margin: 0 0 0 5px;
}
.bf-radio-field .fa {
    right: 50%;
    margin-right: -6px;
    left: auto;
    margin-left: auto;
}


/**
* 22.25. =>Custom Checkbox/Radio Field
 **************************************************************/
.select-popup-selected-image {
    float: right;
}
.select-popup-selected-image:before {
    left: 0;
    right: auto;
}
.select-popup-selected-info {
    float: right;
}


/**
* Selector Modal Sidebar
*/
.bssm-sidebar {
    border-right: 1px solid #cecece;
    left: 0;
    right: auto;
    border-left: none;
}
.bssm-sidebar .title span {
    padding-left: 12px;
    padding-right: 0;
}
.bssm-sidebar .title:after {
    right: 0;
    left: auto;
}
.bssm-search .fa {
    left: 14px;
    right: auto;
}
.bssm-search-input {
    padding: 0 18px 0 30px;
}
.bs-selector-modal .bf-checkbox-multi-state[data-current-state="active"] .fa,
.bs-selector-modal .bf-checkbox-multi-state[data-current-state="active"] + .label {
    margin-right: -1px;
    margin-left: auto;
}
.bssm-filter .length {
    left: 0;
    right: auto;
}
.bssm-button .fa {
    margin-left: 5px;
    margin-right: auto;
}
.bssm-sidebar-footer {
    left: -10px;
    right: -10px;
}


/*
    Upload Font Modal Style
*/
.bs-font-upload-modal .font-woff,
.bs-font-upload-modal .font-ttf,
.bs-font-upload-modal .font-svg,
.bs-font-upload-modal .font-eot {
    float: right;
}
.bs-font-upload-modal .input-section .bssm-button {
    left: -10px;
    border-radius: 19px 0 0 19px;
    right: auto;
}
.bs-font-upload-modal .bf-choose-fonts .input {
    padding-left: 105px;
    padding-right: 15px;
}


/**
 * 3. =>Admin Panel
 **************************************************************/
.bf-admin-panel .panel-wrapper {
    margin-right: -20px;
    margin-left: auto;
}
.bf-page-header.sticky {
    right: 0;
    left: auto;
}
.bf-page-header.sticky .bf-page-header-inner {
    padding: 20px 190px 20px 30px;
}
.bf-page-header .bf-options-change-notice {
    right: 50%;
    left: auto;
}
.bf-page-header .bf-options-change-notice:before {
    margin-left: 4px;
    margin-right: auto;
}


/**
 * 3.1. =>Section
 **************************************************************/
.bf-section-container.bf-admin-panel .bf-section .bf-heading {
    float: right;
    padding: 0 0 0 20px;
}
.bf-section-container.bf-admin-panel .bf-section .bf-heading h3 {
    margin: 0 8px 0 !important;
}
.bf-section-container.bf-admin-panel .bf-section .bf-controls {
    float: left;
}
.bf-section-container.bf-admin-panel .bf-section .bf-explain {
    float: right;
    padding: 0 0 0 15px;
    clear: right;
}


/**
 * 3.2. =>Panel
 **************************************************************/
#bf-panel .fleft {
    float: left;
}
#bf-panel .fright {
    float: right;
}


/**
 * 3.3. =>Panel Header
 **************************************************************/
.bf-header .logo-sec {
    float: right;
    padding-right: 18px;
    padding-left: 0;
}
.bf-header .save-btn-sec {
    float: left;
}
.bf-header .logo .version {
    margin-right: 5px;
    margin-left: auto;
}


/**
 * 3.4. =>Panel Main
 **************************************************************/


/**
 * 3.5. =>Panel Nav
 **************************************************************/
#bf-nav {
    float: right;
}
#bf-nav>ul>li a {
    padding: 14px 16px 14px 0;
    border-right: 1px solid #E8E8E8;
    border-left: none;
}
#bf-nav>ul>li a .bf-icon {
    margin: 0 0 0 7px;
    float: right;
}
#bf-nav>ul>li.child_active>a:after,
#bf-nav>ul>li a.active_tab:after {
    left: -1px;
    right: auto;
}
.bf-tab-badge {
    left: 10px;
    right: auto;
}
.bf-tab-badge:after {
    right: -10px;
    border-left-color: inherit;
    border-right-color: transparent;
    left: auto;
}


/**
 * 3.6. =>Panel Content
 **************************************************************/
#bf-content {
    float: left;
}


/**
 * 3.7. =>Panel Footer
 **************************************************************/
#bf-panel .bf-footer .reset-sec {
    float: right;
}


/**
 * 3.8. =>Typography
 **************************************************************/


/**
 * 3.9 =>Panel Loading
 **************************************************************/
#bf-panel .bf-loading {
    right: 0;
    left: auto;
}
#bf-panel .bf-loading .loader {
    right: 50%;
    margin-right: -150px;
    left: auto;
    margin-left: auto;
}
#bf-panel .bf-loading .loader .loader-icon {
    right: 50%;
    margin-right: -30px;
    left: auto;
    margin-left: auto;
}
#bf-panel .bf-loading .loader .message {
    right: auto;
    left: auto;
}


/**
 * 4.3. =>Ajax Select
 **************************************************************/
.bf-section-container.bf-widgets .bf-ajax_select-field-container span.preloader {
    right: initial;
    left: 5px;
}


/**
 * 6. =>Visual Composer
 **************************************************************/
.bf-css-edit-switch-container {
    float: right !important;
}
.vc_shortcode-param .bf-section-container {
    padding-left: 0;
    padding-right: 0;
}


/**
 * 6.1. =>Color Picker
 **************************************************************/
.wpb_edit_form_elements .bf-section-container .bf-color-picker-preview {
    right: -26px;
    left: auto;
}


/**
 * 6.2. =>Image Radio
 **************************************************************/
.bf-section-container .style-floated-left .bf-image-radio-option {
    float: right;
    margin-left: 6px;
    margin-right: auto;
}


/**
 * 6.3. =>Ajax Select
 **************************************************************/
.vc_row-fluid .bf-ajax-suggest-search-results {
    right: initial;
    left: auto;
}
.vc_row-fluid .bf-ajax_select-field-container span.preloader {
    right: inherit;
    left: 10px;
}


/**
 * 6.7. =>VC Media Image
 **************************************************************/
.bf-section-container.vc-input .bf-media-image-remove-btn {
    margin-right: 10px;
    margin-left: auto;
}


/**
 * 6.11. =>Column
 **************************************************************/
.bf-vc-third-column {
    float: right !important;
}


/**
 * 7. =>Menus
 **************************************************************/
.better-menu-container {
    float: right;
}
.bf-section-container.bf-menus .bf-field-with-prefix span,
.bf-section-container.bf-menus .bf-field-with-suffix span {
    margin-right: -2px;
    margin-left: auto;
}


/**
 * 7.1. =>Mega Menu Field
 **************************************************************/
.menu-item.menu-item-depth-0 .fields-group#fields-group-mega_menu_heading .bf-field-mega_menu_cat {
    margin-left: 0;
    margin-right: auto;
}


/**
 * 7.3. =>Heading
 **************************************************************/
.bf-section-container.bf-menus .bf-section-heading .bf-section-heading-title h3 {
    margin: 0 0px -2px 0  ;
}


/**
 * 7.8. =>Group
 **************************************************************/
.menu-item .fields-group {
    float: right;
}
.menu-item .fields-group .fields-group-title-container .fields-group-title {
    padding: 0 16px 0 62px;
}


/**
 * 8.1. =>Section
 **************************************************************/
.bf-section-container.bf-metabox .bf-section .bf-heading {
    float: right;
    padding: 0 0 0 20px;
}
.bf-section-container.bf-metabox .bf-section .bf-heading h3 {
    margin: 0 8px 0 !important;
}
.bf-section-container.bf-metabox .bf-section.no-desc .bf-controls,
.bf-section-container.bf-metabox .bf-section .bf-controls {
    float: left;
}
.bf-section-container.bf-metabox .bf-section .bf-explain {
    float: right;
    padding: 0 0 0 15px;
    clear: right;
}
.bf-section-container .bf-controls-background_image-option .bf-background-image-uploader-select-container:before,
.bf-section-container .bf-select-option-container:before {
    left: 0;
    right: auto;
}
.bf-section-container.dir-ltr .bf-section .bf-controls.bf-controls-text-option input[type=text] {
    text-align: right;
}
.bf-section-container.dir-rtl .bf-section .bf-controls.bf-controls-text-option input[type=text] {
    text-align: left;
}
.bf-section-container.dir-ltr .bf-section .bf-controls textarea,
.bf-section-container.dir-ltr .bf-section .bf-controls select,
.bf-section-container.dir-ltr .bf-section .bf-controls .select-placeholder {
    text-align: right;
}
.bf-section-container.dir-rtl .bf-section .bf-controls textarea,
.bf-section-container.dir-rtl .bf-section .bf-controls select ,
.bf-section-container.dir-rtl .bf-section .bf-controls .select-placeholder {
    text-align: left;
}


/**
 * 8.2. =>Tabs
 **************************************************************/
.bf-metabox-tabs {
    float: right;
}
.bf-metabox-tabs .bf-tab-item-a .tab-icon {
    margin-left: 6px;
    margin-right: auto;
}
.bf-metabox-tabs .bf-tab-item-a.active_tab:after {
    left: -1px;
    right: auto;
}
.bf-metabox-container.bf-with-tabs {
    float: left;
    border-right: 1px solid #e2dddb;
    border-left: none;
}


/**
 * 9. =>Font Manager
 **************************************************************/
.bf-section-container.better-font-stack-name {
    float: right;
    padding-right: 2%;
    padding-left: 2%;
}
.bf-section-container.better-font-stack-stack {
    float: left;
    padding-left: 2%;
    padding-right: 2%;
}


/**
 * 9.1. =>Fields
 **************************************************************/
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-svg,
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-woff {
    float: right;
}
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-svg {
    clear: right;
}
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-eot,
.bf-repeater-item .repeater-item-container .bf-section-container.better-custom-fonts-ttf {
    float: left;
}


/***
    Notice Styles
**/
.bf-notice {
    margin: 5px 0 2px 10px;
}
.bf-notice.bf-notice-dismissible {
    padding-left: 40px;
    padding-right: 0;
}
.bf-notice-text-container {
    padding-left: 0;
    padding-right: 12px;
}
.bf-notice .bf-notice-thumbnail {
    margin-left: 12px;
    margin-right: auto;
}
.bf-notice-no-thumbnail.bf-notice-success {
    border-right: 4px solid #46b450;
    border-left: none;
}
.bf-notice-no-thumbnail.bf-notice-warning {
    border-right:4px solid #ffb900;
    border-left: none;
}
.bf-notice-no-thumbnail.bf-notice-danger {
    border-right:4px solid #dc3232;
    border-left: none;
}
.bf-notice-dismiss {
    left: 1px;
    right: auto;
}


/*-------------------------------------------------------------------------------------------*/
/* bf Meta Box styles */
/*-------------------------------------------------------------------------------------------*/
.ui-slider .ui-slider-range:after {
    left: -7px;
    right: auto;
}
.bf-metabox-tabs .bf-tab-item-a .bf-icon{
    float: right;
    margin-left: 8px;
}
libs/better-framework/assets/css/pretty-photo.min.css000064400000016305151214002600017015 0ustar00.pp_gallery div,.pp_gallery ul a,.pp_social .facebook{overflow:hidden;float:left}a.pp_contract,a.pp_expand,div.pp_default .pp_next:hover,div.pp_default .pp_previous:hover{cursor:pointer}div.pp_default .pp_bottom,div.pp_default .pp_bottom .pp_left,div.pp_default .pp_bottom .pp_middle,div.pp_default .pp_bottom .pp_right,div.pp_default .pp_top,div.pp_default .pp_top .pp_left,div.pp_default .pp_top .pp_middle,div.pp_default .pp_top .pp_right{height:13px}div.pp_default .pp_content .ppt{color:#f8f8f8}div.pp_default .pp_content_container{background-color:#fff;padding:16px 10px 10px}div.pp_default .pp_content_container .pp_left{padding-left:13px}div.pp_default .pp_content_container .pp_right{padding-right:13px}div.pp_default .pp_content{background-color:#fff;margin:auto}div.pp_default .pp_next .fa,div.pp_default .pp_previous .fa{width:34px;height:34px;background-color:#fff;color:#5F5F5F;position:absolute;top:50%;margin-top:-12px;right:0;opacity:0;-webkit-transition:all .3s ease;-moz-transition:all .3s ease;-o-transition:all .3s ease;transition:all .3s ease;text-align:center;line-height:34px;-ms-transform:scale(.93,.93);-webkit-transform:scale(.93,.93);transform:scale(.93,.93)}div.pp_default .pp_next:hover .fa{right:15px;opacity:1;-ms-transform:scale(1,1);-webkit-transform:scale(1,1);transform:scale(1,1)}div.pp_default .pp_previous .fa{right:initial;left:0}div.pp_default .pp_previous:hover .fa{left:15px;opacity:1;-ms-transform:scale(1,1);-webkit-transform:scale(1,1);transform:scale(1,1)}div.pp_default .pp_close,div.pp_default .pp_contract,div.pp_default .pp_expand{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:400;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;cursor:pointer;width:30px;height:30px;background-color:#fff;line-height:27px;text-align:center;color:#5F5F5F;text-decoration:none;opacity:.9;border:2px solid #5F5F5F}div.pp_default .pp_expand:before{content:"\f065"}div.pp_default .pp_contract:before{content:"\f066"}div.pp_default .pp_contract:hover,div.pp_default .pp_expand:hover{opacity:1}div.pp_default .pp_nav .pp_pause,div.pp_default .pp_nav .pp_play,div.pp_default a.pp_arrow_next,div.pp_default a.pp_arrow_previous{background-color:#E4E4E4;color:#5F5F5F;width:28px;height:28px;text-align:center;line-height:28px;text-decoration:none}div.pp_default .pp_close:before{content:"\f00d"}div.pp_default .pp_close:hover{color:#e42a30}div.pp_default .pp_nav .pp_pause,div.pp_default .pp_nav .pp_play{width:34px;height:34px;line-height:34px;font-size:18px}div.pp_default .pp_nav .pp_pause .fa-play:before{content:"\f04c"}div.pp_default a.pp_arrow_next,div.pp_default a.pp_arrow_previous{padding-left:0;margin-top:6px!important;margin-right:4px}div.pp_default .pp_gallery a.pp_arrow_previous{margin-right:10px;margin-top:3px!important}div.pp_default .pp_gallery a.pp_arrow_next{margin-left:10px;margin-top:3px!important}div.pp_default #pp_full_res .pp_inline{color:#000}div.pp_default .pp_gallery ul li a{border:2px solid #E4E4E4}div.pp_default .pp_gallery ul li a:hover,div.pp_default .pp_gallery ul li.selected a{border-color:#999}div.pp_default .pp_social{margin-top:7px}div.pp_default .pp_gallery a.pp_arrow_next,div.pp_default .pp_gallery a.pp_arrow_previous{position:static;left:auto}div.pp_default .pp_details{position:relative}div.pp_default .pp_content_container .pp_details,div.pp_default a.pp_arrow_previous{margin-top:3px}div.pp_default .pp_content_container .pp_gallery~.pp_details{margin-top:55px}div.pp_default .pp_nav{clear:none;height:30px;width:110px;position:relative}div.pp_default .pp_nav .currentTextHolder{font-family:Georgia;font-style:italic;color:#999;font-size:12px;left:105px;line-height:25px;margin:0;padding:0 0 0 10px;position:absolute;top:6px}div.pp_default .pp_arrow_next:hover,div.pp_default .pp_arrow_previous:hover,div.pp_default .pp_close:hover,div.pp_default .pp_nav .pp_pause:hover,div.pp_default .pp_nav .pp_play:hover{opacity:.7}div.pp_default .pp_description{font-size:12px;line-height:14px;margin:16px 10px 5px 180px}div.pp_default .pp_loaderIcon{background:url(../img/pretty-photo-loader.gif) center center no-repeat}div.pp_pic_holder a:focus{outline:0}div.pp_overlay{background:#000;display:none;left:0;position:absolute;top:0;width:100%;z-index:99999}div.pp_pic_holder{display:none;position:absolute;width:100px;z-index:999999;-webkit-box-shadow:0 0 0 6px rgba(0,0,0,.2);-moz-box-shadow:0 0 0 6px rgba(0,0,0,.2);-ms-box-shadow:0 0 0 6px rgba(0,0,0,.2);box-shadow:0 0 0 6px rgba(0,0,0,.2)}.pp_top{height:20px;position:relative}* html .pp_top{padding:0 20px}.pp_top .pp_left{height:20px;left:0;position:absolute;width:20px}.pp_top .pp_middle{height:20px;left:20px;position:absolute;right:20px}* html .pp_top .pp_middle{left:0;position:static}.pp_top .pp_right{height:20px;left:auto;position:absolute;right:0;top:0;width:20px}.pp_content{height:40px;min-width:40px}* html .pp_content{width:40px}.pp_fade{display:none}.pp_content_container{position:relative;text-align:left;width:100%}.pp_content_container .pp_left{padding-left:20px}.pp_content_container .pp_right{padding-right:20px}.pp_content_container .pp_details{float:left;margin:10px 0 2px}.pp_description{display:none;margin:0}.pp_social{float:left;margin:0}.pp_social .facebook{margin-left:5px;width:55px}.pp_social .twitter{float:left}.pp_nav{clear:right;float:left;margin:3px 10px 0 0}.pp_nav p{float:left;margin:2px 4px;white-space:nowrap}.pp_nav .pp_pause,.pp_nav .pp_play{float:left;margin-right:4px}a.pp_arrow_next,a.pp_arrow_previous{display:block;float:left;height:15px;margin-top:3px;overflow:hidden;width:14px}.pp_hoverContainer{position:absolute;top:0;width:100%;z-index:2000}.pp_gallery{display:block!important;opacity:1!important;position:absolute;left:50%;padding-top:15px}.pp_gallery div{position:relative}.pp_gallery ul{float:left;height:35px;margin:0 0 0 5px;padding:0;position:relative;white-space:nowrap}.pp_gallery ul a{border:1px solid #000;border:1px solid rgba(0,0,0,.5);display:block;height:33px}.pp_gallery li.selected a,.pp_gallery ul a:hover{border-color:#fff}.pp_gallery ul a img{border:0}.pp_gallery li{display:block;float:left;margin:0 3px 0 0;padding:0}.pp_gallery li.default a{display:block;height:33px;width:50px}.pp_gallery li.default a img{display:none}a.pp_next,a.pp_previous{display:block;height:100%;width:49%}.pp_gallery .pp_arrow_next,.pp_gallery .pp_arrow_previous{margin-top:7px!important}a.pp_next{float:right}a.pp_previous{float:left}a.pp_contract,a.pp_expand{display:none;height:20px;position:absolute;right:60px;top:25px;width:20px;z-index:20000}a.pp_close{display:block;position:absolute;right:25px;top:25px;z-index:4000}.pp_bottom{height:20px;position:relative}* html .pp_bottom{padding:0 20px}.pp_bottom .pp_left{height:20px;left:0;position:absolute;width:20px}.pp_bottom .pp_middle{height:20px;left:20px;position:absolute;right:20px}* html .pp_bottom .pp_middle{left:0;position:static}.pp_bottom .pp_right{height:20px;left:auto;position:absolute;right:0;top:0;width:20px}.pp_loaderIcon{display:block;height:24px;left:50%;margin:-12px 0 0 -12px;position:absolute;top:50%;width:24px}#pp_full_res{line-height:1!important}#pp_full_res .pp_inline{text-align:left}#pp_full_res .pp_inline p{margin:0 0 15px}div.ppt{background-color:#fff;display:none!important;font-size:17px;margin:0;z-index:9999;padding:10px 10px 0 15px;width:100%!important}libs/better-framework/assets/css/better-modals.css000064400000047345151214002600016327 0ustar00/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2017 <--/
 */


/*
 *  Better Modals
 */


/* Hide scroll bar */

html.remodal-is-locked {
    overflow: hidden;
}

/* Anti FOUC */

.remodal,
[data-remodal-id] {
    display: none;
}

/* Necessary styles of the overlay */

.remodal-overlay {
    position: fixed;
    z-index: 100010;
    top: -5000px;
    right: -5000px;
    bottom: -5000px;
    left: -5000px;
    display: none;
}

/* Necessary styles of the wrapper */

.remodal-wrapper {
    position: fixed;
    z-index: 100020;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;

    display: none;
    overflow: auto;

    text-align: center;

    -webkit-overflow-scrolling: touch;
}

.remodal-wrapper:after {
    display: inline-block;

    height: 100%;
    margin-left: -0.05em;

    content: "";
}

/* Fix iPad, iPhone glitches */

.remodal-overlay,
.remodal-wrapper {
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
}

/* Necessary styles of the modal dialog */

.remodal {
    position: relative;

    -webkit-text-size-adjust: 100%;
    -moz-text-size-adjust: 100%;
    -ms-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

.remodal-is-initialized {
    /* Disable Anti-FOUC */
    display: inline-block;
}


/* ==========================================================================
   Remodal's default mobile first theme
   ========================================================================== */

/* Default theme styles for the background */

.remodal-bg.remodal-is-opening,
.remodal-bg.remodal-is-opened {
    -webkit-filter: blur(3px);
    filter: blur(3px);
}

/* Default theme styles of the overlay */

.remodal-overlay {
    background: rgba(43, 46, 56, 0.9);
}

.remodal-overlay.remodal-is-opening,
.remodal-overlay.remodal-is-closing {
    -webkit-animation-fill-mode: forwards;
    animation-fill-mode: forwards;
}

.remodal-overlay.remodal-is-opening {
    -webkit-animation: remodal-overlay-opening-keyframes 0.3s;
    animation: remodal-overlay-opening-keyframes 0.3s;
}

.remodal-overlay.remodal-is-closing {
    -webkit-animation: remodal-overlay-closing-keyframes 0.3s;
    animation: remodal-overlay-closing-keyframes 0.3s;
}

/* Default theme styles of the wrapper */

.remodal-wrapper {
    padding: 10px 10px 0;
}

/* Default theme styles of the modal dialog */

.remodal {
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
    width: 100%;
    margin-bottom: 10px;
    padding: 0;

    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);

    color: #2b2e38;
    background: #fff;
}

.remodal.remodal-is-opening,
.remodal.remodal-is-closing {
    -webkit-animation-fill-mode: forwards;
    animation-fill-mode: forwards;
}

.remodal.remodal-is-opening {
    -webkit-animation: remodal-opening-keyframes 0.3s;
    animation: remodal-opening-keyframes 0.3s;
}

.remodal.remodal-is-closing {
    -webkit-animation: remodal-closing-keyframes 0.3s;
    animation: remodal-closing-keyframes 0.3s;
}

/* Vertical align of the modal dialog */

.remodal,
.remodal-wrapper:after {
    vertical-align: middle;
}

/* Close button */

.remodal-close {
    position: absolute;
    top: 0;
    left: 0;

    display: block;
    overflow: visible;

    width: 35px;
    height: 35px;
    margin: 0;
    padding: 0;

    cursor: pointer;
    -webkit-transition: color 0.2s;
    transition: color 0.2s;
    text-decoration: none;

    color: #95979c;
    border: 0;
    outline: 0;
    background: transparent;
}

.remodal-close:hover {
    color: #2b2e38;
}

.remodal-close:before {
    font-family: Arial, "Helvetica CY", "Nimbus Sans L", sans-serif !important;
    font-size: 25px;
    line-height: 35px;

    position: absolute;
    top: 0;
    left: 0;

    display: block;

    width: 35px;

    content: "\00d7";
    text-align: center;
}

/* Dialog buttons */

.remodal-confirm,
.remodal-cancel {
    font: inherit;

    display: inline-block;
    overflow: visible;

    min-width: 110px;
    margin: 0;
    padding: 12px 0;

    cursor: pointer;
    -webkit-transition: background 0.2s;
    transition: background 0.2s;
    text-align: center;
    vertical-align: middle;
    text-decoration: none;

    border: 0;
    outline: 0;
}

.remodal-confirm {
    color: #fff;
    background: #81c784;
}

.remodal-confirm:hover {
    background: #66bb6a;
}

.remodal-cancel {
    color: #fff;
    background: #e57373;
}

.remodal-cancel:hover {
    background: #ef5350;
}

/* Remove inner padding and border in Firefox 4+ for the button tag. */

.remodal-confirm::-moz-focus-inner,
.remodal-cancel::-moz-focus-inner {
    padding: 0;

    border: 0;
}

/* Keyframes
   ========================================================================== */

@-webkit-keyframes remodal-opening-keyframes {
    from {
        -webkit-transform: scale(1.05);
        transform: scale(1.05);

        opacity: 0;
    }
    to {
        -webkit-transform: none;
        transform: none;

        opacity: 1;
    }
}

@keyframes remodal-opening-keyframes {
    from {
        -webkit-transform: scale(1.05);
        transform: scale(1.05);

        opacity: 0;
    }
    to {
        -webkit-transform: none;
        transform: none;

        opacity: 1;
    }
}

@-webkit-keyframes remodal-closing-keyframes {
    from {
        -webkit-transform: scale(1);
        transform: scale(1);

        opacity: 1;
    }
    to {
        -webkit-transform: scale(0.95);
        transform: scale(0.95);

        opacity: 0;
    }
}

@keyframes remodal-closing-keyframes {
    from {
        -webkit-transform: scale(1);
        transform: scale(1);

        opacity: 1;
    }
    to {
        -webkit-transform: scale(0.95);
        transform: scale(0.95);

        opacity: 0;
    }
}

@-webkit-keyframes remodal-overlay-opening-keyframes {
    from {
        opacity: 0;
    }
    to {
        opacity: 1;
    }
}

@keyframes remodal-overlay-opening-keyframes {
    from {
        opacity: 0;
    }
    to {
        opacity: 1;
    }
}

@-webkit-keyframes remodal-overlay-closing-keyframes {
    from {
        opacity: 1;
    }
    to {
        opacity: 0;
    }
}

@keyframes remodal-overlay-closing-keyframes {
    from {
        opacity: 1;
    }
    to {
        opacity: 0;
    }
}

/* Media queries
   ========================================================================== */

@media only screen and (min-width: 641px) {
    .remodal {
        max-width: 1000px;
    }

}

/* IE8
   ========================================================================== */

.lt-ie9 .remodal-overlay {
    background: #2b2e38;
}

.lt-ie9 .remodal {
    width: 700px;
}



.better-modal .modal-inner{
    text-align: left;
    background: #eee;
}

.better-modal .modal-header{
    border-bottom: 1px solid #E2E2E2;
    padding: 15px;
    background: #fff;
    margin-bottom: 5px;
    font-weight: bold;
    font-size: 14px;
    position: relative;
}

.better-modal .modal-footer{
    border-top: 1px solid #E2E2E2;
    padding: 15px;;
    background: #fff;
    margin-top: 5px;;
}



/* Font Icon Modal
   ========================================================================== */

.better-modal.icon-modal .modal-header{
    margin-bottom: 0;
    padding: 15px;
}

.better-modal.icon-modal .modal-footer{
    margin-top: 0;
}

.better-modal.icon-modal .modal-body{
    background-color: #fff;
    position: relative;
}

.better-modal.icon-modal .icons-container{
    width: 75%;
    float: left;
    padding: 0 3px;
    height: 585px;
    overflow: scroll;
    background-color: #eee;
    border-right: 1px solid #E2E2E2;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}
.better-modal.icon-modal .icons-container .icons-inner {
    padding: 12px;
}
.better-modal.icon-modal .icons-list{
    padding: 0;
    margin: 0;
}
.better-modal.icon-modal .icons-list .icon-select-option{
    float: left;
    background: #fff;
    border: 1px solid #D3D3D3;
    color: #575757;
    border-radius: 2px;
    margin: 5px;
    width: 30px;
    height: 30px;
    line-height: 30px;
    text-align: center;
    display: inline-block;
    cursor: pointer;
    -webkit-transition: all .3s ease;
    -moz-transition: all .3s ease;
    -o-transition: all .3s ease;
    transition: all .3s ease;
    position: relative;
}
.better-modal.icon-modal .icons-list .icon-select-option.default-option{
    width: 72px;
    line-height: 30px;
}
.better-modal.icon-modal .icons-list .icon-select-option.default-option p{
    margin: 0;
    line-height: 30px;
}
.better-modal.icon-modal .icons-list .icon-select-option img{
    max-width: 70% !important;
    height: auto;
    max-height: 70% !important;
    vertical-align: baseline;
    transform: translate(-50%,-50%);
    position: absolute;
    top: 50%;
    left: 50%;
}
.better-modal.icon-modal .icons-list .icon-select-option .delete-icon{
    position: absolute;
    top: -4px;
    right: -4px;
    width: 10px;
    height: 10px;
    line-height: 10px;
    font-size: 9px;
    text-align: center;
    color: #5D5D5D;
    background: #B7B7B7;
    border: 1px solid rgba(0, 0, 0, 0.1);
    border-radius: 50%;
    display: none;
}
.better-modal.icon-modal .icons-list .icon-select-option .delete-icon:hover{
    color: #fff;
    background: #ef534c;
}
.better-modal.icon-modal .icons-list .icon-select-option:hover .delete-icon {
    display: block;
}
.better-modal.icon-modal .icons-list .icon-select-option:hover {
    border-color: #5CA65F;
    color: #3A863D;
}
.better-modal.icon-modal .icons-list .icon-select-option.selected {
    background-color: #5CA65F;
    border-color: #5CA65F;
    color: #fff;
}
.better-modal.icon-modal .icons-list .icon-select-option.custom-icon.selected {
    background: #fff;
    color: #5D5D5D;
}
.better-modal.icon-modal .icons-list .icon-select-option .label{
    display: none;
}

.better-modal.icon-modal .cats-container{
    width: 25%;
    float: right;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    padding: 15px;
}
.better-modal.icon-modal .cats-container .better-icons-category-list{
    margin: 0;
}
.better-modal.icon-modal .cats-container .better-icons-category-list .icon-category{
    padding: 4px 0;
    margin: 0;
    border-bottom: 1px solid #F2F2F2;
    color: #808080;
    cursor: pointer;
    -webkit-transition: all .3s ease;
    -moz-transition: all .3s ease;
    -o-transition: all .3s ease;
    transition: all .3s ease;
}
.better-modal.icon-modal .cats-container .better-icons-category-list .icon-category:first-child {
    padding-top: 0;
}
.better-modal.icon-modal .cats-container .better-icons-category-list .icon-category:last-child {
    border-bottom: none;
}
.better-modal.icon-modal .cats-container .better-icons-category-list .icon-category:hover {
    color: #3D3D3D;
}
.better-modal.icon-modal .cats-container .better-icons-category-list .icon-category .text-muted{
    float: right;
    color: #BABABA;
    -webkit-transition: all .3s ease;
    -moz-transition: all .3s ease;
    -o-transition: all .3s ease;
    transition: all .3s ease;
}
.better-modal.icon-modal .cats-container .better-icons-category-list .icon-category.selected:hover,
.better-modal.icon-modal .cats-container .better-icons-category-list .icon-category.selected {
    color: #3A863D;
}
.better-modal.icon-modal .cats-container .better-icons-category-list .icon-category.selected .text-muted {
    color: #3A863D;
}

.better-modal.icon-modal .better-icons-search{
    float: right;
    width: 400px;
    position: relative;
    margin-right: -7px;
}
.better-modal.icon-modal .better-icons-search.hidden{
    display: none;
}
.better-modal.icon-modal .better-icons-search .clean{
    position: absolute;
    right: 10px;
    top: 2px;
    width: 14px;
    text-align: center;
    color: #C3C3C3;
    -webkit-transition: all .3s ease;
    -moz-transition: all .3s ease;
    -o-transition: all .3s ease;
    transition: all .3s ease;
    cursor: pointer;
}
.better-modal.icon-modal .better-icons-search .clean.fa-times-circle:hover {
    color: #9B9B9B;
}
.better-modal.icon-modal .better-icons-search .better-icons-search-input{
    width: 285px;
    height: 30px;
    border: 1px solid #DFDFDF;
    outline: none;
    box-shadow: none;
    -webkit-transition: all .3s ease;
    -moz-transition: all .3s ease;
    -o-transition: all .3s ease;
    transition: all .3s ease;
    margin-top: -6px;
    float: right;
    border-radius: 33px;
    padding: 3px 14px;
    font-weight: normal;
    font-size: 13px;
}
.better-modal.icon-modal .better-icons-search .better-icons-search-input:focus{
    border-color: #c6c6c6;
}

.better-modal.icon-modal .upload-custom-icon{
    display: inline-block;
    padding: 3px 15px;
    font-size: 11px;
    border: 1px solid rgba(0, 0, 0, 0.13);
    background: #5CA65F;
    color: #fff;
    border-radius: 13px;
    cursor: pointer;
    position: relative;
    float: right;
    margin-top: -4px;
    margin-right: 10px;
}
.better-modal.icon-modal .upload-custom-icon:hover{
    border: 1px solid rgba(0, 0, 0, 0.18);
    background: #4f9652;
}
.better-modal.icon-modal .upload-custom-icon-container{
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(43, 46, 56, 0.63);
    z-index: 1;
    display: none;
}
.better-modal.icon-modal .upload-custom-icon-container .upload-custom-icon-inner{
    background: #FFF;
    position: absolute;
    top: 50%;
    margin-top: -190px;
    left: 50%;
    right: 140px;
    margin-left: -215px;
    bottom: 20px;
    width: 430px;
    height: 380px;
    box-shadow: 0 0 25px rgba(43, 46, 56, 0.56);
    overflow: hidden;
}
.better-modal.icon-modal .upload-custom-icon-container.show{
    display: block;
}
.better-modal.icon-modal .upload-custom-icon-container .icon-uploader-loading{
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: #f8f8f8;
    z-index: 1;
    display: none;
}
.better-modal.icon-modal .upload-custom-icon-container.show-loading .icon-uploader-loading {
    display: block;
}
.better-modal.icon-modal .upload-custom-icon-container .icon-uploader-loading .fa-refresh {
    width: 18px;
    height: 18px;
    text-align: center;
    line-height: 18px;
    font-size: 18px;
    color: #565656;
    position: absolute;
    top: 50%;
    margin-top: -9px;
    left: 50%;
    margin-left: -9px;
}
.better-modal.icon-modal .upload-custom-icon-container .section-body{
    height: 220px;
    text-align: center;
}
.better-modal.icon-modal .upload-custom-icon-container .custom-icon-fields .icon-helper{
    display: inline-block;
    height: 100%;
    vertical-align: middle;
}
.better-modal.icon-modal .upload-custom-icon-container .custom-icon-fields .icon-preview{
    width: auto;
    height: auto;
    vertical-align: middle;
}
.better-modal.icon-modal .upload-custom-icon-container .custom-icon-fields .icon-fields {
    position: absolute;
    bottom: 81px;
    left: 0;
    right: 0;
    padding: 0 30px;
    height: 32px;
    text-align: center;
}
.better-modal.icon-modal .upload-custom-icon-container .custom-icon-fields .icon-fields input{
    width: 62px;
    margin-right: 17px;
}
.better-modal.icon-modal .upload-custom-icon-container .close-custom-icon{
    position: absolute;
    top: 15px;
    right: 15px;
    font-size: 16px;
    color: #F32E2E;
    cursor: pointer;
}
.better-modal.icon-modal .upload-custom-icon-container .section-header{
    padding: 15px;
    border-bottom: 1px solid #eee;
    font-weight: bold;
    font-size: 13px;
}
.better-modal.icon-modal .upload-custom-icon-container .section-footer{
    padding: 15px;
    border-top: 1px solid #eee;
    position: absolute;
    left: 0;
    bottom: 0;
    right: 0;
}
.better-modal.icon-modal .upload-custom-icon-container .section-footer .bf-button{
    width: 90%;
    display: block;
    margin: 0 auto;
    text-align: center;
    line-height: 40px;
}
.better-modal.icon-modal .font-type-header{
    margin: 15px 5px 10px 5px;
    position: relative;
    font-size: 15px;
    color: #464646;
}
.better-modal.icon-modal .font-type-header .title{
    display: inline-block;
    position: relative;
    z-index: 1;
    padding-right: 20px;
    background: #eee;
}
.better-modal.icon-modal .font-type-header:before{
    content: '';
    width: 100%;
    height: 2px;
    position: absolute;
    top: 50%;
    left: 0;
    margin-top: -1px;
    background: #DEDEDE;
}
.better-modal.icon-modal .no-custom-icon {
    padding: 5px;
    color: #909090;
    margin: 0;
}
.better-modal.icon-modal .no-custom-icon.hidden{
    display: none;
}


/* RTL FIX
   ========================================================================== */
.rtl .remodal-overlay {
    left: -5000px;
    right: -5000px;
}
.rtl .remodal-wrapper {
    left: 0;
    right: 0;
}
.rtl .remodal-wrapper:after {
    margin-right: -0.05em;
    margin-left: auto;
}
.rtl .remodal-close {
    right: 0;
    left: auto;
}
.rtl .remodal-close:before {
    right: 0;
    left: auto;
}
.rtl .better-modal .modal-inner {
    text-align: right;
}

/* Font Icon Modal
   ========================================================================== */
.rtl .better-modal.icon-modal .icons-container {
    float: right;
    border-left: 1px solid #E2E2E2;
    border-right: none;
}
.rtl .better-modal.icon-modal .icons-list .icon-select-option {
    float: right;
}
.rtl .better-modal.icon-modal .icons-list .icon-select-option img {
    right: 50%;
    left: auto;
}
.rtl .better-modal.icon-modal .icons-list .icon-select-option .delete-icon {
    left: -4px;
    right: auto;
}
.rtl .better-modal.icon-modal .cats-container {
    float: left;
}
.rtl .better-modal.icon-modal .cats-container .better-icons-category-list .icon-category .text-muted {
    float: left;
}
.rtl .better-modal.icon-modal .better-icons-search {
    float: left;
    margin-left: -7px;
    margin-right: auto;
}
.rtl .better-modal.icon-modal .better-icons-search .clean {
    left: 10px;
    right: auto;
}
.rtl .better-modal.icon-modal .better-icons-search .better-icons-search-input {
    float: left;
}
.rtl .better-modal.icon-modal .upload-custom-icon {
    float: left;
    margin-left: 10px;
    margin-right: auto;
}
.rtl .better-modal.icon-modal .upload-custom-icon-container {
    right: 0;
    left: 0;
}
.rtl .better-modal.icon-modal .upload-custom-icon-container .upload-custom-icon-inner {
    right: 50%;
    left: 140px;
    margin-right: -215px;
    margin-left: auto;
}
.rtl .better-modal.icon-modal .upload-custom-icon-container .icon-uploader-loading {
    right: 0;
    left: 0;
}
.rtl .better-modal.icon-modal .upload-custom-icon-container .icon-uploader-loading .fa-refresh {
    right: 50%;
    margin-right: -9px;
    left: auto;
    margin-left: auto;
}
.rtl .better-modal.icon-modal .upload-custom-icon-container .custom-icon-fields .icon-fields {
    right: 0;
    left: 0;
}
.rtl .better-modal.icon-modal .upload-custom-icon-container .custom-icon-fields .icon-fields input {
    margin-left: 17px;
    margin-right: auto;
}
.rtl .better-modal.icon-modal .upload-custom-icon-container .close-custom-icon {
    left: 15px;
    right: auto;
}
.rtl .better-modal.icon-modal .upload-custom-icon-container .section-footer {
    right: 0;
    left: 0;
}
.rtl .better-modal.icon-modal .font-type-header .title {
    padding-left: 20px;
    padding-right: 0;
}
.rtl .better-modal.icon-modal .font-type-header:before {
    right: 0;
    left: auto;
}
libs/better-framework/assets/css/slick.min.css000064400000002535151214002600015444 0ustar00.bs-slider-list,.bs-slider-slider,.bs-slider-track{position:relative;display:block}.bs-slider-loading .bs-slider-slide,.bs-slider-loading .bs-slider-track{visibility:hidden}.bs-slider-slider{box-sizing:border-box;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none;-khtml-user-select:none;-ms-touch-action:pan-y;touch-action:pan-y;-webkit-tap-highlight-color:transparent}.bs-slider-list{overflow:hidden;margin:0;padding:0}.bs-slider-list:focus{outline:0}.bs-slider-list.dragging{cursor:pointer;cursor:hand}.bs-slider-slider .bs-slider-list,.bs-slider-slider .bs-slider-track{-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.bs-slider-track{top:0;left:0}.bs-slider-track:after,.bs-slider-track:before{display:table;content:''}.bs-slider-track:after{clear:both}.bs-slider-slide{display:none;float:left;height:100%;min-height:1px}[dir=rtl] .bs-slider-slide{float:right}.bs-slider-slide img{display:block}.bs-slider-slide.bs-slider-loading img{display:none}.bs-slider-slide.dragging img{pointer-events:none}.bs-slider-initialized .bs-slider-slide{display:block}.bs-slider-vertical .bs-slider-slide{display:block;height:auto;border:1px solid transparent}.bs-slider-arrow.bs-slider-hidden{display:none}libs/better-framework/assets/fonts/fontawesome-webfont.ttf000064400000503254151214002600020120 0ustar00
�PFFTMk�G���GDEF��p OS/2�2z@X`cmap
�:��gasp���hglyf���M�L�head��-�6hhea
�$hmtxEy��
�loca��\�maxp,8 name㗋�gh�post����k�uː�xY_<��3�2�3�2���	�	����	��'@i��3��3s�pyrs@ �� �pU�]�����y�n�����2��@������
��������z���Z@�5�5
���z���ZZ����@���������,_���@������s���@	��@��(������@�����@��@-
�M�M�-�
�M�M�����@�����@@�
�-����`��b����
���$����6�4�8�"�"""""���@�D@���,,@� ���������	m��)@�@	 	' D9>dY*	'						�	��	��T										�@	f�	%RE	 		$!k(D�'	��	�%��	�%	��	��0%�/�&��p@0 �����!"""`���>�N�^�n�~��������������.�>�N�^�n�~��������������>�N�^�n�~������������ �����!"""`���!�@�P�`�p�������������� �0�@�P�`�p��������������!�@�P�`�p�������������\�X�S�B�1����ݬ

	����������������������������������
�
	,,,,,,,,,,,,,��t�L�T$�l	x	�
T(��
d����l,����4d�pH�$d,t( � �!�"0# $,$�&D'�(�)T**�,,�-�.@.�/`/�00�1�2�3d444�5 5�5�6 6\6�7H7�88`8�9L9�:h:�;�<p=p><>�?h?�@H@�A0A�BXB�CdC�DLD�E�F�G0G�H�I�J8K�L�MdN,N�N�O�P`P�Q4Q�RRlS,S�T`U0W�X�Z[@[�\<\�]�^(^�_�`pb,b�dd�ePe�f�g`g�iLi�jDkk�l�m@n,oLp�q�r�sxtt�uD{`||�}}�~��������H��������l�@����������l�H� ���T��H�������`����@�����$�\�X��D�������T�X�����D�P�,���8���d�\����������������H���x��� �t���X���p��d��������x�t�������������@������Œ�\� ļ�ŸƔ�0���d��ʨˀ����͔�x��ϰЌ�,ш�҈�ӌ���8�,՜�`���l�Hش�`���Tڸ�۔�@���l��ބ�߬��l�p� ������������������������������4�����X���$�l���(����`����������	d

��
,�,��8��(�X���x|T�@��| �!�"x##l$$�'h(�*L,T.L1t1�2�303�4�5t6T7$89H::�;�<�<�?X@A�B�C�D�EHFHGpHHIxJ J�K�L�MN@P@Q�R�SDT ULV`V�WXX4X�ZZ�[d[�\|]�^�`�aHa�b�cXd�etfhg�h�i\jxn�p@s�vw�x�y�z�{h|�}}�\���l�t���4���������t���8�8���L���T�������������|�������|�������4�x�����L����������X�(� ������� ������@�����l���t����$����x�L�L��� �H������Ġ�T�(����ʈˠ��ϔ�l�d���P�Մ�x�p���ڬ�T�T���ވ�L�����<�H��$���l������4����������� �P�l����,���x���p�,�x�t��d����4���4,h�P	4
��
�4�<,,408$�8�T� |!h"�$L%0&H'�(�)�*0*�+�,�.$.�0�1�2@2�3�4t5$6�9 :�:�;;�<(<�=4?�@�A�C�D�F�H`H�I�L�L�L�L�L�L�L�L�L�L�L�L�L�L�L�L�p7!!!���@p�p �p�]���!2#!"&463!&54>3!2�+��@&&��&&@��+$(�($F#+���&4&&4&x+#��+".4>32".4>32467632DhgZghDDhg-iW�DhgZghDDhg-iW&@(8 ��2N++NdN+'�;2N++NdN+'�3
8���!  #"'#"$&6$ �������rL46$���܏���oo��o|W%r��������4L&V|o��oo����ܳ��%��=M%+".'&%&'3!26<.#!";2>767>7#!"&5463!2� %��3@m00m@3���% 
�
�@
���:"7..7":�6]�^B�@B^^B�B^ $΄+0110+��$�
(	

�t��1%%1��+�`��B^^B@B^^���"'.54632>32�4��
#L</��>�oP$$Po�>���Z$_d�C�+I@$$@I+��������"#"'%#"&547&547%62���V�?�?V��8��<��8y���
���b%	I�))�9I	����	+	%%#"'%#"&547&547%62q2�Z���Z2Izy���V)�?�?V��8��<��8)>~��>��[��
���
2���b%	I�))�9I	���%#!"&54>3 72 &6 }X��X}.GuL�l�LuG.�����>�m��mU��mE��Em�������>����/?O_o���54&+";2654&+";2654&+";264&#!"3!2654&+";2654&+";264&#!"3!2654&+";2654&+";2654&+";267#!"&5463!2�&�&&�&&�&&�&&�&&�&&�&&&�&�&&�&�&�&&�&��&�&&&�&�&&�&&�&&�&&�&&�&�^B��B^^B@B^@�&&�&&��&&�&&��&&�&&�&&�&&��&&�&&���&&�&&&&�&&���&&�&&��&&�&&��&&�&&���B^^B@B^^��/?#!"&5463!2#!"&5463!2#!"&5463!2#!"&5463!2L4�4LL44LL4�4LL44L�L4�4LL44LL4�4LL44L��4LL4�4LL��4LL4�4LL���4LL4�4LL��4LL4�4LL	�/?O_o�#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!28(��(88(@(88(��(88(@(8�8(��(88(@(8��8(��(88(@(8�8(��(88(@(8�8(��(88(@(8��8(��(88(@(8�8(��(88(@(88(��(88(@(8 �(88(�(88�(88(�(88��(88(�(88�(88(�(88��(88(�(88��(88(�(88�(88(�(88��(88(�(88�(88(�(88�/?O_#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!28(��(88(@(88(��(88(@(88(�@(88(�(8�8(��(88(@(88(�@(88(�(88(�@(88(�(8 �(88(�(88�(88(�(88��(88(�(88�(88(�(88��(88(�(88�(88(�(88y��"/&4?62	62��,�P����P&�P��P�,��jP�����n���#$"'	"/&47	&4?62	62	�P���P�&���P&&P���&�P�&���P&&P���&�P������#+D++"&=#"&=46;546;232  #"'#"$&6$ 
�
@
�

�
@
�
�������rK56$���܏���oo��o|W�@
�

�
@
�

��r��������jK&V|o��oo����ܳ�����0#!"&=463!2  #"'#"$&6$ 
��

@
�������rK56$���܏���oo��o|W�@

@
�r��������jK&V|o��oo����ܳ����)5 $&54762>54&'.7>"&5462z�����z��+i *bkQ��н�Qkb* j*����LhLLhL�����zz���Bm +*i J�yh��QQ��hy�J i*+ m��J��4LL4�4LL���/?O%+"&=46;2%+"&546;2%+"&546;2+"&546;2+"&546;2��������������`��r��@�@r�@��@����n4&"2#"/+"&/&'#"'&'&547>7&/.=46?67&'&547>3267676;27632�Ԗ����#H
	��,/
�1)�
~'H�
�(C
	�

�,/
�1)�	
�$H�
Ԗ�Ԗm�6%2X
%�	l�2
�k	r6

[21
�..9Q

$�
k�2
�k	
w3[20����/;Cg+"&546;2+"&546;2+"&546;2!3!2>!'&'!+#!"&5#"&=463!7>3!2!2@@@@@@���@�`�0
��
o`^B��B^`5FN(@(NF5 ��@��@��@���L%%Ju		�@�LSyuS�@�%44%�f5#!!!"&5465	7#"'	'&/&6762546;2�&�����&??�>

�L�L
>
� X ���
 � &���&��&AJ	A��	J
W���h��##!"&5463!2!&'&!"&5!�(8(��(88(�(`�x
��c�`(8��`(��(88(@(8(D��9�8(����� ,#!"&=46;46;2.  6 $$ ����@��������(�r���^����a�a�@@`��(��������_�^����a�a��2NC5.+";26#!26'.#!"3!"547>3!";26/.#!2W
�
��.�@

��

�@.�$S

�

S$�@

���9I


�
I6>
��
��>�%=$4&"2$4&"2#!"&5463!2?!2"'&763!463!2!2&4&&4&&4&&4�8(�@(88(ч:�:��(8���@6�@*&&*�4&&4&&4&&4& ��(88(@(8�88�8)�@�)'�&&�@���$0"'&76;46;232  >& $$ `
������������(���r���^����a�a`��		@`��2�������(���^����a�a�����$0++"&5#"&54762  >& $$ ^���
?@�����(���r���^����a�a���`?		����������(���^����a�a��
#!.'!!!%#!"&547>3!2�<�<�<_@`&��&�
5@5
�@����&&�>=(""��=���'#"'&5476.  6 $$ � ��  ! ��������(�r���^����a�a�J��	%�%���(��������_�^����a�a�����3#!"'&?&#"3267672#"$&6$3276&�@*���h��QQ��hw�I
�	m�ʬ����zz���k�)'�@&('��Q��н�Qh_
	�
��z�8�zoe����$G!"$'"&5463!23267676;2#!"&4?&#"+"&=!2762�@�h���k�4&&�&�G�a��F*�
&�@&��Ɇ�F*�
A��k�4&���nf�&�&&4�BH�rd�@&&4���rd
Moe�&�/?O_o+"&=46;25+"&=46;25+"&=46;2#!"&=463!25#!"&=463!25#!"&=463!24&#!"3!26#!"&5463!2�
@

@

@

@

@

@
�
�@

�

�@

�

�@

�
�
�@

�
�^B�@B^^B�B^`@

@
�@

@
�@

@
��@

@
�@

@
�@

@
�3@

��
M��B^^B@B^^��!54&"#!"&546;54 32@�Ԗ@8(�@(88( p (8�j��j��(88(@(8������8@���7+"&5&5462#".#"#"&5476763232>32@@
@
@KjK�ך=}\�I���&:�k�~&26]S
&H&�

�&H5KKu�t,4,�	&� x:;*4*&��K#+"&546;227654$ >3546;2+"&="&/&546$ �<��X@@Gv"D�����װD"vG@@X��<��4L4����1!Sk @ G<_b������b_<G �� kS!1����zz�� �"'!"&5463!62&4����&&M4&���&M&�&M& ��-"'!"&5463!62#"&54>4.54632&4����&&M4&�UF
&""""&
F���&M&�&M&���%/B/%���G-Ik"'!"&5463!62#"&54>4.54632#"&54767>4&'&'&54632#"&547>7676'&'.'&54632&4����&&M4&�UF
&""""&
FU��
&'8JSSJ8'&

����

&'.${��{$.'&

����&M&�&M&���%/B/%7���;&'6���6'&;��4�[&$
[2[
$&[��#/37#5#5!#5!!!!!!!#5!#5!5##!35!!!����������������������������������������������������������������������������#'+/37;?3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3????  ^��>>~??�??�??~??~??^??�^^?  ^??������������������������������������4&"2#"'.5463!2�KjKKjv%�'45%�5&5L4�5�&�%jKKjK�@5%�%%�%�5�4L5&�6'��k�54&"2#"'.5463!2#"&'654'.#32�KjKKjv%�'45%�5&5L4�5�&�%�%�'4$.�%%�5&�5�5�&�%jKKjK�@5%�%%�%�5�4L5&�6'45%�%�%54'�&55&�6'
��y�Tdt#!"&'&74676&7>7>76&7>7>76&7>7>76&7>7>63!2#!"3!2676'3!26?6&#!"3!26?6&#!"g(��sA�eM�,*$/
!'&
�JP��$G]��
x�6,&��`
��
h`
��
"9H�v@WkNC<.
&k&
("$p"	.
#u&#	%!'	pJ�vwEF�#

@

��

@

���2#"'	#"'.546763�!''!0#�G�G$/!''!�	
8"��"8
 ��X!	
8"	"8
	����<)!!#"&=!4&"27+#!"&=#"&546;463!232������(8���&4&&4�
�8(�@(8�
qO@8(�(`�(@Oq��8(��&4&&4&@�`
�(88(�
�Oq (8(�`(�q���!)2"&42#!"&546;7>3!2  I��j��j��j��j�3e55e3�gr������`��I�j��j��j�j��1GG1���r��������P2327&7>7;"&#"4?2>54.'%3"&#"#ժ!�9&W��B03&�K5�!�)V�?�@L��'�	
>R�>e;&L:�:%P�>��vO
'h�� N��_"�:-&+#
��:��	'	����+a%3 4'.#"32>54.#"7>7><5'./6$3232#"&#"+JBx)EB_I:I*CRzb3:dtB2P���$$5.3b�ZF�|\8!-T>5��Fu��\,�,j�n OrB,<!
5�4wJ]�?tTFi;
2�3j.�p^%/2�+
	S:T}K4W9: #ƕd�fE���:7>7676'5.'732>7"#"&#&#"OA
zj=N!�}:0e��%	y�
+t�D3�~U#B4#
g		'2
%/!:
���T	bRU,7����}%2"/&6;#"&?62+326323!2>?23&'.'.#"&"$#"#&=>764=464.'&#"&'�!~:~!PP!~:~!P��6�,�,$�$%*'
c2N 	
(�$"L��A2�3Yl�!x!*�%��%%��%��
p�P,T	NE	Q7^���oH!+(
3	 *Ue�eu
wg��a�32632$?23&'.5&'&#"&"5$#"#&=>7>4&54&54>.'&#"&'2#".465!#".'&47>32!4&4>Q6�,�,Faw!*'
=~Pl*	
(�$"L��A2�3Yl	�)�!*<7@@7<
�
<7@@7<
 p�P,T	MF
Q7�47ƢHoH!+(
3	 t���JHQ6wh��',686,'$##$',686,'$##$�/?%#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2&��&&�&��&�&&&&�&&&��&��&&�&��&&�&&f�&&�&&f�&&�&&f�&&�&&�/?%#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2&��&&�&��&��&&�&&��&&�&��&��&&�&��&&�&&f�&&�&&f�&&�&&f�&&�&&�/?%#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2&��&&�&&�&&&&�&&&&��&&�&��&&�&&f�&&�&&f�&&�&&f�&&�&&�/?%#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2&��&&�&&��&&�&&��&&�&&��&&�&��&&�&&f�&&�&&f�&&�&&f�&&�&&�/?O_o%+"&=46;2+"&=46;2+"&=46;2#!"&=463!2+"&=46;2#!"&=463!2#!"&=463!2#!"&=463!2
�

�

�

�

�

�

��

@
�
�

�

��

@

��

@

��

@
�

�
s�

�
s�

�
��

�
s�

�
��

�
s�

�
s�

�
�/?O#"'&47632#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2�
	��		 	
�
�@

�

��

@

��

@

�@

�
�
	 		 	��

�
s�

�
s�

�
s�

�
�/?O#"&54632	#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2`	��	

	 �
�@

�

��

@

��

@

�@

�
�	��	
@
	��	�

�
s�

�
s�

�
s�

�
#"'#!"&5463!2632'
�m�w�@w��w�w��
'���*��w��w�w��w������."&462!5	!"3!2654&#!"&5463!2�p�pp�p��@���

@
�^B��B^^B@B^�pp�p���@�@� 
�@

�
 �@B^^B�B^^���k%!7'34#"3276'	!7632k[�[�v
��
6����`�%��`�$65&�%[�[k����
�`����5%���&&�'���4&"2"&'&54 �Ԗ���!��?H?��!,�,Ԗ�ԖmF��!&&!Fm�,�����%" $$ ���������^����a�a`@������^����a�a���-4'.'&"26% 547>7>2"KjK��X��QqYn	243nYqQ�$!+!77!+!$5KK���,ԑ�	���]""]ً�	��9>H7'3&7#!"&5463!2'&#!"3!26=4?6	!762xt�t` �� ^Q�w��w��w@?61��B^^B@B^	@(` �`��\\��\P�`t�t8`� �� ^�Ͼw��w@w�1^B��B^^B~
	@��` \ \�P�+Z#!"&5463!12+"3!26=47676#"'&=# #"'.54>;547632��w��w��w�
M8
pB^^B@B^�
'���sw-

9*##;No��j�'
�#��w��w@w�
"^B��B^^B�

	��*�����
"g`�81T`PSA:'�*��4�/D#!"&5463!2#"'&#!"3!26=4?632"'&4?62	62��w��w��w@?61

��B^^B@B^	@

��B�RnB�Bn^��w��w@w�1
^B��B^^B�
	@
���Bn���nB�C"&=!32"'&46;!"'&4762!#"&4762+!5462�4&���&�4�&���&4�4&��&4&��&4�4�&���&4�4&��&4&��&4�4&���&����6'&'+"&546;267��:	&�&&�&	s�@�	
�Z&&�&&�Z
	���+6'&''&'+"&546;267667��:	�:	&�&&�&	�	s�@�	
�:�	
�Z&&�&&�Z
	��:
	z����6'&''&47667S�:	�:�	s�@�	
�:�4��:
	�|�	&546h��!!0a�
�
�
$���#!"&5463!2#!"&5463!2&�&&&��&�&&&@��&&�&&��&&�&&���#!"&5463!2&��&&�&@��&&�&&���&54646&5-�	��:	s��:	
��:4�:�
	���+&5464646;2+"&5&5-�	�	&�&&�&	�:	s��:	
��:	
�&&��&&�
	�:�
	���&54646;2+"&5-�	&�&&�&	s��:	
�&&��&&�
	62#!"&!"&5463!2�4��@��&&�&&-��:��&&&�&�����	"'&4762����4��4����4��4��4Z��f�	"/&47	&4?62S�4����4����44��4���#/54&#!4&+"!"3!;265!26 $$ �&�&�&�&&&�&&@���^����a�a@�&&&�&�&�&&&+�^����a�a�����54&#!"3!26 $$ �&�&&&@���^����a�a@�&&�&&+�^����a�a�����+74/7654/&#"'&#"32?32?6 $$ }��Z��Z��Z��Z����^����a�a���Z��Z��Z��Z�^����a�a�����#4/&"'&"327> $$ [4�h�4[j����^����a�a"Z�i�Z��J�^����a�a�����:F%54&+";264.#"32767632;265467>$ $$ ���o�W��	5!"40K(0?i�+! ":����^����a�a����X�R�dD4!&.uC$=1/J=�^����a�a�����.:%54&+4&#!";#"3!2654&+";26 $$ `��``��������^����a�a�����������^����a�a�����/_#"&=46;.'+"&=32+546;2>++"&=.'#"&=46;>7546;232�m&&m �l&�&l� m&&m �l&�&l�s&�%�&�&��%�&&�%�&�&��%�&&�&l� m&&m �l&�&l� m&&m �,�&��%�&&�%�&�&��%�&&�%�&���#/;"/"/&4?'&4?627626.  6 $$ I�

��

�

��

�

��

�

��
͒������(�r���^����a�aɒ

��

�

��

�

��

�

��
(��������_�^����a�a����� ,	"'&4?6262.  6 $$ ��Z4��f4�4fz�������(�r���^����a�a�Z&4f�f4�(��������_�^����a�a�����	"4'32>&#" $&6$  W���oɒV�󇥔�� z�����zz�8�����YW�˼�[����?����zz�:�zz�@�5K #!#"'&547632!2A4�@%&&K%54'�u%%�&54&K&&���4A��5K��$l$L%%�%54'�&&J&j&��K�5�K #"/&47!"&=463!&4?632�%�u'43'K&&%�@4AA4���&&K&45&�%@6%�u%%K&j&%K5�5K&$l$K&&�u#5��K@!#"'+"&5"/&547632K%K&56$��K5�5K��$l$K&&�#76%�%53'K&&%�@4AA4���&&K&45&�%%�u'5��K�"#"'&54?63246;2632K%�u'45%�u&&J'45%&L4�4L&%54'K%�5%�t%%�$65&K%%���4LL4�@&%%K'���,"&5#"#"'.'547!3462�4&�b��qb>#5���&4�4�&6Uu�e7D#		"�dž�&����/#!"&546262"/"/&47'&463!2�
���&�@&&4�L

r&4���

r

L�&�&�
���4&&�&�L

rI�@&���

r

L�4&&
���s/"/"/&47'&463!2#!"&546262&4���

r

L�&�&�
���&�@&&4�L

r@�@&���

r

L�4&&�
���4&&�&�L

r��##!+"&5!"&=463!46;2!2�8(�`8(�(8�`(88(�8(�(8�(8 �(8�`(88(�8(�(8�(88(�`8��#!"&=463!2�8(�@(88(�(8 �(88(�(88z���5'%+"&5&/&67-.?>46;2%6�.@g.��L4�4L��.g@.
��.@g.
L4�4L
.g@.���g.n.���4LL43�.n.g��g.n.�34LL4�͙.n.g����-  $54&+";264'&+";26/�a����^�����
�

�


�

�����^����a�a��
�
fm��
@
J%55!;263'&#"$4&#"32+#!"&5#"&5463!"&46327632#!2���$�$�8�~+(88�8(+}�(�`8(��(8`�]��]k=��=k]��]��8���,8e�8P88P8�����`(88(�@���M��M����N4&#"327>76$32#"'.#"#"&'.54>54&'&54>7>7>32&����z&^��&.������/+>+)>J>	W��m7����'
'"''? &4&c��&^|h_b��ml/J@L@#*
#M6:D
35sҟw$	'%
'	\�t��3#!"&=463!2'.54>54''�
��

@
�1O``O1CZ��Z71O``O1BZ��Z7�@

@
N�]SHH[3`�)Tt��bN�]SHH[3^�)Tt���!1&' 547 $4&#"2654632 '&476 ���=������=嘅�����}�(zVl��'��'���ٌ@�uhy����yhu����9(�}Vz��D#���#D#�������	=CU%7.5474&#"2654632%#"'&547.'&476!27632#76$7&'7+NWb=嘧�}�(zV�j�\i1
z,��X��
Y[6
$!%���'F��u�J�iys�?_�9ɍ?�kyhu�n(�}Vz����YF
KA؉L�a
�0��2�-�F"@Q���sp@�_���!3%54&+";264'&+";26#!"&'&7>2
�

�


�
�
#%;"�";%#<F<������7


���??""??�$$ll2#"'&'	+&/&'&?632	&'&?67>`,@L�����5
`		��
`	�����L�`4�L��H`
����`	��
a	5�
��L@��#37;?Os!!!!%!!!!%!!!!!!!!%!!4&+";26!!%!!!!74&+";26%#!"&546;546;2!546;232� ��`@���� ��`@���� ���@����@�� ��@����
@

@
� ��@��� �� 
@

@
�L4��4LL4�^B@B^�^B@B^�4L� �� @@��@@ � � � @@  

��
��@@ �� � 

��
M�4LL44L`B^^B``B^^B`L���7q.+"&=46;2#"&=".'673!54632#"&=!"+"&=46;2>767>3!54632�<M33K,��	��	
 j8Z4L2B4:;M33K,?		��	
�0N<* .)C=W]xD��0N<* .)C=W]xD?\�-7H)��	��	
�".=']�-7H)�
��w	��	
�<?.>mBZxPV3!�<?.>mBZxPV3!�
���&#"'&'5&6&>7>7&54>$32�d�FK��1A
0)����L���.���٫�C58.H(Y���e����#3C $=463!22>=463!2#!"&5463!2#!"&5463!2���H���&�&/<R.*.R</&�&�&��&&�&&��&&�&������Bɀ&&�4L&&L4�&&f��&&�&&��&&�&&Z� %"'	"/&4762��4���4��4�ͥ���5��5Z����	"'&4?62	62��4��44���5����5��%K%#!".<=#"&54762+!2"'&546;!"/&5463!232
�@�&@<@&�@	����:��&���	�
��& 

��&���&���
����&��	

��`&���:$"&462"&462!2#!"&54>7#"&463!2!2�LhLLh�LhLLh�!��
�&&�&��&&�&4hLLhLLhLLhL��%z<
0&4&&)17&4&
&&��#!"&5463!2!2��\�@\��\@\��\���@\��\�\��\ �W�*#!"&547>3!2!"4&5463!2!2W��+�B��"5P+�B@"5����^�=���\@\� \�H#�t3G#�3G:�_H�t�\��\ �@��+32"'&46;#"&4762�&��&�4�&��&4�4&�&4�4&&4�@�"&=!"'&4762!5462�4&�&4�4&&4�4�&��&4&��&����
!!!3!!��������������������������0@67&#".'&'#"'#"'32>54'6#!"&5463!28ADAE=\W{��O[/5dI
kDt���pČe1?*�w�@w��w�w��	(M&
B{Wta28r=Ku?RZ^Gw��T	-�@w��w�w�����$2+37#546375&#"#3!"&5463�w��w���/Dz?s�����w��w��w�@w�S�88�	�����w�w����#'.>4&#"26546326"&462!5!&  !5!!=!!%#!"&5463!2�B^8(�Ԗ���������>��������@�|�K5�5KK55K�^B(8Ԗ�Ԗ�€>�������v����5KK55KK�H��G4&"&#"2654'32#".'#"'#"&54$327.54632@p�p)*Ppp�p)*P�b	'"+`�N*(�a���;2��̓c`." b
PTY9��ppP*)p�ppP*)�b ".`�(*N��ͣ�2�ͣ����`+"'	b
MRZB�����4&"24&"264&"26#"/+"&/&'#"'&547>7&/.=46?67&'&547>3267676;27632#"&'"'#"'&547&'&=4767&547>32626?2#"&'"'#"'&547&'&=4767&547>32626?2��Ԗ���LhLKjKLhLKjK��	�"8w
s%(�")v

�
>�
	�"8x
s"+�")v
�<�
��3zLLz3��
3>8L3)x3
��3zLLz3��
3>8L3)x3
�Ԗ�Ԗ�4LL45KK54LL45KK���
#)0C	wZl/
�
Y�	
N,&�
#)0C	vZl.
�
Y�L0"��qG^^Gq�q$ ]G)Fq�qG^^Gq�q$ ]G)Fq��%O#"'#"&'&4>7>7.546$ '&'&'# '32$7>54'�����VZ|�$2$
|��E~E<�|
$2$�|ZV���:�(t}�������X(	
&%(H�w�쉉��x�H(%&	(X�ZT\�MKG���<m$4&"24&#!4654&#+32;254'>4'654&'>7+"&'&#!"&5463!6767>763232&4&&4�N2��`@`%)7&,$)'  
%/0Ӄy�#5 +�1	&<��$]`�{t��5KK5$e:1&+'3T�F0�h��4&&4&�3M:�;b^v�+D2 5#$��I�IJ 2E=\$YJ!$MCeM��-+(K5�5K�K5y�*%A�u]c���>q4&"24&'>54'654&'654&+"+322654&5!267+#"'.'&'&'!"&5463!27>;2&4&&4�+ 5#bW���0/%
  ')$,&7)%`@``2N��h�0##�T3'"(0;e$��5KK5 t��ip��<&	1&4&&4&�#\=E2&%IURI��$#5 2D+�v^b;�:M2g�c]vDEA%!bSV2M�K5�5K(,,��MeCM$!I��@�#"&547&547%6@�?V��8������b%	I�)���94.""'."	67"'.54632>32�+C`\hxeH>Hexh\`C+�ED���4��
#L</��>�oP$$Po�>��Q|I.3MCCM3.I|Q����/����Z$_d�C�+I@$$@I+� (@%#!"&5463!2#!"3!:"&5!"&5463!462�
��w��w@

��B^^B 
���4&�@&&�&4 ` 
�w�w�
 
^B�@B^24��& &�& &�����%573#7.";2634&#"35#347>32#!"&5463!2���FtIG9;HI�x�I��<,tԩw�@w��w�w�z��4DD43EE�����ueB���&#1�s�@w��w�w�����.4&"26#!+"'!"&5463"&463!2#2��&�S3L�l&�c4LL4�4LL4c����@��&��&{�LhLLhL��'?#!"&5463!2#!"3!26546;2"/"/&47'&463!2��w��w��w��@B^^B@B^@�&4��t

r

��&&`��w��w@w�@^B��B^^B@R�&��t

r

��4&&@"&5!"&5463!462	#!"&54&>3!2654&#!*.54&>3!2���4&�@&&�&4 s�w��

@B^^B��

@w��4��& &�& &��3�@w�
 
^B�B^ 
�����
I&5!%5!>732#!"&=4632654&'&'.=463!5463!2!2�J���J���S��q*5&=CKu��uKC=&5*q͍S8( ^B@B^ (8���`N��`Ѣ�΀G�tO6)"M36J[E@@E[J63M")6Ot�G�(8`B^^B`8	���',2��6'&'&76'6'&6&'&6'&4#"7&64 654'.'&'.63226767.547&7662>76#!"&5463!2		/[		.
=���X��Ě4,+"*+, 1JH'5G:�:#L5+@=&#���w�@w��w�w�P.1GE�,��ԧ��44+	;/5cFO:>JJ>:O9W5$@(b4��@w��w�w������'?$4&"2$4&"2#!"&5463!3!267!2#!#!"&5!"'&762&4&&4&&4&&4�8(�@(88(�c==c�(8��*�&�&�*�6�&4&&4&&4&&4& ��(88(@(88HH88`(�@&&�('��@����1c4&'.54654'&#"#"&#"32632327>7#"&#"#"&54654&54>76763232632


	N<�;+gC8�A`1a9�9�g��w����|�9�8aIe$I�VN��z<�:LQJ
�,�-[%	061I��(�)W,$-������7,oIX(�)o�ζA;=N0
eTZ
	 (���O#".'&'&'&'.54767>3232>32�e^\4?P	bM��O0#382W#& 9C9
Lĉ"	82<*9FF(W283#0OMb	P?4\^eFF9*<28	"��L
9C9 &#��!"3!2654&#!"&5463!2`��B^^B@B^^ީw��w��w@w�^B��B^^B@B^���w��w@w�����#!72#"'	#"'.546763���YY�!''!0#�G�G$/!''!�&�UU�jZ	
8"��"8
 ��X!	
8"	"8
	���GW4.'.#"#".'.'.54>54.'.#"32676#!"&5463!2 1.-
+$)
c�8
)1)

05.D
<9�0)$9��w�@w��w�w�W

)1)
7�c
)$+
-.1 �9$)0���<
D.59�@w��w�w��,T1# '327.'327.=.547&54632676TC_L��Ҭ���#+�i�!+*p�DNBN,y[����`m`%i]hbE����m��}a�u&,�SXK��
&$��f9s?
_���#"!#!#!54632��V<%'����Э��HH���	�(ں����T\dksz�� &54654'>54'6'&&"."&'./"?'&546'&6'&6'&6'&6'&74"727&6/�a���49[aA)O%-j'&]�]5r-%O)@a[9'
0BA;+


>HC���U


	#	
	
$				2	
AC: �����oM�=a-6O�UwW[q	( -	q[WwU�P6$C

+) (	
8&/
&eM���a�	
&
$	

��%+"&54&"32#!"&5463!54 �&@&�Ԗ`(88(�@(88(�r��&&j��j�8(��(88(@(8��������#'+2#!"&5463"!54&#265!375!35!�B^^B��B^^B
�

��
`���^B�@B^^B�B^�
��
�
`��
�������!="&462+"&'&'.=476;+"&'&$'.=476;�p�pp�p�$���!�$qr�
�%���}�#ߺ���pp�p��!�E$�
�rq�ܢ#���
%�
ֻ��!)?"&462"&4624&#!"3!26!.#!"#!"&547>3!2/B//B//B//B�
�@

�
�2�����^B�@B^�\77\�aB//B//B//B/�@

��
��

�~��B^^B@2^5BB5��2���.42##%&'.67#"&=463! 2�5KK5L4�_�u:B&1/&��.-
zB^^B���4L��v��y�KjK��4L[!^k'!A3;):2*�<vTq6^B�B^�L4�$���)��*@��A4#"&54"3!4."#!"&5!"&5>547&5462�;U gI�v��0Z���Z0�L4�@�Ԗ�@4L2RX='�8P8��'=XR� U;Ig0,3lb??bl3���4Lj��jL4*\���(88(�����\���}I/#"/'&/'&?'&'&?'&76?'&7676767676`�
(�5)�0
)��*)
0�)5�(
��
(�5)�0
))��))
0�)5�(
��*)
0�)5�(��
)�5)�0
)*��*)
0�)5�)
��
)�5)�0
)*���5h$4&"24&#!4>54&#"+323254'>4'654&'!267+#"'&#!"&5463!2>767>32!2&4&&4�N2��$YGB
(HGEG  H��Q�#5K4L��i�!<�����;��5KK5 
A#
("/?&}�vh��4&&4&�3M95S+C=�,@QQ9��@@�IJ 2E=L5i�>9eM��E;K5�5K	J7R>@#�zD<����5=q%3#".'&'&'&'.#"!"3!32>$4&"2#!"#"&?&547&'#"&5463!&546323!2`  #A<(H(GY$��2NL4K5#aWTƾh&4&&4�K5��;����=!�i��hv�}&?/"(
#A
 5K��2*!	Q@.'!&=C+S59M34L=E2 JI UR@@&4&&4&���5K;E��Lf9>�ig�<Dz�#@>R7J	K�5h4&"24#"."&#"4&#"".#"!54>7#!"&54.'&'.5463246326326&4&&4��IJ 2E=L43M95S+C=�,@QQ9�@@�E;K5��5K	J7R>@#�zD<�gi�>9eM��Z4&&4&<�#5K4LN2��$YGB
(HGEG  H��V���;��5KK5 
A#
("/?&}�vh��i�!<��4<p4.=!32>332653272673264&"2/#"'#"&5#"&54>767>5463!2�@@��2*!	Q@.'!&=C+S59M34L.9E2 JI UR�&4&&4&��Lf6A�ig�6Jy�#@>R7J	K5�5K;E@TƾH  #A<(H(GY$��2NL4K#5#a=4&&4&�D��=�i��hv�}&?/"(
#A
 5KK5��;�����+54&#!764/&"2?64/!26 $$ &�
�[6��[[j6[��&���^����a�a@�&�4[��[6[��[6�&+�^����a�a�����+4/&"!"3!277$ $$ [��6[��
&&��[6j[
���^����a�ae6[j[6�&�&�4[j[��^����a�a�����+4''&"2?;2652?$ $$ ��[6[��[6�&�&�4[���^����a�af6j[[��6[��
&&��[��^����a�a�����+4/&"4&+"'&"2? $$ [6�&�&�4[j[6[j���^����a�ad6[��&&�
�[6��[[j��^����a�a������  $2>767676&67>?&'4&'.'.'."#&6'&6&'3.'.&'&'&&'&6'&>567>#7>7636''&'&&'.'"6&'6'..'/"&'&76.'7>767&.'"76.7"7"#76'&'.'2#22676767765'4.6326&'.'&'"'>7>&&'.54>'>7>67&'&#674&7767>&/45'.67>76'27".#6'>776'>7647>?6#76'6&'676'&67.'&'6.'.#&'.&6'&.5/�a����^����D&"	


	4
	$!	#
	
		
	



 
.0"�Y
	+


!	
	

$	
	"
+


		
	�Α	
		
����^����a�a��

	

			
	

	

		
	
		P� '-(	#	*	$

"
!				
*
!	

(				

	
��$�
		
2
�~�/$4&"2	#"/&547#"32>32�&4&&4��V%54'j&&�'��/덹���:,���{	&4&&4&�V%%l$65&�b��'C��r!"��k[G�+;%!5!!5!!5!#!"&5463!2#!"&5463!2#!"&5463!2����������&��&&�&&��&&�&&��&&�&�������@�&&&&�&&&&�&&&&��{#"'&5&763!2{�'
��**�)��*��)'/!5!#!"&5!3!26=#!5!463!5463!2!2���^B�@B^�&@&`��^B`8(@(8`B^��� B^^B�&&�����B^�(88(�^���G	76#!"'&?	#!"&5476	#"'&5463!2	'&763!2#"'��c�)'&�@*������*�@&('�c���(&�*�cc�*�&'
����*�@&('�c���'(&�*�cc�*�&('���c�'(&�@*��19AS[#"&532327#!"&54>322>32"&462 &6 +&'654'32>32"&462Q�g�Rp|Kx;CB��y��y� 6Fe=
BP���PB
=eF6 ��Ԗ��V����>!pR�g�QBC;xK|��Ԗ���{QNa*+%��x��x5eud_C(+5++5+(C_due2Ԗ�Ԗ�����>�NQ{u�%+*jԖ�Ԗ��p�!Ci4/&#"#".'32?64/&#"327.546326#"/&547'#"/&4?632632��(* 8(!�)(��A�('��)* 8(!U�SxyS�SXXVzxT�TU�SxyS�SXXVzxT�@(� (8 *(���(��'(�(8 ���S�SU�Sx{VXXT�T�S�SU�Sx{VXXT���#!"5467&5432632�������t,Ԟ;F`j�)��������6�,��>�jK?�s��
�!%#!"&7#"&463!2+!'5#�8Ej��jE8�@&&&&@������XYY�&4&&4&�qD�S�%��q%��N\jx��2"&4#"'#"'&7>76326?'&'#"'.'&676326326&'&#"32>'&#"3254?''7�4&&4&l��
�NnbS���VZbR��SD	
zz
	DS��Rb)+U���Sbn�
��\.2Q\dJ'.2Q\dJ.Q2.'Jd\Q2.'Jd`!O�`��	`�����&4&&4�r$#@�B10M�5TNT{L�5T
	II	
T5�L;l'OT4�M01B�@#$�*�3;$*�3;�;3�*$;3�*$�:$/� @@�Qq`��@���"%3<2#!"&5!"&5467>3!263!	!!#!!46!#!�(88(�@(8��(8(�`(�(8D<���+����+�<��8(�`(��8(�`�8(�@(88( 8(�(`�(8(��(������<��`(8��(`����`(8����||?%#"'&54632#"'&#"32654'&#"#"'&54632|�u�d��qܟ�s]
=
��Ofj�L?R@T?��"&�
>
�f?rRX=Ed�u�ds���q��
=
_M�jiL��?T@R?E& �f
>
�=XRr?��b���!1E)!34&'.##!"&5#3463!24&+";26#!"&5463!2����
��
08(��(8��8(@(8��
�

�
�8(��(88(�(`(����1

�`(88(���(88(@

��
�`(88(@(8(��`���#!"&5463!2�w�@w��w�w�`�@w��w�w��/%#!"&=463!2#!"&=463!2#!"&=463!2&��&&�&&��&&�&&��&&�&��&&�&&�&&�&&�&&�&&��@'7G$"&462"&462#!"&=463!2"&462#!"&=463!2#!"&=463!2�p�pp�pp�pp��
�@

�
��p�pp��
�@

�

�@

�
Рpp�p��pp�p���

�
�pp�p���

�
�

�
��<L\l|#"'732654'>75"##5!!&54>54&#"'>3235#!"&=463!2!5346=#'73#!"&=463!2#!"&=463!2}mQjB919+i1$AjM_3<��/BB/.#U_:IdDRE�
�@
�
����k*G�j�
�@
�

�@

�
TP\BX-@8
C)5�XsJ@�$3T4+,:;39SG2S.7<���

�vcc)�)%L�l�}�

��

�
���5e2#!"&=463%&'&5476!2/&'&#"!#"/&'&=4'&?5732767654'&��@�0��2uBo
T25XzrDCBB�Eh:%��)0%HPIP{rQ�9f#-+>;I@KM-/Q"�@@@#-bZ��$&P{<�8[;:XICC>.�'5oe80#.0(
l0&%,"J&9%$<=DTI���cs&/6323276727#"327676767654./&'&'737#"'&'&'&54'&54&#!"3!260%
<4�"VRt8<@<
-#=XYhW8+0$"+dT�Lx-'I&JKkm��uw<=V�@�!X@		v
'��|N;!/!$8:I�Ob�V;C#V

&
(���mL.A:9 !./KLwP�M�$��@@
��/?O_o��%54&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!26#!"&5463!2��@��@��@���@��@��@���@��@��@�^B��B^^B@B^�����������������������������N��B^^B@B^^���#+3	'$"/&4762%/?/?/?/?�%k��*��6�6��bbbb|��<<��<�bbbb��bbbb�%k���6���6Ƒbbb��<<��<<�^bbbbbb@��M$4&"2!#"4&"2&#"&5!"&5#".54634&>?>;5463!2�LhLLh����
	�	LhLLhL!'�Ԗ���Ԗ@'!&	
�?�&&LhLLhL�	�	
��hLLhL��	j��jj��j	&@6/"
��&&���J#"'676732>54.#"7>76'&54632#"&7>54&#"&54$ ���ok;	-j=y�hw�i�[+PM3ѩ���k=J%62>Vc��a�aQ�^��� ]G"�'9��r�~:`}�Ch�  0=Z�٤���W=#uY2BrUI1�^Fk[|��a�����L2#!67673254.#"67676'&54632#"&7>54&#"#"&5463�w��w�+U	,i<��F{�jh�}Z+OM

2ϧ���j<J%51=Ub�w��w��w�@w�zX"�'8'�T�yI9`{�Bf� 
,>X�բ���W<"uW1AqSH1�bd��w�w����'74'!3#"&46327&#"326%35#5##33#!"&5463!2����0U6c��c\=hl���ࠥ�Ymmnnnn�w�@w��w�w�w&�46#�Ȏ;ed����wnnnnn��@w��w�w����	]#/#"$&6$3 &#"32>7!5!%##5#5353����Е���tt����u�{�zz�{S�ZC�`�c�����o���t�*�t��q|��|.EXN#�??�������,<!5##673#$".4>2"&5!#2!46#!"&5463!2��r�M*
�*M~�~M**M~�~M*j����jj����&�&&&�`��P%��挐|NN|���|NN|�*�jj���jj�@��&&�&&@�
"'&463!2�@4�@&�Z4�@�4&@
#!"&4762&��&�4�Z4&&4��@@���
"'&4762�&4�@�4&@��&�4�&�@�
"&5462@�@4&&4��4�@&�&�@����
3!!%!!26#!"&5463!2�`��m��`
�^B��B^^B@B^���
 `���@B^^B�B^^��@
"'&463!2#!"&4762�@4�@&�&&��&�4��4�@�4&Z4&&4��@��
"'&463!2�@4�@&��4�@�4&@
#!"&4762&��&�4�Z4&&4��@��:#!"&5;2>76%6+".'&$'.5463!2^B�@B^,9j�9Gv33vG9�H9+bI��\
A+=66=+A
[��">nSM�A_:��B^^B1&�c*/11/*{�'VO�3��@/$$/@�*�?Nh^��l+!+"&5462!4&#"!/!#>32]��_gTRdg�d���QV?U��I*Gg?����!�2IbbIJaa���iwE33����00� 08����4#"$'&6?6332>4.#"#!"&54766$32z�䜬��m�
I�wh��QQ��hb�F�*�@&('�k�������z��
�	
_hQ��н�QGB�'(&�*�eoz�(���q!#"'&547"'#"'&54>7632&4762.547>32#".'632�%k'45%��&+�~(
(�h		&

\(
(�		&

~+54'k%5%l%%l$65+~

&		�(
(\

&		�h(
(~�+%��'��!)19K4&"24&"26.676&$4&"24&"24&"2#!"'&46$ �KjKKjKjKKj�e2.e<^P��,bKjKKj��KjKKjKjKKj��#��#���LlL�KjKKjKjKKjK��~-��M<M�(PM<rjKKjK�jKKjKujKKjK�������L���< 6?32$6&#"'#"&'5&6&>7>7&54$ L�h��я�W.�{+9E=�c��Q�d�FK��1A
0)���������p�J2`[Q?l&������٫�C58.H(Y��'����:d 6?32$64&$ #"'#"&'&4>7>7.546'&'&'# '32$7>54'Y����j`a#",5NK�
����~E�����VZ|�$2$
|��:
$2$�|ZV���:�(t}�����h�fR�88T
h�̲����X(	
&%(H�w��(%&	(X�ZT\�MKG�{x��|�!#"'.7#"'&7>3!2%632u��

�j
�H����{(e9
�1b���U#!"&546;5!32#!"&546;5!32#!"&546;5463!5#"&5463!2+!2328(��(88(`�`(88(��(88(`�`(88(��(88(`L4`(88(@(88(`4L`(8 ��(88(@(8��8(��(88(@(8��8(��(88(@(8�4L�8(@(88(��(8�L4�8����OY"&546226562#"'.#"#"'.'."#"'.'.#"#"&5476$32&"5462��И&4&NdN!>!
1X:Dx++w�w++xD:X1
-�U��
�!�*,*&4&��h��h&&2NN2D&

..J<
$$
<JJ<
$$
<J..

��P���bb&&�7!!"&5!54&#!"3!26!	#!"&=!"&5463!2��`(8��
�@

�
+��8(�@(8��(88(@(8�(��8(� @

@
�m+�U�`(88(�8(@(88(��
�h`���(\"&54&#"&46324."367>767#"&'"&547&547&547.'&54>2�l4

2cK�Eo���oED
)
�
�
�
)
D�g-;</-
?.P^P.?
-/<;-gY�����Y�

.2 L4H|O--O|HeO,����,Oe�q1Ls26%%4.2,44,2.4%%62sL1q�c�qAAq����4#!#"'&547632!2#"&=!"&=463!54632
��
��		@	
`
	��	
��

`?`�
�

@	
	@	
�!	��	
�
�
�
����54&+4&+"#"276#!"5467&5432632�
�
�
	`		_
�������v,Ԝ;G_j�)��``

��
	��		_ԟ����7
�,��>�jL>���54'&";;265326#!"5467&5432632	��		��
�
�
�
�������v,Ԝ;G_j�)���	`		����

`������7
�,��>�jL>�����X`$"&462#!"&54>72654&'547 7"2654'54622654'54&'46.' &6 �&4&&4&�y��y�%:hD:Fp�pG9�F�j� 8P8 LhL 8P8 E;
Dh:%������>�4&&4&}y��yD~�s[4D�d=PppP=d�>hh>@�jY*(88(*Y4LL4Y*(88(*YDw"
A4*[s�~����>�����M4&"27 $=.54632>32#"' 65#"&4632632 65.5462&4&&4�G9��������&
<#5KK5!��!5KK5#<
&ܤ��9Gp�p&4&&4&@>b�u��ោؐ&$KjK�nj��j�KjK$&����j��j�b>Ppp���
%!5!#"&5463!!35463!2+32����@\��\���8(@(8�\@@\������\@\���(88(��\��@��34#"&54"3#!"&5!"&5>547&5462�;U gI@L4�@�Ԗ�@4L2RX='�8P8��'=XR� U;Ig04Lj��jL4*\���(88(�����\��@"4&+32!#!"&+#!"&5463!2�pP@@P���j�j�@�@�\�@\�&��0�p����j��	��� \��\�&��-B+"&5.5462265462265462+"&5#"&5463!2�G9L4�4L9G&4&&4&&4&&4&&4&L4�4L�
��&���=d��4LL4d=�&&�`&&�&&�`&&�&&��4LL4
 ��&�#3CS#!"&5463!2!&'&!"&5!463!2#!"&52#!"&=4632#!"&=463�(8(��(88(�(`�x
��c�`(8���@��@��@�`(��(88(@(8(D��9�8(��`@�@@�@@��/?O_o��������-=%+"&=46;25+"&=46;2+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2%+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2%+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2+"&=46;2!!!5463!2#!"&5463!2�
@

@

@

@

@

@
�
@

@

@

@
�
@

@
�
@

@
�
@

@

@

@
�
@

@
�
@

@
�
@

@

@

@
�
@

@
�
@

@

@

@
�
@

@

@

@
�����
@
&�&&&�@

@
�@

@

@

@
�@

@
��@

@
�@

@
�@

@
�@

@
��@

@
�@

@
�@

@
�@

@
��@

@
�@

@
�@

@
��@

@
�@

@

@

@
����

`��&&�&&
��/?O_o�����%+"&=46;25+"&=46;2+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2+"&=46;2!!#!"&=!!5463!24&+"#54&+";26=3;26%#!"&5463!463!2!2�
@

@

@

@

@

@
�
@

@

@

@
�
@

@
�
@

@

@

@
�
@

@

@

@
���8(�@(8��
@

@
�
@

@
�
@
&�&&@8(�(8@&�@

@
�@

@

@

@
�@

@
��@

@
�@

@
�@

@
��@

@
�@

@

@

@
��� (88( ���

�@

``

��

``
-�&&& (88(��&@����<c$4&"2!#4&"254&+54&+"#";;26=326+"&5!"&5#"&46346?>;463!2�KjKKj�����KjKKj�������&��Ԗ���Ԗ�&&�@�&�&KjKKjK��
��jKKjK ������.��&j��jj��j&4&�@�@&&���#'1?I54&+54&+"#";;26=326!5!#"&5463!!35463!2+32����������� \��\����8(@(8�\  \����������\@\���(88(��\����:
#32+53##'53535'575#5#5733#5;2+3����@��E&&`�@@��`  ����  `��@@�`&&E%@�`��@ @ @��		 �� � � � �� 		��@ 0
@��!3!57#"&5'7!7!��K5�������@ � � @���5K�@����@@��� �����#3%4&+"!4&+";265!;26#!"&5463!2&�&�&�&&�&&�&�w�@w��w�w���&&��@&&��&&@��&&��@w��w�w�����#354&#!4&+"!"3!;265!26#!"&5463!2&��&�&��&&@&�&@&�w�@w��w�w�@�&@&&��&�&��&&@&:�@w��w�w��-M�3)$"'&4762	"'&4762	s
2

�.

�

2

�w��
2

�.

�

2

�w��
2

�

�

2

�w�w

2

�

�

2

�w�w
M�3)"/&47	&4?62"/&47	&4?62S
�.

2

��w

2

��
�.

2

��w

2

�M
�.

2

��

2

�.

�.

2

��

2

�.M�3S)$"'	"/&4762"'	"/&47623
2

�w�w

2

�

�

2

�w�w

2

�

��
2

��w

2

�

�.v
2

��w

2

�

�.M�3s)"'&4?62	62"'&4?62	623
�.

�.

2

��

2

�.

�.

2

��

2�
�.

�

2

�w�

2v
�.

�

2

�w�

2-Ms3	"'&4762s
�w�

2

�.

�

2�
�w�w

2

�

�

2
MS3"/&47	&4?62S
�.

2

��w

2

�M
�.

2

��

2

�.M
3S"'	"/&47623
2

�w�w

2

�

�m
2

��w

2

�

�.M-3s"'&4?62	623
�.

�.

2

��

2-
�.

�

2

�w�

2���/4&#!"3!26#!#!"&54>5!"&5463!2
��

@
�^B��  &�&  ��B^^B@B^ @

��
M��B^%Q=
&&<P&^B@B^^�+3"&5463!2#3!2654&#!"3#!"&=324+"3�B^^B@B^^B��
@

��
`�^B��B^�p�^B�B^^B�@B^`�@

�
�S`(88(``  ��'$4&"2%4&#!"3!26#!"&5463!2�&4&&4�
��

@
�^B��B^^B@B^f4&&4&��

�@
��B^^B@B^^/$4&"2%4&#!"3!264+";%#!"&5463!2�/B//B�
�


���0L4�4LL44L_B//B/��

�@
M   �4LL44LL���  >& $$ ������(���r���^����a�a��������(���^����a�a����!C#!"&54>;2+";2#!"&54>;2+";2pP��PpQ��h@&&@j�8(�Pp�pP��PpQ��h@&&@j�8(�Pp@��PppP�h��Q&�&�j (8pP��PppP�h��Q&�&�j (8p��!C+"&=46;26=4&+"&5463!2+"&=46;26=4&+"&5463!2Q��h@&&@j�8(�PppP�Pp�Q��h@&&@j�8(�PppP�Pp��@h��Q&�&�j (8pP�PppP�@h��Q&�&�j (8pP�Ppp@�@�	#+3;G$#"&5462"&462"&462#"&462"&462"&462"&462#"&54632K54LKj=KjKKj��KjKKj�L45KKjK�<^�^^��KjKKj��p�pp���\]��]\��jKL45K��jKKjKujKKjK��4LKjKK�^^�^��jKKjK��pp�p�r]��]\����� $$ ���^����a�aQ�^����a�a�����,#"&5465654.+"'&47623 #>bq��b�&4�4&�ɢ5����"		#D7e�uU6�&4&��m����1X".4>2".4>24&#""'&#";2>#".'&547&5472632>3�=T==T=�=T==T=��v)�G�G�+v�@b��R�R��b@�=&����\N����j!>�3l�k����i�k3�hPTDDTPTDDTPTDDTPTDD|x��xX�K--K��|Mp<#	)>dA{��RXtfOT# RNftWQ���,%4&#!"&=4&#!"3!26#!"&5463!2!28(�@(88(��(88(�(8��\�@\��\@\��\���(88(@(88(�@(88�@\��\�\��\ �u�'E4#!"3!2676%!54&#!"&=4&#!">#!"&5463!2!232�5��([��5@(\&��8(��(88(��(8,�9.��+�C��\��\@\� \��6Z]#+��#,k��(88(@(88(��;5E�>:��5E�\�\��\ �\�1. ���$4@"&'&676267>"&462"&462.  > $$ n%��%/���02�
KjKKjKKjKKjKf���ff�������^����a�a�y��y/PccP/�jKKjKKjKKjK���ff���ff�@�^����a�a�����$4@&'."'.7>2"&462"&462.  > $$ n20���/%��7KjKKjKKjKKjKf���ff�������^����a�a3/PccP/y��	jKKjKKjKKjK���ff���ff�@�^����a�a�����+7#!"&463!2"&462"&462.  > $$ �&��&&��&KjKKjKKjKKjKf���ff�������^����a�a�4&&4&�jKKjKKjKKjK���ff���ff�@�^����a�a���#+3C54&+54&+"#";;26=3264&"24&"2$#"'##"3!2@������@KjKKjKKjKKjK����ܒ���,����������gjKKjKKjKKjK�X�Ԁ�,�,��#/;GS_kw�����+"=4;27+"=4;2'+"=4;2#!"=43!2%+"=4;2'+"=4;2+"=4;2'+"=4;2+"=4;2+"=4;2+"=4;2+"=4;2+"=4;54;2!#!"&5463!2�``����``��`��``�``�``�``�``�``�````�p`���K5��5KK5�5Kp``�``�``��``�``�``��``�``��``��``�````��`��������5KK5�5KK@���*V#"'.#"63232+"&5.5462#"/.#"#"'&547>32327676���R?d�^��7ac77,9x�m#@#KjK�#
ڗXF@Fp:f��_ #W��Ip�p&3z�	�h[ 17��q%q#:��:#5KKu�'t#!X:	%�#+=&>7p@���*2Fr56565'5&'.	#"32325#"'+"&5.5462#"/.#"#"'&547>32327676@��ͳ�����8
2.,#,f�k*1x���-!���#@#KjK�#
ڗXF@Fp:f��_ #W��Ip�p&3z�	�e�`��v�o�8�t-�	�:5	��[�*�#:��:#5KKu�'t#!X:	%�#+=&>7p
�3$	"/&47	&4?62#!"&=463!2I�.

2

��w

2

�
-�@�)�.

2

��

2

�.
�-@@-��S�$9%"'&4762		/.7>	"/&47	&4?62i2

�.

�

2

�w�
E��>

u>

��.

2

��w

2

�
�2

�

�

2

�w�w
!��




�h�.

2

��

2

�.
���;#"'&476#"'&7'.'#"'&476�'
�)'�s
"+5+�@ա'
�)'����F*4*E�r4�M:�}}8��GO
�*4*������~�
(-/'	#"'%#"&7&67%632���B�;><���V�?�?V�� -����-C�4
<B�=�cB5���!%��%!�b 7I�))�9I7���	#"'.5!".67632y��(
��#

��##@,(
�)���8!	!++"&=!"&5#"&=46;546;2!76232-S��S����������S�

		��S��S�`���`���		

������K$4&"24&"24&"27"&5467.546267>5.5462 8P88P88P88P�8P88P�4,�C��S,4p�p4,,4p�p4,6d7AL*',4p�pP88P8�P88P8HP88P8`4Y��&+(>EY4PppP4Y4Y4PppP4Y�%*<O4Y4Ppp���
%@\ht�	"'&4762"&5462&#!"&463!2#"'&'7?654'7&#"&'&54?632#!"&463!2"&5462"'&4762��		

	����@U�SxyS���R���#PT����('�#��TU�SxySN���@����		

		�		

		
3��@��xS�SUO#���'(���V^�'(���PVvxS�SU��i��@��		

		
`�<+"&=46;2+"&=467>54&#"#"/.7!2���<'G,')7��N;2]=A+#H

�
�0P��R��H6^;<T%-S�#:/*@Z}


>h���.%#!"&=46;#"&=463!232#!"&=463!2�&�&&@@&&�&@&�&�&&&��&&�&�&�&&��&f�&&�&&b�#!"&=463!2#!"&'&63!2&�&&&'�'%@% �&&�&&�&&&&�k%J%#/&'#!53#5!36?!#!'&54>54&#"'6763235���
����Ź���}���4NZN4;)3.i%Sin�1KXL7觧�*		��#��&		*������@jC?.>!&1'\%Awc8^;:+<!P��%I%#/&'#!53#5!36?!#!'&54>54&#"'6763235���
����Ź���}���4NZN4;)3.i%Pln�EcdJ觧�*		��#��&		*������-@jC?.>!&1'\%AwcBiC:D'P%!	#!"&'&6763!2�P������&:�&?�&:&?����5"K�,)""K,)���h#".#""#"&54>54&#"#"'./"'"5327654.54632326732>32�YO)I-D%n "h.=T#)#lQTv%.%P_�	%	
%�_P%.%vUPl#)#T=@�/#,-91P+R[�Ql#)#|'�'
59%D-I)OY[R+P19-,##,-91P+R[YO)I-D%95%�_P%.%v���'3!2#!"&463!5&=462 =462 &546 ����&&��&&��&4&r&4&�������@����&4&&4&�G݀&&������&&f��������
��sCK&=462	#"'32=462!2#!"&463!5&'"/&4762%4632e*&4&i����76`al�&4&���&&��&&}n�

R

�

R
�z����f�Oego�&&�5�����`3��&&����&4&&4&�
D�

R

�

R
z����v���"!676"'.5463!2@�@w^�Cc�t~55~t�cC&�&@���?J���V��|RIIR|��V&&��#G!!%4&+";26%4&+";26%#!"&546;546;2!546;232�����@@@@�L4��4LL4�^B@B^�^B@B^�4L�� �� ��N�4LL44L`B^^B``B^^B`L����L4&"2%#"'%.5!#!"&54675#"#"'.7>7&5462!467%632&4&&4��@�o�&�&}c ;pG=(
8Ai8^�^.�&4&&4&`��	`f�s��&& j�o/;J!#2
 KAE*,B^^B!`	$� ��-4&"2#"/&7#"/&767%676$!2�8P88P��Qr��	@
U���	@�
{`P�TP88P8�����P`��
�	@U	@�rQ���!6'&+!!!!2Ѥ���
8�������̙�e�;<*��@8 !�G��G�GQII���� %764'	64/&"2 $$ �f��3f4�:�4����^����a�a�f4334f�:4�:�^����a�a����� %64'&"	2 $$ ���:4f3��f4F���^����a�a��4�f4���4f�^����a�a����� 764'&"27	2 $$ �f�:4�:f4334����^����a�a�f4��:4f3���^����a�a����� %64/&"	&"2 $$ -�f4���4f�4����^����a�a��4f��3f4�:w�^����a�a���@��7!!/#35%!'!%j��/d��
�jg2�|�8�����������55���dc ��b���@��!	!%!!7!���FG)��D�H:�&�H����d���S)��U4&"2#"/ $'#"'&5463!2#"&=46;5.546232+>7'&763!2�&4&&4f]w�q�4�qw]	`dC���&&�:F�ԖF:�&&���Cd`�4&&4&����	]����]	`d[}�&�&�"uFj��jFu"�&�&�y}[d�#2#!"&546;4 +"&54&" (88(�@(88( r&@&�Ԗ8(��(88(@(8@����&&j��j�����'3"&462&    .  > $$ �Ԗ������>a��X��,��f���ff�������^����a�a�Ԗ�Ԗ�a>����T�X��,�,�~�ff���ff�@�^����a�a����/+"&=46;2+"&=46;2+"&=46;2�8(�(88(�(88(�(88(�(88(�(88(�(8 �(88(�(88(�(88(�(88(�(88(�(88��/+"&=46;2+"&=46;2+"&=46;2�8(�(88(�(88(�(88(�(88(�(88(�(8 �(88(�(88�(88(�(88�(88(�(88���5E$4&"2%&'&;26%&.$'&;276#!"&5463!2KjKKj�
���
��
�
f���	

�\�
�
�w�@w��w�w��jKKjK"�G

�
ܚ

��f


�
���

	�@w��w�w�����  $64'&327/�a����^�����  ��!  ����^����a�a��J@%��%	6�5��/	64'&"2	"/64&"'&476227<���ij��6��j6��u%k%~8p�8}%%�%k%}8p�8~%<���<�ij4j��4����t%%~8�p8~%k%�%%}8�p8}%k���54&#!"3!26#!"&5463!2&��&&�&�w�@w��w�w�@�&&�&&:�@w��w�w����/#!"&=463!24&#!"3!26#!"&5463!2���@�^B��B^^B@B^��w��w��w@w��@@�2@B^^B��B^^���w��w@w���+#!"'&?63!#"'&762�(��@�	@�(@>@�%����%%��� ���!232"'&76;!"/&76 �
�($��>��(����
		��J ���&%�����$%64/&"'&"2#!"&5463!2�ff4�-�4ff4f�w�@w��w�w��f4f�-�f4����@w��w�w�����/#5#5'&76	764/&"%#!"&5463!2��48`���
#�� ����\�P\��w�@w��w�w���4`8�
��
#�@  ���`\P�\`�@w��w�w�����)4&#!"273276#!"&5463!2&� *���f4�
'�w�@w��w�w�`�&')���4f�*�@w��w�w�����%5	64'&"3276'7>332#!"&5463!2�`��'(wƒa8!
�,j.��(&�w�@w��w�w��`4`*�'?_`ze<��	bw4/�*��@w��w�w�����-.  6 $$ ���� �������(�r���^����a�a���O����(��������_�^����a�a�����
-"'&763!24&#!"3!26#!"&5463!2y��B��(�(�
�@

�
�w�@w��w�w�]#�@�##� �

�@
�@w��w�w�����
-#!"'&7624&#!"3!26#!"&5463!2y(��(@B@u
�@

�
�w�@w��w�w��###��@���

�@
�@w��w�w�����
-'&54764&#!"3!26#!"&5463!2@�@####���@��w�@w��w�w��B��(�(������@�@w��w�w����`%#"'#"&=46;&7#"&=46;632/.#"!2#!!2#!32>?6�#
!"'�?_

BCbCa�f\	+
~�2�	
��
	�}0�$

��
q
90r�
�

�pr%Dpu���?#!"&=46;#"&=46;54632'.#"!2#!!546;2��D
a__����	g	

*`-Uh1

��������

�߫�}
	$^L��
���
4��b+"&=.'&?676032654.'.5467546;2'.#"�ǟ�
B{PDg	q�%%Q{%P46'-N/B).ĝ
�9kC<Q
7>W*_x*%K./58`7E%_���
�	,-3�
cVO2")#,)9;J)���
�"!*�
#VD,'#/&>AX��>++"''&=46;267!"&=463!&+"&=463!2+32��Ԫ�$
�	��	
p���U�9ӑ
@�/�*f�����o�	

VRfq
�f=S��E!#"&5!"&=463!5!"&=46;&76;2>76;232#!!2#![�
��

 ��

��
�
�%
)��
	���

��"

��Jg
Uh
B�W&WX���
hU
g��
�84&#!!2#!!2#!+"&=#"&=46;5#"&=46;463!2�j��@jo�����
������g�|�@��~�v����v�
u�n#467!!3'##467!++"'#+"&'#"&=46;'#"&=46;&76;2!6;2!6;232+32Q�Kt#�� ��#F�N�Qo!��"�դ��ѧ����!�mY

�Zga~bm]�

[o�"�U+��������,����� @��h��
h@�@X
��h��h
��@�8���3H\#5"'#"&+73273&#&+5275363534."#22>4.#2>��ut
3NtR�P*�H�o2

Lo�@!�R(�Ozh=�,G<X2O:&D1A.1G$<2I+A;"B,;&$��L��GlF/�����3�D�����;a��$8$��".�!3!
��.�3!#!"&5463!���8( 8(��(88( ��h (8��(88(@(8�(8H!!#!"&5463!54&#!"3!2654&#!"3!2654&#!"3!26��(D 8(��(88( 8��@��@��@�$����(88(@(8��(8� @@@@@@"�}
$BR3/&5##"'&76;46;232!56?5"#+#5!76;5!53'#3!533��H��
��

�����D��q		�x7��	���K/�/K��F��h�/"���		@`����Z		s�Y��w�jj��jj��j"�}
$4R%3/&5##"'&76;46;232!53'#3!533!56?5"#+#5!76;5��H��
��

��������K/�/K��F����q		�x7��	�h�/"���		@`����jj��jj��j�Z		s�Y��
w"�)9IY%#"'&76;46;232#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2�
��

����� ��@������@���`��		@`�����������"�)9IY#!"&=463!2%#"'&76;46;232#!"&=463!2#!"&=463!2#!"&=463!2��� 
��

�������@��������@ ��r��		@`��r������"��
$CV%4&#"326#"'&76;46;232%#"'&'73267##"&54632!5346=#'73BX;4>ID2F��
��

������8PuE>.'%&TeQ,j��m{��+�>R�{�?jJrL6V��		@`��7>wmR1q
uW�ei��/rr�
:V��r"��
$7V4&#"326#"'&76;46;232!5346=#'73#"'&'73267##"&54632BX;4>ID2F��
��

������+�>R�{�8PuE>.'%&TeQ,j��m{��?jJrL6����		@`���rr�
:V��r3>wmR1q
uW�ei����@�\%4&#"326#!"&5463!2+".'&'.5467>767>7>7632!2&%%&�&��&& &�7.'	:@�$LB�WM{#&$h1D!		.I/!	Nr�&&%%��&&�&&V?, L=8=9%pEL+%�%r@W!<%*',<2(<&L,"r�@\#"&546324&#!"3!26%#!#"'.'.'&'.'.546767>;&%%&�&��&& &i7qN��	!/I.		!D1h$&#{MW�BL$�@:	'.�&&%%���&&��&&�=XNr%(M&<(2<,'*%<!W@r%�%+LEp%9=8=L ���	+=\d����%54#"327354"%###5#5#"'&53327#"'#3632#"'&=4762#3274645"=424'.'&!  7>76#'#3%54'&#"32763##"'&5#327#!"&5463!2��BB��PJN�C'%!	B?)#!CC $)�54f�"��@@
B+����,A

A+�&�+A
�
ZK35N #J!1331�CCC $)��w�@w��w�w��2��"33�F�Y�F~��(-%"��o�4*)$�(*�	(&;�;&&9LA38�33�4��S,;;,W��T+<<+T;(��\g7�x�:&&:�:&&<r����%-�@w��w�w����	+=[c}���#"'632#542%35!33!3##"'&5#327%54'&#"5#353276%5##"=354'&#"32767654"2 '.'&547>76 3#&'&'3#"'&=47632%#5#"'&53327�''RZZ�:k��id YYY.06�	62+YY-06	R[!.�'CD''EH$��VV�X:���:Y
X;��:Y
�fyd/%jG�&DC&&CD&O[52.
[$�C-D..D�^^���* l�y1%=^�I86�i077S
3
$EWgO%33%O�O%35	��EE�F�W�t;PP;p��t;PP;p�q��J�gT��F�Q%33&P�P%33%R�
7>%3���!+}��{�'+"&72'&76;2+"'66;2U
�&�
��	�(���P

�*��'�e�J."�-d�Z��-n �-���'74'&+";27&+";276'56#!"&5463!2�~�}�		�7��e �	���۩w�@w��w�w��"���
$Q#�'�!#
����@w��w�w��
�I-22#!&$/.'.'.'=&7>?>36����9II ! '	$ !�����01$$%A'	$ ! ����g	
\7@�)(���7Y
	
 \7@�)(���7Y
@����	'5557	���,���VW�QV���.R���W��=���?��l��%l`��������~����0��!#!#%777	5!	������R!!�XC�C��fff�݀�#�� `��,��������{��{{�`��������Og4&"2 &6 $"&462$"&62>7>7>&46.'.'. '.'&7>76 �Ԗ�� ���HR6L66L�G�HyU2LL2UyH��HyU2LL2UyHn
��X�6X��

��X�X��
Ԗ�Ԗ�����H�6L66L6�L2UyH��HyU2LL2UyH��HyU2L�n�6X��

��X�X��

�����2#!"&54634&"2$4&"2�w��w�@w��w�|�||��|�||���w�@w��w�w����||�||�||�|���	!3	37! $$ �n6^�5�5^h
����^����a�a������M�1�^����a�a���P��
*Cg'.676.7>.'$7>&'.'&'? 7%&'.'.'>767$/u5'&$I7o�b?K�\[z�H,1���+.@\7<��?5\V
,$V��g.GR@ �7��U,+!�����
	#	"8$}�{)�<�?L RR;kr,yE[��z#	/1
"#	#�eCI0/"5#`�	��"8���4~&p)4	2�{�H-.%W.L>���':Yi4&67&'&676'.'>7646&' '7>6'&'&7>7#!"&5463!2PR$++'TJX�j7-F��C',��,&C
."��!$28��h�/���"�	+p��^&+3$
i��0(�w�@w��w�w��+.i6=Bn\C1XR:#"�'jj�8Q.cAj�57!?"0D��$4"P[
&2�@w��w�w��D��"%.5#5>7>;!!76�P�Yh�pN!�HrD0�M��
 C0N��#>8\xx: �W]oW-�X���45���/%'#.5!5!#"37>#!"&5463!2p>,;$4
��5eD�+W�cE���w�@w��w�w�K�()��F
,VhV��^9tjA0/�@w��w�w���@�#"'&76;46;23�
��


��
	���&��

��� ���++"&5#"&7632�	���
^


c
� �&�

��@�#!'&5476!2� &��

����
^


b	���'&=!"&=463!546�
��� �&�
�
��	���
��
��q&8#"'&#"#"5476323276326767q'T��1[VA=QQ3���qq�Hih"-bfGw^44O#A���?66%CKJ�A}}�  !"�䒐""A$@C3^q|�z=KK?6�lk)���%!%!��V��V��u��u�u^-�m5�w��}�n�����~7M[264&"264&"2"&546+"&=##"&5'#"&5!467'&766276#"&54632�  �  ��*<;V<<O@-K<V<�<+*<J.@�k��c�lG
H_�_H
�<+*<<*+<    �<*�R+<<+�*<�f.@�+<<+��+<<+�@.��7�uu�7�
�**�
���R+<<+�+;;	��"%3I�#5472&6&67><&4'>&4.'.'.'.'.'&6&'.'.6767645.'#.'6&'&7676"&'&627>76'&7>'&'&'&'&766'.7>7676>76&6763>6&'&232.'.6'4."7674.'&#>7626'.'&#"'.'.'&676.67>7>5'&7>.'&'&'&7>7>767&'&67636'.'&67>7>.'.67�	\
��
	U7	
J#!W!'	

"';%

k	)"	
	'


/7* 		I	,6
*&"!

O6*
O $.(�	*.'

.x�,	$CN��	
�		*	�
6
		
7%&&_f&
",VL,G$3�@@$+
"


V5 3"	
""�#dA++
y0D-%&n4P'A5j$9E#"c7Y
6"	&
8Z(;=I50' !!e
�R
��
"+0n?�t(-z.'<>R$A"24B@(	~	9B9,	*$		
		<>	?0D�9f?Ae �	.(;1.D	4H&.Ct iY% *	�
7��


��
J	 <
W0%$	
""I!
*D	 ,4A'�4J"	.0f6D�4p�Z{+*�D_wqi;�W1G("%%T7F}AG!1#% JG3��� '.2>Vb%&#'32&'!>?>'&' &>"6&#">&'>26 $$ *b6�~�#��= ���XP2��{&%gx|�� .���W)o���O��LO�sEzG<��	CK}E	$MFD<5+
z���^����a�a$�MW�M��1>]|�YY�^D
�եA��<��K�m����E6<�"�@9I5*�^����a�a�����>^4./.543232654.#"#".#"32>#"'#"$&547&54632632�':XM1h*�+D($,/9p�`D�oC&JV<�Z PA3Q1*223�I�oBkែhMI����oPែhMI��oP�2S6,M!"@-7Y.?oI=[<%$('3 -- <-\�%Fu���Po��IMh���Po����IMh,���#?D76&#!"7>;267676&#!"&=463!267
#!"'&5463!26�%�8#!�
��&&Z"�M>2!��
	�^I7LRx_@�>MN�""��`�=&&*%�I�}��,
	�	L�7_jj��9����/%4&#!"3!264&#!"3!26#!"&5463!2�� ��� ��&��&&�&��������&&�&&��19#"'#++"&5#"&5475##"&54763!2"&4628(3�-�	&�B.�.B�&	�-�3(8Ig�gI�`������(8+U��e&��.BB.&����+8(�kk��`�������%-"&5#"&5#"&5#"&5463!2"&4628P8@B\B@B\B@8P8pP�Pp�����@�`(88(`�p.BB.�0.BB.���(88(�Pppͺ�������!%>&'&#"'.$ $$ ^/(V=$<;$=V).X���^����a�a��J`"(("`J��^����a�a��,���I4."2>%'%"/'&5%&'&?'&767%476762%6�[���՛[[���՛o��
�ܴ
 
���
��	��	$
$�	"	�$
$	��	�՛[[���՛[[�5`��

^�

�^

2`��
`2

^��^

��`
�����1%#"$54732$%#"$&546$763276�68��ʴh�f�킐&^�����zs��,!V[���vn)�	�6���<��ׂ�f{���z����}))N�s���3(@����+4&#!"3!2#!"&5463!2#!"&5463!2@&�&&f&��&&�&@&�&&&�4&&4&�@&&�&&��&&&& ��`�BH+"/##"./#"'.?&5#"&46;'&462!76232!46 `&�C�6�@Bb0�3eI;��:�&&�&4�L�4&���F���
�Z4&�w�4�) ���''
�5�r�&4&&�4&��&4��������}G�#&/.#./.'&4?63%27>'./&'&7676>767>?>%6}�)(."�2*&�@P9A
#sG�q]
#lh�<*46+(
	
<
5�R5"*>%</
 '2�@� 53*9*,�Z&VE/#E+)AC
(���	2k<X1$:hI(B
"	!:4Y&>"/	+[>hy
	���K
!/Ui%6&'&676&'&6'.7>%.$76$% $.5476$6?62'.76&&'&676%.76&'..676�#"NDQt	
�-�okQ//�jo_	������	���%&J�������Ղ���YJA-��.--
9\DtT+X?*<UW3'	26$>>�W0{�"F!"E �

^f`$"�_]\�<`�F�`�F�D��h>Cw�ls���J@�;=?s
:i_^{8+?`
)
O`�s2R�DE58/K��r	#"'>7&4$&5m��ī��"#���̵�$5���$�"^^W����=���ac��E�*���c������zk./"&4636$7.'>67.'>65.67>&/>z X^hc^O<q����+f$H^XbVS!rȇr?5GD_RV@-FbV=3!G84&3Im<$/6X_�D'=NUTL;2KPwt��Pt= 

�&ռ
,J~S/#NL,��8JsF);??1zIEJpq�DIPZXSF6\?5:NR=��;.&1��+!"&=!!%!5463!2�sQ9����Qs�*�*�*sQNQsBUw��
wUBF��H���CCTww���%1#"&=!"&=463!54632.  6 $$ �	��	
��

`?��������(�r���^����a�a�	��	
�
�
�
���(��������_�^����a�a�����%1#!#"'&47632!2.  6 $$ �
����		@	
`
��������(�r���^����a�a�
�
?		@	
���(��������_�^����a�a�����/#"'&476324&#!"3!26#!"&5463!2&�@�&
�@

�
�w�@w��w�w����&@B@&���

�@
�@w��w�w�����"&462  >& $$ �Ԗ��*�����(���r���^����a�a�Ԗ�Ԗ �������(���^����a�a���]�6#"$54732>%#"'!"&'&7>32'!!!2�f:�л����Ѫz��~�u:�
(�(%`V6B^hD%��i�(�]̳ޛ	��*>�6߅�����r�#�!3?^BEa�߀�#�9���#36'&632#"'&'&63232#!"&5463!2
��Q,&U�#+'
 �;il4L92<D`����w�@w��w�w�����`9ܩ6ɽ]`C4�7�7�&�@w��w�w����D+"&5#"'&=4?5#"'&=4?546;2%6%66546;2�������
	
��
	
��w�ww�w�������cB
�G]B
�G��t�y]t�y�
���#3C#!+"&5!"&=463!46;2!24&#!"3!26#!"&5463!2���@��`@`�^B��B^^B@B^��w��w��w@w��@��`@`���2@B^^B��B^^���w��w@w�����'/?P+5#"&547.467&546;532!764'!"+32#323!&ln��@
:MM:
@��nY*�Yz--zY�*55QDD�U���9p��Y-`]��]`.X /2I$�	t�@@/!!/@@3,$,3�$p$0�0��&*0��&���&��
!P@���RV2#"&/#"&/#"&546?#"&546?'&54632%'&54632763276%�>S]�8T;/M7��7T</L7�=Q7,�i�<R7,�5T</L666U;/M5�<U<,�i���6i���Q=a!;�;V6-�j�;V6-�5	P=/L596Q</L5�<U6-�i�;V7,�7O;-I6��8��i;k���)I2#!"&5463#9"'.'.'3!264&#!"2>7%>�w��w�@w��w�!"�5bBBb/�/*
8(@(87)��(8=%/�'#?��w�@w��w�w����#~$EE y &�L(88e):8(%O r		

		�O�?GQaq47&67>&&'&67>&"&#6$32#"#"'654  $&6 $6&$ Co��L��.*�KPx���.*� 
iSƓi
7J?��~�pi{_Я�;��lL�������UZ=刈�����刈�����_t'<Z
�:!
	���@!
��j`Q7$k�y, R����f��k*4�������LlL��=Z=刈��������&$&546$7%7&'5>�����]���5��%��w�����������&��P�?�zrSF�!|��&0	##!"&5#5!3!3!3!32!546;2!5463���)�
)����;)��);;)��)���&&������&@@&�&��&��	�
6 $&727"'%+"'&7&54767%&4762������֬>4P���t+8?::
	�	
::AW��``���EvEEvE<�.���"�e$IE&�O�&EI&�{h.`��m���"&#"&'327>73271[
>+)@
(���]:2,C?��*%�Zx/658:@#N
�C�=�E�(�o��E=��W'c:������#!#"$&6$3 &#"32>7!����ڝ���yy��,��{��ۀ�ہW�^F!�L�C=���y�:�y��w���߂0H\R%�"N^ '&76232762$"&5462"&46274&"&'264&#"'&&#"32$54'>$ $&6$ G>��>0yx1��4J55J�5J44J5�Fd$��?�4J55%6�E��#42F%��$f�������LlL�q>>11�J44%&4Z%44J54R1F$Z-%45J521��Z%F1#:��ʎ 9�������LlL�����#Qa"'&7622762%"&5462"&546274&#"&'73264&#"'&&#"32654'>#!"&5463!2�

5�5

*�*��.>.-@-R.>.-@-�<+*q�6�- -- 0�<�o,+< ��3�w�@w��w�w��

55

**�.. -- .. --G*<N�' ,-@-+*��M <*2
z��z
1�@w��w�w�����0<754&""&=#326546325##"&='26 $$ bZt�t&�sRQs��Z<t�sQ���^����a�a�>OpoO��xzRrqP6�z~{{Prr��^����a�a�����]054&"#"&5!2654632!#"&57265&<T<����H<T<������H������<T<8v*<<*������
��+;;+l���:�������=:��*;;*���
%!!"!!26#!"&5463!2��@� ]���]�@�w�@w��w�w�����]� �@��@w��w�w���	
%)3!!#335!!5!5!%#!!5!5!%#H��H{����R��H��H{���G��G{�)���q���G����R�R�q���R�R�q�����	#0@#"'632#"'632&#"7532&#"#7532#!"&5463!2L5+*5��L5+*5~�}7W|�3B}��}JC��7=}�w�@w��w�w�D�ZQ�[�1�N:_��)�i�$��)���@w��w�w��
)�	�����������6.#&#"'&547>'&#".'&'#"&5467%&4>7>3263232654.547'654'63277.'.*#">7?67>?>32#"'7'>3'>3235?�K�cgA+![<E0y�$,<'.cI
	,#� '!;7$�=ep���	��/�/7/
D+R>,7*
2(-#=
	/~[(D?G  �|,)"#+)O��8,+�'�6	y{=@��0mI�#938OA�E`
-�
)y_/FwaH8j7=7?%����a	%%!?)L
J
9=5]~�pj

 %(��1$",I 
$@((�
+!.S		-L__$'-9L	5V��+	
	6�T+6.8-$�0��+
t�|S1��6]�&#"'&#"67>76'&'&#"67>32764.#"#.32>67>7 $&54>7>7>7�rJ�@"kb2)W+,5/1		#

Z
-!��$IOXp7s�LCF9�vz NAG#/ 5|����Հ';RKR/J#=$,�9,�+$UCS7'2"1
 !�/
,

/--ST(::(�ep4AM@=I>".)x��ls��Y�|qK@
%(YQ�&N
EHv~����<Zx'#"&5467&6?2?'&"/.7.546326#"&'&/7264/7'764&"'?>>32.��A�UpIUxYE.A�%%%h%����%hJ%�����D,FZxULsT�gxUJrV�D�%hJ%�����@/LefL.C�%Jh%�����C�VsNUxϠ�@.FZyUHpV�A�%h&%%���%Ji%�����C�WpIUybJ/��Uy^G,D�%Jh%�����@�UsMtU�C�%hJ%�����C-Kfy�EX[_gj��&/&'.''67>7>7&'&'&'>76763>7>#&'&'767672'%'7'+"&'&546323267>7%#"'4'6767672,32�,+DCCQL�Df'
%:/d
B	4@}
�&!0$�?�����J�f�d�f-�.=���6(��:!TO�?
!I�G_�U%
����.
k*.=;�	5gN_X��	"
##
292Q41�
��*����6���nA;�|�
�BSN.	%1$����
6	$��nk�^�'7GWgw�����2+"&5463#!"&5463!254&+";2654&+";2654&+";2654&+";2654&+";2654&+";2654&+";2654&+";2654&+";26#"&=! B^^B�B^^B�:F�j��B^8(�(`�(� ������������������`�(8���^B��B^^B@B^�"vE�j�^B(8(�`(�����������������������8(����/?O_o��������/?2#!"&5463;26=4&+";26=4&+";26=4&+";26=4&+"54&+";2654&+";2654&+";2654&+";2654&+";2654&#!"3!2654&+";2654&+";2654&+";2654&+";2654&+";2654&+";2654&+";2654&+";2654&+";26@&&�&&�@@@@@@@@�@@@@@@@@@@��@@@@@@@@@@@@@@@@@@@&��&&�&��@@��@@��@@��@@��@@@@@@@@@@���@@@@@@@@�@@@@@@@@@@@��`'	"&5#"&5&4762!762$"&462���B\B@B\B��O�p�P����������.BB.���.BB.8$P��O広�������3CQ#".54>32#".546322#"&#"#"54>%".54>32%2#"&54>&X=L|<&X=M{<��TML�FTML�F�v�"?B+D�?B�J�p��H=X&<{M=X&<|dMTF�LMTF�(<kNs�I<kNs���Pvo�JPwo�/��s.=ZY�VӮv�Nk<J�sNk<I�shwPJ�ovPJ�o@��+"&7.54>2�r_-$�$-_rU���U��%��&&5%ő������'-
"'.546762����@��F�F�$�@B�@$.&�,�&.]]|�q����#<���<#(B�B��B%'-%'-'%'-"'%&'"'%.5467%467%62����@��l�l����@��l�l,���@��G�G�&!�@@�@�@@�@!&+#�+#�6�#+�$*`�:�p������:�p���x�
�p����=�`$>����>$�&@��&@�

�@&�p�@��	&.A!!"!&2673!"5432!%!254#!5!2654#!%!2#!8���Zp��?v�d���Ί�e�ns�6(���N[�����RW�u?�rt1Sr�F���|��iZ��@7�����މoy2���IM��C~[�R �yK{T:���%,AGK2#!"&5463!!2654'654.#532#532"&5!654&#"327#2#>!!�w��w�@w��w��~u��k'JTM��wa��|
DH��������>�I1q�Fj?����w�@w��w�w�����sq�*4p9O*�¸Z^���qh LE
�������"(nz8B
M���'?"&4624&#"'.'324&#"3267##"&/632632.�ʏ����hhMA�LR vGhг~��~������K„y���O^
��ʏ�ʏ��В*�LM@!<I�~��~����������t\��0�������CM4&"2#"&'676&/632#!"&=3267%2654&#"&#"%463!2"&4632�r�qq��tR8^4.<x3=RR��w�@w���_h�
Y��Ӗ���	K>�שw�w���ȍ�de�)�qrOPq�Ȧs:03=<x!m�@w��w�E\x�g�ӕ��є��%w�w����d��Ȏ��V��
-<K\%.'.>7'.?67'67%'>&%'7%7./6D�\$>	"N,��?a0�#O���1G�����9�'/���P(1#00��
($=!F"�9|��]�"RE<�6'o��9%8J$\:��\H�iTe<?}V��#�oj��?���d,6���%N#"
Hl��S��VY�]C

=�@�C4&"2!.#!"4&"2+"&=!"&=#"&546;>3!232�^�^^���Y	�	^�^^��`p�p�p�p`�]i�bb�i]�~�^^�^�e��^^�^���PppP��PppP��]��^^�]��3;EM2+"&=!"&=#"&546;>;5463!232264&"!.#!"264&" ]�`p�p�p�p`�]i�b���b�i���^^�^d�Y	�	!�^^�^��]��@PppP@@PppP@�]��^��^�]� ^�^^��e��^�^^� ��3$#!#!"&5467!"&47#"&47#"&4762++�&�2
$��$
�2&��&��&�4�&��&��Z4&�&##&�&4�&4�&4���4&�m4&�m���+DP4'&#"32763232674'&!"32763 3264'&$#"32763232> $$ g����* �o�`#�ə�0#z��#l(~���̠)���-g+����^����a�aF s"	+g�(�*
3#!|
#/IK/%*%D=)[�^����a�a����	!!!'!!77!���,���/���,�-���a��/G��	t%/;<HTbcq������%7.#"32%74'&"32765"/7627#"5'7432#"/7632#"5'7432#"&5'74632	#"/6327#"/6327#"/46329"&/462"&/>21"&/567632#!.547632632
	
	*


			��X		�

^

`		���

^b
	��c�
	f�u��
U`�59u���

���

4�J���
	
l�~		~�	F��	
��	�2�����

�
�	��	�m����|O�,��� ����	

���
��������

ru|	��u�
�
"�����
)9 $7 $&= $7 $&= $7 $&=  $&=46��w���`���w���w���`���w���w���`���w��b����`����VT�EvEEvE�T��VT�EvEEvE�T*VT�EvEEvE�T*EvE�EvEEvE�Ev�#^ct�#!"&5463!2!&'&!"&5!632#"&'#"/&'&7>766767.76;267674767&5&5&'67.'&'&#3274�(8(��(88(�(`�x
��c�`(8��!3;:�A0�?ݫ�Y

	^U	47D$

	7�4U3I�
|��L38wtL0�`(��(88(@(8(D��9�8(��Q1&(!;��
(g-	Up�~R�2(/{E���(Xz*Z%(�i6CmVo8�#T#!"&5463!2!&'&!"&5!3367653335!3#4.5.'##'&'35�(8(��(88(�(`�x
��c�`(8�iF������F��Zc�r�cZ�`(��(88(@(8(D��9�8(���k�k�"	��kk�J	 	!��	�k�#S#!"&5463!2!&'&!"&5!%!5#7>;#!5#35!3#&'&/35!3�(8(��(88(�(`�x
��c�`(8�-Kg
kL#D��C��JgjL��D���`(��(88(@(8(D��9�8(���jj�	�jjkk��kk����#8C#!"&5463!2!&'&!"&5!%!5#5327>54&'&#!3#32�(8(��(88(�(`�x
��c�`(8� G]�L*COJ?0R��\wx48>�`(��(88(@(8(D��9�8(���jj��RQxk��!RY�#*2#!"&5463!2!&'&!"&5!!57"&462�(8(��(88(�(`�x
��c�`(8�������P�pp�p�`(��(88(@(8(D��9�8(����������p�pp�	�#*7JR5#5#5#5##!"&5463!2!&'&!"&5##5!"&54765332264&"�����<(8(��(88(�(`�x
��c�`(8����k�ޑc�O"�jKKjK�������������`(��(88(@(8(D��9�8(������SmmS?M���&4&&4�#9L^#!"&5463!2!&'&!"&5!#"/#"&=46;76276'.'2764'.�(8(��(88(�(`�x
��c�`(8���������6dd�WW6&44�`(��(88(@(8(D��9�8(��.��	����G���5{��{5�]�]$59�95�#3C#!"&5463!2!&'&!"&5!2#!"&5463#"'5632�(8(��(88(�(`�x
��c�`(8��4LL4��4LL4l	��		�`(��(88(@(8(D��9�8(���L4��4LL4�4L��	
Z
	�#7K[#!"&5463!2!&'&!"&5!>&'&7!/.?'&6?6.7>'�(8(��(88(�(`�x
��c�`(8�`3��3��3��3�v
�
?
�
�`(��(88(@(8(D��9�8(���&��&-��&��&�
?


��
'���6#'.
'!67&54632".'654&#"32�eaAɢ/PRAids`WXyzO�v��д��:C;A:25@Ң>�����-05r��n������`��H(�����' gQWZc[���
-%7'	%'-'%	%"'&54762�[������3[��M���N�����
��3"��,��""3,3"o�ng�$������߆���]�g�n��$����+��)��

")")"

��x#W#"&#!+.5467&546326$32327.'#"&5463232654&#"632#".#"o���G��n\�u_MK'����̨|�g?CM7MM5,QAAIQqAy��{�b]BL4PJ9+OABIRo?z��.�z��
�n�6'+s�:�������z�cIAC65D*DRRD*�wy�al@B39E*DRRD*��'/7  $&6$ 6277&47' 7'"' 6& 6'�lL������������R�R����ZB|��R�R��>����d�ZZ��������LlL�Z����R�R«����Z��&�>���«|��R� � ��! $&54$7 >54'5��������P���f���f����P�����牉�@��s��-����ff���`-����c6721>?>././76&/7>?>?>./&31#"$&��(@8!IH2hM>'

)-*
h'N'��!'Og,R"/!YQG<I *1)

(-O1D+0�n�������z�3fw���G2'3�rd1!sF0o ��.q"!%GsH8��@-!5|w|pgS=
"B2PJfh�G���d�R	�(P]ly��&$'77&7567'676'"'7&'&'7&47'6767'627''6$'67'654'7&'7'&'&'7&'5&$  $6 $&6$ j��j:,A��A��S9bb9R#:j���8AܔA,z��C�9Z04\40Z9�C��!B�;X0,l,0X;�B�*A8ܔA&#9j`b9S$#R99#&A��8A�`
������䇇�<Z<䳎������LlL�fBϬ"129�,V<4!���!88dpm��"��BV,�92[P*V*P\M�C�

�C�M\P*V*P]L�D�

�D�L&BV*�8*8!����f�!4<gmpd88!&!8*8�*VB�Z<䇇�����䇇��������LlL�����9Eis�%#"5432#"543275#&#"3254&'.547>54'63&547#5#"=3235#47##6323#324&"26%#!"&5463!2F]kbf$JMM$&�N92<Vv;,&)q(DL+�`N11MZ
%G���&54	#	i�<$8&@��0H12F1d�w�@w��w�w��B?@�UTZ3%}rV2hD5%f-C#�C@,nO	�a7�.0�x2	yR�uR/u�%6;&�$76%$56S�@w��w�w��D��<Hlw%4#"324&#"32!".5475&5475.546322#654'3%#".535"&#"5354'33"&+32#"&54632S����;<;||w
$+�|('-GVVG-��EznA�C?H_��`Rb���]Gg>Z2&`��9UW=��N9:PO;:dhe\=R����
+)�&')-S9��9kJ�<)Um�Q��/��-Ya^"![��Y��'(<`X;_�L6#)|����tWW:;X���	#'#3#!"&5463!2)
p�*�xeשw�@w��w�w���0,\8�����@w��w�w��9��I#"'#"&'&>767&5462#"'.7>32>4."&'&54>32JrO<3>5�-&FD(=Gq���@C$39a��LL��²�L4

&)
@]��v�
�q#CO���!~󿵂<ZK#*Pq.���%
L��²�LL��arh({�w؜\���i&5467&6747632#".'&##".'&'.'#".5467>72765'./"#"&'&5
�}����1R<2"7MW'$	;IS7@�5sQ@@)�R#DvTA;
0x
I)�!:>�+<B76:NFcP:SC4r�l+r �E%.*a-(6%('�>)C	6.�>�
!-I[4&#"324&#"3264&#"324&#"326&#"#".'7$4$32'#"$&6$32D2)+BB+)3(--(3�1)+BB+)�4'--'4��'���#!0>R	�H���MŰ9�o�u7ǖD��䣣���
R23('3�_,--,�R23('3�_,--,�����NJ
������?u�W�m%������#"'%#"'.5	%&'&7632�!�
�;�
	`��u%"��(����!]#�c�)(�	��� #"'%#"'.5%&'&76	�!�
���	�(%#�#���fP_�"�(���!�)'��+�ʼn�����4I#"$'&6?6332>4.#"#!"&54766$32#!"&=46;46;2z�䜬��m�
I�wh��QQ��hb�F�*�@&('�k�������@����z��
�	
_hQ��н�QGB�'(&�*�eozΘ�@@`���  >. $$ ����ff���ff�����^����a�af���ff�����^����a�a��>�����"&#"#"&54>7654'&#!"#"&#"#"&54>765'46.'."&54632326323!27654'.5463232632�,�-,�,",:!
%�]&
%@2(/�.+�*)6!	<.$.�.*�*"+8#
�
#Q3,�,+�+#-:#"</$�)

w�

���
,*

x9-.2"'
,,
���@�&,,
��Qw
,����,#"+"&5#+"&5&'&'&547676)2�%2$l$�#l#�b~B@XXyo2�$CI@5��$$�>$$�/:yu��xv)%$	��/?CG%!5%2#!"&5463!5#5!52#!"&54632#!"&5463#5!5`���&&�&&������ �&&�&&�&&�&&@������&�&&&���������&�&&&�&�&&&��������%2 &547%#"&632%&546 #"'6���������\~����~\h�
���~\��h\�������V�
�V�������V��V���%5$4&#"'64'73264&"&#"3272#!"&5463!2}XT=��=TX}}�~�>SX}}XS>�~�}�w�@w��w�w���~:xx:~�}}Xx9}�}9xX}�@w��w�w���/>LXds.327>76 $&6$32762#"/&4762"/&47626+"&46;2'"&=462#"'&4?62E0l�,

*"�T�.�D@Yo������oo����@5D�

[		

Z
�Z

		[	 ``��[



Z

	�2
,�l0
(T�"�.�D5@������oo��oY@D,

Z

		[	�		[		

Z
��``EZ

		[		
�5%!  $&66='&'%77'727'%am��lL�������m�f�?���5���5>�f�F�tu�ut�F������������LlL�H�Y�C�L|��|L����Y�˄(��E''E*(�/?IYiy����%+"&=46;2+"&=46;2+"&=46;2+"&=46;2%"&=!#+"&=46;2+"&=46;2+"&=46;2+"&=46;2!54!54>$ +"&=46;2#!"&=������@�������&&������@��������������3P��
>��P3��&��&��r���r��r���&��&���r���r��r���
he

4LKM:%%:MKL4�W��T�&&��%/9##!"&563!!#!"&5"&5!2!5463!2!5463!2�&&�&��&�&&���� ��� ��&��&&i�@����&&@&7�����'#5&?6262�%%�o����;����j|/����&jJ%�p��&j;&i&�p���/|���j�ţ���%Jk%�o��%��	:g"&5462#"&546324&#!"263662>7'&75.''&'&&'&6463!276i���~ZYYZ~�@O��S;+[G[3YUD#o?D&G3I=J�y�TkBuhNV!WOhuAiS�y*'^C�C^'*SwwSTvvTSwwSTvv���WID\�_"[�g��q# /3qF��r2/ $r�g�%4
�HffH�J4d���#!#7!!7!#5!������VF��N����rmN�N��N����������N���!Y���+?Ne%&'&'&7>727>'#&'&'&>2'&'&676'&76$7&'&767>76'6�#
<�;1�1x��#*#
�G,T9�3%�/#0v�N�Z;:8��)M:(	&���C.J}2	%0����
 	^*
J�F	
&�7'X"2L�DM"	+��6�
M2+'BQfXV#+]
#���'
L/(e�B�9
�#,8!!!5!!5!5!5!5#26%!!26#!"&5!5���������������&4&���&�pP��Pp������������������@��@&&@��!&�@PppP@�*
��	9Q$"&54627"."#"&547>2"'.#"#"&5476$ "'&$ #"&5476$ (�}R}hL�K�
N���N
����U�d:�
�x�x�
�����8���
��
�
� ,, |2222�
MXXM

�ic,>>,�
����
�	����	�
��̺

�
��'/7?KSck{4&"2$4&"24&"24&"24&"24&"24&"24&"24&"264&"24&#!"3!264&"2#!"&5463!2�KjKKj�KjKKj��KjKKjKKjKKj��KjKKj��KjKKjKKjKKj��KjKKjKLhLLhL��KjKKj�&�&&&KjKKj�L4��4LL4�4L5jKKjKKjKKjK�jKKjK��jKKjK�jKKjK�jKKjK��jKKjK�jKKjK���4LL4��4LL�jKKjK�&&�&&��jKKjK�4LL44LL	��'E!#"+"&7>76;7676767>'#'"#!"&7>3!2�W�",&7'�	#$	&��g�pf5O�.P�q�ZZdS���-V"0kqzTx�D!��!8�p�8%'i_�F?;�k��R(`��
!�&)�'�
(2!&6367!	&63!2�!
`�B��1LO�(���+#�=)�heC��Qg#s`���f�4#����6�������q�'���X�|0-�g��	�>IY#6?>7&#!%'.'33#&#"#"/3674'.54636%#"3733#!"&5463!2��4��:@��7�vH��%�h��EP{��0&<'VFJo���1,1.F6��A��#���L4�4LL44L"%�	
 
7x'6
O\�JYFw���~�v^fH$ !�"xdjD"!�6��`J�4LL44LL��	�+3@GXcgqz�����-<JX{�&#"327&76'32>54.#"35#3;5#'#3537+5;3'23764/"+353$4632#"$2#462#"6462""'"&5&5474761256321##%354&'"&#"5#35432354323=#&#"32?4/&54327&#"#"'326'#"=35#5##3327"327'#"'354&3"5#354327&327''"&46327&#"3=#&#"32?"5#354327&3=#&"32?"#3274?67654'&'4/"&#!"&5463!2_��g��QQ��h���^_�~\[[\]�_^���h��QQ��g�e��<F�$�$$��� !!�&&�/!/

!!�

00/e&'!"e$�
		'!!�''�
	8''NgL4�4LL44L�UQ��gh��QUk=<Sc���cc,-{k���jUQ��hg��Q��



�9

,&W &$U�K$$KK$$KDC(>("
!
=))=2�( '! '�L#(>(
&�DC(>(z�L#�DzG)<)�4LL44LL��	�
BWbjq}��+532%+5324&+32763#4&'.546327&#"#"'3265#"&546325&#"32!264&"2%#'#735#535#535#3'654&+353#!"&5463!29$<=$�@?�SdO__J-<AA@)7")9,<$.%0*,G3@%)1??.+&((JgfJ*�A�������!&��j�jj��GZYG�иwssw��PiL>8aA	!M7�7MM7�7M�3!�
4erJ]��&3YM�(,
,%7(#)
,(@=)M%A20C&Me�e��(X���0&Ėjj�jV��	8Z8J9���N/4���$�8NN8�8NN��	�#&:O[���	$?b3'7'#3#%54+32%4+324+323'%#5#'#'##337"&##'!!732%#3#3##!"&53733537!572!56373353#'#'#"5#&#!'#'#463!2#"5#"5!&+&+'!!7353273532!2732%#54&+#32#46.+#2#3#3##+53254&".546;#"67+53254&.546;#"#'#'##"54;"&;7335wY-AJF���=c�(TS)!*RQ+��*RQ+�Y,�B^9^��Ft`njUM�')	~PS�PR�m���٘���M7�7Mo7�q

@)U	8�"����E(�1��++��NM7�7Mx3�7��8�D�62��W74�;�9�<�-A"EA�0:��AF@�1:�ؗ����B�f~~""12"4(�w$#11#�@}}!%+%5(�v$:O�\z��K��?*$\amcrVl��OO176Nn�<!E(=�<&l/������<<������
[ZZYY�89176���7OO7�==..//cV==::z,,,,aa,,��7OO7�Z::��;;Y
fcW�(		"6-!c�(		!5	#
b�t88176����tV:
&$'*9	%e#:
%'*9B����<<��;
&(�����	�#:Sn�����#"&54632%#76;2#"&54632%4&+";2?>23266&+"&#"3267;24&+"'&+";27%4&+";2?>23266&+"&#"3267;254+";27#76;2#!"&5463!2�3%#2%%,, _3$$2%%��M>�ALVb5)LDHeE:<
E�Mj,K'-R
M�~M>�ARVb5)LEHeE:<
E�
JAB�I*'!($rL4�4LL44Lv%1 %3!x*k�$2 %3!�;5�h
n
a�
!(lI;F	
	
��	r�p
p8;5�h

t
a�
!(lI;F��`	#k�4LL44LL
��	�
2HW[lt��#"'5632#6324&'.54327&#"#"&'32767#533275#"=5&#"'#36323#4'&#"'#7532764&"24'&#"327'#"'&'36#!"&5463!2=!9�n23��BD$ &:BCRM.0AC'0RH`Q03'`�.>,&I / *�
 /

��8/��n-(G@5��$ S3=�,.B..B�02^`o?7je;9G+��L4�4LL44LyE%#	�Vb�;A
!p &'F:Aq)%)#o�rg�T$v2�� 8�)2����z948/�{�8A�B..B/��q?@�r�<7(g/��4LL44LL��?#!"&'24#"&54"&/&6?&5>547&54626=�L4�@�ԕ;U g3
��
T
�2RX='�8P8|�5�
����4Lj��j� U;Ig@
	��
`
� "*\���(88(�]k
��&N4#"&54"3	.#"#!"&'7!&7&/&6?&5>547&54626;U gI��m*��]�Z0�L4�@�ԕ���=o=CT
��
T
�2RX='�8P8|�5�
� U;Ig��Xu?bl3���@4Lj��j��a���`
	��
`
� "*\���(88(�]k����/7[%4&+";26%4&+";26%4&+";26!'&'!+#!"&5#"&=463!7>3!2!2@@@@@@���0
��
o`^B��B^`5FN(@(NF5���@��@��@�u		�@�LSyuS�@�%44%����,<H#"5432+"=4&#"326=46;2  >. $$ ~Isy9���"SgR8v�H����D�	w
����ff���ff�����^����a�a�m2N+��	)H-mF+1����0*F		+f���ff�����^����a�a�����b4&#"32>"#"'&'#"&54632?>;23>5!"3276#"$&6$3 �k^?zb=ka`�U4J{�K_/4�^����W�&	vx :XB0���܂�ff���)
f������zz��X��lz=l�apz��o�b35!2BX���
�G@8��'	'=vN$\f���f�	1
	SZz�8�z�X�#("/+'547'&4?6276	'D�^�h

�

i��%5�@�%[i

�

h�]��@������]�h

�

i��%�@�5%[i

�

h�^�@@������)2#"&5476#".5327>OFi-���ay~�\~;��'�S���{�s:D8>)AJfh]F?X��{[��TC6��LlG��]��v2'"%B];$�-o��%!2>7>3232>7>322>7>32".'.#"#"&'.#"#"&'.#"#546;!!!!!32#"&54>52#"&54>52#"&54>52�-P&+#($P.-P$'#+&PZP&+#"+&P-($P-.P$(#+$P.-P$'#+&P-.P$+#pP@@Pp�H85K"&ZH85K"&ZH85K"&Z����@��Pp��@��@��@pMSK5, :&�LMSK5, :&�LMSK5, :&����!!3	!	�����@�����@@�����	#"$$3!!2"j������aѻxl���a����lx�a�a����j������!!3/"/'62'&63!2��'y��

�`�I

��y�����My��

�`�I

��y'W`#".'.#"32767!"&54>3232654.'&546#&'5&#"

4$%Eӕ;iNL291 ;XxR`�f՝�Q8T������W��iW�gW:;*:`�Qs&?RWXJ8�oNU0�J1F@#)
[�%6_PO�QiX(o�`��_?5�"$���iʗ\&>bd�s�6�aP*< -;iFn�*-c1B���Wg4'.'4.54632#7&'.#"#"'.#"32767'#"&54632326#!"&5463!2��#$(	1$6]'
!E3P|ad(2S;aF9'EO�Se�j]�m�]<*rYs��hpt.#)$78L*k�h�w�@w��w�w��B

%
$/$G6
sP`X):F�/�fwH1p�dl�qnmPH�ui�kw_:[9D'��@w��w�w��34."2>$4.#!!2>#!".>3!2�Q��н�QQ��н�QQ��h�~w��w�h���f����ff����н�QQ��н�QQ��н�QZ����ZQ�����ff���ff�#>3!2#!".2>4."f����ff�����н�QQ��н�QQ���ff���ff��Q��н�QQ��н�	,\!"&?&#"326'3&'!&#"#"'  5467'+#"327#"&463!!'#"&463!2632���(#�AH����s���9q � ci��<=�
#�]�<������OFA��!�������re��&&��U�&&![e��F �������U?���g�����4_���������a�?b�+��r7�&4&��&4&�p,�+K4&"2$4&"2.#!"3!264&#!"3!2#"&=!"&=#47>$ �KjKKjKKjKKjH#�j#H&&&������KjK�KjK�g	�V�	ijKKjKKjKKjK���..n((�[���5KK5��5KK5�[po�Nv<<vN�:f���.R#!"&463!24'!"&5463!&$#"!2#!32>+#"'#"&546;&546$3232�2$�B$22$�$�*$22$�X�ڭ��ӯ�$22$�tX'���hs2$���ϧ��kc�$22$���1���c�$2�F33F3VVT2#$2����ԱVT2#$2��g���#2UU���݃
�2$#2UU�1݃���2��,u�54#"67.632&#"32654'.#"32764.'&$#"7232&'##"&54732654&#"467&5463254632>32#"'&�ru�&9��%"*#�͟ <yK0Og�" 
&9B3�;��㛘8��s%+DWXRD= @Y%�	!Q6R�!4M8�+6rU^z=)�RN��.)C>O%GR�=O&^���op������C8�pP*�b�Y
_�#��$��N Pb@6��)?����+0L15"4$.�Es
�5I�Q"!@h"�Y7e|J>z�iPe��n�eHbIl�F>^]@����n*9
���6[_3#"&54632#.#"32%3#"&54632#.#"326%4&'.'&! ! 7>7>!���������
�=39?
6'_����������
�>29?
5'17m-V����U--,�bW.�������뮠@Fyu0HC$������뮠@Fyu0HC$L���=??
<����=! A	<��`�;+"&54&#!+"&5463!2#!"&546;2!26546;2���p���Ї����0�p�����p���@��I�������pp���>Sc+"&=46;254&+"&+";2=46;2;2=46;2;2%54&#!";2=;26#!"&5463!2���A5�DD�5A7^6a7MB5��5B7?�5B~�`��`��`0`��rr��5A44A5�����v�5AA5�f�*A���`��`0`�����	!!!!	#!"&5463!2��ړ�7���H��7j�v�@v��v�v��'���:��@v��v�v���MUahmrx���������������#"'!"'!#"&547.547.54674&547&54632!62!632!#!627'!%!"67'#77!63!!7357/7'%#	%'3/&=&'	5#?&5476��!�p4�q"���"�"�6�"� ��'������h*�[���
��|�*��,�@���?wA�UM�pV���@�˝�����)��Ϳw����7(�{��*U%���K6������=0�(���M���		��"!O		dX$k
!!��!
����b��	
���[�����TDOi
��@��6��b��xBA�ݽ�5
�
�ɝ:����J���+���3����,��p
x�1���������Fi
(��R��
463!#!"&5%'4&#!"3���`����а@.�.@A-X��f�B����$��.BB.�.C��}
)&54$32&'%&&'67���"w�`�Rd]G�{��o]>p6��sc(��@wg����mJ�PAjy���YW�a͊AZq���{HZ�:�<dv\gx�>��2AT�Kn������+;"'&#"&#"+6!263 2&#"&#">3267&#">326e��~�└�Ȁ|��隚���Ν|����ū|iy�Zʬ��7Ӕ�ް�r|�uѥ��x�9[��[9�jj��9A�N��N�+,#ll"���B�S32fk��[/?\%4&+";26%4&+";26%4&+";26%4&+";26%#!"&5467&546326$32�]]��ee��ee��ee��$��~i
�qfN-*���������#����Sj������t�2"'q�C���B8!�'�>	
!%)-159=AEIMQUY]agkosw{��������!	%!	5!#5#5#5#5#57777????#5!#5!#5!#5!#5!#5!#5!#5#537#5!#5!#5!#5!#5!#55#535353535353%"&546326#"'#32>54.&54>3237.#"����������Q%%%%%%%%%?iiihOiixiiyiixii�Arssrrssr��%s�ssrrss�Ns%%%%%%%%%%�����������'<D<'paC_78#7PO7)("I$	75!����RA��b��(���ss�ss�ss�ss�ss�"/!".""."
!."".!/^.".^.".]/".�$$$$$$$$$$$$$$$$��Os$$$$$$$$$$$$$$sO$s�ss�ss�ss�ss�ss#��������}$)	13?*
,./:
-�s�*4&"2$4&"2#!"&5463!2!5463!2_��������?-��-??-�,@�@,�-?����pq�8��,??,D,??,��,??(�Z2#".#"3267>32#".543232654&#"#"&54654&#"#"&547>326���ڞU�zrhgrx�S��Пd�U <e�����x՞����Zf��_gן:k=2;�^��9��Œ��7\x��x\7����K=5Xltֆ�W����W{e_�%N��%,%CI��%���#+W4&+54&"#";26=32"&462"&462!2#!"&54>7#"&463!2!2�&�&4&�&&�&4&���KjKKj�KjKKj� ���&&�&%��&&�&&4&�&&�&4&�&&��5jKKjKKjKKjK��%z
0&4&&3D7&4&
%&���'S4&"4&"'&"27"&462"&462!2#!"&54>7#"&463!2!2&4�&4&�4&4��KjKKj�KjKKj� ���&&�&%��&&�&&4&�%&&�ے&4��"jKKjKKjKKjK��%z
0&4&&3D7&4&
%&��	&	!'!	!%!!!!%"'.763!2�o���]�F������o�������oZ��Y��@:�@�!�!�g���������������f�/�/��I��62'"/"/"/"/"/"/"/7762762762762762762%"/77627&6?35!5!!3762762'"/"/"/"/"/"/%5#5!4�ZSS6SS4SS4SS4SS4SS4SS4�ZSS4SS4SS4SS4SS4SS4S�-4�ZSS4S@������4SS4�ZSS6SS4SS4SS4SS4SS4S@�����ZSSSSSSSSSSSSSS�ZSSSSSSSSSSSSSy�ZRRR@%:=
:+������:
=���RR�ZSSSSSSSSSSSSS���������Cv!/&'&#""'&#"	32>;232>7>76#!"&54>7'3&547&547>763226323@``����`
VFaaFV


$.


.$

��y��y�	.Q5Z���E$ ,l<l, $E���R?Y*��@���@�2	!#""#!	��y��y=r�na�@@(89*>�*%>>%*�>*98(QO�!���L\p'.'&67'#!##"327&+"&46;2!3'#"&7>;276;2+6267!"'&7&#"(6&#"#"'�D��g��OOG`n%�E������LL{�@&&�N�c,sU�&&�!Fre&&�s�����s���#�/,�������<=�
#�]�g��L�o�GkP�'��r-n&4&2�-ir&�&�?���o 
��������4_�����5OW! .54>762>7.'.7>+#!"&5#"&5463!2"&462�{�����{BtxG,:`9(0b��Կ�b0(9`:,GxtB��&@&�&@&K5�5K`�����?e==e?1O6#,
#$
,#6OO��&��&&�&�5KK���������?!"'&'!2673267!'.."!&54632>321
��4��q#F�""�8'g��o#-��#,"t�Yg��>�oP$$Po�>�	��Z�e�p#����)�R��0���+I@$$@I+����+332++"&=#"&=46;.7>76$  ������@����ᅪ*��r���������@��@�����������r���'/2+"&5".4>32!"&=463  �&@��~[���՛[[��u˜~���gr�������&�`����u՛[[���՛[~~@��r������=E32++"&=#"&=46;5&547&'&6;22676;2  >�����``@``�ٱ��?E,��,=?��r�������H�����@``@�GݧH`�j��j���r������BJ463!2+"&=32++"&=#"&=46;5.7676%#"&5   &@�~���``@``�� �v�X����r�������&���������@``@����+BF��`r������ks463!2+"&=32++"&=#"&=46;5&547'/.?'+"&5463!2+7>6 %#"&5   &@�~���``@``��~4e	
0
	io@& �jV	
0
	Z9�������r�������&���������@``@�G�ɞ5o
,
sp� &@k^
,
c8~~��`r�������8>KR_32++"&=!+"&=#"&=46;.767666'27&547&#"&'2#"�����@�@���'�Ϋ���'������sg��gs�����ww�@����sg��g����@����@���-ss��ʃl������9���9��������OO���r9���9��FP^l463!2+"&=$'.7>76%#"&=463!2+"&=%#"&54'>%&547.#"254&' &@�L?����CuГP	��v�Y�� &@�;"����������ޥ�5݇�����ޥ���5�`&����_��ڿg��w��BF�@&����J_	s���&��&�����?%x���������%x��JP\h463!2+"&='32++"&=#"&=46;5.7676632%#"&56'327&7&#"2#"� &@�L? ���ߺu�``@``��}
�ຒ�ɞ���������ue��eu�9����ue��e�&����_��"|N�@``@��"��"|a~���l����o����9���9��r9��@�9���;C2+"&5"/".4>327'&4?627!"&=463  �&@Ռ		.	
�N~[���՛[[��u˜N�		.	
����gr�������&�`֌
	.		�O��u՛[[���՛[~N�
	.		��@��r������9A'.'&675#"&=46;5"/&4?62"/32+  ��'��֪�����\
	.		�4�		.	
\���r������|��ݧ���憛��@�\		.	
��
	.		\�@��r�����~9A"/&4?!+"&=##"$7>763546;2!'&4?62  m��		-

���@���ݧ���憛��@&�

-		�@r������m4��

-		����ٮ*�������		-

��r������+"&5&54>2  ����@��[���՛[�r�����������dG�u՛[[���r������  ".4>2������r�[���՛[[���՛�r������5�՛[[���՛[[����$2#!37#546375&#"#3!"&5463�#22#�y��/Dz?s����!#22#�2#��#2S�88�	����2#V#2��L4>32#"&''&5467&5463232>54&#"#"'.K���g��&Rv�gD�
$*2%	+Z hP=DXZ@7^?1
۰��3O+�l��h4���`���M@8'�+c+RI2
�\�ZAhS�Q>B�>?S2Vhui/�����,R0+	ZRkm�z�+>Q2#"'.'&756763232322>4."7 #"'&546��n/9�b�LHG2E"D8_
p�dd���dxO�"2�xx��ê�_�lx�2X	
!+'5>-�pkW[C
�I
I@50�Od���dd��˥�Mhfx�����x^���ә�	�#'+/7!5!!5!4&"2!5!4&"24&"2!!!��� 8P88P�� 8P88P88P88P����������P88P8 ���P88P88P88P8� ������������+N &6 !2#!+"&5!"&=463!46;23!#!"&54>32267632#"_����>�@`

��
�
��

`
�
� L4Dg��y� 6Fe=O���O�U�4L��>����
�
��

`
�
`

��4L�2�y5eud_C(====`L4����3V &6 #"/#"/&54?'&54?6327632#!"&54>32 7632_����>���		�	
	��	
	�		��		�	
	��	
	�		��%%S��y� 6Fe=�J�%��>����	
	�		��		�	
	��	
	�		��		�	
	��%65%S�y5eud_C(zz.!6%$!2!!!46;24&"2!54&#!"�&���&�&@�Ԗ��V�@&&�@��&&�Ԗ�Ԗ@��&���3!!!	!5!'!53!!	#����7I�e�����eI7��CzC�l��@�����@������@�#2#!"&?.54$3264&"!@������մ���pp�p���������((��������p�pp����#+/2#!"&?.54$3264&"!264&"!@������մ���^^�^@����^^�^@���������((��������^�^^�����^�^^�����v(#"'%.54632	"'%	632U�/�@��k0�G��,�zD#[�k#�
/t�g��
F��
����Gz�����	#'#3!)
p�*�xe���0,\8�����T���#/DM�%2<GQ^lw�����
&'&676676&'&7654&'&&546763"#"'3264&7.>&'%'.767&7667&766747665"'.'&767>3>7&'&'47.'.7676767&76767.'$73>?>67673>#6766666&'&6767.'"'276&67&54&&671&'6757>7&"2654&57>&>&'5#%67>76$7&74>=.''&'&'#'#''&'&'&'65.'&6767.'#%&''&'#2%676765&'&'&7&5&'6.7>�&5R4&5S9
W"-J�0(/�r
V"-J�0(.�)#"6&4pOPpp�c�|o}vQ�[�60X�Q��W1V�	
#5X		N"&
.
)
D>q J:102(z/=f��*4!>S5b<U$:I o<G*	,
&"O	X5
#!

��	R N#
C
83J*��R	!(D
#%37	�;$-.�
(,��覦�6ij
�	���"���)9
E�%����!B83
	j9�6/,	:QD')yX#�63V
��b�a	,
Ue��LPA@���*	̳�`Xx*&E
V36��%	B3%	B3XA	
#!.mU"A	
#!.mUB-#2+Jii�i�m-C<I(m��8qF/*)0�S
		
I
E5&+>!%
(!$p8~5..:5I

~��T�
4~9p# !
)& ?()5F	1	
	
� d%{v*�:
 @e
s|D�1d {�:�*dAA|oYk'&��<��tu��ut�&vHC�XXTR�;w��
��71™
Z*&'
1	9?	.

$��Gv5k65P<�?8q=4�a	
SC"��1#<�/6B&!ML	�^;�6k5wF1<P�C	�;$"&462"&46232>.$.�`�aa��sa�``��Z9k����'9؋ӗa-*Gl|M�e_]`F&O������ܽ�sDD!/+�``�aa�``�a1<YK3(
 /8HQelA�Z3t_fQP<343J;T7Q�+?Kgw  $6&$  $&62+"5432+"&=.54  $;26=462;26=4& 4&#!"3!26)����߄��4R4߄��mlL�������r {jK#@#Q�a����^�����@���@���`&��&&�&�������߄��4R4�Ď������LlL�N� �@K5#:rr:#5K���^����a�a��``]��]``����&&�&&	/!3#4&#!"3!265##!"&5463!22�������@K5^B��B^^B@B^5K���� �@���5K�B^^B�B^^B�K	/!2##!"&5463!2#4&#!"3!265�5KK5^B��B^^B@B^���@��K5��5K�B^^B�B^^B�`� �@ 	/!2##!"&5463!2#4&#!"3!265�5KK5^B��B^^B@B^���@��K5��5K�B^^B�B^^B�`� �@ 	/!2##!"&5463!2#4&#!"3!265�5KK5^B��B^^B@B^���@��K5��5K�B^^B�B^^B�`� �@ 	+2##!"&5463!2#4&#!"3!265�5KK5^B��B^^B@B^���@�K5��5K�B^^B�B^^B�`� �@ �{#!&'#"'&547632m*���
�0���((�'(�$0K
��*�*��% 3#!3# '!#53 5#534!#53 6!3@����@@@��pp��@@@����@@pp@��`������� �����	�+/7;A#3!5!!3#!!5!35!355#%53#5!#35#!!!!!!!!����������������������������������������������������������������������
�	#'+/3?CGW#3!5!!35!!3#!!5!#!5!3535!355#%#3%!53#5!#35#!5##5!3!5!3!5	����������������������������������������������������������������������������������������������������������������!"&5463!2!"!�`(88(@(8�`(8�}2�2R �`8(@(88(�`8HR2�2���##6?6%!!!46#!"&5463!2x���� ��8�(�`(�(88(@(8�
���� (8��(`�(8(@(88��	�'ATd+5326+5323##"' %5&465./&76%4&'5>54&'"&#!!26#!"&5463!2�
��

���i�LCly5�)*H�celzzlec0h�b,,b�eIVB9@RB�9�J_�L4�4LL44L44%��2"��4��:I;p!q4b�b3p(P`t`P(�6EC.7B�I6�4LL44LL��	�.>$4&'6#".54$ 4.#!"3!2>#!"&5463!2Zj��b�jj[���wٝ]�>o��Ӱ�ٯ�*�-���oXL4�4LL44L'�)�꽽�)�J)���]��w����L���`��ֺ��۪e���4LL44LL�;4&#!"3!26#!"&5463!2#54&#!";#"&5463!2�
��

@
�^B��B^^B@B^���
��

��B^^B@B^`@

��
M��B^^B@B^^>��

��
�^B@B^^��5=Um	!	!!2#!"&=463!.'!"&=463!>2!2#264&"".54>762".54>762��������?(`��`(?��b|b��?B//B/�]�����]FrdhLhdrF�]�����]FrdhLhdrF@�@��@�(?��@@?(@9GG9@/B//B�aItB!!BtI�Ѷ�!!��ьItB!!BtI�Ѷ�!!��ь�-M32#!"&=46;7&#"&=463!2#>5!!4.'.46�ՠ��`�@`ՠ��`���M�sF�Fs�MM�sFFs�M����ojj�o��@@�jj�@@�<���!(!���!(!�-3?32#!"&=46;7&#"&=463!2+!!64.'#�ՠ��`�@`ՠ��`��	�	Dq�L�L�qD����ojj�o��@@�jj�@@B>=�C�����-3;32#!"&=46;7&#"&=463!2+!!6.'#�ՠ��`�@`ՠ��`��UVU96�g�g�6����ojj�o��@@�jj�@@β����**ɍ�-G32#!"&=46;7&#"&=463!2#>5!!&'.46�ՠ��`�@`ՠ��`���M�sF�Fs�M�k�k�����ojj�o��@@�jj�@@�<���!(!3��3!(!�9I2#!"&=4637>7.'!2#!"&=463��@b":1P4Y,++,Y4P1:"�":1P4Y,++,Y4P1:"b�@@��@7hVX@K-AA-K@XVh77hVX@K-AA-K@XVh7����Aj"#54&#"'54&#"3!26=476=4&#"#54&'&#"#54&'&'2632632#!"&5&=4632>3265K @0.B @0.B#6'&�&
l
@0.B 2'	.B A2TA9B;h" d�
mpP��Tl��L�c�_4.H�K5�]0CB.�S�0CB.�/#��'?&&)$�$)�0CB. }(AB.�z3M�2"61�d�39�L/PpuT(If�c�_�E�`1X"#4&"'&#"3!267654&"#4&"#4&26326#!"&'&5463246326�\B B\B�&@5K�&@�"6LB\B B\B ��sc�i�L}Q�P<m$��3�jN2�c�B.�p.BB.���3K5+"�3,"� �.BB.��.BB.���.�G=�c�i�(+�lOh7/DVj�"�c�=���&5Jb�#"'&=.547!"&46;'.54632!2327%.54&#"327%>%&#"!"3!754?27%>54&#!26=31��?>I��j��jq,J[�j.-t�j�lV��\���$B.R1?@B.��+?2`$�v5K-%��5KK5�.olRIS+6K5�̈$B\B 94E.&�ʀ�15uE&
�Ԗ�Pj��j�dX�U�GJ7!.B
�
P2�.B
�
%2@	�7�K5(B�@KjKj�?+f�UE,�5K~!1��.>F.��F,Q5*H��$b2#!"&=%!"&=463!7!"&'&=4634'&#!">3!!"3!32#!"3!23!26=n$<vpP��Pp���Pp�w�*�Rd�ApP�]��'@�A&
3@��&H-�[(8@
2�EB^&1
=&�&81����PppP��pP w���cOg Pp��c�
4& #.& &,,:8(�%^B &�
.�&&��2t"&'&54'&5467>32>32>32#"#.#"#.#"3!27654&#"547654&#"#654&�Mye
t|]�WS�Sg�SY�\x{
70"1i�92�DU1&=	��	=&0@�c	>&/Btd4!�*"�8K4+"��@H@/'=	t�?�_K�93-�]�
UlgQ���QgsW
�]#�+�i>p&��3�0&�VZ&0B/
���%3B.�"t�o ){+C4I��(
/D0&�p0D��3[_cg"'&#"3!2676=4&"#54&#"#54&#"#4&'2632632632#!"&'&5463246#!#!#�5K�)B4J�&@�#\8P8 @0.B J65K J6k�
cJ/4qG^�\hB�2<m$��3�iG;��     �K5����6L4+"�3p`b�)<8(=0CB.@Z7OK5`:7O��k�EW�^�tm��@Q7/DVi�##j�������������%4Ia�2#!"&5&546325462632"32654&"3267654&76;74&"#.#"2676=#"&'+53264&#!"3</�U�X�dj���jP��ԖEu�!7JG72P
�
B�%
�
B.!7�	@�A�f+?�jKjK@�B(5K,EU�H*5Q,F��.F>.��1!~K5y?��^\��Vl�j�t-.j�[J,qj��j��I7$��?1R.B�+��.B$`2?g�vEo.�5KK5��%-K��6+SIR[��&.E49 B\B$���5K�G#!+"&5!"&=463!2+"&'+"'+"'&5>;2>76;2Y
��
�
��

M	

�.�x	�-�
	N�	�


�	�
�u
��
,
u
�?

L�W���

���#	�	*:J4'&+326+"'#+"&5463!2  $6& $&6$ <!T{�BH4�	�›�&�>UbUI-����uu�,�uu�ڎ������LlL�AX!��J��m����f\�$
6u�����uu�,�K������LlL���-[k{276/&'&#"&5463276?6'.#"!276/&'&#"&5463276?6'.#"  $6&  $&6]�h-%Lb`J%E5
,5R-����h
-%Lb`J%E5
,5R-���'����uu�,�uu��lL�������/hR

dMLcN����hR
dMLcN����1u�����uu�,��������LlL�@��� 	'	7	'7	�����`��`H� �����`�`H� �!`��������`H� � ���`�`�`H���`��'%		7'	7'7	' $&6$ ���X�`��(W�:,�:��X�`��(WL�������LlL�X�`(W��:�B����X�`���(X�������LlL��
��	$%/9ES[�#"&54632$"&4624&"26$4&#"2%#"&462$#"&4632#"32&! 24>  !#"&'.'#"$547.'!6$32�7&'77'&7�7N77N�'q�qq�q�qPOrq��E�st�����ts��st���}�||�}�������uԙ[W��Q���~,>	n������P/RU P酛���n	>,m�����'77'&77N77N6^Orq�qq�qq�q�t��棣棣�(~|��|on[��usј^�~���33������pc8{y%cq����33dqpf��	L 54 "2654"'&'"/&477&'.67>326?><����
x
�������,

(-'s�IVC��VH�r'-(

$0@!BHp9[�%&!@0$u
��
������]\��\]��-$)!IH��V
D��
VHI!)$-#3���6>N"&462."&/.2?2?64/67>&  #!"&5463!2�]�]]�3
$;
&|�v;$
(CS�3�1	=�rM=	�4�TC(G���z�w�@w��w�w���]]�]��($-;,54�0=	�sL	=�45,;�����@w��w�w������(2#"$&546327654&#"	&#"AZ�������\@�/#�%E1/#����#.1E$�!�[A�����懇�@�@\��!�#21E!��6!E13"�|!��	gL&5&'.#4&5!67&'&'5676&'6452>3.'5����A5R��V[t,G'Q4}-��&�<C!l n?D_@Փ>r!�
��G;��>��!g�1�����2sV&2:#;��d=�*'�5E2/..F�D֕71$1>2�F!���&12,��@K�
r��#"&5462>%.#"'&#"#"'>54#".'7654&&5473254&/>7326/632327?&$  $6 $&6$ �!&"2&^	u��_��x��^�h
;J݃HJǭ
q�E
Dm!
M�
G?̯'%o�8
9U�������(F(�ߎ������LlL��&!&!SEm|�[��n{�[<ɪ
"p� C
Di%
(K�HCέp�C
B
m8	
@Kނ
H�F(���������������LlL���"*6%&6$	7&$5%%6'$2"&4}���x����3��n��QH������:dΏ���Xe�8�����z��'	������l�i���=!��7�����S�o�?v�������M '&7>>7'7>''>76.'6'���El:F�gr
*�t6�K3UZ8�3P)3^I%=9	)<�}J���k+C-Wd��	&U���-��TE+]��Qr-�<Q#0
�C+M8	3':$
_Q=+If5[ˮ&&SG�ZoM�k���ܬc�#7&#"327#"'&$&546$;#"'654'632ե›��fKYYKf�¥y�ͩ���䆎�L��1���hv�v��ƚw�wk��n�]��*��]�nlx��D��L�w�����~?T8b��b9SA}����+5?F!3267!#"'#"4767%!2$324&#"6327.'!.#"��۔c�2�8�Ψ����-\���?���@hU0KeFjTl�y�E3��aVs�z�.b��؏��W80��]T��Sts�<�h�O��_u7bBt���SbF/�o��|V]SHކ�J�������34&#!"3!26#!!2#!"&=463!5!"&5463!2
��

@
�^B� `��`� B^^B@B^ �

�@
�@B^�@@�^B�B^^����>3!"&546)2+6'.'.67>76%&��F8$.39_��0DD�40DD0���+*M7{L *="#
U<-M93#�D�@U8v�k�_Y	�[�hD00DD0��0D�ce-JF1BD����N&)@
/1 d��y%F��#"'&'&'&'&763276?6#"/#"/&54?'&763276"&'&'&5#&763567632#"'&7632654'&#"32>54'&#"'.5463!2#!3>7632#"'&'&#"'&767632yq������oq>*432fb������a
$�B?
	>B
BB
AA�.-QP���PR+	42
%<ci���ђ:6&h�HGhkG@n�`��I���Ȍ5
!m��(|.mzy�PQ-.	
	je����	
�����q>@@?pp�gVZE|fb6887a
%RB?
=B
ABBAJvniQP\\PRh!cDS�`gΒ��23�geFGPHX�cCI��_ƍ��5"	
�n�*T.\PQip�
[*81
/
9@:��>t�%6#".'.>%6%&7>'.#*.'&676./&'.54>754'&#"%4>327676=
>���vwd"

�l����"3	/!,+	j2.|��%&
�(N&w���h>8X}x�c2"W<4<��,Z~�fd�aA�`FBIT;hmA<7QC1>[u])		u1�V(�k1S)
-�	0�B2*�%M;W(0S�[T�]I)	A 5%R7<vlR12I]O"��V/,b-8�/_��#3CGk2#!"&546;546;2!546;2%;2654&+";2654&+"!32++"&=#"&=46;546;24LL4��4LL4�^B@B^�^B@B^�@@�@@�����@��@L4�4LL44L`B^^B``B^^B``�� �� ��@@��@���#3W#!"&=463!2!!%4&+";26%4&+";26%#!"&546;546;2!546;232���@�����@@@@�L4��4LL4�^B@B^�^B@B^�4L�@@��� �� ��N�4LL44L`B^^B``B^^B`L��#'7Gk%"/"/&4?'&4?62762!!%4&+";26%4&+";26%#!"&546;546;2!546;232W.	
��
	.		��		.	
��
	.		��	� ����@@@@�L4��4LL4�^B@B^�^B@B^�4L�.		��		.	
��
	.		��		.	
��
��� �� ��N�4LL44L`B^^B``B^^B`L��(8\	"'&4?6262!!%4&+";26%4&+";26%#!"&546;546;2!546;232�

��		.	
��
	.	�`����@@@@�L4��4LL4�^B@B^�^B@B^�4L<�		 
	.		��		.	�:� �� ��N�4LL44L`B^^B``B^^B`L�2632632#!"&5463�&&&&��&&&���&���&��&&�&�#27+"&5  %264&#"26546��>&�&T�,��X�������q&&�1��X��,�LΒw�%��%;#!"&5463!546;2!2!+"&52#!"/&4?63!5!�

�(��&&@&�&(��&�&@&&��(�

�(�

�&&@&&@��&&�&�&�

�����#''%#"'&54676%6%%�������
�hh �@�` ���!�� ���!� ��
��
��
�
������
�#52#"&5476!2#"&5476!2#"'&546
� 
��
� 
���
�
�@�
�
�@�
��
�@

�
� 84&"2$4&"2$4&"2#"'&'&7>7.54$ �KjKKj�KjKKj�KjKKj��d�ne���4"%!������KjKKjKKjKKjKKjKKjK.���٫�8
!%00C'Z���'���.W"&462"&462"&462 6?32$6&#"'#"&'5&6&>7>7&54>$ �KjKKj�KjKKj�KjKKj�h��я�W.�{+9E=�c��Q�d�FK��1A
0)����LlL��jKKjKKjKKjKKjKKjK���p�J2`[Q?l&�����٫�C58.H(Y���ee���	�

			���Y'����w��(�����O��'��R���@$#"&#"'>7676327676#"�
�����b,XHUmM�.�U_t,7A3ge
z9@xS���a�Q�BLb�(�	����V���U�����
!!!�=�����=���w)��������AU!!77'7'#'#274.#"#32!5'.>537#"76=4>5'.465!��KkkK_5 5�� �#BH1��`L

I���&�v6��SF���!Sr99rS!``� /7K%s}H���XV
��P��V	e��		V�d/9Q[ $547.546326%>>32"&5%632264&#"64'&""&'&"2>&2654&#";2���P���3>tSU<�)tqH+>XX|W��h,�:USt��W|XX>=X*
)���)
+�^X^�|WX=>X�:_.2������//a:Ru?�
	
Q%-W|XW>J�(	�=u��>XX|WX�`

*((*


+2		2�X>=XW|E��03>$32!>7'&'&7!6./EU����noh��i����I\�������0<{ >ORD��ƚ�~�˕V�ƻ��o�R C3��7J6I`��Tb<�^M~M8O����	�	
5!#!"&!5!!52!5463	^B�@B^���`B^�^B `��B^^"�����^B��B^��0;%'#".54>327&$#"32$	!"$&6$3 ##320�J�����U��n��L�n��ʡ���~~�&��q�@�t�K�����L��}�'`� -
-�ox����nǑUyl}��~������~�F����ڎ�LlL��t�`(88( ��	7!'	!���\W�������\���d;����tZ�`_��O��;���}54+";2%54+";2!4&"!4;234;2354;2354>3&546263232632#"&#"26354;2354;2354;2�````��p�p��`�`�`� !,! -&M<FI(2�`�`�`�����@PppP���pppppp�#  #
�
�pppp��p	�j#"'&=!;5463!2#!"&=#".'.#!#"&463232>7>;>32#"&'#"!546���	��%. `@��` :,.',-���Xj��jX�h-,'.,: kb>PppP>bk .%Z �&�
�:k%$> $`��`6&L')59I"Tl�ԖlT"I95)'L&69Gp�pG9$ >$%k:��!+32&#!332 $&6$ ~O8��8���O�����������LlL�>pN
�����
i������LlL����	'':Ma4&'#"'.7654.#""'&#"3!267#!"&54676$32#"'.76'&>$#"'.7654'&676mD5)
z�{��6lP,@Kij��jOo�Ɏ���ȕ>>��[t��a)GG4?a�)
ll
>�;_-/
9GH{�z�yN@,K�ԕoN��繁������y��!
?hh>$
�D��"
>��â?$��	n"&5462'#".54>22654.'&'.54>32#"#*.5./"�~��~�s�!��m�{b6#	-SjR,l'(s�-6^]It�g))[��zxȁZ&+6,4$.X%%Dc*
&D~WL}]I0"

YYZ��vJ@N*CVTR3/A3$#/;'"/fR-,&2-"
7Zr�^N��a94Rji3.I+

&6W6>N%&60;96@7F6I3���+4&#!"3!26%4&#!"3!26 $$ ��������^����a�a`@��@����^����a�a�����'7  $ >. %"&546;2#!"&546;2#/�a����^�����(�����������������^����a�a����(������N@��@�����4&#!"3!26 $$ @��@����^����a�a`@����^����a�a�����'  $ >. 7"&5463!2#/�a����^�����(��������n@����^����a�a����(������N@���%=%#!"'&7!>3!26=!26=!2%"&54&""&546 �#��#]V�TV$KjK�KjK$��&4&�Ԗ&4&�>��9G��!�5KK5��5KK5�!��&&j��j�&&����#/;Im2+#!"&'#"&463>'.3%4&"26%4&"26%6.326#>;463!232#.+#!"&5#"�5KK5sH.�.Hs5KK5e# )4# %�&4&&4&�&4&&4&` #4) #%�~]�e�Z�&�&�Z�e�]E-�&��&�-EKjK�j.<<.�KjK��)�#)�`"@�&&�`&&�&&�`&&�)#�`)"�d�Xo&&oX�G�,8&&8!����O##!!2#!+"'&7#+"'&7!"'&?63!!"'&?63!6;236;2!2�@�@�8��@7

8��Q�
	N�Q�
	N��
	8G@��

8GQ�
	N�Q�
	N7
	�������8��8��H��H��k��%		".>2I�������2�0�]@��]��@o�����o@@o�����o㔕����a�22���]����]�p�^���|11|�9�9�|11|�(��%7'7'	'	7T���� d���lt��l)q��n�������luul�������)1$4&"24&"2 &6 +"&5476;2 &6 LhLLh�LLhLLhL����>�
�� �&
  �&�`����>�hLLhLLhLLhL�����>����&�&�����>��G��
	.7)1!62	1!62h��e�������2�20e���2�2>�	v
+4�	[��d����+
���d� �135#5&'72!5!#"&'"'#"$547&54$ ���Eh���`X����(����cY���z�:L:�z���Yc��������\$_K`Pa}��f��iXXiޝf���a���	���(+.>#5#5!5!5!54&+'#"3!267!7!#!"&5463!2����U�`��`' ����� �����j��j�V>�(>VV>�>Vq����������������(^����(>VV>�>VV�=&'&'&'&76'&'&.' #.�h8��"$Y
''>eX5,	,Pts�K�25M�RLqS;:.K'�5�R

Ch���h�����R�t(+e�^TT���u B"$:2�~<�����2�Hp����wTT�� V�/7GWg. %&32?673327>/.'676$4&"2 $&6$   $6& $&6$ d-����-�m	
	,6*6,	
	m���KjKKj�o������oo���K����zz�8�zz�Ȏ������LlL�U4>>4-.��YG0
)�xx�)
0GYޞ.�jKKjKq���oo��oo�lz�����zz�8�0������LlL��D��/7H#"'.7'654&#"'67'.6?>%"&46227#".547|D,=),9#�7��[͑�f�x���!X: �D�$+�s)�hh�i��jZ������t�<��F/��*8C,�q؜�e���\�r,W�BX���/C2��h�hh���=�t������Xm�����>NZ+"&=46;2+"&=4>7>54&#"#"/.7632  >. $$ p��=+& �35,W48'3	l
z����ff���ff�����^����a�aP���2P: D#;$#
$*;?R
��Cf���ff�����^����a�a��'�Y	>O`"&5462&'.'.76.5632.'#&'.'&6?65��\\�[�<C��z�C
25�U#
.�ZK ��m+[$/#>(	|�	r���[A@[[@A�#2#�
����7�*
<Y���$
+}"(��
�q�87] F 	_��1)
��	�	#1Ke34&+326+"&=!#!"&763!2#!"&5463!2#>?4.'3#>?4.'3#>?4.'3��Xe`64[l�����7
��
,	L;�����=+3&98&+)>�>+3&98&+)>�=+3&88&+)>	�Wj�|r�>Q$��~���d$kaw+-wi[[\�;/xgY$kaw+-wi[[\�;/xgY$kaw+-wi[[\�;/xgY���J\m�4.'.'&#"#"'.'&47>7632327>7>54&'&#"327>"&47654'&462"'&476'&462"'&47>&'&462i$		$^"

%%

"^$		$W "@9O?1&&18?t@" W�&%%&4KK�6pp&4���6ZaaZ&4mttm�^x	-���-	x^=/U7Ck���kz'[$=�&5%54'4&K�K�4r<r4&��X��4[��[4&m����m��'/7?GOW_gow����"264$"264"264"264$"264"264$"264"264"&462"&462"&462"&462"&462"&462"&462"&462"&462"&462"&462"&462�^^�^��^^�^^�^^�^��^^�^��^^�^���^^�^��^^�^^�^^�^� p�pp�pp�pp��pp�pp�pp�pp��pp�pp�pp�pp��pp�pp�pp�pp��pp�pp�pp�pp��pp�pp�pp�pp�`^�^^�^^�^^�^^�^^��^^�^^�^^�^^�^^�^^�^^�^^�^^�^^���pp�pp�pp�p��pp�pp�pp�p��pp�p���pp�p��pp�p���pp�p��pp�pp�pp�p��pp�pp�pp�p	��LTi{�"&4626"&462$"&462#"&4632654>7>54 "&54>2"&462%"&54&#""&546 %#"&'&'.7>#"'&'.7>�&4&&4�&4&&4SZ��&4&&4�4$#&�&&j�3$"('$������&4&[���՛[��&4&&4F&4&�]\�&4&�$��
	!D�4�%	,\�4�4&&4&�4&&4&-�Z�4&&4&;cX/)#&>B)��&4&�j9aU0'.4a7����&&u՛[[���4&&4&@&&]��]&&��Ώ0
�u4��0
)�4���#g�&'.#"32676%4/&#"326'&#"2632#2+&'%#"'&6?676676632%#"'&6767#"&'&6767#"'.7>327"#"&'&6763"'.7>;7632;>%5K$
"0%>s$
"0%>;;>%5K�VL#>H30
\�($$(�\���(�є�yO2F/{�(?0(TK.5sg$��є�y#-F/{�$70(TK.5sg$L#>H30
\�($$(�\#�(@5"'K58!'"5�8!'"55"'K#dS$K		K$Sdx#@1
w�d>N;ET0((?
-
2K|��1
w�����d#N;ET0$(?
-
2K$#dS$K		K$Sdx�DN\2654& 265462"2654 #"32654>7>54."/&47&'?62 &4&���&4&���h�՛[&4&r$'("$3�j&&��&#$4[����"�@��GB�[�
"�&&��Β&&]���[��u&&����7a4.'0Ua9j�&4&�)B>&#)/Xc;u՛����"�"
�G�i[����Xh#"&54676324&'&#"'>54#"32#"54>54'.#"32>7>767632326#!"&5463!2b
)
:4FD�N

[�1�,^�J��K-*E#9gWR�Yvm0O	��w�@w��w�w��C2�2c@X�&!�9{M�A���_��"S4b// DR"Xlj�PY<	�@w��w�w��%���e4.#"32>7676#'.#"#"&54>3232>754&*#"&54>763 >32�
''il$E/
@�P@��
^��`��'W6&�!.. ! -P5+


�E{�n46vLe�Vz�:���,SN/
M5M[��
	]$�[��^��5�iC'2H&!(?]v`*	��l�	��b��$9>
���=R�2
#"&5467%!"&7>3-.7>;%.7>322326/.76/.'&6766/&/&#"&676	&676&6766/&672? �=1�(H/ ��	'96&�@)9<'���)29%
�&06#���#��$� J� �07j)�5@�"*3%�"!M
��%#K�"%N�e8)'8_�(9�.<�c +8 8(%6 <)'4@@)#-<^
?%$-`%.
}Q!&�}%&N�-l���IJ�;6>/�=*�%8!Q ���#P"�\Q#N&�a��)<9�bR]mp%"'.'&54>76%&54763263 #"/7#"'#"&/%$%322654&#"%'OV�9
�nt
|\d
ϓ[��nt
|@�D:)��	
;9�8'+|�j�," �41����CH^�nVz(�~R	�9�\'	�r�

@����L��@�
	@�w4�6�HI(+�C
,��55,��
f[op@�\j�;(zV~����i/5O#"'&54>32&#" 654'67'"'>54''&'"'6767&546767>7���蒓��`V BM���R� B9)̟�!SH-77I�Xm�SM�H*�k#".o;^J q�ן���ד��>@�����YM
$bK���d ��ү[E"����;���Kx%^�6;%T,U:i�m=Mk���).DT4'"&5463267&#" 6;64'.'4'>732676%#!"&5463!2),�蛜s5-<A���4ϲ
2W9
�&P:\�3)SEPJ��D4:3NI�w�@w��w�w��NE	2@u��us�+,�����/?x�sa�tmP�'�)fHVEA(%dA4w&4J5*�@w��w�w�����O[4'.'&54>54&#"#"'654'.#"#"&#"3263232>3232>76 $$ �Cf'/'%($�U�L
(
#'/'@��3#@,G)+H+@#3
����^����a�a�X@_O#NW�#O_�.*	##(��^����a�a����q�[632632#"&#"#".'&#"#".'&54767>7654.54632327&547>P��9	B6?K?%�O4�T% >6>Z64Y=6>%S�4N�$?L?4B	@���{:y/�$ ,'R�!F!8%
#)(()#%:!F �Q'+%�0z:�z���O_4'.'&54>54&#"#"'654'.#"#"&#"3263232>3232>76#!"&5463!2Cf'.'%($�V�M
)
#'.'@��
3
#A,G)+H+A#
4
��w�@w��w�w��XA?4N$NW�&M&L�/*
##	+�@w��w�w����	O$>?>762'&#"./454327327>7>	EpB5
3FAP/h����\�/NG�S�L�	� ���R�P*��m�95F84f&3Ga4B|wB.\FI*/�.?&,��5~K %
&��Y."7n<	"-I.�M`{�ARwJ!�FX^dj''''"'7&'7&'7&'7&547'67'67'67'63277774$#"32$			*��'ֱ,?�g=OO&L&NJBg�;1��'����'ֱ.=�gCIM
$'&&NJBg�=.��%�����w؝\\��w�
�I�o�o��<�<���-NIDg�=/��%����(ײ+A�hEHO*"#*OICh�=/��'����(ֲ/=�h>ON.��]��xwڝ]��������7��e��[���@�����)6!!"3#"&546%3567654'3!67!4&'7S��gn�y]K-�����#75LSl>�9���V��%�cPe}&H�n��_�HȌ����=UoLQ1!��4564���7U�C"�
�!-9[nx��"&46254&"326754&"326754&"26754&"26#".547632632626326'4#"#"54732764&"264.#"327632>#"'"'#"'#"&5#"'67&'327&'&54>3267>7>7>32632632T"8""8�)<())�(<)))�)<))<)�)<))<)T�د{ՐRh�x=8 78 n 81
p��H_6�S��oc
�F@b@?d?uK�bM�70[f5Y$35KUC<:��[;+8 n 87 8/8Zlv]64qE 'YK�0-AlB;
W��#;WS9
&�(#-7Z�://:/�Tr++r,,r++r,,r++r,,r++r,,ʠ�g��xXV�ע��e9222222^�K�Vv���F0�2OO23OO��`�lF;�mhj84D�ro��B@�r+@222222C0DP`.�r8h9��~T4.&o�@9��1P���%14'!3#"&46327&#"326%35#5##33 $$ ����}Pc��c]<hl���ࠥ�Ymmnnnn���^����a�aw!�LY�Ə;ed����wnnnnnv�^����a�a��%�'#"$#"#.5462632327>321��I��U�Π?L���L?��cc�4MX�&��04;0��XpD[��[DpD,)&&�Q	9V\�26&".'&'&6?.#"#26327677>'32>&3#'&+"?626&"#!'.'!"&5463!>;26;2!2�P  P 	
92#.}S�P9:�:%L\B�� )spN/9oJ5 
!+D�`]�Bg�Y9�+�,�9%
Pk4P  P &�NnF!_7*}B<�{o0��&&�B;*<@$ucRRc�#@16#37c&�@@@
J"@*4�^`E�D�B�����o/8927
*@O�LC�!T!32�3X$�BJ@@@��&AS
0C59"'D/&�&D488$5A&�%O#!"&547>7>2$7>/.".'&'&2>^B�@B^>FFz�n_0P:P2\n�zFF>��R&�p^1P:P1^��&R
P2NMJMQ0Rr�.B^^B�	7:5]yPH!%%"FPy]5:7	���=4�QH!%%!H�t4=�<"-/ ?�1Pp+".'.'.?>;2>7$76&'&%.+"3!26#!"&54767>;2�'
+�~'*OJ%%JN,&x�'%^�M,EE,M7�ZE[��P*FF*P��:5
�
�^B�@B^){�$.MK%%KM.$+��X)o3"�a  22!]�4	I�>"">�,�&�S8J�B##B��12�`
��`B^^B�8&ra#11#$��R&��"&.2v%/%''%/%7%7'%7'/#&5'&&?&'&?&'&7%27674?6J�"�����0�<=���_gNU�?D��f���u�Y����G�b���7=^H^�`	�=v~yT������3����G���D��P�O	4F��ѭ����q������i_w\ހ�!1u�S���%V_-d�
���1=U{J8n~�r����'U4.#".'"3!264&"26+#!"&5463!232+32+32�0P373/./373P0T=@=T��֙�֙|`^B�@B^^B�B^`````*9deG-!

!-Ged9Iaa�l��lk���O��B^^B�B^^B�������	+Yi"&54622#!"&54>;2>+32+32+#!"&5463!2324&#!"3!26�֙�֙0.I/ OB��BO	-Q52-)&)-2�
``

``

`^B�@B^^B�B^`
�
�@

�
|k��kl����"=IYL)CggC0[jM4				
�
�
�
�
�B^^B�B^^B�
�@�

�@
���!1AQu4.#".'"3!24&"254&#!"3!2654&#!"3!2654&#!"3!26#!54&+"!54&+"!"&5463!2)P90,***,09P)J66S�����"��@��8��@^B��@�@��B^^B�B^U�kc9		9ck�U?�������@@88@@N�@B^````^B�B^^���!1AQu�#!"&4>32>72"&462#!"&=463!25#!"&=463!25#!"&=463!24&#!"3!546;2!546;2!26#!"&5463!2J6�6J)P90,***,09P)������"��@��8��@�
�@

`@@`
�^B�@B^^B�B^ՀUU�kc9		9c�������`@@�88�@@�2�

�@
````�@B^^B�B^^�(%.'"&' $&  #"$&6$ ��wC�ιCw�jJ~J�����>��������LlL�ś�JSSJ͛����>����6������LlL���$,  $&6654&$ 3 72&&  �lL������m�z�����z�B�l������>�������KlL�G���zz���G���>�����'7#!"&54>7&54>2  62654' '3�/U]B,ȍ����,B]U/OQ��н�Q������>�+X}��������}X�0b�Ӄ��ۚ�Ӆb0}�h��QQ��h�����>��f����f��#=#!"&4>3272"&462!3!26#!"&5463!;26=!2J6�6J)Q8P�P8Q)��������
�
�^B�@B^^B`�`B^V�VV�ld9KK9d��������`��
�@B^^B�B^``^���+;K[eu4.#"'"3!264&"254&#!"3!2654&#!"3!26%54&+";2654&#!"3!26!54&#!"!#!"&5463!2�"D/@�@/D"?,�,?�p�pp�p�@�����@����@����@�^B�@B^^B�B^D6]W2@@2W]67MM��pp�p��@@@@@@@@n`�@B^^B�B^^���+;K[eu#!"&54>3272"&462#!"&=463!2%#!"&=463!2+"&=46;25#!"&=463!2!3!26#!"&5463!2�?,�V,?"D/@�@/D"�p�pp�p�@�����@����@���
�
�^B�@B^^B�B^D7MM76]W2@@2W]֠pp�p��@@�@@@@�@@��`��
�@B^^B�B^^��A#"327.#"'63263#".'#"$&546$32326�������J9"65I).!1i���CC�u
+I�\Gw\B!al���݇���y�ǙV��/]:=B�>9�����+<F+a[le���Pn[A&JR7t�)��+�tH�������kFIK�e	� .��#"'&'>32%#!"&5463!2#"&54>54'&#"#"54654'.#"#"'.54>54'&'&543232654&432#"&54>764&'&'.54632� ?c��'p& ?b1w{2V	?#��&#9&�CY'&.&#+B

: &65&*2w�1GF1)2<)<'

(
BH=ӊ:NT :O	�)4:i F~b`e!}�U3i?fR����UX|'&'&I�c&Q
	*2U.L6*/
L:90%>..>%b>++�z7ymlw45)0	33J@0!!TFL����� P]=GS�-��kwm	!����*�(%6&692? $&6$ ��	' ����al�@l�������LlL���,&��EC
���h�$�������LlL���
/37;%"&546734&'4&" 67 54746 #5#5#5�p�pF:�:F�D<p�p<D�
����������
���������PppP<d��ud<M�-PppP�-�M����������Dž����9���������
/37;%"&546734&'4&" 67 54746 #5#5#5�p�pF:�:F�D<p�p<D�
����������
���������PppP<d��ud<M�-PppP�-�M����������Dž����9���������
/37;%"&546734&'4&" 67 54746 #5#5#5�p�pF:�:F�D<p�p<D�
����������
���������PppP<d��ud<M�-PppP�-�M����������Dž����9���������
/37;%"&5467534&'4&" 67 54746 #5#5#5�p�pF:�:F�D<p�p<D�
����������
���������PppP<d��d<M�-PppP�-�M����������Dž����9���������	+/37%"&54624&'4&" 67 54746 #5#5#5�p�pp�p�D<p�p<D�
����������
���������PppPOqqOM�-PppP�-�M����������Dž����9����������&.6>FNV^fnv~����"/&4?.7&#"!4>3267622"&4"&46262"&42"&4462"$2"&42"&4"&46262"&4"&46262"&42"&4$2"&42"&42"&4�

��

R

,H8Jfj��Q��hj�G^�R,

!4&&4&Z4&&4&�4&&4&��4&&4&&4&&44&&4&��4&&4&Z4&&4&�4&&4&��4&&4&�4&&4&��4&&4&&4&&4&Z4&&4&Z4&&4&

��

R

,[�cG�j�h��QRJ'A,

��&4&&4Z&4&&4Z&4&&4Z&4&&444&&4&�&4&&4Z&4&&4Z&4&&4Z&4&&4�&4&&4Z&4&&4Z&4&&4&&4&&4Z&4&&4Z&4&&4�%-5=EM}���������+"&=#!"'+"&=&="&4626"&462&"&462"&462&"&462&"&462#!"&=46;4632676/&?.7&#"!2"&462&"&462&"&462"&462&"&462&"&462"&462&"&462"&462��@?A�A?
@
�@R.�..R�@`�jlL.h)*��*$	%35K���..�..�.����u�vn�u���....��@@�j�N *��*.t2#K5���..R..R.��
@Hq '&'&54 &7676767654$'.766$76"&462&'&'&7>54.'.7>76�����������ȵ|�_ğ��yv���/ۃ�⃺����k]
:Bu�q��
CA
_k�ނ���XVo�bZZb�nW��|V	0 	Q2��-�
l��}���O		/	:�1���z	
q��%������z�G
4(

6�Ro�aą\�<

)4	J�}�������%!!#!"&5463!2�^B�@B^^B�B^�`�@B^^B�B^^���%#!"&=463!2^B�@B^^B�B^�B^^B�B^^�&))!32#!#!"&5463!463!2��`B^^B��^B�@B^^B`^B�B^�^B�@B^��B^^B�B^`B^^���#3%764/764/&"'&"2?2#!"&5463!2��

��

�

��

�

��

�

��
s^B�@B^^B�B^ג

��

�

��

�

��

�

��
�@B^^B�B^^���#'7"/"/&4?'&4?62762!!%#!"&5463!2�

��

�

��

�

��

�

��
�
�^B�@B^^B�B^��

��

�

��

�

��

�

��
��`�@B^^B�B^^�	! $&6$ .2�r��`�������LlL�f4��������LlL���#.C��&>"'&4762"/&4?62'"'&4762%'.>6.'.>6'>/>76&'&.'&7&'">?4'.677>7.>37654'&'67>776 $&6$ (4�Z�##
&##
&y�"�6&.JM@&� "(XE*$+8
jT<l$3-V<
2'.


-1
%#e"!Z�
+*)H	 8
(j

	#*
-ƷVv/kh?'��������MlM�$($�R#

&
"
#'#vZ@+&MbV$
�
G7
--)

R2T�
313dJ6@8lr2_�5m/."�G:=	)%5f0gt*2)?;CB66&, �	`48]USy������LlL���G6?>?3#'.'&!3!2>?3.'#!57>7'./5!27#'.#!"g�%%D-!gg<6W��WZe#1=/2*]Y3��-,����C1/Dx���] VF��I�q-H�����D2��NK'>*�%�R=f
07���=.
fD�]\|yu���,0>Seu#2#"'&5<>323#3#&'#334'."#"+236'&54.#"5#37326#!"&5463!2�		<	��zz�j��k-L+� )[$�8=".un/2 �^B�@B^^B�B^�5cy	
�
��(�ݔI�(8��?C�(3�>�� #"��($=�@B^^B�B^^0�K�S�&'.'&'./674&$#">&>?>'76'# "&#./.'7676767>76$w
.~ku�BR�]� T%z+",�|�ޟ���j<���)(!(	~ˣzF8"{���%%#5����)��}''�x��JF��0"H[$%��EJ#%
.Gk29(B13"?�@S)�5" �#9����dm�W"��;L�65R�A0@T.���$�}i`:f3A%%
BM<$q�:)BD	aa%`�]A&c|	�M��s!
Z
2}i[F&���**
< ��ʣsc"J<&Ns�F%���0@Wm6&'.6$.7>7$76".4>2.,&>6'"'&7>=GV:�e#:$?+%

q4����g
&3h�T`Zt�Q��м�QQ��м�pA������P1L������K!:<��}҈`d��l��b�,�9'


%%($!
���a3���)W)x
�������
о�QQ��о�QQ���cQ����ǡ-�җe)U�s2����XD\���ϼ�Yd����/?O_o���#"=#"=4;543#"=#"=4;543#"=#"=4;543#"=#"=4;543#"=#"=4;543%#!"&5463!2++532325++532325++532325++532325++53232�p00pp00pp00pp00pp00�8(��(88(@(80pp00pp00pp00pp00pp0� � � � � ��@(88(�(88� �� �� �� �� �/�Q�/&'%&/"&=.6?&?&'&6?'.>-#".6?'.>'&6'.>54627>%>76#"'%
%6��

2�7
2G
f���!)p&4&p)!��f
G2
7�2

��	*6���	"��
4�7
2G
f�!)p&4&p)!�f
G2
7�2

��"	���6*	�!k
3

j�&3
%,����*��&&ր*�9���%
3&�j

3
k!./!>��>$,*!k
3.j�&3
%�Ԝ9�*��&&ր*�ǜ,%
3&�j

3
k!*,$>��>!/.�&6.'&$	&76$76$�P��utۥiP��u��G��xy
��Զ�[xy
�-���_v١eN��uv١e	��=��u�ʦ�����[t7��8�X�
&6##'7-'%'&$  $6 $&6$ ��3��1�N��E0�����g��R�=|�����||�">"��������LlL����^��v!1f2i��Ђwg�fZQ�Q^>"�||�����||�w������LlL��&�Z�Xblw��������.'&>'&'&".'.'&&'&'&7>767>67>7626&'&>&'&>'.7>.676'&'&'&'.67.>7>6&'&676&'&676.676&'&>&'&676'.>6/4-LJg-$	6)j2%+QF)�b3FSP21DK2�AW")")�$??8A&A�E5lZm��=g�G2Sw*&>$5jD ���GH�yX/4F �r	1
	1�"�"!�l=6>��	6
,5./��'e



.*�|�Ed!
u&�&%&��	&��5d	
���))66@�C&8B@q��L?P^7	G-hI[q��:<�rS	U~97A_�IR`gp1	1	�;"("j?>"�T�6
,6 
&/`���LwQ'�	
��A	^	�	�	"�		$&	_	��	y		�	*�	<Copyright Dave Gandy 2016. All rights reserved.Copyright Dave Gandy 2016. All rights reserved.FontAwesomeFontAwesomeRegularRegularFONTLAB:OTFEXPORTFONTLAB:OTFEXPORTFontAwesomeFontAwesomeVersion 4.7.0 2016Version 4.7.0 2016FontAwesomeFontAwesomePlease refer to the Copyright section for the font trademark attribution notices.Please refer to the Copyright section for the font trademark attribution notices.Fort AwesomeFort AwesomeDave GandyDave Gandyhttp://fontawesome.iohttp://fontawesome.iohttp://fontawesome.io/license/http://fontawesome.io/license/����������	

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab�
cdefghijklmnopqrstuvwxyz{|}~��������������������������������������������������������������������������������������������������������������������������������"	

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRS�TUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~��������������������������������������������������������������������������������������������������������������������������������	

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~���������������������������������������������������glassmusicsearchenvelopeheartstar
star_emptyuserfilmth_largethth_listokremovezoom_inzoom_outoffsignalcogtrashhomefile_alttimeroaddownload_altdownloaduploadinboxplay_circlerepeatrefreshlist_altlockflag
headphones
volume_offvolume_down	volume_upqrcodebarcodetagtagsbookbookmarkprintcamerafontbolditalictext_height
text_width
align_leftalign_centeralign_right
align_justifylistindent_leftindent_rightfacetime_videopicturepencil
map_markeradjusttinteditsharecheckmove
step_backward
fast_backwardbackwardplaypausestopforwardfast_forwardstep_forwardejectchevron_left
chevron_right	plus_sign
minus_signremove_signok_sign
question_sign	info_sign
screenshot
remove_circle	ok_circle
ban_circle
arrow_leftarrow_rightarrow_up
arrow_down	share_altresize_fullresize_smallexclamation_signgiftleaffireeye_open	eye_closewarning_signplanecalendarrandomcommentmagnet
chevron_upchevron_downretweet
shopping_cartfolder_closefolder_openresize_verticalresize_horizontal	bar_charttwitter_sign
facebook_signcamera_retrokeycogscomments
thumbs_up_altthumbs_down_alt	star_halfheart_emptysignout
linkedin_signpushpin
external_linksignintrophygithub_sign
upload_altlemonphonecheck_emptybookmark_empty
phone_signtwitterfacebookgithubunlockcredit_cardrsshddbullhornbellcertificate
hand_right	hand_lefthand_up	hand_downcircle_arrow_leftcircle_arrow_rightcircle_arrow_upcircle_arrow_downglobewrenchtasksfilter	briefcase
fullscreengrouplinkcloudbeakercutcopy
paper_clipsave
sign_blankreorderulol
strikethrough	underlinetablemagictruck	pinterestpinterest_signgoogle_plus_signgoogle_plusmoney
caret_downcaret_up
caret_leftcaret_rightcolumnssort	sort_downsort_upenvelope_altlinkedinundolegal	dashboardcomment_altcomments_altboltsitemapumbrellapaste
light_bulbexchangecloud_downloadcloud_uploaduser_mdstethoscopesuitcasebell_altcoffeefood
file_text_altbuildinghospital	ambulancemedkitfighter_jetbeerh_signf0fedouble_angle_leftdouble_angle_rightdouble_angle_updouble_angle_down
angle_leftangle_rightangle_up
angle_downdesktoplaptoptabletmobile_phonecircle_blank
quote_leftquote_rightspinnercirclereply
github_altfolder_close_altfolder_open_alt
expand_altcollapse_altsmilefrownmehgamepadkeyboardflag_altflag_checkeredterminalcode	reply_allstar_half_emptylocation_arrowcrop	code_forkunlink_279exclamationsuperscript	subscript_283puzzle_piece
microphonemicrophone_offshieldcalendar_emptyfire_extinguisherrocketmaxcdnchevron_sign_leftchevron_sign_rightchevron_sign_upchevron_sign_downhtml5css3anchor
unlock_altbullseyeellipsis_horizontalellipsis_vertical_303	play_signticketminus_sign_altcheck_minuslevel_up
level_down
check_sign	edit_sign_312
share_signcompasscollapsecollapse_top_317eurgbpusdinrjpyrubkrwbtcfile	file_textsort_by_alphabet_329sort_by_attributessort_by_attributes_alt
sort_by_ordersort_by_order_alt_334_335youtube_signyoutubexing	xing_signyoutube_playdropbox
stackexchange	instagramflickradnf171bitbucket_signtumblrtumblr_signlong_arrow_down
long_arrow_uplong_arrow_leftlong_arrow_rightwindowsandroidlinuxdribbleskype
foursquaretrellofemalemalegittipsun_366archivebugvkweiborenren_372stack_exchange_374arrow_circle_alt_left_376dot_circle_alt_378vimeo_square_380
plus_square_o_382_383_384_385_386_387_388_389uniF1A0f1a1_392_393f1a4_395_396_397_398_399_400f1ab_402_403_404uniF1B1_406_407_408_409_410_411_412_413_414_415_416_417_418_419uniF1C0uniF1C1_422_423_424_425_426_427_428_429_430_431_432_433_434uniF1D0uniF1D1uniF1D2_438_439uniF1D5uniF1D6uniF1D7_443_444_445_446_447_448_449uniF1E0_451_452_453_454_455_456_457_458_459_460_461_462_463_464uniF1F0_466_467f1f3_469_470_471_472_473_474_475_476f1fc_478_479_480_481_482_483_484_485_486_487_488_489_490_491_492_493_494f210_496f212_498_499_500_501_502_503_504_505_506_507_508_509venus_511_512_513_514_515_516_517_518_519_520_521_522_523_524_525_526_527_528_529_530_531_532_533_534_535_536_537_538_539_540_541_542_543_544_545_546_547_548_549_550_551_552_553_554_555_556_557_558_559_560_561_562_563_564_565_566_567_568_569f260f261_572f263_574_575_576_577_578_579_580_581_582_583_584_585_586_587_588_589_590_591_592_593_594_595_596_597_598f27euniF280uniF281_602_603_604uniF285uniF286_607_608_609_610_611_612_613_614_615_616_617_618_619_620_621_622_623_624_625_626_627_628_629uniF2A0uniF2A1uniF2A2uniF2A3uniF2A4uniF2A5uniF2A6uniF2A7uniF2A8uniF2A9uniF2AAuniF2ABuniF2ACuniF2ADuniF2AEuniF2B0uniF2B1uniF2B2uniF2B3uniF2B4uniF2B5uniF2B6uniF2B7uniF2B8uniF2B9uniF2BAuniF2BBuniF2BCuniF2BDuniF2BEuniF2C0uniF2C1uniF2C2uniF2C3uniF2C4uniF2C5uniF2C6uniF2C7uniF2C8uniF2C9uniF2CAuniF2CBuniF2CCuniF2CDuniF2CEuniF2D0uniF2D1uniF2D2uniF2D3uniF2D4uniF2D5uniF2D6uniF2D7uniF2D8uniF2D9uniF2DAuniF2DBuniF2DCuniF2DDuniF2DEuniF2E0uniF2E1uniF2E2uniF2E3uniF2E4uniF2E5uniF2E6uniF2E7_698uniF2E9uniF2EAuniF2EBuniF2ECuniF2EDuniF2EE����=���O<0�1h�libs/better-framework/assets/fonts/bs-icons.woff000064400000032274151214002610016010 0ustar00wOFFOTTO4�MPCFF 0�G'=�Z�FFTM1�z�.GDEF1� xOS/22G`��
�cmap2d��u�"head3+6�bMhhea3D$0�hmtx3`d���maxp3�KPname3��ȩ��post4� x��{	xW���qu_� ��̖t'02�0d'�$B�HY�*˶,�-�"�����SKW�ޭ�Ԓl�rl'��%������	[ ��Y���}�y�έ���}o��ץ�u�s�=�,��u��[����r�}Kp�Ѐwp����V���nY\�����/p����k�����`%q�˕�
s�y7��¾�?����ya�~n�]}_�d��'}�뻨��K�.뻢�ƾ[�����{����7�����r}B����k�-�=�H߱�����{��{}?�E�����w��u��=�]��.w���E׽�M���1פ+�*�W��r͹��v�p=�z�]�]?w���]ˮ�Xu������U���z���6n�CC��``k`h˖-#��C���`p�PhGx������!8�wo�nܱy�����nl7����ͻ�a��6 ��<42�ch�h(�k�H��/��5�k�` 8�ߵkpw(8���C������wM��
nAj[F6c�@d|����n	c/#��2�7�y�րh붡��+��+G�[F��;[餂���!�]t��}�֡�X8蔮ۼk�?�.�.���Hvo�a��ԕ+��6���:Xɹz%u�J�ڕ�'��������������D������o�W���
ڿ��u���nn�y��[|� 2jݮ́�@�}�A�'<�n��W��92�-�.0�}Gh�����jq���x��]�\2J���\E��2\%�Š�ꪹꮆ��9�j��]3�YW�s޵�����ZD9��Zrp=�:�:�:�R���Q��Q�c�c��(�']���p=�:�z
�׳��\ϻ^p}�"J�ˮo�^q}���5���]��U�U�b֪M����W=�L6���5���_�����/��wt�z��w|�ľ�5߻����?��o���m�����;�{�b��.�^��|���ӏ��O.}�G��?�˶_��
�fn���}�n<��k?i�t�Mw�t�M?��ħ���ҧ���o��,���l���[��֫���أ��"�2^����R�5E��#?�ӽ
Fs�H,���nx�J��L��)���_/��H>Z��3�ƔљLO���t�2c�F�
C�@^�+�Ae{e���)�\h1��c��/%�d%]ϑ8$��A$���F�k�g����rPN��d5�J�Rmn���`b�(e������p�����*�٩�v{�1G��꼱P�W`��<�z�Uo�~S4���R�˹/��T�;�0�0?�X�%�32F���M�"��j�,��N�'���H:�JgR�t*�̤�Y�
� 
C�DO�S���W��t)QLkDI��嵮`yU@������Y󎍬$1��oF�G��nj-���x�ѝ�z����s�'�3��
��[r��{��;��z��;	�9�.�*�C�FV����7�+}s,=ƍ���\$�{�[O��)��m�
�^���F�(�N?EMՈVd�okn�o��Ϥ�T�JXW�RHE�%UR��W�D�>��h3�8-6ŪXI3_ݽ����'��H��?����~k�9"m��7-�f��Ť��خ���@A4��|E,e��7
m�$�Ć��R��U��W`�%N�i�bVΈ~<�NF��4ɤsY.O��)
���!y�P�:{��g�[�t1]J���l5�H�o����ǎ<�����{��
J��{Xhr�L5]M��T!��B�/&1;]+��4�^�V+U�Mb^����%��х�l�����ݥ]
��%������\��EM:�?]Yij����N~ȣ�"U�4��"� ���'�O���8����
�V�W�tn[���
*O)�<}8z �wt�hgxj�Զ�Vuq*iNwGW�S4���Xo^ς!�ĒP�
��tN�Q�8���y���<���SsJN��y�3��]E�24\�$c1�����C,o�Ą�x����b�M��SJ�C��Z�
q.�O�3�|6��|�O)))&p�ȃ�$ ��䄊vEK�Y��|%_�jB��c��[��j�:P����o�M�-h�
e�6����\=F�1c��;�X8�|dl��T[�Ba&33>����ؘ>�����.���hEj�R܈h㐙( ���bllWr6�GjA=UJW3�l5W��*�Q��BKl�
�&�L�xrSn)muZmz�X/�+�j�n4j�����jA��j����d9A�J���sTTA���g4�(��W�*x�x��.�d����էC�ez�
%ِuYG��*��ط��o�AS����|�P䊸�F���E��
/eK��dFGWC���ʊ���VE��Ŷ0r���L�;]�Zc�@
�K�Fۨ��KG�{�*�TFR� �
y�|Jb$ jzѼJ��4%��
g'�.�e���9?� �DE,�أ��
�0E�$�T=��C�	T�à�!gH�8��*b]Qq��E!��Ny\��(%.� *P
��Y`�f��^V�RV�BN*�ŋ���H%"I�~�v8*��
h�h��B���ĈE\�
I�e$4"Z�NX�R@n��(Id��"��<��Pi�kŦss@̽�9�.��S��9|��\n�[��k�;��~r�"m�"ּ�m�Y���M��4.�֛뭋����T*�"��"s���$[>�}�����f\��flg�r+@43�3��|�-�_�EQ�r��w3�\��r�}Za�g9�a4�N��r�T@��hާ��-�nZ^�h9o���3�"�E�\f�gx�LQP8oQ�E�ޫ�����=!���<k~Ab��2�z]oB��f����������}���	όUv����/�"����)(B��o�{ٚ ��K�RUk��ؗ��6��piys���zw�m�%���U��U�k�>�Y�!3h��id	}|�7��CQbP2Q%4N�Ab(k�ljY W�e�ث~�������9��iH���D�k�̯�a�(IJ�l2�O��\����B8B�$�&7���F&�T)YKO妲��<�E�i�m��l7ʳ�H�Aub$�P�qY.%��M�L2�l%[.4`��ׁ�d�TB�o�\#U�U���b�S����(e�\)��5dPJ�(�*�«��JA�dT�%R7�c����=���|��Q=X��7�9TDP�=�𵦔�"�PQ�b$�'�����Ž�7N�XJw��,l�n��D��q?�eR�T�<P�5T}Mmh5�J��V��JU��({��R����\:��&�/��ӓd�u�ǥ�#OcJ�̺�4�y�h,�O��7r�|���'���G��4O�K�H';��M���z�@%X+��c|0�Od�IM&�X2���\D�B��/-������8d#%)T
��U�Lu���k�z����?Av7Cs����Ax�s��l�5]m�f�8��q2���V�v��8�L��T�%A����!e�F�v�@-�h���B]K9[�@r�|���q��`u�&����CP���Tɗ=��0�h&�����X:�N�Ri�2�\>��
�PT�ł�G/�׳e�t=�L7���9��K/d�f�fd�>�?�=�N�Y
�<̴*���2
���.���l�3����<r`�q�]�Z�>�i�2ƅ���x$2�
'C��^ƈc��Dd"ʌB¥��d+5]�'��*gj�Z��7aڥ&~JmLvr�x3ތ�Ɓp@yK$�WM1��pz9K�cy,0y����5�0V�'�#��h�2�nOW:�ܓ�D� \Ʊ�xkrҎ����Z�E�m4�mcf������|4��H~�8D:���"�ʫ/^c>���5��֚C�es��u�/~y���8��ڛ�o��\�q?�K=�,��jHi���@��sס���U�F�	O.�ɥs_�͝;C����糅t!�g�
�d �"�b��G�5ҥ��o����R��+�c��B�Q�N>:^��S�T�����`D(
;Е)i�>0�U�*BR��"�U����Ţ*��ډ��<E�Z��(7�
@T_@k�-SE'��s�!]�er>qdӓ�*�ʡyC�2o�5�g<��c|���ӣ���J��KUl!��k�����wJ�*Eo�V�Y�Q��k��}�[}�n�c*�b#g��.[���~������$�ĄS4�DФ֫5T�2�uI�*L%J1��@�o���VG/)5�X�,V�W��F��"Ę�9U�fX/k��jPG�T��>nv��/đT�d"��$��H��Aw'Oj�r�U(&��V@�eI*�0���$�	���*��R^�h���T�M@
L6�D��2"��i%�K�1��T=_�I�#W���g����tA��;��h�Q�T1PF�2�`�o��Q5���<ϋ'�D7�=b@.�33}��
8^��Kc���
����
/�Tp
�T]�AQ��5�Z��z]Q��d�L��I��""��Z^Ia����	
:hx�[hE��M�RA*�*����&�|#SI���]lQ���;<�|>���0�i�K���S_�O�0SB�k���V���80�N��k�cb�L��{<��Q����E���Qf����E8�x� :�
_�8g�%P
�')��b�`QU�Ґ�=���5����Uߛ(i����Wg��t=���1jjAY.+�����C�o�<���|e	�D!�����Y�3�˗�'Yؓ]�t��@{�>R�il��0�I�$��H8��XA��O4&���Xy�(�F���H+ 6D�,�x�(ۈ�|�0+(�B� ���S�����槦�)T���!c��T_hOu�s�y�K�U��0��$fⳓ�@��P�(�c�`*�E&��p,�ڝ#��n~84�i������ȉ)eJ���I���bY*K��P�0h"�G�cT؎��I�-ٿ�CA��H�(?�pU��8�h�3���U�;�hԂ��M�>��D;l{Q
�h�F�
n�d{kw���֊�?�5(b��?g����(���F��>�p], �5��{<�S9b	����])R;K[Hf�Z\-S!W���b`W�u��ߴ���[��~�����ۯ�Z[����[>s���_�k�dY,><���ݴ��
�>��y�������Mf�}�Żn��.z���/����Z}���'�ްa��
o?�3�3w��D#I$"�F�=�hLy���0±s��|c��.�ƒ��s�����8sx��q����Z��gi� k�Xgy,��u�m���P��0������18IL�?��|��|�5�"?|�DJJK����C�`�`?�o5u�uCր��*`܍����`T;$��P@������M�c��3�.�t�֠N�0���@�Cf�����#����wn�82�$��@U��p�l�z�$dKbC�)U�
t+��'t�OBu'�;PC���|pil)��p$���?��cG;�W�D8y�{(EI
����=5�� ��[^@?c��M��
��o�gnt�yt��c�<��Wc㡅�R��霽Y�5]k��a�wo|��YKh7��N�"V�g��Q�Po)�EY��h�ʰF�.`�vv������9�%t0����]�p<ł�aݚ�{�ǡ�"d,���ޛa���y�u�}���,��0�{�S�_���Y��_��W'0?x����G�?Y�����P��b�nk�=ֹۢ�X~�<|.�y\����w�aR��׿�$�2F��z��*}kĿ�k~�'�}��*&~��4��S�g�=@6Y_g/�ˉ�sKGv�4n�[�-�����/�F����O��S�F;���u]����c�1���CƑ#�%b�oa59Kc.�b�nTjz]Ð.��
�K�!�#�b�pB*���x����B�!	q���b�Qm�U1�Z��me�FA�)��,���]�b�Pu�S��fpz��m�NN�����f�X	^�R���e8D�`H:��s����5'�/GlHUQb�b%��b˿�ְ(�U�6�2���
�1.V2�Q�0�|�.PI�ak��d���V����xU�ʠ�d�Ϊ�0��NJ%�G���pP� 	��B�/��[W�"�"O���(�y�c�Fc��|�k�ş�1YK�i)����\�.��TIj&?�W�z�/�g.?��\DTX�w��V�6b�X�/�庽/Q��\%od���.&���bZR��␂����ѭC�Nt�(*@���T
�����P1��5���%��l�r�D�vo�vRLb'C&�X>ʥ��t6�'XC\C�Q�Բ
��MfM�&���`��t8��0#]Ȧ�|��R0� Xָ"��7��]S#��諨o*ؾ���$UN�R�L=�����ì6eL��r�,���Y(�}�<�iv���{7��
߁aO�+�cj��r�h���܆�Vb��z�Y6�X<�s�z`��d�]w��2�&�|��Q
Oztې]B�[��DI#~ىF�ߖ�#��`=lj�,�,E�p�������S�xfa����Ҳ4c<��НA ��%^#�2�*ŵ���N�m�c�$���w2|d<��_}�KL:�
M�Ѽ�:�/J��N�?�{V/r%�'Vź����9d��Ȣ
���/ �����h1^KN'��Zg��z[/Wk�Z��)g�hm�ӽ�?�M�BW$�N�Ũ��a�'����H`}����܇�HMm�M��^�
�mD�e 0?��pk�:_�'V��+�LEE�Q=C�`"1����u��JE���j�V��
���1*�7�[^�
 ظ�j4}	J-�J�������@:	CE�1K��
t���F�boh�UP�m��h#+~/K��3N���zK�\z�K�7E�
�дPOF�51�/�V�����N��-P�;�?���Gi�z��eNᬧ�}���er��";�0�3�c�h�d|���&�	��I>�#�0K"������6f"M�&S����9�9n&5���6&�ļк�T�Bw��9N\��B}��߼Cf��c�G2����?���S�V<X�	�\9S���Z��b�������ҝ������R��ɍ��� tU[zj��Ol;�|�B���|,pws�T@- ���̼j��z���Oj/�x\}qjD	+;�}�_�~�/�G���g��=���JZ��˟��A���_�G�
l(���[vo�8�Y$� g�^�N�|��������3�؍�������bNL~�$���eaLb]ma���4̫ͷ�99L[�YVY��p�7?i�`�h���_��9���u���ǂ�h �.P�(xU�{�D�[r�ئ��,����1����9O1��X�DqA_N���E�2@),M�c�xb<Ɇ����4�M��G�eU�V~zjO����K)��4��������l���ﶭ�G�vdF)֏�:Z.�Ԭ������ݍd�5��γ�1���}��[#.$��~sj�.n�L$39rИ'c�����&Njx��?yb�yմIL׽߭o�r��$��|�;ŧ�g��#ERw�MM�����|8~��ȱ����]{���RG�-������ls�3��<����&4�A�	ߝ;��o�o��w��w�v��r/�w���U�˺���
����t6"���W&��;�Q%�U�˼�k�f��=���|p0��w�C@.�\���[�S䬐�s��60��l�z�t�ok���e�ۿ��B	�ϲZ6tb��)j:�&��k���'_�.e��o��?��i�!@7�o�[����0�݇��p�R�	�&��̨1V	6#5n�6]m���g���lW��Hm�ER$ˌ�ɽ��@`׮������v�����b���׏l�%��:�[���a�Q�e˙r����L6��S�'�݅����iA�X)W�Z
���������ٱ�N��i)# �P�����Qi=��$\�7�Kҧ�o�+�P�KJ]B�l��
�lA�C�R�0A����ӿ��<�r"��G�*פi���}��C�P@�*E�D�1/��Tx%��y!W���'5��鮒�#"�s��ppG� �����B�����_洸"�Ԏ6#L'ݽ�,N7f�9�!���$��*%��V�jQS��i�,�;�}�)Uo���U�X6�J��#�q�*��=l����z�Z���&�k�6O�~�6�R63:��Ze�V�
�L��X�q��Y���,<�^
-�G:[[S�J�a�,�d����P4�L&B$�S���<6�
̏�
to/-���:�����d� �Dۻ2�=(HD�H�kY\x��t�DPAH��r�~|RC��I8V:2Em-u���K�j��X3<�_�gy*�9-g�
������/ZH�<��,d��j����H�F�Q��F.l�z��I�ߨė�D��G�Dȗ�n���C��?=;	���Z�V�3�7J�qF�o
���O&R�Gw����qL� 
�Al\c�]�b����>�д0#�qXw.�Ǘ��T=����'�LF������]��A��q�T�5�=|�;Ԟ�x����'o����<59����S=��5��z���~�;��$}Vԓ�d���w�k�J�g�6_c��J���^�ֱu��N���P�:�b�!�xm2S��J��R�bWJ M����t��S�0��5wX���y+���J�/o�gUɉwtE�J�Z*d�\�T[�E8BL����z^�>�O��z�����U���v�`e�z�_0
�w܀�SP$��\L���b�|*0�X��h"����5���&���O��t��qp)�s�6��
���px*����y��N�)��u�"����/�my������=}�з���;ݡə9���gnzf��8��������FQ%>�ͤ�$S�Db&��]{t�
u��T+����_��<�Fzt��V�'!���҉&���"�H5�L���Y��])��>(�9�������܍Z<I%>�C�D��nך8ɺ��$w2��f3�:VL&��b-X�;l������7=->��9��$��I�$p��%\.��r��1���t3$'��2��;'7�Mi"�[�	 ҙD�(�}�&m��z��k�<��hi���}ӭ[At�:?N	�<��JkO���?�f����u;Ovi����L��W�CG6ag�+T����8ls�	�m�,�)�xBD�	h��h��Ow�mF���=Qz�
��T��N�;|��
�dP͢��7�c��%$'a�g>:�3�$�����@ݎ�_{���<��y�=�t�]R���8�ɟ��咴"e�8��)�C9gI��]�Y=�Ồ	gI�Dc}�%�b�[v�ו[�>#�<�u�����h5��ig(�*�T�I�}����.�d�!�c��d�m�(�w���ݸ�-:�46'v�E����$MP���l�+�^Λ*��סOd7:8�
��
DƉ�
_ZΫRɫ���
���G�痾Q$������m1��(bc�Rs�x��*�ֲC�i�i����iНgB�ѹ�iZ��t
֡�I;�8���v�[o�K)�Z�v��M��l%�WM ��8��͵��wfN��ݣ�	���(1YvuI;iڒȽʘ�,�SH�Y���T,Ԙn�^ȌSjO��)g8G��2��ɔ�g����OlB��Br��^O�x��1B[J�KhOo��3����}v��
�i7Îhm-�Rޕ,Z���m"����ȷh��������t��?h�m�q�z�Sܽ�Փ��m��&��������{�[\)�O��e���W�"��/��P����H��&a;�C��ɉr�ڨtUl���ꈗ-��Bg��e�HM�d�Y��weǡ(��ע(����'Y���V_O��؇��(aE��X��mᤃ�miW�PEZ�ۘ��-]�wY>�X�ts�숓Ilu��r;Y��]ǭ!LӜ&�=t7_�-�L��zB{���u�����>VT��&Xj~�(�sb���g�3E�]���؃7�#���vw1t�-?]��\����p IדI+u(�qEPR��Qr�m���h��T0�c�3H��5�?!��Bձ�B��8�8�i�P8���2�s���3�6�C��I���$A��[W��բs�a=kkC�^3��<������+u1=�`���1]L�<�C�
�1MRo5(����H���p�Ъ]p҅2�M�w.�������.�m0�ԡI�cX$]l�� �!+(�l#v�
�쬂�`�Cڤʩ��ns���J6��1XYpP�HQ�J�kic�6�7�E���VЊ�U�a!аQ�Nzi}��C�u��(��I
ZT��lc4����M}�W��Z��8�W:�0�8a�f� �qg�Uǎ96�m�y��9>�gS{@`Q�m�D�5�g���fŴ3����h�c���xB� ��J�Fw]���>��{���\�C]�8#U� +���-�uѡa]O��^�y�B��pxq��'*gM�.4E�t M����Bg��RK �xV~���ӆ-6b��"]f��zG�l�@��"���9P��=����3DW5pa��"��A/[��w�Y�^��0]��P�xV�pQ��ꢭ��J��<�GEl��
�9s����zz�5�pе�A��q�C�'c=����:�m���Jq��w��k���)���{�x�S��S�}��9N�+��r��{�ơF]�QVpN7�XA>�Y!�7�a�,�`�3^T}��'�G��Zks�F��d�Ҫ��]��T��+��œ~3���ḳk?�����“���&o��X�[� �@8:�ɝ���k�<��ڻ��:He,��<ӭ�����n�6�/2�L��)1Ǭv��`�aӅycw`���Xs�z����u�`��uX�u�`�s�.z�a�O/_�6Z�2*pv������%7	Y1#eH����=�/���zJyIyz��H�0Wk���u���9l��Ԙ���>�w�3>��Z��lj`a��#�=63O�i!�L�8l�ջ�W��}���\d>����ܷ��=��� m�{�>r�Z��k�j�R5�P�+q ��	�ܵBe>��P��,�'�ҏ3���8U(���wz��u��t�ybb5]P����c�Hu�%�ĆP�Z�����Ie��E���(l�IRL2�L6�BJLH11&%!C`lb #'��SjJM�J�����1���KxE=���R+V*��QSjMi�-�%ס���|Yg'��|��\�Z42>�>:�;��N���Yk�O�����7���o^���������*=C�k��?f�NE�����I��2|d9˚�ndZ���"co��~
�L 2
Gf�`�pӕ-���m��l�#捎��*k+�s��9�����/����N�?��!!<���[X�S�q���	,�Ǿ��^�^b��; <;ށC�b�d�h]�Hpai��’�|��^�_�#I��Up63�P�
g���u!��,x%:�T(@�6k^f"wpֱv������D�0��P(2�"�n�5�Ő��1/�nP�ކOw�л���1�cTצQ���/�X(�y��/&G�5�	��D��"[��ðc6�l��l	��8lA�ԁ
"�閻\�헊i��_��+ad�I�3hlD�&�LX�hT�����U�ς�/$f0�@U����X�����Z��in���S28:z��7/fճ򐴉��z�L�F!�H�m�ve�F	��]ɥ��H�@��?k#�t��$g�R7��ܾ�?"�旗\r�5�x�S{��Y�Ɍe7n?|��azo߸q�����7����yV�4޸4	� ���#L��x,�@+F޼�z�p<7���&\=�aY�[�V���G�(�F���2�DP��yl#Q��0=m�肴^���$�6������ց���ܾ��EL�z��2�x#��m��EցW^�?l��bi1��c6�����4j$֠�
����Y�9�`�Z(�j��O��g-cgWL�.��%s;��;��
������;��w�k�O�I��_2i����?f���h��k���E߿�����k�`~�}�>;�9�=O=�%����~�&S�٩���vt���y�����z���\�w���V�\Wf�$������8{�s��Pu�a8=��hz�0�V1.���OV�>1{>=o�s�5���i=��=ߺ��e���<��.~��X�}�Fk��	��#x�c```d�3��΃�kO��hOKpx�c`d``�b	`b`B/ f�x}x�c`fb`������Ø�����2H2�0001�r2�#�����ఁaC"���P�(!#�
�x��GnBDߧ�^�wB'tĖl� r��Cp�Yq�n�H�5����<+����2�m���qa�R��ld/��)�+k����Ml����ˁ�kh�ߪivMqjڌ�xT���9��	&�'_D��M�I�"M�,9�(R�L�*54i�C�]z�0d�/c&LY�d���{_�g�ex�c`d``�c�x~���L p�z��X�B
a	�x�c`d``b���A���$#*`?*x�cb```b`�� � � �`� Pec�hq#7��d�N	0m�	�@;����a���Ā03p@Y
@��n@�+���"?u-�nPKx���1N�0�?�i���P�����NTf:3���*K,%U���\�c�����Z���~��o�e�w�',x�<�̅<��g,��<ge��4�B/��5�2Oy�%s!�G��|e��6K�8ZD��g��k��9���p�n�vJwϑKE)�e���'�j-v:�z��Icw���ت�vc/è���]僜W��)S/�M6+˘�]�m�l(���~��C�x�c`f@�h�libs/better-framework/assets/fonts/FontAwesome.otf000064400000407230151214002610016347 0ustar00OTTO
� CFF 9s�7���EPAR(�l0OS/2�2z^��`cmapǢT��head���6hhea
��P$hmtxJ+��t
�maxp�P
`name>$#
h
postx FontAwesomeC�������������	�U�6����U�6���2�2���
�",04<>EGMT\_ehmqy}�����������������#)4>HT_lp{������������������
'4=GRYfoy��������������
&,39COVcoz������������"/5;FPUZes}���������������&+16<EOW_hmqv|����������������)04=DPX\aju����������������(,26GYhy���������������%16;>EMUckox��������������				$	5	G	V	g	l	p	v	�	�	�	�	�	�	�	�	�	�	�	�	�




&
*
-
0
3
6
9
<
?
B
F
O
_
c
u
�
�
�
�
�
�
�
�
�
�
�
�
�&5BQafmty�������������������!%)-159=AHLPTX\`dhlptx|������������������������������






%
,
3
7
;
?
C
G
K
O
V
Z
^
b
f
j
n
r
v
z
~
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�
�	
!%)-159=AEJNRVZ^bfjnrvz~��������������������������������
"&*.26:>BFJNRVZ^bfjnrvz~�����������������������������
"&*.29@GNU\cjqx������������������ '.5<CJQX_fmt{������������������ '.5<kvglassmusicsearchenvelopeheartstarstar_emptyuserfilmth_largethth_listokremovezoom_inzoom_outoffsignalcogtrashhomefile_alttimeroaddownload_altdownloaduploadinboxplay_circlerepeatrefreshlist_altlockflagheadphonesvolume_offvolume_downvolume_upqrcodebarcodetagtagsbookbookmarkprintcamerafontbolditalictext_heighttext_widthalign_leftalign_centeralign_rightalign_justifylistindent_leftindent_rightfacetime_videopicturepencilmap_markeradjusttinteditsharecheckmovestep_backwardfast_backwardbackwardplaypausestopforwardfast_forwardstep_forwardejectchevron_leftchevron_rightplus_signminus_signremove_signok_signquestion_signinfo_signscreenshotremove_circleok_circleban_circlearrow_leftarrow_rightarrow_uparrow_downshare_altresize_fullresize_smallexclamation_signgiftleaffireeye_openeye_closewarning_signplanecalendarrandomcommentmagnetchevron_upchevron_downretweetshopping_cartfolder_closefolder_openresize_verticalresize_horizontalbar_charttwitter_signfacebook_signcamera_retrokeycogscommentsthumbs_up_altthumbs_down_altstar_halfheart_emptysignoutlinkedin_signpushpinexternal_linksignintrophygithub_signupload_altlemonphonecheck_emptybookmark_emptyphone_signtwitterfacebookgithubunlockcredit_cardrsshddbullhornbellcertificatehand_righthand_lefthand_uphand_downcircle_arrow_leftcircle_arrow_rightcircle_arrow_upcircle_arrow_downglobewrenchtasksfilterbriefcasefullscreennotequalinfinitylessequalgrouplinkcloudbeakercutcopypaper_clipsavesign_blankreorderulolstrikethroughunderlinetablemagictruckpinterestpinterest_signgoogle_plus_signgoogle_plusmoneycaret_downcaret_upcaret_leftcaret_rightcolumnssortsort_downsort_upenvelope_altlinkedinundolegaldashboardcomment_altcomments_altboltsitemapumbrellapastelight_bulbexchangecloud_downloadcloud_uploaduser_mdstethoscopesuitcasebell_altcoffeefoodfile_text_altbuildinghospitalambulancemedkitfighter_jetbeerh_signf0fedouble_angle_leftdouble_angle_rightdouble_angle_updouble_angle_downangle_leftangle_rightangle_upangle_downdesktoplaptoptabletmobile_phonecircle_blankquote_leftquote_rightspinnercirclereplygithub_altfolder_close_altfolder_open_altexpand_altcollapse_altsmilefrownmehgamepadkeyboardflag_altflag_checkeredterminalcodereply_allstar_half_emptylocation_arrowcropcode_forkunlink_279exclamationsuperscriptsubscript_283puzzle_piecemicrophonemicrophone_offshieldcalendar_emptyfire_extinguisherrocketmaxcdnchevron_sign_leftchevron_sign_rightchevron_sign_upchevron_sign_downhtml5css3anchorunlock_altbullseyeellipsis_horizontalellipsis_vertical_303play_signticketminus_sign_altcheck_minuslevel_uplevel_downcheck_signedit_sign_312share_signcompasscollapsecollapse_top_317eurgbpusdinrjpyrubkrwbtcfilefile_textsort_by_alphabet_329sort_by_attributessort_by_attributes_altsort_by_ordersort_by_order_alt_334_335youtube_signyoutubexingxing_signyoutube_playdropboxstackexchangeinstagramflickradnf171bitbucket_signtumblrtumblr_signlong_arrow_downlong_arrow_uplong_arrow_leftlong_arrow_rightapplewindowsandroidlinuxdribbleskypefoursquaretrellofemalemalegittipsun_366archivebugvkweiborenren_372stack_exchange_374arrow_circle_alt_left_376dot_circle_alt_378vimeo_square_380plus_square_o_382_383_384_385_386_387_388_389uniF1A0f1a1_392_393f1a4_395_396_397_398_399_400f1ab_402_403_404uniF1B1_406_407_408_409_410_411_412_413_414_415_416_417_418_419uniF1C0uniF1C1_422_423_424_425_426_427_428_429_430_431_432_433_434uniF1D0uniF1D1uniF1D2_438_439uniF1D5uniF1D6uniF1D7_443_444_445_446_447_448_449uniF1E0_451_452_453_454_455_456_457_458_459_460_461_462_463_464uniF1F0_466_467f1f3_469_470_471_472_473_474_475_476f1fc_478_479_480_481_482_483_484_485_486_487_488_489_490_491_492_493_494f210_496f212_498_499_500_501_502_503_504_505_506_507_508_509venus_511_512_513_514_515_516_517_518_519_520_521_522_523_524_525_526_527_528_529_530_531_532_533_534_535_536_537_538_539_540_541_542_543_544_545_546_547_548_549_550_551_552_553_554_555_556_557_558_559_560_561_562_563_564_565_566_567_568_569f260f261_572f263_574_575_576_577_578_579_580_581_582_583_584_585_586_587_588_589_590_591_592_593_594_595_596_597_598f27euniF280uniF281_602_603_604uniF285uniF286_607_608_609_610_611_612_613_614_615_616_617_618_619_620_621_622_623_624_625_626_627_628_629uniF2A0uniF2A1uniF2A2uniF2A3uniF2A4uniF2A5uniF2A6uniF2A7uniF2A8uniF2A9uniF2AAuniF2ABuniF2ACuniF2ADuniF2AEuniF2B0uniF2B1uniF2B2uniF2B3uniF2B4uniF2B5uniF2B6uniF2B7uniF2B8uniF2B9uniF2BAuniF2BBuniF2BCuniF2BDuniF2BEuniF2C0uniF2C1uniF2C2uniF2C3uniF2C4uniF2C5uniF2C6uniF2C7uniF2C8uniF2C9uniF2CAuniF2CBuniF2CCuniF2CDuniF2CEuniF2D0uniF2D1uniF2D2uniF2D3uniF2D4uniF2D5uniF2D6uniF2D7uniF2D8uniF2D9uniF2DAuniF2DBuniF2DCuniF2DDuniF2DEuniF2E0uniF2E1uniF2E2uniF2E3uniF2E4uniF2E5uniF2E6uniF2E7_698uniF2E9uniF2EAuniF2EBuniF2ECuniF2EDuniF2EECopyright Dave Gandy 2016. All rights reserved.FontAwesome�[_�������"+/37;TX_dhn���������������#'Prz�����������.26:@DHM����%*.48@ENUZ^}������/3�������������PW^cgl������8<FJ�������������CUajov{�������			@	J	Z	�	�	�	�	�	�	�	�	�	�	�


&
*
.
:
A
T
m
r
}
�
�
�
�
�
�
�
�
�;BFLTX_cinsz���������� .38@FKPp|�������������

&
E
d
m
z
�
�
�
�
�
�
�
�
�
�
�
�
�
%1=BGNU[e���������
#)-7=CJO]kr����������������):PUblqv|����������",5:BJOTgz���������������$6HZ]hs{�������������
 &,6@JTX`hnt|�����������������
)8@OSX\bhp~�����������������"/4;?FLSW\hmt����������������
',2=HS^elw�����*
�A
�T&������fA�V��
��T���l�f��P��������������z�z����
�P
���4�!
��t������
���
�����q
��q
�bt�&
y}}y�3���3%�3���3�
`z���T~����~���������������4���]
�Tg@Z
�4��
���
������R
��,�T[@��
��<���<4
,
^�2
���%�%�����%�%�����%�%��3�
�T<
�n�h@;�TN
���TI���TN
���C
KFKk�6
?����������J
��������
�
:
K,:
��y}���Tj
5
�/W
K$'�T$����V
L
v
��
�
L
6
f
y}}y�y}����������}y�lz||z%
��1
��
��������K�T���T�Y�=��|�zKz||zKz�|����������N
�
!�5�
�!��
�
�f�f�(
������������G
���
Q
3|�T|�T|��T�
�T�
�T��|zs�
R��������3��&'
'
<
@A
��������G
������������^
���[�=������
�T� /
3
c�-�`�V�}�h�n"����B�v
�����g
�O����G���
�`�E��}n\>l�g
����,�������������������h����h�@�@�h��E�Q��P
�|�z�@z||z�Tz�|���������|�z��z||z�Tz�|�����7
�F
���x�
����3�C�DRRDD��uy
;
�;
���5�!Jb���
h
����
�����5
�/������
�T���T �+
-tzux��u�[��Br�lmy�z�~���5�������q�s�������U��hnnh�hn����������nh���
��t��t��t�T
y}}yKy}���?
j3CC��
��
������5�;��(�=��Z�XW�G/�9�;���/�_M�knm��n9��:Y�I�Ƒ���P�`�q���������������~���d�_�i�r�c�rr�i��i�i����������y��
@�H���-�R
�'
�����
���T� �����1��<t0
��l�n�l||��}_zob^��^�b�z�����������M�<�M�<v��������������	�o�_��}|�|r
���
/�0
���]�}
���]�
���
�E�Q���y�
v�(�
��W���
��T/�T����
���
�j��i�h��{�t���*
�<���<�<���
��<+���B�����������
�����A�S� ����i�^wv�h�������v�i�^����S� �A��E�]�#���'
K(
��D
F�m���3�'!�����%�Ơ���#xM'�nq��w������d����������������o�^�]���
t
x
�1�!���!���������EQQE5������i��������'�Ty�}���������
�tV`�����
��
K��
�T�����
��
��
����t��
kb
K<����z�
X
�@3CC3�@���#P
����n�hQ
�h����������/�:�n�h��
��
���:�
���
���;x��t������u�l�TK�
1���
�0
���8�i8_dd_�~~�x�z�������������������ƅ����y���"�9��O��9�%������9�)��o�'�0�q�i�?�@�h�h�?�@�i�r�����C
�TFKk�Tr
P
��;���;�Y�S<��!��y�o�t�s�{tq�T/�T��g���5��[��
�F
��
��s
��*
�41
���������������������Z�Zr�w�h�)��S
�
-
v�v����z�z�����:
�t�t���t�t���t�t�
1
����7
�Ԏ���8�
����J����n�������������������+����t����m�y�;�
[�8�����
�����������
������hn�>�����~�w�~����~�w�~����������K�
=+�tX
�@]
�@g�Z
�t�V``V��;
��;��`���L����<��� �xra��������
Y�W�
@3�&��
~~�w�~@���������5!�����������}y�vKy�x}z��y����n
������T7rr�c�r����~�g
��hnnh����
���YYG
����P
�����~�����*���*�*���*�*���*�*���*=
�4�����
�4����������)
.@�����(�����[
�h
������������������P
����v��T�~z��$�j�
+�[
��<���<�5�!I
��4���*
�A
C
�7
�r
C
��7
@r
b
�!�6��g������T����E ��
��ˋ�������h�3�/�����{�V=��������������n���������������\�n���]������������9�
��v���������x�{�zz{��X
�����CZ�7)������D
�T���}�y�T8�TC
�T7
�Tr
���]�]��[
1��
��
����������
����7��������U������f�
�@��m���
����� �
��<
�Z�Z�������Z�Z�������{�B
����r�r�����z�{���
+
�T
<�Z��������:�������w��B��������D�$�$�D�����(�=`��h��Z����������TA
�
/��0
�����nh����&�&�����&�&�����&�&�����{��V��v�7�+�4��2�y�qpV``VV`��������J
���Y
M�Y��
}�
���>
��|z��nhyy�rrr�r�ypttp&pt��1��5
t�v�������'
K(
����
�����������;���;�����g
���
$�4��������y���������~�M���Q��������������s����Q�Dnt��y���������������������y���t��
��F�t��e�11e�BB������T�������������2
������
����������r��������I
�F
y����������'�&��K�
��w�_�_�c����������4��4�����4��4�����������p�]��R����
���G�T��TX
��������������x�����]�]��
 83��
���w�rrh�������h�@���;�f�v�eK\xcik�v�ss]tRat�7�+�4���4��7�&&����
7����
�V��(����-
hn�����D�$�$�D�
�,
�}�t��P
��`=��d��b��9�7�B��x����������������������t���3
�������?�L���g�__gg__�g��������������a��
������`�V������������������C3~�w��]������}
���y���6�%�6-��������������	�_�$��cX��~
�TR�V�2�2�V�V�2�2�V������P@��z�y�z����z�
������s�/A����v����������zz{���������������b
�������z����-
�
�����f�t����&
���3�
������
���]�]�EG�xZ�n�yt�P
P
�������������+�+P�,������������ʲ�������,�������
����
_h�m��x�����2
�
������������
����ˋ��
�
�
�d�4����������4
�T[�`�M���`�My}}y�T,�V���;���;�0
���&�&���T��
��3
��
����������t'.
%���@p
�)qt{t��s�o�y�����s�%�$����������33�3v�K�����
�4��4\~�v����
}jii�C�@�@�����x�~�C
��Kw5 !4���wk�z|��|,$P��+�+�
����������-
�������
�
���
�g�s��}���}y������������f����
����#�E���T�@��)W��b�it���
��S
���4X��wmx�yj�h�����o�fZedZdW
f�r
r�syy�'�&� �������������h�@�v� }�������������59������������2I�8��8��!����~			I	�
M
�
�?y���
*
�BP�|88;�l�]5��m����+\��<���b-�G_y����'>U��>c� R �!0!�","^"�#0#�$$q$�$�%%~&5&�'A'�))�*J++�,,m,�,�-�..1.�.�.�/P/�00�192�2�45q5�5�6<6�717x7�8h9�:S;x<<T<�==�=�?�?�@!@�AjA�B�C�D�E�F�G�HJH�IITNN�N�O"OxPPPPP�R-RvR�T�UGVV�V�V�WX1YXZ�[+[�\C]]�]�^�_+_9_G_o_�_�_�_�_�`�aaGb6b�b�cPc�d'd�eNfGf�f�g>g�h�h�i-i�i�j j�kwl%l�m7m�m�m�n$n;nOncn�n�n�n�o"o�o�pp&p>pXqq
q}rIr�s8s:s<s�s�s�t�u�v<wIwhw�xGx�y y�z&{6{u{�||�|�}�~~�~�~���C������M�����9��C�|�����2���8�V�����P���	�c����S�������O����I�������#�|����L���������`������m�
����P�o�������1�����*�x���������4�f�.��H����U�\���1����������'�C�w�����[���W��������(������b�������;������J�{���.�ŝ�Qƭ�fǮ�*����ʛ˗̉͌����|�`ϫ�Zҝ�(���Jտ���׻����p�9����D��9���������g�����t���g��,������q���?�����o�]��1�a�JC���0��g����	$

�N��
F.yq��4����+M�<�� �!>!�";"h"�##�$b%g&D&�''�'�'�'�'�((�)�*"*�+�+�,?,p,�-F-U4>4�5~5�66636>6�7	8"9�9�:-;F;�<9<�='=\=�=�>?Y@RA�B�DEAF�G�H(H�IImKGLL�M^NZO�PxQ@RS%SlS�V�W�X:XRX�X�YY]Y�Z�Z�[+[n[�\d\�]g^Y^�_2_�`5`�a�a�cBdd;dWdvd�e!ff�gog�hNh�ikj@j�k�l�m�n�o�p�qhr�t�ukvYwfx�zV{r|�}/~~�������U�����u�����[�������
�t����J�����~������������������3�J���#���������c�������$���;������������������������������������T��t� �T��T���4P
�4��� c�
��z���.���.Ȯ��h�K�h�<�Nh���-���
��
�����-N�<vhNK�hN�<�h���.���.Nhv<�N��N�vȮ���-���
�����-�hڠ�����v�N����v���4�4���T�
�4�4V``V�T<
�4�4��TA
�4�4M
����0������T���y�u��uyyu��u�y�����������y���?�j�`�,4�G��y�u�~�8������������գ����������YSKkj>h3c�#�
^u�i�����������ƭ��R��������������@2�A
��4
�����F�M�f��fM�Zn�n�w�������
�������������v��
�x
P
 �`�V��������c~ofa�[�!
�Y�������!
 �����
����
�T@
����������b����@�
���s�u�w�#��$���L��>�����������$��#�����������69�JX�"�!�!`V+/E��E+�V������1�R�F
����_r���
�Z���o�
���p�]����������t��
�k�s����u�[��z�tv�U������������Z
�tq���9�
�[��[�9����:�Q��Q��:M�q��k�s����u�[��z�tv�U������������Z
�Z�����J�����
��J����&��	���	��&���a�
�)���|
�����s
�Kw�����
����t�������
��w��4X
��]
��g@�
 �v��
������
�����
�������Y�T3
���Y���`�V��V``V�TV�`���������Գ
���
�T3
������Y�T3
����TV``V�T�;
��Y����TV``V�T�;
�T\�TV``V�T�;
����
��^���y����
�$�%�����
���I�������V��������h�h��������v���j���y�����������������y����
���������
���I���������I���V��������������V������������ ���V��
V��������
�t�tC
KF�t�tFKk�t�t�
�r
�t�t>
��@
�
 ���V��
������
��FKk��r
��@
�
���������
pP
�����t�W�&S�:�aR`S�:�a�)�)�6����z�
�6�)��õ��`�a�;�R`�W�&��t�����P����Q�EEQQE�E�Q��������������Y
���8
��&��8
��&�T�8
�T�&��8
�@�
e
���{
�����z��K���}�z�����������������a�E�V������������" n�m�l�o�L��{�y�ry}{�{O�J�Nl�l~n|�������i��&js�����������^�^�[{m~m�k�No|�y|�rz�{���Kp�i�j�ki\f_i]�����������Q�M�[�����������!��|�����Lz��~��r������Ǒ̒Ȫ���������������'������������f�g�i��������M��������m����������������������������([po����p���H��H�4���
�wO�V��VOcZwE�;����L��1�������H�u
 �v�
��t���������n��n�����t/��
������s������~��o�J�,z�W���`a�G�ah�c��~��v�~�A�������������H���H��������������������
���
���w
!�4��t�4����t��t����4�t��t��
��to
�T
�4�#
�)�v��TV���{�||��||���������N���������g���|��5����p�p����Ty�~}y�:y~�����T����ppur��5��|g�ccn�_��Tz}���������������y�}}z�T���� ���
����T�
�d��gf[wXX[��f���e�6
�
��t�q���T�K�T�����T�T�
�T�T������x�4���4�t8����
��z��T~����~���������������f���9x�4���4�t8��(���������������������������&
��T���
��T�������9�v��T�
����,�T��,�T���������h���X�h���������Ym���}������}c�h��hcqj}����}i�Vg�v��
�����w�����x�r�w�wvt��L��������������#
������P
���
����!�S�Y��
�y�l�D�&�������������������)�'C�3�$
��Y4����K
�Ti
������t�}�y�T|��}�zcesd�,.�9/�F����-���
1�T5
�T��
����"�Q>�W�����������������
����"�S�X�������5����z�|��[������������,�9�F��Z3����
�Ti
�������9
�����"��!
��!
�
�T�����������@�
���
��G�����
���v��T�i
���T����T�
�T��+�3
k�T���^�^�����^�^���Tk��c�����v
]�b�t�k�r
�������Kg
_�=��1ln��o����1�"�-SK�q~n}s{x}zs�z.�������;�3�n� �L��������� �v��T��T��V��T���/���W�W���/��!�(�Z�Mj���:�kD
��L
k+8V=_G�xɁ��������������H�KxMG�_8�+��������M������������r�������r����N�-������hnog?���
�
��?g�o���������� Gw���_
r����N�-������hnog?���
�
��?g�o�������������_��Q�P��o�x��}��y�C���Q�(Csyrp}t{xo^�������P��Q�_����K�����
��n�{�}�������|�z�x�8�
�S�`�`*�S�8�
qxozo||�{�}�s}|{n.��������
�K���������������
�������������
��
���
�x
��
�����������
����
���������
��
���� ����0m�� 8����
����������������v�v�ʪ�ʪ����ꪫ����������ʪ��骫������k��i�hvv�v�i��j�i����ʌ�����������
�����1�
����
w�������
����ʓ
����ʓ
������1�Y�������1�����������������������Q�
kl�l�������ʙ
�����F?������i��j�ivv�v�i��i�j����z
�)z
����_�^�X*�D�t��cX��_�^�s�jii}jtt�j�jh��s����������W
 m���
����g��|�v�t��y�w�x���og�`vf�/TF��w�����������������.��������q��ra�\��zz��z������aM{tsw�x�y�z�z�Vc,sj|wu��t�{�t�v�\h2p]�yx}�x�z�u�x�Wi:mY{pvz�s��~�{�s�w�w}e�_�^#��:��/�����������r�����8����"������ �����
�����
�������������4<
�4���K��4�"K���m�e��,�,�eB�V�4�
��K"44"�4k�t�4�:�4�t>
�)����T���3���3�3���3�3���3�3���3�T�4�tX��r=�E��E=UIrX��t����
tK��

�T��/
 ��,�Q�����i�ep�%�/��,�xx�x((��(���#�Ɏ���������	w�����������R��'������V��b���gfV�p��o�q�qq�������{����������\�/�j�}�}���Y�h�^��?�DF�G@�E�a�t������V@���h����a�%�-n�<����5���s��c���������sŔ�O��������5���*��V�JM���(0�x[[��_}�~􊢋��������%����������;�AH�W�{�'Q�bgf��g���
��F�I��G���������f�=��R��!��G������v�^]�^����z����8����'��n�\��PuH�#hPMqJ�K{�-�!ߜv���`�������Њ�����xġ���������M�M�N�������[�����������Đơ�ϦԖУ�������!!�!�����x$ǁΓ�m`r�;�n�i~G�h�ftnOlF�Kw�z6���������-�������������;�������p��6p�_�ph��6hp�o���;_}oh���6�h������6���}�_�����
�Ǐ��\����������|��}�Cy�	�^��^�^L���uZ�
����������������������q�����m����ept�c��CD�C��m����������
ǐ��]����������|��z��b|�|}3��mrS�
�6��6��7W��,��������
�"�����������������m����~yv}u�������������]� y�����]h��vp|�zww�z�v�����{����y{ ��������������|��p��hm
��R�<�0
���R�<P
0
��R��<�
i
m
��R�<�0
�������R�<�i
m
��1�<�0
��1�<P
0
��1��<�
i
m
��H
��H
��H
��������t�#���#����@�������w
��t\
�
�����������������������>
t�Tdw
��T���i���������F��y
�������������td��v�0��{�t������z{�~�'�&�9*
�T��T�3���3�T&�:�'�'~����
�)��T�T�������Tn����4�4�����4�4����Tt����|z�@���
���4kX
���S
�@g@�
m���� �
�����D����������������~��������������������~U�T����4�4�����������~�sj�iij}st�:�9�4�4�:�:�W
��
�
��
���{
����
�
N�L�T���_��p����������’��x���J
������ 
�����v�����P����P���������Ϡ������������H�G�w�w�srP��
�m�X�X�j��:���b�kkcv`~:���j��X;`Y;l-&P���y�y���Q
�����4����������S�+����,�,������|�������|�������������������������~���KK�������X����������������������������fc�c��Q+�4�4�4�����4�4�0�0����f��,�,f�M�ff//������ ���
��g���t�������}���{|y~w������j�X������������������|�z����h
"��Q�����2��{�z�����t�{tq�T�4� 7����\�3�u������������������l�z��*���� ��p�4�Tq�t��������������
 ���
�Jw���
���t����������������KK�������3CC��
��
���������������������G
���������������fc�c��Q�{������k���k�Y�kk������k�Y�kk��kk�Y�k�B�B�k��������������
����C
��
�
�����
�����
���-
�4����=�����
1���
��
�����
�������gs���v���������Z�v��Z� ���S���Z�v�Z�Z��Z�Z�r����Z�����h������l���vl�r|h��h�|��e
P
@g
���
��@��g
���
��i
e
P
@� �����
�Z�w�Z�Z�2�Z�Zr�w�h�Z�
���P
����
�Z�w�
�Z�
����������
�@�w�}����rr�w�������r�Z�Z����
�
���
�%L�.�����2�:�:��z�z��z�z�r�����:�:�2���������%L���'�2�z�z��:�:�����������:�:�
�z�z�������������
����p��������h
��H���� 
Z�������
��hn�����
���� 
e
}�2z�z11z���I�I�I�I{�zzz��1�����������I�I�I�I�����������������
���I�I�I�I��������1��zzz�{�I�I�I�I��{z��v 
�P
�����������z�z{z�����������������M
�v�v�,�+�M
�1��zz���6��
����T���
��4y}}y�Ty}���T��
�T���4�,#Q?`\pnZt�������ҫȧ����P�Kgjzx}wy\O������������~������#��7�@�T��K��T 
��t��t��t�4�
���4:
�T��
��+y}���4j
�����4��y}}y�Ty}���4��
�4��4 
��
����`�$���$`����$���`�$���
���$���$�����$`����$�<���Tg
�#Z�k�=�=�k��#��#�kZ�=�=Z�k�#<�#��k�=�=�kZ�#��#�k��=�=��k�#i
���]�������&�&�
�����
�&�&�������&�&�������&�&�k�K#
���g�2%�������'�'�%%������
�:�:�!8#
��t��
 ���������%��5�����6�&��{��S�j�����������jQ��h�[�=���<�<���=�>���
��>Kw��P
��^�C�T����������}�s�@��sk�iij}ss��t�v
j�t�� ��
��������}�s������TӸ��Kw������~�s����sj�iik}ss@@st��j�t�����TC^OG�G�O��T����s�v
j�s�@t���E��������� @w�K�������sj�iij~st��s�v
k�s�@s���������TC�^���Ǹ��T����s����������� @��K�T��@��sj�iij}tt�����T�
��
�T�����tj�iij}tsA@s�v
j�t�� t������ �W
��@��j{�����������t��,Q��a!���� �K��t�k�v��������������������q���C�t���
�����
e
���t�����
�������ԛ
��������4���
���*
�<���<�<���
��<+��!y}|z��
|���R�����T��|y��.}�|�y�Mx|��z������������p����������������
��������4�Hhnzh�Thn����h�T��T�hS�\��V`��f��y~���5���V``V�V��5�������`V���R�L����'�HMoZd��9��9�dM�H�''��e
�L(
��$�4���A
�4�u
��v��߈���
���/J�7�I[^_[Z_~}�yhn����������{�x�(���H���Z�f���7p\XT���H�aG��-���w��h�h�i�w�V�Q�Z:#v���z]��l���`���L{�l��{��,�+������\�^���˒�����1
��t�4C
��FKk@r
�������C��������N�.E���Ti����C�������k�h����T�������$�T�$������?���L������L���?�'���0�cGv=<���
v�c��0;���'�d�quuq�--��]
��������L��a������a��Lv�trr�t�v��L��a������`��L�������v���$�T�$���]�D�'�#�5�'���0�cGv=<�#��7���quuq�-.��]
���S������v-�y����U*�PN�O���_��Z~w�rsr�s�w��H�7�*�V3�ziU{������Q��������g�
�e��g�
�������S����������A��:�N�T����~�=�����L��=�&��0�����E��rA�������u�X��������������������5y}|y��
}���R����|y�R��
~�|�y�Mx|��z�]�����������p����������k�o�u`�\\`qbu����ud�[�dd��s�P
���������u����z``K�4K++�4�4�-�3���������������������������V�������
+*���������������Q�Q���������������듔����V�V�������������������������땓�����4�L�5�5���4K� �
�������4��
�˫��4�4��˫����
�����
�4�������������4����T�t��
�T�t��
�T�t���4�������4��K�
���
�G���t��������4���
������t�K�
���
�G�������q
��q
�bt��������.���"&��F�t8�t�+�
�
��������������+K�
�
Qc-b.T5���M�K����Tz�|������������sRrQnS�SL0��t8�t��������ĤŨ��������Ty�}���v�0����%�������%�����_��I�b�	\�;COLD|yz|�r�����s�{���������A��0����������%����e
P
�T�%�K�i�``�i��K��%�,����Q�Q����,����g
��
�/�����g
��
�/������
�a����r��z�y��z�yrr�b�r�:�9�r�������������
�:�9�k��
�l����r��:�9�����������:�9rr�b�r�z�y�
�z�y�)��
�����������4�T��������T@��������y�xxy�}�����||�g
�T�4�4r�d��Tr
��4g
�T�4�4���f�TF������4�T��������TB
|�|����}���������������� ��
��
�����p��Q�EEQQEE�Q����Q�EEQQEE�Q������g
�O����H���
�`�E��{l^@l�g
����,�������������h����� �v��
��4�
�4�
��&���Q�)�WW���X�g��3�
UGQ�� {y|ss^������
����� ��������
���
�������� ��/�����
�����T�����
�
�����
����1�4����=�����
1����i
�������
����
����
�����
��m����}
����������������������t����������������������������2o`gfbn��������h������.���������/�>�p�����������+�>�������|����R�i���������/8�C�����������rb�������{Zja_q���������V �O���m�|������
�P�C�������������4��4�T%V``V��
����L
�t�e�����P
����
���������T������
�����
�h���P
�
���T��T��T��T����
no��q�q�on��
�������������T�����f������t//tq�:�v++��������n�+�*�m�����m�*�+�n������3�3�V����y��p�p��v��-�����)m�v�v����
����
��>��{
����ERQDEQ��c
��ERQDEQ������QE��9���}��,����~��������������
�q������������
2s�r�q�t�-��}�}�N}�}�~Z�T�Yp�r�r~�������n��
pw�����������e�f�c~r�r�q�/s~��|~�M}�~���,s�o�p�pndmfne�����n�
 �s�����������
�������-}�����N����������������1��������������������k�m�o��������/�����������
`
��
>�a�����
B`
���
�aN����t������y���������6��$�7m��F��
�����d��I�.�3�W�W��-
��hn����
��fo1\��s�\ko��{�y�xx�<^��
�
�����U/�Sk��W���?Ÿ��������j�-����@�	�
+6�	����OG��o���
�	��D�ɝ��·�l��Z'�#ik}ts')��2OKebh`i_��mdG1dq��h�����W���m��]��a�"W����Y����������������
V��F�� �����e��
�G�.�3�O�׈����-
7�hn����
��GNOH���	�6�
�	t@�K̬�-*�o�s�r��^��?<kO����篞������
�O���Y�	O�x�x�y�t�R]׈s�sv�k�c\k}\vsO����1f��O��z�k������O��~�r�������v�d�����O����J��.�eY�$�n:mo��O�h������q�1�d�_�`�c�Jl�2�)t��}�����Ǐ���y�m��D׈��
�	���83�������v���b��@�K�M�>����������M�>�K���R�4�)�<�5M��n����ɿ�<�5�)�4�RP����
���p�]����������o �u���d�r����
�T�������~ϧ\
�ԕ�T�3���3���~ϧ�4���
����J�������{��{���{������J�{�J�� IYU:��=Y��Ͽ��ڼWG��� ��j�8Ke`bz�|�vw��{���	�̋�{&������,�(�i�"���z ���
�����4�t�4��
�T,
L
�T�4���8��0�����Q�E�EQQEE�Q������0�8.�(�y{���������������w�Ai
����
��
t���
��X�Ti�TQ��g
��B
�4�D�D� � G
��U� � �D�D��
�����t����
���*
��^�Gof��������Tp
��^�Go�
��& ���
�������8�^�!�Y������1���/���)���Yb���1��+���3
���X
��]
+��V``V��R�z�f��|�X�m�}�[�YKKkK+++K+>��7��+�++k��˙����������̚�z�f�R����[�
�/��`����������������������������������o��������������������������b���������������������������t��������������������������@��������������������������������������������������������������������������v�'�T�_Gq���������z�y������Y�w�j�����o�`�)I��b`�__`�b�)�`~oD�W�~jgw^S�X�_�~|~~t�jn~@t^�o�Y��Y�k��|�P��/�"���`�c}�{q��_�'�T�v�Q
���y�y�����t  ���
�����
�?ApDU8��8D��p�?�6
�\����x��T�T�z�{{z�~�T�T�K
���T���T���������������
�1� ��!���8�� 2 �Z���Z���.n8��2����Y\uZQ m{���������r�������^�-Ʒ֫Ϧ����� ��[�����������@�{�wx^�^]U�p�[�c��\��ˀ�t�� ���������b�de�e�	����@�$fb%� <l6fGW���G4���� 9�<:]ua\Q ,�2�������n��������{����
t���������Z�w�R�Q�S��qk�lN2�IUph��s�J��&�J}�r����I���m�{�j�l�kā�u�v������gE{|jZvkSr^kPxOH.�7�6�N�P�T�>�a�a�>"�i�p�ul��e��Ǟ����ë�����ѯ�����
��
�������X�����4*
���(�����3��&���
�����
���&�;�*2�26�;�*���������qX�sIm�[FHN��M�o����;�ot�p��л�ͩ�������������&�o�x�tt_�Jdw�r�y��0�A���y������u���{�&A�y���������  �v�(T��QrLyJ�γ�ʣ�MfEpB}�P7�.�G�$�%�Fr�r�s�������3�Xo[{TO��(�QV�Y�`������1���(m�pn�nvw��w���.�"�4��X�+pr��q/�#�>V�K�����?�����ʹ�ķ�����������S��p.���v�/����n�������������������Q���11��'�A������<������*
�<���<x��p����%�����������j]^��h�Y��E�֊�ׅ�B�
�����������?��G��ߩϼ���qٵ�˟�'(���͔��͂z���'��w�!q=�w�U�G7���HJ�?x�s�]C$�8rw�s�����p�����+�q���������������������������i�������������������������^�������������������������a�������������������������r������������������������ʆ������������������ŕ������������������������ �v��T���T���T��T�$�T�4���\+�T�
��/�i
�)����������*
��l
@Z
�����@�G�t���t��
���
������ ��������V��
��Tn���z�i.�]�,�+�+�,�]�i�����{{���}�zy�j�p����n�������j��r����������������y��'�����������'������{{�~�{y�#j�o����i�c�c���i��q��#���������������4���
�����4�4��������������4��@�
���
��G���2�t�1�v���������~z��1�v�F�4������Y���tH�A��AHZEt�Y���r�tp��g��
���
�2
����
�4�T��t��t]
�Tg�E�u�F�F�6����!�1��=۴�����n���_�F�(���
�R�D������\�����������������\����D����
��V���T����$�4�[
�
�.���G�^������S������S�����G�^�J�(��@�t�w�T�3�f������V``V}�~���d�3�f�T�w�@�t�(�E�Q��T�!���
�T�e
`�����������w�r��P���N����x�y�p�r��NV[�P��w�r�q�q�yx����y�p�r�r�ww�r[�P�N�r�p�yxxy�p�r��N�P[r�ww�r�r�p�y����xy�p�r�r�w���P[V�N�r�p�y�x�����N���P�r�w������������}�����������������P�NV������������V�N�P�����������x��,���4���.����o����U
w�t��FPPF���s�\k�{o��y�xx�>\��V�?��Ck������������������������w���k+�+JL����OG����
�	��
������=��3��`�?.Qm\ibgbjnG5[��ho��������fu�e�l��Y�������=� ��	� �,���.�G�c��4���n8`��X�C�>��[�B��
n������a�tĹ�����o8i�x���������FP��������v8�+��֫ঽ�t��t�t�u�V�]�]B��1�����������
o8��[G�ng�i�m��Q`�?��3�4�=_�`�b�
��
�	�� ��	� �=�a�c�fn��}�|}K�K�Y�X���S��#�L���n8�������
�
���4���.����B
�`�K����P�V��?�Ck���1�B�]�]�V�v�u�u�t����������+��������`��PF���`�������xi�������P��ta�������
�?����M���Q��YK�K}|��}�Pf�c�a��=� �	�� ��	�
��
�b`�_�=4��3��?`�Q�m�i�g�`�n�G[����
��
��ʰ�����
���.�G�c��4���B
��t���ZB�
��xx��yatRt]ss��vikcx\j_��q����FPPFGO����LJ+�+k����������������������ϰ�k�p�C��>�[���������H�������k�f�u�f������
���h��[5Gjnbgbi\m.Q�?`��3��<������
��	�
�� �	�� �p�=������ϰ������ˠ�������S���L���������H���
���Q�Q���{zH��
00��
����0������,
��{zz�{�Q�Q�����
� 
���
����X���00�����{�zXz{��0�����������Q�Q�������Q�Q���N�����0��{z��� 
�����������00{���Q�Q��p���Q�Q��
�������,
������{z�����
���������P�������00��
�������M
�Q�Q��q���Q�Q�,
��{z�����
�����%�������������Q�4�.���������&����E��݂���������v����'�����*
�<���<�<���
��<+�'����������������~��'���������������|iyz���r|���������x|��~t��}�uz��������������������������~�}����t���yzr����j����hv�������������~|�����'����{���|����������������~�oz|������������'���������r}s�pw�h����������������������jh�y�~�|��������������������}}��|x}�o���w������u����x�����������z�����p���}�o�~�v���q�y���v�}��}�{�o�����������y�~�t�����c�����u����������������y�u�u~�������x�����������r���}�������|�~���g���w������������ɛ����������|����������������c���������x|�����������������������|����������������������������������v���������������'݀���������������t���|�������$���|����~����������������d����������+������|������~��������v���r����y��������s~�݇�����uw�}�{�~|�G�����|��}}x�z���ut�����������������l��������݇�������|���������~���|�r�������������������������k��������|��������������������'�����|}�����y����������������������~���������z�{�������|������}�{����x����|�����sv��~�v�z�y�z�z����������y���������'���7�����������������������������������������������������������}�r~�����������w�������������������������w������������/*�G�s �k�i��n
��8��"�W��=�=s�v
j�t����
�>�>��G��ww�|�&xj�U��t���=�����������N,�B[
��Q�?��F������������������
��������������
�������������������t��{���t�q��������z�4��~����
�z������������v��
�x
��
�����������4�4B
���
�4�4�t�
���t�������X
����S
�{e
�w�$�$����
�Tx
�Tqt{s��t�o�y�$�$���������$�$��������t�q�T5
�T�p
�$�$����������
y�o�t�s�{tq�T/�T���
���������$�$�K
�T0
�T�
�$�$��������)�
����W�n�������|`_�]�#�v����:��[���������vV��i���\�\��i��V��v�6�*�4���4��6���e�T�a�
��u܎���v#6�]_��`�u�uu0n1W@��^�;������e ��U�U`�4�U�5�T���T��T�T`�4�S�2�SB�����zyr�rrr��y�b�cy���������j��d�M
�d�j���������y��d�d�y�sq�S�Umtvw�jo�XV``VX�o�jvwt�nrr��yB�d�d�k������y��b�c�y�rr��U�n�T��d�d�UA�?<AkST3��«���n�U��b�c,��UB�>�?BnUU�'�&UVlA?>�C�T�d�dU��m��ի���3STk@<�?�B�U�b�cT��m�,��Ԩ���'�&������)�����J��,�>��������
KQtd_�O>�K��j�
}�|�}�,D!�/�G����
 ���
�������#�����
�#�����@�*�!�
�!��@���i����#��#f�l���A�\���4�v��4����4��4��3�T�3���o@�T�M��K���"��������~�x��������������F��͇�������������F���6)�-1?pWSRWn?�=�%�(�EU��m�þ����������B��B�������_X�S-(mU6�EF(�%�=�?�VX��p�O�������򎬇������������F������������˞���������y��\�&sqb]�NE��N��e����������wd��G�&NS6�}dNDwO�]b��qNñ����џ���s��Se&�G�F�������������������\}�w~vt���:�4+q����������������4�����C�K�t������ې������E����,��
����� ��aV�����4dYztd���P\�4VAlff�,�,fflAV�4<
�����:�\���i�������?��������fflAV������4M
�4��4������4�0M
�4������������������|�+�f�L�����dU�S�55�T�T�d�.�.�������Ġ���
�.�.|�����������|�����e�WT6LL6UV��e����[�o���!���"��m\�������������
����B)�%�h�;�=�h&�)�C����M��e��0���0���������
�����������4\���
�4����4<
��A
�4��{}������~�bx����4��T�
���
�T�G���k�m�e������eB�V�4V``V��Te
P
�� ��
�&
�P
�T��������
�w�Vn���5�!Jt�4C
��
7
�F
����nt�4C
��
7
�F
�T�
��
7
�F
�����'��)�����������h��	�$�J��7�_�H����,�� �� �����`djXg]�S��ˈScfzheb��pR3� ^��v������" O���m��(�;�.?GdFj�P�������yi7�vo�My�y�y����4�
�������(!���?�������:�:: @(��t���
�T�
�@��
�Tz�|���>
�������$����@1
�i���{p�k�g�G�R�[��"�.�_�_�u��š�����ȟ���mN��g�G�&��߅���������Ȃ�������A�P�_��AT�e�A�a6226^%�O�L�J�n�p�s�����o�s�x�Z�WS]{`lcmcbnXzyY\�a\^��cb�h�n�n�p�s���z�f�%�_w�h�Y�+�W�~������������ cv�͉��Β���������������������И���������������1�5��h���v�9��U�!݉�}�t�{�D���$�<�T�;�J�Y�Y�b�ll��|����ԡǩ������������������+�}������������������������������������y�L�J�G��a�7�5�����t�|�m�`�P���v���G#�?}Z�hzdqcwuvltlsj{h�xPK�GQP��Ob�k�t�l�{·�}����y����ُ���������������ˌ��|n�a`�Z�U���TS�R{S��-�de�h}~��~�3U��������:
�@�4
u
�R
 ���`
�����
���4������y}}y��y}���T��������}y�T����
�����
�5���X
��]
��g@�
 &e�e��O ������ �.�����Z�Z�{�zz{������{zz�{��Z�Z�����
�����������R�%
���O�XO�X�XO�XO�X�X�X��r�6�%
�v�2�%
�������	
��>
�
����������W�W������2�����
����g
��5
�T�4g[wrr��Z�ZTT�<D��Aٕ���!���
��!���
�ف����1�;�������)�)�����P��P
�+�<���<��Q��������̙������r��ԋ����ѭVLE^"t*9x�I��&�O�q�=���b�}�%�B�VH�\�f�z���w�}�i�~�w{�z� �Y�
��n�L������U�i�w��<�u��8=��q^�E�i�{PjPn]v�Ӏ��
���)�9��
�(�(�����N����K�‚��������s��Ӌ����ЬWMF_#t+:x�I��$�M�o�;���`�z�$�?�TH�]�f�{���x�}�i�~�x{�z�!�Y���l�J�������S�f�u���:�s��9>��p_�C�i�v9U:j\�i�C���eM�#&�nY�A� �������,�Ó�m�����x�wr��� ��.������f�f�������F�f���������H����4 z��e�����`�c�����`�c���#�NW��[�S���9�Z��)���)�)���)�;�����7����e�e�f�e�e�f�e�e�f�e�e�)���4������
������
�������{r|�sv>��(���T�+����J��~�f�f��~�J�J��~�f�f��~�J�����������K�
�
�����g
�5
��/{i
����W�Ԃ
�����W��~
�����������
�T�T�{z�4�T�T��
�������������T�T���
�T�T�
 m�
������F8�4�
����������
�����X
��l
@�
�@w�W�T�
�~
�K��W�T�
�@w�W��~
��t�0��mjingr�;��<��7�
M7#?����#��7�7��<��:�f�i�m����
���B�4�@ V7)0��[�/��1��/�^�/�������/��1��0������6���;�$�����p��#��s�����E��AA*,�?���������m��6�"�mp�F=(G`���$����.�����������ƣ�����0�����������п�����
����D�&�l&�y�P�������������sj�iel{pp�������������m��o��������������y��,�,�yr�rUg[giyx�tq]�u�m���~~���������~~����mu�]qt�yxgi[gUr�r�y�,�,�V�����������o�m���������������pp{lei�j�t���t�������W
�m�
�b��
G�T�TG�@�u�^�9v:p%"M$�%�M�����ڑ�����������h�i���G��G�T�TG��T�����&�&���@��;�$y����z������%��:�@������b���
���%��������%�����
��v�������
�T������D�d�d���D��WX��YV�_lw}v~v��*���A���d���D����������y����o�6��$�7���������	�^���~������ )�?�c������w�r���vy~x��]�͈}�|�������������*�Y���v�v�������������������������T�����
p{���3
+�T�
���T�A
��\���
��<
�T���
�T+�
��\+�T���T+�
��\+�T���T+�
 m �4���
��X�vv�uuv��v��HNNHHN��)
��	�	���	�	�����������1��j��
��j�/������
������������������������������eU������>
���k�)���������$��1
��
�����������
����
��4<
�4�����T�
��
�T�GK���4�������i��m�e��,�,���~���\��-���4�:����4� �#��x�:�4����t�T���.F�
��pF�
F
�4KqHaZxuuvwtD6O'���x��O�D�w�u�x�a�q���\�_��I�I�_��\������D�������D��$�2�?��?� � nzykjs�t�z{z�tsj�m�y�}�z{�J�l�Q��e��űťž�̛������������{�������y�n�������׭������
�0���|�z���T�|�����������������������T`>
�t���7
`�Tz�|��)��t������������������������������������t��F
�T�G��t����t�
�)�������4z}|y�t����T�
��ty}��������������������������������
������b
������t�T�4���T����N�[c�����G�=B�^�60�A�Q�EEQQE�AK����u��I7#e  #��7up�jj�_�p�B:��
ܾ�ئ�_�������Wc��[�|��a�
��m��
��w�����������������7�E�p��{
��m��;�4�U��3������ua�[�
�RҢ�����&�{
�&������
�R�D[apdu������-
���U�;�4�mp��h�]�@��@�h���֦������
���t��
�t�����������K�}��������������
K��Q��$�4�[
�
����(��@�t�w�T�3�f�����V``V}�~���d�3�f�T�w�@�t�(�E�Q��T�!���
�T��)���T��T��T���
K����5!�����
�K���h���h��5
�t��
�T�Q���
���
��_
����4��n�hhnnh�4��n�hhnnh�:�B�p����
��צ������g
���U
��k�t��E�Q������9��
���w
!�4���4>�Ti�T(
�t�t�T1
�Ti���T1
�Ti�����9����9
�������t"��!
���N
���T�|�zKz||zKz�|����������I���T�|�zKz||zKz�|�����������|�zKz||zKz�|����������6F
����^P
�
��@g
�5
��/�i
���������
��� �����U��t"��!
���6D>
�����^�
��k<
�TA
���������K�
�+�K�
���
�G+���

T�G���E���g
���p�\�T�
�����/�i
�)����������������������>
G�����������W�W���������2�����G��4��
�t�t���T������1��5
��4hZwrr���Z�ZrrwZh�4�
��!���"�"��
��
�"��
�Ti
���������
�4��
��4�����4����
�t�t�����T����t�������k�}�����4��4�����
k���Q�)���T��k��k����������������t�K�����
+�4Kk�4�4�T�t+kk�T�k���Ts��Ts��kk�T�k���T�t�4�4Kk��4�
F������t����ˋ�� �v���
�����|g�>DR������������T��T��˫k�T�Tk��tk��K���h�@�@�h������T�T�����Tp�����p�q�����q����4 ����
���p��������h
�����
�� ��z��Z��4�
�����
���k
��
�����
���k
��z��Z����
��
���!�Z���tL�L���A�Z���4K
�K
���z�����t���k
�
�����
���z�������
YY�������������
�����������Y�
���������L���������K
�)�d
��{�����
����|z�����X
��]
��g��4KGf�g
��0
�K�����
�)��+�TK���x
����
�^�4����Z
�T���]
�Tgk��F
��G�T��Ԁ
`�t���4+V�`�@�Ӷ����+�r
������S
��
�>
n
��4��Ԁ
�T�
��q��]
��g���
����4���������d�_gg_��
�d�4����
�T�
���G�T�T���[
�r
�������
��E�Q��������9 �v�
�
����ԫ��� �����
�������T���T��Y��������w����N�������T��t���"�R�DEQRDE�Q��������bB�T�TB����Q�EhE�Q���X�x�C�3p
3�C�Bc
���B��T��
���
���b�&��'&��e
p����e
P
� 
��@*�j{�4���a����,���t���
�����{z�4�����
���t�C��8�qb�b�b�{�y{x�{��������������K�  ����t�4��
�4�t����_��_�4���\���<�������-��7����������������ʗ��7��-�t�D�&c�+�������z�i��0&H.��0,�-##�s&�&�2iGz@@R�Q�T+�c��&����&����t������������
� ��������x
P
�tV``V��
V`���T�^
�T��
�T��T�
�4�
��&���Q�)�����������F������|�~������aiEjV��ul�������������Ѭ������o���70 XDQ������^
���
�4���7������mG�G�T�4�}
���
��&���������������������
�T�n�a��x�j�i�gx�i j(C��(�j��g�j�i�xh�i�5��'��=�=�'��5����G8
m�T�i
�n���5Y�'��=�=�'��5Y�i�h��������������C ��i�x������������8
�����
�Tg
��
�0
���T8
�)��TK���4�T��T������T:
�T�Tx�
�T�T4
��[�T�T��T�T�����KG����xP�
��
���x��
���
���y�y����
����p<�
Z��Q
�)����
��������������������I
����t�+�����t�
�������I
���4��!���+�������
�������I
��������r@I
��������0��I
��������I
���p%I
���0�0
����+�����t�
��$��������
��h������
�������q��������^��jM�P�di��oo�� '��.��<WN�����2���XV�u������
������^v
~\�b�u�D
���
��
^�z�xvu�z~�L������^�?
ޠ����������˜�0���������������$]�U�M��'����T�6���"W�
N�Q��(���Y��cjM�P�im��p�P~�~�~�����+�����r������+�UQ��������t�b�3���L�?0X�3>���X�������
�Q����v
\�b�u�D
�J�
���
�zxvu�z�L����J����?
����� ���s����
��]R�T1
�T�*�)�\�&���������Y��
�f�f��f�f���������z�M�{�y��z�	���z�y���z�������	�%��
��@��tJ�j��Z�!�!�3�!�"��
�
��$y�f�+�/���Y������
���kz�X�,���Hn���|�}���������������1��d�t���Z\�I����<P��W�3�֩Ó��W�W���}�O�����u�[�}z�y�yy}p~�u�[��BO�}a�`���5��_��q�������U���U������������5���������t��y�����w��{�z�������q~}m�nn��w����m�r�������������� ��
������������������4R�t�����������~�w�~������tT
�t�t?�t����t��t�t6
��������T���T����
�
�
��V``V�V`�����
`V���
D�M�j��e!_�NPZ|UzXr���Ĭ����D�M�j���RjdMD!�5�
�d�R��쿣�3��>���ێ��Ĭ��� ��TPv�4�T��T��T���T��T{��K����=b����u�t���5����m�U����z�x�w�y�������y�sq�ggK�g�������y�w�x�z{����T��m��Ө���'�&�������h�~�z�����UB�>>CnUU�'�&TUmC>>�C�T���z�~�{���������k������y���������
7�5��������u�+�=������
�T������Tg
K���%.�Khnnh��<��K�T/��i
���v�P�����K�t/�
�����o�h��honh����h��n���
���������;�m�g�<��&S�3������r�<��
����;�|��#����&�%6Nkj�k
�����hW�
x�}�p�������;�F�&���<U�3������r�<��
�Y�;�|��$����&�%6Nli�k
�����hW�
y�|�p���)������
�������9�I�v]�Y��fh{os���je�V�]]��n���������������w� �v�v���K�u�Kp��J�Q��T*Fhl��tn����ݖݘ����Ǝ������q�DA�������5�%!*Q���TFhulstnl_�a99��:��P���p���������������~�݀������������*�������P���k�9�o������������k��թ������������m��
p�
����[
�S����D
�
�����D��
�D�U
���D�$�$�D����m����8������������?�C�I������9��
�.�.��9�~���������`�n��
���[
AE��N����������������^�
��U
�������T��T����%�� 7;L9\Xpq�T��T��g
��5
���9�������������$�����9 �
���
�
#���
�������4�����@n
������������������T+}��~|��������C�3p
k�n�r�]J'�V��{k�e�{��������������o�h���c-��#���<���/���&��|�~���T+���������������� �t`�`����
�t���{�y��S;����RQPIOD�w�������t���{���K���������������6��������K��������t�������������������q����v�M�����������n�;��<����-��������=��v��v�k�h�F�����8����������
�!�!�f
�Z�Z�3�Z�Z�g�%�E
������E
���! 
��������
�a�!�f
%��3������3��g�Z�Z�E
�� 
Z��������!�f
������f
%�3�Z�Z�g�Z�Z�E
���! 
Z�����������f
�Z�Z�3���g������g�%�E
��X 
�����F�I�C�������?�6��I�Y����(�����u���C�� �XV�Y���x��\���������b��6��6�������S�������*
P���e�S�GQ���G��z�5�:�5��'��D���N��������5���T�T��(���TK��K�T���(�Tn
��4R��~����~���'1�
�A3�Zp��T4��
�T�7׷���
b
,�9�_�7�T5
��2
�T��Z��A�1�
�����������~���'��~�������������Q�1���
������
�Q�1�.�����
ꗐ������v@�T�i
���T�����t���2
�@�$��k���\�����9
��
���e�
���
�
���y�y���Q
�a
�U�)
����������_
���T_
���T_
�������_
�T_
�T_
��s������s����
G��-�������
���|�a�9�9�a�z�~���������z����������������
���|�3���3�z�}���������z�9�9������S e
���*
�<���<�<���
��<+�����������������w���������������������vttvw���_������������������������������+������3���������s�����E
�������Z���@@��@�@֋������Y�9�ZYh��YY�9�Z������@�@��@@���Z݋���� Z���������
������
�� ���t
���
��
�tR��1
���
�~���������*
��Q������
���9����{���s�Y�sn��{x�p�ut��}��T���������4�T���~�������T7��T������������
���������}���4�T��������Tru|u��t�p�x���n��������������u�r�T���}�yZ�n��n�A���f
�����3���g�g�g�g�g�g�%�E
���� �������������(�@WWS�+���������}����������}���������������������F�������������������簰ɋ�f�,�,�f�Mff���� ����z������z�����q{tt������z{����
�����f
%�3������
x�����������t�
�t���� ��4��4�����4���G{�z�����s�{���4�O!mFNB9x�*����}�}~��������������5�W�]������4����������x����E
�G�� x���������t��T�������c��������
���##
�y����u�s�su~u��v�q�x��Tz�����������T��������QO�y�7����}���T�x�vvx�z��T}x�q�vu��~����������O������z��T��x�q�v�u�~us�s�u���������T��������T�t:
�T,�T[�T��}ys���x���E�F���v��d�y�������������Ds4�>�$�0K��������������������_�������|�������������������h�)�!�<��z���������3��������������5�#�����N��2)(
�$��h�e�kI��
�z�|�������P���諌����������j�j�n��W��{����2�v|���#R�6�'�I�2|���6
�S��k�����G�������������������������\���L�9�x�s,'�$�*��
�*$�P�*��
���[��f�����d�L��"�������*�
 ���������������&�����������_��DS�z|}y�H�ec�$�,�L���t1�HD�U�
\+�!W)�E� ���������������$���z����� �~j�Cy�}��7�C�h��&�5�`���v�8�:�$�:�����R�?��v�k��}7�S��(
�z�|��%� �e@��1(
%$�?�n�P�D���
�������Q�]�(�E�5�U������W������������+�M�3�T�)�3�w��'���T�<�*�|�v���;�<�#����������6
�S���7��}�y�k��א�����������S���S�8x_uaz`{�{�s��k�=�����V��������������j��
#$��6�
$$������@��v�t�T�
�i�T�i���{�������_�,1�!��T����!�1������N�H�����'�	���)$�t�
�t(
�$�t�T���;7�T��6
�S���
�����N�H����v�����������������@���3���uk����1��������@����������:���6���zi����
�4R�G���%i��쎔����������|~�}�.���)�����|�}~�}�*����1����~�|���������������1
�"���C1
�d�4��}�����3������;���e�:��}�����3������8���i�*���O�J�K��.��J�?�7�����1�.��.K��z�J�1�Z����.S��cb��b���.K���jj�l��h�M�8�����ʟgk�������������&w�l`�����l�KK�\��������.���������K�.������H̢����W/�&�����~��k���S�ڡ#���ڨ�ZD�p�A���4�����I���
�����l�������,�,���}��������V``V��T����V`�������������,�,���}��l�l�������p�8V`������V``V��T����t�
�T�
�T�
 ����������$�����+�����)���f������}�����]�|�
��z
�@�\
 ����$�����������+��)���f�1���z
�\
2����}�����]�@�|�
�+
�t�)�f���R��8����8����T8�T����8���*�+
�kR��8��7�t��)�f�4�R�T8�T7�T�TR�8�7�T�TR��8��*���
����iw�q
�s�j
�)�f��Оm�a�
����"�
�q
�j
��)�f�d���
��� ���4�gnohgo�������H�4�R��5
�/��0
���3�#�������������؋�G�t�
`aM�PQ�Oddlli`g]_Q+�f�j�ooj�h�o�����v�uf��\�#�������ͥ�����ȅ֤�������������������������� ������T�n�hgoogh�n���4��-
���
���
���
����)�������|�m���������x�r���z�e�`�I�3��}�y?z�#�\f�LuOvh�i�moh�j�o������Q�]�`�l�d�O�Q�P�M�a��t��G��m�q��������������v�i���� ���Ǿ������n�4���^��ːΆ—̀Ə����n�԰�+�}j�{x������t�������zj�1�"��L��������zii����|E�;�;��]SH��v|~�}������������I��q�z��x���������c������������y�pst}qv�5H��ίp��}��������������Gq�|�z���{t��������}��yp�jip~rx}x�od�d�n�yr��~������������������W�����vu�yi�0i�z���������x�`6�0w7~Q[`R�|���������R�[�~�wߋ�������ƻ�ő��������|�ą�`�P�8�05�����]A�]��|�s�|�z�|����W��W��[�
d�m}yrxq~jiq��y}�����������������~r��x�nd��I��mpr|rv|������������{������������������H�� ���X�?�����A���܅w��l�D���z�ك��{�ц����Ԩ�_���~�q||�||��|����������f�|�mm|t^]��Z����'��X��"��-�I���bgiwknv����������v����}�������������(]�j�vg�rxhkl��m[2�+�*�m�������xf��w�j]�Y��n�w���w�y�{hsfy\\h��qx�����A������������zi��r�eV$�G4]�t������������~��%]~smn}���f������t]�f�c�����q�y�J�>���L�N��M�M�N�w�K=�KQx<r�����������<�Q؃v�L�N��M�M�N���Lؓ�Ş�������z�G��D��!�M�L�M�.�E�Z����
�#�������x��rh�]^hzirxr�dV�CV�d�qi��z��������������0�nwx}y����������0�g�s�|r��������T�����v��������7���y�g��}������}�~�5����������T�~�~�����������������K����������}��g|ut~���$zm������v��s�����������������������:�������/
�s��s�A����~�T��z�}xp�M������������X��������l������������L��y{���q�������������-�g�������p������������Ln}������t�������"�V������O������w�( ����[�,���x���x���M����
��y�h�>�GC�TU{�x�%��%�����%��%���T��D即���#}�f���
������؋����›���%��%�����%x�%{�T��G�>�h������
��
˳�&�����~��������'+�����������'���}���������~������~�����������������}���}����������3���3	+�t�4��b��4�t�D�����8��0���9�m�i���%�i����f��������������+�q����U�����3���������@�������
��
��n�D�D�n�n�D�D�n�n�D�D�n�n�D�D�n��.�b�XXbbXX�b��������p����c��}�z�p�p�q�h�&��������c&}hzqppppqzh}c&���������&h�q�p�p�z�}�c��������������������������
�����o�1�1����!�"�!!"�!$���o1111o����!�"�!�!�"!%�����1�1�o������$��������������Z���<� �<��ps
�����7
���7
e
���&�]���&�8�t#�4��#�4-�_�G�_�G��� 
���C���3��u����X���r� ���9�*�Hb=g���h�`�̀�����,�����������ް��5-��"����MM/�8��(x�,��(�9�0�KDz�іɕ�O��T��Om̀ց�Q������\����Y�5����Yy��{�)�)�+�)�j�x�Yh�m��G���{����I�U����s�V�7�=��o�{��vu!� z'f@o&d1��c��a��a�P�E�b�4�"f�|�au�n��O鿦ɯ�˱�n��n��o��I����7�J�!�I������5����.�OB\W�Q���Ħ���dRۛ~��-aOpbK�I�2�C������@�l�U�[������s^�Y�oc�`̄ƃ�~����ƒΑ����~vD�,@a�D�1��"�@�3�b�yЀ�ѐ����l�"����k�"��rbs��Ir�3p�1o�1�]_qew�G�1��(�'�$�:�e�����r�)n�'y�*��ԧ��ӥؘؒ�6��;��2]�z�t�[�u�n�s��� ����P�D�cl|P~_���q��������<����������}�N�x��0�k�<���N�������������/
p�ti"d-����"�`�#�6��9�VѺ�D�����������M����V���"T�A�������K�$�� ��T��h��������~�t�T
� �t~������~�����������h
������������������h�������������������h
����������~������t� ��t���������{�tR� �t������~�������������������򕃘���������t�6
���������������~�����~�t� ?�t~����������������������
qq��P�V�]�]�t��סж�������i�h�h��MD�;ZQuItI[�nt]��F�EQ�Z�-[+@@*e��-�8��;�@�@��4��������������u�vǹ��������ߤ��������������p7ZYCYCq5�(����������������������� �v��
�>����>���>-r�>-��>�j7��)������1����
�;��a�u�a��b�t�a����vz��������yvvzyu�:uz��������yvvzyv���LR]]S�BR�]�ĸ���B�]�S��x�*�.N�Z����wR�]�Ĺ���w��wR�]�Ĺ���w�Ǽ���|���������������C��NG�CCG|pNC���������������!C,��3�1�3,�� ��q�|�]�RS]^R�BR�]�Ĺ�����_���w���η�����}�����|���w����$��䔻k���i��ᦿ���ů��I�7�����J��+��k��t���������}����n~����x����?�����z�}}���}�������������b����;u{�{~(0YP��
�K��S{T�Sm���������������������{qiTAsF�G�K�i���wz�������w0�o�_ew��k�j��	"�˒��l�s���h�z�t���u�|Ц������y(0u"�5��������@B���'��\��ϊ؊����s�q��ٱ������0@��.&7�e�}�|�_��g͗��������������������������|qD|u�n�l�a�K���]�~���������������������d� i��q�qq��u���zw��|�wʎ����ó����^�=~Ş�v�}M�,������7���Qu�p�z�������T�S��(�����p���zKY�N��G����J������ ��b/ѓ��������c�c�t�u���p�4�K�6�gp1���zy�������@���������������������y�r�7�Y�}�{�w�\�������w������x�F�i���������������������s��}��t���x��y������������������������������o�G���qt��
�s�p�^�)X)iz�=J<I�
����ԑ�yʂ����������X�j�eˈP𫐠���{�y�M�9<��I�b�q�u�ҏБ�Z�=�Z�>�F�df�|o�L{1�$�+���#~[G0`SQRn�e*wXjs�I�x�[��Ͽ���^��d�7�,vX�9�<�D�B�c�r�������������~�������������������������}�\{zeugwT�qtmq�F�X�ec_�d���d��y�q�]ʼn���������������m]�n�r╠�����Ĩ�@԰�=�������{������ ����j<5x0�3�%��������������������\�Q�M�������������G���#�K�.�<(�������؃���f�f�f �h�8����z��_��=�K��
�8��^�@��m�K#�2�'(��h�U5���h��KQ�����y�����������%��.�"��/��b��7�������$�:�,M%��s�y���s��vnX������}�|�|�����,����#��/�� 
K���=�{���@��������m�_�X-�P�u�P�ª�����.�M�IJ��T�2��&��&���<�_�]�A�Q�S@�QdXJ*���13SsVQ�~�y�s�"k�=O�B���m�m�Y����������XX��[�J:�3�3�:�J�[�XX���������Y��m���
��)�M���C���K��K�|��|��v�pus�r���dopdad�o��������mn��no�&�{{�xoj�p��h_�hm�nf����������������A�����rk��R���h�������g/Q��Q��I�s���������7�z����������6����ݺ�����Ͱ�H�f�H��́b������������48�T�T:
�t,��[�tR
���4�:
�t,�[�tR
��4������������t���������cM�A�AM[Pc����|�xxW
������w�������/�����g
�T��M�Y��4��
���T@��������/���w��p��{�M
�4��|
�������T�t�t�T�����
��
�4�
���$�D�d�d�D�$��
����|
e
���~��mp�k������`�Yy��u��������ݶ�S�Hk�pf�1H 
��������x�
����������������������������������������H���H��������������������������������-�H���o�{�H����遏�������������+�������������H���H����������������+�����������������H�������������H����-����������������p������m�t������}�%��I3�U�����[���R�����H!f��������������_�����x�x�o�r�iB?z<���������.�"����������t�o��2|���3�������C�������T˳��T-
��hn��4���
��Tg
��5
�T/t0
��g
��
P
i
 �v������@`��g
�t�����A�A�2��A�A���A�A���A�AI�'��t�
�t��2�F�^�wtp�c�s�����������K�c����I��
��>����Z�Y�
�2�d�e�Ҧ��t0
�t���E�
�E�E�#���)�v�����o��}���}�4����u�{���z��u\�
O#���nWv�Z�����h��,�l�t�:�$�4�Zsj{rg�������l��b�1���Xl�dvG�'�b�Q�^���{���y�q�����a|x��|{�j�j���������s�}�����������������.Ӣ�ѡ�?�I��Y–�����K����k�.�#�4�)�s�V���
�1��|��5���G�c�%�1��A���� �X��R�f�
����7��n]Mw]�^�}�����ǟ�x�w�Vo]�
�yt�y�y��������������w�y�B �A��'��!��3EM�M��!�#]��([�B����4��W�t�I��m�@��n���x�Wx�W�t�I�����������W�ȇ���$�r�z����ӎ�l�Q�3��J>�Rq�����_�(�%�v�v��=�=)�G�/����H��{����uA�R�6�=z@k�wl�k�k�w��������l�l�ae��l�j����������{�R��I�7�
��A��5i�f�sg�f�f�s�����h�.�/��g���g�e���������0l�F�
����
mi�E��#�=[�Z\�Z�#�=�E�O��i����������N�����Q�@������Q���������������y��Q��������@�Q�������p������z�E�������������&��}���9�ً���܉���{�H�[�1�����������N����[�G�C��J��ۋz"q*g2E��K�a�"�8�1�&����*����a�/��rwxrr�w�������T�(����v��]����������������*I��0���������������
��
��3����30�H��5
����7
��Tz�|��4#
�5
��
��T�|������������������6
�T��>
�4�#
����T3~~����T��z�wwv�x��T�������4���4O����e����9 �1
�����������d�p���S�F�4�7�z��w8�,�l�����������r�7����R��Z(�x�[��t�s�[{��+��;f�������C�3DK^Fx���u���k��r��l���qv��}�������������T����K�����?�(�&�P�X�+�)#JU�^m�m�m��jg�e�nyiYW�»������ë���P�����7�i���S����պ�ԤÎ�˒r�Spp�o��G��.����B��%���r ����u�`v���t�T�tp��
�TR�4%���Z�d��z�{�	
�	
�IS�4(
���
�k�.�
p�k����T�������t
�t
��
�tR���M���o
����
���6
��~���������*
��Q�)��ۛ��S�%������4��՘Ζ���T��˫�K�T�]�H�A����F-�"�K�
g_�y�z�}>�Q~{{�~؉؇}�zy_�g��K��飳���ܩ�n�_ZZp_bn:�������v�k����bA*t%n�d�ʋ��̫�����4�4���������m�����4��tb�����m�����+�+�4�4k��kL�J�J�l.�d ��
��|{��|�8S"��1�Þ����H�=|}��}�6TV�5�wS�L<JI<{�{�|��4��"U�4�wT�L;KI<{�{�|��3�1VPwcSM;�Nۛ�����0���0VPwcSM:�Oܜ�����-��7O��d����ٛ����T�8���9O��d����ڛ����S�;�@�Ǡ����L�9����"������t��������s
���V``V��V`���H�z�u�|�K�R�Kj��g���
�ů�������ɣ������YPOdq2P2R2QreL]]]L��e3�0�3�a�S�f��ó^U�����hv������n�2�o�����E��������`+s!���j�m�d�f������������J�\������e������܌���
����<������b�d�a��ʵ���֊��ی���
�������������!�z�2v�Ԁ�����������<���r�qo=w5d���:�y��.�����h�O��6���?���)�k��k�k��
�k�k���k�k���k�����������
�������ɲ�~�=�`�U�f�6����@�IV������������`b�����1�N� <��:�M��@�x�i�]�'8��������T���
��}
�T��
�T�mh�n��������������PelnhK���l�eP�����������������������;�T�
elnh����l�e��Z	�P��I�{{�{{{��{��Iy���!�����������
�������~�������������$���~��}}�����#M4m���	eupb[^�d�tQ�E������������T�����������Q�E������r�e�����ĸ� �b���������$�����������0�Y����	�`�	�_��_�	�����fd�egg��h����1���(���'���,��� ���ge�ffg��h�a��C��N��~�W�����������������������������H�y��n�����j�m�����j�m���)�KT��e�]���B�c�=���=�=���=�O����J������i�����!�G�)�e���G�l�G����}���ff>TT=��g��}������}��R����������������I�c�ZYccYZ�c�������c�YZccYZ�c��������\pcdw�y�wx�R�j�.�����j�.�R�����c�o����ͭ�}t���������������qZ�������bZZcbYZc���\�L���
��g�S������VI��m�
0�ܰ�
�.��G�.�����k�.�L�.�k���?�+�����llH�\\H��l����������Z�釧�鏼����������0��
����
�k�cthjz�{�{z�7�L��v�v�K��7�����i�s��ù�Ĩ�w�л�����������Qa�������haahhaai����?�U����l�[�����Ĺ]S��Z Z��+�)�*�*�����MO���v�rqvvq�� 25 �3�����
�+�q�v������������6!M���r�34��2���o��q�v�������*�
����� 
�).����`��`��`�������N�W���{�W�M�}�|�X�L�y�R]^SS]��������������T�T����V�Q�~��ù��ù]S������S]^SS]�����WQ������U�R�����T�T���������t���t���4�''��t�T�T�t����t�T�T�t�T ����7�8��8����a��`��a��a�`��a�^�������M���kl�`���
���8�a�M�a�k�aW�`�a��9�M��9��7���B�a����
���8�M��9��7���B�a����
������H����g��g�[�o�������\���@�\���C�G��%�:`d��h�b�gb�ۏ֯�Ȱ�����������:��%�G��?�G��%�;ad��h�b�gb��N������;��%�G���H ���v���/��}��������7����������
Q��Yr�3F���ZXa��X�x�wx_blk�x�����B�)� K��%Lo�3�B�����J�������w�u~�k�u��x�u�����*�k�?��O�z!x�yxv�z���A��������Y�����
�Ϲ�������[�D�j�m�hl|�{�{������̡���ԡԈ֊���j�8ч�������������5�T������&�9�E��
�Z�$�j����������b������������<���r��������(�B{]�<��6�T�Y�u���Z�|�i�JC^E,g_zsyub��Ֆ�Ӫ������u�^�q�-��1������ݛ���zJ�1jI�1jgT����iԻ���E�Y��}M�F{M��`���@��������]�����~tv��t�z����,�������������������������J�����~����Y�������=U/�0���A����������������q��t��ת��ԛ�����d��z��}��������PPxvtnos�������������������������~���}�m�z����Vz-cObPru[�N��
�S=��)�i�d�<&l��i�X�sŒՍ����0��Z���Z���6�:���3W��4�U��_U�2�6�6�W�B�N����	h[aj6GUv@cLj��^�H�I���,�+�����T��j���k�(�j���j��c�+�,�5�4�+�,mmZZ;�Z�Z��۽����+�,33m���0vH9*��/������o���⩩�+�,�4�4��>4�
��q�{7�$�//�)�9�wh�	���0�m��+�,�5�4�+�,�4�4�,�,n�Z��ܼ���ۋ�Z��,�,�����>�'���l�4�n��,�,�4�4�,�,�4�4�,�,�m�Z�;ZZZZ;�Z���+�,��/�o���-��D��������/�#5>'}���n00nm�,�,�5�4��,�,�4�4�,�,����ۋ�Z�Z�;ZZ�+�,����j���������+��
����J��Ѳ�"�^����������z�}�i�{��ѧ������錐��������z�s�s�^my�z�Svn�n�U{u�u�w���z������~����������������������˜����ڦ���L�vewe��:rnwt]R{���������ϝ��ȹ̯�����\�����j�����t���a�z�������m�|�}�l�~�~�n������h�~�u����������������������N�?�M�a�m�����J�}�����f��g�^�%��l���l�I�%��u��X������Blznxj|Z�6{�&���1�~\�����������N�UL���������ܿ�I��4�����'��6�������k����Z�6nNw���������������������������a���������������t�T�T�T�t��
��
���T��������]
��g�Z
��`�7�7�l�f��,�,�fA�V�4�
�g��K���W�?��t�qE���E���E������4��4�
��������
�
��
��@��
�5
��/�0
�x
���AA�K�
�TV
1�CK�
�TAK�
�TA_�K�
���y}}yKy}����������}y�T9
����;��9
>0����y}}yKy}����������}y�T9
���P��t�t��p����f�e�O�ef�x�x��x�xe�O�effe�O�e������D���D��������8|
 Z������ *�`�7�Q��� �`�6�����w�%�	�Y�4�W%*�%�	�X�4������������j��%����1�������������g�6�`� �Q���7*�`� ����D��4�	�Y�%*�&��4�	�X�%�W���
��T�����#���E�E�#�����\��[^��h��n��T�����^������\������z��.����}��T���N���N���N�����i�Y��T���}|�|||��}�T��Yyi[U��\�`�u�T������������T���������v����
��
�+�
�@��
������8���T�j�M�Q�M�Q�M�Q��W�m�[��F�N�$�l�\��T�T�{z�zzz��{�T�T\vl]X�$�F�N\vl]X�4[�^�v�T�t��
�������������T�t��
���������P�8�j�J�2��R��Q��k����V���o�����8��������>��A�
��,��������'>�&�&��������2�u�����Q�e�����G�W���n�!�e��q=s)b?�ɽV����W��X��/c���������@���o� E`(�������y�k����2@�	�/������@���O�l��m�C����L�����A������A���l�s
�����	e�1<fXEi�o�B(�4�G�#������ɷ���R�M�7�L�M���ģ��[�?�Q�m��k�ȥ����a3N���H��
�F�?���A�G�!�<������/0�U����@Y\@���քd�= @�6��>�������U�*���*j�*�.�N�������������������z����+8��a��{�z�{�a�����Y�%�#������������y�=���<�=���=�<���=�<���<�*����`�`�����`�^������+���LPzlX��1�A�z/�-����6�D�&��@��I�����`�_����4��|�����4���B������
 4���4!�����3�}|��~�j�k�/k;j:/d;�j�k�j�L��`�������*
�`�h��������������u���Y��5�4�Y�\�5�5�\�Z�5�6�\���~� � ���
q�@��-�3���3�T&���k������������������v�vXw��p���D�>��m2W��.�_�Z���8n��������E�� 5<�hL��hL�Q�R�����S�u���'/�����>0����A�g���z���8�(�Ғ��ӑ���P�����0K�C�'�Z�L{o_�u�����O�n�	�ɋ�#��x���W�{��D����ߥ���p������B�dȋ�e�E��)�p��3�����+5�7w�p�	����n�t�T�y
���@
����y
�4��'���
���
��
��
�
��u
����n ���
��t'
�T��
��
K�
��K�
�V
��'�� �t��X�t�@
�X�t��v������&�'�y���&�'�Y����
�
���
�Y�&�'�
�y�&�'�
�b�K�HJj�p�������̃Έ��bi
����������a����ouwr~�������'89�{=�{��mx������������<�*e>����o�kjqpi{������A��R*7}xE�|��}jp�����������]�VY0�-�|�xp���aime{���}��l��d""�p*��}�|bl�������������v��\&�A�}�xf�a�) 
����W������po��"��_m���3���m������������"�������3��s������ٝϞ���¿���������8~���~����}������������~�������h�s�������������������������������׌���������������$���������������������z����������������c������������t�c��^�����������_�������P����������v����������������������������v������������������~���������w�~������������������������������������y������������������f������������{�h�������������������������{�������������������
�����
��Z�~���}}��}}�����}�����������������||{������|������������Z}���������������������������	��z��}���������{���1���0df�}i��t�j�\��KMuTu���z�y�~��������0���0�����&
����
���
��
�
�<���!��!����
�
��!���<�
��jv�����t�
��Ǒ�m����l�����!��4���CP�W�h�Ќnj��������������������������|�vw||r�yI����s7h3^1c:gJlX������������JU>�]�w�������������������D����&���_��n�����������������������r6�Hgd��al�o�r�@���/������K&``m}�"�,���� �����y������������@��}�z�~�|�{@��Ë�����)�������ҧ̞ȭB�O�`������)y)o3h������������m^��Z��x���
���
�:���w
!�4�i��� 1�J�{�z�~�v����������$����$���{�z�~���������������J1��� E�8�)�3��y���������������{�|�|��y�3�8�)E�
���
���1��V�!�4�g����V���Q��G��� ?��3�������������������3A��� H�W���T���!����� �5���������������|x$�5�!���
�~�;������
����~�V��!�4�t���/�����|��h�7��S.1l~gd�`��;�!������������������w�g��vp�h����
�i
�?v��
�x
V�!�4�������m�T�T�T���������
�
���x
�������-
��V���P
����P
����P
�������P������fA�V��
��T���l�f��P��������������z�z�! ���
�P
�����4��4�����r�n<��B@(��vM��z�zy��:�(�(�������! �u�6��B@�!�eDR���Ĩ���nhhRnD�
�����
�x
K����!�4B���f�~����:�;�8��:�;�����
������������5�E}}��o������ۮ���h�J�t����������o�%����]�8%{~y�x�g�(|{��~r�����������x�j�r����������q�O�>99l>SO~~z�z�
���
�x
K����!�4����
�E�Q��y��
����������
����1���������
������������
�%v��
���w
!�4�4��v�����{���v���}�������������J���J������}�X�}�w��}�����v����w�}�Xe}��w�}�J���J���}�w���e�������v����������aʁ��������ӎ���y�L�z�z��y��ӈz�z���|�c���y���u���Y�aa�f�f�6�&������̶Q�HyA~`��D���ޟ������(�����#�P������g�Q+<�3%�!!!�S�|�B��D�����������M�h����ߺ����� ���ђ���O
�.�-�.�-�.p�l����H��s���-�����U���7����s���H�<����J���J���J�?����H��&������U�����r��s����&�l�~�v�����~|�|||��~���v}~rr��r�r�}�������������������������|�"�����������������d� �^)�[O�K�0���-n�p�q�
D:��)�r�J�?�t~���������r�I�F�o�9$�"�%�����9��/����i�ü��I�IR^rdcl�m�k���ԧ��2�*�:�8�)�0��\��pFN[BA�\�Ÿ����g�h�gGDDl)�3��=�
���
0�
���jR��V�V�VT�PQS�yV�V�V�����:��R�j�������V�VyV�TPQ�S�V�x�������V�Vy�Á��•���V�VR��j���h���h�
��@��x�m�����Ł�y��V�V�����j�R���t�t��t��t��F����4��x��P�p�����������������[��p������x�4M����F�q���q�q���q�Iw�w��v���|���yx���*��|��8�����������G�}�A�I��r��w��-�u�����\�?�	�5'���p�����x$�� PY8������4�I�5�K��� �G�3�#���T�1��!����I��%�>�H�G����U����������B�&�����������v\w�ͷ�����- �-������%b�b�d����&���-�JRp�r�v��Qi��u���,������t�~��՗Ӣ�9�������R�M�g������Ĭx�{�}�ާ�EvhrjplJ�- �?�&n	�5d�b�b�I������,��u�e��u�i�`��M�6�f�X�P�����lj�iij��l���PXlf`�M�6`ZiRuL�};�p�omm�o�p�|;�L�R�Z�M�6�`�m�[�������
���[��Ɨ�����M�6���Ġ��|������������}�����������+��v�j�������S��&�z���������z�g�M�Rj�h�e�d9o�I�CAA~CtI�o}d{fxg�j������;��v���+���I������z5�&o�?� ���m�j�hĬ�7�;�j���j�j���j�j���j��j���j��
�0��K����B��H���
��\�O�+�:�������x�O�a_U�TS˄�B����g�f�t�XRweWW�k�!�����:�{�z�{��z�zy"J<%wl�y}jh�w���|�m'�!+\�!�
��ո�ϡ�n���������M�b��������x��������7�������������t�tt�p�o�p��yje�f�{��m������~���	Ǻ������ �i�ii�	yz�yW�uf�^�������
���V]g`[[f��������_\��� ����A���^���N�?�I�`�U�j��f�#�b�'�^��j�T�m���4=yBF$�������3P��:kS43g��߫��ޯG@����pFAw@�UM�M�M�%��O&��i�Wt�LXU�_�o��gBF��b�WR�?�d�/�y����(#�-������:���=�������������;�������������r�a�``��^�_�^�r��ruke�dA~����������R�?��‰“��w�n�mm"�?+��R���������������U`�B��=�j�ȕ����w�S�<;QE>?�F�` �����
� ���R���X�����X�4�! 55 p�q�sa_^U^H��K��ʲ�Jp��w�����������m�����7���ų���u��~�������������������/�/�:�q��������~�i�y�����k�k�����k�k�����k�k��gf��ho�py�p�o�o���������������
�����n�0�
+�(�\f�m�j������ő�¡���������C�B�{������������g�tzl�dg{S������)���������i��k��-���������z�/�R��ɮ٫ސ������q��,�Þ���2=�5�����������q�n���Y�V�L���9+�3��zZ$�;;�#�}�Mwz�V�qzvy^oy�z�z���v�!������UggTUT���¯�¯gT�{��fggTgg������¯gg����UggUTU������gT���ffgUgg��������gg���!��M��m���#�����[��8�I�C�n���y��y������|����������죢����������������������������Ԟ���[�T�I�&���%�7�O
�����~�~��������Tvt�s�r�v����6���1����p�s�����������������Y�M�	�O
���w�p�v~���Tv~t�s�r�v���l�U�Xq�s������������������k�	���%���]�r���������������Kw�x
���ܿ����
���D�&�l&�y�P�����
����>�T
�/
��������Ua
�������
�
���������3�����������^�������bX�k���>��C������_��}�g55�533�3g}cm6ﳽm�v�%f���������~~��O�~~��~�����^���������a��}�g76�7/.�/h~bn1���l�p��.[���Rh�5kuZi/�4o�e������������
^W�f����������������7������������h�7jvWi'�2n�f�������������z�#�z�C�p�i�s�L�2r@;pEVP<Q<m+�,�4�>�;�O�d�l�w�����
�#�>��
��������������������ƭ��
��t��t���������4��������t��t ��t��t�T��������t��t�����e
���7>jVR���H�����������%���HV��j��E�#�#�E�E�
�E�E�#��������H�R>�7�E�#��E�#�#�E�ج�����H�����E�#�#�E�E�#�#�E�E�
�E��?�>�?�
��������	++�	�
+�	��������heXuS�	+�
�
��	þuh����������	��
�	�+�	�
++�	SX��e��������������%���������	�+�
���� ��o�9�˫�4��9��/�ː�/��4��G�j{fj}�^11^�r�t|q�����j�|����$���$�J���|�j�B������G�r�b�rrKK�&�	���������������j�	S��ˤ���r�eG����e�����~�1�~�w�~~�w�~�1��������G
�z�z�����0��v�~���0B��������KR+%+
�~
�T��+u�+������~�w�~10����������G
���4
�v���2
���d���������d��0�
����m���c����Fr@:}77:��@�����ڳm�-�T�0�>�����2���tM�����2�V����3���3V��2Y�&���L����t�������>T�0-����������V�-���
K��K��K��K��K��K��K��K�����T�tY
�T��Y
��TY
�"�6
������������g�n�~��Y
��T��Y
��TY
�"�@6
����
��������H~���������Hf����T
�T��������g�n��p(���������������p�T��<}~�}��������<���4������T�����T������~�}�<��2
���<����p�4�t�p�
��Y�:�YY�%�$�~�~�$�%����Y�Y�:�YZ�$�%�*�*�4�4�o�ol��8�������I�I�������8��o�o�4�4�*�*�%�$����Z������u������*���
������+���
����u�H����d���8�lh�Tw�w�v�������y�m�\����_u����5��������^��/�7���h�Vf�������J�C�2�2C=+�J������V�hX�[�<�*�N?�Y�3�: ������]�#�������"��S����:��Y�3�N���������%��%�I�%���%���%����%�F�%�"�F�%�F�%���"�m�m�m�������%�@�5����z�"�m�m�m�m���F�F�
�V���m��y�j�j�g�wrPE����]�����}��������~���S�u8ӗ������������������)����x�m�6�����
���|u�w�}un]~�'�)�k�p�{�u�~������������������������y���������
����n�k�upto�g�o�>�4���y���}����Ϧ�)�Q���4���
g������y�r�=���7TRyy�t�v��z����3�����������*��������WJ�t�t�x~����8�tA&���ys�j�m�m�}���������������՗����������������
��:
V�x
�������
����������������������������������������d�T���T�-
�5�������P
����������x`�������
����������� � ����ee�pZp� � �������%�$����
� �B�(�(�BP! ������(�'�'�������$�$����
�G�G�������(�G�G�����s�$�$���z�h���l�?��9�����������%�$����
�������������������������_�{����������_�{�������
V��|
��m
%
�G���G�G�G���G�G����EQQE�EQ��������QE����G���-
��
����
��
����%
������
�E�Q�t������
�
���l�T�������^_|_j-Z7BG:?)_�s:y8�C��Xc�cs{~s�y�y�y�y�z�y�o��t��������������������o�����֎�~���@���,=��"��H(�`��dine��|�An��q��������������˗����NJ����ܨ�,����+P�מ���
���M���	q{mv��=�m�
�����RJ������C���w�w���7�c��l�!�w��/|�)q�%�
�Q�X��e�������Y�G���D��������W[���r�����0�I����d��?����q�o��v|wv���N��X��^�U��������������Z���������l�-ƒs|e��W�"}f��ڋ��\�G�Q�+�L�������~b����G���D����C����d�5�.�2�6�J����:#��:���t�|�m�c�U�Jmopm�v�n�]�TB���4�B�@D��d��$��r���������v�J�L�8�������8˿}~��=����.|Ն��s�=�x��zo<�B��������������d
��������l�8�l���	�\�������ʨʩ��ܧ��x�x��Ӫѩ��̉�Ш�ܧ��̩ۨ�~��������+U������n��/���nT8)m'����x�x�����x�x����+U��mT��s���_�����^���^�����_���������x�x������x�x��((��8���m��0���n�y�fz�������z��~���|����~���w�L����������������������������@���������������%������"���s�x�@�����{�s�@q|xs@�m��w~x� ���~�x ��_s�x������{�rr|xs@��s�x��@�����z�s (r{xs �2C���������������������������%���������������������$����������������������%����������������������w� x}s@n����ww~s@m� (�{��������|���������vk�6��~�}�xen�������������H�G�)�qtyduw��{���������������z�~�l�{������������s��{�y{��������������s�i�����|�h���o����b�p[N�@~���� ������r�@���na����&s���� ������u}{x�w� cn�������3�������o������w�~u?m���{�������D����@�����}s����~�szzqq�z��������s�}}�w��_o����G��~�}�xem��������������HG����������o�����x�~u?n��{������� ��~�}�wfm��������������G�������������(�����������������%���������������������$����������������������%������������������d
�����;�z�u�1�t&�A����"Ω̵�i�����&��L�̔��+��@�����~�t��vq�az�p�������@��������u�bw&�����8@�SJZu\ek pkf�Y8@,�����F)��:�������J\^GZg��m��n��|���������~���~�r�N�v�����Ư�r�i_��z{�wow{vy���}�p�sV��1}ns�o(>�������}�>�pt�lN[XKH�[ͨ����>��-
���"�?���4�����'::'�':��������:'�,�Ah�"����t�t������LR�A�S�1�S�c1���J����ֶgLXpjZ�@� ��=�P�B�BPOA�A�O�����������gŬ�\�]�W»�[�Z��3�)��S�����f�f�@�_±�R���D�=��̹���|��ͻ�M�V˹�$���Q�G̟�^ͫ�w�_�B��G�.����O�`�I�Τwϓ�RϺ�T�EDjX������������3��"����"��7�<�"�ߊ��m�Q�1@@ry�t��8�����s���pv�u:@�����r���fqv�u:���d@���r�_F�������/D@�>�L6�L!�� @���+���������O��h�h��h�h������[�N@�c@92;�����@�����1 ���y������,����(�(��,�m���m<��}ni�k�<�ytg�n��������(�B�nl�mva2�gW�TP �����Q���~a���w���e���z�����!uP�������!�Eu�������:�P�B�BPNB��G�=�_!!@1�@��Z�*������y����@u@��������_@��M��_��H�EQ�Ji�Q�wr�SrNG2��Jt��A��������(���@w\�EQx�]�nr�TrN��:B�N���������c�T�X�.���E��!���]^����g���������g�T�W�-�������|cQ�� ����f�
P����������+���(�(��+�l���l�>�vI����I���<5�������YaqT��;�Qvy�{�Q�ŷ�����`b��Z������
�Y`qT��;�Rwz�{�Q�������9�RI�P��P(�����*/�inW�����|ϊ�L/b\04�]������O��_��_@�P������(��	���e�,�l�,���|�}�
��v��������)��e�iy�����z ��������)��v��������?��������?����4��
F���������or^{g=Z�������i���
�*��������������>������薚��=�v�������������*��0��������������������9H����3��
�F���������os^{f=Z��P�����i���
�E�(J�-�����I�������4��������������i�^x�����z �������x��d
����6��2��3�������~�����*�*��)��(��!���=�
�x�e�t�pqR�t����������������J�͉y�iiylH����Xzdipsl_~UGJ��h��s��x������y�W�9�Y������������ӿw�y��k]�]s}�zw�~�{��m�h7���k>�Yi�{�������
�zt�dYg��rn�|���oM�򹓝�������������gp�tx��*�k��S���������������k�*�k�l��1wGb_]aT�fvs��t�+�*r����\�������zh��e�N;�h��_hg_@_h��������h_�����i�����l�u�~��~����������$rfP|KEU��f�a�v���,��ɼua��a�P@��d
�����Xv�v����T��@���A�!����!�K�Ty�	�����
��~@7뀙v�~��6����
������������D����
����
���T���4�[
*<�씒�������<�Jڔ������o�C��j�����S���R�'"��p�G�	�*��J�,�����)��!����!K�Ty�p��v�~��6���
����������������9������4:�T[��R
�T��:��T?
�T��:�T?
�T���t�
߼wO�V��VOcZwE�;��(
�K�&
�L��1��������H�u
m�4�"�9�!�4� �D�7���*��*�����~�b���������EL�pC�Q��'�]�V���O�
nLE�������
�
��3���(���`�`�����b�e���!�u��!��3�U��a
�������
���
m�O����%��*� �&�-�~�&��ހ���`���b� �z�]�A�)߀���F�9�:��5�$����
�_���_��
�E�A��������������b���w�}.��$X�'�����[�����[ހ���������poG�b{����������������������
������S�x�Y-��	���q����|���k������j�o�uh��yə����R��r�	�����T�i
�����_����s�u#�
�f�f��"���ss~ki�_����K����_���������"��f�f�#�u�s����_���^���T�T���T�T�O
�O��
Z]ukh���PUj=;�<��$�=�ӭ�������}�(������7�0�!���u��c6�rt�v}ra��f��'�����Z�X������,�W������a
p{��Y��
�XXuxmihaX_)(X��b�hu�X��
�{�T�K�T���T���T���T���T���TK�
�T���������������������������_h�m��x������������
��������T���Գ���
��������
�i�V�!����������!��V�iK�������
�`R�Go|iv��
�
�d�d�}�}�
���T�T�4�4�}�}��
�
�
�
�v������8���7��8�W�9��7����̩��u���x�t�o��v�w�p��E�V�3��'����(�������I�6���/H#�@��_��6s�2�r�����������v����)���	���������7�,u`melh�@K(w,�k�/�T�c�W�B�R�Z�s��Z��������V�:� �[�X�2�;�@�L�p������Z�"
���x�#�&��|C���@H�#SQ�4� ����+�� �2�й����y�z{�6C'r �v�'�Q�j���a��N�S�c������I��=��λۊ���6�O���F�u����������ɷ�a���y�r�v.D����x���yl�u\eh[��x���O�~�|�i�K�!� ���u���F�
���$
���z�z�������0�	�N�e�e%�N�0�	����z�z�������������������������������
��������������������
������������������t���$
���z�z����
�������-
����F׀����
�D��
�D�����w��P��ak�O����N���(瀰b�X�S���9}�^�H���t��T�U
�D��
�D׀�������7׀����]�]��FJ{oQ���$�w�v���
�r��G���
�t��K�KB�=׀[
��v�N�;�m��Y��������i�)09Q��瀷���]��
��T���
�4���������������G��%
]� c�mgc���cm����������*��um���v��pvvp��qu���������vp�$�i݆�y�"�Z�4x������+�4x$�Zy;�N9�������������@��?�@�?��@�]�?�?��T�e�[�R[ed\\�d��R�����j����������b��O�� �����e�[�j|ƒ�����������~�b��O�� [ee[\�e��j�T�SP����e�[�P������Z���[���ZQ�R�T�[ee\[�e��Q������Z���Z���ZŅĀ���������������4�
P����:�����
l�����9�4��t�M����J���lrH��m9�	��M��������qxttur��������������Je��
���sp�szy��}e�
���<��������cH��u�Rtyzuw@B�X�����2�����ʳ�8�g^zp}UY̲nx�v�w�ww~zm��#����Ԓ����������,���������f�����������������������~��t���x*��}�-�������������oA��c�2S�3_�(���%�Q�,�d�F��W<~����4���g�E�W�RC�tp��|��1����$�+s��<����
��
@�T�)�0��a�_�i�3��� 4��X;&��
���us�s9&%9l�_�n�hY5�����]��\�a�\�<�R��V��k���_�k���`�1�T����<�kOF�w���2���ϵZ6��_�"
�
��g���<�jOF�x���2���ζZ6��`�"
���g��-���~�	L9wu�z~\L��y����Ǟ�My�v�}�N�}�������	����������ǜ����z]�����z�7�����T������t�T�t��t�4�t�4�t�4�t�t�$���r�r���d(
����
���*���*�����TR�4(
��*���*����'
�4(
�T$�d���r�r�����n���Z�\������J�x�k�^kwwk�k�w��^�����~�|��}T|����z�x�k*kw��U|����z�w�k-jx��T}�����һ�����xj�������Һ\D�����E[[D�S^m��x�H|��|T}����.һ����һ\D�.����#����##�����#���������
�'�V�'���'�����8�����������L����t�t�2���2�T�2���2�T�2���2�T�2���2�����������������O���
)�$������x�r��O��������r�m��c��������q�ly|�~��"��|�yy|�~��@� ��|�ylqrk������e��w�}xt�����[��p�wtop�t���b�������p�t���U�������k�r�������#�����
����$�����������������U�������������a��ᰥ�����m����}�||}���€�����#������V�䕌�����O�V���@�P�[�������d�������������������������������\�R�\���D?���G������!�cL���������m����������?J���9_����������	��l��q�1�:���KI���������<�E�Q�8���8����?�E���������d�V��w�s������-�1���a��������S�]�aA�����<�U�i�u��t�,����������e���#���z���_6�������������������I�c�������l�����������T��7P�7���o���7������w�>��������>�����?�������������
�D�����B��(�D���D��(�B����z�D��)�A����NZ����ȼ���xȼXN�=�v�
�:j�TR�R�;���;P�P�Q�2�<���;�5������,�$�(�)���M�U�]�(���)�+���+\�T�M��q���q�z΂�3�����4��y�p�m�1��
�.�o��Qk�e�^�
�����'�u�v�&������^�e�k����7|��e��pex�#�B��9��o=������9�B]:�#��/���ݠ��p�����"�\&�����"��iR��e��x�p�����
hB���
���R�XD�@���������� �_*����� ��pX�����@���Rp��c����h�E�����:�dM�+��A�����*�[ �����$���0�b�w�q�f�]�]�]�U���9pttp.pt���q�������to���q�J���N
�����J�A�N
���A�J���N
��l�L��6�H���������������p�A��O�YK�I�+���+s�r�s� I0�"�/�r�I�H�q��q�I�H�r�v���;�(h�q�j�u�q�i�F�����
����ﷰg�����(����7�]F���$������g�����)XP
��������p'���7���)���28���]8�����j*�%��j��j��j���A�o�]��"��
-�]��"��-�]��"��
.�\��#��<]�i�|����i�|����i�|����j�|�������6���6����6���F��ٯ��������6��UaZ�g����<��xg��w��������������������;�A� � �A�@� �!�A�@�!�!�@�A�!� �@�9����ŵwv�mQ��uL�flD�^A����94�wHMZ��X���a�ǂ��ݏ����,���!���|�����)�
�
�*�)�
�
�)�*�
�
�)�*�
�
�*���*�
�
�)�*�
�
�*�)�
�
�*�)�
�
�)����[�O�CPZ[P�5���5�Z�P�CO[[P��P�[�(ǻ��������.�S��"�0���@��:��M���������`ed��e��������S�O����[/:~~|yw�{���
�>�g�7�.�iczdfp�t���+��&4��R���������l�^�����v�Q���B�R��������{�xxgd~y<��/R��c�4��j�c�'��^������d�<�/�g�Z�8�%�V�������d�
�
X������'nh��`����z�{����{�������@����X�'�&������'�&����H�`�������h�������-�Q ���N����������k�g���-�����`����`��%�`�������a�z�x�w��wx�z���xs�h�t�T��~����������T������x��������'e�'������'����
����
���������x"�888ށ888ށ888ށ888ށ888ށ888ށ��888�11�
�r�����J��8�
�����8��m��D�ڱ��8�
���8��m�898݁xy���f�΢�{�c��E����H�����
������$��D����EQc}{[�h�f����KK8݁��898�11�
�D�r�����'m�$�������H��D�
����m���������>
K��4�T+�T����������������DqT1���aa���1��q��������������������ӌ��������������$�����ӊ���������4��Fl���G��u�j���������/���>�c�v�Y�X��wr�lO[MOO[�Olr}twXPY�v@c��>kPS�/k�������_�`�b�j�p�N1k���I�|�������
��� ��F��k����u�U�)�4�S�'�-{:d��@�G��
&zz�����E��w�v��lmul�c��h��r�������]��t��
���bF�s^�[X�V[
��v�N�;�m�Ћ�������D�1��� g�%/O���,k���j�F�?�j}����y�y��k�����D��
�D��������'���w�s�xx������
t�D��
�D�������7�U
�1
��t��_�>�h�jt�h�h�j���bg�S��g��T.�
�
�T譁����b���������j�h��>n�_K��D�;����D����
�h�/�����4+��|
�Z���su���S��&�yp�rxo�h
nr����R�/E��o�qwn��������������������썍�����c�@�
��"�;�;��d�������xp��X�B��B���������}�t��q��۽���������w
�
�T������d��m�l�su��r��|����j���to
�t�t�
�t�tD�t�����E
[
�S����)�����\�<�����D
�4x
���/
�m�
���
8���������{�uNv����Q�*�3�3��Q����~Fu{uv����+�N�R-��X�v�D
^
���v��X�R����X/
m�
��
����
������*��6x��l�l�sv��r��}����jX�m�
�9
��������)�����[=)R����~�[�~�w�~5-!��i��5
��D
���"�~�v���_��������V=)[���D
X����w����a����u���q�u���� ��f!D!��� }��q�q�uu��r��|����j���to
�t�t�
�t���tD
�t�tD�t���ì�|��r������6�Z�<:���S�
�vg����$gJAv<��������ֽ�Y�i��<A��J�������Z�)����
����������
�����P
���0����u�l�c������
�
����*��5x��l�m�xy��v�������{����?�������Z�S����!��
���4���t�9�M�kj������t�9�M�k��x�xw�����
�J�1��1���Z�`���w�w�x�n��=�O�v�T���J�1��1E����`���������nm�=�O�v[
��m�������� V������
�������)����
�gN/��#��-t��e�Z�\i��\�������h^
����ֽ��?�#f�,�����W�S�����CZ�7)������
����6�Z�<:������
�vg����$gK@v<�S���T<@��K������Z��i�i���#
�@�@==�)�����\�<��� �!�������� � �i�j��D
�4x
���/
��
�
����w
����4D�4�9�/��������^�]��^�]�����9�4o
�4���j�|����ѡ���l�s��m��d���������t�����K��/
�������
m������v�~^^���M�M���t�M�t�j����|��r��u�s�lm����d�����������t�����t�
�t���M�M���^�~���������2���/
�����
p�
�T��
�D
��D
�����T/
��������[
���]�]��E
������������O���m�|����*
��\ee\��\�e��s�
�����V�e�\���9���7��M��|�?���S�#`���������<����`�R���w�<����ED��z8D������^�7�E�&S�M�X]�Z-���`L�M�L�����<�z����=��a����3������l����x�-��v����x�m��qY*m�����S�Z�]�e�a�u�������ж��X�������p~�v{�}|[^s\�I��F�F�S���#Jw��a���â�������������7�z��_����
��%��>�}=�a������������������f�4���4����	��)x�5��M��k��4���4�4���4���+�����
 ������
������
���T�
��T��
���T�
���
������{���{���{��������t���T��
a�T���
�TF���7
����
�Tr
����J
��t�T���s�R@�6{���@),\��,��)�@�ə������EQ����Z��T��
a��������������������������������������������������������������������������������������������������������������������������I�Is�~��������xx�x{���?+)]��)��+�@�����8�s�~����������v���
����������T��@����P
��Tx
����{
��������T���
��T�i
�
P
��
������������T�T�T�T�����T�/��������/�T������T�T�������l�v��T��
��T�
�T�����!5���
��������
��s�^v���t��
��4�����~�������4���������������4���������
��������������}}�{ptr��m�g�}�e�}������������������������M�p�������������������������vw�y����������ۏ�
�
��P
�������X�t�j\���b��'�d�j�����гg�[���L����״�(�
����¯����#��w��m��ݿ��������b���t��G�(�r���|�k�j�>S�l�s�t�������� =���������S�l�s_ti�q�n�����v���„Ņ�3I`QnN�^�D�y��a��g�T�Q��3I`�nȜ������n����;((5;!!6����r��y��������q�h��������n}�����.�d�9�=k��%���)���}���|�|���������|�{�z�v�v��������u�yyv�v�x�}�������������̖ҹ�֐�������a�c���r�p�p�xs�w����z�n�}{������w�v�v�����������������Ӎ⟳�����͂�p�T�l�Zx�e�y�R{��0o|W�b�e�V�H���q��u��O� �z�|�n*�)j4_SnNe]_\]“��†gwkrmn�n�n�y�{��ʼn���Z�lvTdp@�J�I�4�X�^�xԉ�@����������j������w�v�w�������@~�n�y� ������y�o�r�pm�ue{`nY��n�p�r�@�^������r�ss�~�~�x�v�v�y�v�����}y�@u�wzD8{�{������|�z|{}{x}�~������y�z�~�~�}��	�;���$ˉˬ��7y�8��8��S�iˎ���;���	D8������h���������L����p�`� �d|�j�K������='��������t�<�<������vug|c��`��|�[���hf�@�_�&u1�||�~��y�o��������9����������ut�w��KrjR|Y�% �������ڬ�Ӣ�
2�H��������[Q|+�<c�g�v��EU||��zzЕ֦����������dBr;�9�Wd�������Ir�Pmu������͆�~������/���/�0���/�/���0�/���/�x��y��w�`~"�b�|������ьҋъ���[[~!�[�s���'��ҍҋӌ��l��3z���Q��������R�#�k�r�w�:�v�����������������t�v�v ��L�F���T����Ő�����{ό���������x�s�x�<�ծ���������������������
�|����D�B�F�+��D�~�I�#�6�B������7�}IH_I�D�&�\Ӂ��@��r�{�)�5��
�������?���}�����������������������z���������
������ T����&�#?�a�O�C�����:������������)��x�{�}�������������.`�A�<�~���������$��!��	������������z�~�|�}�}��������X�X�X��}s�r�uj~^�a�t\C&OD�I�H�}���������ߤ�@������J�6�	�r�B�00AA00�B��������A�00BA00�B����������N������p��i���4�r��������������������t�����������T�������_�	�	�_�_�	�	�_�_�	�	�_�_�	�	�_�0�
�$��k��t������
�t�
�$Kh\�b�u�D
��������
���<���<�<���
��<+��t��+�
��'��''�+�
��-
��
����
��
�����i
��T�� ���������������i
�R
��,��T[@R
���������
�4���]
�T�3�C�@Z
�4�
�����������K*�����������K*�������������K*����T*��
��
m�������{�z�����s�{tq� �p
���S�X�k�{���E֫���}��]�p����
���FV��*
�K�H�W-C�C���HK���h�@�)�4��
���)�@�hK���H����-�W�H�K�h��)����
�4�)��h���
�������������� ������������-
���@P�����@��h���!����(��@@���P���
! ���@@�� �!������@�@���! m�iP�t��
�����m������P
�����������������������������
�����
�����m��a������� ����������������a����R@	�������@�P(���" ��Z���D��

��$�����@��@D������
%����D�B���" �
@ �@��� �$"���� �@D�� @�$���

(���
��>
���jm������P
���P
�Z-m���m����
���
me
����f�4�4�����-�4����������L�L������m�������x���z�z���M�M��z�z��������V``V��������4�3
���-���ժ���L�L�������\�U�I� �����(�f�c���}����s�m�������-� �-����������y�i�s�n��������������������K�8�A*����,����g��t������x���^�L p&����{'��%�%���{��p�V�J�9��$�5E���E�$�ݑͥ��}��r��:CW*����[������_?P`X=��}��[A�����bo���/
���k�������k�������(��2�2����I�����2(��U�J�U��2�k����������������������������������������������������������d
�
�+��Ԁ
���
��G�����X
��]
��g��Z
��X
��]
��g�4��4�
���
��G�4����
�t����
�����������������T����T��T�����i��pE�77EV@p�1
��U�_�x����o
�H
6
�f
���������I{��
_gg_����n
���7���b��n
���7���b$
���Xr�zspp�s���^?�`�������`���^��
$
�_�`�b���������������Z���[��z�[;�Z����$
��&j�W���W�j��&�[�@�"�U�����z�U���U$
���Xr�zspp�s���k�G�+�P������
���T�v@�T�
�K�
����x���I�L��L����I��������I�L��L����Ix��^�
m����K�+��� �t�������t�����t�t���������΄�PH����t��
��������ZV����t��
˻WL��q�q�r��H�r�qqr-
�hn�����n����u�~���t��
�t˻WL�@�m�A��
˻WL.���t�
�JMs^\�t�lj�i�!)���������tI�K�^�����0���������t��H��������!��ww��x�t�^B�<``uf�t�`W�U�4
�x
��������t��t��t��t������*
ɽYM�$�����
ɽYM�������
ɽYM��w�w�x?�)^�cj]�Dce��s��
���ҳ�xk��.�a������
ɽYM����$��
�18X:b��}}�}��F�hX�a�"���!��
�D�����(�������� �	��������}}��}���b8�1�m��o�9�����t�������t�����������ʓ���������
�0�

�%����nl�lb
!�+�f�z���x�!�����p��|/�7�c�h�h�k+��^���[TH�P�}��.�}{�{MY�ɷ�����7��o��_qccy��4��{�H]���ȣǦ��������ɽYM�|����%npzdc�Z�}!��DR��߼�
�����\Z�j�����ћ�����|���0��!�����߼�X�E���������dk�dNYTMNX��������������
�0PcXR}��6~YV�W��������t���
���
��
�S�
kI�J�X���%��Ba��8�k�������#�E�����
���b�>�����[=�:����-
��
�Y�v�k���2��������
������O������T�����\0�OU�ƀ�������ԫ��afob~h������S��wk�����9�&&�����F�D�[� �����_���J�������ͽ���� ���"QQO;���������2���x)��+?�q$�@8���q+��*;�u�~-%�x�x�x��q�u�utg�f�h�%�'��E���̹VL������*����v�����˺VM������`�����w��z�������TE`ubiq���zup�p�J_e���'�%|ŕ�}���r�����ɾ�ɿ�dZ��,����������ɻ�˾�gY��%����8�>������4
�x
��[�;������k�t��t�T��t��T���l��*
��MC���
��MC1����
˻WLN͜�f´[V�mJ�J{K/�o�qwn�bce��s՜��
����ѵ�vj��+�^����
������d^�]� ��� ��
�b������l�Ք���m�)�xy��x�^H�Cii�}l�\N�J������p�"���#���k�����k՜��͜���k�眫�
������t�������t���:
���o�V�t�t�
���c7�/{{��{���b
�z��f+�!b
l�l�n����%�
�0�
������Ǔ���E�t�^�+��jf�f�l�l�ɽYM{�{�}�.���}P�HT�/�7������q�ͻ]H�{���4��cycq_MY�ɛ�������Ǧ����s�������jZ��\����
�
��!�}�Z��cdznp%������������� �0DR�������������ɹXNMTYN�dk��d�����E��X�ÿ����!��0W�V~Y6����R}XcP�^�v��H��Z��t�|�z��(
�	z]�����������������������}�z�!~�����q���{�y�z�������p������~�"{}~{�=�U�������������������P�?�����������Q�=���{��~�����G
����������4��I���H�t����Z���]��4����1YW3�6�������u�bQ�������������E����d]�"��(
�T$�7��/�V�������,������������'����t�
�0����4�����4����
�'�%�Y�T�8�l
�������9���|����2'�8�
�
�(�%�X�U�7�l
�������9���|����3'�9����40�
��k@���t�t++�����U�U�t�t�t�t�C��<�<�4�4�4�4��
�T�T��������U�U�t�t�t�tC�++�<�<�4�4�
�a�J�Z�Z�Z�Z��44c�����������T�S������������c��������++�T�S�33����������Z�Z����
0��g�Qv����O���y#������D��O��R����K��P��K�������a�XWaaXW�a��������a�WWabWW�a�������� 45! 5����4!�� 5���4!����-���.�.���-�.���.�.���.���.���.�-���.�.���-�.���.���X����c�c��@����c�c�����c�c�����c�c���0���ɂ���������ь�8�`��a�@�a�NdC�9�s�����b�c�����c�c����@���c�c�����b�c���������X�������9��X��E�-�JF,b���������H�5����@�Y�&�n��Ë��49�H�������b�F�8s��̷�������p�z�S�z�N�{�R�{<��	���`�_�����`�_�����`�_�����`�_���9��'��''��'�������pq�D�-A��&�a�a��-�D`qX_1�`�A�M�t�CC%&*)GGbb�I�c�~�c͋�������%�)�G�c͋��������c�����B������ս�_�m�����
�3�P�D�33DD33�D������j���Kgl:VF_-zM��W�S�R�n�\nn��nn\�n�Z�E�C�S�Snn\�n���n����������Ӿ�N�+�F�:�g��˝����V��C�&�&�Ӌ��l�gZ���G�%�%�G�G�%�%�G�G�%�%�G�G�%�%�G�P�8 X�P
�����������*
�6DD6���s���r�p���s���G�4�T��mm��v�)�t�~����̩�v������������VJk}ltu�(�vumm��4�[��	`��$�����O�?���$�d����`���`�z�w~���y�8�M��v��a�\t�i�N��߶܎�`�����4���s�~���nkA�[�"�gwdL�a�G�$l�Υэ����`v�~{ҊꅮK�-�5��%L�
�.��U <�B���B<�Gi�
�Џ����|�r�`��0�+�=� �E��=��������w����	�y���K����w��"w����o����I��l�khslji�s������Q�x�K�)]`������J�'�����������R~����������×b�B!�-�(��pW}��������������^^��_�I����������|�Dc�/ %�)���p}�����[���D�e��\�]�]Ϛ����������F|��E��/�+'���Ǚ�����eT��G��f������{������������H�B��-��*�\��������m��������N�����N�N�����N�N�����N�N�����N��
0�
���
������
�@�j���<�Z�\�
�f�zd?�*���1�"�0��-���)/�!U�=�I�T���AI�z�W�dd�]�,�O��+2�=��q��4��{��E�)��<��A��1���t�1�j�1�(��w�;���;�;���;�;���;�;���;������
�	��u��p�������R�@���@�g�����L�)�w�te�C�#��B��3�B3�C��V���j�>|���肙�����i�5�4�_:�v�x���H|�Q���̋����y�P���B����CĻ�*��O8Q�z� �}y����������2����!��v�����
�w�
���2�!�d�x��������%�%���u���ou������y�f�"�2E"�c��i�P��8�+�H�>��V������V�>��8��P��i��cE����0����}�D�8�F?�:/5mV?�_@�)������*���_AU��m��֡���F�8��~������4�p�w����:�{���h�I������K��6��AOR��||�|�����7���:�:�-�R�=�6�j��snVK�
{Qr2w..�4�$�<��1��U��n����k���;�H�K��T�C�$�[�����E�Eq;rI/�(���6�������F����+������G��-�7+`=(c2�F����]�U��=��P�O�>��U��l�������x
�x
{�����
�T����@�q��]
�Tg�t���1
��i���t�
�c�����*
KWWK��K�W����#�1b�nZ�yO��L���/���õ������B�+��
�h'X�=�-k7yS[rWmK|C����O�]�e�w�,������i����@�R���F˿���W�K����Jv�f��|��������)���}������xy�����k��~�������������JJ?X7gf3.x,+.��46�?�J�G�X�j�kځLJ��������v�l�~�d��o��J�L�N�*�4�A�@�P�ba�u�����������������l����~��x�y���JJJ���������ww�}���IIJ������������������������Ð��N������������~���L����kR�{�m�m�a�U�U�L�E��C>�<;;{mDRs*MSP��w���������m�s}wy�<u�|�������������ƌ���
����Y1��0����Y�
11��22�X�48��C�1£dz���ʧ���r]��^�NJ����qZ��o�e�~|Z����~�����W�4�3�X�V�3�2�X+1fIHJLh6�7�����:�g�f�s˂�u�n��c�o���r�~�E�M�U�U�a�ml��|��ؚ��ѩʵ�����ɩ��ӛ��l��G�@�/��' ��"�vg9���������~�{�~�i��������ye��n�a�M�����������x����x�����,���w����M��������������w��^�����Fy�l}�l�
����6�6���x����t�m|�c�w�&�L�L�+d�t������������j�iJ�4qq����ߠ�������˚�|���O���)�x���O�p�Y��p�Z�,���,��p��W��wT�,�J��y�I���������E�7�w�t����4v�Q�^����6���_�4
�T��T�4��
�������P
����q
��q
�bty��
����%�
��������%�
���
�@����t��T�t�L
�t�to
�t�t�
�t�tD�4
�T��T�
�
�4� 
���t#�4
���
��+������P�P�P�P�����]��w�~�P�P�P�P�#
�Q�P�Q�P���P�Q�P�Q���k��#�4
���
�������]��w�~�P�P�p�p�#
��������������i�P#�
�T��
��
��/�0
���
���
�x
�`���t�����T_`��b�#��#�b`�_���
���y�y���Q
��
�t�3���3��
�V�2�2�VL
'�
�������!�!�yr�r���1�1K��-
��/�H
������!�!��e�+�������T��T���T��rr�yy�!�!��!�!�V@�;���v�����������y�u�w���������{�{�{����s�{sq��v�w�������������������������������t���z������z�
��z�����m�
���m{�`���m����m�
����
�
��
��F���������������>
�����������������v���
���m
�m
�m
���%�������%�����W��B�S�	q�g@\LP���{��|�����������@��)���҅����%����������V�����`
���B�B�B�����
���%��������%�����
������������������������������������������������������������������@w�\�����h<��;��v��-�;�������ݯ].��Sg9G��FXVi_d�:f�t�l�\m�M>�U�:\!-<F<C;D�)�Ե���4�C���5��5��4�C��3��.�N�$���r�j����m��2��	�O�
���W�������q��q����q����t��*�Q���t������
��4�������������+��j@8ߪ�rr � Rr���@����L�iO;����{e��S�w�����)}5�T��Ԓ����������?����>��B�	�o�-�Bvˌ{�b������є���������~�8�������w��������0�R�8�#�0�F�2�SXteg��J�]��l��A9�H������H�8QXi[s��y�x�y����\��HN�-�fX�R�22�<�G�j�m�kk������K�L�����Ь����̬������[������H98HH89H������,,�K�UU�K��,|����������}N�v����������}�|�u||��a8H��������H98HH9��������v�[�����y�-�r���n�
��� �f�����������=�q�����F����)�����?��
��`�9{��d���P�3o�&?����(���$��������W�2����
����3�C��Z
���������������`���@]
�t	�t�����T������0�����!���,���J�����J�J�����J������v�'�k��$&�8�C�����������������P�B�4��n����!�4���8���V�����%�%�����%�%�����k��,�H�����T�����4�Tw���������/�+�,��{�{�a�{��������������L��{�{����������
���=��=������

�

k�
�����F
�o�~��������|��܏��f�
yh|lid�boo��p�������r�mmrrmv�w���~o�v�F
�����I
�����������v���	�o��T��~�������������ƣ�������@��V���5�!7EV@p �-F�1�M \Z�G#�n'���x�!������ϼ� ����1�-�+���T
��S��(
++EZ��[s�p�k�������������������T���������������~���O�@�������������G�A� � �B������H��E��B� � �B�c��
0���-���/���-��-�-�-�-m�J#66"���!���!�!���!��p[��m��������m�V�J�E��4�6��H���`�`��Z�[|]~c�`�}�����������������p�G;�-�7���-���m���������{�<��8�Yn�,�=�a�u�K�K�v���Q�.�-�Q���j�K�s�[�hshs�\�h�F�:87s;\Fsh�[�t�����������������3]�-3�s�\�hsht�[�h�"����e�E!sh�\�s��������������-�3����������~�+��**���*�����}���Mz�]�c�.���p�����%��$��f���M������5�5�2��7�7�<�������&�������U���A�+��+�K�������q�5�P�Pm�;XY����;����v����2�
��,�c�T��T��:
��,��[��R
���T:
��,��[��R
����� 
x�t������t��t�
��
e
���:
��,��[��R
���T�� 
��t��t��t�ԙ���t��~S��(
��$�t�����
��Fh�͉y�y�}~����������������������p�j���P���P���jprk�5����j�T�h������c���
���c�����t���������t��������
�R����*N��^����Ȗ��*��
�R�D�e������jo���k�4���������p�h��4�hplh��/�X
��4�X
��9j�oqj����h�p�����4���������l�h�\��ƙ����;2
���;ǾbP��0�&�M�	q$��;1��
�;�$9�	q&�M���t���������s���������T���������������
���
��|~�}�S�t�������������K����|�}�S�t�������=�������u���������=�������t���������������t�����������������������t�����*��w�����)�)�)�������(�(����������.��������������d�d����������Z���N�����N�Z�Z���N������N�Z��
�Q�+������A�@�A������A�@�!�����������[��������	���	�������[�������P
��������������P
��������B����
�����
����a�
��+��1�4wx�{���������~}�g
�4�������t������4��a�
��Mr�����&�Ȃo�l�y���
���������������_��l�Z����b�����������
������&���Z����_��l�Z���b��>�������T�t�4�t�9��lF9y4�d��;����1�?;�U��Ғ�/����t��t����<�%�����%��<����"SKj<5�e�Z�>���:�$�����������$��$=�:���Z�>�e�j�S����m��������$�������5���������������������������4��4��4��4��q�����(��������������f�?�f�?����������(����q�*�*���*�M�*�*��w�I�9�(9II9�(9�I����������*�'
�w�����d�A�4���6�7�M�������R����*�M8�=�I���F��[-��2�	�~�����������
�0����������X��P����d�ow�����4
�4�����b^��hvii�!r(u)����-���v�jzfj~�����qs�����o�q�z�az�qHoC�wq�s|q�����j�z����������)�(�!�i�v���������i�#�o������#���v�i��%G�������������������T���;���;�;���;�;���;�P����
�0���V�v���i�W�P�V��gu�m�l��w�a�|��������|�q�����{��c�Y�il���i`d�H�_�_·���I�5�)4�����y)Y>B����ݮ��U�1�1�V1h8SM������$�w�h��#�h�A�Q�WƇ�����¹�Ð�������v��Z�]�����;�();;)(�<���&�U�1�1�Uԡϱ���B.`������������	�����eSGtCm�$�t��]�$������t��t������R��4'�4����$�B�L��8��,�L�9�}�x���9�����������������������`Q^fxOoDk3d�G�������Դ��"��T�Ua
�������
�
���v����s�X����Q����������F�55EE65�E��������������������<����xi�UNg�s{�����f������<ϖ�Җ~�h�r�8��4�W��{��m�X�x�|������������c���������������q��J�_�s��'�*0����󍂎������i�ZӵԵY�n��5�U+������"�C��������������~��?��i�h����y�v����x�n��n���n�6������������������>��������#A0�W����9���
�|�x�����������uz�l������������Mx�|��l���������T�(����x||x���x�|�������T�*���0������(�=��`��h��Z�������6��,��
�L�8��6��-��
�I�8��6��,��
��������_
���-i1Yn��||�|jj��k�8�d�J�!E�+z�$�9�9��$�+�!��8��������������YisV�>�c�r�bxy~v�z\\�\}v��{~�^�ws8~644�6�8�w�^�~��������������y�b�r�c��>s�3�%�����������p�[��rr�c�r�r�kii~kssqr�b�r��I�I���������V�*����B�+$$c+CB�~�����I�I������%�%�U�a�a;�U�%�%����
�5�?�?H�5��
�~�����)���ԫ���
���
���
�T����t
������������t
���`�
�����5�!J�����
�J����n�����
�J�����
��������������w���N��k����+���m��T��T�T���11��������W���
�E
�
VNMDH>>3�5b
d�-
�E.�
���������:��������V�2�2�V�V�2�2�Vd�������'��c���U�/���o�c�uovo�c�v�?�%��	q��|����������~��f�F�F�
�0�.�*o�c�vnvo�c�v�&��0q��|��������������K�T�i
K�T��T��d����h�jw{i^u_oYln��u��s����
��o^��i�w����hY_��u{�j�h���������������w����u�ji�>�q��w�[��GA�?�ij��k����Œ��������[�V�(1g=V����������i�j�N�bi�6�%�Qt�b�(���e�nz�f�l�4��u��~������d������p��������������"������v�[��~�}�����d����t��V��l���������d���v��tş���W�4��t�t�����������}�}�}���������"��C�Vt[�R�t�����}~��[tvR�[���C������lj�h\^��a\�Qwt\s[�R�sj��z������\oUwQ�V�f[�VT[��g������d���k\c`^ebi�O�bt���������6��Q��b�(��T�e�����|�������T����T�&��&'������d�q���������:=2G<LCYR��hn��@K�5�������
�$������������c���{{�q�{�<�<�{����������{�q�z{�c�c00�E�3�'�ҥ��}�}����{���P��RH�L�������byz��{*Tb�#E�.ᕖ�������������������z�<����������_d�_:@sgD�������_�^�_�*d��J�A�	B�ɴ�׵�to��������'W4p�w�ο�š������������v���W���X�M��u�Y�������1�A�3�g,{ ����հ���������	y�L�� �����Z�=�x��s���a��v�^�������|�Z�Z�[k�.k�/k�.h�e�m�f�$��6�k�+������ː]V���$���Iq��o�~��QN�ڈ���7�.�;�������gh��h��V�N����D�<��������{B���3^w����/ۍ�ֵ��5�b�	L�Q*��G���J���W���}��ϗѝ�ڏ�����������y�������� k�T��U���nn~ryj_�M�l�N�y�|bm�����m��T������]bj[��X�]�~��-�u�����[_k[��T�Z����K�N�W]dW�T��]��T��kY�acYU�a�������ö������1����r��&�>k�f�b��r�(�yw�vE�^n�w����������������"�'h�R�cl`j�O�b�����������e���nf�Q����a�WT�`]�T��t�i\~{�&�X�U�3t�O�Zq]s~Q�[������8q�Q�]sZq{N�\���[����k�P�`m]l�M�_�����������|��r�(�n�h�d�&�>�l�e�c����������o��������v�D�d��$��H������6��}���z�~��������t�1��Y���b��������Su��������\�������������������q�����������P�����y��������������,�:|��`�B�/��O��������~���T��a��KJ�~L��y�����y1V�w����y�:�p�I>�/���2ndgaWr�s�w��	��	=������������!�Y�	2��R?�2�"��?��=�.� �O?��U�����<���<quuqqu���u�d��dV�Tqu���������"����w���+�������B�~�o�ftaz_��V�SR�t�9�K�x�x�:�K�t�p�;�V�w���x��������QM�M���t�����#���"��Y�(�)�������#�`�Q�x�g��i�hi��V�K�����������l��f��T����'F�b����(��-���]�������ݸ�u�W�h@JM;uT|NwbdghsK[b�e�i���(���{q�}P#�4%Sa��j�����_≖�����������`�/�7�b�b�/�6�a�a�.�;�c���}�}p�m�m�lj�i�0���+�.���1�0���.���{��������\�YY�F���C�?>�AD�$�(-�}}��}�[ׯ���M������g�Y�S��T�*�*���l�SmMrWJB`e��n�ū�)���c1&E,u|�����Ѱڡš�����X�MN��9*
�T�(�T�3���3�T&����V���
��]!zl�t��ahqr�p!s,��o�"pr�rg����l�!�������������������|���������������������N#��l�[he�e�e�����������zpK��^������7�L�w����}���� 
 c�b��*
�[��)F3�RtZ�>UK�L�L�����dl�lh]rd.�^�7|�}�}\".% _q�q�o�y��~yG�Ao��k�zAï��������w����P�W�����������~��|Ԫ����A�����y�o�q�q���0�[�������]y��Z�igmpg������ː�����t�@�6�)�H�����W�����������\!zk�t��aiqq�q s,��o�!qr�qh����k�!�������������������{�����������������
����N#��k�[ie�d�e�����������zpK��^������7�K�x����}���p ����
		��
#`� R�N�{��M�{ ��xi�wi9�#G�s���������E�����}T������������l�+������{��X�|���������V������}������2��h��8p�ihE[��&�Yr!h�g���R��o��q���������-ε�ߝ�A������ ���U���Ǿ�����Ծ�*��������}�t�~�x�q��i#�E�3l�g�c��2�F�j`�\�Y�=�u���r�r�qrq�s$���>�tY~\w`r�k�2�Fclgglb�E�3�j�r`w\~Y�u<����r�q�q�q�rr%����t<�Y�\�_�j�F�2�b�f�m�1�F$�k�q�w�~�v}�����������$}���x������$�k�1�F�������E�2�j$��������t��}���������������������������������%��%����%��%��%�L�X�0���X�/�X�/�������T���T����T���T ���������&�O�,�-�O���O�,�-�O��jj��k��1�����'��
�'�-���4�n����O���x���q�i�ggg�h~ie$DN�y�W��������v�w���#1���rH�e�%����:qzt{s����������[����s�,�w���������!���w����"��"��0������t�dcubhg�c������8��cliccm�������������id��@dmh�o
�id�0�B�cli�o
�id���Bdlhccl���������id����@��Y3�W�,��zh�ehjwmy�xj�hhj�
gk�
ditiy�7�4�k�g����
}R�QP��t�����d�,�c��*�p�q�q`NAp@�`��J�Q���zH~GF�+�/�2������������rY�N�'K_IFF_��ʷ��зIL�	���P�&0������h�Fyz��y�\\�[� V��������_�
�J�P����m�z�
B��pg�fsvy|s�#L���������c�|������������gV�XTVtbe�wv�v�N�A(�$�h^~mo_��~���|z}y~x�|n�f�{D��BY�L�\�'�
��>mZR{Qss��t�N�]�wig�g�X��n��Ϥ��O�Tͮ����m��w������m��w������m��w�ŷ������	��v�����|����iI�#&�bS�S�!�����������m����v�vu�� 
�
�D�4P
��3i-k�b�US�T34��5�II�I��yq��߬����
)�
�
))�
1�9�j���4��������:�P�*�������������C�3���������+�������K��}�������T���
��-�M��u����jmatvhj_|[�t>4a@�kk[|^4<��N�����hc�_���/���2�2��ģ��֖k��E�b=0���/���Y������� �-�"�$�3Q��t�l�Z�[�Y�f�b�e���7�]X�U�nPI"�R�g��ɰ��e��������;��o[��1�Hw���T��
�T��g
����<��R���;JLwgV�VL�J�	�B;����95
�4w�2
��������
�N:�9�����՛ͻ����ů��F��4�O
�cb�c{������"犖����M��88�']L�����"/������f�
��UA�������=�0���;�}��������������Q�<�0�^�'�����0����ř����}�W�}�w}�;O�<�0��4
����
�b���w�}�GU)@�'�eY(.E�������"E(�Y�"�+�G�}�v��|fW�}�x���?�r�?��Q��<����������ŕ��z�E�٘������+�0��@�
�4��|��c��������������"��-d��c��|��.�4��4�|�q��\�N���E���E*�#�������"#*;QE�"�	���9�a�Rqs|ig�4���v��������ߟ�	��ތ[��l�i����f�����k�����8I����`�����Z���\�����u���ρ�6�ٿ�������<�������0�J���A�e���c�i�>����z�8���qF�l�;�7��M�t��H����������$��v�"�?-�=���x�G��n��������S�-���������u�������������������b��������7È������
A���������
������w�c�������-������E��������f��7��-^���������D���Nf�������r������x����������������~�������5�8�������~�O�������	 �������K������������(JD;��;J��E��Y�Fk��T���«��F��Y�E�A���#�	��#�#�	��#�$�	��#�#�	��$���R+��7�TS+��V
�T�}�y����� �
���`
���������$�	��#�#�	��$�#�	��#�#�	��#[�pdIH[<<H��I��Nm�}�!7�5������'m�w�S�@���T�|�z��J
+���J
+��r
������@�
��
��G����������������
�x
����)4RMD��DR��/��@�2o��[��ͻ���2��@�/�1��$�%&��%������%��1��:
�ԩ
��R
K��w{{w��w{�����������{wS��::
��,�u
��R
K����X
�@l
���A+���?
+��c
����������V���w
���)�/e�@�2oZI[BBI��Z�2e�@�/4�M��������1���%��%%���&�����1�Q� 
���{�w��w{{wSw�{���������'
��1
���
�����M+���L
+���
��
��G�@��X
�@l
��
�4
�������Y�X��y������y��X���O�:�>�+�N� � �����>t�:��O���O
�����
���%�%�����%�&�����$�'�����b���
���%�%�����$�'�����#�(���
�����Gg4�(�K��
�K4�(�Gg.�S�1�>�P�;���;�>S�1.���
���F���
��
����ڨ�����z�z���'�.�<�!b�V��[�b�-�;�P���P�-�;�b�[�V��!��E�$��@��h���h�
�?����	+�����Y�Z�<�	[���	����Z���Y���+��	��
�d
��������0d�A�1]ZInBBI��Z�1d�A�05�K��������.���$��$%���&���������T�
`������X
��+����S
�@g�T�
�����T�����������
���B[PP�>P[����,�c��s��£�����,���P��
����t�
K���:
��y}���j
K�y}}y�Ty}����
K���
K�����[�R
+��X
�@l
��
����9������t��������k�,�ccTsNNT��c�k�,�B�P��>ƻ����Pn���4R�T1
�T7����}�y��1
�T
��8
K�
��'
�T1
�T��
����@�
��{����X
�@l
��
�����o�0�v��@��0��<��;u�^'\�	=*�S<�,cXP�*�������"����c`�[����h�3\�5��j�����j�5<��U�gF19P��R��E���i���j���+�#���h�d���$�є�������Z�ۯ��ӄ��h��w���*�K���	�(���Y&�Z�v�V�^�e�1�.j�4�E�9��"�"�о���������q�rQ)�`j�#�KE�[�|���z�0�Y�`�7�~����������?�g
��drlf.�������k���g�*��{W�r����r�Z^mwvl[�s� n���jb�gn�z��������h�y�l�qf�S���B�[�<�	��.S���������������h�t�v�i�����K���k��������Tp��x��vn�mn`�j������|��������k���f�Z_��Fn������������ʬ��Ҟ���gn�����|�rR�M��H�h,�Irqprg�^�s�A�M�/�)���8�[P�D��0nf�	�iv�q���Xѵ�+��D�D�
��y�Znb��t�9�#��t��x��
�3���u�s{����q�[���Ƣ��᳚�s~N�\���
0H���"
H���"
H���"
H���"
��1
��
��V��K�T����T�6�  64"�
��E�#��E�
�E����������P�/"�@���Z�<��[�@�E�
�E�E�#��[<:Z�������
���T���T��T��@�T��T�x �T�)�������
������9�
__��&��X�.��$��
����K��p_�A���;�__��9�~�������2��M���@�n�h�
���M*��
�TK�����MT��
���@�n�h�
���M(���@�n�h�
���M P��
��M@ ��
�@��
����i
����������@ ��T��T��&�D�Nu�y�e���  �}������������
���
�V�ҽ� �T��}��
�l�j�l�l���R� ��
��~u�fH�7�Nuu�������a���������������a�������uuT�A�Mr�\J�C���+1
�7����}�yy}}yy�}�����K��}�yy}}y���+
,
@�j�
����������v��������j�I�I�J�#� �%B��z��Ϝԝ����̒�����<�L����Ro�s���x�z��c������������������������������e�%�k�������������������$�l�d!�������|�{�{�t�u�v���������\�������|
��k�����~��}���l�r�����>�+�+������������������6�Y�����F�$�&�E��{��Y�I�v�['?E�������l�j�o�~�����
��(�9���
��������������������0�tX
�@]
�T��������������
��
�����
����������������+����������X
�T]
����S
�Tg�TZ
���c
��������k~~w�~��}�}�}�}~~w�~��&�&~������}�}�}�}~������&�&�����~�}�}�}�}�����~�&�&�~�w~~�}�}�}�}�~�w~~�k������������=��=�=�=�=��&�&�
�=�=�=�=�
�&�&��=�=�=�=��&�&��=�=�=�=��&�&�}������������
����"����"�4���
0����_�}�2�/���b�����w�������_�1*���S����@���H2sp�o��ȫg� �����������z������z���������9A����{�e�z�p�{{hh{z�q�z��@�e�z���������������@���z������z���������'���L�`�F�F�=1<1�#�W�X�
����]�vv����L;�3lK@+�@L�V���	+�<������q�U�]�%��F���������O�^��e�PV���n�`�r�'s���y�sfX\Rq8dsض��������������s�F�%����Kٮ������J�}�3����������х�b�s�lt�[�`T��������v�uai4�.�:�e��?�2��%��ٰۂ�~�%~��GbRSl��g}^�`�s�t�`�an좾]�4�jމ�Q@���.���&�%�����&�%�����&�%�����&�%�����	�Y��J�	������I�������8�/����������-�p����R��%�s�z�w�8�����&����%����Bpq2z�r%�����!�����!��2.�l�?A�����R������჋Ί�t�,�����ә��$j�"u/}s-����|�Z�H����8�����	��	��
�H�.�w���_�������������pu�j}���$�x�������������l��l����`��?^���� �l�2�B�A�A��q�3�l����۴����l���8��o�km��YQ�SBjt��v�m��l�	�.�����ڎ\K��H�qX
�@l
��
�)����u��A��p�6������w�Y������l4����~�y������U������������������ѯ������W�?Q���Y�m}�ptjh���������F��E������Px3|�����(���/�ŏ�4��5��&ϻ��ą���f�am����J�?�j�ԋ�<�#�>��n����,�����i�I�Ι������J�\�D��Hհ���4����.���4��g��"]vzuyia=sA|M5#M�o�`Ba,����l���#��:��P�hC�t���"���]у��������H���������������ą�����������3��B��̖ڒ���������/���q��u�=��hU��U�v��@i�����/��
:�:��hU��������yr�w�>�g���g��j�k>��p���D���L���U���x�z�����x�z�����x�z�����x�z��������[�a�����������7���������M��z���R��?�ݙo����b�����4�~�{z����+�4�+�4�+�4�+�4�+���
����T���@ �
� �
 �
( �
 �

 �
 �
��
`�
@��{���������3
���
�@<
��A
��������P�������
 ��������
��������
�P�������
��P���� �
�x
�7ޜr�8{��M���1���1��M�����ז��@�;��N�����y�y�d�my�N!�4���p<%�����0���d����*�TK���j��j��T�*6�L�d�������0%��p�b�;�4�N�m�d�ylym�c�z�N �;j|@�������������1���1���8�r��z�;j�N mz�c�m�m�����N�T�4o;�b�����0���d��SL�6�����j�c�j���K��S��d�������0�<��o�T�4�N!�y��������m��N��
��]��]���z������Ϟ�Ҟ������ԝ�������x��x����y����5��_��_��_�Y����t�	~�r�l�3�/����������������r5�l�3�/������� ��� ��H���r�����vZ�j�G�
��?��C������-��������T%����%��\:�R�R:�R��_�D���D�D���D�D���D�D���D����?�)���|�8��oC��A��
�/��-���$��"�,�B�5��|6���-�G�c�K�dԛӘ��
�p����y��|���|u~w�'��~rb<!��ێ��j������w�w�s{��z���}qr^r}d�0�Gة蘵�и۩�޴�r�~�v���~�������������w�v�y�������������y�7�-�8�����<�ÖC�K�l��w�x�x�w�x�w�������������|�l�t{u{�l�t�t��������{���������h�h�[�sgsh�Z�s�r�����|
�9�q�Y�fqgq�X�f�|�f��������r�!����|��b�R�$�������I��=�X�,���3�|�Mq&�h�8 �?�4��ye�R�R�Y��Ni�ꏏ�������]ȵ�9ЉОȶ�%�[/�+���(y�f�qypx�f�p�p��������y��|�3����u�u�u�}u�u�t�}����������H��q�q�q�zq�p�q�z���������,�N\u�\�gugu[�f�g�������v��~�$��x�x�w�w�w�x�~���������S��w�b�nvmv�b�m�m��������w���������������p�@��
�����
���
��#'+/2<@EJOcgkoz�����������BFJNRY^ly����������������.9��������&.9=AFMQZbfmsw{����9BJNRY^u������-z������������<MU[agos�������"29@EN^px~��			 	V	Z	_	�	�	�	�	�	�	�

	



/
>
F
o
�
�
�
�
�
�
�
�
�&,@es{������������� -:KUcglu|������


/
O
V
Z
`
j
o
u
{
�
�
�
�
�
&Dbs~����������������-18>EKOTm�������������� ).7<DQYns��������������%:@Ui{���������������"',1CUZl~�������������$(-2BHP`gku{������������������$,2APWZ_drw}���������������+8EOU[binty~��������������	$).38CNY_doz���������
�<���<C
KFKk�r
=oYB;�
��E�#��E�
�E����������P�/"� �@�Z�<��[� �E�
�E�E�#��[<:Z���@���
���T���T��T�� �T��T�x��T���������B�t)
�
P
�����t�*
�i�@���E���X��X��E���+y}}yK��
�.
+��E���X��X��E���P�
�
+
.
' 
�3���3y]����hnnh�}�y���]�]�����]�]���s4�
.\��2��A
y}�B
,
F�TkB��B��a
�U�)
y}}yKy}����������}y�TN%�
��=hnnh�hn���q�F
A[
���]�]��E
�����}�t�����	�� �"�������������"� ��	���M
-
\
�
��
���������������1��<�0
�0
+������
������������
����������f�f�
��}yf_��"-
.hnnh�Cp
�}�y�T(
���-�V�`��C�3�}�y�Ty}}y�T�
c
���|�zS
�+o
�+�
��D+\�T2�TA
���������� ʆ��iimdod���������$��@�~� K������z�&�w{�y�yw��}|� |�}���x�z�{�wa&z��������K������������$|��'��������������[�����[�!���!������oZ�S1���
0
[��R
��Y�W�f�fG
�f�fU���
]
�@gw
�TH
U
�
3CC3X
K]
+>
��T�Y
�����[�R�Dh���1�
��T��T�T��G�������_�^�X*�D�4�
�4D�*�Y�_�`t��������W
����!�
�'��''��e
������
�
�T�T�
�
�T�T�
�i
��h���h�
���
�
O
g
�B
�4�T�T��=�T�T�
y�}��7�!�x�!hD�:
�,�����
�J�����J�4��
����������F��/�B��������
NPuc]�T<�O��d�
}�}�|�1B&�2�B����
:����5
��/���%�%���
YY�������������
�(
�f�f�����������9�>�!����
�
�>��9��U��G�
��@���V``V}�~���d�3�f�T�w�@�t�(�s�u�w�N�5~��w�}�+�}����PV�
������{z�g
�����:
�T�
�TR
�]�Ky}��Hg
�TB
�4�$�$���G
��U���$�$�
V``VV`�����
`V����!�_��I�b�	\�;COLD|yz|�r����u��{������������A��0����������%�����{[�k������@�hhn��z|������r������4��~������~�4`_��`R�`e9C/R&a���žҦ�4��A�'�"�)����~�4���U�f�f�
,u
!55!=
�=
����������T-
�/�T���
�����
�{�z���G�C���C�8�=<�<�8��C���G�C��������� �VV�����z�|�Y���Y�.�:�t��:���}
���&&��T�O
�'��Lf��eN�z�y�z����#� u��"������������=�1�?�u՗����f�f�
YY����
��Y��f�f����
������&��������/����]�]������1����a}�.
�M�M���Y����;���/����������������������a�3����:��������t�������@y
������t����������
g�Z
!�5�
��\�|�\�?�Z���E�ԅ���c��*y^H�(�ym�|�[��n
��U
��t�3
�������Z�Z�r���EQQEEQ��c
'>�
�0
�4Z
V``V�
���������~����
�����������������������z�z����3�'�)������������
�����{z�4���
�+�<���<�<���<�{�������.�=�=
C
�9�"��T�M�5���������{��~~�D�;��i�
�f�fW4��x
�!�x�!�Q�E�
���8�
���8�
���8�
����x
�
���i����
��������	����������������	�tkR��E�;V``V��<
��A
5
��/�
R��T�&
�
��
+
,
3�
��� ���O�>
��������z�r��^�`�������`���^?*<�씒������<�Jڔ���>��������@(
���
�St
���}��
�����
���
X
�@]
���-
���
����
������}y�yr�rrr�yy�
��(
���y�y��~�w�~~����������
��������������������[
�
���t����������t���|�z�@(
�Tz�|���}D}��}������������������RD��,�l"�7o�''��$�{��������������������������1���D
�
�������
����!K��
��z{�����8���T���(�A�(�A�(�A��m����t��������K��x�x�t�w�����~��̍�����������t|~�}�:����@�w�{�t�s�o�yx~����������R��1
��7�OI�I��gX�!�!�gX���g��!�fz���\�J�$�9������:�l�A~�w�]]�w�~���z��
�
m�m))m�m�)������{G
�YU3-
t������a
�h����N�0����������K�m��
+��
�)vP
�\��
��t�4���4�
�
�
��<
�A
���	,,�	�	,�	�	��	�	�,�	T
���
�b
�<
�TA
����F
���}t����.�+ݭ�����������������{����`�T�3���3�����V��@�
���t����k�r�crr������@�
>
��xy�o�ts��{�SK(
����
���������tp�
�����y�y����:
�������7�D�$�$�D��������������nh&�T*
�����5������������������@��$����$@!��quuqqu���;���;��uqf���
K<
�����p�������
� ������QEt�����'�rrc�r�2
������TSTdJ,]��շ����49��arwwvyr�/��������(DB%$�A���Ό������%
����`���u�ttu~w�c��cl��������q�t��������=�h�F��� B�4������4�����
��
����V
s���V�������E�z�*�6�z�*E!�!�$��D�D�$�
����7�T���-
R
����
�5
���y�y��C
�.
���@�h����������<���<�<���<����o7��������T�T�_���L��d��h�aahi`a�h���������
�/ti
�V���H������
��ԫ���ԫ��
��
��]�������������T�t���.�;���;��<:�Z�����:����3}|������A���P
3C��ɽ������Nb�a�]����
0�$�7o"�7�l�����
������������
��
@���
�����������������<�<��y}|z��i
�z�{�R�D3���$�$D�R����i�p���������w��������
����
E�Q��y��
���
���1�
0
��
fM�@�
jm��q�����������,�4[�
���@XtxmihbW_)�RK(
t����:���z�{���������z}R��%���7��tC
(
�t�
���z�x
����x
�
!5������x
����&�%y}��������_g��������g_��
����
��*1���0���˒�����������h�����
��`V������m�����������[
ˋˋˋˋˋ�7���ߋ�7�������
K��������[���L����z����������-
�-��������������������Ty�������!�5�����z��+���&m���/�%��t��~���-���������\�$�"�W�T�*��������n�h�t��t��t���v��������������#�#��
��	��h��3��3s�pyrs@ ��  ""
	���x@8 �����!"""`���>�N�^�f�i�n�~��������������'�(�.�>�N�^�n�~��������������>�N�^�n�~������������ �����!"""`���!�@�P�`�g�j�p�������������� �(�)�0�@�P�`�p��������������!�@�P�`�p��������������\�Q�A�0��ޕ�R

	��������������������������������������v^��%|�_<��O<0�1h�����	�	����	��p��v�_�]�����y�n�����2��@����������������z�����Z@�5�5
���ZZ����@���������,_���@��������f���@	��@��(������@�����@��@-
�M�M�-�
�M�M�����@�����@@�
�-������b����
��� ����5�-�8�����@�D@���,*@� ���������	m��)@�@	 	' D9��>dU*#						�	��	����R										�@	e�	
%RE	 		$�� k(��D�'	��	�%��	�%	��	��0$�.�$P�//:/K/Q]�	
���	^�	U	k	"y	U	$�	U	��	a		y	*�	<�Copyright Dave Gandy 2016. All rights reserved.FontAwesomeFONTLAB:OTFEXPORTVersion 4.7.0 2016Please refer to the Copyright section for the font trademark attribution notices.Fort AwesomeDave Gandyhttp://fontawesome.iohttp://fontawesome.io/license/Copyright Dave Gandy 2016. All rights reserved.FontAwesomeRegularFONTLAB:OTFEXPORTVersion 4.7.0 2016Please refer to the Copyright section for the font trademark attribution notices.Fort AwesomeDave Gandyhttp://fontawesome.iohttp://fontawesome.io/license/libs/better-framework/assets/fonts/fontawesome-webfont.woff000064400000277350151214002610020272 0ustar00wOFF~�
��FFTM0k�G�GDEFL �OS/2l>`�2z@cmap�i�
�:gasp��glyf _yL����Mheadb�36��-hheab�$
�hmtxb��
�Ey�locae���\maxpl� ,namemD�㗋�posto`�u�����=���O<0�1h�x�c`d``�b	`b`d`d:$Y�<��x�c`f�d�������b��������ʢb��l��|6F�0#�F��nx�͒�J�q��gje�>�"�D���>�{�E�O >�����,"�u�^�[[[���j�os���_�M��%:0g80������B�.L�s�zðפ 1Y��lKWv�es�t��)Mk^�Zֵ֪�m���׉Θb�k̳�2����6���>'�Y�Җ����jukZۺ�g�m2� ����(�4�-iEk�Жv��}�X�B��Y`���`����c��9�Z�JV��5�e�Y߆6�G΂�`3�|6����[uI�p�n�-�����[pL��0�Lp�;��׸�%���8�o��>F8�	��G8�`�W�ί�����"�E^�_�=(K,F�K�+�y�b�����x���	�TՕ0��o�}{�uuuwUWի�n�njmz-��nv�E�EAAJ!*�(��hD�2c�%F�ʦ�Ebb6���$&�����7�߹�UUW7
��t�w���{�9���8�m�8b�I�	ڃ�����݌7�S�E�G�!�3�����j�㔐=w;�P�^I�A;RR�n��k��LS�.��)�o8G�([��)�9O,,�At�S�
��h
y�u�jZupPGx�N�o��n��{��ho2�A�D�-r��]��u��5��e��^��dM�X�8=���r5ͻ^Q\�~��2��V�0 �o�0kC� qA跍����G<�
�9���v�`�|N�X�W�I�:"�'�a��W޺O=}��k�#�"�7�e	��%Vs�~-�y$ŵ������X��w&'q��.n.�E��K�#��JD�ڝn봽7����=�|�w�L:Ӎ2vmrRv:=0P�@D�ۓ��V�Z7eO��d��7�HM�SY�|�[o��f'B��L}��Ʒҗ�V����^�+�{W�=���uҤ֦='j��,�|;�v�A���o=��0�q8"�I³��8���yZ�6Ǵo9��q<i3���k������1%�&��
���u���k�����{H}��@΁W�—^q�Է��4;gg7���N�y��/��
q���P���OЌL�4��q�,���ԇ�"�Sv�=jL�/U�jC�-w�o���ȍn���j�̮�{�j\��
��vE��k

���z�>p�n=�^=�ajID(����෠���qu��F;э�5֮�s7;QC7�U��[����׈���yZIۘ�ػ�*�!$	�dⵄ��Ŗ�-ˇ?��{��m������f6��po��~�mԽw��o���G6M��oz�a�--�m#]?]?V��k�z��ܥܵ�.�>�)�9NH%�&T/� ��_���I�Ax���O��B��]8(���.v��)�G=���H�P�S�U��P���>f�F�E�-G�G�s|���'?~z�I*���R�|��[`���-V�'ݙG�P3b�'\R��I̞#n�;W��ٟD�T��ѹb8�0�^s6,rȥ��i��������sm15kk��,}��q��Wȝ;�t�s��e�Yq�qC/���0�q��|>��
3������W�/�ը��s�F�"���s��I�oAHI� 8��C�„���w���~�@
����_�(�]h=������r�9���p!�;�H���-[If��w;%=�d��꯵���bmH)��k=o��\���h�E�i�7i:-!mn:`[�G�]���GE,�;��s�yH6�2�ƈs�՗:��I��@�^\�w���OV�õ������<�g?]�Y{?qK�g�H�[��X��&�td�n�[�,�Z�!H�6#�=nݳ����;O��W�U����G4]]�6�ٰp��7��[�aM�5P���B�]?����4�����P呂����7o\�!׺ߜ����ؤ������
��2>8�/p�2�h@�k~ھ��B~�a�[�r��=Pr8�S�e�sc�F�
ӗ�� �S�#P��|0z��'�z��S��)��8aFB�FE	��V�r�J��(E���fDp���U�\���'h4P�� 	�j��<t�$>d3}Cv�f���M�}Zlf���,.��p��j1��t�Y�j�2�lƗ,U������<:�z��t[�%�Y!1v��M�frc:_n�"��7z�w�v��m�
z�ui��dt���O��.3K��<y��d0��3l�Ll؞�Y�ĭ~�bg�#8H7��J�C*gY��_��YKi�n��0�AQ���PiMg-c�����)<�9ܹ��JH�X-��o��w��aX�;�����<z�̳�@)��*��rw��|u�`���l�c����߸m1�:���H2yΡ�ؕ�d��Yנ�E�+�G�Z��Q
k��P*��.�6�O����W�=���n���u��B��d�u��8�<�7�4~c�8�(bK]4�x�~�*x�=��¿���1T��2��Gߡ}S�}����J�X��ùP��@z${P�™��"h^���b�ؙJr����`R_3���@|8~� v:G�E8�c�i�]5&4�t��َS��צ��	#�������5���jQ ��0즰���N`��v�!
�Ry�S(v
]wB}J]�>u��=�.#Cjn(,THu��_Z���	6�q���hh�P�4#J�H�%jt�3�M�)�#��z���z���dt��1Dn~�9�/��ȋ������B��@NV?�p'r��f:�;�b�B�QHb�$h�3�CG|��#v2�y�d�m)�e��sv��w�~٬�fp�~��DG�	�r�0��^Xzˣ����Շ��c���l&
 \�`\�8HHa��IC?������6���:5�H;�l��ވ�4C����&�\�F����jԬ,�|MC�ݔ��/f8��ܮ2���	�.��ҍl
_/��A���kT�V�Νg�~T��΂<`2����Q�&;�X�A�W@��@g��j{��j,�	�s�uuE
����֟���:�A��
8,&���ռ
}|��b0��lFQ$px=��4ddm7��nru"�N:O�u^��x@񝂍��C�G����*�%F�>Tm��?��2.�o��p������ˮ�1�r�\T��١K+L�؜c���n��:8����q�y�N��\Dv�j���[��ܦDy/�*=H	�[0�l�8=���`�D��d&�<����qR�}~��|m?9[�Y
{�H�I��FP��H�p;@���Y�����[D��]j��}�*ÞhJԆ�'v^��6XD��L���V�a@XF�k�<������N����.���pV�e�u���p����+O�;����FG�\E��нb�kfy
z��s��

	X����k��M֊P����Y�_g��#�f��}{���Lh.tMV((���/���4u�X�4u�<�k%�Ņ��s=x�f�Ȍ�ݐ��P��(�.(��q\��+����i}��J�/[��O��k<Ew{W%��҂p�RJ�
˙��$["�H�6#] �F���C�֫C�_c����|=�F�2[�#�\��eyÃ�.�a��nơz�K�9řeN��Ԟe����Uտx��Uw�Ϋ�m>����76�t�O�d�٧�,崅v���2+�׷� TU[�NHN8�W|���fG{�ܘlT�_��Z1 ���8j
�`A����r��㼌��`h�*�b��
���#����ռ��B����j���0s$n�^�7��w�$�Gɡ;�N
.�A>3;M��y��?��zpͥ�Ι��4�aqp҃GF��w�|]��֯�!��ؾ�bv�q8�e�+�)��h.,U~�4]�h.�P4s��)��+k�q�D2�u����ϸu��E3V�⭯�ҟ�f�S��8��/D�]5���ޖ*xWG�j���}�l&k�lnçi��Pv'�6#�������(%��)>q��E��o6U+�6�ŋ�8ۢ��lޏ>���`����M���n'���'��zB-t�/ꬱ����3ik�3
���55��Z	1ao�|+�
őm��
��0$Yə�Oa��1ag�9��up�9Gת+����b��=H߀��Q1h�T��]�Ғ�Q���^��?������s9��ػ��� ��l��B�|4�TN���YBL�,�
g�#�5��A�㉐=!�7~=�/X]W��uw�ZW����避[��Ꞟ�W�d==B��m®�ҏ΋v�?$���
E#
�L�!7���ط��!����T��RR�I4��)���H#��l*�:#��H.���)����pӇ�
źR�M�B���=�ƅ��(ǂ�͵���˥�>A��,�_��2�%�5�p�yn�6/���Mb�t,�L֮���l+�9�Q�Gb]*�D;�
����{PZ!�*��U1���|���s��{�"�3�\�g�������Gχy��G:�-nQg7��`ԏ3�x���Ax�%ÏU���XMZ�&HX9�>o��s�Ga��
��'��!�lü��|�EW-��e�b��bxs��Y0��6E��>�)�V��H��߰}��V=��G~�Yk�h��/;��ۇ��0�{4.c��\h`�5���
F�A��5��Tg�[4��#���S�o3��yuy��=����<'j{�	h�N�k�6�	�@1c/��5-T:��`Y�X]��g~���i��l�p�!��e>�1x06�?�e�oA�s�b���̪fy�b3�@B�߂�Yq�?;�m)�h4s�k�P�����UfW��62��c�>8F�(�t*G�C	ym
s��r�p�?��I��C�Y:ϻ&͜9��9T�Y�-k���%�)�@�|FF�h�9*��(Rt���K��ǻ�T��XM-IP.%�C"���?�,+ˆ�=��	��>�t�����U�gQ���W��w#�Υ7݋���[��P�	��ޮ���'j7��7̗�9Z���I
�S����O4YkDE�͂�B~�`�Ig;�m�����u�֢z�Sg)����r��E܉�=m�K��9�ZD�]�4����~7߉R6Hۂ(��j��i!�BldpӜ^���zz拾�g�F:�qꢝk�Wl�/С��uX2�r��TsB�נ�����ͫڂ�t�}}ƶ��_5�	��k�4���	�A;oH�L�Ϲ�)�z�.�qu���A�z��yx�j�k5�F�-��@�lҙ��c�ڗ�җ\6�=�
���O]9�/�5ڔ�볝�\tO���C�T3�f(i
]�w�P��iQ���w�γ�=J�ߌv�Gޮy���[�[���,��Et&Q��o�c�Â��yb66k���MK|�֋$Y��z%���P��(���^�87D�rK��`��%�5�.�:��	�Ďx=m��n�ً���m]�Ю�&�2G�(-@�Q7xu3%@�p���~н��t���S�]���=�)AG�����A��Vg;��*=�$mz
�-|_E�Z�ˢk�<�5U5�fF�I�j����`�=H}���)0��~�F�,"���N�6�k��"��}�Ṓk���T�"$��mZPc�',�ϛ�tz���Յ��];+�j��+�NG�>K#�h-zp�6\��;y��b�~�9�.m�	�\�=�qrqü�=fS
6�u(����؍��3���#����0����
:�Nz{S�M�]"��`R������.C���r`-��U{낍�z�n�q��	t�x��
�ic+Ԛ:3Y��㳙N��*�a�V��P��
�`�1�Q�b���@fc^X�9�̼���ܶ����jtҜYӂ��hھ����3�	i�js��+\�8Tv��i|�Q<
v��߹c�8�1���-��t�������\1����6���G���I��n�J�:̇�h�X��G��r�+��<�O�|a��l�yxuco���7狿P�'�j{���G�w��s��ʥ���s�����
?��?kL5>4��Hj��v4���l���!���,��c�C�5�4{�ٱ�4d��R��~��p�*;9n����C%d��}�d�A4Q8�i��O�i	���T����gd��ul�U�S���A�q�$.j6U;�MǶ�ۏێ�ۏ���j�9J�D�vAF��b�m�LOI=`�j�f:��>Iǁ�J!�
�6T�xư�qn���̓��S9�ĀM|�!ґ8X)��h�ͅ��ͳ�(����,�ӌ���2����+l�D���3Qɕp�$`�Pt�[��� ���DV��2�op��o%x�Z)�����n�:p4�N)�F Նt�T7M�u`8��P*r
>�(��O^����tX�i(��M4!
t(�>h��cU��<�@��ܦç��$�M'���(��J�׳��Q�܃�<8�Vj��j7P�?Ͼ;�������_��!Q����.h|:B��)Ӓ��xܘs��_���d9��aN=�.WO.�\|�_O&t�k.�".D�p53�͓	6�`8���I�u�����Kj��k/�����wi�U��S��us��U�lr
̥;��ѠMe`�T���B�&��n¦\�	g2pd���[0��O�v�z����I�'m%�4���1}�@�€:įZ���/r
@1m8_.���W�R���lv(F5A�ս���~]*@Qؿ
V�����g��M܊�����:M��ʞQZ�㖵��.
H��f��J�wK�IA��\������f7�z��l��}5�V��z����G����Ɛ�
u̻vߋ�a��ɰ��Z(�S6W�z���7e��k���[j�����#6[���6i���Sڣn��@�d��`�[��}�i�]<{b�N&k��G�[�Q������`E�������k�$|'������GO���R��4:	y��X��1d��hz3T�ʷL-�3��D�G%�Z
��b锥�3�I��陌R�^cy,�3��P!�@�ieNq좀FS'}@4�шÏ~�����*�T(�P���Y+�=�!?�}>�Ю�+�����w*�3�U�����sƽ ��i[�9�a���\��u�We�Y5���	���+����,��iK�\��ʚe�<����z��K�C�&�Hd�bktݩ7<��Gh���
�f�O��fp�+d<�8�Y��X��(�ϴ�s�>!;B�TR@J	vK��U�8�bU�H^Q;O�k�b%�[Q�H���O�9谉����0r�0��}����U��>�ʔV5^����ܵ�����}ecF���mۈr���qLEl��	"�I5��ڦ�fU���2c��W+�O,
���MJ񝁧6���y�?*�0&N�ݚ�xq?�)��>�e�(�	@��qT�Vx��>sjA�i�2W@�W�<K������P
+
�i
���4�(ا����	�
����xA��̓��	1Jz'O����?�<L0,;V|'[�9;j:[��B��خRk�nC�.и�iޱ�T���ݝ&[h��5V�,�R��I��N�{oF|Tn�_|Q�W��>��U����{L�Г�K^A'�96&�E[h8�����J*�X�>�w��yW��+��V���c�*��Y���P����!���3�
��^������%�"��`�ɒ�R������cD@�2�ܵG��5g��L6}*X�l틵�\�"������*����p9������B4M�z�A����65L��.���2�k,0���^�>�G@���@H�ty����Z4iepWt��A�h,8�<{9Ƚ��ǷƶwZ��OY�E�<���Z�)��t#�/�崐�\F7ʔ�B>(���&��6�ld�i��t��/���=�n�>?&s��]@Ν�0Z.3Ĥ�9M�G�6�XI�J�H�Xa�:��C�}��3����6��~>�D��3��U�O>[vZ_�}ס�qN!ʃ�
��-�W� �������
S���Ha)Y���'l�g8=�`z��(bwv�����i:2E�!��`�;x�,����Y ������ߩ����
=��Іj^ǻ��Q�^��_�Yy`���Q����[&aY��Q
u�s0{&m胑*����j)���T�C��$YQ�>*�P����}H��������˥��_�7��!n?Vا(s����O�GRB�X���bG/*󨴉b����E��(��"�lrʔ$Ϋ����dJ�wGp6���
P�/�#j��mtC�R0�}B�j̣R��X�v��I�>(�j=���:E�C�t�V�:O[h[5�"u�E�3W�.
f�[eܫ8�P)�e
�0Rԁ��d.ُ:~}����t<)��/Q
c��O�B��GGp�<��"-G�-b΢�y3�b�#����5�RPCk{d˚� ح6�d��]������L�d�Lu鋶
��LCz�Ӯ��IYs�;�A��@*n�yڢ�����Kˏɩ���E���W���eM����â��x�[�*u����-z��җ�rizH>�������2$�����=�_�����j7�{�!�h7Ύ�|p�fs%9LA�Q,��2��WH�(EEug��&�/�
$̃cm$0^(K_�C]D����i����+�/�TR�hOJ?��N���ޛ j�;�쁳�#��ISm0Q�4W�����Տ��5_��fd���"0�ԏ� ��~D}��R'��k ��GK1(���_/�T��F�Ȥ8��>��Q8����m�.m���s��t�Á��-��`wZ�a���x��x�";ͯ��2�o2�:�h*4X���-hW�3sn���P,ɞ
��"ޗ`7�Nw8ɐ�D\���	�(,f鄝�	��I�M�|؟��ն���k��ÿl�5�n�v�xL/L��M}��ݻ/�Е�um�.�u��m�d>�Nh���&k�Ե-h���#�
+���q����s�}v.��L��8�c|�P=/2�,��T�,��\f��x���P!:*���}��uL�v�yj{C��[��	���^�܋�����lV�͛C���Z��k������9�~�_��+�2_�ʗ����7��%�\~�N�V�w�|�:$^�fH����-œl6��[D���n��i�D�>�=�}4b��=�U{��x�C��u���:����6ݨ�18�=�Z��%�ܓ��&��?i*�V�߻"��z��,K���=�,�5keb �PÒ��}aM)d��Ő".Aǝ�2�An�K%
���%7;��QΤx9:�J'���s�������9��:�(��w��̿s��lt�W�����N�~�+lA�ڏ��m[w�7���7n\����W<9��-N�߹t���i�?��"�;�i�w�[��;L�vP�2�z����r�g�k�cl;#��E�*��b��8�*�<~h!������:�Q�@�qӼek�/��#�@w��ꪫ'���	���r���*2_�2mp�pm��"Oގ�:�wFgR��ۜ����������{z�h?U_3�������m3�ؾ)��[�_�.��/��d��
j�����G�̨�.��+{����7g�|�6w6؟>d��5��;{O"�-��<���+�jaW2�2�����p�����W�a��g��y6&�Bh��I2%��1���S������*�[Ϥ��F��۷�%nwT��	Q��Ķ!=����00!�dP��$O����j!%��l�6bd������[6�,6��`^H�fɖ3V߶[��8|\��M��Q
���lƜYxj�?KO�3��ٲ�%)���)JrGƼQ��̼)���2c�"����^�–�;��@Y5��u�!���'�h��VGTi M9��#�(ן<�4�s�{��������@�e�fQ`�Gy�
�8�L��"KB3�+��fOx����_�c`=C@�d�-T�Oj�+�Jw�]��f1���򉠦J��� ��-�L��[,�Əv�u�&}��z�)Aԫyz�X߶"��M�Ww�P-蒺Mr�k����
4�4L�ZvɎiZcK���U/N��j�a,�a����!"Y<��]�K�����-��������{S��&�,�-��l�5�V�(��DSJZ�������U����+�6��U�Ԥ)�j�ȀMXju5xk�O�x�kC��f���>���v;o�Ău)O[���H<t��_X���4�i�+*�d��Ԓx7)�l��O=��R�|O��h�\��ؼ��E�RD*c R?ʇ�﫯��"��bL�+n�wSB��IZ���^��ģ|��r#R�e���A�>����%��rJ���r�ZN���C�Q�n�?|��x�����_B��*k��gY�n��3:B��4Wͤu�Q�������.�R�M�F�2���>��8�G�3J<ZŠ�r���Vŗ�Y�~P�9��w�;�<
+�iչ+�5�D��D�hp,;ʹ�j���fƼ=䵫9�� �3�Ƒ,�@�('h:���Ƌ&m��TkP�q�8�󨴱�!�ä.���#��Q�{�=����=4��V���#��m���x	�_�)If�C�#y��F��N�������
u����Q�R��PQ��y��Q
�u�:�]�g�*O<�j,0?��g`O�N\Z��\�F�k�rIݝJ%QM	$%G�/-�S_hz��t�>U����֧�c��'��P���fՅԭ���ں�o�>x�,u�����P^��"���������yXdc�i+�Y�_'�z�����6~(+q$��U�;{S<�^x�Gn}���ou�vXt%�&3`�.:gA����'�%��O�0j�@E�w���:���м�jd���q�g��e��<TCB=�nҗ��Cq�+���d������)Ӫ�L�Z��&��ίYْ�bv���sm��������k'm�xl�0�k"���ȓU��\��{ӲY�zY��.T���Yt|�"�������cK����:6�.4L�S��z�D&D��LJa|��+Q����h��_�}�e�Ξ��z�_���
b"	P8^����Џ��>�����4c�&ū��Y3�]��*��tI�*�
r6% ���&A�R�^3��$�p��,a2GÇ�}O>W4�7�6Ո�n7[�Y��Nq����O�e�cu/=�cm:&�4���C�o��<���}��i�A�O6�ă�N�Y�����m�:�̲f3�J�"M��K:�Ek���:e-O��7�
�6��;k�h}x�?�1�/\���g^��y}7�|�4����q���'�7o^�� o.�Uξ&�d�5���v��� ���3�_P� Mp���Ĺ�V�jl�U�	��a^vqǹ�܈\��?虽쪰��:���Oo���b2AL2���9�zXv��Q� VUq��^�k%@���$Ǡ��#�o}��Ts�cFW}�$y��F����$y^2:�����l4�/�m�a���Խ�&�o�L�3Ѥ�N��Iq�!�#��ĺ~������N>�0=�ٞ��bD�A�w�	���O��h��C���Tѡ�
�����֩F�I��.��M[�V�#�Œ�3�z�e�{��EvceR]�
�
�ecsER����n��`{ah��Z]���'3W�0v��Ix�V[mQ�8��f6�4�Sc%�Wr��F.aR�6�a��Lv0�n���=,L	�Z�BU\���]�a�JX��L���7�e銛
ljQƀ�c��H�j\���}MG����ޛ
�[X@"�W�dNS<���+�������#(���;<�"w�~o�myL�'�D���pEb�Y?�~�{{����,o,�RD��(J�bC�>�ܶ�_�dՇw��f�f�s�ܦk3�ގ&��~�L	�=�$&���Cyd�"�le��؄� ��tQRʉ�@*����΋����7����JՄpC��#5-�V�g�o��!G�i
4�&��N�pO���o޴խ�9�k�'y=JS4���/�;�٬����v�Y��3M�iB<�
���(Yuv<�9_�m��@|zU��
_<'�;��^;��#�b})�K�yw���n����o�%���6��,i7�-+v�(�k6i�c"Ym���=t#WRT�����m���R[����na��<���j
X�)G�VX�,��gB���&blц�*�ϸ"^(���^�Bk(tǒD�>f�ʭk��l�W�޼����(�I��d�r�U��U5=^�Df�j}-���:�$r�p(��<M����zM���Ư:|�%7L�>%\�x�+>w�W�؄	O��u���
gq�/�,��W:˺/Ɏ��+�����y+�&��Lo)�	���@�[�@e�x���b�i�u;���:��Ykw�[50��x:��r���s�S&_Xx��f[b�T���:7ak�}���Yx���<5����r'���(>q�-��p�r���o��ɴ2��H��U&�I-K������m�h�ɠ\���YF���Y`��|fM0]63���B�w5�%#�'iH(�8�[*�k�.�Etc&a���Nm�V�JQ�K�T�M��b�X4�?��#4c�왓Q�,<��v�5���?J��	[��J�s'�ڛ�iӒ��Ӈ�C�>�䶵���h��Mz__�m2�7��b�2�HC'���
 j
,J�N؋����
��Luq�M�Z�W7��'./�^L^�DL���%S�	������n��4:O�W���^�o�f߷Rпl�q�{��\�PȖ叙y4*x�Ba�v���� k��x@͗qY’.3�HQ�F����|�:r�Ɣ���9`P_�SRL���
6b�|jAn~<D��N��"�u���0��Q����\�� W��u�ާ��fn6�oH�玤�N	N'�S;���)̓vG�vejO��XJUP��s�p�����s<���׷4�����}��a��m}S�j�T���Y�Cheubm���20�~�t��'r3��:_H7��M�笜�Y���rN:1��!-��z��\�M�a��P}���l��&pq�6�*_U�Y�IG�~O����_KU8��FT{��t��(���av"CBf���_F��;Q��n�qӳ�B$MU*r��g,�^��GD�,I�H:7FD�	�Jl���k6��c'�]�u��;��&��Fb���F��iB�"�&͙Myk�U�����P�\�M���]J��~q��Z JP�$5K���?��1/,#	K:I�)�D�o�Y��:Mg�!'�S��$���M� }��Ê�N��~�$��Ū��3�w��m6�]r׊s���O^�
��ll
6�H�{R�vB����o���Lg(�i��Z�hVd��˂��]�w!��r�<3��H�/����7Cy�Y�N9���Y����@��Lc���eY�֖�Y���$�rz�2�d��k`����8v1�gI1�"0��k�~��,��c�$����ty��h2�^/�sv���骩m{��T���UM~{�W���Ï��ɿm���k�U�ٹ������?��΅s�4a��:���Z�D�g�;�@�V�ם�4����`�gلw]x�/���g�o��L���v�w�'v��ڟ��ڔ��y���K<+<f�>�Ǟ�����~NF�=ΐ7�.'�h��ٖ�}�t�)v�SK4�Yԉ����s]kW��N��-Я��K�`~k��R�-^���"9BF%`%5��S'$��^\o��;��NKM#_5y�<C$(V��*ޖ��Zj�����/��IV�Z��et�M��k,��x�C_m��{�ۏ\�ʶ�k@1�R�+ې�.����臬������t�и�����l���=C;�x�|^c&�a=w���9�9��p�t袋�Š��7���1��R���1@e��a�����<�3�w6��Lj�(
~���n0K��M.��
�E�aR��I��W�1[S���,9p'��Y���P�M>�r��֖
�j����K�g�M�dn7Y
n� Nl��ݮ��m�G��Y��N�̂0�9E&W�K��b�K�|�ĸ������JﱵWr{�ݷ���kQ�cZ\2�R�؛�O����ۡ��_��h]��Ը��y��&܈V��;~��M��/�׭�n�߮>�_���[.��/m�2������A	�q�J���{�>��L���M���8�A��f��]��'�v�HTUO��μ�Ń���̚u\�eA���b�~�u��:�y���nw��������ݥIٸ��$j[Q�����V*b�聇nE�C�*�ZɭE�o?҃�&k=�t��#��=�K��T�rf�W�Q�jJN^yٔ������Q�W/����O��o�^�rr��j��;�N�M4I���`0wϚ� _���ߜ����!Io���uz�#�3�tz�i
��k�j��m��f�L�'��k�
^9�u�Dћ������Vn�Ǽ^����߲r��n_����CSC ���"�6�Gi1#�W���0=p�'��]�@8z}�Q/
F�"�̒��&=�lF�w�d�F3v1��F�uDFY�V�'F���`.bN�u�䡁��V�l�|I׀��ɷ�*�~���)���Z�*�!+��u��Qv���C�M/��vԂ.q��c���Ys��,������wD������iN6� Y���r�L����U߲�[cr�c�q5)V��!�c0�31;�B0ތeG͝Ua�V��NU�e�	�(��;�;��|d���;��_T��A"�?/}�M�i	���;]��w�t7W�Y㰛�n�����Ng��h7���E��B��7_R�E=S�x�V�5P�s���m�`�ržYa�������z�Ra�t��	�k�����_�F�=���dVٿgC��j��߇%��T�}�[��n.�Z$��Uq�:�ۛ*<gg�n�Gh�(U?.b�=Ђ� z��3ek�
4��	v^�QVJR�T����+N�1�E�y���D���;Y�C�+�dN�A݇n$9�M���Ay��hpJ����=^�蹭�%[ҫ{���\r8L^Rڠ����g8�ޥ~�a�d8U=�gP��'�1�.#l�
��=ΑѬzR6��np�~[�E��fn��G�+y��|:���f���E˻�~E׶�M�ʟ�]�����f�}jE�3�qMOϚ���{��d?]u���U?���#�/;��s�~���򹃫ؚǀK��-�6�B��'闘̵�L��gc��g&�=��G��'�
���}�S�唩���VC�I�s�y�����RCM�)�r�d��7&UC͝w�4�N�sc�a7�fl���]t��Tw�ݵFè4�o��u��֍�2�B�>#o7(���J~j�E(�EM���-P<��n}�en�pt^���
�^<���5�fͬ�>3���/rQQ@��Wヌ�����(�Q��Um��)!s���G��7����ꜜZ�4���	��…U��l���ڟ��p�d��:�Cc�e���'s2�E���;�u�*�'����$�]"���c4��}�
v�zyDz�ɨ�n4��bTF�.b4R#�P*��~6��t�jt���ŋd�ۥ�y1W!�ןD}g��lْW_A�4R�/�u|��]���P	�Ǯ~��:t���[�����94{-�.�ǀ���y�A��0�� �x��6-NMv�M$�c50g���hQ6����1���B��n����W_u�s��;B��E���g��}\���"\�a���Q=�#���ͧ���վv����1�ŊS�Y(R.i�[��9��Jd��QӜ<0@B�Nya�)�j0Vh�2쬄�s��O�eP5>I��~���1!���-�A8ag�j�Nq^7�6��e��/�쾇ݳRuԢ�Z&�U�EJ��l�p�Yo�<2�"_���:��97�9f���阎���.�!
hI��4
Rk��Cj�G�Bu+b���tQ�P�u�/А1��TZ5�����V:+�zp��8��j����y\ST��!�zr��u8Y۸$��Յ�F�uFY���Tj
+[k�j`�GŦ��+�yl�֦Y닍�4R����,�+��h"�)=��U�>���yV�˕!��V]�Z�8G_
jW��p��H�� ֬Q6P��8=w�Q9�]W���80��9���{��z$�5��p�+��҃D%ꔒ�-��R`5CbJi��h�EI@����x�Q@��-�J����h�n��א!7���#ם��Y
ѣX�����2��M��n��Ɣ���i&�#i�x2n�B��~��#��}2n)Ͱ�.w��o��B��(��Y�k�"��5n��G
PTF����;�N�Q@�(�奣$���%l7Q?��lR��P�fB!w�ҤJƝa�îG�ٍ�J� �vK�g�WOӬ��L_�$��t���a��[!i&�M�>J�LBf�R����%�ۣ6!�o����"$�,J�{�l2"Qo����#BQ'!"#����H�:�.	o	��<�9*a$
<1ʔ/-
᪠(J&���$�
f^o�ћ�<o���n�!����A���E
fl��5
��H�<�o!ͭ�(�p�N��tH¼բ��.�a.�&3�!"I�:L�fsZ�0A�:�A� RE�E�b"`��\�`qbѦӻEA��lr�Zg0��_
�X0JX�	�Щ��9�1��"BN,�b�q�H/b�I����2&0�6�IM�U��%U��	l�I:D�Y%�Y�K�xí�AЛt�PG$Lx7��0lĤ'vluۏ�x���!"Io#�E�NF.�`�E�b�Uo���˘'�\�y�
����~ّ��$�(�d�Fnd3Haz���I��+F��#�&�z��h$�Yg�u.����X���l��b%��N���[/���*W8����BV���0f�^�@�`^y'/T�z��:h��M�#�$��<E�H,0���A��o�a�,0�(�i"!1”_E�63�;�x���Mr��X�v�uaQ2���C_�yY��#"/輘�X�Hp#9x���1@1@�
6�	Z ����m��݆�Q���D/��.T;O|�`1�e7J:�^G�	:^��&#�a�A��$è
:d�z+
a�(�~�d�D[��i��F�XVX��DX�F�'�
:Cqs�����jӎp�q��2��E5!K(����K�Wk̙�g�ط(����h���P+���R���^Q���-O˻�h�@�&�l�o�%<x��j/ޅ��G6R-V|l��ht��iL�`���xlhY9��U~�S�㨆ӵ(�`*�J�|�u���(��xn\T�"K��L?�
gKl/j����P�[�&�cr�n�l�*�oEŅ��u�̬۝�dU���F�W
5�\�1�v��C@��4P�b�|�M��e�^I�]%�S!W�}�`��*�_��U�<���(�cnu/�Xxh�w���
���)��k�0T�$׻Z3
^�^v����1e�F��g'P��JAR�#F��,+E��Y�@�'��C�K�_}B}�~:@ŏݏ.��g2��K�.�L�KZy��,��ߍ��6:&5Fs��n���-Ț\%��۹I�dn
��[ɸ��@�i��5�]�i��v�$��t��W3�L\�	C^\L�>}��6�,����+�7���
�g��2�.��;����H\Ұf��,-Jǒ��Ew\��B�wjǎ>�fM�.��.kl�Dj�.Xv�}����mW\:5֔j����K�ضV�3�B������S��$l��&�ijD�YdIO�~q��!�rW��)\�3�
H��.iT2�R
˔D��'�i���>-�(*�Q�����o�c��$`������g�#A��ꆘ���0�����ߨn������7.>�x��;w,yc�?�Ơ��3����6I6��1�q���	���($�����,��Njwܴt�r(y��h�2�l{s\p�@5�H?��]�J�Hʽ���<l��n�h��'�1��P�mϣ�So���7i��$��½݇�����a͙�~}�Z}gP��$���6M��h������M_:�~z�{�dZK�e���:s�/޵�bR��+ʤm��.F_�����-m�AE�L��ǭ��s;�;��\�激��q9��:��L0��hֳoȰ�h�mS!��S�b���f�D"N��� (����(�YqG�"�Č��;Ck%�mD��D�͙mvKa�5:p�5��<p��Fi͢=Oӛw�4�->�g�Ihh�h�{�� ���e��f��
�zUs|�+�D�W��xst����-�}�"��<;�p>�#��?���X;$}�u�pȖ�ow/�&�ν'�dޒ���M-�3�g�֛떤������$y���I��E�uR�
;�5�It��Б��f<�n;u->b��{g���-:��6ާ���>�k�0ڹQ��s.A�,1��xB��U\�tBBA=
��)~�3�.{�ҍPa�~�OBP��:s��QS�=��:Uf�s1�K�ɗM
�@����P����s�y���gQ'�)�_�@\l`�|N�1�6f�p�p3��,Y��,w�Z�1��~ט���On���oy�'�Ǘ�lfC��W�?�Ot=��Kz
����(U�QC��dP��n��.<����=y�]��S����d�2�K�Zu���{�d���^�&P�^	q��h��E�AakF�Q���7>�<�~̈^�=Qby��A�s�X� Gr9�A���ժ���`�	����Ε�Mʆ�돱��,����,)���4K���ݑ�Y���Z���?0J�d\;|���h��~��ki��?�e��v��宰�����K��v��2�)i�9J��cj��~�Uivo��	V޴�ʍX�~�eC�k�ˆ���Ɔ�K�ڰZ�n�߹ZX�ko�n�퀭���:�h7Τ�����G�+Ș��}I��]Sfn"u�!�`*��ئ(E3	��M�N�4���j�nRX�M��Gs/Mtb������RS���{i��+�-��v	��a�J���u�3�Z/�WS9ZK��]>�Ɵյ�68N^~�i�>v$�$�&x���;�ό/n�Tu�������
�_�p��d���R7���#ƌ��]��Kqk�^:J�1�)Ǥ5���$�2
;�ʗ$X��[���Z(ޜ�h�J���7*�%2E叙#����z�g��{��hLK,����M�������#�ǤOkdւ�n�n��V����Z��Ħ��پ�[���ȷ����kV���%��ʂ�:�@S>Զ��}��S���~�.��vm[k������l&�ż��V�L��s��H��uvM[2���/z9ն���.�S<#y\�6 n�G����fmȬ@���xʃEӻe���iwX��D��v
[#:b��L�_�hkm[-�Nٌ�E��Z~�emM����%Y��뛮��%���Zbt�h%:���9}6xn��.��^%,uXF>�.1^�x��o��U��Q��O7��������}����\�1�B�,53V̒ׄ���'Ō�z�w6�7Oi�6��o_���rU���qp��,�1���qOi#*�n�;6������F(�Ny�'�+ܣcT��q�<e����LA�"qe���޲Sq�x�LPQ�W��Q�W�y�h�Bf��M���(��[�vL#���ۛ�Q�}�;��Ε��˒-�$�glY�o+�s8q�N�er:��@B���p��&�*АB�y	�����RZhMKy-Gۗ����̮!��>������3��3�3��~x�h�4[� �A�=,O�c⋢�rx{�+=�.z���f�G�A=��SM�ϒk߉�kѥ1|���u�g�<D�k~>�\==j��=$��rR3�,��xٰ�U`B�!��"LQ�� �Jc@(��{˯��F�/�����4��3�i��bM6A�
>A� �0Z��������(�	��zc��d�I
Q&������Z+8L�T�W���&�� ��a�Q<a���"�*F�S)1�^T�}uМ�5`��-q'6nh���־�ڻ�O׬��%��3<h��%r�ܿ�e��	:b��
VY���z�l�N�]6��p�/oyiOc������5x����r�M��{�>_�ؾ��v��5������>9�X�ru�ʓ�3�r0�rd���e��t�|��¶����L�d_���*�5�hct,g�}��W��i��\�<�c�s���p=�i�v6��l��۽�N��8��E�߹�����ٿ}aq̈́�s���+Wߚ
D�ٶ�D^�؉>[DP�jq\j3t��h �d[�)��7r��h����UW]�jiK�97���
X|����/����>g],p�K�4�Y�W_�ځ��/&���-�.S���0����+���0:��A��H4bc���7o��|~۶�F�y�W��ub����^yV{1���
�o�8�����S8#(�緥~���w�޹�jҢ����6��ĉ�"�h0P�T�	u)�� �$�`]+�E:�E��q؎�W7jD����-7�(3�uŲ{�Q�l`Y��$����OC�oɊ���= ��;h�>���E3g^tP��e����N�B*���ʘ��!x�%�	�֙�Y}IK %�ep��H�	�ZR�́�H�+!)�ʵ	*	1B�1ˬ�B`�>� &�)ç��	&��
���)��,~�)|H}��ؚ"����od�A��[�aO:)�禓�G����wLr��(y����ļ��C��g�Q���#[U�N��84��~��c�!yz��ݰ��ҔZ�3�;z�ss��.�F������M�ؾ�1F�SI`A	��4Q�ByE軼a�"�Oi���P��S�b�nByḰ��XK���G�����`SVЍC/|WM�߫ʪkj��v�!�:�|uQ�(�U�Ϝe׷��]N�#h<;�����v�U{�}���f��j�H�%X&?	V�u����~���V~j����6���A'��MY�v�M��!�GP۹re紳�� ����D��k�����/�s�)�k�q8vI8��#x�
���G,�c�?��;_�?��!��sy�ٯ3��ηw�>w`����||����t���u�P~I�����hh�nE/�&�j��y+���ٸ�uT��S6�o�o�O�oh-N�p8ޗU��2$�u�]������v$0$��
c���߂��S��T�6��h�Bڭw�.ci��[����ҙ-:g������<F�=�*ǫT���9� ���r��%@+�2�u!t�ޮՒ�2#��ލn�A7�A���YQ��Ⱥ�U���ax(�Ę�[6��b��œ�8���{`.�92q��+vK��$	2�+���p��*~M�r����Vs\IΤ_!���j)p��j�f�]_^ș�P�G>��*�K���h�q��{F�A��
�lW��?}�'�M��R~<3.(�[v<�QHPC����c
}I�br`\~`8��{�;N\�w��Yu��I-��U'N��y]��9
��Kp;�+��I^����^�V۳dv�9!Ns�߁��_倻l�1p�~�G��� p�F#�:��:ԅ�[���	H��˯�����쀿�":s�-@w��;1n��3�+���U�&���97��ϳJ�:���W���ja�3�,���)���a>�� ��'Tgx4J�A�]ԧ?21:��yA�c4�Qd�8�`��b���4�D�lu�*�l��.]�&'� ��N�Y	�?�_EJ�OG�#�y�n�	^��TA��/UB
{d��Ȏ��U�}xX�1r_i}~8b*��=�^]W*s->��K��d��fgQ�U�(��s,�Ze��M\�����]2�)�1
��$l!?OnG'o~��P]h�꙾V�'���E���6Fo���/�q��+Z����jz�*�S`�O�Ɓ�| M�U�a�����{o���0�3g��}�(骪�5�J8��+�5O�OWU�$#��+�����Z	�J,�2Y��i�n���>Ŗ��X���p�'E!��4�l񺻜��i��	S�(�߁T��R_ʠ�̈́�$^����ŊM����O�wޯ,�cӊф惞�\I�`�T)���&IX��3��W��
Sv$F�ݸ{�e�1�fH�ț�aw�(Q �\�9u�\����O�x���7N�Ѝ�%��hۑ\W���TT۪��˻�Um�ʂ�j���r����S�-���kU-����n�E�*+g]4u�,}���뮻mf��msM����X���9�U�uu�UNGQ>+���U���UG7O���(��Y�A!��9ې�#I�%�y���\��gf<�/
��Z-H��L�HP&O���E�Z�:�3.&0B�}�H������`n�(�.�Y�2�,L�~�]��Da��x�Q�`2�:��6_u>�6��)+���{?�D�C�<���Uk��mb��~�c|T��`�ᾮ����&��
>E�7�"B����1�����;��/��� ʤ�A�$v�Bf�������Ytج�G_))P@	p�7�:�z3hfa2
������:v(�^&��m胍���ɛ�7Mi(�&�+�;��v�v��&����1��S���	{��\ر���%���W��[�7m�nYm}������5q�oqQ��ˊc���^��nBq]�dZ������CG6�\i�9I/�����`��b��}��ޥ7���5!���pa�r�H�ٰ�)
|��\����n���@s�؇Ӂf��s�޿j��Z�V��+m�#~xd���	���Iq�|Y�;$���`k�G^i[ي�F�T�X�
*�Ql�N��+����xD�Ց������-M��L���[J�� ��ϧ����},��i.F,2"B�G�щ�����0��~�Ie�O��Ö��[咛���o���}�T�a>��ľ��/���o���z>�E}ʋ�`v�z%5Q��l��ҥH��+�+��l6g���S�Ô|�B��h�8��ڱ�t}C_Ꮐ֣*�=��d�[™��M{�W�J���fw.a4��4���D�o��*��V��VA�8�sP-��Ҟ�}��A���"�
�@�"Ȥ�����t0���+|�|E�4N��Ł�ݓ1	�9��)*���Y��Ѷ����QoP��@�	�J�2��::b��?2�H���ϴ����3�Y_�n�x[��b¼�Y1-��M�ҧ���i��.�#?<���e���n��g���_�+�w,��1���?�Q�`���tt@��܁�
�w|3OQ�������ozi�/#����@ :�ۨDl���#����w��w
k�h�i��Sy�I����M�@�$�I��g�QC�3I/���Iү�RО��c����}>�\!��Б��c�k3Fʷ�׌8'�חe�d($lٷYS �hC�:Sl��i�,�ɯ�䝂�<d)r�$�S����Ib��T�^K���p�+Vu	i����A�>F�i��$��柌��t���n�_=���Pp��T
�;�(�3V�{I�D{��iEZL�I
��sҢ�c����"3�[*8#��^NG#�c�`4�cCf4q���&������E�:��r�@B��$�=��D���M�RI��'���04	�'yP^�?R���xS^�3�Ԡ��j�"�����!���p��sm�h��g8�����G41$�G>Lx���Ny8���.'R�ԇG@"�L��C�8S1�I�.u�ߣB�G�?>�����sj��6�خ0FƆ�{�1�7qD����X�SJ�Rʳ�R%F�L!sM(�~l^0�������a�v$.��X�V]�Υ��t:�J��t����1�"GЏ�e��C7�aR.#*�f�E�|[r���X�\�p���M�[�\c�3�����`�Z�*�؇q�fPW3f��!�u������6�����1SJ���rm�o��XQ�N[�1�c�_.ʁ6�a<������K�#�QGRs�7�gc7�P߀s���ޝ�to��s02z�r�����{V�{n͕�{6>]y��T�Њ�X����(�|�'��׵�h����%"� ���׫��{�i���`./Md�!����]Ђ�[�x��C9w�<�X�c�pKC�a��bP�#lm�Пur�8�/�^�W`���Mfs��(=TA��{r���\�X݃f��?8��:4�g����d��<�Pm#�4Vo-Y@PV��p	�׆9�1JȺ�C�F?��!i�&0���I��SH��H�o
7A?�U'S��C]�
7�4���O��z�C$���=*E�L��@1NfY�oȒ�:4�����#�}n,�uN���\}Za�gi���~��@S���d�&l�'�Y��p}�@�&:y�0�o�)�@���}H�U��q����Ss��G��|����@S�
��$q�Os�I�#KH�OsY�d�Y/�R�����&5�@�ѩ�Ff����k.�`����G뺦��Ÿ~%�0iB�7}�y����1_��w�lᆬ��q�_�M��R�uŐ���p�t�����{��JH��E�2#�f�,��t��D%Q}�:�0�Z`�1��
b������W6K�+���b�d�
f��e�+7�r�JLZ+S�!�}w�P�3�wi-V�6�u���o�+6�]�
�`W��d�d)���P��L �#,{yi��*�+��ӕђ�����	g,cʺ9^V'��0Y�2����[��g�?��)M�������~0�9?8�21�����^:3y��+�|�W�#�ܻ�oط��
���{^GǼ�?]�M��=p��K�W
B��K�捋fljh9i\��	���ȜE��Κ�Ι�v���ÿ+~긇���}�$���9�3&�E�4ɹDR�u$���c���<�a!�;���Ă��Ȃ!ŕ�1/嗋X�v��`�t�K��e�K@H���2؅�Ѐ�8�6T��jLeˍ4�T�,�	.��7:́�b���x�*GASt�=����I��,�"���G^H�Pu�e��PCn��A�	�G���W�fD#��OR~^�e����*��\�����NY���LW|i��=��<��ѵh�ώ~<�h��o��Btt��U��]Ns5x�O��|�2�lm�6h��ݎ]7;��S���.���i����ZU��\W9�?�[��ڜ���Uj��u��rl��!�.������D߄I����D1
�'�G�W�<�Qf���BŒ��*1S8�)�Z:!
)QH
��I„Zu#��v���Ro�o������ 5��\G��zx��dT�f17e�E�X����\9�ZAm�vP����{�Lj�	
��t8/��Ҩ���9��ӥ��%���}�����	�{��_�<`F��=�2!���1��������ʔ��ۢ�n�|�����o	v&F��H�/�~�_�:$���n��Q��$�ǟ%�~��:���٩2j��2�A���l0�l�Z3�q�єɢGĉ�k&b
����i[���cu<~��x����sE��U@}�Mt��nZ4�01yS�Z��&�l�^}o�_l
Ev�k�����`�oM���M��`�7-�����҈����lXd�m��)\Ԩ�HA�q�j+o	�ƥM�,Zq�O��,�eT-5�ڂ�C���$���(*��9l�R�:��j���j:��+�=����ҟ��F���k�*WE���pIk�� Y�j.8��J�
����
:S�5��G^М��F���m���.䜼����CcT��@��%������kKH.!�%
��ud�)�kAA�T��1��x�7�*�\�y��p���g�
*����5�U�ftL���1���ń��Zm�I���j42`���W�Y��c�D1��_��-����D�w���|㟥lS�2�4�B���a"
�OR��z#2���(Klq�h\X�*I��_-�4V�.��7&޹kxp�����1��*{cG�I�	0��ݻ�
�q���M�e�O>Y��c��
O���*Eu�DmO[,���	�f<�a�#$�K�0w �>�s�	�6�W�X�����6�����b%���֢Bۇ�ߕ"l?Y�k�Z��&��|�l�
��!��\I�8�����
�|��`�&��1���1�P�/��IK)����){@'ZY�hv�&��g�
@6`�	wE�&yI���IJ9D�I=A���b̚�|�/����H���u<��R	禓���̘*���Y.�F�E���vP�ߡ��<�ݓg�Z�E��=tL�T�"&ǣ2=��"��ǾG
GL `D݋g�9��X�F��Me������
8�~ErnE�F�*�Mlu|BWY�Bv���i��J~{��^*/m��*X\�wt��˥e���R,k��T��$�ӈ�� �t�R��6j����<ڭ�'������E6���ZhP��q;��q>D���@&� ��찇��NQz�^�~y�
��@^,,�Q��`q�q__X(.l�{^��/�/T8 �c�#*b�i����&�O���a�S�	�l"y�$�&̲D�s7P�u��
=j\.Qܑ?�҆���|r���z�4�ʻ�}��ǃ��u�fůs���fB�Q���B���Ev^M9�4�$?��8<�"<.��L��3�j��L(L5��FV��w߽wpf.p©��M�n�c^��8(Uν>�n�.K�e���y�@��{SF׆�{�`�|���73���7K��ݒ�pȕHd��Q"�p�(@dY��T
c�T�YKKJ�+�V�O�wd�C$Zѧ�tH��ο����n� ���w��?�&i��G,���
蛙�������|шD�>y��A�-@K��#��L����җ|sĩ�i@3@g�M��/<�X��6t��\��_���e���y�̺�q�*�������+j�/������2�����<y?�1!�Ak(���+����݅b�������	��K�Ev��_��X���V�!���{Q�:�_���׍��u�{Zf��u�>�+&�Z=�9s��{�]	F�l�Ǝp7�@��Ŭ�7G��/Ð"�^9M��4%?�}e�%C�i*�fFi�i�&8{L�?�p���G[m�����Xګ`d�l�'k��&���cb5n����cd`A0g�	-������X
R��Y�<��z�ŽU-���̞w�'�
v�8�
j�BX���V�����>�ג�k5`Y�TT�j���,O�Ƨ.
�f�ء�6;*;��Z�dNywM���"��0ԈKՒ4D=#���eL�p�E�H�6_�-�8��(�u��wʫ���%S���$��#0��z�ޓ���d%NQ��o�c�[:��@~ƹOq���S>P����䬕�}Ǐ�{�"�f+�wm�3;�a�8Z�x����
9�a>�n
���
f�|��}�X���<C�;�>�ϓѸ?G�c�"[yg�����g�Y�Q�@z䛒��K=�"�aU5v�:t��o�p
��I+<I~��}���*���2�E�$�Ď�K��ڿmO�l(4��{��_ծ8��L^�6�i��4��K/���Œm��9]��e`T�%*��������~�?"bH�)Ԣhr9�>���'���	/N����AO٠#HzK/� �]^z� 1Q�8��0�)�]��h"� ��+�_Ta�U8�i�cm<����ǥe�}�d���@ų���Ac`h9�NQ�S&�ݫ�M���XK���X�~�����JЃ͠�X��)��=Pԯu<�u�LU���A���i>M�7�:u��&�e�V�b�{��u+9���de�n���W���jdS���X	6>�A8ozt�+�$�5�Fv��_��iN�&,�����>�V�2��
���7>��#_f�
0Z�Ҭ�`>�&$+H
кe���H�!oڇ����և�h���N�+?����]����¿�0Ck~��\�,���������?0evg�φ����
�cuH��`�s$%��C_�V���@D��b��Q���R���Uͫ�YA��$|E���{Z|u���a�ޡU���_C�Sn�n"�k� ���ǥ�ES��ʇ�8��A<��vQ �#��\�W)WI0���#F`�w�i~m�!F���Q�R^�ȥ��H#�|ap�m� �#���gaH���F�A�>�
2}桫��j����>��M_d���d2���/��?�(�J�t5X�O�wN���n�
���r>-�|<��+��> ��z?=y
W~>����<����W䯀������\0�gj[�y��c~޷��CՀC��C��<�9O�E2VnK+�g�j�2*��j�~�y�\'oޱL+0+1{��iu�W7*�v���o�ܨ��U�j�Fc=��|LƦ�~�߮��e����˴P9i�̫���ˉ�~��d�
9y��r }�u���f�**�?��8��?'a"U�[/�͑zyU�@��ʙ�p��y=�K��.��۳�H+9�ې�3۽��R�NgQ l�]�}g+D�d���3E�
d�٠�C|=����"�猖���D�$����1���K��/%���c�io&5�O���p�F��r���r��re�+��9�Sn*���Y�L�I�D�#�#�@	fq �패����a�#���'��b��}=�I�\̮��'�
Z�h|,=��:=(��T"����)F`E�E��V��j��,���Q��|�FQ��_�/���a��|2�r�K�bIx�X��^��b����I�&��$J�t2(i��]�NE�Wؗ�,�ޥ���x�V��c�m�pF&+a�)
�����z؇d�=�>���>1F_9�=�!��~S��`�����;{�L��|c���pn|U�^;�-�.�߄�m���"��;�aX�(��Ȑ�1|Y�Yz�_-�^U��{����3�u��!��C+Hn9��d>�)Ȯ�˵�U�I�ͧ@E�$*}���*�~�� V���9�_��X��AW6��Я5�D�T��@BlE��M��+��Ք��d0X�v������mRf�Fu%�T��c^�*-q�)tS9岠G�)A�o�jYJ����}A�8�I}J�J�e��<Y�s�����\�����X&Z��?�kUY�Q2�*�?���q�C#�M}�;�x�~Z�T2#�h�n���o	��Q���E�^y =@'��\�]��ce}�溞z�F|�`ė��з)���芛����/�����%�g��@Y@�k�K��ӟ*
�E����{R"��p>�r(��Z`Y~Ir��Ximf�)~�U�(�0�$���(���@z)��p�_\zv�Ow�^�9;]�W��U����5�c(?	z���?ܶ�g��'�h��N�rG]u����a���!z�"�!�`4y��p
�A72E{�\G9 �T2	f��t�B��IQ�
W���sxn�R��P>�#G����\(:�4Q�S�R
��7�~�F��9�����r����@ ��:b�Q&e�P�3��R�N�ZD�%&J ��~�2�{�@1H��r�X��/�SV�18c����Y�Ϸ����w�5��m��4�����y�� �/T�4"9�	|�O��"u(�M�(�֍�nb.e1�"���r%��	�ӆ���ڠg��t� }*�ݶ7�DH��B�lg�]��rt9m72��Z�.��T�6ku��u�N������^�=���Œ�B��a�F�_�l���cY����@2n6J
�Ea� �(z��6���i��d0[\����Ioھ�fЅ�<����j���W��}�q�G��9�aM�\WWr�!���(�^�k���=s��F��-멜�jH ��NQ���k��p�è�],/�?��nM��b=�Z��dy׻�p�Q�/{B5T�)�~�+�������0�c�ы�[�p��kM��[��J%����~uD.7Jwuw��:�l���{��ٻ<��X�rf��qU���bÆ�f��fkL��v�[����R�^U��O
���[>p=�[�amEeĉ�u�B=\��,�UX�簙ŀ�b\CӴq��<�a��23'Z����@�cA��"�H��Qj��H}g{�;k�����*Sp�
g���Y&���3����֚������J��K�V~c}l�w�]�O���h���p�h�}Rm9������x�q��fQ4���j��sD��,/�yQ�e�H@
���ʋ�u_@�WaJ��M9j1�2R_%�F�j$��l�g��P� 1���l#�L�щ��t�JA�8�g��,:�F�ջ����-�
�&
��|Q�5Jp��l兡��Ep�d,��$c� Η��Q~�(�����QOtu��1WJ~ɲ�1��dSʨ�H{�pTWؘ~I~|K,y�x�D��[C�K�.��.y��?ґ
��}� ��i(�v
�h{�R@�[u1)�s�"�>�� 倢#Ҥ��Za����͍�t��a[;Ogxl����Ll��{�]W&�#3�l�����w��G��O܏�z���a�5xs�bV�3�w�g�ug��=N~%8w��o���%q���1c>(G�3��J&�i�J��t�X2�E�4}��	{ѯ���D�VV��"���o�N��`4���~[�b���1BM%�CvL|"0�-��m�}Fq$Y"��;(:j�ш-��P=4]W�	im+�w�ԀvZ9�Z���ی|d涋���]v�8Uz�xc����]�N�n�Sz묝�-'<S����hC5�j<Ҕ������	<��X�*��]����r��j;sjQ��Sp��{�~5�7���������A�ǀf
f��
|�:�54=hGq���A�%�xIl�w�J�`ޔ�Pv�,��K�7�E��oA��������瑽o)�n��6u�,T~x���.��{�>{=��.t������(F������~>WZ�Y��fu3 �����i7�Q�K���T��
�h2
SF}R&�U���*�0����,	6�1*a��p������2Հ���:��:�A/��J\���`�����`�A�I��_/�q�ZΤ��oޒ�W��z������]����aГ�2KV�@o��/��,h�Z�[��8��F�CwЗ�<�����O~��p���z���7Q3�;��{��a��N�
�j�i�Z�C��1�j��v���WqӰ^�@ub��w���+#!δƮ2��_Y��~�t�$ّI�)�s�";�g�Z�A���Ie���ߔ���Z��=F���a�V�;vk��u��v�f��e��[���ϳ��}�{���X�O��V���`^B5�	�����5յvv�NN�y�J���>���)�M�`h�3�ͮ��sw�����׈�sR����7mKWl�Xu���8wN�Y�o����k׬?��޲<�;Y��(6.x&��U�8����ǹՓ��9�G��̯�/��!��?��C#��F�l�ndB]�]�y����u?��y;��x��m/1HB�
D_���A//Q!�;t�B�!�Ll���
1�q]e������e%]���/��+�
�8{k:|�K��V�U�Y�3i�$���a�m�b�A���l�]�V��j�oin���ݮr�.xIA�-��>�9X�h�J����f�3�U��Va�����1s�8�ٗ7R��mD��C�1�/Th��&���Dc5��[O���`�L�o�F�E�
�&_ug�K��y��%�:jz�%!W`׌��O�t�\�hԆMKMgZ"��
H{<ܲh���䂥3BNOsim�M�6W�˂͢oab��x�+@��]�&m
6����b��Z��ؑʩ�������;�G�_^��W�"Z-�F��E�/�.�[X�Ge��#^e�Y3,1h@$N�E `���u�:�i��4jA���y	:�
~�%���|8@�0mLtJ<����,�a �Z��Z�Qx7Y�fK��'�_�6��=�i��V;h�
���vo�8?i�;ZWd��u�.�;9 _�H@���X~��w��+*&�V݄�0����Ƴ�G�3y�&��|�����fsGj�lO��8�vN����_��Z�?��dy1������BK��:��87����+��UZf{R[$��Ґ��&w(T��5!�����=��.M�dnEk2�M�=2�������M��t,u�������E��F�q7�-�_���	���h��᢯��!���ZE�S�Q=��w�"���6�x���o�גyyQ�;�����aZ@dԋ�c�?ڭ%�<�%]C��^�%=Dhtw��2}O�g�����+a����9g�5ԸA~i�j�]���i�Xc�Ǵ�Xm��ŕ�c-��
kU�����¢�HQ���.aQ��i�Ӎ��.�nz
~L�C������}S������Paa��#Tf-��V5K-�=��?����QU�qx������l��#_X��,��U{/�~|<�k��J&-\7+�gC��ۭ��֤IoMN/�t[S7g�q�M�>�i�j�Q����?�iځu��o'?<]�~��d�l���p@����`��K�ys�MI8�p��j���
�2�2 �A8_��;�ͪKp�A�u|Q�_���_�n�Ng���)!(��N��iU~�[�^��T	V�mCg��-V���祯�̌���$e�E�z� �h΁���v@�ba��p�(��[�Ӣ���~^�՘�)��8oy�#�k��m�>-��<n�~�"5
>��
�����`,�g�0�}�`���O��1k(O1�F�N��/�2���+l�ESs����_��*3	��- D��[�H�
|$>�h��^���zN
�R �%� x�N!�+ސ�_SR���C�Ap��4X�e��tf��+XO\7��뮋/F�ä�hZ�,����:o��EJ���R�b[���hX`l�� �@��6�)��?��l�lG���z��0=,�E��l�#;��B�cY�[�7�?�6��s��>��9=����1���,�	���?䟃"z��s��`<�h\������Ȥ��?,�/gyLI��h�k��������h��6�ҋ��;��^׮}|���GioH'a��n��C���ҧvѻ���KN�u�����u9/�m��Br��h��S�����ڱ��t���b9���y�97�e�4��O�1�
�ĺb�.y�p����vY�&�k�[�j��_8��ӟ�籺��\$�����%i�2NC;q��*O��<$����~J>o�Iz�wm"8#�e"���L�
�:R�4p�E�\t�#����)_�����/�9�^�\�-��}�\��_���r9*G��B��pH~}>���jƊO�f/a�A���l�}ع0�3��wW��r�KDoSB﹄E�;N#iQ"�H���������܅ :��3�3#^�b��Z�=.*�t�7
/�l�N3�/]��#�Ԋ�����Yo�������d�/���2'a-�r�a|�ƙ�p�g+�}C��2ٌ,��KK��K<���]`�m�f�k��Z�̱��&ˆ-�NZ��hn�;������]�-_T���Dך�N�jڢ��������n����NO]�eOȽ�P4�]��}i�CS]��I_%VuY[	��4d�oD:9a�*�X����P}	�3��FU�.
����!n��S`9^ik��3XWG	��sJ�Ayx�4͢}}4�WN��Ik{��+B�6c����[���z=k�K���L�w|���c�\k)��[�����#��^�
'�?�'����xP:̚wky�ݺ^t�Z&�gX�^��Z<4�\k�r|�Ur�H�`��4͇��>�pk�lw�*iB�U����
~�u��㪗K�:�_�m-\b��l@jG�C��1`�Y�����*IbQԟ ��X=��G��,�=�i�[:�[Y�3�
fȏ���g��Y����\���.۸����EC铞���|;�� FS[�Z|Q�Ё>	��Y�`�-tSkESI]��S�q
`�k:��/�mդ���7�);p��s�k~&�*�.(�O^ް�o���P�T�Q�1j�}l�~e6�w댂N�è�ZU�@����N�fIb��b0�SB�4��T�V���q5H������`9�;Xed$i�8p3!3@7��f�%�St��3�����w(�<�K0�Pp`�3V
��2���zO�.==��pF�
^���NA�_�@Y�ͨ=C$�QU簰��0�J�Xf'��
2ܪ
ѝ�jg7��]��Y�`B��ّ�o�~��S��+W���cy]ݬ���E��X,�NO����3a���^�����A���P�h�,�|ы�Ζ���b����
�h3�����\�(`	Z����?J/�\rh;v�bz�rX	�+}.��w}��H�7�1��u+���2�"Itҁ(�6F�'Fݲ�,�tnʒT�`u�,.���Zb�z��Z��p�8O��è������{�v�ch���iAs33+Q9�yA���f0�*�!9�*y��`䧮x{�T�h�a|�����)r�(��h.��77���5K�U�?�?+��*x+�1���/�/5�a_Y�>��7f�*ojB�(���%�&�4H��� x*L�T��B<��q����J7����;x��Ē��B1u9�hԏ���0��P7����@š!O��v���)��c?���p��Y"��h��#^��ކV�!ю��@JI�+��h��
X�jȏ3n�A�V�p���Z�C�/��LU�:4�q�aE�aa. `�M���1�8�@���
�a�)�p#`�DIq�hފ�����ո>I��P���!`6���N$Or[�F�Y��-�a�Mz-�J�RƤsjh�6��4��2@ =?��4
y��i�o�O.6��&�@��ƪ��8
g/��"�*,v�h��_�.�@k�u��-X�+v�&��N����8,s{Y����k���UCӂ�����v#���tᬘ�Vf����(:fi �46/9�����-e�h�t�GS&T�#h����*zD��l�B��J@���]���BZG�z���ղ��2Q�\g�9��Fc��6i�,
�2�F���V;䝎�+�	�(��
���S�@�VL)�ݛ�%�NV�
�:a���E���(B�?M�����'8��iѪ�p|G��A����5A{�z�```]wxB���a��U��&$n�unw�/�E��!�l�t�g�6�tF���^���`r��� ΀vM����s��²=j_��/ʷ�NS��\������ֶ���B�rgU��X4��9��m�_C{������3	�Sj�Қ=&�@�
h(6UCZ�E���J�`p��j&=�`�Z��JBsŌ� 	�aLfɤe��e����2�[��4_�6���{�A\�qڊ�
%�	k^�q��TUJ��j����Z��l��pU�Hݖ�ym��ĠWO�Y\jY`��B����x�q�z�0`�4?������1F��Q���K���n�EF��6�Ȏz2zK�����g,z�B�y|�Dk`t���鳲��T�9
v��C�h�
�h��nB��Ӻi~��l/�t�kc�k�6�x֮r(r��X�c�7�L)��D���ElP���{��W(@�*��M1G<n�I��Dz�@y�]E�R���U�l��ct(��,�P��X�
/�� �|���;�a�P_EF�VP�a�ae+!4�n�sE���Zl^���a������BAF\w�ER^PE��֯��x��?Фg=�M׬K�N�9���}h���wO*��%3&w4G�=��#�|%g�������e�pч�߶�C0�7��7�7}�\����B��u�J?z�5)�l��}

���2։����4��~��r�T��s'Gj=��{���!��-�[���;J+T��8�4���a�(�	E�=��n\4���SX&��w��T��6=�ӑ�������Yvo���욲ڢ��?���������y�<��Fs��X�ޫ��p�<o6�,3�>�3Q_\Uܶ��eIsP(���p�[Y�m�\zip�G>�6o|��v��ݫ�ȃx���Hwx�IJ�Q$�*c�|�ZBSʳr����_�	��t���B[��Q́����F��&��F��D�Ǧ���ݵ>�F�F^n�4Ļ���H��dZg03�����LE��-6tmYQ�y��[���n��[uZ�]�k�]������O-�\J�XwP4�Q��g�8�vi"3��b����N��~S��Q��K.���B.S(W�����b�
��d'~L��Y��R4@�lm$�����/����kmȕ�X�_51�
i���sQ�����u ��Pf���������`�>y�It��/�&N��K4���G��K�� �a��t�=��K��2��A≫
���l�6��Q����K'�?���
�ݛ�R:!+<y=C�HIޔ��-}P&��{�&�Z��{�aV� ꒡p(�j��쎒�,7[��K�8K��J�-�UY�̢̧�=���b�WJK��U�3�~�cD�/�fO�~ԉW�aj[A
+8�-$1�,q��'�3�A�#��	�<��a�#��Φ��Χ�ܶDـ��Y~�h��yu���&����a��?�e3(A'A��Z��qP�N��$��n�6Q�#�n������,�t:3��aM�7���,�U��Y�ut�l���������Q��x\��GF�HmI�cԡN��IC|`�a"�3��꟔_~��ק��l�A4_��˗
܎)f���[*,�o��C'o8��q��	�M���}�����ѵ�~�ʿv�
o�8^��q�g������"b�P�`�q)զ]�z0s�o���ؖD�\���3'��`�P������‚�p8���T?�æ����"���n%�����W���bPI��%���b���zB���7%I��/���ĕ㓑5�M��)k�S�h�ˍ
��1)T'���Iu!�؀K��N>t�³�BGw���$Iz�5��08�;6
o��b��-��b!�B�6�� uٳϢ��)
�)�e�g���K�Y@��\͍4�VB���}��f�$��9�z��x+C�#�…{
�i������<�A���ǜ�J=żT�g�յ4�k�B�(g�j�t7Lp�:�d<È��So^�,��齺��S
v�5k�u&sQ����9Q�c��s�F�l��ǜ��-�	�EЈ���`s5�Dr�Yu����o{���wi�g�����a��m��j
`��I���hf܄v�SWzM?�6�YNB�&C�m�
����@S���Y:�h�k�]һ 0��b_c�␾�_]����|Ik�:�dMZ��#�kv:�##^55�ZO]��ƬN�gc�D��#���5XJx��b<VDz/ql��v�:�Nk�(�>[�ZBPCcH�TT� 9F�Xe�*:��~g��b��m�Q(�-��D�6n�]]}�o�
�#�˧�Q������A������?�����W&��M�d8��qW�������а�cۼIS�@�.js�1����/����1����������
��9�l\>�$��6��e��b��/_�S�f��'�{n�,8>;�l�����O��0�0-q�`@�6��m5
zԡ���wգ��2���ӝ�X㬞�V�K�u�y�cRT��9��|�b��$�O�m���k��Ǥ�%�̣��bgD�ܣ/<�/��_ʷ�_}�~P�D�x5�(�߿|��o��m��C�٫��g��ߤ�俾�
�F~VY�C��N$�m�k/4U9�'(h, 6�q�p��i�ĢU,�i8hx�k#��9�dwz-�]�|V�ٲY>��rI�@�ڒ���\0׷�˷�D]�}JNJ9���W.h���,cи���	�H��%,g5<R���آ�t�p���,G-�޽c�5�'��Z���)��>���Px� j��̭�fvU\�hH[��m�\h��5��՘�;;9�i�6_�Q��}֢��c&���;ڢ���1��9-}>�W��Ab�
�.c)�In%�UD���>��,�/h�021�:�AJ1{+��������[�{��q��`�)���~�jo��cG����j��1iL�	�b�*�i�dS!2}���5c�����a2�Z��l��d��iˊ9KqsT��ɴ�;;��afT��U>���%�+k��b���GY���jQ��,VC�j)�[eP�����G<����\�x�՞[�]�jt=�~'}�����6*�#A�8����ϭT�2�
�X���bK��p��D�Z�(�����׷���e�!�?�����x�2�K-_ȥ� �5‚���Ap���~Uj�,{��?���?�Z/���g�o�~�ڒ�����[
"m�'N:����L�a:����h�x�>�,j�Q����
�8�;Ѡ;�_�+B��U�����۴�}���K�Pkj6u���O{�{�i�I=
�?��s~����^�X����@����,h*�*#���Q԰��Q��3aXHp)Brk�$,1J=�$�����_ߥ9���$�t�0��us0�(L�L>��(�U�3'�)˲��X�|bk�{.�$�#��{��b�*��M
3R*���V��.+��r?Q~{���3F���O��]��j\��x�	�_�b}�*JpPh���=�->"�WT������>��#��БZ: a�^�a"�/�9��$����3yɘH�y����❕�;�/)��������a��Pp-��YVt�E�z�����k;K�KC�m�?���9��i�N_u"��iS���"b��Pɦ��˿	��w:�W(x�7��(c�غ��D��d��b
Q�"!�2��4�:��n�H��%Ux;�R<�4�~�:w�C��������r\3��������2;^q���]��9�;�ʉ��4�q���6{��;���������-g����*����{���t�G�w�GUe��{�{�7�f��'3���N���zh�w	 ahb��(Qv,(�Y�ZP��ς����� s���L�t?��?0���}��s�9�eq�r��>��rt<�gn)�Ȼ=!^�?TG/�J�鹠b��{5ق&�:"@�vd_Ү�C���i�I��M��@%����})6��~Z�s��yi��
�&��zåU���C�C��-F����
���uMΜ�|�:��AY���A)j!�ff���íYKl���dD��x��y8��%
�,�̓��Tj1E�xB!�D?A���Ax'�?���ą�h≩}�7��5[���X	����� ^n�T�?��A��M�����JY��δ��
rx5Ͽ9l�R'�5�����Ӹ,�\0���b�<��0J���$�0�6tϥ�Ly���+��@��۷���!�A'���+>A/����;w��S��@ʇ*���]N���r J=�R��ҵ�Ԟg�u�H(-�]�R���R�$l^����}��{���n�"<̩'��T]���Gh=�:6�'cğ0J��1�HC1��T��O�k��0�q�)�}F?H}wÊہ�
�4i؟�q�O�m�'���ێj��%#��=k3:��)%���ї�¾�袺�s�ql&�{��d��ܑ�xMJf�W8�O�
	��
%E��T
��O�'%�_�I�h�N��$t�Ϛ"������58>��s�dO2~�$��3џ�~�烌V�JLL��L�dR��Jj�ˡ\����䰼�N1=f21]8��GЋ���A���R�yã�[f��
��j�S�G����Z3GZ ]����&�D��� �g`6Ko��$XL��	����ZU�}xRy$��f��s�w�,��J���6�ؐ�R(���K |�F��K�dU����X�:4��r��i�8���Je�~Y�h���O!y�΢��R>�z�Vt��UG��V���w�<�����0v��&���7TG����8����Vl����Ƣ!;�^�8O�W/�&H#LD90((ѓ���?
�a��)A�m�!�L<|ئ���%\��ÌL4⏕`n�?`�������V�Wk���h��b�+i�Ś��b�%8t�i���5���@�/th��$�pK�套��s�����G�X����h%��bɻ�b�/u�5K:����`��Ěc�bֈ^�:Mžr�ݹ��׶gY5e�\pA:K#xs"��N�t;�f
d����B�C	3�v���Dk��/���U��1��ղ9GsX-B�����C<��27ǽ�� �M�.E�guL�͋\y��Y6��{�Zbu��y���E�5%���.wA�P3}�S�nc�e����z�5�2�QYͫx`�բ*'/Η���C�i�~��E�'`ciE�*������&9��ҞKA��#��
�\���:+/�c)q!�r�^=�{�p�n7�\ݱdq;������z������kڗ,\�Ր9�N.�N�[�EZ4��w^/<4�z29愘�+GU�=��0R=��9��#}�^�)t�r�����grt:��".����^Q~;���3�ʪr�mNEE�@~��}P�f\t�z���Mբ�I�`/81iS���N��M�PV�v�<_aO�6)��h��N�v�9dy�X�O�JA�1�`S�N�F�0d
���7�����`z�$�
8g0:�a�ї
���Z\f0<\o�����qg�~1�?8`|�l�"�[��nb�1 �Mys���B�'F~���Zb�vGN���u_f�͉�k�E�/���˚�>����6��D٘����HN �T1P>G��O��6g��\��=������WNe��qo�t#u�z�:J�O���'�)�%��A]4Q�WC���MR�&
�$%�j��¢
�7�Hl�%�Gm�P�P�F� ���@9sBM�\���+�,u�`4c�NZ#�,�U̥����.a�L��Q<4I&ũ1��@��aWN�]��P9�h�^^�=T0}�\��$y����'�Ѿ�Y!�aE�D��*��n�Ĉ\n�E���*���e����S���4Op����D��1���K��r�2B��}���qj���1�Ʀ/T���
7�8K�YY&�駵��l�W�S�J9�=�4OG�:�ٝf+\����*Z8�N�ʢ�g^�@��$�|%�-ϦWH�M��VLR:/Q�J�h{8�s*dX�J�5`��j�[p��k��&UY��b���d`l�&��L�S�Tr��@���t�ڞ�)�{i�E���ڲ��Z�w�:��0Th���	&�!̀\��V`)��;^��L1�C�|]ߢ����r.-��8��e�u�J�|�W>R���N��r �8x�A���#��b�+�<���SfL�M�6�e-��
!��d#_��Ԛ�Q&��q����qPB�k����A��(#Zq�Ɨ!���Jp��l"�1ײ�kI�ZV��p@�?-�=6�S��s���,��e:3���eZ5���R9+7�N�9��In�ۇםX��gCSٮ嫳lmu�
��,�3��m�9z��O�PEǰ�B^��r�������F&B^m�c� �r�4�s�ͅj�\�g1H9T1rFBC�Z��0JPh��w����an��]b�յ�P5��ނ�G���n��W��g��k�uʥC��?■�ͮ��|��@�-^%;��x>�@5e�yA�U�9��54mƄ�Wbp�\!,�G��hD"��	3!�
鄛HT\�6H8�`9L�E5t�V�\�)���{`��{����
ꔻ�@`N�����{��9�瞞ݷ�v5�ٛ:W�nY�u?={���%�1�4*ve\{z�?gm��e&��b+hP��9B��{�
O�Q,m��ճ�U[`l�\5zH�ṽu�=���`��zr�������X
~�UӚ
�gv�^5y�#�Q(2'}CW��Ks륊�O6��7�Րo6k��C��D��&PS���<�J�N��,\ՅDe�PZC1$ӡ� *r���1ѽ�c�ȅOQe�4}�TB��%"�9:���v̀��OHn! ˆ�"B]b���	��PIH'h�$tl$gup;0y�\#��0�¸iI�q�Z����!����-z9$Ey�(�WȬi�����*/c�[4��\6����P��u𹚫��H53�g=>㯳�X�N�o�Q�5���\�8<��O�n�����}�թN��h
f ft+x��2�����mS4���8�vו2�
)ѻ����$:(��Z�1��F������bpB�2k��Yc�ÐQ+Ꮏ�n�#�4w��ݩ�/��+�kO�T=�#�ʶN��=;��3��3�Q�
@&.֯ɗ/�oD�{����L��=a���M�M=I�����;�eχ,'���d<�FO�c�J��wy^��@��L�{��i׼���ɥa��r�q�SY��<�.��'\�J2���+��]>(E��5�^B�K�1��g��Հ�bAt������p��7o�C/�Ҳ�j8�Q��Q��ޢ>”�Y�nPj.����$Qlw�����[�Dž@>����|���rF�R�=�v�?$k�sH
�L�k꿿��
�N	�\|D g������C ]<xF�L��_�=�	�g�L/ۅGI��^�TGd�e!�ɐ�2e���Ӻu�}��9�qt�t�;�GT�{����Z�DIA���I�ɓ��'�n���L�S���h��|�	_D_1 ���FO,*������4&0�4�	�aDr
�g�ส����غ��7��eS�pW-���5���_�ԧ���m0�j\�rM+9�3ZG5mj!&\9�m�ޡ�xK�X��E{��W,�����҂*��s��1�\~�m~e�-K�q�ޥsV�7�]�����E��,�/p���ț������g��K��C����S���u߮���׿�{]��^�>�ݭ�~wS$cw��T<б�|�"QDRMc����jI�d*Y�N5����~w��Q�Hպ�A�k�3��`�$0	��t1B�(_�%�Z��U�h*\��Tz�R׋Py��Rя�9�h����`A����s�d�Ӭb ��ဟRX|�
N�j��hZ��; �'���h0{*�A��Z+�ehȦ��`�<����r�����^P����Hm˄V���}��T��WkO��' �#gm��k�O���W.���Q���ZQ����{�p������=4A6
Ҙ‹B�3?��#9���Db%>O�Cxu�'@<�����>W�8���-{�j��>���9أW�9�.Yz&�o����m�C}�s�1��e5�\Z<rI�)u+�Z�ǹ�/���M�7��/o���Թ���}蹡���Ѱn��YV
[3�ܖ����L�����\�����[ 
�/�)UC���2�x���&�#fz�QJŽ�m`ݲ�k燚G�>|犩��]�C�-`���.��*����
�4�5��K��}_.]|[NIw��z�������d��6?rp����%�K끼5�kq��Ag�Z �3�g!B��E	��R�Ǖ�>C�l)I���]{�k�m;���sZ���=-�C��s�[����֯{l���|~󪧭�[�OV�ƀ�#@��I�k�<��I�{wKk�[�V�?Z�����E?��oxtϥ��A�� E?P��R�>
Tk	�l�R"7(�/��C��m�Ue�@$��8��} ��,�	a�[ҳxq�^�Q:�ZRP��j�Vu�t��%n�2�f9��ر]7�~,�U�����n�6c�6:�g���ѫ����+-.?�M�&��fv߱����s#zV�wq:꙱m۫۷��c$_�g)��O&�&�\@�b�d�3�4�n�'B�X̡�<i �!�h%�D�ĩY.�St A��8��Mt���x�+8�����P3��M3�� '�
�F�<�,�o���w���R����dž����Wd)����+L����Ӥ����>����1�R�;�q�"��LN�,`/m�O䔰m�8���F0�V���\6&�������yhM&��t�3J0��`���g�����@���5��zzX�—#�Ն1�o�ԠRڮ�T�}�V*�y���p-����"D$ן2�pԓ1 �8��G����0��7O��y#��xh��(���������>
��M�s�wL��iw��:&m�H����)�yi�*F)�I�$q�����K��wN^�~2��I�����6JU`>�u���<����I{�2��Yp���)\֤M}��$/p��3�7��`r�$����k�㹗8AȬ�UP��L`��}�QLda��~��TW�l�i	�f�Gџ0Q"�쉠
E��oE�V���-ȃ�Ǘ�1I`�|�؁����%Aݶ�����8���C���D�À��H�R��.L4I���f��N�H�Ry����K3�{>0P5m��h��9v��y����ռ��%��M��|Vεz0�cQ[}��У��cvg��-�����3���盲��^Y��)��Vؿ�娢V�ԳV��B��a�\��Α���.ї-�&<���_6��0�¡��0z�̈���B�@�}
��0�g�I=�FS]�+(��]`��\x�����\J��
K<�WRC�Q�4j:�s�ۨ�ۨ�T/�.�Ez����Gq3���h�9�< Fv��Ķ7a&�8�P����3���(���e�ӊ;8�sd���g$�"ٔ�0&FD��2@�l��D�i�az��s�B�x�_�o�:�@	B
Z�IH�\�V��Jf9
�J����\!��2ٙ/��:T��٠Tf6ˤ�v�jUȡ���f3T��F������ �����(��KZN>��R�q�bN3�8��ʔ�ʗ5
f	�j�A3]�֚�@�Z��Oj�M$%��RN
�Y���[�w��z�t��e�r�Z������l�JYV�����9��q*� �N&[��5���L��[2<2?��K����l�*�}*�g?je܏�Id���?r
��`�^1�}/U�߃wyE�|k4~N�T��~��Wr�Z�@
�څ_(�Z���V���T�%��ZZ#�X�>u㲻�^Eo2˽�T����'��v�����	<Ր�*`��c�N-FK�+���P���
��W�A�v4?JScF�'�c�7���3 ���SR��Ӏ�\��Q>j2;�ⱳ�I�ܯ3s:�,([.�edW��=s
~��=; �!F�Kl*`D��ǯ���P 1�I����𿐁�I����
�Ș,a�8���p�c3X)W�W�`:�5KQy��7��j$uE��|p�M�5*`�l�h��$��J�6�R/#�������4*�8B��ݺ�ؖ���WX.m)R3�fa�-�v4�+�JP�<�g(b�v��#l.�؄�+�a���攀��³�eGw_���HXc,�@�u���-���ѫs:�f��p{����(nX8fQ����:����h�o�6���֏E��:�~�D|%�5V'���8��jK�mڿ/�ѐ�K'��oB�vNg!d��K�uK��,`�靿�����|��Zh�����Q��f$�v�,�>��%F������v��ځ���'�C7�8-6��F�
�@���6��a�Y9�_��,G�o���Чͳ%�{#Q�kA6>��oh���ͻ�㥌��d�����͟���_G����蓌���/t�k`�R�Ӎ)
��|:2r	�⯿s<�ʖ����5E躉�]���]Z�m/x�Ɯ�����O�	X�R����\�r��o�yt�X�Q]��$��^����Ӎi���ܠ���*�nR� gf�5�/C�7A5(�1���������G��u@����|,J�$�4
�DI������ID�m��x��8=9��="�zc�����q2���wНv�ȅGZ�5�5��!��_�u��*�Zm�ߴN3^#�7$��Q��LZu%!^AI1)��91�C|G�D�M��߰A7Y݌:֨�n;VB�������NRS�q%y��o|�&5ز��g��t1��cL���0�o�1Cٍe��^w�>����½!6�jf4��K��	Gzi��d�ߴ���L]���/y �r�E��F�~ӛU�Q@�߉��`��1q��Uwb���\L(�bY�����%�)�
Z��Rlҿ��˪��0-Wi�UФ�I�S��+�_!���y���]����+���r�=`�'tv7{�������}��1���{\ǃ��$
��c�ϜZ��;
�;usg,�kv۸U��߻|�oz�r��PQ�w�Gb�����
���"]lɵ\��{h7���{�‡{8ֻo=`����#�vN���_�2}N��$�sSz̙Z	6t6��@f��n:6�i�!�T��$"�W8=�����(}�mZ�x}}5hK�ż�{�8P�޾7�yƾ7�^:�8,B����7l�{�8���O<�Ĥ��lt	�j��C`�)7�a�9��J��l��6C/��?4g�Z�+q�+�Ia���Ʌ��������q&�g����w���.���yE�Z�EW~q7������K&*�/��:�;,w��oܳ����eCk��5�7��n��u��g͵�&շ��7����ڱ�f�}����?��u���P��;�o>r;��N�}�z�t�Pu]C<֘���јs�Uۧ.����
��o bo���?�7�g�W�� ,I�$Z*�!N�|˲f<s&|헪��m�����:�?������^K���g<���CB]DSX�I*᪤�hs�9!?+K��_���_�%9����@�s
Nz��O|��j������ĕ�D�������A���i���������$���ڇ��~�>��z��Qtc���+���k����x>�7n�鸧��H1���L"�b�N65�|#.h��d
�`/�0�뉚�]R�>�[�K�����R;tHdNk�Vrh�*�<;?G��j3� d4���	ьi��1;����^C�g���&c�P��S��V�9y8xqcn���蒳�ѡϷ�]�j<B��Y+��<08Һu��%3\Nk��&�,�5��E���O>^���	�閪�8�����w<:ml튵ݳGV�t*�魏�7Ϛ�q0J����g�!�=B_Sb>7L�S���*�J�&�o#�'����q��&���]+F.O��	s��!����qLCDk�tK���||<Q����~J����%�� U�Z�+P�a�8�<5xz���y�μ���ե�6�d/�6���w�Xi�<t�ۥu��o��[��Z�/w��΢��%E�e��R�?���W�� �h\��z�SWJ�}e�@��Vf7��:xW���$7)�{t�֓�Et�xr�֓�t�ʓ�]d�̪��u�[)�'o���%�C��C��Rnj��_ރoI�rL�=e8�=gLN���;�������h�($Mj��Q��\�������19���z����:�)�t�^�=�QZ�	zpƽ9c����ɶ|Z��b��dY��T� j.��h7DJ���)��2j�F��O^��d8�P��
����7lLč���1I#n��5�peZ�����.PaӤ��f��[[��me��1�+�ًÍ-�'����ŭ���+!���]x���ds�k�J?���{ӻK���բ!ő�b8c�H�d}M-�9zTg4p�ӹdLd���5�,t`V~�O{��Vͺ-yR�%�-�jO�MfsZ��2v|�u,��e4�����O��X|����CGl�����ZA�z��ĿMV$ #C�. ��F��+�&��K����#Z��(Q�T��.�
����D��U�ΐ��?8���X�vP�s�;ֆC��nj��vZ}I�
5C�<wMW�4�ć�!'
�]�qJ!g��]��K�ה�G��J}�VV�>���4c�LzbU�[���)���3K�!w����Y�޶��o������X�q��¾���é���	�[�?�b(\�5�La�乖�/{�s�a��t���q�/�Rˀ�Ɠ���/�=����V�!疕��	�r�R�|��B�DP�xt���|߳eg)����V��A"#�^A����qF��$ڻ"��d���b&B��%�+�ձ�����a�6��U���{�����n�m0�Y�o��M}4�Ғ|�y|*������I{���6�b=�}
��6d1y�ݰ��=���s�/�}q���U�|gF���OS��1�
j~��;q/^��u� 5�eZ�XnK�Dk��c`LSU���xM��֔v)#(���&:�!��PU����Ԥ:��ˮ>�eKqGe��6(ABO3�cC~�QgTh&�*�F&��ak�[:�V#U�J���5.Ugp+*�¢�*���f����=�c(ך��W����1^��4���٠.Q�K�� w�ƐetC��<�(�a,��z�B��0�������V<[M��>CwUc:�y'܃i���9�}��^<� C��08C\�OPE��^1��sZ�R5��Hvn}}n6m����p�b1,	��P	��������؊����������A�1���e�Wv5�wǽ����#
��h�#/����_]�ps3:��������u�8��i�fٟ�>�0��[�v۶�D��Y�4���a�g
�"DR�9K�v���H�R�]�S�Pŷz�Jƛ�3�в
����?X§)�V�F���1�I��o���0O����%�eœh�yw����	x������A�;�2ބ���I�>��g�vz
�_�a�p����^�i5��ҕp}��ϛwJ�9���ˉ�lԔV�4��W5q��H�>.{�C[�|_B�>�N�=�^[��r����9�^5b�U�Ιv��J��ڂ�k�|�߰8��Ng��NJh��J����,�J��A��9���*��r��D��x��0s��{P�6_WF����j��pm8Ϛl#�)k��u?���!K�́�Г��
V�{=��ӓi�3a��3�	`�F�`v�i�n`�n7�<2n���7�un�h�C�"�$T/^B��dG�#�y�Yl޼r�U 5)� ����������嘭���C�/Y�Z��,�[,�r�ͱZ����h��XqE�~D�jŗ�=�k����q�W[Y�$9.��v1r�q�j�3�܈�m7�%���q\���b�r��2:�.�G�!�D�8��<��%r�ըר�i��^��`:�X����+�r:]�<c�r6� ��yi���䜂��?D��E;�x6��@K��Ih�u���϶��aں��q�V-���6u��U;����V�3���V��Z��������G�>E
�;B4�����1zb�_h
{b��#g�¼��p9�t�(��J��8!�RY'�%��saX{�D_�!"8�d����r50�.&ʷӾ�6��ې������9�p:��X�	�q�w�3Ϡ��h��u8�e�D0�7D{ s&B�yf��th�sȤ��'�7VT����
l�L������.�/!�”��.7����5��^����FV�=.H*�^W�R�֮,_�0.�iW�]��ee+�ܸ���&��w��o]M�P��{�(a�W���80�=���p���\�����qZkք�΁���w��3�V]��"�K��f��E����J���ne��*����k��T�7�*��>q{-��ȕ*��Ln�w��WX�r��.� �ҫ�.��z���=���b6���9b��X`-���Q�
�@�w�����?qm��Ep_���|#�KW�W�%eB�3µ{ҷ��e(�K@ږ��˃K{�[@ Ǹys0df		��Q�9��)��8��{!�����p笯k.�U}�>�}�kk�׳v�@�՗.�q٥W�&���o����E�3C^?C�?�G[��۷��={b<}��a��A�� ���ui���������p�(u����iW����2JM�_+��X	���^]��"�~ǡ@�)��<��MN=�B�ó�M-�L!�mL!]�}�c@���ж���\��%��:����%K��o�`���*�*�|3�*]I˰��@��uXK	{��(|I|�~�_� hq���%� A_&A%D̠ڍ��ޠ-hCxB>�Y����3�=��8�:Y�7bzS8?%,���S���/�ҋ^$(3H�ݝ��H�
��$��#�BL�*��f@��p��O ���UF����ٳ\��@ݟ����� ��e
�
E��H����q��uA�o=���S��g���DQ.����b�&.�{���f�׋�w	Z���%��0���.7�s�?��?���~���u�?s�Ȋ�	�'D�;F�F�����El��188:����UgFͯ_6�m�0c��YV7w�U֜��'70�6L6�rh��+F�Z�|T��~����815��5ipM��V���OKZ�۲s6���ž���b����D
��K�읁;���!�f
I5k�%��f�poZNK�$p�܉���7&�x8"~����}���3c@�qL4����GK2m�
<J~))��g�y�8s_�����#���g{�œ`.��ڨ�d����"J�ϐD��1��x1"".@�P��9�~����O����QO�mUP���h��P��O����
*4�V�}]�}���JV����7�l�˸{����B5���寷I�N���].�g����[h���`����/����]�����,�lr�ƨT˛k�2y�dB��H�㍰թ��rё��
j�[�c����	��eЍ�c|��I�O����!��E#�� )����Kx���2��_��$ϳ}�S>L��5��	T�N�y���#4��I���� <1�BD��,5X
a���y���$y�R��c����T��P��YL�єP�����Z�Wfj��z�A�3��*S��Us(�go����.K�Z�!���Jڊ&A� 0���%Έ��-B:�)NゝKg��u\6��߸~��-o��_��wSg�+��g��g�C�.�f�$����]H�x�G�h�c
�n���@d���V�`����2���]z��uܸV�J�h�s��UW���+�w��,W�D���}�n���O���Ӥ т�f�}́R�j5��Nͧ��y�O8�<lH�.�6�N;@{ ��È^x]8!�D�h"=�eN��2�3�x,>
I����$�,>�扵��pB��]41����+�R���KH���)'!G��,�~%!�z��}���< A���
 ��&�d!�t2�B�	��&Jd4�1Q���4y�A�I@6d=c��2��/c����~�{V̢4�������Wwv��Ñ@������|'�]_41�z�J������qKOtT����)��j$4�+���ӎ0�K��Q�1��sm|�~2���k����<L�*3�{ �̟��t<��$E�4�ou�ఇ�.T��k��@�/n�H�9��� ׇ���̙ـ޷�`x-�m�K�.�]g�àD�C���<��'�Ap-:���bxJ��qh-,�
��Z�̀f���h7��,��8�z�	b��ҸorL@p�G�}�`)B����0g�������w�f��h"j2G/��ܓW�KhFI+Oo,WԢ�!H�:��![l�pϠ�5{�Q��i2��m�^S�W\�׀�d���}ﲚ��-%?�I����.�g�+A(�>5�oZ�DnH�����g
1���,��:/X9c^��k4y�UzK<u���L?F�+�MK�k�\*J�bN�	fS����^�)���P+n�J�Ɓ5�j��q΁�� �'$Po��aȤ������@4�3F�0F|K�1s4AsA���H4/)�\�E�%�B}��cĹ�����
y��4O�ő���Zl6�������IQ"��r��c|Ւh�	���%PL6��;I�9!�
��%�6y��d�y�H;c�E�B�N�sw�W1�3C�I�p�oz^�tf&��Ȗ�
0��	�'�p5"���ϔ�M���bĈ+�̹)�i�;�M��~����6N��)yӜ#$���7������+����a���	(���gL&^o2�ypW%���0}��O��f�+љ$�Ȟ;`�P	��G\Nk�F�h\.���qp:u6�hġy�Pm��
J���*TY�V���qz6JU*����pg:�!�Ǥ���L�&���rʥ2�>�q�j�No6�y����u�4vg(�t����N')&]�tjJC!�S�F4�!�H!C3�Ą'$O={�b���j6i���A�9C�N��@������<Rb�l\��8M�*�A�R�2H�Y@ZA��-V=o��V��������C�n�3���,�v�0��56h
���@F�QX���uj�΢�r�*{v��*�=��
�&�G��[|�����-J���̥Vg��n\=ؐ]�m��#-�� �CA�0��
D���\ dz����RӨyx&�����Y�rHa��!�Cx]�9<��!��
)�Q��q-�*A��V�eЩ���s�B@�D�'��K�@Tм"���Bj��J����|]�jN��1|ʔ�JW]��N8�v����.˫����Td����@vqMMAn0n�=�9���nz݋I<�`��v͛���w����V,]��)��}nKu��:�&~�&Z[�ωV�S�c{��V��\�<	=����
��z��h�$¾l�J�4�y�ڪ��@]��!�j��cf�I�	�۱ᚢ |��t��9q�'+�,m.C�]�m+,A�m��3�Ҷ�R�{|$举��AL��1��xs�é	�Q�oxg��A
�FQ|4d2��Z�3���7O@<��q��BF_��x��E�	`P3� �C&��	\���E�����txa4s=&����L��g���TH�^!��B�y��s�'� Ẹ���B�IO��6H8pb�t
�(AD'���h!�Lv�<&Ap;0A�+Q��D�o��@�(��IyD:�h]�9����
��"!�Nl�|X��t��j���Q#��'�cD.������L���&o�n�6]�uɼѭp�B簄,ٲu�#�R�i�xk!���=7�Ⱦ+��Eք�=~�:�r`6�f��YK��>q�z�|jP���8uMn�˦{��n�2�z$aF/�K�17~��;��D�1c��A����2�=��|�ɪ��x��\T�>�m�:��V�����b̗����o�}Y��n��[�7��}_Yj/��c
�������7N\��v�u؆-5\�ƭ�I�~�ĩ�/��,H]>|xq"�v��JϠ��
|�.(D߼��*+��੧R�\���N�?��h�p��;�$�O�UU��Ӂz�Y��������&�7uj^�c`+)��4�������U��3ұ�sX&�:��t�q�{,8�q�d>�I�M�L]��Z��
�E�M��1�V���C9eV�H꙾r�J	XE�E
�֣o_��r�Uxv��|0�'�5�#G�T�O�|x\��.��P������ި�D�K�8�ć���GK��g�d,�Xo�3.A	�5 $@���k3�7_� ��c%ByN�;I�p�M����h��Z��UT�M6��;�$��=��=<�RI��R�5�c��X6IQ��!3�;*��j����
n^��JC��C���Y���z�A�H����El��E�z@.�Y!��ᩡl�I����%�����Y�@Գ2��+���^�����D*��ԿV"���h��2-0�e򽻴2.��tKUr�]�����U��т�@�@]��������b��ҿk�5���ԥ���-�:�TB�����
�nz��҈܄�
�n"������(E�.VX��䫋\I^X�+�PM2q��2$��E��)�2����(O\"�DO}Q���
���:Z��B�"g�[?�kDQ3[]����Ь�,e�R��*��7�jw킗��Ƥ�w��FF�P^A}AA=�pQdrע�ļ�ڲ��3�3<�KZ5(�p���iE�UeR�<�Y�PSy�Emֺ���فl�[�ոD:�F�]��\�%��t��e��=���겒����nEix�ܹ}���v�de"<���j��y��Ԙ'�VB	� +�ͤ��~p���c��2�D`J[����f����^��D�^b������zw'�V[1:k6������Q8�4�W��9ii{�t�s1p΁��WKZ���9�Z��ْZ�]v�>)�w��gys&�p߷W���7�z��0	��D{�s�a�tD�����]3jA��%<A:�'���b��*CS?�s�2��"�7�;��U��Q����_|��fڂ(J�Z��7<�S�^枮���l�_Ε �C�w�0��D��_�	�f�
�ė���q����.�40�:z�89zA�ы��.с� p�&M[Ԇ�4M ��@A�����0��e2e;q��e�e#駄��()	ܭ�e�'h:]9D��.��PNު��R��O:(̺�KW�����׽#gw�j�k7
��'�7^#����~MG]i����ׁVf���P�m�-~r�r�8���5-��rx5��*���l�Y�l�g��֯^@��=q�Mx�$eq��R��d�$p���r�~c���Ӫ�O��
K��\3L�sS
lɾɷ?��o[�^�
 c��R�d�Y��q�Eh?z?�	��M�-P>���������SVW-80�{��Wt�N�B�D���[�����|�D�`��-��
�BU��0�?1�D�ɠ�X�T�Fv�K�R�8�������|dO�2i�M�A�<�xaC<��2FI��ϑ�(����
�^?K�&p�\1m�G��^����^	u�4�98�r�l�P�DŽ�Bڜ�'�����Ȑ ��N����^;��L��h�]�D5#�47�2uպ�'�u}O�����/k�[Z�5�Vk��ֺ�Ys$Ԥ��q���L8�>9
6��ز�4�O�Iw��������I~�y��~4=�:"`h��0*� �6���4`��F��)b�r���#��!�f��"G#jS1�s2�_F8���t�r}������]Fs���u9��b�W�������&S���e!��n�%~����g�!��a�����?F�D��[�&����N��תM8�!�
!P�+�:lb�mV������̯�ֶ�s�Y���[�cD󂼊%t��H�@`������u*	za-�N2T_⾗���+��Z�R���>�Y-�{���=MA�<�ɭ���;�����S�;xށ��>\�23��[�'��4�'��͝y6�d��F�[Ha��,��rTH�*��OQW/J��UZ�<�֋�p�uB�L!�LH����Q�X��P���u�%!�]��D��kա�m["��)���\0$��R.w��`б�s�Z"e�bEVŸ�]�ӭ��(���8�&t���{�+s�^7{lyEN����K�5c�5�*���.J���`s�����Z�ϙmW�'|�������/w��;.��Ѯ�����x�`�m����i3._�#�����,�9�bn�Vw�~�6�(���b#0֟��d�D�0T�پ�0)�H�-^�L��*K��l�D?t�0̹�Ep�|��e,��u��O
�=���k�v�g8b#+�6��B��'G�|b�Lzp�ӓ�ʜ%���?����ϔ�O�����3�<?'����R@�F��;
K�9m�8�T�ȶ��M�bHq�S3��'_b�,l�ಹ��_a�R>��1d�~r������Q�|ϻ~���!*L�G�Z<�C-�%<
2ɴ�x��X�n��W��<{�;dmKQ�U�&!h9W!s�Dߣ7��#�w_@�'��|�Ļ����_�������o����P����F����>�K��*��5D"ђ��b2x8��@������
Yx
�">�!���~�S�&�����J��Z4O���>ˑ�!��ټ��;�֗�� eM�kd�#�+���M�O��#@
*�)���T���=/���9�N��W
�� 	����1ń��A�)����_���$7��"���>s�Z�̔����JS���rm��X�ē��`����;o�]5'�\��G] O�3`T�D����.ķҕ�'13��0#�n�CX��o���a�.&�
��aH%
�&
� )���!i�-{�`D6��P	�f�ӌ���xI��;RRw%cÆŒ�N�^^n[^Y��
��օ+p��[�����0-�XE=J0#�,��!�1@Q����8T���� <��OF��z$����ܗC��5��{<��=d��L�.Bl���9`iĿI��}���?��ӟ%��q���9��?���6Enj�#���z��Lx�C߀;���w��>���#~!�?؄~<!v���C���q�_&`��f}󆂭t~5��d&{ZpNM�Wd]��i�V\WB�Q��F��ID�$��#N�$���5L����]q�PXT�M�jV�DI�h��>�d�]�2t��x�9>��>]��rհ"�0|�f�ڜ�
��;
�۬�n��-{�w*EXP*sǎ�pj9�V�8��j�h�J��G�;�H[K�·���%�';VW9���h��J
���w�TO��oϢ��1�����Ҿ�vi�r�e/g���}}?�\cS[ڲڧ��ѭ�5���^s�Z��1��8x��<�w�L��+����J(?
9ul��^O�r�N�p|b�Z[��z���>3��N�]�3�L�5i�'O�݅���$����#럍�8��\�|�Տ,t�����'
z�������"`�Հ�4,�{K}��;?}͍��^g��e5r[<4�����L�Lu���B�	�Н/�8�ԭ�kG�V�$��ʗ�͒<��p�X֢c\�?SP{��z����mZ��hH���Z�x��*�Rkj�JZ��;o�R%U�YOV�V�*_�_?M��̺�v�vqR��c =8���0���j�Y�3��}B�-�Ӎ��a{��- ���VTD�8h�{�}�
e���9�$!��[N��;��#�g�V�[�eɲ$W�Ȓl�e٘bl��f�馛N���$@BO�@�R)��0�KB
�A�8�4�\��Kli���J�l��}����������̛7o�<Pف��*aOiaZ6�$H4x��ڱ��U���Q\�֭���NEr/��ރ�IKIz'�bA�h��m��X��*
ĺOH��FK�$���*��B���S���[�:�7m���4m��[�s���,.���_㸯;�K�*+}p���Lv%}���-��i45c-B{
����
wÏv_�
_���u|i$���L����u��q�(��?�����q5��D5Ss���r�
�@�A�Q�QG�����ԓ����k�i�]�!�Ll�.�?��1���t�8J�mv?�	�:�����b��k
h�"�MN�'���@@g~΋V8&#c�x�F�2i��&�9�� ��n
�{�I�O�^ø����:�W�NL~1e֟e���{R��h�5p��lJgO듙s���[ �}6�dւmj�ܥ�wo��/�#n������X@�W��BM?W�Fg�oչ�
i���T��+�0Hi�H��E�dW�{���GX ~̺d}�{���Y������gft��u��a��K����(�ǖ��=�<�vG�5���>�D�NO�Ŧt�^��'��`���H�T.M�ҀF���-'�
�=I$��ݨP�Wش�Y0V3V"�ར�����4h=sF�1\�U�	��l�?|�U��'EX^*��Փb�h�V�
|�(��S1�6�mZ�y|�^�v��'�`K�€�,,,�/�_>�_G�_��?���)e�gΌ������1�(�;��	�xϯ��Mϯ��}���Bh�*�����
���!��(�0�zO�ެG��vJJ<{cyK1�qA|��^t��@K9�#����72����e����|�:�?\}c��`�G�0%S	��в��O?���\0�=C}%7�6�
O�uL:{g���p�1`]��L��K��X��c���r��,��w�'c�AL�� �����/?d�$��{mX����3x���9O�C��&~���Ϝ�bϞ/N�	�����W
�{�C�{�m߾�7[5�Ƽs��O�?�ӧ�,\������x�]�!.�g��R�ښY�:*�d���oarrs�3[�{VE�y����>����v�[���ˡo��XM@Z!��
�+V�x���V�4Fx��an�wud<�����,�>8d��7�[���1���j�:pBZ�����<��p	�"�}��C�}���7���~��?��*�LamI�FP$��~��S���jˣ
)UJ�S�T_��塈2���#�<��MͧQ˨��BoDz;��{���1�"X��$G�݀��L=���.������	��[��q���Xi�����ԧ"���o4y^��ȵ�������>�~f�3��B5S��~VrnV
�����n��#��~0,���/�x��聞�?^ԙ�3�e�/�]����wuow�$3��gbj�����4�ר7�!�*�Fyj�gQ�;����9�?�2�~~�hў�������tO:�)��t�=�'݃���=�=��Cu�Y4$�[����:���,	t�BoE�Ԙ����LoHMe@��-5��,B�o;�{���q^̍,f4&��v�p��h�Ȼv)��"<��
�'�*�|�0Nز�0[�JnEE.W����
:��LD�.��D��8�ߵ?O���DP�I1����We�s��烏�8�ba���v���zig��������k6~���[~��΍�����q�D��>M���f��U��^OM8�R����u���6.x~���j��T�A��k����Mg�z�և�:j崉a�U�����3�iP�R��t��LU�xY���`�(��@|R��*���EDzgcg�@�
��'uA`�2+���,vЋ�ć/	D�t�U�wm���Kb��I"��et�'��&�d���{��b���D�r�RINf��$U`�>��[�2ThӌN�Յk��-��z�*�FO<����(��:s��X��v7b2u����Tt�\k�.��7�ǻt(���?���GC�߱7N9�5C�t����%��igC��̉g�S`/�@χ�U0>��`;lc�(��������|0��v0���:Җi#!5�a��
�*:���0,����O <R�|M���YJ���)llj*������S��nE�뇀`�O��Do�k��ͨC�b
��+��z%089�fx���1Æi��a�P��p�_�?�=/!U���z2,l�OZ��t�9���@`������~��m�nC�N�NPf.���l/�I���M���l��LX��\ܗKj)E�u�%u*bN �c� 7��kg1( �;�p{1��-�g1�@�\����2t��	7D�	P4-�oo�'�)%z�2���9�L�5)2<:�B&�)�:O�¤������T�]�E�ݶK����~�M�[�uN�9�\[F_���)6T��V��p�H��tK�u4�ӬV��<k��z^βɎ���tG2��y=���<�H"Go������1o��J($�g��fwd;�Ag��`viI��!����;�oE��q�-��EIc�
�(!"PG����in�Mv/���^;��1�b�Mx�	q���"���3��&�8*�^���|��ҿi�3�շS^W���Yb�iJn*M-��ű���]�o�.e��_����k=e�o:�Z���
��…����2w�����/�����/ץ���y�ԥ��yV��2s����:Q�b���9?͖�VtX�JOq{̿���;τv���yhOÈ�l�,oe�'t�ALAV��qҩ��1��ʳ?��Ϯ�Z���9����eM��*�L^w�©u���,m*3�ql�����U0�2�'�z�>��6_W����ʧU�;�(+��4%ɤfei�^o�H���$S���;�C�!;��竭�>��N�5)D{ʎ!�K�}� �rљ��y�V��Ќ�w�1�H�d�����e�;����N
\��D�FC�hW��vπw�;ty���9rӹ�p��\;�>#�~��`�)��a��h��Z�b��iz�Y�jq�;~���\l��ЛS����+�rjB���k���oPl���
�)^��NA]'ޮ�h�}��f�"�c����.�!��ok岭�o<���PB��{?L�'�Eԗ�
�D��	�=���]*�.�g�����J�Ŷ��}Bo�t��&�&��
e��\��E^׭{��/�NK޽��DX9#^4x�C_
jK"���w���C��j�M{��.��(,����ր���+M�sQD�Q��c�T�P^/4�y5���@^+/��'w��4}
����Zsũ���"�`W%��
�y��GIpC���0��:E?kݺY��Ɏ+	U"���5U�@��Sx�W�����.�0p���Ka����X}����:���]z����I��nN�6����C�̦�߾uQ'�|䘔U��V�є���N���=�?��v7�	9l�&m�O�N�b��{#p���G^]<Mb�H�d�|r!��q��؍1�����a+�n�a�|)�S��Z6�>/��	�SJV������N\�*��T-�@vf���V��O��!h�4Rh�t��LaH\d�,�Ӏ"F�'aKDP��o�(�z�
p�=��c��wd7b]Z�8p`�"2����X��:�"�ŋ��׃�'��H�����-2����s֯�{�/�Ǿh{�ThrĐ��!CT0b����/��b�
����	Ԝ[�9�>�(^��0a�tv�av؀ńQ1�So4�V�x��E
�Nl�n=��˜z�x�ϒ��Œ;�ؼ��Ѥ�$���.	)����_$��1(�}�5$ӊE��P۔��&�~F̩��8���ޫ�`(1���E(ѻ��&�G"�T��¹|���b,i��(��(��1��8��W����0w#BS��GX��K�{_g�S�.�ф6��g?{i�֛��뷛��⥶�v=�vlTRa���dځӖ�Ȕ
��\v��힁���U�U7V͋ ����*5}�$2��uC0w�҇A�å�ήC�v��E���L�SY��>{�4&��<zq�D�ADh������B����>�~�MjF	%ۇt�_��O\�'�,}�%�l)��h�z�%ۺZ���y�I�F��]݂�Շ_�'��7~�U�)�<2N(�;h-��P�q�]�aV%�?y�y�N���M��	��َ��y[�{[�h�1r�#�}B+:>̮�ׅ���N �"
��	ܖ���7A�q0������t�#I�$O*}~�����T��w���D�E�	7^� ���ٝ�#D�(�%�M�*�6X>$�@p^ ���
��")	zA��G���%b�>�>�T�^}��;�
�O��ǘQ��;c-/
^��#7w�Vt	s&��G'*�-#�צ�����Q%��^M'p�c��"��-�W��+*m9z�LԎ�p�������힒�{ɑ]�}}��(�b��0}��;ax]����t�[)��Q��@��]�g�Д����vÉ7g�㮆�'fToJ�fȬ��"�R���ۚ�˫DŽ*
S?u�=95�j�U�!9F�9��j.��4�p|�P�{wΔ���"Nz(m�W`���yخ����`Ű���Kf�?~F��m(ȑX�0���s�r���6��D#�P2	�='����H���BL"�-0j�0d�NG����̏r�F=/�t��u�?�"J�u*���/�^]2Q.U�����ԩ�\��|�O�Y�w�/^���p�9�ߡ�%�Ԟ��v��%���(�-��FʋkB��e�Nk�=vuP37g���,��	�}��Q�įKL����Z��>��:M���N�⏆���/�"[I}II}{R…�w�u
�R�_����Kn��x�RFmX`HS]��}G�ŝ�-g(�K�qA��M�"�����qpn��8o|�5R�g����1:?M
�N���
<�/@����U=��x���oZ�N?䞧���m�Yq���o~Z�7�Z\�Cѝ���-�:�O����4��u����y��	��=Q��W\A�F[%2|���	�BbE�6RM�|u������B)�~]�T� ��u:�L�*|<��YR-fgg}����L�b�u�}�aLW�W�ЈR<v�3A/VK�	�"�������g�Ԥ���7�vDȉ��o�n��GC�#��&����}��?G�p�.�cF���x
v�n�Kp_w�}^������
�8
D�������P�X�@j�%C���H+�O�5�����8}ރ���,�ψ�!��Bp�����=��z����x�Zm�h3����@|ُĉ���7F��^��Qef���^XDŽ7���J|6��ީo.��9�4����O�˲|!�,
E�(�4
a+�[Kp�
^�Ŋ&^�j�Dth)�b!�72A��yc!��$��y��� D�#��4j�oH��Vp�	����ٖ�O'Go���Z�P��T��1;�!�*�7����
��9�t��/��W���ȩ��
Ze���n�ꪞ��vMOL�v��:{\�~K�����n���jj"�)���|o����x\W���a�4�I3rXڍ=1�]�	�f"!
V@��7����cۙ�.��⃴#❍B���8����xq;�[�/6��P���.���]�ĞC�>��1a�%O0�<�;�,�A[w��*�
X�'����!(�=��i��}��&?��#�^$	^�2)�m4��sD��E|g�P�b�2�Dq>�����n.*�?�W̸x��(Ļ8�s�D���SD<\��"�5�3PsA90�7�@�R���F�q1x�od�YХ&���]�b�nʁ�db��zy�a(r�j�~���}@��8��
��	>���>4��J�.]���R��RŨ�2��*F
A�6�r���]��eH}KK۔��J��ҡ�ObƆ�������L�
G�hN'%+Sx�̒jU�,�V/�}�2�D5�NwY8�G���,�Je���A�h*c�幔‚�����wޡ�.���0��{D�x��Sf�Ѣ��2�w�$�F�-�:W�Y\���D,o�Iy�ך��nN�I��	�,i��)�m�#Y�Ǫ��j�U�-3���Y$v�%%3�Z��p��V򒲗.#�cNf.�5��d�$��C}���,�KSצIX�$fX�͊D��M�^uV�J�0R���s0=t�@k�T�o��RZ$��b�X��*e�V�E�W��ϕ�5��T0��T��nk��ޑ
��7&�$2�iy�ThF7�����u�bqe�y�#l�R�*[)I����M��k\���a�#��u[�N^��3Vq�אnL��(v�\���f�T�GQ�I7p��=3?��קw�(sn�Y�IS��M�g''g��aFm�L*1��J�J�2U,��O����}}���]�&k9-��D�����i-%�}jS*0������XX���W��b%��c��R�LR)��$M�����NK�,N����c�إ�Udf��I��$�D�Ģ�*$R�� f�LM�Mu�LձK�7�)lJeh�Z%�V1՛
�ڒS��.u��4e��l�J=�RS�j>��r�l��ڮ��b���4����%ǎ-Y]�#�,E�J����؈�]?��S�gz-K���=��:�b�����+4�A|h��FCR�(��"���F'ch�)���=
Ejj�����R��7�﫧��W*J�o��J����L2�lX����B��a��a��r��:���Z�cůM��?�'�-�V���<C	�^%�y/�ϻ����v�YYL�� �A���iˤI[��&mij�S:{��=ܠ���?�3)���?gՠ��N���%r�|^���E�����$��$����Zo�I�IM���C�ͩ<4ƻx���ij�V[��{
���r�T�Zj��Bu�T���4�+��v4�{Y�X�;�	X����ڸͳ� ��	 ׈�_�l��X�l|��ن
��b��q(:�f��j�M�+g�:R�?�1T�l��J@�׿����+�&�9��s�>��x��n����]m�P��Q�Y��5eS��0� ��Ư_?^�:w.rMP	ToܞL"�ʛ_��b^��GS�7e�ZUd����<Z�i�׈<Ol�k}���VM�PŇ�&�jY
��V�����j��dI|���Q���2��=�`H7��E���R�("*E��z!�Խ���Q-m�*�8���Н�1�QK�OJ"��R0���,�cW"�a!(�赺��L����nb���ޖ�N&�N�3:�\��)��h��Vw&�@ѵ�6���i���l
��,��>
l�X�������>�ͧAGM1	������0�B�ǖ�c(B�0lEguKP��pl
G��»v��h[!A�9�v
qo9����b\����#�}v�@�0�4>���
B4ZQ)�?ݘ�:>�u��X� vn�(��z�HE�~���Jń�s�(�7Pz�Xx��@�?n;����E)҃�4�E�J��ACuJ�yc>,Fu�U��i���Z:^�����{��P?��cY�ոOB�k����3Xt�5�P��T�Er�ׁn�*~)pD�����M�0��;bMA�폨p�[인�ւ��	4��]�Lv�ky��4a.�YB\��UE/5lbK2#M%P��J����vW�θ��n�p�����k����'`�@��ɴ�`iʌP�W��8Ġl�%�t�	%ʌ�SQ~V����pj*���$�w��^#G���1i��6��}��"vw�"��b��<nc?��ͦN��i&�t�~�ؤ���֭��:f~Y�g�m�-Y�`�ΔisV��3mJA�Ų�ɹ���_3��YUj�B�$,8�;DQq�����ܓE�,X�6P�+��բR`_P̋'�4Y�{[�*�e�7-n���w��r���'PŠuw
��?�u��:0S*�{����?E<�y��N�!7�Pղ��A�&��1�6l�'o�5�=���C��oJ�2�����x
^~�	���[���Acb-��~6��?���������u������!X��燚�������G�cD�q��n��-���&�h��ˀ�Hp�����:EG+�n�!�.<����zMh���9�l��b�젮�@�ȑ��p,.��U�i7�e�Q��j.��`)Ƒ�t�;��h��yAP��IظLK�q!���"���zF�Z�c
J�g��4�����F7eV(���`1L^5��B�+�������ڽa�]�-���j�l�ԅ�:�[Ų!�}!b�(����8z)	���_J�|�}dR��*��jq�l�Ͻ���KϽ�Mv��Dg5�Z5��q��.\jm�Ek6��md|v4�MVlq�dvԵ���_<r��&��M�ל`Oy���E�~�vҙL:|�Ư�0��g͂�aG:v��p	(M�S�<�ӆ
?=�&��g���<2��j��z��N�n�߿�V[��0?H�l���nۂ��&U��>�zrMZښ�]�].����?+;�z�����#��#J���z�����~:��vv��ۻ������$���3�1�~e�����ݹ�+t��J�G;�I	���mW�y�ؤ�q�k�*�dƜ^VX_<:7''wtq}aY��a#����TH��3:��#C�y�V��Z�Wj��U֕�?��;A�Y|�.d�7�R]���&�ODh<*z@��	i݉Aw�N�A�%L
@�v�I0�c���*�T����.3����9R[�VJЩ���,��՜�b��M1W�R
�߫�>EƉ�N,�`õ��>U8�z����/{��2�3Y��h�확b��^�āpQ����{�/�RX��_߲d8Ȭ��6e;���зk��	}�B
r�fq� � �Hˠf�ŬD	�ζ��%�,�Ĭ��m
?sx\��j\�W�W�UqC�S�~����m�lY��3M�>�q����s3`ػo���SL�4.\剶�jl��u�[��I��77쵥������������S4�m3�23��ȧ�ꑳ�����lg��@��͢��؏1��W��%`T�;�����ω�
�ExC�t�#�8*g��3�0Gx{�!w>滢x�i$�pl�ɣ�`
;f��7kA��fy���h�3>>��G�U�4V��O-����H�M֌o�K����<'���)m��?����%�{[2p������;��>κ��K���>�e}��}����ڸ�0�D���2`�TIH�nP(�A!6�Ƣ��2�h��k}�U�3��Y��ެș�t#d}s�|����'��s�|�\�P_��ξGփ�$��į8;���Bh�Q�",Ƙ��{5�k'Z�Uָߚ8��~�)��A�^�R�-��-�.fG��W�ԋZ�G�E*�.F��zӘP��������.$-J�}�&��\�V��T�Tnv�������?a�/'�n��-{4�yʐ����`ʡ5���e�9<�4��e�U斕d�T���	U6��?��AX&�튨Řf�5?M��A����6�eb�$�d�`�t��%Q��p3�`��s�b3�N����n�MSp��U�5�G
[�6C�n���q��Ҁ� �0y��"�U�(t�K\�SR�*1�S$AW~��g�S��v���t�QR[������
��%������Z��ԛg��X�o���3c(|�:c�(����s�V�l��`�n����Hz���*_��~�uz�<J9L�,���,3X�ӧ����X �
�,����t�RYP�����%$S׭)]��d��K���nB�d&�n&|���)�ò�{���
����K*�/���~4Y���k�N�_��J�u�q��h�@����kߟm���84@
����"�b-M�/g�.�,��@hL`H���.	�}��k�o�py�\�#4T �3�qЎY��cvh�/a_�I��N��O+�U�i��
S�V1���O�!�D�t%C��ԯP4`��@|��&��8CP_�º�OV*��^��w�v������Y����7�~�E�U������zD���4:
f�b��ʃ��HB��k�s*�DT�6tFY��e-�}e#t�5�}CŹ�Ο��z�B��Zs�����	���#��C��8�3k�؁�0!�\M �z�`E!hЛ=U����~��VФ�U�Ƥ�Ҿ�=Wi���0�t�ն�ş��4���<}�K񬗱���ā�a)*��[k�9��'�n�JG'�������Pٔ�	�0�u
��V�Y��T�J&Y�c���D��$�ϫb�r��<��oVH%��.��T�(�O$��
-ӶD��\ �jK�Z�4R��I5r����cѧ��Tɜ�kt�kI)�CB�u������P�T�`���8�M����.o� �0��$T�	�0a����W>P5���X"�ݫ�~P��]���#jDy���%K�j��$��-v!��F�~3�2ܪQ�5`.|�ap���>nw���/y��#?X�##J�w�5��(
�����Nx�4슩q�V��^�����=~�R�'Ҫe,�ҧX����M�}�j�J-�)T�:�א��w�3r�T�'�����x�}scF�y��7k�
�V0�\���S�M�(�2@��u�:-YzǮS8���W���[4;0���q��Ʒr6�SBIX��qL���t&t�&��#M�
�����G�#�&t
ڠ�4�7�0݆���I���p�X2���M Lu��w��Do2�`
�%\��7߳��g�
^mlm�W�)s�X��7a�o`B���f�b�nQ��1J�)�?F�T�7ѣ���;��C6���XV}EBq��:��ٗ�zh��W���*S/�'��W
I��~F,��앀��Ud�
�A:�ɫ�+�z:�b��4'�Ŵ���؉�szk��ܮ�.08q/8���k�Y��H���E��>��Qv��ŋ����g�O�~aժ��b��x.��쨽���'��T�Y�&7(�w^;�����[�Ս��$�\0w/��6p'�"�>@�'�w.XHZɋ��(���j����X�yc\X��{'Dy�>z-�z�x�y�>xm˔���ۜS��^��O]Ђ���{��E�&`��`�w)�+��ySL��>c���u�a=$+�h)V,��7�R�H�֯a=�U���<��35@f���F��9N��i@6�݅�L�D�Q�s��-�cr�졂z	���
��W^׏�~���чS�2���5�$��Z}�݊#q~��d{VF^�ުԚY��l�&'��Jk~O�� �V���{��W��|šG&�$��d�]���8��/�v�Dj��&���7��x��Ҥ�U떦���ʐ3���{W��(1�O-����T��}2�����k@N�H�:e �i|�}�,N���j��$}^�\�����X��,_+V�r{-���s�v�7d/�zk�ux�C4�9�9/���%���V���<��S���[ƅ����ٷ��_��:<�}3�^;[��l�z��A�)���d���}���-��U�������}�����sQ������H���:�z��3
\D��_�+B��3F�	xh�&��>����ϕ����4�]����j3�=/�#���T�Q��c�ϱͫH��Bw��_��Ee�^f�[�џ�3���76N3�w���\�"�R���1��v�/}}�"�O{<��Z���@!�g�(��E��=
5�uW� ���n��&�iK�$j!�jw%P<��T�<�N=���Q��Z�UA�nŀ82�+�^Ra>?�1	�E>��9�|�.�mV�
�
40
����l�<kO6�ҋP�$K6m�����
�&�w63�dV�k�'�Ո!���o=�t
4H���Je\�r.mOa�z���
*Z�ҩ�W���[.s�ߟV"����k>���K�҇k�|2A?���g��`�f.�}�W<wպ���+�����~�8�U)��-�l}P�ժ����*R3���7�9~�>�F�\���[XQ:�J1�D��~�NN�*(|C^�&�@���G���j��1:�;kN�\�	0�ƅf�Ө��p?���$��0����o�G�G�߽�0���Cは/�������z�����F�4X�~�d�IE���[��.����9љw�I���`� 샧�'�a��b��$~�+�/�m��`��.-�� Q�b��'͛�"+6�XJ̓n+�fA0�����H+�l�_��sʴ��!�-Td�ؿ�O����dɜiL�j�����N�q��J��ɘe���O�;;%G�'o����;"),=�K��
�][��� g<�F�h�.��~�[�?�
u��}r�����f�2h^�3���s�j��ƾ���5��q0f� 8���u�Ĕ�,'���5�D�k��)@?\��a��^�=M��Z_1�&����c���M�Ͳ�k���׏��>��|���M�o<�<
���4/�c遷�<�l�ٛ��,�v�߾={{��5���Y�{~�'��=	,�\k����^&�'0�tX���Dl}�F��G*��QT?���.�ZۂK�
�u-Z���Rhu���0��!$7@d~X��ɢŎ���xx��+x����4����V^�Vu��P��i�f
���w�z��9i�{V<��ї�Kw�#=��`������~ёޏ��_���ф3,1&W->�xj��~����ܱj�a>�t�x�k���la^�3�qn��i�i�З�1M��Ɏ�H�͌�و������
KQ�j�1$a�g2g#��K|�!�y�eD��Q�Lx�X��{i�4�{{V�����N��l�	��Ѩr��|�_I�G�$iu,�N�?TW�߂bt*x�����A��u���t�A�Տ�7���Ѐ�\84�d��ه&��I~�Xsu��l����0eZ�~�rsUJ�kG����
)�2S~�m��Vy��n#�~�c�hV��A+�c%�YY�� Z!���W1������t���A�1y51�+A�E��8��ICo.��V�3��['��1�;��S�v2Q��:p�ؽ{�/f��b/�����vܽ1<I$U�
�PUa�hTRI����ԴV\U��j"��RkMoy���Ӈ�
9* ).�:{f��=�Ͽ���oQ��j�%k�1���y���T�}�[g���h��n4�4�\�5rd���]qۇ�C�<i�̬�𳦅�l\��E�O����C&Z�*ZZv�i�-��w�����*1��t)����S�*%/��R�j��J�5e��y3�֏W��l�S4j˔j0���4�ܮ��ղ"��aDwϘ֯��F8�Oͦ�&��}�6_:-�HŜIE?�2̓���u�q�Cg���b�Za��f�J�j�4T��L�
J�c���X����h:p�{�[`���:�N�6�84�����J&�n�F�ٗ�,-P2d��_
'1@�2�'��r�dD*�Q�����e?<slj��I\��x
�+��ӽ�Đ��vs�.��b	'���YE�UpC�ӥT�)s�N'S��mٱ�9X�x��mS��D��Ž���1�ON������hS����Ve�湕�E�T�:0�Oap��Y���§Ff~��]8,K)���7��BTpK��/��Ue�dm�Az���kT��`��c�o_�e��k*m>��l��^:����f���������y%����6?a2Gy������8�r�mng�ô��0.�ׂ~�X�nj����cpD1�N70%��p{����UWܥ�҄�oS�(آ�	�v-6=�C=s"�n�"^�D�͐8'��ݿ��
�ڊE�BTPAE��U!�DwU�I�O�e��p$�F���Zo��|놪��'܈s!}��q�"T��P��d����(le��+�����
V���W^�Dl�Y��s��:�a����h�I�`�X��k�����Uq&HI�R�&�
����5�R	�	
�r#�F����<oj��25�O	�	�jv�IS��2_'z�"�e�l�+]f(�:�xt䊬��!^G��@��<~�$;%�"#?xmC��}��\x6�4�+��֢}����+��B�6��ԡ{�v�d�d�N�?&s����T����ca��x���i����R�vKf;�7�C�U*�i��U�व�fZ���4j[���o�`@H��2�,W����i�Pr���U���)����L	{�<��\\c�@���sN�D�:�_Z��h8))zo�^�R�A�4����f[G�h�ml[���Yoo�m�
J&��N��s��KŁ���/��e���(���i�lX�J��7x���$*��1�p<�p�iJ��@/F'�Ƴ�v��xD,�)�N!At!f�=��ΣCs�^p�gs��������߯��x�c��b{xT���N��S�@�`%	��I�S���O?©�7�q�^�.�3l�T�Uf�����>�-���M����>/?�}�D��Le��J�����{L��'����:�y��!��=l��g�w��K�sC�8��3�j�wV˩}.�����'v
c���U����Q)I�{W�-Ly�}0W�_훰���S%�����YIV١g�D�7�;���;Z�X�4vh��H��;��n}5���>J1�3��U!�P�3�xd��}�?1mډ��w����E��R`*�A �36��?M~h����Ix�Y=	2��8L��q,�6�h=΅��P�t����{k0f���7?��rF��R�����8`�vG<����ؔkTzgL+V����aL�wp
�#�
��&�ɼS,Y�~>�o~3b��!w�cE.�� k����,��)���O��>�������e �1z<���g�T%5"�<O0��;���J7�Քc� ���vZub�o���9�� 
|DIϧ���\,.�M^��<{vrZ�|���l��	GՀ���RE
h�+�hN���,#O���y��ߛ����~��l�}��������MMGm��@�S��a1\���q���r`}X$b�SRRe�ߎDK!F.��ӌ�ޥ�В�Bݧ��{�b/�Xϐl��b�01�v�.LQ-�c��dX����B��G��������AWZ�S����Xw^�y������Z�$)�퀜`c�Q��f��qوa�����1X�� �^j�e9r$Kf��d9�Lh�p�qը��`#�t��dO�Axm�~ >���<��aIŽRZ�P3C�y(�Q��0SrO��
yI#l�YeRivff�T*M��I$E���F�"}��
Z�2j�,}2x
k:ح����~�(����a��
�/P��{���7w3��߮��l�g������J�-8���h�|���W��yw��?���W�m���x��@�_�~�>���	�V*1���'�_�n��F�BQ���X
�!�I'��P��!q`3�Q���ltS���tb‚�����	���/��<�;ɖ��?��&%�yD,eOp8jb�>��
�@T����ᄊc�η歿Z��y�w~?��z���E���g�Z��sq	�s��n��ݴŖ'��2��;�����͹�����G�z�,>���#Q�Q��?_���bN��Ɇ���Ӎ��i���v��njj��~���w`�GS�^`�=�O3c��M#�!�ȧt�xۄ��~����.k:��D!�,茮�?�:�A���t�$6p9�*�> bi(�[�nϠ�A#�鰺I��h*~��[��Dqt珓�j`���my.� ��7���e5/����6u�_T
BXa
��?��-t:������U��fr�4R�J��J��o��E-���-j��#髳,��*v����>�&�$Q?㰗.;Q��<a�U (�b���t%�ա��G1*l�%�:�ӣ֤��l�&ĩ���d��,�cqku&Kn^��xg#V�i��؜��k1�n�'��6�09�+�l����|4j��cS��]�V��j�e��A[��)��V٤O���Y�Қ��s�]�7gxzM�/�]���K���ҿT�af8g���zYw��b;�I����6@^�ԲzHI4Z����!�D�ћo��l��}!
0��'��\F�ō��2j5�� v��MxK�UM�ܻ�-~���C�g&�
<~L�vU��3
�� �[���|V�\�f��V|�r��9��ܐ�v&��q��o����G<�7���kZ��}�)+Ig�k���ʋ+���ɔeҙ�9s�
�9���h��O�0�Rk�+�_��6�`S(�X������:��G�i|�K��o�_���v�����fs0Ca��&����������<�7(�
ه���H2��*�2b6��4����OR֍��}q��rdK,��WS+c���+��Y���W��:������Ē7lVCn��d���\�O��0�ƢZ|׌�����Z����1.k�?WC�t���E�jt:��dK]իG��>�� ]'��׬=f͚S�'�
��3rx�W�˯�f8�{���)VLo0�床��|`��;&ޱ~Riqì�^OMN�T�u�G��:���I.A���R(��_�M����o�=p��Nt�M�j�7���#�~��s��&#�K(�=<kw�r��M�X�wZ�S� P{����D_i����5��ݦ��v��K�~�eh�*9p=��Į�Χw+zB���=�Ԓ�\��s���V7�ӣ}�i�m5�Uk����	z�G9�r�k�A3�W��'Z܂|�Ȉ�C�'<�FB�o3�>q0:]�p�N�8D�G^>��HY4���׻�]�F�#��
÷,F��h�L��u�O�'zܴ��%���*����cvv�d E��lg���:�1h�r3�5kg��Fa�t�u~��ˆ�����m�>џ�z�9q�L�I)U��<�g�x�
_�ifm����љ�`��.���l��8�s��dg����鶍yX�Wx�6ݴ
�e}�ư_("�/�[0:�ӻ��އ��6:���l�6%��P�,4���
P8�u�,:��N/6�Ƿ�7���.A�ߎ��gd
6{�r0x���؋LF"\b�6(����%D��"`�F��v�p�g!b`	�_��J*eK83|q(�Ԧ�J���>W����R��!&)A��|r�*�2�H�8���%ݠ�Je[|MojP?�C[�8����ra�9�3{c��bqo�5&��0�
4���%�e��ٳw��<<�`��� [�S7�߇�?�����C��Ӟ�̶�{"��yP�����n����)�hAc���W�z���Z*����y�b.u��rܚ�[�%Xq��Ꮳ605����n���'N�y'ND����~^���%s�%��藂]ML��c��B��uJ�D�O��_D~��_�8��;U�\W��#'��s�o���MgC=P���9���NWǐ�u0-�ת׶�Nn�k9tz9M�F̍��(�"���QIS�?�E�@!&O�"��>H@!�����}Z%?
�����?�	��q�x�6r�D.�L0"��*r�8"���GO5E7�9���?Е)A�ֆ��u)�~Q}@l��� Lrz�\�'��I���,�\z�ӷy���M��ڞ�0�`�����V�+����έxFGO�_�C?ҭm��2h0���~����|l��C��l�q槇�L?���d�n��O�u���D��`�mp�t����GD������Vf�롷G3�H��	>F`��h㖋mp��M6�\.f/�ђ�E8��	:|12ؑ92�^
����ԍ5k F?��p�A��
��Иwd�<�	����w=6���J��@l�^�������}SCG�mr�������f��%[ϧg����i��\	�[�x����,�ރ
u��*�Ժ�0:
|W�l�rJ��i���6��}�w
�,�i2�ִ�i&׈��y|�[��I�0�������C�^ym�r򑯎�i���&�"H����m$��ۖOv���y�x��t)�^��F�(  
�buroQ ���i7��c#���R�s��M��a�v���)����)f�DjL�(s�b�&[��s��d�Tb1��s_7�牀��:�U������_��UX�/ϭXqX@	��Й[�F���AQJq��#?����)��ߺ|�V}+-H6���a�Gt��S�x�Yq~�ㅰ�Vjh��W#��r���#1�!���w�48Q{�n/��������i=(
�U�-�z�FnU5�˖g���R�qw`�c���4�����g�e���j+�6C��9e�in�33�Ѭ1[w���c�⭽�ҿ�ˏ^�.L�\�x��K��1m��s��\�rG���U5�^4�Z��!�Oѷz�h3Φ���w��ye��ƹ;�R=}�&��z���(��6�It���}	|����ZieݲNˇdK��ۊ�8�'�slj��	9I�!��R �j�p�%�p�%�H�Z�޶�(���h���ʎ�Ҿ�~ߗX;;�������<���<�4�kA`��6KTV2�^4���"��?K/�A��nyܵE!��JbG��*/����J�Z�X���?��3ҹO�;��OCBp�`����D8o�r[Lf����5��~���V;������>Qq�����J������D>�C\K7���]�A-�a�oy�@]
"
;�v�sHH��'����&����!�zX��X5���g�ԞNpCM�N���14�^4���x��F���~Fe2��1����)�^p?�#fJZRԙ���1]�����顕j3�R�%��i5��!���̐�?�����B{��WJ-�sv���a����{>�Zi�9O?��W�������'+�Ӽ�Q�J0]z�L�BVQ=>�J�}FS*)ƉFZ5�˨Vj�	�p4����]��!n
s��Ds4���3�Q:�pӞ#�
���'��N%;g_��=� �.�2I_Y-,V��H���>{L�Bg6��ep�;k��J���W��"u.#|
��]H�������(Pڰ��������F����t�oQ���,�V�XST�fA�ápuN�\[;o�����l��BME��hZ���ة>g�6	%�ؑY�$h�0g��gyX$�^�T���D�V��Å� �b��$R�rIh���;�,J�>`���i9�� P�*N����J���}�׌���.G��Be���i:㳙���CB0�1�Z[-O�L��|9���uG�̘1G�\~��;�]k�L�C�S�Y��bz�	ɪ�:���Q��R�����n��NH_�X�>�����҇B�B�)�,l}�U�1ƙ[	jV�]Ҥ]/��?�ϝ8i	��~%���I7モ���l�4U��b��5��˨5��Q7Sߣ�;{��ȅ0N��|�v4�-�]�����$����e�q�����2\Ni�%b�d�.�3�]��@�8m@�n�|7��\9+�إ2�9�e�9���?�G-���n@�@��R�H���T�lI[���RV
w=b�C�����A9MVꐗ#�bPƝ����&�b��f.A���@�c5I����ؚ�=����>,�/�eM|ဌ����b7dI~Ќ��Ӧ^���@�5p��|��n��`LZ�A�Ŧ���*�C���}d��.y��<5P��U=kR,��5D��«2+g�/
G�3�2�
�S�}r��.q���nƬ�(^��*p���ٍ���9=\�<����,�Q?"�|��p�)�+F�kr�x���o>.�����|4߅�A��d
)S:�ƦI|*���Έ� q�Gs�6;^O�~+r.�uD� �뻐�%WC���A�QTیu��ր�W�3��e�gչ+��H��D)����)0:&��p�L�N��t��~�N��m���yF�yOs�[
���`\k���y;�h_���e��0�@�.ӿx�9�?f`�/�Z^���}�W�BHR��o7z�`��@�Q�4��Άб�����L��w�l_7�^=t�=�SU���Z7HGq���g�E�G�J}9�R��c�jB<�T��M��B�>=)Ĝl
#=�v�~�����x�q�vwo������D��k(���k��.�	�@���@ºk!��}��!��HZ;wg_8�}V��ܯ�pt��>���׵>x4G�;r�>�p<8"���d4\:~F�B���/�P�Gb�fU�ޓ��J�i8�ۆݹ��uM�5|35��.a��xn�o��X�0f�1K�����4?��szRG|���{G�gjC��B��*���:����m�6H�}�W�u{ˁ�6���֒B��-�yC=�Jۼ�;&[8��ի���4�|r�q^��9������pH�/U�`mP<=�c�x�O����A����X^�kC��]M�I��h'����P?�Lq�A�C�`�S6ħR�_�h fA
��tL2�jX�BZ����`�͘�p��iDl��JA�Lx�f�ˮ����Ѻ�������ԘUА1����3�CO�9�Ka��|�{۾��T���z�%��E"˫T*��7C�xvi2V�d�9'�a=�z�ˣ�VI���x��F���:��x-�
�i
!p����;�m/�Y���p|x(��~���B%��W��~�FA)�1S�~�����?E4���=K�R���0j*^F�R0*9GH�g�PR�
�Ar��X㲁�xkҽ��쯎����[��q���-E%�C!P�L�4"�z��ڲ��\̛���_�L�#e"�ք���D�WT�SҁP)ǥ���
`�Uo~گ�9,O�`g
��^O��&����W��K5�0��<�0�Ħ��������]o�G���p�
���+���
*��H��EL��� �b�5�pd�L�_Rӥ�J`wD��c�C�l��<�lV�s'`a�bpH���������؃���Y��"⺽�~p��.��|�T0�?�(�CҌ��Y��d�T�c���ؙ�kMC�ba�2x�GM�x��ؚ��6�HF"�"���v G�h��]~l�K���$n(L�bn$E�-��ѐ�po��aT��3�'�f��r�I�a�l���4�;�%�Ն���WE��Qj�+i�"\�6�u�2O�����,�G�>n�%-u�'�w8_iJ�qX�����l0kD��>��%����K�>��g���g^Қ�(a
��󬬔���H���΂�l#�*�~������)���e�,�3L]�,�.p��`v:�W62|���]�����ţ��^J+���q�XrJ�Ű�/�a��b�
��`�ݰZ�<��TVb�;o�ßv�����	^���Ї�@�IoCe�W���\�c7
/����-��dǶ�.���}���.GK�w����������e����O?}pr�60�����l�zo���v��>|�t�y�ֵ��B׭�Tup���m_��%�m�z�c���NE�(�O�D}�˹�8%ٛ�	�/V���a�M�r��8NJ
�,�3R,���w_V^�Xk���� ��a���'VZ,��CL{�TpU"2vh{^�scS�*1�b#�O�QCm�xf���.{@(*��Fz孷A6/V����f��p���'�wG��`�)gI�	%[�?�hN�}��Do.�ۇ�̡c��ܴ�m}��J'cy� �
��*2u��=/6�u��X8h��kll��eT��ŏ���P�7h:�xX�hxQƯKh
:����a׈�~RF���%
6�.����x��0����F�s�u.V��l��t���Oa.`Epv�:��V�v����q�dE&�;HpYs�`P�k��3��$7�L�X�ʎ&�x9ݾ��J�R�35�\���zMp�hg�>�0[��Ġ�[����JN�M�y��F�Y�������ԏ�O��
f�N�ȼ��믨Z��w��b!��;;��kԜ�9_]Բ�?R�pD�,�V��]�Z�n�6yA;S�k����Wi`���� ��@]�!t�e�Km&N��̈� tpT�ڄ�?D��!~mR��+�u���&
�Z�9"�O�
 "��FB�M&�A�J&�PD��zP_�N"��ce��`��:P��K�'�`.
c Y�D��D��g��:1�Jj��rQ�U	��yH�"6_zH���7c��aO��2�i�s+�����sz�Dm���^��uK~�
���I�\J��lذ����S�G�8ӧQW}���{��J����ޠ��9Q-r�y�!pF}F�KA
P�}%#��2m�W�2�cMK~??X͈g�f�63F�{��/��C�xU��~hx���_�D���0	D/�(�g�[��~���=�jG�օF�t�Z��.;�NX8�)˞9�3Dk��k��pHα�6���A���#}�w�{{�N��ޚ�@�gDvYv��,[��a�%���ģ5�	�;�nP��s�;sZ(x�pѐ���+�u�G4�߇s�����>=%�s8V�o~��Q:Ot?����5'��f=tg�t�%���_���4�-�9���\��G�p�Oϒ�E��7�s�0H��u�L�c�W��@B�T�]��n�����yK���fm-���1�����V�|���u+�f�Ï��'�����7��6g#�w����v��7��
/������F�)ˇ/��N����w�'�gH��\��Ǩ^_�9]>3�O�P�h4\J��n��x���I���A4�]:2�p97�i4T�z��YS��FMa,�qXK����AJ��9%��+dDF��������ر��DBF�t(LF_2��d���u"�ၝ���E9���*���D\���5����A�5�Ќ���o��a��Zwm�ۛF��^w��L��ꛆ��S��c�X6K+5gff�g��U�ߛ�vK��sn��1Qδ��ƚ*�L'S]�+ �~��)�WOK%W��'�-�3�Y�P-
Vh�U�<�į����V�-"��aO��_����*��}3n���Ƚ�]\�g���=tr�	?|���[s*������Z9��	�7ݶ�wͥ�p|��xb�h�d�}����-��P�*�vsӋ+�I�4d��ʢ�|ciS;<�|��ʊ����}帤�F�9}4d^v
��dy֨��A�����2��
-�d8ߒ�S���80De�D���o�[�Ā=��9i�o4�g�pìi5�߾�����L^�d)�L�X�&�s���7�ts���X��5KI�Ճ�<7s�e���ajE�o��9'��F^1#��L9�����>�k��G��Y�ܝ�f�^L�MR_g����S��du��v�mySgOOg�r[S�FL���������8��J�FQ�x
u6ʆe��z��>z�7Ʊ����1ɰ]5��Cքя�ҡLؤMf)7�&\
Cʓ'ky�D�=X!.�M�Xuutpsر��^o��S�*�qT�8�l{%�zT�
�TOmػ��j:�D.[>*V���Rn�BU~Q����{ڞ�y�&W���(�Z��
ɮ�v�k�:	(R,P���(�����
5�\��T:%�E���5��k2�U�::f�g�R���޳�!Г�d8m�/S�����t=��Z
`���I��;�B��������VUaft��e�������	�0)/p�������!cU����JƧ7ŀ=d���!]�3iu�+*4ƀ��3��s$\�(��R�g��E��������m�p���X7��y���LC�ZQgin^�Rvzi{U{|*����͖:�:�+�w�iEHaW�q9�U���u�O�Q�Q����=>���mLi��\�@���W�icU��u���`��̶��V^eL���?�U��IT�ch|58��rTVRmS�TQ�+Ř�~��cՎ%p����������"�覫!V��S�`D/��\d������߄[�Vy!��UE��d…�[�[F�ص�¨�A�C��V<4����m,�i���)C;�w��f��\�N����r������+�K\ �֊�lm��N�����}W͠�޸��0Ӯr��a�#2u��SǼT���!z�؊�?����n���+�k�s��~�����W�V���_��W�w>ҁɅRS���I?�;�|Tɢqj5"#kU+�+A�14�r�F�t�y+IN�y�����0�MYcX����p���dW>��q++Zb�m�bilˊ]m`A�Z^�L���ޒ�|X�b"ku�~p�t8Bf�x>[�&�cf��0{
����]�����3�̟y~&�H�3P���|m][`7T�GY�rfn��,������k��f�x�/oK�_���
��*{���t����@�����2��#g��=��/���{��Lg�5S?�(�lK?òc��!_0��3�	�γ%��
�
�ɰRO׎��-S������m�r��;�<����ɪ)��1X��ɫ��l�̊%�"a ���	ΘG՞��v'b�X����Z���ȝ�܉�������l� fm�"&�}GPX9{ΰ&ߐ�R��asfW��1�^|���q�4���t��؍�Dӻ'w��'�wTRE�dj���i����}�GU7�c.�.}�!.zs�Em��j��1��ݐ=�0Z�,S��qK�+��J,q����&ʹ�V�
�)A{���0�7�Ы.B�,=�1yd�q޼��΅mIƣ�*�?����	2�|��*�0����V�B'G!�$�h�B��Va{�(�H���e��Rz�q�#.O��b��{�o�2E�+�RGqaaa����l��ZR�J���-[~����[�ٗ��V�-T��l"���C"�,zw0�gѬJƩ7+�f������g<�Džo�����*p��RG�oҟ&���%c^�~[�$��[⑩.wػ�<�G�wą�u	���a���D�Z.n��&E�uF���C~����L_��3��ϐ��v�5䙾��/�\�!���̫zB��kh�y�8!�� ��G��JR�^ό�*�_���4>��S�k6�A��\��6��n�Lz��#��UC�ر-�Ww���a
�HI�I?�� ���2P���j�&����%v�sh1[M	ћ��r����%݈$wH���d��~A���7�ś? Wa�º�G~�*|�M���^��nY�R���o^�zz�j=��#[ۀC^�W��b�H�Ro�0�
sd�y46~ZC��7�{�Ɨ�����sݳǟ�n�8d]�I��U��֝{6N���Jgnys�]���7��,�m�9�F7��	���|s�湟3�i/�峹7���fe6ʏ�z��&1>�+a��K;��i�
c*��k�پ�m۞Ρѕ���s��0���HzBτ	=�gW��V�OR>���#9��~��Vs#�y��nIUM�R��<��}H$���ո��6����K��.^�P�����}M�̓�X�O__,��!�0�r��I���]��^�H@���L�d���\LӤ����)5mb<��O��J����D�F:ya�������/,%�׿���v�#�!�oS���� 
؋��Kn�biBq}���c�׈丣���&�v龖�V�^p���%�Bڹ�L�YL��LH|��F��N�
��F�	;9d��3Y�	o�#A����b玲I$^9J ^�o����Z*E_�|D$�_��k56�����2�Ʃ��Lmȟ�x����m��n_�ɱ;'�.6���~�ģJ�%�E�g�/�E5�E.Ì��sn��8ڗv	�t���Dx�r������礟/j��;�QR�nʋ$�;��O�6�^G ��Ez��Y���g��&��UuB�����W����Y{o���3A����c5�Y�Y"q�.��SF�/��Meg�H����4��N�^��3��\�m:���������.��z��69lP�P�i}���Vi�D����Ty��7`�k�(�\fs9�H�&Rv�Pi�*��@�h^߼N�5�kpW�V>IV-��ZP+�B�3�5p�%��oN�����ਟ�q��o��D�
6q�+���uVh�Y�ᔅ��ё�BVӊ���*��b�K��h�.8���̲�6���_�^�d�dy�ԠԘ]B"ђ)��,��i��37�ܿM:�_�i��~�X�@����,�-�Ѭ��,}�pa���<2����8����<�|{����ޝʰ��~�Ő�;,j^-�@��d.��=���4�cj��
u
V%]��8���})��Ϸ���$'*��K��	�X1��l8HH̛J����41��E!gy��,�U=U�=M5账��z�GV��!�=G�?l�^3�B_n�evM����IY�dkۖg����5�:�ñl�fp�l\Cl���;�>��m���J������_����$�\������?�7��wj=zŊ�q�
}Lx�	{�o�FQ�.j.��ZM]Im�n�vQ{e���W`�el�|cΑJJ�b�L�sI���R���0)���-����
�;U��M*��C�*.T��]��<���
�z��]ʗu��@V��ޗSޕ5����3J'�Grd�)��,���ꁪaWw�iְ]�"Fs�-aאb�J:D�r�1I���'.J	]��-[�|����:�j�6"y�F�vju/��c�Y��x��|�P�/���A�ޡ\(��.�]V��H���!��O6q���r�����q�Gv�X?$K
���q3̘�&����丣߹|d:dnI&�.���B�Zz�b@�&�[1�㹞��~�_��OG�>����բ��h��^��Q�|��w4]���`��]��w`増�s��^toǿL��ψu)VB�l�N��u�x$�V��6����}y�q�c�<$^�G�VM�)$��U�e_y�[��ń�$�`xK)J�_Sn@�6z�D霘�1���-��=F]` P�{����7�>0����!Mz�m��)��?�������7?�y����i
��XyUUê�Vl9�U5Q�y,4(�/��5\}�?o�&,{w�)3�]:�~@}.m�@k��&�^I��'%���ŏ�q���i�%O�(5L��A١���z�j�q� ~������q
U�@�J��X����g[��_�RE�J�rb����r�ֿ�|��v���� �e4L�E�Cލ��f?��_^r9�-R��7~��'�rfna����@S4�S`�@4z��9���Me�`(x$������[vrQ���
�p������
AW�_v����.L��1@!��Cd/;)̡�X��?x��{;T��?V�v�a�vՠ8������m�rqF�ߦt����>��_�A��?���P5(~N{�'\:o_\z���ʬ�c<�%�}[��J�5��<<���_����yR6$��k�j�~F���Lt���ɦq�N���DrÄ{��� ����x!E��:��0���r ��D�8���ҡ��hWaY[�p���q.�p�Qr�Fv:
�:&!=Q�Ί�PXǠ&e":�آ}0���hԺ�A����
oU�{��6���:��+D�޷3�2-m�y���,ͿH[�>�`�P�P���tQ�Z8�f�����	:g�AQ�V�*)�Bȃ��&���1�^o)*���k�V�y,Z��/X��V˸E���J?m��N+���g�jGl����ч|}���kC_��s&`4��l�-�B!�W;�ZmH��5��ƿ�+qJ�(�l�9��@gQY�9O2�]:�jXڠUPRb��Ty�q[T|�,1�%�g2�WZ�B�����bh����u�aI,�{b�A�1٪D�P놜�z�|$X>�t��B�����wʞ�N���j�a��Nn��6~,
��Kڠ��uX�h�}y=HЂ�h$�����A�T��g��wLa엪�͏�1a�x�r�
�J���t�<��&5Q���)`���6/4M��%���go��oj,
Z
cM��Z���p���Lh�֩gGdW��a����75Ł"�֨VFm���:jYh�ڴ�i��6�͛�q4e�Mݰn�1�Bt\�T1U�x�;$��1��H�kh�b�Ą�Џ��H�����1�S�[.�s���Kګ�d:�I����J����,
�~�~=8�p�Ӭٻ�ddx��
&�%b�(�Ns�
�ZF�sE=����X�x�-9��FTx
ʡ�6��u���sJ�n����Ԭ�xO*��(��^��F��fа4JH�۷���}wI�@-m��R�硢��'��,����(1&^�D
+1��/������������J_�i�^F"�����5<�M�ҍ�œ�KѾ���0�5J�@��c�����"f
�j�W.Z�1�mҴ�m^�d�����
oJ��)�m�[_s��E
��}�/�of��+�~��`P��]�q)��H����׾x�Ego��륾ᝁ F�i���� <���]4d+�>�P0�c#ۜ�z�w/��]�=�s@+ܳ�<4���-���#�H�w�4�f�EEi�xk��!���+T�-
m5�_Vq��&[�A)�f�����ӆ�5��,�(���>�,_mW�`
Ђ���v��9t�͛�Eo�s84*O��{����l�ӧo�	��LjF�/x^ý����^��&�S�P8��>��A&���::�ف V�7C3�!D6d���!X�|y:E��_%7���gk]�&Tm�c��VO�#P_�3k�*�"��_�/�o>|�����������1�r�'���X>�ҧ�/��%�H���yӳ�>����Z�j4һ�T@h��n�u����/~�L�y�C�a��aU�4�Wi���@~�d���y��G������Z�qi�$ݥ9p�C�@����&�sr��<>K1�ѿK�;J����D���,~�t���&�<��g��OvL���;^��I�C��J=��^FmB}d�C�,~�P�xG�2�?���XVD~��h"^�?�]n(5����2?�(8w�L�3�1��[H����E��l�7�?���+�G(���6}�[0�)��ư4
�A�k߄b�؝��k�Ŋ��uX��U�#�)V����7Ń��D��e��t�[���ٙ�>�@����84�� �-9����Z�.n}:���Ε�z���#��dh�!��
ǥ����k�O[�:���!�]Y�)�
�t��dO��r�����rv��P2�+�2�*T���EڄUj�PB�wK�Θ
=�����|�Ǥ<��3��n魠*ڿ�fMh�s�X>W�gO����N'$�u7��tAұ�A�����q��h�͌̇��D0��'�*��&4�0<BXFF�V�}�o�q|���߻�Gg�^��ä�kש�G������NrJ��w��s`Ϗ���U�L��:��J���^��	��c�k@�� }ߓ��M�$�?��t�^"�Y���S�N[yļ�+��]p}�L���FY>�HCA���qp��y��M?�x��	MzA���
�>Dm�7�r)y��蒾V�͍������l�1ύ�"wm�_\s	�ɬ�?�=OM�fR��5�U�C��ԫ�{�G�����eHa[�y����
�=sD� R�U�W%Rd1�'�=�uR�(/_� �9�ַܺI��
�"�%����;�0��ݎ����b�+M���G`�p�\�{��?sX΁R�K����V7��M3��y��>��
��s���h�)wd���c���yt�\��̌m��7�x���5~ng��l4mp‰�Ѩ�!k	ԣI�dBG�4CB�s�5C�OYb�jo��۰8=vMa�.��/l�n�����M�q�f���J��,�i��a��s2�`0:�{�Y�),fs~v�A�t��T��1��2?�+E1�V��h���cO=��B@����U�
X��y$c9��h���
����h�ׂU
��ׇL_�CAkHq�>�������yJ-��-?��I'��<��TJ#�2v��$d��1��h0�Y!}=��n�b�J0�d��N݊�T�l_9V9��Jk����m���{\n.ӡ�&GTA�B0��f�s�f�X
|,c�:��k;�u>Cv����F�ގ�sZL��W�T�x�c`d```a<=�|Ed<��Wnv�b|�F�������
��``b�d#�x�c`d``c������8�"Ȁi+{
�x��VKkA�y�<��,�5VIL�,���E����"�E"�'sj�����J��U3U=ߴ��K>�����Փ��g�_��(�ET��u���=O�'{?<c|u�>�Law��]+t�w���^��nD.�}k�zՇ��쯍U}ɩ�o9�:�΋���;��FШ����O��;��XS�B�[x���e#2U�o�ا�C��������??✼	9�Xz{w�>�	O3��E��*��De�[�=픖wE�:s�e�I5o�ÞR݇�G����=SB�P�s�|W�+�Ⱥ�	��}[0��l�]�1V����~�ٴ�F�o���M���r�����;�'�����O^gL���y�h�o����l7��/���ӌr�q3}=vC����C��HF=�ǡv���@�i�lr�.�r�4�C���үV����ldV¬�L�[�e��N���0WԿ�o�ϓ�iosW�wz:�z���Q��Y��Y��3���R�y��K �>?��+#�B����|�J���zj�����6�]@�UD-�P�v�>n໌u�;���W����O���MeFY�г���\�l@���*�!����u?�'�m������
�'�18��>�w��C�Ú\f�M��c}��~5���l���mo,.�}��Y��r�[�K����f\�y���B�G�y���o����C[�����
����|�E�E@
����\}�d<�z��/�
|�x���{T�g����N.��i�B�d�b!���3�i�M��e�$׹4��M�=�'4r���i�!�e������������}Nҿ�1��H6dH��A�T8T*�
�H�GJ%��K�^�
������2	RY����HY��Ryr*УB�Tq"(�*ѯ��T���D�S�Tu�T-�I����z
�jp�E/�N��:�R]ɕW����gKn�l7w��S�G�G�{�o�x���D��J�=é	=���Ż7����,5�w�0@N386C�����&�9^5��;�J-�H~�i	>��j�^+z���O��P�u/�/��w�R+�����=q� �v@G�S�LLgr���<��IR�B��]�<�1���ug���fO|�E���_�P;�ap�K\?��G�������ǁ�\���Ti5��s܇�}8�A�p	�O�?������Ͽ���R� �Kr�Q'�s�?�YO�w���1��IN���0��EQ
�S�9�?�'���0��i�O��do91�1��ٜ�X�Ų�X�b9�s�?��84�Q+����q>�_��:K�ຈ��L����zK�[�w˘Y<����r4/G�
f��+��*�$p�V�{"��r
�kr���Z��u�1	nI��x���c�7�l��Fzmd���f��L�-�ڂ[9�[�L�6�i{�[�G
�w�o:wSo3܇��j?�R镊���:�g&
>��u�:��s�GXK�˟���Qt�����8�;��<O��$�'�|
ON������2�Ltg��k��uo����\�G���|�؋輄���]書竬_×�h�ιȆ�
�o2�[�ݢw� ��q���L�g��<D�#r�=��'�|J~>��S�g�9�^г�o��/��/�
ͯX{]\Fe�l�)�H�X�L��eJ�dJ9�8+eJ{Ȕ�*.-��o�x���2|@6�t�L%7@l�^�@���(��ce�E�T�q>%S��IN-��bυ����!�.�ꎔqeϕ��ʸ�ȸ�xP�!�Fލ��4�I2^	2ެ7%���w�i$��<���_�L+8�;�гu�L�X�-��@��2A<;���@c'8��3�tAC�.3���=P&��p�(ۓ��1�����o���������O��)2�	ye�e0ڇd�eN��d��gF�{u�B��p��o����q�D��>�*3��	�s3������=��6��(���T~G�7�����7��L4���Y�C�ٜ�9��񜋮��z���]�����%�q	���ϖ1�T���e�W�e}�(�=��dr��w���s�oWs�e
\����迎�$�H�}nEc2�pϘ��o�����K�S
}w�o����Z{�/��o?9��w*z�� ��%
އ�a�a/�G�|���<�lO0��!�������r���Q&�<�/P3\�w��D��p����ˆ�
�n��܂�-��?�3u�>w�y��wᘋ��ɀ��u}�є��<��m�󐼇����O�~�p���)>���k�y�g���{ü�,��Ǜ��u���β�<d�-rJ�X�l	�K���l�<ٲN��Xs̖��'[��J���lOY'٪��բe���&ٚ� ]�%R�6��$ʺ˾C|� �ĺ=�m0C֝5�,�w�d=x6�V�\YO�(J��?(�m�,�!��~Sr��������~n S�%�Z�@6m�e�ю��p@~����e��tx�c`d``:�$ɠ�L@��`>(Mx����jAƿݤMk�`�R��AD��ݴ��7�?�Mhb�W�6;I�&�av��k_@��+@���U�o'c�BMH�7g�����<�������d�E	�,p?-QvZ^��S��J��r	/�g��p�}oyw�/��x���G��Y��:w�LƜl�e��>[.�1�[.b�q-��	u�y��זK�輵��mwfy����x�~������b�b�Ї��1BL I���vQ����K^��I��k��&���LŽ���D��0�fb����`0�(JfRMdD��I/��DK1�Z��`*�t�M��Ƭ d.�do<U��ڨ�U�ڴ��Mr�;�g�zpXm�k'�F�}���FUF��]�=j;௲��K��i"���bD�.x�B$�d��y�&��_j����Q�>��º\ՒO���-�9"Z��mW���j��\DI�滎��Sid�IΩ+�Щ�})��dG�»�2']�Z����J�Z��rl�$��;2��V���z���n�M�"�L4�R�+�_�
���e�k=��~^^8����D�9�yW�y�1�E&���ϋ�x�}Wt�ȲuU�b'X��̔ؖ�,O`����ݶ5�-� 0����̏��1�}�̰�����L�s~N�$ݾ�}oW))L��?����nJ]��.uc�ԭ�R��n�4d 9����0����
X	�ư	l
���l	[�ְ
�	���`{�v��`g�v��`w����`o���1����P�	���`8���`8V�L��¡pG��p
��p'��p����p�g��p�
�P��zj4�Fj�-hClX
]p�}p��5�C!D0���·�B�.�K�R�.�+�J�
��k�Z����F�	n�[�V�
n�;�N��{�^���Ax�G�Qx�'�Ix
��g�Yx���Ex	^�W�Ux3��
o���;��.x7������!�0��������	�$|
>
���������"�_�/�W��5�:|�	߂o�w��=�>�~?��O��3�9�~	��_�o���~�?Ÿ����+�
���¿����/��0��b�pX�a�Q\��q�čpc�7��ps��ĭpk�߄��v�=�;�N�3�n�;�{�^�7���c	�XAM��N�~�?��Ax0��p
�qg�P<�#�H<
��c�X<���D<)�:����x��g�x����X����:6��
[��ڸ��`�袇k��C�p�qq-���x^���x^�W�x^���x^�7�xތ��xގw�xލ��xޏ�>���>�O�>���>�/�����f|�߆o�w�;�]�n|�߇����C�a|
?�ŏ����I�~?��������E|��_Ư�W�k�u�~������w�{�}���?Ɵ�O�g�s�������o�
�����?��/�W��������?�_JQ�2���i�
T�a�QZF�i���hcڄ6��hsڂ���hkچ�D��v�=�@;�N�3�B��n�;�A{�^�7�C���S��T!�L��M�~�?@�At0B�h��i�f�P:��#�H:���c�X:����D:�N�S�T:�N�3�L:�Φs�\��ydQ��$E-jS�lZM]r�G}rɣ5�S@!E4G�@���Χ�B��.�K�R��.�+�J����k�Z�����F��n�[�V��n�;�N���{�^����Az��G�Qz��'�Iz���g�Yz����Ez�^�W�����cA�v#(�ot�?��S���tZ~A���y�b:
��n�N/vj������� D���UϝS���۫�|\�QHn��
�v�r��3�o�t��<Ϧj��C��Ҿk5���|����l�I���uw��9�b�a�
G1���0竖��N^�O踍n��X�o��uܾ

s��T��S�M!���ˮ�nS��V\Sh������Kѳ�n���~�mX=�[������ڡ�؍b��ZG��NX���v3��Y�_sT+N�
��_L:��>��WGAh�Ӳ���o�{	N��wG[VCɩ���rs��#_e=�o�N�gy5Y��VS&��u��f���L����D�� T^�n5���iY|��^~�Hˡg<�M��p�\�e|8~}Љgҝ�Z��0��n��A'��DAM�Q��}�,&&��9��#k"�G�8�
�������T?�ሆ%�b`�*ԭ��i��;���4�U�v���#�#�r{���"���g9�r��p���nY��b�)��w�Wy��Fc5���p�@
���~;~=���W���~���o��\��X�l�j�UX�W�;GY�=�W*�{�L��;�b*?!+�,a�^���C�W�~��l_�b���$��C�er�b2�}�N_crߥ�ZL�m�z�H؉z���*�L�d���I�rZ�8�$1%'�r�q�~�͙e΋�ok�o��9l��qB�~�ɽ�b�m3C=�A�&��p�c�'D��˛t�	��p~��l2s6�K)����7��4�R����r�bC����B�e��\܊�dDdE���zG��`$�`�C��!H����Uv��;�ɄV�
�Qy3Cu�V����87�'���F^Z�2���ٺ�8BP#
YJ�O��b��^:��TAΧVg�v�q��~��A����]vx�vg(����PwT��k78�G�������;�����y7�b@q�@�5T�>s�;�'M��I#��I3>+�7�A:p}��=�[|y�-N*��y�.��orJ���qQ�Y�X;�(�C�k�8����>koqD�Wpd5�E=�q�un���k�6�t��$��z�"cÎ��|١(�S	c���J)�0.Geɔq:�-�#�����$�Y=f��
��f��-Y��V�t�y�����XK�h�Q]�ԗ����H�
���e_����`~�(�5�TA��Fֱ<�b���=�.��o�w�š�
��I3љw���f�w3���ł|0˗��8-	��/�Ona�.�%�e�/$��է�����<���0�"/���h܈C����3��e9i�b�į9���;�8�$�"���G�!�H��J�aW�k��dqIf)�H���Ƕ��I�_�({�ڵrv�j(N�2���f-�����i�M����j�&�Pd>Q����ij�hr���&|���`D��C�����	{��nA9���YH��61G&Ύ��m/��%	iź�A�J��c��O��� �wt��C�����ŗ^l�4b�&��ψ8��W�V/��g��|�%�%Y����]%�Ԯ{M��>��ɏ���6�3Y
�����8Tcx��7�V.M�\7r8�G�
6��C����p�WlЋcS�\�Ha/r6��z#��^`����ޑ��5�,�Q�!����������^��ߴ]��&����h�����#���*Z�L�>K�,�G�ҧ��K�����\w>��5�]���-�2�䖠��qRs#?X�b�9�Vq�-ˎJK!	<�=
"��4s�ύ=���q���Wv�����/TK���k���Xe�dI���$9G��M7\�@�&��S��J�5����H��⁚+C%)�R�V��U)&���E}���Uc|��8�L
h�,]M
hR@����d�V�ui��(KQIf���)EU�	)4>&�<и��+RRb\��k�ӵ�J�+	�$���J�+	�$��0���,�� ʂ(����	g�u�!в��1tm�Z&��a�kEX+��V4tV�
!6dZC@��2dȐ���0a
����zh�L@f�ϻ?PUTTPUT��*4US^nHKh���Ą ��EE|Q_T��EE|Q�Ĥ &!��L
b��n�b�܊BLa�)���$EY����U)&����)��K2�!�0��X�Kb	C,a�IIHJ�3bC�`�1�!f0����3bC�`�	_FYeA�!0ʂ��"�� DzC�7DzC�7DzC�7*�0!���!���!���!���!���!���!�� LA��)S,z��.��sK"�!�UAT!�"�!�"�!�"�!�"�!�"�!�"�!�"�!�"�1)��DC"����JU۴41�kƙ"�)қ:�&]�2X�bB
�3�K��o����o����o����o����o����o����o����o����o��f)���Uz���u]�uY�z���RW����zB׃�V�zJ�Ӻ��lROi�)�;�y�4��ҼS�wJ�Ni�)�;�y�4��ҼS�W�Ҵ�ּӚwZ�Nk�i�;�y�5��ּӚwZ�Nk�iͫckI��Ҍ�Ѽ3�WGؒ����;�yg4��Ѽ3�wF��h�Y�;�yg5��ռ��wV�ΊS&5�&�դ��tV��j����	�libs/better-framework/assets/fonts/bs-icons.svg000064400000146647151214002610015660 0ustar00<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by Fontastic.me</metadata>
<defs>
<font id="bs-icons-v10" horiz-adv-x="512">
<font-face font-family="bs-icons-v10" units-per-em="512" ascent="480" descent="-32"/>
<missing-glyph horiz-adv-x="512" />

<glyph glyph-name="facebook" unicode="&#45056;" d="M292 353l74 0-9-81-65 0 0-235-97 0 0 235-49 0 0 81 49 0 0 49c0 35 8 61 24 79 17 18 44 26 81 26l65 0 0-81-40 0c-8 0-14 0-18-2-5-1-8-3-10-6-2-4-3-7-4-10 0-3-1-8-1-14z"/>
<glyph glyph-name="twitter" unicode="&#45057;" d="M481 395c-13-18-28-34-46-47 0-3 0-7 0-12 0-25-3-50-11-74-7-25-18-49-33-71-14-23-32-43-52-61-21-17-45-31-74-41-29-11-60-16-92-16-52 0-99 14-142 42 7-1 14-2 22-2 43 0 81 14 115 40-20 0-38 6-54 18-16 12-27 27-33 46 7-1 13-2 18-2 8 0 16 1 24 4-21 4-39 15-53 31-14 17-21 37-21 59l0 1c13-7 27-11 42-11-13 8-23 19-30 32-8 14-11 29-11 44 0 17 4 33 12 47 23-28 51-51 84-68 33-17 69-27 107-29-2 8-3 15-3 22 0 25 9 47 27 65 18 18 40 27 66 27 26 0 49-10 67-29 21 4 40 11 59 22-7-22-21-39-41-51 18 2 35 7 53 14z"/>
<glyph glyph-name="dribbble" unicode="&#45058;" d="M245 323c-11 18-22 37-34 55-12 19-22 33-29 43-7 10-11 16-12 17-28-13-52-32-71-57-20-25-33-52-40-83 63 0 124 8 186 25m25-68c3 1 5 2 8 2-4 10-9 21-17 35-62-19-131-29-206-29 0 0 0-7 0-7 0-51 17-96 51-134 2 3 4 6 7 11 3 4 10 13 20 25 10 13 21 25 33 36 11 10 27 22 45 33 19 12 39 21 59 28m-138-157c-1 0-1 1-2 1 0 0-2 2-2 2 0 0 4-3 4-3m76 354l0 0m181-44c-39 33-83 50-133 50-16 0-32-2-47-6 28-37 53-76 75-117 47 18 82 41 104 72 0 0 1 1 1 1m-133-388c-65 0-120 24-166 70-46 46-70 101-70 166 0 65 24 120 70 166 46 46 101 70 166 70 65 0 120-24 166-70 46-46 70-101 70-166 0-65-24-120-70-166-46-46-101-70-166-70m35 203c-74-25-126-66-158-124 0 0-1-1-1-1 38-28 79-43 124-43 27 0 53 6 79 17-8 47-23 98-43 152 0 0-1-1-1-1m8 81c4-8 9-18 13-29 1 0 2-2 3-4 1-3 2-4 2-6 23 3 45 4 66 2 22-1 39-3 52-5 13-2 20-3 22-4 0 47-15 89-45 126 0 0-4-5-4-5-3-4-8-8-14-14-6-6-13-12-21-18-8-7-19-14-32-22-13-8-27-15-42-21m31-71c17-50 30-98 39-143 47 32 76 76 86 134-3 2-10 3-20 6-11 2-26 4-45 6-20 2-40 1-60-3"/>
<glyph glyph-name="vimeo" unicode="&#45059;" d="M484 362c-11-63-40-123-87-179-48-57-90-97-126-122-14-9-28-12-41-8-14 3-25 10-34 19-9 9-17 20-22 31-6 11-19 52-40 123-21 70-34 109-38 114-5 4-12 5-19 3-8-3-15-6-23-11 0 0-10-7-10-7 0 0-19 25-19 25 6 7 14 16 24 27 9 11 27 26 51 45 25 20 46 31 64 35 10 2 19 1 27-4 8-4 14-10 18-18 5-7 9-18 12-31 3-12 6-24 8-35 1-11 3-24 6-39 2-14 4-26 6-34 5-18 9-32 11-41 3-9 5-18 9-28 3-9 6-16 9-20 3-3 6-5 9-5 14 0 35 28 65 85 14 26 15 47 3 63-12 17-32 17-57 1 7 43 31 75 71 96 36 19 67 20 93 5 28-16 38-46 30-90"/>
<glyph glyph-name="rss" unicode="&#45060;" d="M165 128c0-15-6-28-16-39-11-11-24-16-39-16-16 0-28 5-39 16-11 11-16 24-16 39 0 15 5 28 16 39 11 11 23 16 39 16 15 0 28-5 39-16 10-11 16-24 16-39z m146-35c0-5-1-10-5-14-3-4-8-6-13-6l-39 0c-5 0-9 2-12 5-4 3-6 7-6 12-4 43-22 81-53 112-31 31-68 48-112 52-4 1-8 3-11 6-4 3-5 8-5 12l0 39c0 5 2 10 6 13 3 4 7 5 12 5l2 0c30-2 59-10 87-23 28-13 52-30 74-52 22-21 39-46 52-74 13-28 20-57 23-87z m146-1c1-5-1-9-5-13-3-4-8-6-13-6l-41 0c-5 0-9 2-13 5-3 3-5 8-5 12-3 41-12 80-29 117-17 37-39 69-66 96-27 27-59 49-96 66-37 17-76 27-117 29-5 0-9 2-12 6-3 3-5 8-5 12l0 41c0 5 2 10 6 13 3 4 7 5 12 5l1 0c50-2 98-13 143-34 46-20 86-48 122-84 35-35 63-76 84-121 20-46 32-94 34-144z"/>
<glyph glyph-name="github" unicode="&#45061;" d="M201 165c0-8-1-16-3-24-3-8-7-15-13-22-6-6-12-9-20-9-8 0-15 3-21 9-6 7-10 14-12 22-3 8-4 16-4 24 0 7 1 15 4 23 2 8 6 15 12 22 6 6 13 9 21 9 8 0 14-3 20-9 6-7 10-14 13-22 2-8 3-16 3-23z m183 0c0-8-1-16-4-24-2-8-6-15-12-22-6-6-13-9-21-9-8 0-14 3-20 9-6 7-10 14-13 22-2 8-3 16-3 24 0 7 1 15 3 23 3 8 7 15 13 22 6 6 12 9 20 9 8 0 15-3 21-9 6-7 10-14 12-22 3-8 4-16 4-23z m46 0c0 22-7 42-20 58-13 16-31 24-53 24-8 0-27-2-56-6-14-2-29-3-45-3-16 0-31 1-45 3-29 4-47 6-56 6-22 0-40-8-53-24-13-16-20-36-20-58 0-17 3-32 9-44 7-13 14-23 24-30 9-7 21-13 34-17 14-4 28-7 40-8 13-2 27-2 43-2l48 0c16 0 30 0 43 2 12 1 26 4 40 8 13 4 25 10 34 17 10 7 17 17 24 30 6 12 9 27 9 44z m64 50c0-40-6-71-18-95-7-14-17-27-30-38-13-10-26-19-40-24-14-6-30-11-49-14-18-3-34-5-49-6-14-1-30-1-47-1-15 0-29 0-41 0-12 1-26 2-42 4-16 2-31 5-44 9-13 3-26 8-39 14-13 6-24 14-34 23-11 10-19 21-25 33-12 24-18 55-18 95 0 45 13 83 39 113-5 16-8 32-8 49 0 22 5 42 15 62 21 0 39-4 54-11 16-8 34-20 54-36 28 7 58 10 89 10 28 0 54-3 80-9 20 16 37 27 53 35 16 7 34 11 54 11 10-20 15-40 15-62 0-17-3-33-8-48 26-31 39-69 39-114z"/>
<glyph glyph-name="vk" unicode="&#45062;" d="M0 353c0 2 0 3 1 4l1 2c2 3 7 5 15 5l73 1c2-1 4-1 6-2 2-1 3-2 4-2l2-1c2-2 5-5 6-9 4-9 8-18 12-27 5-10 9-17 11-22l4-8c6-11 11-20 15-28 5-7 10-14 13-18 4-4 8-8 11-10 4-3 7-4 9-4 3 0 5 1 8 1 0 1 0 1 1 2 1 1 2 2 3 6 2 3 3 7 4 12 1 5 1 13 2 22 1 9 1 20 0 33 0 7-1 14-2 20-1 5-3 10-4 12l-1 3c-5 6-12 10-23 12-2 0-2 2 1 6 3 3 7 6 10 8 10 5 31 7 64 6 15 0 27-1 36-3 4-1 7-2 9-4 2-1 4-3 6-6 1-3 2-6 2-9 1-3 1-7 1-12 0-5 0-10 0-14 0-5 0-11-1-19 0-8 0-16 0-22 0-2 0-6 0-11-1-6-1-10 0-13 0-3 0-7 0-11 1-4 2-8 4-10 1-3 3-5 6-7 1 0 2-1 4-1 2 0 4 1 7 3 3 2 6 5 10 9 4 4 8 10 14 18 6 8 12 18 18 29 11 18 20 38 29 60 0 1 1 3 2 4 1 2 2 3 3 3l1 1 2 1c0 0 1 0 3 0 2 1 4 1 5 0l77 1c7 1 13 1 17-1 5-1 8-2 9-4l1-3c4-11-9-37-40-78-4-6-10-13-17-23-14-18-22-29-24-35-3-7-2-14 4-21 3-4 10-11 21-22l0 0 1 0 0-1 1 0c25-24 42-43 50-59 1-1 2-2 2-4 1-1 1-3 2-7 1-3 1-6 0-9-1-2-3-5-7-7-3-2-9-3-15-3l-69-1c-4-1-9-1-15 1-5 2-10 4-14 6l-5 3c-5 4-11 9-19 17-7 8-13 15-18 21-5 6-10 11-16 15-6 4-11 6-15 4-1 0-1 0-2-1-1 0-3-1-5-3-2-3-4-5-6-8-1-3-3-8-4-14-1-6-2-13-2-21 0-3 0-5-1-7 0-2-1-4-2-5l-1-1c-3-4-8-6-14-6l-31 0c-12-1-25 0-39 4-13 4-25 8-35 14-10 6-19 12-27 18-8 6-15 11-19 15l-7 7c-1 1-4 4-7 8-3 3-9 11-19 24-10 12-19 26-28 40-9 14-20 33-33 56-12 24-24 48-35 73-1 3-1 5-1 7z"/>
<glyph glyph-name="delicious" unicode="&#45063;" d="M37 119l0 274c0 23 8 42 24 58 16 16 35 24 58 24l274 0c23 0 42-8 58-24 16-16 24-35 24-58l0-274c0-23-8-42-24-58-16-16-35-24-58-24l-274 0c-23 0-42 8-58 24-16 16-24 35-24 58z m18 137l201 0 0-201 137 0c18 0 33 6 45 19 13 12 19 27 19 45l0 137-201 0 0 201-137 0c-18 0-33-6-45-19-13-12-19-27-19-45z"/>
<glyph glyph-name="soundcloud" unicode="&#45065;" d="M17 168c0-1-1-2-5-2-2 0-3 1-5 2 0 0-7 36-7 36 0 0 7 37 7 37 2 1 3 2 5 2 4 0 5-1 5-2 0 0 9-37 9-37 0 0-9-36-9-36m53-20c0-2-2-4-7-4-4 0-6 2-6 4 0 0-6 56-6 56 0 0 6 85 6 85 0 2 2 4 6 4 5 0 7-2 7-4 0 0 7-85 7-85 0 0-7-56-7-56m52 2c0-4-3-6-7-6-5 0-7 2-7 4 0 0-6 56-6 56 0 0 6 113 6 113 0 4 2 6 7 6 4 0 7-2 7-6 0 0 6-113 6-113 0 0-6-54-6-54m52 0c0-4-3-6-8-6-6 0-8 2-8 6 0 0-4 54-4 54 0 0 4 114 4 114 0 4 2 6 8 6 5 0 8-2 8-6 0 0 5-114 5-114 0 0-5-54-5-54m52 1c0-5-3-7-9-7-5 0-8 2-9 7 0 0-3 53-3 53 0 0 3 131 3 131 1 5 4 7 9 7 6 0 9-2 9-7 0 0 4-131 4-131 0 0-4-53-4-53m37-7c-5 0-7 3-7 8 0 0 0 202 0 202 0 4 2 6 6 7 12 5 27 8 43 8 30 0 56-10 78-30 23-20 35-44 38-73 8 4 17 5 25 5 18 0 34-6 47-19 13-12 19-27 19-44 0-18-6-33-19-46-13-12-29-19-47-19 0 0-183 1-183 1"/>
<glyph glyph-name="behance" unicode="&#45066;" d="M207 274c19 0 33-6 43-20 10-14 16-27 16-41 0 0 0-20 0-20 0-20-3-36-10-50-7-13-15-23-26-29-10-6-20-11-30-14-10-3-18-5-25-6 0 0-10 0-10 0 0 0-165 0-165 0 0 0 0 331 0 331 0 0 165 0 165 0 26 0 48-8 65-23 17-15 25-36 25-65 0-17-4-31-12-42-8-10-16-16-24-19 0 0-12-2-12-2m-134 93c0 0 0-74 0-74 0 0 87 0 87 0 9 0 15 2 20 8 5 5 7 15 7 31 0 10-1 18-5 24-4 6-8 9-12 10 0 0-5 1-5 1 0 0-92 0-92 0m88-213c25 0 38 14 38 43 0 13-3 24-9 31-5 8-10 12-16 13 0 0-9 1-9 1 0 0-92 0-92 0 0 0 0-88 0-88 0 0 88 0 88 0m239 187c24 0 44-5 61-15 16-10 28-22 34-36 7-14 11-28 14-42 3-14 4-25 3-35 0 0-1-15-1-15 0 0-164 0-164 0 0-19 5-33 14-42 9-10 19-15 28-15 0 0 13-1 13-1 16 0 28 3 37 9 8 6 13 11 14 17 0 0 1 9 1 9 0 0 55 0 55 0 0-28-9-49-27-63-18-15-36-22-54-23 0 0-28-1-28-1-24 0-45 4-62 13-17 8-29 19-37 32-7 12-13 25-17 37-4 12-5 23-5 31 0 0 0 13 0 13 0 3 0 8 0 14 0 6 3 16 7 31 5 14 11 27 19 38 7 11 20 21 37 30 16 9 36 14 58 14m51-99c0 1-1 3-1 5 0 3-1 7-3 13-2 5-4 11-7 15-2 4-7 8-14 12-7 4-15 6-24 6-14 0-26-4-35-13-10-8-16-17-18-26 0 0-3-12-3-12 0 0 105 0 105 0m13 164c0 0 0-40 0-40 0 0-131 0-131 0 0 0 0 40 0 40 0 0 131 0 131 0"/>
<glyph glyph-name="pinterest" unicode="&#45067;" d="M51 308c0 18 3 35 9 53 5 17 14 34 27 51 12 16 26 31 43 44 17 13 37 23 61 30 24 8 50 12 78 12 28 0 54-5 78-15 25-10 45-23 61-39 17-16 30-34 39-55 9-21 14-43 14-65 0-60-15-110-46-150-30-39-70-59-118-59-17 0-32 4-45 11-14 8-24 17-29 27-13-50-20-78-22-83-6-24-20-52-43-84l-21 0c-2 17-2 33-2 47 0 21 1 39 5 54l39 166c-6 13-9 29-9 48 0 22 5 41 17 56 11 15 25 23 41 23 13 0 23-5 30-13 7-9 11-20 11-33 0-9-2-19-4-30-4-13-8-26-12-41-4-11-8-23-11-37-1-4-1-8-1-12 0-11 3-20 10-29 10-11 23-17 39-17 28 0 52 15 70 47 18 31 27 70 27 114 0 35-12 63-34 84-22 22-53 33-93 33-45 0-81-14-108-43-28-28-41-63-41-103 0-23 6-43 20-60 3-3 4-7 4-12 0-1 0-3 0-4-2-5-4-13-6-25-1-3-3-6-6-7-3-2-6-2-9 0-21 8-36 23-47 44-10 21-16 45-16 72z"/>
<glyph glyph-name="vine" unicode="&#45068;" d="M31 435c6-42 13-82 22-119 9-38 18-70 28-97 10-27 21-52 33-75 11-23 22-42 33-57 10-15 21-28 31-40 11-11 20-20 27-26 6-5 13-10 18-13 9-5 18-8 26-8 8 0 16 2 24 7 5 3 12 8 21 16 8 7 18 17 29 29 11 12 23 24 34 38 11 14 22 30 33 47 11 18 21 35 29 52 21 0 42 3 62 7l0 61c-15-3-28-4-38-4-33 0-61 11-82 33-22 22-33 53-33 91 0 18 4 33 10 43 7 10 15 15 26 15 10 0 19-5 25-14 6-9 9-22 9-40 0-16-4-35-10-57 0 0 0-1 1-1 0-1 1-2 2-3 1-2 3-3 4-5 2-1 3-3 6-5 2-2 5-3 8-5 3-1 6-2 10-4 4-1 8-2 12-3 4 0 9 0 14 0 6 0 11 1 17 2 12 26 18 56 18 88 0 39-10 70-29 92-20 21-48 32-84 32-25 0-46-6-64-18-19-11-32-27-42-48-9-20-14-43-14-68 0-38 9-72 25-103 17-30 40-53 69-68-24-48-54-90-88-125-13 16-25 31-35 46-10 15-21 34-32 55-11 21-20 43-28 67-8 23-16 51-23 82-7 32-12 66-17 103z"/>
<glyph glyph-name="steam" unicode="&#45069;" d="M0 113l29-12c5-24 17-43 36-59 20-16 42-24 67-24 27 0 50 10 70 28 20 18 32 41 34 67l135 99c26 0 49 6 71 19 21 12 39 30 51 51 13 22 19 45 19 71 0 25-6 49-19 70-12 22-30 39-51 52-22 12-45 18-71 18-25 0-49-6-70-18-22-13-39-29-51-51-13-21-20-45-20-70l-87-126c-5 1-9 1-11 1-20 0-38-5-54-15l-78 32z m63-26l38-15c8-3 16-5 23-5l24 5c16 7 27 18 33 34 3 8 5 15 5 23 0 8-2 16-5 24-7 16-18 27-34 33l-32 13c5 1 11 2 17 2 21 0 39-8 54-23 15-15 23-33 23-55 0-21-8-39-23-54-15-15-33-23-54-23-15 0-29 4-41 11-12 8-21 18-28 30z m214 266c0 26 9 48 27 66 19 19 41 28 67 28 26 0 48-9 67-28 18-18 28-40 28-66 0-26-10-48-28-67-19-18-41-28-67-28-26 0-48 10-67 28-18 19-27 41-27 67z m19 0c0-21 7-38 22-53 15-15 33-22 54-22 20 0 38 7 53 22 15 15 22 32 22 53 0 21-7 39-22 53-15 15-33 22-53 22-21 0-39-7-54-22-15-14-22-32-22-53z"/>
<glyph glyph-name="flickr" unicode="&#45070;" d="M0 256c0-32 11-59 34-82 23-23 50-34 82-34 32 0 59 11 82 34 23 23 34 50 34 82 0 32-11 59-34 82-23 23-50 34-82 34-32 0-59-11-82-34-23-23-34-50-34-82z m280 0c0-32 11-59 34-82 23-23 50-34 82-34 32 0 59 11 82 34 23 23 34 50 34 82 0 32-11 59-34 82-23 23-50 34-82 34-32 0-59-11-82-34-23-23-34-50-34-82z"/>
<glyph glyph-name="forrst" unicode="&#45072;" d="M43 0l188 0 0 109-52 36 8 12 44-30 0 88 51 0 0-57 42 22 8-13-50-27 0-39 80 40 6-13-86-44 0-84 188 0-214 512z"/>
<glyph glyph-name="mailchimp" unicode="&#45073;" d="M0 82l0 227c8-9 18-17 29-25 69-47 116-79 142-98 11-8 20-15 26-19 7-4 16-9 27-14 12-4 22-7 32-7l0 0c10 0 20 3 32 7 11 5 20 10 27 14 6 4 15 11 26 19 33 23 80 56 142 98 11 8 21 16 29 25l0-227c0-12-4-23-13-32-9-9-20-13-33-13l-420 0c-13 0-24 4-33 13-9 9-13 20-13 32z m0 305c0 15 4 27 12 37 8 10 19 15 34 15l420 0c13 0 23-5 32-14 9-9 14-19 14-32 0-15-5-29-14-43-9-14-21-25-35-35-71-50-116-81-134-93-1-1-6-4-12-9-6-4-11-8-15-11-4-2-9-5-15-9-6-3-11-6-16-8-6-1-10-2-15-2l0 0c-5 0-9 1-15 2-5 2-10 5-16 8-6 4-11 7-15 9-4 3-9 7-15 11-6 5-11 8-12 9-18 12-43 30-75 52-33 23-52 36-59 41-12 8-23 19-33 33-11 14-16 27-16 39z"/>
<glyph glyph-name="tumblr" unicode="&#45075;" d="M296 110c-7 4-14 12-17 20-3 7-3 23-3 49l0 119 108 0 0 82-108 0 0 106-66 0c-3-23-8-43-16-58-8-16-18-29-31-40-13-11-35-19-53-25l0-65 63 0 0-162c0-21 2-37 7-48 4-11 12-22 24-32 11-9 25-17 42-22 16-6 29-8 50-8 18 0 36 1 52 5 16 4 34 10 54 20l0 72c-23-15-47-22-70-22-14 0-25 3-36 9z"/>
<glyph glyph-name="500px" unicode="&#45076;" d="M21 314c-7-36-12-65-12-66l0-1 43 0 2 2c3 4 9 10 13 12 7 4 19 6 29 4 17-3 29-14 33-32 1-3 1-6 1-12 0-7 0-9-2-13-4-16-14-27-28-32-3 0-4-1-12-1-9 0-12 1-18 4-11 5-18 16-20 28l-1 4-24 0c-13 0-24 0-24-1 0 0 0-2 0-5 2-19 9-32 21-45 9-8 19-15 31-19 12-3 23-5 37-5 16 0 26 2 40 8 17 9 30 22 39 39l3 5 0-2c8-18 25-35 44-43 10-4 17-5 32-5 10 0 12 0 17 1 14 3 28 10 41 20 6 5 12 11 24 22 8 9 9 10 10 9 2-3 15-17 20-22 18-16 35-25 54-29 4-1 6-1 16-1 13 0 18 0 27 3 19 7 34 20 44 38 12 22 14 53 6 78-9 28-30 47-59 53-5 1-7 1-17 1-13 0-17 0-26-3-10-4-19-8-28-14-10-8-19-17-34-34l-4-5-7 7c-7 9-21 23-26 27-11 9-23 15-33 19-9 2-14 3-25 3-10 1-17 0-25-2-22-6-41-22-50-43-1-2-1-4-2-5 0 0 0-1 0-1 0 0-1 2-2 4-8 16-25 30-42 35-8 2-13 3-22 3-19 0-31-4-44-15-2-3-3-3-4-3 0 1 2 13 5 28 2 14 4 26 4 27 0 0 23 0 50 0l49 0 0 39-133 0z m236-51c2 0 6-2 10-4 11-5 20-12 35-26l9-9-1-2c-2-2-15-15-19-18-11-9-23-15-33-18-5-1-17-1-23 0-6 2-10 4-14 9-4 3-5 5-7 9-3 7-4 11-4 20 0 5 0 8 1 10 3 12 11 23 19 27 6 3 10 4 17 3 5 0 8 0 10-1z m184 0c12-3 22-13 26-27 1-6 1-18 0-23-4-14-13-23-24-27-5-1-15-1-21 0-15 2-32 13-48 30-3 3-6 6-6 7-1 0 1 2 6 8 19 20 32 29 47 33 4 1 16 1 20-1z"/>
<glyph glyph-name="members" unicode="&#45077;" d="M492 217l-83 40c20 12 33 36 33 63 0 40-28 72-62 72-12 0-23-4-32-11 6-14 9-29 9-46 0-24-7-48-20-67 4-5 9-9 15-12l0 0 53-25c15-8 25-24 25-41l0-70 57 0c7 0 14 7 14 16l0 66c0 7-4 13-9 15z m-330 40c4 3 8 6 12 10-13 19-21 43-21 68 0 17 4 33 10 47-10 6-20 10-31 10-34 0-62-32-62-72 0-28 14-52 34-64l-84-39c-5-2-9-8-9-15l0-66c0-9 7-16 14-16l55 0 0 70c0 17 10 34 26 41z m232-49l-72 34-31 15c14 8 25 21 32 37 5 12 9 26 9 41 0 9-2 17-4 24-9 38-38 65-73 65-34 0-63-26-73-63-2-8-3-17-3-26 0-16 3-31 10-44 7-14 18-27 31-35l-29-13-75-35c-6-3-10-10-10-18l0-82c0-11 7-20 17-20l264 0c10 0 18 9 18 20l0 82c0 8-5 15-11 18z"/>
<glyph glyph-name="comments" unicode="&#45078;" d="M402 293c0-27-9-51-27-74-17-22-42-40-73-53-31-13-64-20-101-20-16 0-33 2-50 5-24-17-50-29-80-37-6-1-15-3-24-4l-1 0c-2 0-4 0-6 2-2 2-3 4-3 6 0 1 0 1 0 2 0 1 0 1 0 2 0 0 0 1 0 1l1 2c0 0 0 0 1 1 1 1 1 2 1 2 0 0 1 0 1 1 1 1 2 2 2 2 1 1 3 3 6 7 4 3 6 6 8 8 1 2 3 5 6 8 3 4 5 8 7 11 2 4 4 8 6 13-24 14-42 31-56 51-13 20-20 41-20 64 0 26 9 51 27 73 18 22 42 40 73 53 31 13 65 20 101 20 37 0 70-7 101-20 31-13 56-31 73-53 18-22 27-47 27-73z m110-74c0-22-7-44-20-64-14-20-32-36-56-50 2-5 4-9 6-13 2-4 4-7 7-11 3-3 5-6 6-8 2-2 4-5 8-8 3-4 5-6 6-8 1 0 1 0 2-1 0-1 1-1 1-1 0-1 1-1 1-2 0 0 1-1 1-1l1-2c0 0 0 0 0-1 1-2 1-2 0-2 0 0 0-1 0-2 0-3-2-5-4-6-1-2-4-3-6-2-9 1-18 2-24 4-30 8-56 20-80 37-17-3-34-5-50-5-52 0-97 13-135 38 11-1 19-1 25-1 31 0 60 4 88 13 29 8 54 20 76 36 24 18 42 38 55 61 12 23 19 47 19 73 0 14-2 29-7 43 25-14 44-30 59-51 14-20 21-42 21-66z"/>
<glyph glyph-name="posts" unicode="&#45079;" d="M366 119l0 18c0 3-1 5-3 7-2 1-4 2-6 2l-202 0c-2 0-4-1-6-2-2-2-3-4-3-7l0-18c0-3 1-5 3-7 2-1 4-2 6-2l202 0c2 0 4 1 6 2 2 2 3 4 3 7z m0 73l0 18c0 3-1 5-3 7-2 2-4 2-6 2l-202 0c-2 0-4 0-6-2-2-2-3-4-3-7l0-18c0-3 1-5 3-7 2-1 4-2 6-2l202 0c2 0 4 1 6 2 2 2 3 4 3 7z m73 101l0-229c0-8-3-14-8-19-5-6-12-8-20-8l-310 0c-8 0-15 2-20 8-5 5-8 11-8 19l0 384c0 8 3 14 8 19 5 6 12 8 20 8l155 0 0-155c0-8 3-14 8-19 5-6 12-8 19-8z m-1 36l-145 0 0 146c15-3 28-9 37-19l89-89c10-10 16-22 19-38z"/>
<glyph glyph-name="instagram" unicode="&#45080;" d="M359 512l-206 0c-85 0-153-68-153-153l0-206c0-85 68-153 153-153l206 0c85 0 153 68 153 153l0 206c0 85-68 153-153 153z m101-359c0-56-45-101-101-101l-206 0c-56 0-101 45-101 101l0 206c0 56 45 101 101 101l206 0c56 0 101-45 101-101z m-204 235c-73 0-132-59-132-132 0-73 59-132 132-132 73 0 132 59 132 132 0 73-59 132-132 132z m0-213c-45 0-81 36-81 81 0 45 36 81 81 81 45 0 81-36 81-81 0-45-36-81-81-81z m164 212c0-17-14-31-31-31-18 0-32 14-32 31 0 18 14 32 32 32 17 0 31-14 31-32z"/>
<glyph glyph-name="whatsapp" unicode="&#45081;" d="M512 263c0-138-113-250-251-250-44 0-86 11-122 31l-139-44 45 134c-23 37-36 81-36 129 0 137 113 249 252 249 138 0 251-112 251-249z m-251 209c-117 0-212-94-212-209 0-46 15-89 41-123l-27-78 81 26c34-22 74-35 117-35 116 0 211 94 211 210 0 115-95 209-211 209z m127-267c-2 3-6 4-12 7-6 3-37 18-42 20-6 2-10 3-14-3-4-6-16-20-20-24-3-4-7-4-13-1-6 3-26 9-50 30-18 16-30 36-34 42-3 6 0 10 3 13 3 2 6 7 9 10 3 4 4 7 6 11 2 4 1 7 0 10-2 3-14 33-19 46-5 12-11 10-14 10-4 0-8 0-12 0-4 0-11-1-16-7-6-6-22-21-22-51 0-30 22-59 25-63 3-4 43-68 105-93 63-24 63-16 74-15 12 1 37 15 42 29 5 14 5 27 4 29z"/>
<glyph glyph-name="line" unicode="&#45082;" d="M511 313l0 0 0 1c0 0 0 0 0 0 0 0 0 0 0 0l-1 5c0 1 0 2 0 4l0 1-1 0c-6 35-23 69-50 98-26 28-61 51-99 65-33 12-68 18-104 18-49 0-96-11-137-33-79-42-125-119-118-196 3-40 19-78 45-109 24-31 58-55 96-71 23-9 46-14 71-19l3 0c7-2 8-4 9-4 1-2 0-4 0-6 0-1-1-3-1-4-3-11-5-22-3-34 2-14 11-22 24-22 0 0 0 0 0 0 14 0 30 9 40 15l1 1c25 15 49 31 67 44 38 28 82 59 115 100 33 42 49 94 43 146z m-352-78l-44 0c-6 0-12 5-12 12l0 93c0 6 6 12 12 12 7 0 12-6 12-12l0-81 32 0c7 0 13-5 13-12 0-7-6-12-13-12z m47 12c0-6-6-12-13-12-6 0-12 6-12 12l0 93c0 7 6 12 12 12 7 0 13-5 13-12z m109 0c0-5-4-10-9-11-1-1-2-1-3-1-4 0-8 2-10 5l-44 60 0-53c0-6-5-12-12-12-6 0-12 6-12 12l0 90c0 5 4 10 9 12 5 1 10 0 13-5l44-60 0 56c0 7 5 12 12 12 6 0 12-5 12-12z m88-10l-60 0c-7 0-12 5-12 12l0 93c0 6 5 12 12 12l58 0c7 0 12-6 12-12 0-7-5-12-12-12l-46 0 0-22 37 0c7 0 12-6 12-13 0-6-5-12-12-12l-37 0 0-22 48 0c7 0 12-5 12-12 0-7-5-12-12-12z"/>
<glyph glyph-name="blackberry" unicode="&#45083;" d="M118 450l-71 0-21-97 75 0c58 0 75 29 75 55 1 18-11 42-58 42z m125-291l-73 0-20-97 75 0c58 0 75 29 75 55 0 18-10 42-57 42z m-150 150l-73 0-20-97 75 0c58 0 75 29 75 55 0 18-11 42-57 42z m335-97l-72 0-21-88 75 0c59 0 76 24 76 50 0 18-11 38-58 38z m27 150l-73 0-20-88 75 0c58 0 75 24 75 50 0 19-11 38-57 38z m-185-53l-72 0-21-97 75 0c59 0 76 29 76 55 0 18-11 42-58 42z m27 141l-73 0-20-97 75 0c58 0 75 29 75 55 0 18-11 42-57 42z"/>
<glyph glyph-name="viber" unicode="&#45084;" d="M492 388l0 0c-12 49-65 100-115 111l0 0c-80 15-161 15-241 0l0 0c-49-11-103-62-115-111l0 0c-15-67-15-136 0-203l0 0c11-46 61-96 109-109l0-54c0-20 23-29 37-15l54 57c12-1 24-1 36-1 40 0 80 3 120 11l0 0c50 11 103 62 115 111l0 0c15 67 15 136 0 203z m-43-193c-8-31-48-71-81-78-42-8-85-11-128-10-1 0-10 0-12-1-6-6-24-25-24-25l-42-43c-3-4-9-1-9 3l3 73c0 2-10 3-11 3-32 7-73 47-81 78-13 61-13 122 0 183 8 31 49 71 81 78 74 14 149 14 223 0 33-7 73-47 81-78 14-61 14-122 0-183z m-122-41c-5 1-10 2-14 4-46 19-88 44-121 81-19 21-34 45-46 71-6 12-11 25-16 37-5 11 2 23 9 32 7 8 16 14 25 18 7 4 15 2 20-4 12-14 22-28 31-44 5-9 4-21-6-28-2-1-4-3-7-5-1-1-3-3-5-5-2-4-2-9-1-13 12-33 32-58 65-72 6-2 11-4 17-4 10 1 13 13 20 18 7 6 16 6 24 1 7-4 15-9 22-15 7-5 14-10 20-15 7-6 9-13 5-21-6-13-16-25-29-32-4-2-9-3-13-4-5 1 4 1 0 0z m-70 259c59-2 109-41 119-100 2-10 2-21 3-31 1-4-2-8-6-8-5 0-7 4-8 8 0 8-1 17-2 25-6 45-42 82-86 90-7 1-13 1-20 2-4 0-10 1-11 6-1 4 3 8 7 8 1 0 3 0 4 0 59-2-1 0 0 0z m90-118c0 0 0-2 0-4-2-6-11-6-13 0 0 1-1 3-1 5 0 13-2 26-9 37-6 11-16 20-28 26-7 4-15 6-23 7-3 1-6 1-10 2-4 0-6 3-6 7 0 4 3 6 7 6 14-1 27-4 39-10 25-13 39-34 43-62 0-1 1-2 1-3 0-3 0-6 0-11 0 0 0 5 0 0z m-37 2c-5 0-7 3-8 7 0 3 0 7-1 10-2 6-5 11-10 15-3 2-5 3-8 4-4 1-8 1-11 2-4 1-7 4-6 8 1 3 4 6 8 5 23-1 39-13 42-40 0-2 0-4 0-6-1-3-3-5-6-5-5 0 3 0 0 0z"/>
<glyph glyph-name="skype" unicode="&#45085;" d="M465 221c2 10 3 22 3 33 0 118-96 214-214 214-11 0-22-1-33-3-20 12-43 19-68 19-71 0-129-57-129-129 0-25 7-48 19-68-2-11-2-22-2-33 0-118 95-214 213-214 12 0 23 1 34 3 19-12 43-19 68-19 71 0 129 57 129 129 0 25-7 48-20 68z m-109-64c-9-13-23-23-40-31-17-7-38-11-62-11-28 0-52 5-70 15-13 7-24 17-32 29-9 12-13 24-13 36 0 6 3 12 8 17 5 5 12 7 19 7 7 0 12-2 16-5 5-4 9-10 12-17 3-8 7-15 11-21 4-5 10-10 18-14 7-3 17-5 30-5 17 0 31 4 41 11 11 7 16 16 16 27 0 9-3 15-8 21-6 5-13 9-23 12-9 3-21 6-36 9-21 5-38 10-52 16-14 6-26 15-34 25-8 11-12 24-12 39 0 15 4 28 13 40 9 11 21 20 38 26 16 7 35 10 58 10 17 0 33-2 46-6 13-5 23-10 32-17 9-7 15-14 19-21 4-8 6-15 6-22 0-7-3-13-8-18-5-6-11-8-19-8-7 0-12 1-16 5-3 3-7 8-11 15-5 10-11 18-19 23-7 6-18 8-34 8-15 0-27-3-36-9-9-6-13-13-13-21 0-5 1-9 4-13 3-4 7-7 13-10 5-3 11-5 16-6 6-2 15-4 28-7 16-4 31-8 44-12 13-4 24-9 34-15 9-7 16-14 22-24 5-9 7-21 7-34 0-17-4-31-13-44z"/>
<glyph glyph-name="gplus" unicode="&#45086;" d="M500 289l-32 0 0 33c0 6-6 12-13 12l-43 0c-7 0-12-6-12-12l0-33-32 0c-7 0-13-5-13-12l0-43c0-7 6-12 13-12l32 0 0-32c0-7 5-13 12-13l43 0c7 0 13 6 13 13l0 32 32 0c7 0 12 5 12 12l0 43c0 7-5 12-12 12z m-334 54c14 0 29-4 41-12l14-9c4-4 11-3 15 1l40 40c3 3 4 6 4 10 0 3-2 7-5 9l-24 16c0 0-1 1-1 1l-23 11c0 0-1 0-1 0-19 8-40 12-61 12-44 0-85-17-116-47-31-31-49-73-49-118 0-45 17-87 48-118 31-31 74-49 120-49 45 0 87 17 115 48 23 24 37 56 41 93 0 0 0 1 0 1l0 33c0 1 0 1 0 2l-2 11c-1 6-6 11-12 11l-141 0c-6 0-12-6-12-12l0-49c0-7 6-12 12-12l72 0c-3-8-8-15-15-22-14-16-36-25-58-25-24 0-46 10-62 25-32 34-32 92 1 124 15 16 37 25 59 25z"/>
<glyph glyph-name="telegram" unicode="&#45087;" d="M478 470l-467-182c-15-6-14-28 1-33l119-35 44-140c5-15 23-19 34-8l62 62 120-88c15-11 36-3 40 15l79 381c4 19-14 35-32 28z m-59-85l-217-192c-2-2-3-4-3-7l-9-75c0-2-3-2-4 0l-35 111c-1 5 1 10 5 13l257 159c6 4 12-4 6-9z"/>
<glyph glyph-name="apple" unicode="&#45088;" d="M453 165c-8-24-19-48-35-72-25-37-49-56-74-56-9 0-22 3-40 10-16 6-30 9-43 9-11 0-25-3-40-10-16-6-28-9-38-9-29 0-58 24-86 74-28 49-42 97-42 143 0 44 11 79 32 107 21 28 49 41 81 41 14 0 31-3 51-8 20-6 33-9 39-9 9 0 22 3 41 10 20 6 36 10 50 10 22 0 43-7 60-19 10-7 20-16 30-29-15-12-26-24-32-33-13-18-19-38-19-59 0-24 7-45 20-64 13-19 28-31 45-36z m-108 335c0-12-2-25-8-39-6-14-14-27-26-39-11-11-21-17-31-21-7-2-17-4-30-5 1 29 8 53 22 74 14 20 38 34 72 42 0-1 0-2 0-3 1-2 1-3 1-3 0-1 0-2 0-3 0-1 0-2 0-3z"/>
<glyph glyph-name="android" unicode="&#45089;" d="M196 374c3 0 5 1 8 3 2 2 3 5 3 8 0 3-1 6-3 8-3 2-5 3-8 3-3 0-6-1-8-3-2-2-3-5-3-8 0-3 1-6 3-8 2-2 5-3 8-3z m120 0c3 0 6 1 8 3 2 2 3 5 3 8 0 3-1 6-3 8-2 2-5 3-8 3-3 0-5-1-8-3-2-2-3-5-3-8 0-3 1-6 3-8 3-2 5-3 8-3z m-232-53c8 0 15-2 21-8 6-6 8-13 8-21l0-123c0-8-2-15-8-20-6-6-13-9-21-9-8 0-15 3-21 9-5 5-8 12-8 20l0 123c0 8 3 15 8 21 6 6 13 8 21 8z m303-5l0-190c0-9-3-16-9-23-6-6-13-9-22-9l-21 0 0-65c0-8-3-15-9-20-6-6-13-9-21-9-8 0-15 3-21 9-5 5-8 12-8 20l0 65-40 0 0-65c0-8-3-15-8-20-6-6-13-9-21-9-8 0-15 3-21 9-5 5-8 12-8 20l-1 65-21 0c-8 0-16 3-22 9-6 7-9 14-9 23l0 190z m-66 116c20-11 37-25 49-44 12-19 18-39 18-62l-264 0c0 23 6 43 18 62 12 19 29 33 49 44l-20 37c-1 3-1 5 1 6 3 1 5 0 6-2l21-38c18 8 37 12 57 12 20 0 39-4 57-12l21 38c1 2 3 3 6 2 2-1 2-3 1-6z m136-140l0-123c0-8-3-15-8-20-6-6-13-9-21-9-8 0-15 3-21 9-6 5-8 12-8 20l0 123c0 8 2 15 8 21 6 6 13 8 21 8 8 0 15-2 21-8 5-6 8-13 8-21z"/>
<glyph glyph-name="fire-1" unicode="&#45090;" d="M181 1c5-3 10 3 7 8-17 25-32 69-7 125 41 93 67 142 67 142 0 0 13-57 50-107 35-48 55-109 24-160-3-4 2-10 7-7 38 19 82 59 87 138 1 24-1 57-15 100-17 54-39 79-51 90-4 3-9 0-9-5 4-58-18-73-31-40-5 14-8 37-8 65 0 46-13 94-43 133-8 10-17 20-27 28-4 3-9 0-9-5 2-32 0-122-79-230-72-100-44-177-34-198 19-40 45-64 71-77z"/>
<glyph glyph-name="fire-2" unicode="&#45091;" d="M159 0c-34 71-16 111 10 150 29 42 36 83 36 83 0 0 23-29 14-75 40 45 47 115 41 142 91-63 129-199 77-300 277 156 69 390 33 416 12-26 14-71-10-92-41 156-143 188-143 188 12-81-44-169-98-235-2 33-4 55-21 86-3-59-48-106-60-165-16-79 12-137 121-198z"/>
<glyph glyph-name="publisher" unicode="&#45092;" d="M249 306c57 0 103 46 103 103 0 57-46 103-103 103-56 0-102-46-102-103 0-57 46-103 102-103z m118-25l121 52 0-160c0-49-36-103-81-122l-120-51 0 160c0 48 36 103 80 121z m-142-121c0 48-36 103-80 121l-121 52 0-160c0-49 36-103 81-122l120-51z"/>
<glyph glyph-name="betterstudio" unicode="&#45093;" d="M340 506l0-168-167 0 0-167-166 0 0-168 499 0 0 503z"/>
<glyph glyph-name="fire-3" unicode="&#45094;" d="M443 227c-21 29-31 52-34 89-2 28 10 60 10 60-15-10-15-9-24-17-50-41-63-82-65-87 0-1 0-1 0-1l0 1c0 0 39 152-69 222-9 6-30 18-30 18 0 0 54-132-42-210-19 77-119 78-119 78 0 0 8-27 9-33 16-84-34-110-44-190 2 9 1 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0-7-62 22-111 68-143 2 22 11 44 24 62 14 21 21 36 23 62 1 19-7 41-7 41 10-7 10-6 17-11 28-23 39-47 43-56 0 0 0 0 0 0-5 21-18 105 49 149 7 4 21 12 21 12 0 0-38-83 46-151-2 28 8 54 28 73 11 11 30 16 30 16 0 0-5-18-6-23-11-58 38-103 27-158-2-10-4-20-8-30l4 0c25 13 48 30 64 54 35 54 19 122-15 173z"/>
<glyph glyph-name="fire-4" unicode="&#45095;" d="M461 365c-20-89-74-98-77-71-14 109 124 107 116 218-22-81-100-67-143-123-43-55-28 34-21 56-75-34-31-119-59-137-7-4-22-2-29 41-7 44 33 100 51 112-22 1-92-43-96-96-5-52-72-116-91-98-19 19 70 56 57 98-25-67-134-14-153-130-27-159 97-207 97-207 15-8 30-13 45-18-4 4-8 9-12 14-24 34 8 51 34 67-7-24 24-58 34-39 10 18 29 86 59 92-17-26 15-108-22-144 21 2 44 5 69 11 73 18 134 107 154 177-117-104-6 88-13 177z m-413-104c-23-32-23-99-22-114-7 24-14 65 6 113 21 49 101 66 101 66-48-24-70-44-85-65z"/>
<glyph glyph-name="disqus" unicode="&#45096;" d="M265 320l-30 0 0-126 30 0c35 0 63 28 63 63 0 34-28 63-63 63z m1 181c-136 0-246-109-246-245 0-36 8-70 22-101l-41-98 107 11c43-35 98-57 158-57 135 0 245 110 245 245 0 136-110 245-245 245z m7-369l-107 0 0 249 107 0c34 0 66-14 88-36 23-23 37-54 37-88 0-69-56-125-125-125z"/>
<glyph glyph-name="better-amp" unicode="&#45097;" d="M404 255l-121 70 61 146c2 4 3 8 3 13 0 15-13 28-28 28-7 0-13-2-18-6-1-1-1-1-2-2l-213-202c-7-6-10-15-9-24 1-9 6-17 14-21l121-70-62-148c-5-12-1-26 10-34 5-3 11-5 16-5 7 0 14 3 20 8l213 202c7 6 10 15 9 24-1 9-6 17-14 21z"/>
<glyph glyph-name="ok-ru" unicode="&#45104;" d="M309 140c27 7 53 17 77 32 18 12 24 35 12 54-11 18-35 23-53 12-54-34-124-34-178 0-18 11-42 6-53-12-12-19-6-42 12-54 24-15 50-25 77-32l-74-73c-15-15-15-40 0-55 7-8 17-11 27-11 10 0 20 3 27 11l73 72 73-72c15-15 39-15 54 0 15 15 15 40 0 55z m-53 295c30 0 55-25 55-55 0-30-25-55-55-55-30 0-55 25-55 55 0 30 25 55 55 55z m0-187c73 0 132 59 132 132 0 73-59 132-132 132-73 0-132-59-132-132 0-73 59-132 132-132z"/>
<glyph glyph-name="linkedin" unicode="&#45074;" d="M136 333l0-283-94 0 0 283z m6 88c0-14-4-26-14-35-10-9-23-14-39-14l0 0c-16 0-29 5-38 14-10 9-14 21-14 35 0 14 4 26 14 35 10 9 23 14 39 14 16 0 28-5 38-14 9-9 14-21 14-35z m333-208l0-163-94 0 0 152c0 20-3 35-11 47-8 11-20 17-36 17-12 0-22-4-30-10-9-7-15-15-19-25-2-5-3-13-3-23l0-158-94 0c1 76 1 138 1 185 0 47 0 76 0 85l-1 13 94 0 0-41 0 0c4 6 7 12 11 16 4 5 10 10 17 15 6 5 15 10 24 13 10 3 21 4 33 4 33 0 59-11 79-32 20-22 29-54 29-95z"/>
<glyph glyph-name="snapchat" unicode="&#45105;" d="M368 288c5 1 9 3 13 4 7 0 14 0 19-3 10-5 11-15 2-22-7-5-16-8-24-11-18-7-21-13-11-30 15-29 37-51 70-59 3 0 9-4 8-6 0-5-2-11-6-13-11-5-22-9-34-12-8-2-11-4-12-11-4-15-7-17-21-14-23 4-43 0-62-14-40-28-69-28-108 1-19 14-39 17-61 13-16-3-18-1-22 14-1 6-4 9-11 11-11 2-23 6-33 11-4 2-8 8-8 13-1 2 6 7 11 8 35 10 57 34 71 66 4 8 1 13-5 17-6 3-12 5-18 7-4 2-8 4-12 6-7 4-13 9-8 19 3 8 14 12 23 9 4-2 9-4 14-5 7-1 10 1 10 9 0 18-1 36 0 54 3 39 26 64 60 78 50 19 109 4 136-44 10-17 11-35 12-54-1-12-1-23-2-35-1-7 3-9 9-7z"/>
<glyph glyph-name="comments-1" unicode="&#45106;" d="M475 384l-36 0 0-219-293 0 0-37c0-14 23-37 37-37l219 0 110-73 0 329c0 15-22 37-37 37z m-73-146l0 219c0 9-28 37-36 37l-340 0c-12 0-26-28-26-37l0-329 110 73 256 0c9 0 36 27 36 37z"/>
<glyph glyph-name="comments-2" unicode="&#45107;" d="M512 256c0-33-11-64-34-92-23-28-54-50-93-66-40-17-83-25-129-25-13 0-27 1-41 2-38-33-82-56-132-69-9-2-20-4-32-6-4 0-7 0-9 3-3 2-4 4-5 8l0 0c-1 1-1 2 0 4 0 1 0 2 0 2 0 1 1 2 2 3l1 3 2 2 3 3c1 1 4 5 8 10 5 5 8 8 10 10 2 3 5 6 9 12 4 5 7 10 9 14 3 5 5 10 8 17 3 7 5 14 8 22-30 17-54 38-71 63-17 25-26 51-26 80 0 25 7 48 20 71 14 23 32 42 55 58 23 17 50 30 82 39 31 10 64 15 99 15 46 0 89-8 129-25 39-16 70-38 93-66 23-28 34-59 34-92z"/>
<glyph glyph-name="comments-3" unicode="&#45108;" d="M183 256c0 10-4 19-11 26-7 7-16 11-26 11-10 0-18-4-26-11-7-7-10-16-10-26 0-10 3-19 10-26 8-7 16-11 26-11 10 0 19 4 26 11 7 7 11 16 11 26z m110 0c0 10-4 19-11 26-7 7-16 11-26 11-10 0-19-4-26-11-7-7-11-16-11-26 0-10 4-19 11-26 7-7 16-11 26-11 10 0 19 4 26 11 7 7 11 16 11 26z m109 0c0 10-3 19-10 26-8 7-16 11-26 11-10 0-19-4-26-11-7-7-11-16-11-26 0-10 4-19 11-26 7-7 16-11 26-11 10 0 18 4 26 11 7 7 10 16 10 26z m110 0c0-33-11-64-34-92-23-28-54-50-93-66-40-17-83-25-129-25-21 0-41 2-60 5-33-33-75-54-125-65-9-2-18-3-24-4-2 0-5 1-6 2-2 1-4 3-4 5-1 3 1 6 6 11 1 1 3 3 6 6 4 3 6 5 8 6 1 2 3 4 6 8 3 3 6 6 7 9 2 2 4 6 6 10 2 5 4 9 6 14 1 5 2 10 4 16 1 7 2 14 3 21-27 17-49 38-65 62-16 24-24 50-24 77 0 33 11 64 34 92 23 28 54 50 93 66 40 17 83 25 129 25 46 0 89-8 129-25 39-16 70-38 93-66 23-28 34-59 34-92z"/>
<glyph glyph-name="calender" unicode="&#45109;" d="M482 475l-24 0 0-73c0-23-19-42-41-42l-13 0c-23 0-40 19-40 42l0 73-59 0 0-73c0-23-19-42-42-42l-13 0c-22 0-40 19-40 42l0 73-49 0 0-73c0-23-18-42-41-42l-13 0c-22 0-40 19-40 42l0 73-36 0c-17 0-31-16-31-33l0-411c0-8 3-16 9-22 6-6 14-9 22-9l451 0c17 0 30 13 30 31l0 411c0 17-13 33-30 33z m-13-409c0-12-10-22-22-22l-381 0c-13 0-23 10-23 22l0 230c0 13 10 23 23 23l381 0c12 0 22-10 22-23z m-218 313l13 0c6 0 12 3 16 7 5 4 7 10 7 17l0 85c0 13-11 24-23 24l-13 0c-13 0-23-11-23-24l0-85c0-14 10-24 23-24z m153 0l13 0c13 0 23 10 23 24l0 85c0 13-10 24-23 24l-13 0c-12 0-23-11-23-24l0-85c0-13 10-24 23-24z m-296 0l12 0c13 0 23 10 23 24l0 85c0 13-10 24-23 24l-12 0c-13 0-24-11-24-24l0-85c0-13 11-24 24-24z m-16-104l66 0c7 0 12-5 12-12l0-52c0-7-5-12-12-12l-66 0c-7 0-12 5-12 12l0 52c0 7 5 12 12 12z m0-111l66 0c7 0 12-5 12-12l0-52c0-7-5-12-12-12l-66 0c-7 0-12 5-12 12l0 52c0 7 5 12 12 12z m131 111l66 0c7 0 12-5 12-12l0-52c0-7-5-12-12-12l-66 0c-7 0-12 5-12 12l0 52c0 7 5 12 12 12z m0-111l66 0c7 0 12-5 12-12l0-52c0-7-5-12-12-12l-66 0c-7 0-12 5-12 12l0 52c0 7 5 12 12 12z m134 111l66 0c7 0 12-5 12-12l0-52c0-7-5-12-12-12l-66 0c-7 0-12 5-12 12l0 52c0 7 5 12 12 12z m0-111l66 0c7 0 12-5 12-12l0-52c0-7-5-12-12-12l-66 0c-7 0-12 5-12 12l0 52c0 7 5 12 12 12z"/>
<glyph glyph-name="comments-4" unicode="&#45110;" d="M467 24l-89 28c-35-17-96-28-134-28-135 0-244 110-244 244 0 135 109 244 244 244 134 0 244-109 244-244 0-40-10-68-21-84l34-130c3-10 0-20-8-26-4-4-10-6-15-6-4 0-8 1-11 2z"/>
<glyph glyph-name="comments-5" unicode="&#45111;" d="M512 121l0 375c0 7-6 13-13 13l-486 0c-7 0-13-6-13-13l0-375c0-7 6-13 13-13l99 0 1-87c0-5 3-9 7-12 2 0 4-1 6-1 3 0 6 1 8 3l127 97 238 0c7 0 13 6 13 13z m-26 14l-230 0c-3 0-6-1-8-3l-109-84-1 73c0 8-6 14-13 14l-99 0 0 347 460 0z m-328 177c0-22-18-40-40-40-22 0-39 18-39 40 0 22 17 39 39 39 22 0 40-17 40-39z m137 0c0-22-17-40-39-40-22 0-39 18-39 40 0 22 17 39 39 39 22 0 39-17 39-39z m138 0c0-22-17-40-39-40-22 0-40 18-40 40 0 22 18 39 40 39 22 0 39-17 39-39z"/>
<glyph glyph-name="comments-6" unicode="&#45112;" d="M373 465l-331 0c-23 0-42-20-42-43l0-332c0-23 19-43 42-43l470 0c-58 41-90 75-96 102 0 0 0 125 0 273 0 23-19 43-43 43z m-257-291c-14 0-34 8-34 22 0 14 12 22 25 22 11 0 20 10 24 22-27 1-49 22-49 49 0 27 23 49 51 49 28 0 50-22 50-49 0-71-25-115-67-115z m152 0c-14 0-34 8-34 22 0 14 11 22 25 22 11 0 20 10 24 22-27 1-49 22-49 49 0 27 23 49 50 49 28 0 51-22 51-49 0-71-26-115-67-115z"/>
<glyph glyph-name="comments-7" unicode="&#45113;" d="M428 180l71-99c8-6 13-11 13-19 0-11-9-20-19-20l-422 0c-19 1-37 8-52 20-11 15-19 33-19 51l0 286c0 18 8 37 19 51 15 12 33 20 52 20l285 0c39 0 71-32 72-71z m-337 154c-14 0-26-15-26-33 0-18 12-32 26-32l142 0c14 0 26 14 26 32 0 18-12 33-26 33z m246-188c13 0 26 14 26 32 0 18-13 33-26 33l-246 0c-13 0-26-15-26-33 0-18 13-32 26-32z"/>
<glyph glyph-name="quote-1" unicode="&#45120;" d="M512 478c0-16 0-32 0-47 0 0-1 0-1 0 0 0-1 0-1 0 0 0-1 0-1 0 0 0 0 0-1 0 0 0 0 0 0 0 0 0-1 0-1 0 0 0 0 0 0 0 0 0-1 0-1 0 0 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1-1-1-1-2-1 0 0-1 0-1 0 0 0-1 0-1 0 0 0 0 0-1 0 0 0-1 0-2 0 0 0 0 0 0 0-1 0-1 0-2 0 0-1-1 0-1-1 0 0-1 0-1 0-1 0-2 0-3 0 0 0 0 0 0 0-1 0-2 0-2-1-1 0-2 0-2 0-1 0-1 0-2 0-1-1-3-1-4-2-1 0-1 0-1 0-1 0-3 0-4-1-4-1-7-2-11-4 0 0-1 0-1 0-1-1-3-1-4-2-1 0-1-1-2-1-1 0-1 0-2-1 0 0 0 0-1 0 0 0 0-1-1-1 0 0 0 0-1 0 0 0 0 0 0-1-1 0-2-1-3-1-1-1-3-1-4-2-1-1-3-2-5-3 0-1-1-1-2-2-1 0-2-1-3-2-1-1-3-2-4-3-2-1-3-2-4-3-1 0-1-1-1-1-1 0-1 0-1 0 0-1-1-1-1-2 0 0-1 0-1 0 0-1-1-1-2-2 0 0 0 0 0 0-1-1-2-2-2-2 0 0 0 0 0 0-1 0-1-1-1-1 0 0 0 0-1 0 0-1 0-1-1-1 0-1-1-2-1-2-1-1-1-1-1-1-1-1-1-1-1-1 0 0 0 0-1 0 0-1 0-1 0-1 0 0-1 0-1-1 0 0 0 0 0 0 0 0 0 0-1-1 0 0 0 0 0 0 0 0 0 0 0 0-1-1-2-2-2-2 0-1-1-1-1-1 0-1-1-1-2-2 0-1 0-1 0-1-1-1-1-1-2-2-1-2-3-3-4-5-1-1-2-3-3-4 0-1-1-2-1-2-1-1-2-2-2-3-1-1-2-2-2-3-1-1-2-3-3-4-1-2-1-3-2-4 0 0 0-1-1-1 0-1-1-2-1-3 0-1 0-1-1-1 0-1 0-1 0-2-1 0-1-1-1-1 0 0 0-1-1-1 0-1 0-1-1-2 0-1 0-2-1-3 0-1 0-1-1-2-1-4-3-8-4-12-1-2-1-3-2-5 0-1 0-1 0-1-1-2-1-4-2-6 0-1 0-1 0-2 0 0 0 0 0-1-1-1-1-2-1-3 0 0 0-1 0-1 0-1 0-1 0-2 0 0 0 0 0 0-1-1-1-1-1-2 0-1 0-2 0-3 0 0 0 0 0-1 0 0 0-1 0-2 0 0 0 0 0-1 0 0 0 0 0-1 0 0 0 0 0 0 0 0 0-1 0-1 0-1 0-1 0-2-1 0-1 0-1-1 0 0 0-1 0-1 0 0 0-1 1-1 0 0-1-1 0-1 0 0 0 0 0-1 0 0 0 0 0 0 0-1 0-1 0-1 0-1 0-2 0-2 0-1 0-2 0-3 0 0 0-1 0-1 0 0 0-1 0-1 0-1 1-2 1-3 0 0 0 0 0 0 0-1 0-2 0-2 1-2 1-3 1-4 2-5 4-9 6-12 4-6 10-11 17-14 1-1 3-1 5-2 1 0 2 0 3-1 1 0 2 0 3 0 0 0 1 0 1 0 1-1 1-1 2-1 1 0 1 0 2 0 1 0 2 0 3 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 2 0 3 0 0 0 1 0 1 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 1 0 2 0 0 0 0 0 0 0 1-1 1-1 2-1 0 0 0 0 0 0 1 0 2 0 3 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1-1 2-1 0 0 1 0 1 0 1 0 1 0 2 0 0 0 1 0 1 0 0-1 1-1 2-1 2 0 3-1 5-1 1-1 3-1 4-2 0 0 0 0 1 0 0 0 1 0 2-1 1 0 3-1 4-2 1 0 2 0 2-1 0 0 1 0 1 0 0 0 1 0 1-1 1 0 1 0 1 0 1 0 1 0 1-1 1 0 2-1 3-1 2-2 5-3 7-5 1 0 2-1 4-2 0-1 1-1 1-2 1 0 2-1 3-2 0 0 1 0 1-1 0 0 0 0 0 0 1 0 1-1 1-1 0 0 1 0 1 0 0-1 0-1 1-1 0 0 0-1 0-1 1 0 1 0 1-1 0 0 1 0 1-1 0 0 0 0 1 0 0-1 0-1 1-1 0-1 0-1 0-1 1 0 1-1 2-1 0-1 0-1 0-1 1-1 1-1 2-2 0 0 0-1 1-1 1-1 1-2 2-3 2-2 3-4 4-6 1-2 2-3 3-4 0-1 1-2 1-3 0 0 0 0 0 0 1-1 1-1 1-2 0 0 0-1 1-1 0-1 0-1 1-2 0-2 1-3 2-5 0 0 0-1 0-2 1-1 1-2 2-4 0-1 0-2 1-2 0-1 0-2 1-4 0 0 0 0 0-1 0 0 0 0 0-1 1-1 1-3 1-4 0-1 0-1 0-1 1-1 1-2 1-3 0-1 0-1 0-2 0 0 0 0 0 0 0 0 0-1 0-1 0-1 0-2 1-3 0-1 0-2 0-3 0 0 0 0 0-1 0 0 0 0 0 0 0 0 0-1 0-1 0-1 0-1 0-2 0 0 0-1 0-1 0 0 0-1 0-1 0-1 0-1 0-2 0 0 0-1 0-1 0 0 0-1 0-1 0 0 0 0 0 0 0-1 0-1 0-1 0-1 0-1 0-1 0 0 0 0 0-1 0 0 0 0 0 0 0-1 0-1 0-2 0 0 0 0 0-1 0 0 0-1-1-1 0 0 0 0 0-1 0 0 0 0 0-1 0 0 0 0 0 0 0 0 0-1 0-1 0-1 0-2 0-3 0-1 0-1-1-2 0-1 0-3 0-4 0 0 0 0-1-1 0-1 0-2 0-3 0 0 0-1-1-1 0-1 0-2 0-3-1-2-2-5-3-7 0 0 0-1 0-1-1-1-1-2-2-4 0 0-1-1-1-2 0-1 0-1 0-1-1-1-1-2-2-2 0-1 0-1 0-1 0-1 0-1-1-2-1-1-1-2-2-4-1-1-2-3-3-4-1-1-1-2-2-3-1-1-2-2-3-4 0 0-1-1-1-1 0 0 0 0 0 0-1-1-1-2-2-2 0 0 0 0 0 0-1-1-1-2-2-2 0 0 0 0 0 0 0-1 0-1 0-1 0 0-1 0-1 0 0 0 0-1 0-1 0 0 0 0 0 0-1 0-1 0-1-1 0 0 0 0-1 0 0 0 0-1 0-1-1 0-1 0-1 0 0 0 0 0 0-1-1 0-1 0-2-1 0 0 0 0 0 0 0-1-1-1-1-1-1-1-1-1-1-1-1-1-2-2-3-2-1-1-1-1-2-2-2-1-3-2-5-3-1-1-3-2-4-3-1 0-1-1-2-1 0 0 0 0 0 0-1 0-1-1-2-1 0 0 0 0 0 0-1 0-1-1-2-1 0 0 0 0 0 0-1 0-2-1-2-1-1-1-2-1-3-1-2-1-3-2-5-2 0 0 0 0-1-1-1 0-3-1-5-1 0 0-1 0-1-1-2 0-3 0-5-1 0 0-1 0-1 0-1 0-2 0-3 0-1-1-2-1-3-1 0 0 0 0 0 0-1 0-2 0-3 0 0 0 0 0 0 0-1 0-1 0-2 0-1-1-2-1-3-1 0 0 0 0 0 0 0 0-1 0-1 0 0 0 0 0 0 0-1 0-1 0-1 0-1 0-2 0-3 0 0 0 0 0 0 0 0 0-1 0-1 0-1 0-1 0-2 0 0 0-1 0-1 0 0 0-1 0-1 0-1 0-1 0-1 0 0 0 0 0 0 0-1 0-1 0-1 0-1 0-1 0-1 0 0 0-1 0-1 0 0 0-1 0-2 0 0 1 0 1-1 1 0 0-1 0-2 0 0 0 0 0 0 0-1 0-1 0-2 0 0 0 0 0 0 0-1 0-1 0-2 0 0 0 0 0 0 0 0 0-1 0-1 0-1 0-3 1-4 1-1 0-1 0-2 0 0 0-1 0-1 0-1 0-2 1-3 1-1 0-1 0-1 0-1 0-1 0-1 0-1 1-3 1-4 1 0 0-1 0-2 1 0 0 0 0 0 0-1 0-2 0-2 0-2 1-4 1-6 2-1 0-2 1-3 1 0 0-1 0-2 1-1 0-2 1-4 1-1 1-2 1-3 2-1 0-1 0-2 0 0 1-1 1-1 1-1 0-1 1-1 1-1 0-1 0-1 0-1 1-2 1-2 1-1 1-1 1-1 1-1 0-2 1-3 1-2 2-5 4-7 5-2 1-3 3-5 4 0 0 0 0-1 0-1 1-1 2-2 3-1 0-1 0-1 1 0 0 0 0-1 0 0 0 0 0-1 1 0 0 0 0 0 0 0 0 0 0 0 0-1 1-1 1-1 1 0 0 0 0-1 1 0 0 0 0-1 1 0 0-1 1-1 1 0 0-1 1-1 1 0 0 0 0 0 0 0 0 0 1-1 1 0 0 0 0 0 0 0 1-1 1-1 2 0 0-1 0-1 0 0 0 0 1-1 1 0 0 0 0 0 0-1 2-2 3-3 4 0 0 0 0 0 0-1 1-2 3-3 4 0 1-1 1-2 2 0 1 0 1 0 1-1 1-1 1-1 2-1 1-2 2-3 4 0 1-1 2-2 3 0 1-1 2-2 3 0 1 0 1 0 1 0 1 0 1-1 1 0 1 0 1 0 1 0 0 0 1-1 1 0 1 0 1 0 2 0 0 0 0-1 0 0 1-1 2-1 4-1 2-2 4-3 6 0 2-1 3-2 5 0 1 0 1 0 2 0 0 0 1-1 1 0 1 0 2-1 3 0 2-1 4-1 5 0 1-1 2-1 3 0 0 0 1 0 1 0 1-1 2-1 3 0 0 0 0 0 1 0 1-1 2-1 4 0 0 0 0 0 1-1 1-1 3-1 4 0 0 0 1 0 1 0 1 0 1 0 1-1 1-1 3-1 4 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1-1 2 0 0 0 0 0 0 0 0 0 1 0 2 0 0 0 0 0 0 0 1 0 2 0 3 0 0 0 0 0 1 0 0 0 1-1 1 0 0 0 0 0 0 0 1 0 1 0 2 0 0 0 0 0 0 0 1 0 1 0 2 0 0 0 0 0 1 0 0 0 1 0 2 0 1 0 3-1 4 0 2 0 3 0 5 0 0 0 0 0 0 0 0 0 1 0 1 0 2 0 3 0 5 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0 2 0 3 0 0 0 0 0 0 0 1 0 1 0 1 0 2 0 3 0 4 0 1 0 2 0 3 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 1 0 1 0 1 0 1 0 1 0 2 0 3 0 4 0 0 0 1 0 1 0 0 0 0 0 0 1 1 0 2 1 2 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 2 0 2 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 0 1 0 2 0 3 1 5 0 1 0 2 0 3 0 0 0 0 0 0 0 1 0 1 0 2 0 0 0 0 0 0 0 1 0 1 0 2 0 0 0 0 1 1 0 0 0 0 0 1 0 1 0 1 0 2 0 1 0 1 0 2 0 0 0 1 0 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 0 2 0 3 0 1 0 1 1 2 0 0 0 1 0 1 0 1 0 3 0 4 1 0 1 1 1 1 0 1 0 2 0 3 0 1 0 1 0 1 1 1 1 2 1 3 0 0 0 0 0 0 0 1 0 2 1 3 0 0 0 1 0 1 0 2 1 3 1 5 0 0 0 1 0 2 1 1 1 1 1 2 0 1 0 1 0 1 1 1 1 1 1 2 0 0 0 0 0 1 0 0 0 1 0 1 1 1 1 3 2 4 0 1 0 1 0 2 0 0 0 1 1 2 0 2 1 5 2 7 0 1 1 3 1 4 1 1 1 2 1 3 0 0 0 0 0 1 1 0 1 1 1 2 0 1 0 1 1 1 0 1 0 3 1 4 0 0 0 0 0 1 1 1 1 2 2 3 0 1 0 1 0 1 1 2 1 3 2 4 0 1 0 1 0 1 1 2 2 5 3 7 1 3 2 6 4 9 0 1 1 2 1 3 0 0 0 0 1 1 0 0 0 1 0 2 0 0 1 0 1 0 0 1 1 3 1 4 1 1 1 2 2 3 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 1 0 1 0 2 0 0 1 0 1 0 0 0 0 1 0 2 1 0 1 0 1 0 0 1 0 1 1 2 0 0 0 0 0 1 0 0 1 1 1 1 1 2 2 3 3 5 0 0 0 0 0 1 1 2 2 4 4 6 2 4 5 8 7 12 1 1 2 2 2 2 1 2 3 4 4 6 1 1 2 2 3 3 0 1 0 1 0 1 2 2 3 3 4 5 0 0 1 1 1 1 1 1 2 2 2 3 1 1 1 1 2 2 0 0 0 0 0 0 0 1 1 1 1 2 0 0 1 0 1 1 1 0 1 1 2 2 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 2 0 0 0 0 1 0 0 0 0 1 1 1 0 1 0 1 0 1 1 1 2 1 2 2 0 0 1 0 1 0 0 1 1 1 1 2 0 0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 1 0 0 1 0 1 1 0 0 1 0 1 1 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 1 0 0 1 0 1 1 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 1 1 0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 0 0 1 0 0 1 0 1 1 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 2 2 3 2 0 1 0 1 0 1 1 0 1 1 1 1 1 0 1 0 1 0 1 1 2 2 4 3 0 0 0 1 0 1 1 1 3 2 4 3 1 1 2 2 4 3 1 0 2 1 3 2 3 2 5 4 8 5 2 1 3 2 5 3 1 1 3 2 4 3 1 0 1 0 2 0 1 1 2 2 3 2 1 0 1 1 1 1 1 0 1 0 1 0 1 1 1 1 2 1 0 0 0 0 0 0 1 0 1 1 1 1 1 0 1 0 2 0 1 1 2 1 3 2 1 1 3 1 4 2 2 0 3 1 5 2 0 0 1 0 1 0 1 0 1 1 2 1 0 0 1 0 1 0 1 0 1 1 2 1 0 0 0 0 0 0 1 0 1 0 1 0 1 1 1 1 2 1 0 0 1 0 2 1 1 0 3 0 4 1 1 0 2 0 4 1 0 0 0 0 1 0 0 0 1 0 1 0 0 1 1 1 1 1 2 0 3 0 5 1 0 0 1 0 2 0 0 0 0 0 1 0 0 1 1 1 1 1 1 0 1 0 1 0 1 0 2 0 3 0 1 1 1 1 1 1 1 0 1 0 2 0 0 0 1 0 1 0 1 0 2 0 2 0 0 0 1 0 1 0 0 1 1 1 2 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 1 0 2 0 0 0 1 0 2 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 1 0 2 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 2 0z m-283 0c0-16 0-32 0-47 0 0-1 0-1 0 0 0-1 0-1 0 0 0 0 0-1 0 0 0 0 0-1 0 0 0 0 0 0 0 0 0 0 0-1 0 0 0 0 0 0 0 0 0 0 0-1 0 0 0 0 0 0 0-1 0-1 0-2 0 0 0 0 0-1 0 0-1 0 0 0-1-1 0-2 0-2 0-1 0-1 0-1 0 0 0-1 0-1 0 0 0-1 0-1 0-1 0-1 0-2 0 0 0 0 0 0 0-1 0-1 0-2 0 0 0 0 0-1-1 0 0 0 0-1 0-1 0-2 0-3 0-1 0-1 0-2-1 0 0 0 0 0 0-1 0-1 0-2 0 0 0-1 0-1 0-1-1-3-1-4-1-1 0-1 0-1-1-1 0-3 0-4-1-1 0-2 0-3 0-3-1-5-2-8-4-1 0-1 0-2 0-1-1-2-1-4-2-1 0-1-1-2-1-1 0-1-1-2-1 0 0-1 0-1-1-1 0-1 0-1 0 0 0 0 0-1 0 0 0 0-1-1-1 0 0 0 0 0 0-1 0-2-1-2-1-2-1-4-2-5-3-2-1-3-2-5-3 0 0-1 0-1-1-1-1-3-2-4-3-2-1-4-2-5-3-1-1-1-2-2-2 0 0 0 0-1 0 0-1-1-2-2-3 0 0 0 0-1 0 0-1-1-1-2-2 0 0 0 0-1-1 0 0 0 0 0 0 0 0-1-1-2-1 0-1 0-1 0-1 0 0 0 0 0 0 0 0 0 0 0 0-1 0-1-1-1-1 0 0 0 0 0 0 0 0-1 0-1-1 0 0 0 0-1-1 0 0 0 0-1-1 0 0 0 0 0 0 0 0-1 0-1-1 0 0 0 0 0 0-1 0-1-1-1-1 0 0-1-1-1-1 0 0 0 0 0 0-1-1-1-1-1-1 0 0-1-1-1-1-1-1-1-1-2-2 0-1 0-1-1-1 0-1-1-2-2-3 0 0 0 0 0 0-1-1-2-2-2-3-1-1-2-1-2-2-1-1-2-3-3-4-2-3-4-5-5-8-2-2-3-4-4-5-1-2-1-3-2-4 0-1 0-1-1-1 0-1 0-1 0-1 0 0-1-1-1-2 0 0 0 0 0 0 0 0 0 0 0-1 0 0 0 0-1 0 0 0 0-1 0-1 0 0-1-1-1-1 0-1 0-1 0-1 0-1-1-1-1-1 0-1 0-1 0-1-1-1-1-2-1-3-1-1-1-2-2-3 0-1-1-3-1-4-1-1-1-2-1-3-1-1-1-2-2-3 0-1 0-1 0-1 0 0 0-1 0-1-1-2-1-3-2-5 0 0 0-1 0-1-1-2-1-4-1-5-1-1-1-2-1-2 0-1 0-1 0-1 0-1 0-2-1-4 0 0 0 0 0-1 0 0 0-1 0-2 0 0 0 0 0 0 0-1 0-1-1-2 0-1 0-2 0-3 0 0 0 0 0 0 0-1 0-2 0-2 0-1 0-1 0-1 0 0 0-1 0-1 0 0 0-1 0-1 0 0 0 0 0-1 0 0 0-1 0-1 0-1 0-1 0-2 0 0 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0 0 0 0 0-1 0 0 0-1 0-1 0 0 0-1 0-1 0-1 0-2 0-2 0-1 0-2 0-3 0 0 0-1 0-1 1-1 1-2 1-3 0 0 0-1 0-1 0 0 0-1 0-1 1-2 1-3 2-4 1-4 2-7 4-10 0-1 1-2 1-2 1-1 1-2 2-2 0-1 1-1 1-2 0 0 1 0 1-1 0 0 0 0 0 0 0 0 1 0 1-1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1-1 1-1 0 0 0 0 1 0 0-1 1-1 1-2 1 0 2-1 2-1 1-1 2-1 3-2 1-1 2-1 4-2 1-1 3-1 5-2 1 0 2 0 3-1 1 0 2 0 3 0 0 0 0 0 1 0 0-1 1-1 2-1 0 0 1 0 2 0 1 0 2 0 2 0 1 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 2 0 0 0 1 0 1 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0 2 0 0 0 1 0 1 0 0 0 0 0 1 0 0-1 0-1 1-1 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0 2 0 0 0 1 0 1 0 0 0 1 0 1 0 1-1 2-1 3-1 0 0 0 0 0 0 1 0 2 0 3-1 1 0 2 0 2 0 0 0 0 0 1 0 0 0 1 0 1 0 1-1 2-1 4-1 2-1 5-2 8-4 1 0 2-1 3-1 1 0 1-1 2-1 0 0 1 0 1-1 1 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0-1 1 0 1 0 2 0 0-1 1-1 2-1 1-1 2-2 3-3 2-1 4-2 5-3 1-1 1-1 1-1 1-1 2-1 2-2 1 0 1 0 2-1 0 0 0 0 1-1 0 0 0 0 0 0 1-1 1-1 2-2 0 0 0 0 1 0 0 0 0 0 0 0 0-1 0-1 0-1 1 0 1 0 1-1 0 0 1 0 1 0 0-1 0-1 1-1 0 0 0 0 0 0 0 0 0-1 0-1 1 0 1 0 1 0 0 0 0-1 1-1 0 0 0 0 0 0 0-1 0-1 1-1 0 0 0 0 0 0 0-1 0-1 1-1 0-1 0-1 0-1 1-1 2-2 2-2 0 0 0-1 0-1 1 0 1-1 2-1 0-1 1-2 2-3 0-1 1-1 1-2 0 0 1-1 1-1 1-2 2-4 3-5 1-1 1-2 2-4 0 0 0 0 1-1 0 0 0-1 1-2 0 0 0-1 1-2 0-2 1-3 2-5 1-2 2-5 2-7 1-1 1-2 1-3 0 0 0-1 0-1 1-1 1-2 1-3 0 0 0 0 0 0 1-2 1-3 1-5 0 0 0 0 0-1 1-1 1-2 1-3 0 0 0 0 0-1 0 0 0 0 0 0 0-1 0-1 0-2 0-1 0-1 1-2 0-1 0-2 0-3 0-1 0-1 0-1 0 0 0-1 0-1 0 0 0 0 0 0 0-1 0-2 0-2 0 0 0 0 0-1 0 0 0 0 0 0 0-1 0-1 0-1 0 0 0-1 0-1 0 0 0-1 0-1 0 0 0-1 0-1 0 0 0-1 0-1 0 0 0 0 0-1 0 0 0 0 0 0 0-1 0-1 0-2 0 0 0 0 0 0 0-1 0-1 0-2 0 0 0 0 0 0 0-1 0-1 0-2 0 0 0 0 0 0-1-1-1-1-1-2 0 0 0 0 0 0 0 0 0-1 0-1 0-1 0-2 0-2 0-1 0-1 0-1 0-1 0-1 0-2-1 0-1-1-1-1 0-1 0-2 0-3 0-1 0-1-1-1 0-1 0-2 0-3 0 0 0-1 0-1-1-1-1-2-1-3-1-2-2-5-3-7 0-1 0-2-1-2-1-3-2-5-3-7 0-1-1-2-1-3 0 0 0 0 0 0-1-1-1-2-2-3 0-1-1-2-2-3-1-2-3-4-4-6-1-2-2-3-3-4-1-1-1-1-1-2 0 0-1 0-1 0 0 0-1-1-1-2 0 0 0 0-1 0 0 0-1-1-1-1 0-1 0-1 0-1-1 0-1 0-1 0 0-1 0-1-1-1 0-1 0-1-1-1 0 0 0 0 0-1 0 0 0 0-1 0 0 0 0 0 0 0 0 0 0-1 0-1 0 0 0 0 0 0-1 0-1-1-2-1 0 0 0 0 0 0-1-1-1-1-2-2 0 0 0 0 0 0-1-1-2-2-3-2 0-1-1-1-2-2-2-1-3-2-5-4-2 0-3-1-4-2-1-1-2-1-2-1-1 0-1-1-2-1 0 0 0 0 0 0-1 0-1-1-1-1-1 0-1 0-1 0-2-1-3-2-5-2-1-1-3-1-4-2 0 0-1 0-1 0-2-1-3-1-5-2-1 0-1 0-2 0-1-1-3-1-4-2-1 0-2 0-2 0-1 0-2 0-3 0-1-1-2-1-3-1 0 0 0 0 0 0-1 0-2 0-3 0 0 0 0 0-1 0 0 0 0 0-1 0-1-1-2-1-3-1 0 0 0 0 0 0 0 0-1 0-1 0 0 0 0 0 0 0-1 0-1 0-1 0-1 0-2 0-2 0-1 0-1 0-1 0 0 0-1 0-1 0-1 0-1 0-2 0 0 0-1 0-1 0 0 0-1 0-1 0 0 0-1 0-1 0 0 0 0 0 0 0-1 0-1 0-1 0-1 0-1 0-1 0 0 0-1 0-1 0 0 0-1 0-2 0 0 1 0 1 0 1-1 0-2 0-2 0-1 0-1 0-1 0 0 0-1 0-2 0 0 0 0 0 0 0-1 0-1 0-1 0-1 0-1 0-1 0 0 0-1 0-1 0-1 0-3 1-4 1-1 0-1 0-2 0 0 0 0 0-1 0-1 0-2 1-3 1-1 0-1 0-1 0-1 0-1 0-1 0-1 1-3 1-4 1 0 0-1 0-2 1 0 0 0 0 0 0-1 0-2 0-2 0-2 1-4 1-6 2-1 0-2 1-3 1 0 0-1 0-2 1-1 0-2 1-4 1-1 1-2 1-4 2 0 0-1 0-1 1-1 0-1 0-2 0 0 1 0 1-1 1 0 0 0 0-1 1-1 0-1 0-2 1 0 0-1 0-1 0-1 1-1 1-2 2-3 1-5 3-8 5-1 1-3 2-4 3 0 0-1 1-1 1-1 0-2 1-3 2 0 0 0 1-1 1 0 0 0 0 0 0 0 0 0 1-1 1 0 0 0 0 0 0 0 0-1 1-1 1 0 0 0 0 0 0 0 0 0 0-1 1 0 0 0 1-1 1 0 0-1 1-1 1 0 1 0 1-1 1 0 0 0 0 0 0 0 0 0 0 0 0-1 1-1 1-1 1 0 1 0 1-1 1 0 0-1 1-1 1 0 1 0 1 0 1-1 0-1 1-1 1-1 0-1 1-1 1-1 1-2 2-3 3-2 3-4 6-6 9-1 1-2 3-3 4 0 1 0 2-1 3 0 0 0 0 0 0-1 1-1 2-2 3 0 0 0 1 0 1 0 0-1 1-1 1 0 0 0 1 0 1 0 0-1 1-1 1 0 0 0 1 0 1 0 0-1 1-1 1 0 1-1 2-1 3-1 2-2 4-3 7 0 1-1 3-2 4 0 1 0 1 0 2 0 0 0 1-1 1 0 1 0 2 0 3-1 2-2 4-2 5 0 1-1 2-1 3 0 0 0 1 0 1 0 1-1 2-1 3 0 0 0 1 0 1 0 1-1 2-1 4 0 0 0 0 0 1-1 1-1 3-1 4 0 1 0 1 0 1 0 1 0 1 0 1-1 2-1 3-1 4 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 1 0 2 0 0-1 0-1 0 0 1 0 1 0 2 0 0 0 0 0 0 0 1 0 2 0 3 0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 1 0 1-1 0-1 1-1 1 0 0 0 0 0 1 0 0 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 2 0 2 0 3 0 4-1 2-1 3-1 5 0 0 0 0 0 0 0 1 0 1 0 1 0 2 0 3 0 5 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 2 0 3 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 3 0 4 0 0 0 1 0 1 0 1 0 1 0 2 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 1 0 1 0 1 0 3 0 4 1 1 1 2 1 4 0 0 0 0 0 0 0 1 0 1 0 2 0 0 0 0 0 0 0 1 0 2 0 2 0 0 0 0 0 0 0 1 0 1 0 2 0 0 0 0 0 0 0 2 1 4 1 5 0 1 0 2 0 3 0 0 0 0 0 0 0 1 0 1 0 2 0 0 0 0 0 0 0 1 0 1 0 2 1 0 1 0 1 1 0 0 0 0 0 1 0 1 0 1 0 2 0 1 0 1 0 2 0 0 0 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 2 0 3 0 1 0 1 1 2 0 0 0 1 0 1 0 1 0 3 0 4 1 0 1 0 1 1 0 1 0 2 0 3 0 0 0 1 0 1 1 1 1 2 1 3 0 0 0 0 0 0 0 1 0 2 1 2 0 1 0 2 0 2 0 2 1 3 1 5 0 1 0 1 1 2 0 0 0 1 0 2 0 0 0 1 0 1 1 1 1 1 1 2 0 0 0 1 0 1 0 0 0 1 1 2 0 1 1 3 1 5 0 0 0 0 0 1 1 1 1 2 1 2 1 3 1 5 2 7 1 1 1 3 1 4 1 0 1 1 1 2 0 0 0 0 0 0 1 1 1 2 1 3 0 0 0 1 1 1 0 1 0 2 1 3 0 0 0 1 0 1 1 1 1 3 1 4 1 0 1 1 1 1 0 1 1 3 1 4 1 2 2 5 3 7 2 3 3 6 4 9 1 2 2 4 4 7 0 1 0 1 1 2 0 0 0 1 0 1 0 0 1 1 1 2 0 0 1 1 1 2 0 1 1 1 1 1 0 1 1 3 2 4 0 0 0 0 0 0 0 1 1 1 1 2 0 1 1 1 1 2 1 1 2 3 2 4 1 1 1 1 1 1 2 3 3 6 5 8 1 2 2 4 3 5 0 1 1 2 1 2 2 4 5 7 7 10 1 2 2 3 3 4 0 0 0 1 0 1 1 1 2 2 3 4 0 0 1 0 1 1 1 1 2 3 3 4 1 0 1 1 2 1 0 2 1 3 2 4 0 0 1 0 1 1 0 0 0 0 0 0 1 1 1 1 2 1 0 1 0 1 0 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 3 0 0 1 0 1 0 0 1 1 1 2 2 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 1 0 1 0 0 1 0 1 0 1 0 0 1 0 1 1 1 0 1 1 2 2 0 0 1 0 1 1 0 0 1 0 1 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 1 0 0 1 1 1 1 0 0 0 0 1 0 0 0 0 1 1 1 0 0 0 1 0 1 1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 1 1 1 0 0 0 0 0 0 1 1 2 2 3 2 0 1 0 1 0 1 1 0 1 1 1 1 2 1 3 2 4 3 0 0 0 0 1 1 1 1 2 2 4 3 1 1 2 2 3 3 2 1 3 1 5 2 2 2 5 4 8 6 1 1 3 2 5 3 1 1 2 1 4 2 0 0 1 1 1 1 1 0 1 1 2 1 1 1 2 1 3 2 1 0 1 0 1 0 1 0 1 1 1 1 1 0 1 0 2 1 0 0 0 0 0 0 1 0 2 1 3 1 1 1 3 1 4 2 2 1 3 1 4 2 2 0 4 1 5 2 1 0 2 0 2 0 1 1 2 1 3 1 0 0 0 0 0 0 1 1 2 1 3 1 1 1 3 1 4 2 1 0 2 0 2 0 2 1 3 1 4 1 0 0 0 0 1 0 0 1 1 1 2 1 1 0 2 0 4 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 2 0 2 0 1 1 2 1 2 1 1 0 1 0 1 0 1 0 2 0 3 1 0 0 1 0 1 0 0 0 1 0 1 0 1 0 1 0 2 0 0 0 1 0 2 0 0 0 0 0 0 0 1 1 2 1 2 1 1 0 1 0 1 0 1 0 1 0 1 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 1 0 2 0 3 0 0 0 0 0 0 0 1 1 1 0 1 1 1 0 1 0 1 0 1 0 1 0 2 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 1 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 2 0z"/>
<glyph glyph-name="quote-2" unicode="&#45121;" d="M0 222c0 153 76 233 224 233l0-103c-64 0-105-28-118-84l111 0 0-219-217 0z m288 0c0 153 76 233 224 233l0-103c-64 0-105-28-118-84l111 0 0-219-217 0z"/>
<glyph glyph-name="quote-3" unicode="&#45122;" d="M512 174c0-65-53-118-119-118-66 0-120 53-120 118 0 36 17 68 42 90l0 0 197 192-73-173c43-18 73-60 73-109z m-274 0c0-65-53-118-119-118-66 0-119 53-119 118 0 36 16 68 42 90l-1 0 197 192-73-173c43-18 73-60 73-109z"/>
<glyph glyph-name="quote-4" unicode="&#45123;" d="M39 202l180 218 65 1-113-222-35-108-133-1z m223 2l179 218 66 0-113-221-36-109-133-1z"/>
<glyph glyph-name="quote-5" unicode="&#45124;" d="M504 74l-215 0 0 207 150 164 21 0-83-164 127 0z m-496 207l149 164 21 0-82-164 127 0 0-207-215 0z"/>
<glyph glyph-name="quote-6" unicode="&#45125;" d="M427 376c-12-15-7-38 11-46 45-19 76-63 74-115-2-60-52-111-113-114-70-5-128 50-128 119 0 0 0 3 0 9 1 10 3 20 6 29 13 43 52 112 169 160l9-17c0 0-14-9-28-25z m-260-46c45-19 76-63 74-115-2-60-52-111-113-114-70-5-128 50-128 119 0 0 0 3 0 9 1 10 3 20 6 29 13 43 52 112 170 160l8-17c0 0-14-9-28-25-12-15-7-38 11-46z"/>
<glyph glyph-name="quote-7" unicode="&#45126;" d="M111 68c-27 0-52 9-76 26-23 18-35 39-35 63 0 74 29 140 87 199 58 59 97 88 118 88 20 0 31-2 31-6 0-4-20-28-59-71-38-43-58-78-58-103 0-25 12-49 37-70 24-21 36-37 36-47 0-53-27-79-81-79m276 0c-27 0-52 9-77 26-24 18-36 39-36 63 0 74 29 140 88 199 58 59 101 88 128 88 15 0 22-2 22-7-7-9-17-20-28-32-12-12-23-25-34-37-38-40-57-74-57-101 0-28 12-52 36-73 25-21 37-37 37-47 0-53-26-79-79-79"/>
<glyph glyph-name="youtube" unicode="&#45064;" d="M366 256c0 7-3 12-9 15l-146 92c-6 4-12 4-19 0-6-3-9-8-9-16l0-182c0-8 3-13 9-16 3-2 6-3 9-3 4 0 7 1 10 3l146 92c6 3 9 8 9 15z m146 0c0-18 0-33 0-43 0-10-1-23-3-39-1-16-3-30-6-42-3-14-10-26-20-35-10-10-22-15-35-17-43-4-106-7-192-7-86 0-149 3-192 7-13 2-25 7-35 17-10 9-17 21-20 35-3 12-5 26-6 42-2 16-3 29-3 39 0 10 0 25 0 43 0 18 0 33 0 43 0 10 1 23 3 39 1 16 3 30 6 42 3 14 10 26 20 35 10 10 22 15 35 17 43 4 106 7 192 7 86 0 149-3 192-7 13-2 25-7 35-17 10-9 17-21 20-35 3-12 5-26 6-42 2-16 3-29 3-39 0-10 0-25 0-43z"/>
<glyph glyph-name="envato" unicode="&#45071;" d="M412 509c23-11 116-212 36-388-63-141-224-141-305-91-70 42-176 176-58 339 5 6 17 6 14-13-2-13-19-109 13-150 15-21 19-6 19-6 0 0-3 138 103 244 67 64 159 74 178 65"/>
<glyph glyph-name="arrow3-n" unicode="&#45127;" d="M1 51l255 410 255-410"/>
<glyph glyph-name="arrow3-s" unicode="&#45128;" d="M1 461l255-410 255 410"/>
<glyph glyph-name="arrow-n" unicode="&#45129;" d="M287 494l0 0c-1 1-2 2-3 3l-2 1-1 1-2 2-2 1-1 1-2 1-2 0-2 1-2 1-2 0-2 1-2 0-8 0-2 0-2-1-2 0-2-1-2-1-1 0-2-1-2-1-2-1-1-2-2-1-2-1c0-1-1-2-2-3l-1 0-147-167c-15-18-15-48 0-66 16-18 42-18 58 0l78 89 0-304c0-25 18-46 40-46 23 0 41 21 41 46l0 304 78-89c15-18 41-18 57 0 16 18 16 48 0 66z"/>
<glyph glyph-name="arrow-ne" unicode="&#45136;" d="M512 462c0 1 0 2 0 3 0 0 0 2-1 3 0 1 0 1 0 2 0 1-1 2-1 3 0 1 0 2-1 2 0 1 0 2-1 3 0 1 0 2-1 2 0 1-1 2-1 3-1 1-1 1-1 2-1 1-1 2-2 2 0 1-1 2-1 3l-2 2c-1 1-2 2-3 4l0 0-1 0c-1 1-2 2-3 3l-2 2-3 2-2 1-2 1-3 2-2 1-3 1-2 1-4 0-3 1-2 0-3 1-296 0c-31 0-55-25-55-55 0-31 24-56 55-56l157 0-307-306c-21-22-21-57 0-79 22-21 57-21 79 0l306 307 0-157c0-30 25-55 56-55 30 0 55 25 55 55l0 291c0 1 0 3 0 5z"/>
<glyph glyph-name="arrow-s" unicode="&#45137;" d="M287 18l0 0c-1-1-2-2-3-3l-1-1-2-2-2-1-2-1-1-1-2-1-2-1-2 0-2-1-2-1-2 0-2 0-8 0-2 0-2 1-2 0-2 1-2 0-2 1-1 1-2 1-2 1-2 1-1 2-2 1c-1 1-2 2-3 3l0 0-148 167c-16 18-16 48 0 66 16 18 42 18 58 0l78-89 0 304c0 25 18 46 41 46 23 0 41-21 41-46l0-304 78 89c16 18 42 18 58 0 16-18 16-48 0-66z"/>
<glyph glyph-name="arrow-se" unicode="&#45138;" d="M512 50c0-1 0-2 0-2 0-1 0-2-1-3 0-2 0-2 0-3 0-1-1-2-1-3 0-1 0-1-1-2 0-1 0-2-1-3 0-1 0-1-1-2 0-1-1-2-1-3-1-1-1-1-1-2-1-1-1-2-2-2 0-1-1-2-1-3l-2-2c-1-1-2-2-3-3l0-1-1 0c-1-1-2-2-3-3l-2-2-3-2-2-1-2-1-3-2-2-1-3-1-2-1-4 0-3-1-2 0-3-1-296 0c-31 0-55 25-55 55 0 31 24 56 55 56l157 0-307 306c-21 22-21 57 0 79 22 21 57 21 79 0l306-307 0 157c0 30 25 55 56 55 30 0 55-25 55-55l0-291c0-1 0-3 0-5z"/>
<glyph glyph-name="arrow2-n" unicode="&#45139;" d="M243 372l-209-209c-3-3-5-6-5-10 0-4 2-8 5-11l22-22c3-3 7-4 11-4 4 0 7 1 10 4l176 176 177-176c3-3 6-4 10-4 4 0 7 1 10 4l23 22c3 3 4 7 4 11 0 4-1 7-4 10l-209 209c-3 3-7 5-11 5-4 0-7-2-10-5z"/>
<glyph glyph-name="arrow2-s" unicode="&#45140;" d="M243 140l-209 209c-3 3-5 6-5 10 0 4 2 8 5 11l22 22c3 3 7 4 11 4 4 0 7-1 10-4l176-176 177 176c3 3 6 4 10 4 4 0 7-1 10-4l23-22c3-3 4-7 4-11 0-4-1-7-4-10l-209-209c-3-3-7-5-11-5-4 0-7 2-10 5z"/>
<glyph glyph-name="map-marker" unicode="&#45141;" d="M236 10c-145 211-172 233-172 310 0 106 86 192 192 192 106 0 192-86 192-192 0-77-27-99-172-310-10-13-30-13-40 0z m20 230c44 0 80 36 80 80 0 44-36 80-80 80-44 0-80-36-80-80 0-44 36-80 80-80z"/>
<glyph glyph-name="arrow3-e" unicode="&#45142;" d="M73 0l367 256-367 256"/>
<glyph glyph-name="arrow-e" unicode="&#45143;" d="M489 281c1-1 1-1 1-2 1 0 1-1 2-1 0-1 0-1 1-2 0-1 0-1 1-2 0 0 0-1 0-1 1-1 1-2 1-2 1-1 1-1 1-2 0-1 0-1 1-2 0-1 0-1 0-2 0 0 0-1 0-2 1 0 1-1 1-2l0-1c0-2 0-3 0-4l0 0 0-1c0-1 0-2 0-3l0-2 0-2-1-2 0-2-1-1-1-2 0-2-1-2-2-2-1-2-1-1-1-2-2-2-147-147c-16-16-41-16-56 0-16 15-16 40 0 56l82 82-329 0c-22 0-37 15-37 37 0 22 15 37 37 37l329 0-82 81c-16 16-16 41 0 56 15 16 40 16 56 0l146-147c1-1 2-1 3-2z"/>
<glyph glyph-name="arrow-up-down" unicode="&#45144;" d="M303 279l-30 34 123 129 116-129-30-32-63 68 0-279-47 0 0 279z m-275-46l-28-34 116-129 117 129-30 32-63-68 0 279-47 0 0-279z"/>
<glyph glyph-name="arrow2-e" unicode="&#45145;" d="M371 262l-209 210c-3 3-7 4-11 4-3 0-7-1-10-4l-22-23c-3-3-5-6-5-10 0-4 2-8 5-11l176-176-176-176c-3-3-5-7-5-11 0-4 2-7 5-10l22-23c3-3 7-4 10-4 4 0 8 1 11 4l209 210c3 3 5 6 5 10 0 4-2 7-5 10z"/>
<glyph glyph-name="arrow-left-right" unicode="&#45152;" d="M278 211l33 29 123-118-123-111-31 29 65 60-267 0 0 45 267 0z m-44 263l-33 27-123-111 123-112 31 28-65 61 267 0 0 45-267 0z"/>
<glyph glyph-name="bell" unicode="&#45153;" d="M256 0c28 0 51 23 51 51l-102 0c0-28 23-51 51-51z m166 154l0 141c0 78-54 144-127 162l0 17c0 21-18 38-39 38-21 0-38-17-38-38l0-17c-74-18-128-84-128-162l0-141-51-51 0-26 434 0 0 26z"/>
</font></defs></svg>
libs/better-framework/assets/fonts/bs-icons.eot000064400000045074151214002610015640 0ustar00<J�I	�LP��~�bs-icons-v10icons-v10Version 1.0bs-icons-v10
�PFFTMz�.IdGDEFzID OS/2��
�XVcmapv	gT�gasp��I<glyfzv"�?thead�bM�6hhea0�$hmtx	����locau��:<�maxp�)8 name���DL�post�06�F'�~�_<�����������.M&@�LfGLf��	PfEd@��a��.�7%3+nI77a&#Ml%C"GE@IrN'���)�9�I�Y�a����0�@�P�`��O�O�^p	
<
=+ !"#$%&'()*,-./0123456789:;>?@(|x����N�j�h��R4�	>	�	�
jVR�
^
�
���FX�n��h�Z���&p�b����&`���
T��@j��� Dn���%n�3##5#535476;#"$J	Aa118A(aQ��Q14Q
I��7#"'327"&'327&'&=3&'&547&54632676�!!)*2MA?40	
#1386'(
�)!&!*($!+
&6!	��
!"+3=S`&'&/263&'#676767676#/&#"67"&462'327&'72164'67.'&'&�
+
_t
_o3
iP�;J*!I$������n0:B'( 	%-		G	C0%%.+M9
�_,28=,�}�����?%W+BVPF8		PJE1U5��;'&'&'&'&'&'67676763276'&676�FF8  

	($	-'
=5(*j_TS'mj

 
"U'@ B7I��	(J6"&462+"'&5&'&'&'&=476;+"'&5&'.'&'"'&=476;�.  .�	'/.B,+)! �	)R79<MBC74 �* . J	A/.'	!,'1@57R)	74EH%��/S�7#"'&'&54767632#"'&'&547676324'&#""'&#";2767676767+&'&'&'&'&'&547&54726326763�						�						.!
+0+
!	

0

	@!)	'(1)''�
		
		

		

		!!		L;$

$;D- 
	 /V�y�4?637213263476767>56'4'&/&'"767623327676767674763?367633#'&/&'&'&'&""+'&'&'&/&'&'&'&'&'&I
1

M.	'E

	
	
a	
			&=
&		

			'0%%��7463!2#!"&733276=#5#"%0""00"��"0ɉɉw"00"��"00�����q!+7N7#"/7632#"5'7432"5'742"5'742#"/7632"=47632632#'	,-./		!-!!
��$%%88UU68qq66rr55��<�,X�%/[lq2+32'327654'&/254'&/#%2#3276?3"'&'&'&=4767676'454'&'&'&#"7#53�



��'
�W
&			\G$		�



7%

T

v��
K+[J�+
X�	
	*

c	
�((3����S4767676762#"'&'#&54?&547632327654'&#"'&'&3	#$T$%
.-I	"'	
,"!<D()4
! [;;P%/#�#

//C4 !+)>$!"�\3276767676767275#"'&547623327654'&#"&'&'&'&'&'
			
		#3!

 		
6%+#5
	�E2;&)""
  =!!:
%'1:" !%70.G6!%%-%B�7CQ5326?2>4'&'&#"&#"'3767654'&/632#"'&64762"/32654'&#"%'>�'@&"!&'"WN?&
	 
..�N8J, , q#8'c&@N &~ �

	
. .�N8&%C,, �t264&"264&"D`DD`�D`DD`0`DD`DD`DD`D+�;5'753773+�4,3*2PV��m$X9
'(
,T%�R=2767>76767#!"&463!2"'.'&'./.'.'&'&
t\2
�\�b$		
3R�O		@"�DE		$
	
n��"%&'&=35#5#3327675#"(llB'?$ "$n
*wRj%
A�!
H��zo��37676"#"'&/#"3276?32767>76327676'&'&#"'&'&'&#&'&'&#"#47>75;5#2'&'&'&5476762'&'&5"7676+



		-	


$

21��	

		�
:>	


$*,	
!
's	
	
X��1S%'654&#"326=4%67&547&#";547/67654'.#"3!26=4�S!$		59	��
$"T		7 H	((
K
�(+*&
F	B,%
*,'B	F"
$#
#
RR%�3f#"'#"'&=?25767>767>767&'&547676222#'&'&'#"'3276767654'�/05#-"-0j0/�#-#M:0(+!$&*MP"!!(!"!�!&
"$%<I%��'=D%54'&+";276=4'&+";2767#!"'&5476;37#5n����I
��

���
YwMi���$�Y'/7#";26=4&+"&=46;2&"264"&4626"&462g�@YY@�@YY%;*�*;;*�*;�nMMnMbD//D/SY@�@YY@�@Y��*;;*�*;;*MnMMn�/D//D�R#"'7&5462"732654&&'&'&'&'&'&7>7676'&'&+"?>7>�hB8�-$��hX|)Q6?W||( 

	%


	


nΓ,�:Gg�({VE6N#{WV{��
	)
!


	��+9D\s51'=#&'&'&#"332?67676%#"=4632327"&=432#"/#"&=476542#"=4;2+32+32�	)(;26L=;@(#=.$U4��, 
"

m	,		,X<:.%%096,+!k:=0-
	>&B]Q]]	<5Z<8g]
>� '/8#32656&#32654'#32654&#3254'#3254#32654'#32654&vGK(#]IK(#�IK(#0HKLIKK�HK($IK(#�a ��a *�a aX2&�X2&5a *�a ��8cz��.'&?327>76'"&574#.'&7>76&'&'&'&'&76763>76#"'4'.'&"'"'&3"'5&54'&'&'.#"5431"'4'&'&'"&'&6�	D&yx%E	A$6A7&D	B3=C
*33op3�
M,
	
.

P-C1!

	^
			%%&�%BB%fe#@
69B%e[1+I2[\21\� 1)

5	
	
6,	"2v	+	
&��r%654&#"&#"32732654#"'&'&547632327654'&'&'&'&'&54767632#"'&'&'&#"�~X $5L}X&5L�
#+
	


!

#
	
		�X~K6$ Y}K6%!
	


	
	
				

Z�P#54&+"#";;2=32=4%2?64/#&#"32767='&+";#"'&476� + 

 +
 ��(!C1101GH+#
�H$#!!!+ 

 +6	(/1EF010$9!1K*�� ?676&"/&7%6�-w,>xOH�	#ֶ#�>X	}Z�Ko�7%�&6%#"'&"#"'&5476323276326767�
&$&-)* 2 	!!
S

3�'!8
	
	JIF@+)	

!#H+7��&F^m2764'&#"3264&#"2"'&=47%+"'&=#"'&5'#"'&=7!4767'&766276"'&=462�}�		D		
			(		
		�!�� <t		v



5
{
		{
�	A
		AA		A	

�t!"%&&�{		
{

a�*76'&?7676'&'&'&54'&'&�&C
%B*Q 
+
V!	8E�92[E(b04=4+M8
pv-]+6&�*3.67>?>'>.'./&'�
E.&NE	,.
&&"p55"9$)(W0�L,qc^7;,G&b�6  k=\�	264&#"75464&/�+<<+*<<�y/"x/m/!y/"x2<V<<V<4�%G3�$Hl$H
4�%G3��##!T��������#�Q%&'&6?5>././967674&/.>?&7>?3676&�-
$	<	1
N	&+�*/		
%2;6=61="'0qY6!!..$#.+f
 ,W�Xb'&5&>'747.'&67&'&>'&'.>77>767>75476&7>?�$%%$'.	'H&*	"%//-
!!


&3W6�`	3<mC	/ 0#',+'%	F=$6	))'/G/



4#	v
j:0SDH&L:7!�� #3264&'"732654&#532	%%f�)kFXe��^kk4$%I@~%4%��f41b9�ef����$%34IM�'7654&#"32?6&�y=�y>	

��F��	F�
�	l�!)1%67>'."'&2?264'2"&4264&"5,!	 
)a(
 	!,J
"
II �,!!,!nMMnM�	

	I!HH!p!,!!,�MnMMn%2��2#7#"'&47632#54'&#"#6='3676767632�^dM^^^


1M��X

,
壘�LmU
)  CL��I>322'&"'&&'&'&'&5&67676'&/&76=676p-
#1#
0

8%O
 	

0
	4

67#%�#!;4&54&#!"7!26�$���nT��n��%
II����I�4#"'"'&'&754?>76767>7&'&5476767632"";;F
9K
."#//4F;;"3f)*1


%&*$#"
*	�M64&#"3264&"264'&#"3276#"'"'&5&?>376767>76?.5476762�




��




x"";;F 0M)0"";;�;;"�
 
 
Mf)*0	
H)3)**-=N^nz�����#+"&=#+"&=#+"&=#"3!2654&#!"&=463!2'3276=4&+";26=4&+"!326=4&+"32+"=432+"=4732+"=432+"=4732+"=432+"=4�
;
1
$

�

	��


}	
�
		


�



	
��



BBBB�BBBB�BBBB�IIIIII
�e

�
�g	

	�


SU

U

U

U

U

U
h44o44o44o44o44o44�%'#"&462#"�Y:Le��ʏ"
	�ʏ�e5�
� *4>%4#!";232?32'#"'4+!"&54632"&5462"&4632
�

c�
�m
c�� �  � yw

��
WaTI[� ' /�1!"3!&'4&"&46327.4623"&54327.4632u���W	��
*$y$���=)��(5>
(5>*� ,%#!&'&54763!2";264&#264&+"3�G
�Z*���h

�

�c
	*A�"�%++"+"+"+"#"#"#+""#####"1##1#1##"33332;;
;;322322232322122332233233333
####"##"##+###*"+++4+"&+&+&#"'#&"'"'"/"#'&+/#/"1'&'"&+"4'"5#'1/4#4"5#4#&/&#'5&5&'4'4'54#54#5#5&5'4'54#4'45'4'541'5'4=&=&=4'=4#=4'=2=47=7=7=47=7=647546=6=6=4?547474656=254347543756154676?45753572474353534757467567>?465756?65742525?6534357342535352525?343573525343525376357367567672763>36736373637325?27;7324;6272727;727;7;7;4;4;!+++"+#""##"""+#"###1""#1####1221323332;;
;2;3322;3323233333332
##1"######"##""####"++++
5+'+"1'+&#"'#&"/*/"#'"5#4#'"'#'"'&/"'4#4#/4#'4#1'4#'5/&'4'4#'5'5'5/45&'4'54#5&41'54'=&=&=&=#='=&=6=47=2=43=47=2=64354647=6=4756=74>5256543475657464676767475656574?=7657>76?>5675672567374725635?6537535353525725253535734352534363576?6?627676?24257372736362761273636342536;427;7327;7;7;���/	/	1�	5463"3#%463"3#qobo� qobo��svgTۭsvgT�8�%#"&54?"&547#7F12F*�I!(��FbF*�I!(�1EE15%��;$1EE16$��;Z��?%73'�Aq#��Bq$����lr��mJ��
%#5733!733#�זS��R�JϤ����e�'&=6767&=6767�	
")A.4L�	��")A.4L�	x>&-CG4	
h8	>>&-CG4	
h8	D�&7"'&54623"'&547632#o'%#�>;:%$�'&$XW)!9$%OD$o�AB%' O$oXX
$<R OI�9$4/&32?"'&'&'&'&=4767676762n	�	
		��K�KK�K�\�\+++"��&'.67>74>7>�-'QWT3%*
+-r�v�Z2=
>Ws9	o'<8I+	3��7	��3��f3��	���f�G��3/#/#'+###2?3265264'�"NN"��
(


Y��0Y
';54'5'454#4'4#'45&5'4/&'#/#'#'!";27265��  ��� .2!. � .!��. 3� !#E�0%#+'#'#/&462462762�"N"N"�
(
Y0��Y

&;%###!"&46;&47625462��  ���.2!. 2 .!2.�͝ !��t�y32?2?654/&#"�����t�������7'&54?632762#"����������@�7.5462"&264&"�="
p�p
"=B//B/
#X$5"PppP"5$X#
�/B//BI�3	Io��E��:32"'&4?!"&463!'&4762��!R��IR!��!R Q!�F�'7'#7'#/{t?/��tu?/"�� D��t"�� D��rx�'&#"32?64s��������
N��%7'7!5!'7'!5!!{{A��o!{{A���vo<-Iop=-'�:65#754&'54&"!5�*f�H7 8H3�|�:ZZ:�3�	;(���%		'	PE	�	�	bs-icons-v10bs-icons-v10icons-v10icons-v10FontForge 2.0 : bs-icons-v10 : 31-3-2018FontForge 2.0 : bs-icons-v10 : 31-3-2018bs-icons-v10bs-icons-v10Version 1.0Version 1.0bs-icons-v10bs-icons-v10M	

� !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJfacebooktwitterdribbblevimeorssgithubvk	delicious
soundcloudbehance	pinterestvinesteamflickrforrst	mailchimptumblr500pxmemberscommentsposts	instagramwhatsappline
blackberryviberskypegplustelegramandroidfire-1fire-2	publisherbetterstudiofire-3fire-4disqus
better-ampok-rulinkedinsnapchat
comments-1
comments-2
comments-3calender
comments-4
comments-5
comments-6
comments-7quote-1quote-2quote-3quote-4quote-5quote-6quote-7youtubeenvatoarrow3-narrow3-sarrow-narrow-nearrow-sarrow-searrow2-narrow2-s
map-markerarrow3-earrow-e
arrow-up-downarrow2-earrow-left-rightbell��L�=��������libs/better-framework/assets/fonts/better-studio-admin-icons.eot000064400000033056151214002610021111 0ustar00.6,5	�LP�_2better-studio-admin-icons$studio-admin-iconsVersion 1.02better-studio-admin-icons
�PFFTMyT�5GDEFk4� OS/2/�L�XVcmap�;4�gasp��4�glyf�^�t+xhead�C��6hhea�R$hmtxF��loca8-L�~maxp��8 name4�/�post�ot�2l|_�_<�֋��֋������^��.����^>�@�LfGLf��	PfEd@��:��.U������	/���:�����	

 !"#$%&'()*+,-./0123465789:;<=*BX�L��L���b<�d���Nz		l	�
$
X
�
��T�

�^��PT���l�B��.b������##!T������������!!
� ���
� ������!!���I
���� ����!!!!��
� �����I�!!!!!!3#3#73#3#��*���R��+�Հ�hh���������,��T�g%^X �	'EO5!35#!'&"7&?62'2?64"/&4?67&"2?64'?6'&�vM�,)1)0�
*/,*/:P

P�q�*�Ix+/)
/)�.*,-)

O

P�	!-5!35#!!"3!2=4+"=4;27!"3!2=4�vM�
��]NNo��6�q�*�I���I�AA�	$5!35#!32?6/&54&+"'&�vM�bp9
	:

�q�*�I�xp

:�

�:�	$5!35#!&#"?;26=?6'�vM�Kq:	
9�q�*�IFq

9�

�:�	-5!35#!#";2=4&"?;2=?6'�vM��

�
}
\		
	/

/
	
		�q�*�I��\	
/�

�/		
	�	-5!35#!#";2=4'2?6/&54+"'&�vM��

�
�[		
	
/

/	

		�q�*�I��[	

		/��/		
	�	&5!35#!"&46323!26/.'&�vM�� .  A3
&
X3�q�*�I�  . �<
�

R
�	
%5!35#!#5%!!'3''7"2654'35!5�wM�
���'��<7$�!�q�*�I����EO6J{��#�	
5!35#!#5%!!35!5�wM�
���'��!�q�*�I����@��#�	9@5!35#!772?'7&'&/?6'&767676'&6�wM���		/$U��
)
�C
	
	�q�*�I��
	/'T�p
B
� !	(	

�	FVgt��5!35#!&'"&'&'#"327676/43632727676765675676#"'&'&763267676'"'.7632632#"'&'&7632#"'&'&�wM�#"(<CV	8

"	
$
�
� 
E
�q�*�I	+fAF 	""
-
	
	,	##-	- 

-
	
	�		�	!=P5!35#!264&"&264&"264&"7&3276767676764'&#&�wM�8((((�((�=C+*:4��'�q�*�I��((Y((�((�	07)	*A<��	$<5!35#!&?6#&576/4&'&6576?6'�wM��
�	
�	�	�
�	
��q�*�I��
E��
'''!
T
"	��	25!35#!"'654'73264&#"&#"3273264&�wM�ee"""d""d"""�q�*�I��<<"0!!<!0"<""0!�	C5!35#!'&#"#"3276=&54&54767676767676;32?64�wM�&_*�


*_�q�*�I�`/K"5	/_
�	&5!35#!4#!";2?3;253;265�wM�*
��

J*
K�q�*�II

:
����^�	'.38>DINTZbjqx���5!35#!&'&#"327676764'&&'67''&'6#6&'&'657&'53'5677&'&''&'6#6&'67&67677&'673�wM�L%$,*&$$&*,$%>	 �CBC / CA$�
+?<!9
�
+	?�q�*�I�'(P('$(P($e"()4�5HH5Q8 >8! VH5GH5Q8#A8#s	


	* *2P* +2s	



		*("4�	Q[����5!35#!'&'76/&&/&+"'&"3?;2?67?6/6?2=4"&54627'54#'""'&#"3??27?6/6732574#'&'76/&'&76&'74#'""'&#"?3?27?6/6732?4/&'76/&&76�wM�!



	


b$$3
			

		
�


	



	�q�*�I��
		

	


			


<�
			<

I
	

	

B&�	5!35#!3#3'7#7�wM�����
^R:��3�q�*�IW9%:A  E44�	F^5!35#!'&'&1463327656'&'&'&547673&/&'&#&'3'&/?3276?=�wM�$+"	! 
��q�*�I��"
#
			

vOR&
	
ON�	G5!35#!272654'>72327264&#"'654&"&#".'654&"�wM���	+ /	#	 1 $
 �q�*�I��$
H	 
)5 �	$?5!35#!>7;2=4&&3&'76&+"767676'�wM��DE
+n'.1�FF
+n'.�q�*�I�	`!	'-B,-		`!	'.A�	%1=5!35#!"264"&462'"32654&"&546327#"&54632�wM�4�__�^pbEEbEv*;;*);;)!!""

�q�*�IJ^�__��EbDDb�;)*;;*);�!""!9

�	!5!35#!!26=4/##5#"3#�wM��	<�/�++�q�*�I�s	�
	=qq
��	+[�	%5!35#!3;2=32=4+54+"#"�wM��]
5
]

]
5
]
�q�*�I��]

]
5
]

]
5
�	%5!35#!??6/76/&'&�wM��BB&BB%BB%BB&�q�*�I�AB&BB&BA&BB&	��!1#"3!2?654&+"#!"&=4&326=4&+"[<	

	y0
1	
	��	

�(	

	(	

�
	�0
7y	

	�	

	�	
�
T

T
�	U5!35#!/&'4?&'&#"32767672#"'&'&'&47676762?6�wM�*q(	"

D�q�*�I�&
"






<


��J/&5&?&'&#"32767672#"'&'&'&47>762?6��+

6&! @ 30/""D/,n,/!*>	!,
""/,n,/D#�	05!35#!767''.?66&'&7'"'&4�wM���q

 ITH	p

�q�*�I��q
 ITI 
q�	&,7@5!35#!5#5733#'547#7"&54632324#5#5733#'547#�wM��<3'�22F{<3'�q�*�I�v SO 8	

 '('\\q SO 8	�	!/;GU5!35#!#";2=4#";2=4#";26=4'#";2=4#";2=4#";26=4�wM���������q�*�Itpq		�pq		�	-17=HS5!35#!27326=73264&"&#"'54&"$2"2#"4&2"5"'35'#"'35.�wM���
b_ ]\ I�
�?
C�	�F


��q�*�I�'7
 6$O>=
@']�*�]	�	15IN5!35#!#53##7#"54325373#;#"&=#53573#7327#"&54632'4#"�wM���%j% u;	

BE�q�*�I��p��dd�$(�( 	�	=5!35#!'6'&#'&#7676727654'&?67>276�wM�(/	.M1	
	(
#	�q�*�I�DD
J3!	<			#	�	5!35#!'#"&54632�wM�03K'-X{{XW{�q�*�I�?3KfIHff�	$25!35#!&#'?6.'&/?6/&�wM�	&F23FBB
.'.'��<=<�q�*�I�F23F%BB�
-'.<=<�	`5!35#!#54&+532=4+";#"#";26=4&+54;#";26=4&+532#";26=4&�wM�
j2w	2j


(


j


'
j
'

�q�*�I��'*<	<*'''
'/
''
/'
''
�	1F[�5!35#!&'"&#"327654'.547676'&'"&#"327654'&'&5465676'672763667632"'&'"'&'&�wM�"
	W
	


�

%


�q�*�I��!	

	'#
		
		F0+G
C'%.&b�	(5!35#!"35353732654&"&462�wM�C.@�@&':-@@
 �q�*�I1@.�A'&:@-.@t �	&3?5!35#!72!.>?6#4.'">54&#"&54632�wM��9#��* �"
7 )#..! .. !.�q�*�I��87&,#1$�4!*!.j .. !..�	D\_��5!35#!3&'&+";276772576'&'6732=4+54+"#"&+";2?3;276/7%312?5/&"#"'&/3256/&#5"7;632'1##31?654#'5&'&#1"�wM���U
	 -,�&'	K��3#

(� (
3!�q�*�I�$	

% n|277+<	
$8*�
$8*; 	�	"/5!35#!"26=4"&'26=#"&'265�wM�&pPPpP�5OPpPNRN65OPpP�q�*�IC((�DD2C�	&*28@Z5!35#!#'&+"#3#!5#76=&'3#3#73#6%#675#"54;'27632#"#676/3�wM��	WUBo3H�#J#c�!
"#)]!) (+C��q�*�I�&&�[4LN22	+4'
��	-G5!35#!!"3!2=4&"?;2=?6'32?6/&54+"'&�vM���

,
KR**��Q	*)			�q�*�I��Q	

*��*

	�R*��*	/��=E%'6'&'&>7676764.>?676276567'7'7�E
F1
J
!	

=)++(:"	��ff	&F3	/!2Z3

��	QY5!35#!'&'76/&&/&+"'&?;2?67?6/6?6=4"&462�wM�!

	
""
	
!�4$$4%�q�*�I�

!!
	

	
	""	
U%4$$4�	264&#"75464&/�+<<+*<<�y/"x/m/!y/"x2<V<<V<4�%G3�$Hl$H
4�%G3�	!35#!3#5#53#?3#'#53�e<�*�-9�9�.2@D4.--��)�|���&&W1F\B3�d�	#5!3#!"/&4?62762*�TMw�e<��I�T*����f=��#3##3#3lll���ړll���6���$���3#3#35353#7353#(�����I��?���� �o����L�ܘ��ݙ�Eٹ�����H�#!"&547276?>7>?676767>7623367654/&#""'&'&'&'&'&#"276767>7>7�\

/


/

�P\	

	4.P	
	E��

!

	!

�:C$#:	
�	"5!35#!7''732?'7'7�wM�]###v63w##\LL/�q�*�I�]###w-54
w##sM/�4t5�]��	2	$N	j�	2)	w	2�better-studio-admin-iconsbetter-studio-admin-iconsstudio-admin-iconsstudio-admin-iconsFontForge 2.0 : better-studio-admin-icons : 22-1-2018FontForge 2.0 : better-studio-admin-icons : 22-1-2018better-studio-admin-iconsbetter-studio-admin-iconsVersion 1.0Version 1.0better-studio-admin-iconsbetter-studio-admin-icons>	

 !"#$%&'()*+,-./0123456789:;<betterstudioheaderfootersidebar	page-textlinkarchivearrow-bottom	arrow-topexportdownloadimageslider
slider-newpaintpaint1paint2images	share-altshare
typographyglobalgearscss3js	analyticsrefreshgoalsaveadddelete
save-cleanresetreset-cleanverdict404list-bullet
analytics1title	advertisecommentpinsitemapwookeybbpresstranslationdatabasefont
export-import
advertise2gear	publishertypekitcheck
skyscraperchecked-gridnewsletter-packinject��=�=��֋��֋��libs/better-framework/assets/fonts/better-studio-admin-icons.svg000064400000072104151214002610021116 0ustar00<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by Fontastic.me</metadata>
<defs>
<font id="better-studio-admin-icons" horiz-adv-x="512">
<font-face font-family="better-studio-admin-icons" units-per-em="512" ascent="480" descent="-32"/>
<missing-glyph horiz-adv-x="512" />

<glyph glyph-name="betterstudio" unicode="&#57344;" d="M340 506l0-168-167 0 0-167-166 0 0-168 499 0 0 503z"/>
<glyph glyph-name="header" unicode="&#57345;" d="M-8 517l3-522 522 0-2 522z m43-483l0 288 439 0 0-288z"/>
<glyph glyph-name="footer" unicode="&#57346;" d="M517-5l-2 522-523 0 3-522z m-43 483l0-288-439 0 0 288z"/>
<glyph glyph-name="sidebar" unicode="&#57347;" d="M516 518l-522 0 0-524 522 0z m-483-42l288 0 0-439-288 0z"/>
<glyph glyph-name="page-text" unicode="&#57348;" d="M0 511l1-510 511 0 0 510z m42-468l0 428 428 0 0-428z m46 389l338 0 0-103-338 0z m19-132l299 0 0-27-299 0z m0-57l128 0 0-27-128 0z m0-64l104 0 0-94-104 0z m128-6l171 0 0-27-171 0z m0-59l171 0 0-26-171 0z"/>
<glyph glyph-name="link" unicode="&#57349;" d="M512 398l0 113-512 0 1-510 118 0 0 42-77 0 0 428 428 0 0-73z m-14-120l-44 43c-20 19-51 19-70 0l-49-47c-19-19-19-50 0-69l28 27c-3 8 0 18 7 25l31 30c10 9 26 9 35 0l26-26c10-10 10-25 0-35l-31-30c-6-6-17-10-25-8l-27-26c19-19 50-19 70 0l48 47c20 19 20 50 1 69z m-178-173c2-9-1-19-8-26l-29-28c-10-10-26-10-36 0l-26 26c-10 10-10 26 0 35l29 29c7 6 17 10 25 7l28 28c-19 19-51 19-71 0l-47-46c-20-19-20-51 0-70l44-44c20-20 52-20 72 0l47 45c19 20 19 51 0 71z m-30 12c6-7 17-7 23 0l80 79c7 7 7 18 0 24-6 7-17 7-23 1l-80-80c-7-7-7-17 0-24z"/>
<glyph glyph-name="archive" unicode="&#57350;" d="M512 398l0 113-512 0 1-510 118 0 0 42-77 0 0 428 428 0 0-73z m-32-187l-260 0c-3 0-6-3-6-7l0-196c0-4 3-7 6-7l260 0c4 0 7 3 7 7l0 196c0 4-3 7-7 7z m-86-73c0-3-2-5-5-5l-78 0c-3 0-5 2-5 5l0 22c0 3 2 5 5 5l78 0c3 0 5-2 5-5z m111 174l-310 0c-4 0-7-3-7-7l0-65c0-4 3-7 7-7l310 0c4 0 7 3 7 7l0 65c0 4-3 7-7 7z"/>
<glyph glyph-name="arrow-bottom" unicode="&#57351;" d="M512 398l0 113-512 0 1-510 118 0 0 42-77 0 0 428 428 0 0-73z m-140-392c3-3 7-5 11-5 5 0 9 2 12 5l112 112c7 7 7 17 0 24l-15 15c-7 6-17 6-24 0l-57-58 0 217c0 9-8 17-17 17l-22 0c-9 0-16-8-16-17l0-217-58 58c-6 6-17 6-23 0l-16-15c-6-7-6-17 0-24z"/>
<glyph glyph-name="arrow-top" unicode="&#57352;" d="M512 398l0 113-512 0 1-510 118 0 0 42-77 0 0 428 428 0 0-73z m-117-70c-3 3-8 5-12 5-4 0-8-2-11-5l-113-113c-6-6-6-16 0-23l16-15c6-7 17-7 23 0l58 57 0-216c0-9 7-17 16-17l22 0c9 0 17 8 17 17l0 217 57-58c7-7 17-7 24 0l15 15c7 7 7 17 0 24z"/>
<glyph glyph-name="export" unicode="&#57353;" d="M512 398l0 113-512 0 1-510 118 0 0 42-77 0 0 428 428 0 0-73z m-13-352l-242 0c-7 0-13-6-13-14l0-17c0-8 6-14 13-14l242 0c7 0 13 6 13 14l0 17c0 8-6 14-13 14z m-112 286c-2 2-6 4-9 4-3 0-7-2-9-4l-92-92c-5-5-5-13 0-19l13-12c5-6 14-6 19 0l47 47 0-177c0-7 6-13 13-13l18 0c7 0 13 6 13 13l0 177 47-47c6-5 14-5 19 0l13 12c5 6 5 14 0 19z"/>
<glyph glyph-name="download" unicode="&#57354;" d="M512 398l0 113-512 0 1-510 118 0 0 42-77 0 0 428 428 0 0-73z m-13-352l-242 0c-7 0-13-6-13-14l0-17c0-8 6-14 13-14l242 0c7 0 13 6 13 14l0 17c0 8-6 14-13 14z m-130 24c2-3 6-4 9-4 4 0 7 1 10 4l91 91c5 5 5 14 0 19l-13 13c-5 5-13 5-19 0l-47-47 0 176c0 8-6 14-13 14l-18 0c-7 0-13-6-13-14l0-176-47 47c-5 5-14 5-19 0l-13-13c-5-5-5-14 0-19z"/>
<glyph glyph-name="image" unicode="&#57355;" d="M512 398l0 113-512 0 1-510 118 0 0 42-77 0 0 428 428 0 0-73z m-213-133c0-31-25-55-55-55-30 0-54 24-54 55 0 30 24 54 54 54 30 0 55-24 55-54z m-65-176l-51-60c-13-15-7-28 12-28l294 0c20 0 28 14 18 32l-88 158c-10 17-26 18-37 1l-51-82c-11-17-32-22-47-12-15 10-37 6-50-9z"/>
<glyph glyph-name="slider" unicode="&#57356;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-29-170l0-198-238 0 0 198 238 0m29 29l-295 0 0-256 295 0z m-247-187l199 0-60 79-55-54-36 29z m60 128c-11 0-20-8-20-19 0-11 9-20 20-20 11 0 19 9 19 20 0 11-8 19-19 19z m-169 123l0-253 33 0 0 218 258 0 0 35z"/>
<glyph glyph-name="slider-new" unicode="&#57357;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-29-170l0-198-238 0 0 198 238 0m29 29l-295 0 0-256 295 0z m-356 64l0-253 33 0 0 218 258 0 0 35z"/>
<glyph glyph-name="paint" unicode="&#57358;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-336-262c-7-8-7-19 0-26l9-10 23 9-9-22 47-47 36 21-18-39 15-15c7-8 19-8 26 0l85 84-129 129z m325 196l0 0c-9 9-20 12-33 10-25-5-52-32-71-74-5-11-13-18-23-20-20-3-45 11-59 26-3 3-9 3-12 0l-15-15 23-23c3-3 3-8 0-11-3-3-8-3-11 0l-23 23-5-6c-3-3-3-8 0-11l128-129c3-3 8-3 12 0l31 32c3 3 3 8 0 11-14 15-29 40-25 59 2 11 8 18 20 24 41 19 69 45 73 71 3 12-1 24-10 33z m-14-41c-5-6-14-6-19 0-5 5-5 14 0 19 5 5 14 5 19 0 6-5 6-14 0-19z"/>
<glyph glyph-name="paint1" unicode="&#57359;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-7-127c-1 1-2 2-4 3-2 0-3-1-4-2-6-9-14-12-23-15-8-3-15-5-24-11-11-9-16-20-14-31l0 0c-5 7-10 13-16 19-26 28-63 44-100 45-2 0-3 0-5 0-42 0-82-18-110-51-28-33-40-75-34-116 0-4 1-7 2-11 10-45 37-79 72-94 9-4 18-6 26-6 22 0 41 12 52 32 4 8 7 15 8 23 1 5 1 10 0 14 0 5-1 9 0 14 2 10 9 16 19 16 3 0 6 0 9-1-4-7-7-13-10-18-5-13-10-23-12-30-1-5-4-17 4-23 3-2 6-3 10-2 3 0 13 2 40 34 8 8 16 18 24 29 22 7 39 25 43 46 1 5 2 11 2 17 8 12 15 24 22 36 0 0 0 1 0 1 11 3 19 11 25 22 7 17 7 38-2 60z m-116-78c-4-6-11-10-18-10-3 0-7 1-10 3-5 3-8 8-9 13-2 5-1 11 2 15 4 6 10 10 17 10 4 0 8-1 11-3 5-3 8-8 9-13 1-5 0-11-2-15z m26-37c10 15 21 30 31 44 2-2 4-3 6-5 3-2 7-4 10-5-8-15-18-30-29-47-19-27-38-52-55-71-9-11-17-19-23-24 2 8 7 18 13 31 12 22 28 50 47 77z m-180 0c-4 0-8 1-11 3-5 3-8 8-9 13-1 5 0 11 3 15 3 6 10 10 17 10 4 0 7-1 11-3 9-6 12-19 6-28-4-6-10-10-17-10z m-22-45c4 6 11 10 18 10 3 0 7-1 10-3 5-3 8-8 9-13 2-5 1-11-2-15-4-6-10-10-17-10-4 0-8 1-11 3-5 3-8 8-9 13-1 5 0 11 2 15z m65 121c4 6 11 9 18 9 3 0 7-1 10-3 10-6 13-18 7-28-4-6-10-9-17-9-4 0-8 1-11 3-5 3-8 7-9 13-1 5 0 10 2 15z"/>
<glyph glyph-name="paint2" unicode="&#57360;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-98-348c0-27 22-49 49-49 27 0 49 22 49 49 0 27-22 49-49 49-27 0-49-22-49-49z m0 118c0-27 22-49 49-49 27 0 49 22 49 49 0 26-22 48-49 48-27 0-49-22-49-48z m-122-118c0-27 22-49 49-49 27 0 49 22 49 49 0 27-22 49-49 49-27 0-49-22-49-49z m179 284c-2 1-4 2-6 1-7-3-27-14-81-57-38-31-83-70-110-96-14-14-27-28-38-41-1-1-2-3-2-4 1-2 2-3 3-4 4-3 8-6 12-10 5-5 9-11 11-17 1-1 2-3 4-3 1 0 3 0 4 1 15 11 30 25 44 38 27 27 67 70 100 107 45 52 57 72 60 79 1 2 0 4-1 6z m-285-250c-2-9-3-17-9-24-2-1-2-3-2-5 1-2 3-3 5-4 25-5 47 0 61 14 15 14 15 35 0 50-7 8-14 12-22 12-8 1-14-4-18-7-3-3-6-7-8-12-4-9-6-17-7-24z"/>
<glyph glyph-name="images" unicode="&#57361;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-274-171c-1 7 4 13 11 14l175 16c7 1 14-5 14-12l14-156c1-7-4-13-11-13l-175-16c-7-1-14 4-14 11z m16-225l208 18c7 1 13 7 12 14l-21 228c0 6-7 12-13 11l-209-19c-7-1-12-7-11-14l21-227c0-7 6-12 13-11m248 293l-206 39c-7 1-13-3-14-10l-8-39c-1-7 15-9 16-2l5 24c1 6 8 11 15 10l173-33c7-1 11-8 10-15l-16-84c-1-6-2-18-1-25l3-34c1-7 2-7 4-1l29 156c1 7-3 13-10 14"/>
<glyph glyph-name="share-alt" unicode="&#57362;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-57-282c-14 0-26-4-35-12l-101 60c1 3 1 7 1 10 0 3 0 6-1 9l101 60c9-7 21-12 35-12 31 0 57 26 57 58 0 32-26 57-57 57-32 0-58-25-58-57 0-3 0-7 1-10l-100-60c-10 8-22 12-35 12-32 0-58-25-58-57 0-32 26-58 58-58 13 0 25 5 35 12l100-60c-1-3-1-6-1-9 0-32 26-58 58-58 31 0 57 26 57 58 0 32-26 57-57 57z"/>
<glyph glyph-name="share" unicode="&#57363;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-4-198l-95 96c-2 2-5 3-8 3-3 0-6-1-9-3-2-3-3-6-3-9l0-47-42 0c-88 0-143-25-163-75-6-17-10-38-10-62 0-21 8-49 24-84 0-1 1-3 2-5 1-2 2-4 3-5 0-2 1-3 2-5 1-2 3-3 5-3 2 0 3 1 5 2 1 1 1 3 1 5 0 1 0 3 0 5-1 2-1 3-1 4 0 9-1 16-1 23 0 12 1 24 3 34 3 10 6 18 10 25 3 8 8 14 14 19 6 6 13 10 20 13 7 4 15 6 25 8 9 2 19 3 28 4 10 1 21 1 33 1l42 0 0-47c0-4 1-6 3-9 3-2 6-3 9-3 3 0 6 1 8 3l95 95c3 3 4 6 4 9 0 3-1 6-4 8z"/>
<glyph glyph-name="typography" unicode="&#57364;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m0-73c0 6-5 10-10 10l-312 0c-6 0-10-4-10-10l0-58c0-5 4-10 10-10l24 0c3 0 6 1 8 4l18 22 74 0 0-271c0-6 5-11 11-11l42 0c5 0 10 5 10 11l0 271 75 0 18-22c2-3 5-4 8-4l24 0c2 0 5 1 7 3 2 2 3 5 3 7z"/>
<glyph glyph-name="global" unicode="&#57365;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m34-133c-19 19-41 34-66 44-25 11-52 16-80 16-27 0-54-5-80-16-24-10-46-25-65-44-19-19-33-41-44-65-10-25-16-52-16-80 0-28 6-55 16-80 11-24 25-46 44-65 19-19 41-34 65-44 26-11 53-16 80-16 28 0 55 5 80 16 25 10 47 25 66 44 18 19 33 41 44 65 10 25 16 52 16 80 0 28-6 55-16 80-11 24-26 46-44 65z m-34-130c-1 26-5 51-10 74 13 5 26 12 37 19 20-26 33-58 36-93z m-97 158c20-8 38-32 50-65-16-4-33-6-50-7z m-29 0l0-72c-18 1-34 3-50 7 12 33 30 57 50 65z m-59-93c19-5 38-8 59-9l0-56-67 0c1 23 4 45 8 65z m59-95l0-56c-21-1-40-4-59-9-4 20-7 42-8 65z m0-86l0-72c-20 8-38 32-50 65 16 3 32 6 50 7z m29-72l0 72c17-1 34-4 50-7-12-33-30-57-50-65z m58 93c-18 5-38 8-58 9l0 56 67 0c-1-23-4-45-9-65z m-58 95l0 56c20 1 40 4 58 9 5-20 8-42 9-65z m103 115c-7-5-16-9-25-13-2 7-5 14-8 20-4 8-8 16-13 23 17-7 33-18 46-30z m-189 30c-5-7-9-15-13-23-3-6-6-13-8-19-9 3-18 7-25 12 13 12 29 23 46 30z m-67-52c11-7 24-14 37-19-6-23-9-48-10-74l-63 0c2 35 16 67 36 93z m27-123c1-26 4-51 10-74-13-5-26-12-37-19-20 26-34 58-36 93z m-6-115c7 5 16 9 25 12 2-6 5-13 8-19 4-8 8-16 13-23-17 7-33 18-46 30z m189-30c5 7 9 15 13 23 3 6 6 13 8 19 9-3 18-8 25-12-13-12-29-23-46-30z m67 52c-11 7-24 14-37 19 5 23 9 48 10 74l63 0c-3-35-16-67-36-93z"/>
<glyph glyph-name="gears" unicode="&#57366;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-9-264l-23 4c-1 7-4 14-7 20l15 18c3 4 3 9 0 13l-10 10c-3 4-8 5-13 2l-19-12c-9 6-19 10-29 13l-4 23c-1 5-5 9-10 9l-14 0c-5 0-9-4-10-9l-4-23c-9-2-17-6-24-10l-19 13c-4 3-10 3-13-1l-10-10c-3-3-4-9-1-13l13-18c-4-8-8-16-10-25l-23-4c-5 0-8-5-8-10l0-13c0-5 3-10 8-10l23-4c2-7 5-14 8-21l-15-18c-3-4-3-9 1-13l9-10c3-4 9-5 13-2l20 12c8-5 18-10 28-12l4-23c1-5 5-9 10-9l14 0c5 0 9 4 10 9l4 23c8 2 16 5 24 10l19-14c4-3 10-2 13 1l10 10c4 3 4 9 1 13l-14 19c5 8 8 16 10 25l24 4c4 0 8 5 8 10l0 13c0 5-4 10-9 10z m-107-60c-24 0-43 19-43 43 0 25 19 44 43 44 24 0 44-19 44-44 0-24-20-43-44-43z m95 257l-10-6c-3 2-6 4-9 6l0 12c0 2-2 5-4 5l-7 2c-3 0-5-1-6-4l-4-11c-6 0-11-1-16-3l-9 8c-2 2-5 2-7 0l-5-4c-2-2-3-4-2-7l6-10c-3-4-5-8-7-12l-12 0c-2 0-4-2-5-5l-1-7c0-2 1-5 4-5l11-4c0-4 2-9 3-13l-8-9c-2-1-2-4 0-6l4-6c1-2 4-3 7-1l10 5c3-2 6-4 10-6l-1-12c0-2 2-4 4-5l7-1c3-1 5 0 6 3l4 11c6 0 11 2 16 4l9-9c1-1 4-1 6 0l6 4c2 2 3 5 1 7l-5 11c3 3 5 7 7 11l12 0c2 0 5 2 5 5l1 7c0 2-1 5-4 5l-11 4c-1 5-2 9-4 13l9 9c1 2 1 5 0 7l-4 5c-2 2-5 3-7 2z m-25-58c-10-7-24-6-31 4-8 10-6 24 4 32 10 7 24 5 31-5 8-10 6-24-4-31z m-205-60l-12-6c-3 2-6 4-10 6l1 13c0 3-2 6-5 6l-7 2c-3 0-6-1-7-4l-5-12c-6 0-11-2-17-4l-10 9c-2 2-5 2-7 0l-6-4c-2-2-3-5-2-7l6-12c-3-4-5-8-7-13l-13 0c-3 0-5-2-6-5l-1-8c0-3 1-5 4-6l13-4c0-5 1-10 3-14l-9-10c-2-2-2-5 0-7l4-7c2-2 5-2 8-1l11 6c3-3 7-5 11-7l-1-13c0-2 2-5 5-5l7-2c3-1 6 1 7 4l5 12c5 0 11 2 16 4l10-9c2-2 5-2 7-1l7 5c2 2 3 5 1 7l-6 12c3 4 6 8 8 13l13 0c3 0 5 2 6 5l1 8c0 2-2 5-4 6l-13 4c-1 5-2 10-4 14l9 10c2 2 2 5 1 7l-5 6c-2 2-5 3-7 2z m-28-64c-11-8-26-6-34 5-8 11-6 26 5 35 10 8 26 6 34-5 8-11 6-26-5-35z"/>
<glyph glyph-name="css3" unicode="&#57367;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-292-87l-11-57 234 0-7-37-235 0-11-58 234 0-13-65-94-32-82 32 6 28-58 0-14-69 136-52 156 52 51 258z"/>
<glyph glyph-name="js" unicode="&#57368;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-6-308c4-9 6-17 6-28 0-18-5-32-17-42-10-11-24-17-42-19-7-1-21-1-28 0-29 4-50 17-64 40-1 3-2 4-1 4 0 1 34 20 35 20 0 0 1-1 3-3 10-16 23-23 40-23 11 0 19 3 24 8 2 2 4 4 4 5 4 8 2 17-3 23-5 4-12 8-30 16-14 6-22 10-28 13-22 14-33 32-33 56 0 17 6 30 16 41 11 10 25 16 42 18 6 0 7 0 14 0 14-1 24-5 34-11 5-4 13-12 17-18 2-3 4-6 4-6 0 0-32-21-34-22 0 0-1 1-2 4-1 1-4 5-6 7-6 5-11 7-20 7-8 1-12-1-17-6-3-3-4-6-4-11-1-6 1-11 5-15 4-5 10-8 29-16 24-10 36-18 45-27 5-5 8-9 11-15z m-193 126l22 0 0-79c0-52 0-80 0-82-4-25-15-42-35-50-17-6-39-7-57-1-16 6-30 18-38 34l-1 2 17 11c10 6 18 11 18 11 0 0 1-2 3-4 8-14 14-19 26-19 8 0 13 2 17 6 2 2 4 5 5 10l1 4 0 79 0 78c0 0 22 0 22 0z"/>
<glyph glyph-name="analytics" unicode="&#57369;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-351-323c6 0 12 2 17 5l43-36c0-2-1-3-1-5 0-21 17-38 38-38 21 0 38 17 38 38 0 6-2 12-4 17 21 31 47 71 63 95 3 0 5-1 8-1 9 0 17 3 23 9 15-9 33-19 49-29 0 0 0-1 0-1 0-21 17-38 38-38 21 0 38 17 38 38 0 21-17 38-38 38-9 0-17-4-24-10l-49 29c0 0 1 1 1 2 0 21-17 38-38 38-21 0-38-17-38-38 0-7 2-14 5-19-19-30-45-69-62-94-3 1-6 2-10 2-8 0-15-3-21-7-12 10-27 22-40 33 1 4 2 7 2 10 0 21-17 38-38 38-21 0-38-17-38-38 0-21 17-38 38-38z"/>
<glyph glyph-name="refresh" unicode="&#57370;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-214-180c33 33 83 38 121 15-13-13-28-28-28-28-10-12 2-20 8-19l69 0c4 0 7 0 7 0 0 0 3 0 7 0l13 0c4 0 7 3 7 6l0 96c0 9-9 17-19 7 0 0-17-16-28-27-58 43-140 38-192-15-31-30-45-71-43-111l49 0c-2 28 8 55 29 76z m164-59c2-28-7-55-28-76-33-33-84-38-122-15 13 13 28 28 28 28 11 12-1 20-7 19l-70 0c-3 0-6 0-6 0 0 0-3 0-7 0l-14 0c-3 0-6-3-6-6l0-96c-1-9 9-17 19-7 0 0 16 16 28 27 58-43 139-38 192 15 30 30 45 71 43 111l-50 0z"/>
<glyph glyph-name="goal" unicode="&#57371;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-161-74c-89 0-162-72-162-161 0-89 73-162 162-162 89 0 161 73 161 162 0 89-72 161-161 161z m0-279c-65 0-118 53-118 118 0 65 53 117 118 117 65 0 118-52 118-117 0-65-53-118-118-118z m0 218c-56 0-101-45-101-100 0-56 45-101 101-101 55 0 100 45 100 101 0 55-45 100-100 100z m0-157c-32 0-57 25-57 57 0 31 25 57 57 57 31 0 57-26 57-57 0-32-26-57-57-57z m29 57c0-17-13-30-29-30-17 0-30 13-30 30 0 16 13 29 30 29 16 0 29-13 29-29z"/>
<glyph glyph-name="save" unicode="&#57372;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-278-397l258 0c11 0 20 9 20 21l0 195c0 9-3 16-9 22l-60 61-1 0 0-113-161 0 0 113-47 0c-11 0-20-10-20-21l0-257c0-12 9-21 20-21z m141 299l43 0 0-91-43 0z"/>
<glyph glyph-name="add" unicode="&#57373;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-269-294l93 0 0-93c0-5 5-10 10-10l53 0c6 0 10 5 10 10l0 93 93 0c6 0 10 5 10 10l0 53c0 5-4 10-10 10l-93 0 0 93c0 6-4 10-10 10l-53 0c-5 0-10-4-10-10l0-93-93 0c-5 0-10-5-10-10l0-53c0-5 5-10 10-10z"/>
<glyph glyph-name="delete" unicode="&#57374;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-257-192l66-65-66-66c-3-4-3-10 0-14l38-38c4-3 10-3 14 0l66 66 66-66c3-3 10-3 14 0l37 38c4 4 4 10 0 14l-66 66 66 65c4 4 4 11 0 14l-37 38c-4 4-11 4-14 0l-66-66-66 66c-4 4-10 4-14 0l-38-38c-3-3-3-10 0-14z"/>
<glyph glyph-name="save-clean" unicode="&#57375;" d="M91 511l-60 0c-12 0-22-10-22-22l0-464c0-13 10-22 22-22l377 0c12 0 28 7 36 16l48 55c8 9 14 26 14 38l0 377c0 12-9 22-22 22l-49 0c-12 0-22-10-22-22l0-137c0-12-9-22-21-22l-257 0c-12 0-22 10-22 22l0 137c0 12-10 22-22 22z m203-134l40 0c12 0 22 9 22 22l0 84c0 13-10 22-22 22l-40 0c-12 0-22-9-22-22l0-84c0-13 10-22 22-22z"/>
<glyph glyph-name="reset" unicode="&#57376;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m0-232c0-2-1-4-3-5-2-2-4-2-6-1l-113 38c-3 1-4 3-5 6 0 2 1 5 3 6l26 19 5 3c-8 7-17 12-27 15-9 3-20 5-31 5-13 0-25-2-36-7-11-5-21-12-29-20-9-9-16-18-21-30-4-11-7-23-7-36 0-13 3-25 7-36 5-11 12-21 21-30 8-8 18-15 29-20 11-5 23-7 36-7 16 0 31 3 44 11 14 7 25 17 34 30 1 2 3 3 5 4 3 0 5 0 6-2l40-27c2-1 3-3 3-5 1-2 0-4-1-6-7-11-16-21-25-30-10-8-20-15-32-21-11-6-23-11-35-14-13-3-26-5-39-5-21 0-42 4-61 13-19 8-36 19-50 34-14 14-26 30-34 50-8 19-13 39-13 61 0 22 5 42 13 61 8 20 20 36 34 51 14 14 31 25 50 33 19 9 40 13 61 13 22 0 42-4 61-13 19-8 36-19 50-34l2 2 27 19c2 1 4 2 7 1 2-2 4-4 4-6z"/>
<glyph glyph-name="reset-clean" unicode="&#57377;" d="M505 267c0-3-1-6-4-8-3-3-7-3-10-2l-183 62c-4 2-7 5-7 9-1 4 0 8 4 10l43 31 7 5c-13 10-27 18-43 24-15 5-32 8-50 8-20 0-40-4-58-12-18-8-34-19-48-32-14-14-24-30-32-48-8-18-12-38-12-58 0-21 4-40 12-59 8-18 18-34 32-47 14-14 30-25 48-33 18-8 38-12 58-12 26 0 49 6 71 18 22 11 40 28 54 49 2 3 5 5 9 6 4 0 7 0 10-3l64-44c3-1 4-4 5-8 1-3 0-6-2-9-12-18-25-34-41-48-15-14-32-26-50-35-19-10-38-17-58-22-20-5-41-8-62-8-35 0-68 7-99 20-31 14-58 32-81 55-23 23-41 50-54 81-14 31-20 64-20 99 0 35 6 68 20 99 13 31 31 58 54 81 23 23 50 41 81 54 31 14 64 20 99 20 35 0 68-6 99-20 30-13 57-31 80-55l4 3 42 31c4 2 7 2 12 1 4-3 6-6 6-10z"/>
<glyph glyph-name="verdict" unicode="&#57378;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-335-349l113 113c6 6 15 9 23 8l26 26-32 32c-10-7-24-5-33 4-11 10-11 27-1 37l73 73c10 10 27 10 37-1 9-9 11-23 4-33l84-84c10 7 24 5 33-4 10-10 11-27 0-37l-72-73c-10-10-27-10-37 1-10 9-11 23-5 33l-31 32-24-23c5-10 3-23-6-31l-112-113c-6-5-13-8-20-8-7 0-14 3-20 8-11 11-11 29 0 40z"/>
<glyph glyph-name="404" unicode="&#57379;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-277-394l0 32-60 0 0 20 51 83 39 0 0-79 16 0 0-24-16 0 0-32z m0 56l0 29c0 9 0 17 1 26l-1 0c-4-9-8-17-13-26l-18-29 0 0z m159 12c0-42-17-71-51-71-35 0-51 32-51 70 0 39 17 70 52 70 36 0 50-32 50-69z m-70-1c0-31 7-46 20-46 12 0 19 16 19 46 0 30-7 46-20 46-11 0-19-15-19-46z m142-67l0 32-60 0 0 20 51 83 39 0 0-79 16 0 0-24-16 0 0-32z m0 56l0 29c0 9 0 17 1 26l-1 0c-4-9-8-17-12-26l-19-29 0 0z"/>
<glyph glyph-name="list-bullet" unicode="&#57380;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-14-116l-166 0c-8 0-14-6-14-14l0-28c0-8 6-14 14-14l166 0c8 0 14 6 14 14l0 28c0 8-6 14-14 14z m0-112l-166 0c-8 0-14-6-14-14l0-28c0-8 6-14 14-14l166 0c8 0 14 6 14 14l0 28c0 8-6 14-14 14z m0-113l-166 0c-8 0-14-6-14-14l0-28c0-7 6-14 14-14l166 0c8 0 14 7 14 14l0 28c0 8-6 14-14 14z m-225 225l-28 0c-8 0-14-6-14-14l0-28c0-8 6-14 14-14l28 0c8 0 14 6 14 14l0 28c0 8-6 14-14 14z m0-112l-28 0c-8 0-14-6-14-14l0-28c0-8 6-14 14-14l28 0c8 0 14 6 14 14l0 28c0 8-6 14-14 14z m0-113l-28 0c-8 0-14-6-14-14l0-28c0-7 6-14 14-14l28 0c8 0 14 7 14 14l0 28c0 8-6 14-14 14z"/>
<glyph glyph-name="analytics1" unicode="&#57381;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-366-212c11 0 21 4 28 12l98-39c3-19 19-34 40-34 21 0 39 17 39 39 0 1 0 2 0 3l95 55c7-6 16-10 26-10 22 0 40 18 40 40 0 22-18 40-40 40-22 0-39-18-39-40 0-2 0-4 0-6l-93-54c-7 7-17 12-28 12-14 0-27-7-34-18l-92 36c0 1 0 2 0 3 0 22-18 40-40 40-22 0-40-18-40-40 0-21 18-39 40-39z m326 79c7 0 13-6 13-13 0-7-6-13-13-13-7 0-13 6-13 13 0 7 6 13 13 13z m-160-88c7 0 12-6 12-13 0-7-5-13-12-13-8 0-13 6-13 13 0 7 5 13 13 13z m-166 61c7 0 13-5 13-13 0-7-6-12-13-12-7 0-13 5-13 12 0 8 6 13 13 13z m306-77c-9 0-17 2-24 6l-67-39c-2-22-7-30-29-34l0-93 149 0 0 166c-6-4-21-6-29-6z m-181-42l-70 27c-8-5-17-8-26-8-8 0-11 3-17 7l0-144 143 0 0 93c-17 2-25 6-30 25z"/>
<glyph glyph-name="title" unicode="&#57382;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-344-283l-37 0 0 28 106 0 0-28-37 0 0-112-32 0z m117 16c0-8-6-15-16-15-10 0-17 7-17 15 0 9 7 16 17 16 10 0 16-7 16-16z m-31-128l0 100 30 0 0-100z m89 129l0-29 22 0 0-23-22 0 0-36c0-12 3-17 12-17 4 0 7 0 9 0l1-23c-4-2-12-3-21-3-10 0-18 4-23 9-6 6-9 15-9 30l0 40-13 0 0 23 13 0 0 22z m35 17l29 0 0-146-29 0z m69-106c1-12 13-19 28-19 10 0 19 2 27 4l5-21c-11-4-23-6-37-6-34 0-53 20-53 51 0 26 16 54 50 54 33 0 45-26 45-50 0-6-1-10-1-13z m36 22c0 7-3 20-17 20-13 0-19-12-20-20z"/>
<glyph glyph-name="advertise" unicode="&#57383;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-2-249l-47 68c6 12 5 25-3 36-7 10-19 16-32 16l-46 68c-2 4-5 5-8 5-4-2-6-6-6-13 2-79-75-125-76-126l-49-31c-9-7-23-26-9-48l23-33c0-1 15-24 38-18 3 1 7 3 10 5 0 0 5 5 14-9l40-60c2-3 8-9 16-7 1 0 3 1 4 2 0 0 15 9 15 18 0 15-28 45-35 52-30 27-7 41-7 42 19 12 38 21 58 27 52 14 88-4 89-4 0 0 5-3 9-1 3 1 3 2 4 3 1 3-1 6-2 8z"/>
<glyph glyph-name="comment" unicode="&#57384;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m6-195c0-44-20-83-51-114l0-75-75 29c-26-10-54-15-84-15-117 0-211 78-211 175 0 96 94 174 211 174 116 0 210-78 210-174z"/>
<glyph glyph-name="pin" unicode="&#57385;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-33-222c-18 16-42 24-65 24l-70 70-50-50-51-51 70-70c0-23 8-46 24-65 3-3 8-3 11 0l66 66 66 66c3 2 2 7-1 10z m33-166c-3 10-9 26-13 39-1 4-4 8-7 12l-46 45-39-39 46-46c3-3 7-5 11-7 13-4 30-9 39-12 6-2 10 2 9 8z m-263 254l-60-60c-3-3-3-7 0-10l21-22c3-2 8-2 10 0l61 61 60 60c3 3 3 7 0 10l-22 22c-2 2-7 2-10 0z"/>
<glyph glyph-name="sitemap" unicode="&#57386;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-18-322l-10 0 0 39c0 15-12 27-27 27l-106 0 0 42 50 0c8 0 14 6 14 14l0 60c0 8-6 15-14 15l-119 0c-8 0-15-7-15-15l0-60c0-8 7-14 15-14l50 0 0-42-106 0c-15 0-28-12-28-27l0-39-10 0c-9 0-17-8-17-18l0-39c0-10 8-18 17-18l40 0c10 0 18 8 18 18l0 39c0 10-8 18-18 18l-10 0 0 39c0 4 3 8 8 8l106 0 0-47-10 0c-10 0-18-8-18-18l0-39c0-10 8-18 18-18l39 0c10 0 18 8 18 18l0 39c0 10-8 18-18 18l-10 0 0 47 106 0c4 0 8-4 8-8l0-39-10 0c-10 0-18-8-18-18l0-39c0-10 8-18 18-18l39 0c10 0 18 8 18 18l0 39c0 10-8 18-18 18z"/>
<glyph glyph-name="woo" unicode="&#57387;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-8-271c-6 11-15 17-27 20-4 0-7 1-10 1-16 0-29-9-39-26-9-14-14-30-14-48 0-13 3-24 8-33 7-11 16-18 28-20 3-1 6-1 9-1 16 0 30 8 40 25 9 15 13 31 13 48 0 14-3 25-8 34z m-22-47c-2-11-6-20-12-25-5-5-10-7-14-6-4 1-8 5-10 11-2 6-3 11-3 16 0 4 0 8 1 12 1 7 4 14 9 20 5 9 11 12 18 11 4-1 7-5 10-11 2-5 3-11 3-16 0-4-1-8-2-12z m-85 47c-6 11-15 17-27 20-3 0-6 1-9 1-16 0-30-9-40-26-9-14-13-30-13-48 0-13 3-24 8-33 6-11 15-18 27-20 3-1 6-1 9-1 17 0 30 8 40 25 9 15 13 31 13 48 0 14-2 25-8 34z m-21-47c-2-11-7-20-13-25-5-5-10-7-14-6-4 1-7 5-10 11-2 6-3 11-3 16 0 4 1 8 1 12 2 7 5 14 9 20 6 9 12 12 18 11 4-1 8-5 10-11 2-5 3-11 3-16 0-4 0-8-1-12z m-237 74c2 3 6 4 10 5 9 0 14-4 15-12 5-36 11-66 17-91l37 71c4 7 8 10 13 10 8 1 12-4 14-14 4-22 10-42 16-58 5 43 12 74 23 93 2 5 6 8 11 8 4 0 7-1 11-3 3-3 5-6 5-10 0-3 0-6-2-8-6-13-12-33-16-62-5-27-6-49-5-64 0-5 0-8-2-12-2-3-5-5-9-6-5 0-9 2-14 7-15 16-28 40-37 72-11-22-19-38-25-49-10-19-18-29-25-30-5 0-9 4-12 12-9 22-18 65-28 129-1 5 0 8 3 12z"/>
<glyph glyph-name="key" unicode="&#57388;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-109-49c-61 0-110-49-110-110 0-13 3-25 7-38l-135-135 0-65 64 0 0 39 38 0 0 38 39 0 58 58c12-3 24-6 39-6 60 0 109 49 109 109 0 61-49 110-109 110z m32-116c-22 0-39 17-39 39 0 21 17 38 39 38 22 0 38-17 38-38 0-22-16-39-38-39z"/>
<glyph glyph-name="bbpress" unicode="&#57389;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-200-319l57 56c0 0 104 0 91-134-180 0-297 0-297 0 0 0-21 128 92 134 41-41 57-56 57-56z m100 62l14 15c0 0 86 14 86-113-19-1-34 0-34 0 0 0-3 79-66 98z m-37 177c-15 0-29-4-41-12 42-10 73-48 73-93 0-18-5-36-14-50 35 8 61 39 61 76 0 44-35 79-79 79z m15-106c0-43-35-78-79-78-43 0-78 35-78 78 0 44 35 79 78 79 44 0 79-35 79-79z"/>
<glyph glyph-name="translation" unicode="&#57390;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-325-141l85 0c-2-15-10-32-24-49-9 14-15 28-18 37-1 2-3 4-5 4l-14 0c-2 0-4-1-5-3-1-1-1-3-1-5 4-10 11-31 25-52-16-16-33-28-40-32-2-2-3-5-1-8l7-11c1-2 2-3 3-3 1 0 1 0 2 0 1 0 2 0 3 1 7 4 24 16 42 34 7-7 22-20 32-26 1-1 3-2 5-1 1 0 3 1 3 3l6 13c1 3 0 6-3 7-6 4-17 11-27 22 21 24 33 47 35 69l5 0c3 0 5 3 5 6l0 15c0 3-2 6-5 6l-45 0 0 8c0 3-3 5-6 5l-14 0c-3 0-6-2-6-5l0-8-44 0c-4 0-6-3-6-6l0-15c0-3 2-6 6-6z m227-110c-1 3-3 4-6 4l-31 0c-3 0-5-1-6-4l-38-124c-1-2 0-4 1-5 1-2 3-3 4-3l20 0c3 0 5 2 6 5l8 30 39 0 9-30c1-3 3-5 6-5l21 0c2 0 3 1 5 3 1 1 1 3 0 5z m-37-74l14 55 0 0 16-55z m-253 43l14-3 0-3c3-38 23-71 56-91 18-12 40-18 62-18l0 0c0 0 0 0 0 0 15 0 31 3 45 9 1 1 2 1 2 2 0 1 0 2 0 3l-10 21c0 0-1 1-1 1-1 1-3 1-3 0-11-4-22-6-34-6-16 0-32 4-46 13-20 12-34 32-39 55l-2 7 13-3c0 0 0 0 1 0 0 0 0 0 0 0 1 0 2 0 2 1 1 1 2 2 1 3l-16 56c-1 1-2 2-3 2 0 1 0 1 0 1l0 0c-2 0-3-1-3-2l-40-42c-1-1-2-2-1-3 0-2 1-3 2-3z m217 131c0-1 0-2 1-2 1 0 2-1 3 0 11 4 22 6 33 6 16 0 32-4 46-13 20-12 35-32 40-55l2-7-14 4c0 0 0 0 0 0 0 0 0 0 0 0-1 0-2-1-3-1-1-1-1-3-1-4l17-56c0-1 1-2 3-2 0 0 0 0 0 0l0 0c1-1 2 0 3 1l40 42c1 1 1 2 1 4 0 1-2 2-3 2l-13 3 0 3c-3 38-24 71-56 91-19 12-40 18-62 18l0 0c0 0 0 0 0 0-16 0-31-3-45-9-1-1-2-1-2-2-1-1-1-2 0-3z"/>
<glyph glyph-name="database" unicode="&#57391;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-136-67c-75 0-136-22-136-50l0-40c0-28 61-50 136-50 75 0 136 22 136 50l0 40c0 28-61 50-136 50z m0-163c-71 0-131 20-136 46 0-2 0-68 0-68 0-27 61-49 136-49 75 0 136 22 136 49 0 0 0 66 0 68-5-26-64-46-136-46z m136-50c-5-26-64-46-136-46-71 0-131 20-136 46l0-67c0-28 61-50 136-50 75 0 136 22 136 50z"/>
<glyph glyph-name="font" unicode="&#57392;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-14-208l-218 0-18 38c-2 5-6 8-11 8l-4 0c-5 0-10-3-12-8l-17-38-87 0 0-4 85 0-66-143c-1-4-1-9 1-12 1-2 2-3 4-4l-24 0 0-4 367 0 0 4-24 0c0 1 1 1 2 2 2 2 3 5 3 9l0 91c-1 33-21 54-53 57l72 0z m-251-4l4 0 35-76-74 0z m-70-154l23 50 99 0 23-50c1-2 3-4 5-5l-155 0c2 1 4 3 5 5z m274 5c0-4 3-8 6-10l-33 0c10 2 19 6 27 12z m0 45c-9-20-23-29-47-29-14 0-29 6-29 23 0 17 22 19 35 19l41 0z m-93 65l1-2c2-3 5-5 9-5 3 0 6 0 9 2 15 12 27 17 41 17 29 0 33-17 33-30l0-6-41 0c-46 0-63-24-63-47 0-24 16-43 40-49l-43 0c2 1 3 2 4 4 2 3 2 8 1 12l-67 143 128 0c-17-1-33-8-50-21-5-5-6-12-2-18z"/>
<glyph glyph-name="export-import" unicode="&#57393;" d="M512 398l0 113-512 0 1-510 118 0 0 42-77 0 0 428 428 0 0-73z m-24-352l-300 0c-7 0-13-6-13-14l0-17c0-8 6-14 13-14l300 0c7 0 13 6 13 14l0 17c0 8-6 14-13 14z m-62 256c-2 2-5 4-8 4-3 0-6-2-8-4l-82-81c-4-5-4-12 0-17l12-11c4-5 12-5 16 0l42 42 0-157c0-7 6-12 12-12l16 0c7 0 12 5 12 12l0 157 42-42c4-5 12-5 16 0l12 11c4 5 4 12 0 17z m-179-233c2-2 5-3 8-3 3 0 6 1 9 3l81 82c4 4 4 12 0 16l-11 12c-5 4-13 4-17 0l-42-42 0 157c0 6-5 12-12 12l-16 0c-6 0-12-6-12-12l0-157-41 42c-5 4-13 4-17 0l-11-12c-5-4-5-12 0-17z"/>
<glyph glyph-name="advertise2" unicode="&#57395;" d="M465 221l-69 102c8 18 6 38-5 54-10 16-28 25-47 24l-70 102c-3 6-7 8-12 7-6-2-8-9-9-20 3-117-111-186-112-187l-74-47c-14-11-35-39-13-71l33-50c1-1 24-35 57-26 5 1 10 4 15 7 0 0 7 7 21-13l61-90c2-5 10-14 22-11 3 1 5 2 7 3 0 0 23 14 23 28 0 21-43 67-54 76-45 41-9 63-9 63 28 19 57 33 86 41 78 21 132-6 132-7 0 0 9-4 15-1 3 1 5 4 5 5 2 4-1 9-3 11z m-215-179l6 5-5 6 7 5 14-19-18-14-5 6 6 5z"/>
<glyph glyph-name="gear" unicode="&#57394;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-12-206l-33 5c-3 10-6 19-11 28l22 26c4 6 4 14-1 19l-13 15c-5 5-13 6-19 3l-28-18c-12 9-26 15-41 19l-6 33c-1 7-7 12-14 12l-20 0c-7 0-13-5-14-12l-6-33c-12-3-24-8-35-15l-27 19c-6 4-13 4-18-1l-14-14c-5-5-6-13-2-19l19-27c-6-11-11-22-14-35l-34-5c-7-1-12-7-12-15l0-19c0-7 5-13 12-15l34-5c2-10 6-20 11-29l-21-26c-5-6-4-14 0-19l13-15c5-5 13-6 19-2l29 18c12-9 25-15 40-18l6-34c1-7 7-12 14-12l20 0c7 0 13 5 14 12l6 34c12 3 24 7 34 14l28-20c6-4 14-4 19 1l14 14c5 5 5 13 1 19l-20 28c7 11 12 22 15 35l33 5c7 2 12 8 12 15l0 19c0 8-5 14-12 15z m-154-87c-34 0-62 28-62 63 0 34 28 62 62 62 35 0 63-28 63-62 0-35-28-63-63-63z"/>
<glyph glyph-name="publisher" unicode="&#57396;" d="M249 306c57 0 103 46 103 103 0 57-46 103-103 103-56 0-102-46-102-103 0-57 46-103 102-103z m118-25l121 52 0-160c0-49-36-103-81-122l-120-51 0 160c0 48 36 103 80 121z m-142-121c0 48-36 103-80 121l-121 52 0-160c0-49 36-103 81-122l120-51z"/>
<glyph glyph-name="typekit" unicode="&#57397;" d="M512 511l-512 0 1-509 101 0 0 41-60 0 0 429 428 0 0-124 42 0z m-248-510l-45 0 0 175-57 0 0 38 159 0 0-38-57 0z m129 88l19 25 46 49 50 0-64-70 68-92-52 0-46 66-19-15 0-51-45 0 0 226 45 0 0-100z"/>
<glyph glyph-name="check" unicode="&#57398;" d="M512 398l-42 0 0 73-428 0 0-428 77 0 0-42-119 0 0 510 512 0z m0-201c0-6-2-10-6-14l-176-176c-4-4-8-6-14-6-5 0-10 2-14 6l-101 102c-4 4-6 8-6 14 0 5 2 10 6 14l27 28c4 3 9 5 14 5 6 0 10-2 14-5l60-61 134 135c4 3 9 5 14 5 6 0 10-2 14-5l28-28c4-4 6-9 6-14z"/>
<glyph glyph-name="skyscraper" unicode="&#57399;" d="M108 511l-108 0 0-310 108 0z m273 0l0-510-250 0 0 510z m-16-17l-218 0 0-476 218 0z m147 17l-108 0 0-310 108 0z"/>
<glyph glyph-name="checked-grid" unicode="&#57400;" d="M296 511l216 0 0-217-216 0z m-296-293l216 0 0-217-216 0z m329 259l0-152 152 0 0 152z m-297-291l0-153 153 0 0 153z m-32 325l216 0 0-217-216 0z m32-32l0-153 153 0 0 153z m264-261l216 0 0-217-216 0z"/>
<glyph glyph-name="newsletter-pack" unicode="&#57401;" d="M512 325l0-279c0-13-4-24-13-33-9-9-20-13-33-13l-420 0c-13 0-24 4-33 13-9 9-13 20-13 33l0 279c0 3 1 5 3 7 2 1 5 5 11 10 6 5 10 9 12 10 2 2 6 5 13 11 7 5 13 11 20 16 7 5 16 12 28 21 11 8 25 19 41 30 15 12 34 25 55 40 1 1 6 5 15 12 9 7 15 12 20 15 5 3 11 6 18 10 8 3 14 5 20 5 6 0 12-2 20-5 7-4 14-7 18-10 5-4 12-9 21-15 8-7 13-11 14-12 21-15 40-28 55-40 16-11 30-22 41-30 12-9 21-16 28-21 7-5 13-11 20-16 7-6 11-9 13-11 2-1 6-5 12-10 6-5 9-9 11-10 2-2 3-4 3-7z m-161-167c50 36 83 60 98 72 3 2 4 3 4 6 0 2 0 4-2 7l-11 14c-1 3-3 4-6 4-2 0-4 0-7-2-44-32-76-56-98-71-1-1-5-5-14-11-9-7-16-12-21-15-5-4-11-7-18-10-8-4-14-6-20-6-6 0-12 2-20 6-7 3-13 6-18 10-5 3-12 8-21 15-9 6-13 10-14 11-36 25-69 49-98 71-3 2-5 2-7 2-3 0-5-1-6-4l-11-14c-2-3-2-5-2-7 0-3 1-4 4-6 15-12 48-36 98-72 2-2 7-5 14-11 8-6 14-10 19-13 5-4 11-7 18-12 8-4 15-7 22-9 8-2 15-3 22-3 7 0 14 1 22 3 7 2 14 5 22 10 8 4 14 8 19 11 4 3 10 8 18 14 8 6 13 9 14 10z"/>
<glyph glyph-name="inject" unicode="&#57402;" d="M512 398l0 113-512 0 0-510 119 0 0 42-77 0 0 428 428 0 0-73z m-23-181l23 25-93 93-24-23 35-35-35-35-35 35-118-119c-22-22-25-55-10-80l-54-53 24-24 51 52c10-7 22-10 34-10 18 0 35 7 46 20l119 119-35 35 35 35z m-129-80l-76 16 76 77 47-47z"/>
</font></defs></svg>
libs/better-framework/assets/fonts/fontawesome-webfont.svg000064400001543733151214002610020132 0ustar00<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg>
<metadata>
Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016
 By ,,,
Copyright Dave Gandy 2016. All rights reserved.
</metadata>
<defs>
<font id="FontAwesome" horiz-adv-x="1536" >
  <font-face 
    font-family="FontAwesome"
    font-weight="400"
    font-stretch="normal"
    units-per-em="1792"
    panose-1="0 0 0 0 0 0 0 0 0 0"
    ascent="1536"
    descent="-256"
    bbox="-1.02083 -256.962 2304.6 1537.02"
    underline-thickness="0"
    underline-position="0"
    unicode-range="U+0020-F500"
  />
<missing-glyph horiz-adv-x="896" 
d="M224 112h448v1312h-448v-1312zM112 0v1536h672v-1536h-672z" />
    <glyph glyph-name=".notdef" horiz-adv-x="896" 
d="M224 112h448v1312h-448v-1312zM112 0v1536h672v-1536h-672z" />
    <glyph glyph-name=".null" horiz-adv-x="0" 
 />
    <glyph glyph-name="nonmarkingreturn" horiz-adv-x="597" 
 />
    <glyph glyph-name="space" unicode=" " horiz-adv-x="448" 
 />
    <glyph glyph-name="dieresis" unicode="&#xa8;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="copyright" unicode="&#xa9;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="registered" unicode="&#xae;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="acute" unicode="&#xb4;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="AE" unicode="&#xc6;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="Oslash" unicode="&#xd8;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="trademark" unicode="&#x2122;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="infinity" unicode="&#x221e;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="notequal" unicode="&#x2260;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="glass" unicode="&#xf000;" horiz-adv-x="1792" 
d="M1699 1350q0 -35 -43 -78l-632 -632v-768h320q26 0 45 -19t19 -45t-19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45t45 19h320v768l-632 632q-43 43 -43 78q0 23 18 36.5t38 17.5t43 4h1408q23 0 43 -4t38 -17.5t18 -36.5z" />
    <glyph glyph-name="music" unicode="&#xf001;" 
d="M1536 1312v-1120q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v537l-768 -237v-709q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89
t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v967q0 31 19 56.5t49 35.5l832 256q12 4 28 4q40 0 68 -28t28 -68z" />
    <glyph glyph-name="search" unicode="&#xf002;" horiz-adv-x="1664" 
d="M1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -52 -38 -90t-90 -38q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5
t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
    <glyph glyph-name="envelope" unicode="&#xf003;" horiz-adv-x="1792" 
d="M1664 32v768q-32 -36 -69 -66q-268 -206 -426 -338q-51 -43 -83 -67t-86.5 -48.5t-102.5 -24.5h-1h-1q-48 0 -102.5 24.5t-86.5 48.5t-83 67q-158 132 -426 338q-37 30 -69 66v-768q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1664 1083v11v13.5t-0.5 13
t-3 12.5t-5.5 9t-9 7.5t-14 2.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5q0 -168 147 -284q193 -152 401 -317q6 -5 35 -29.5t46 -37.5t44.5 -31.5t50.5 -27.5t43 -9h1h1q20 0 43 9t50.5 27.5t44.5 31.5t46 37.5t35 29.5q208 165 401 317q54 43 100.5 115.5t46.5 131.5z
M1792 1120v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
    <glyph glyph-name="heart" unicode="&#xf004;" horiz-adv-x="1792" 
d="M896 -128q-26 0 -44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124t127 -344q0 -221 -229 -450l-623 -600
q-18 -18 -44 -18z" />
    <glyph glyph-name="star" unicode="&#xf005;" horiz-adv-x="1664" 
d="M1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -21 -10.5 -35.5t-30.5 -14.5q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455
l502 -73q56 -9 56 -46z" />
    <glyph glyph-name="star_empty" unicode="&#xf006;" horiz-adv-x="1664" 
d="M1137 532l306 297l-422 62l-189 382l-189 -382l-422 -62l306 -297l-73 -421l378 199l377 -199zM1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -50 -41 -50q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500
l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455l502 -73q56 -9 56 -46z" />
    <glyph glyph-name="user" unicode="&#xf007;" horiz-adv-x="1280" 
d="M1280 137q0 -109 -62.5 -187t-150.5 -78h-854q-88 0 -150.5 78t-62.5 187q0 85 8.5 160.5t31.5 152t58.5 131t94 89t134.5 34.5q131 -128 313 -128t313 128q76 0 134.5 -34.5t94 -89t58.5 -131t31.5 -152t8.5 -160.5zM1024 1024q0 -159 -112.5 -271.5t-271.5 -112.5
t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" />
    <glyph glyph-name="film" unicode="&#xf008;" horiz-adv-x="1920" 
d="M384 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 320v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 704v128q0 26 -19 45t-45 19h-128
q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 -64v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM384 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45
t45 -19h128q26 0 45 19t19 45zM1792 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 704v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1792 320v128
q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 704v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19
t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1920 1248v-1344q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1344q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
    <glyph glyph-name="th_large" unicode="&#xf009;" horiz-adv-x="1664" 
d="M768 512v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM768 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 512v-384q0 -52 -38 -90t-90 -38
h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
    <glyph glyph-name="th" unicode="&#xf00a;" horiz-adv-x="1792" 
d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 288v-192q0 -40 -28 -68t-68 -28h-320
q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28
h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192
q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68z" />
    <glyph glyph-name="th_list" unicode="&#xf00b;" horiz-adv-x="1792" 
d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-960
q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28
h960q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68z" />
    <glyph glyph-name="ok" unicode="&#xf00c;" horiz-adv-x="1792" 
d="M1671 970q0 -40 -28 -68l-724 -724l-136 -136q-28 -28 -68 -28t-68 28l-136 136l-362 362q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -295l656 657q28 28 68 28t68 -28l136 -136q28 -28 28 -68z" />
    <glyph glyph-name="remove" unicode="&#xf00d;" horiz-adv-x="1408" 
d="M1298 214q0 -40 -28 -68l-136 -136q-28 -28 -68 -28t-68 28l-294 294l-294 -294q-28 -28 -68 -28t-68 28l-136 136q-28 28 -28 68t28 68l294 294l-294 294q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -294l294 294q28 28 68 28t68 -28l136 -136q28 -28 28 -68
t-28 -68l-294 -294l294 -294q28 -28 28 -68z" />
    <glyph glyph-name="zoom_in" unicode="&#xf00e;" horiz-adv-x="1664" 
d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-224q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v224h-224q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h224v224q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-224h224
q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5
t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
    <glyph glyph-name="zoom_out" unicode="&#xf010;" horiz-adv-x="1664" 
d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-576q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h576q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5z
M1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z
" />
    <glyph glyph-name="off" unicode="&#xf011;" 
d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61t-298 61t-245 164t-164 245t-61 298q0 182 80.5 343t226.5 270q43 32 95.5 25t83.5 -50q32 -42 24.5 -94.5t-49.5 -84.5q-98 -74 -151.5 -181t-53.5 -228q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5
t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5q0 121 -53.5 228t-151.5 181q-42 32 -49.5 84.5t24.5 94.5q31 43 84 50t95 -25q146 -109 226.5 -270t80.5 -343zM896 1408v-640q0 -52 -38 -90t-90 -38t-90 38t-38 90v640q0 52 38 90t90 38t90 -38t38 -90z" />
    <glyph glyph-name="signal" unicode="&#xf012;" horiz-adv-x="1792" 
d="M256 96v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 224v-320q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 480v-576q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23
v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1408 864v-960q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1376v-1472q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1472q0 14 9 23t23 9h192q14 0 23 -9t9 -23z" />
    <glyph glyph-name="cog" unicode="&#xf013;" 
d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1536 749v-222q0 -12 -8 -23t-20 -13l-185 -28q-19 -54 -39 -91q35 -50 107 -138q10 -12 10 -25t-9 -23q-27 -37 -99 -108t-94 -71q-12 0 -26 9l-138 108q-44 -23 -91 -38
q-16 -136 -29 -186q-7 -28 -36 -28h-222q-14 0 -24.5 8.5t-11.5 21.5l-28 184q-49 16 -90 37l-141 -107q-10 -9 -25 -9q-14 0 -25 11q-126 114 -165 168q-7 10 -7 23q0 12 8 23q15 21 51 66.5t54 70.5q-27 50 -41 99l-183 27q-13 2 -21 12.5t-8 23.5v222q0 12 8 23t19 13
l186 28q14 46 39 92q-40 57 -107 138q-10 12 -10 24q0 10 9 23q26 36 98.5 107.5t94.5 71.5q13 0 26 -10l138 -107q44 23 91 38q16 136 29 186q7 28 36 28h222q14 0 24.5 -8.5t11.5 -21.5l28 -184q49 -16 90 -37l142 107q9 9 24 9q13 0 25 -10q129 -119 165 -170q7 -8 7 -22
q0 -12 -8 -23q-15 -21 -51 -66.5t-54 -70.5q26 -50 41 -98l183 -28q13 -2 21 -12.5t8 -23.5z" />
    <glyph glyph-name="trash" unicode="&#xf014;" horiz-adv-x="1408" 
d="M512 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM768 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1024 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576
q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1152 76v948h-896v-948q0 -22 7 -40.5t14.5 -27t10.5 -8.5h832q3 0 10.5 8.5t14.5 27t7 40.5zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832
q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" />
    <glyph glyph-name="home" unicode="&#xf015;" horiz-adv-x="1664" 
d="M1408 544v-480q0 -26 -19 -45t-45 -19h-384v384h-256v-384h-384q-26 0 -45 19t-19 45v480q0 1 0.5 3t0.5 3l575 474l575 -474q1 -2 1 -6zM1631 613l-62 -74q-8 -9 -21 -11h-3q-13 0 -21 7l-692 577l-692 -577q-12 -8 -24 -7q-13 2 -21 11l-62 74q-8 10 -7 23.5t11 21.5
l719 599q32 26 76 26t76 -26l244 -204v195q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-408l219 -182q10 -8 11 -21.5t-7 -23.5z" />
    <glyph glyph-name="file_alt" unicode="&#xf016;" 
d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
" />
    <glyph glyph-name="time" unicode="&#xf017;" 
d="M896 992v-448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640
q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="road" unicode="&#xf018;" horiz-adv-x="1920" 
d="M1111 540v4l-24 320q-1 13 -11 22.5t-23 9.5h-186q-13 0 -23 -9.5t-11 -22.5l-24 -320v-4q-1 -12 8 -20t21 -8h244q12 0 21 8t8 20zM1870 73q0 -73 -46 -73h-704q13 0 22 9.5t8 22.5l-20 256q-1 13 -11 22.5t-23 9.5h-272q-13 0 -23 -9.5t-11 -22.5l-20 -256
q-1 -13 8 -22.5t22 -9.5h-704q-46 0 -46 73q0 54 26 116l417 1044q8 19 26 33t38 14h339q-13 0 -23 -9.5t-11 -22.5l-15 -192q-1 -14 8 -23t22 -9h166q13 0 22 9t8 23l-15 192q-1 13 -11 22.5t-23 9.5h339q20 0 38 -14t26 -33l417 -1044q26 -62 26 -116z" />
    <glyph glyph-name="download_alt" unicode="&#xf019;" horiz-adv-x="1664" 
d="M1280 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 416v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h465l135 -136
q58 -56 136 -56t136 56l136 136h464q40 0 68 -28t28 -68zM1339 985q17 -41 -14 -70l-448 -448q-18 -19 -45 -19t-45 19l-448 448q-31 29 -14 70q17 39 59 39h256v448q0 26 19 45t45 19h256q26 0 45 -19t19 -45v-448h256q42 0 59 -39z" />
    <glyph glyph-name="download" unicode="&#xf01a;" 
d="M1120 608q0 -12 -10 -24l-319 -319q-11 -9 -23 -9t-23 9l-320 320q-15 16 -7 35q8 20 30 20h192v352q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-352h192q14 0 23 -9t9 -23zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273
t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="upload" unicode="&#xf01b;" 
d="M1118 660q-8 -20 -30 -20h-192v-352q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v352h-192q-14 0 -23 9t-9 23q0 12 10 24l319 319q11 9 23 9t23 -9l320 -320q15 -16 7 -35zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198
t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="inbox" unicode="&#xf01c;" 
d="M1023 576h316q-1 3 -2.5 8.5t-2.5 7.5l-212 496h-708l-212 -496q-1 -3 -2.5 -8.5t-2.5 -7.5h316l95 -192h320zM1536 546v-482q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v482q0 62 25 123l238 552q10 25 36.5 42t52.5 17h832q26 0 52.5 -17t36.5 -42l238 -552
q25 -61 25 -123z" />
    <glyph glyph-name="play_circle" unicode="&#xf01d;" 
d="M1184 640q0 -37 -32 -55l-544 -320q-15 -9 -32 -9q-16 0 -32 8q-32 19 -32 56v640q0 37 32 56q33 18 64 -1l544 -320q32 -18 32 -55zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640
q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="repeat" unicode="&#xf01e;" 
d="M1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l138 138q-148 137 -349 137q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5q119 0 225 52t179 147q7 10 23 12q15 0 25 -9
l137 -138q9 -8 9.5 -20.5t-7.5 -22.5q-109 -132 -264 -204.5t-327 -72.5q-156 0 -298 61t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q147 0 284.5 -55.5t244.5 -156.5l130 129q29 31 70 14q39 -17 39 -59z" />
    <glyph glyph-name="refresh" unicode="&#xf021;" 
d="M1511 480q0 -5 -1 -7q-64 -268 -268 -434.5t-478 -166.5q-146 0 -282.5 55t-243.5 157l-129 -129q-19 -19 -45 -19t-45 19t-19 45v448q0 26 19 45t45 19h448q26 0 45 -19t19 -45t-19 -45l-137 -137q71 -66 161 -102t187 -36q134 0 250 65t186 179q11 17 53 117
q8 23 30 23h192q13 0 22.5 -9.5t9.5 -22.5zM1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-26 0 -45 19t-19 45t19 45l138 138q-148 137 -349 137q-134 0 -250 -65t-186 -179q-11 -17 -53 -117q-8 -23 -30 -23h-199q-13 0 -22.5 9.5t-9.5 22.5v7q65 268 270 434.5t480 166.5
q146 0 284 -55.5t245 -156.5l130 129q19 19 45 19t45 -19t19 -45z" />
    <glyph glyph-name="list_alt" unicode="&#xf022;" horiz-adv-x="1792" 
d="M384 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
M384 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1536 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5z
M1536 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5zM1536 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5
t9.5 -22.5zM1664 160v832q0 13 -9.5 22.5t-22.5 9.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1792 1248v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47
t47 -113z" />
    <glyph glyph-name="lock" unicode="&#xf023;" horiz-adv-x="1152" 
d="M320 768h512v192q0 106 -75 181t-181 75t-181 -75t-75 -181v-192zM1152 672v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v192q0 184 132 316t316 132t316 -132t132 -316v-192h32q40 0 68 -28t28 -68z" />
    <glyph glyph-name="flag" unicode="&#xf024;" horiz-adv-x="1792" 
d="M320 1280q0 -72 -64 -110v-1266q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v1266q-64 38 -64 110q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -25 -12.5 -38.5t-39.5 -27.5q-215 -116 -369 -116q-61 0 -123.5 22t-108.5 48
t-115.5 48t-142.5 22q-192 0 -464 -146q-17 -9 -33 -9q-26 0 -45 19t-19 45v742q0 32 31 55q21 14 79 43q236 120 421 120q107 0 200 -29t219 -88q38 -19 88 -19q54 0 117.5 21t110 47t88 47t54.5 21q26 0 45 -19t19 -45z" />
    <glyph glyph-name="headphones" unicode="&#xf025;" horiz-adv-x="1664" 
d="M1664 650q0 -166 -60 -314l-20 -49l-185 -33q-22 -83 -90.5 -136.5t-156.5 -53.5v-32q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-32q71 0 130 -35.5t93 -95.5l68 12q29 95 29 193q0 148 -88 279t-236.5 209t-315.5 78
t-315.5 -78t-236.5 -209t-88 -279q0 -98 29 -193l68 -12q34 60 93 95.5t130 35.5v32q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v32q-88 0 -156.5 53.5t-90.5 136.5l-185 33l-20 49q-60 148 -60 314q0 151 67 291t179 242.5
t266 163.5t320 61t320 -61t266 -163.5t179 -242.5t67 -291z" />
    <glyph glyph-name="volume_off" unicode="&#xf026;" horiz-adv-x="768" 
d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45z" />
    <glyph glyph-name="volume_down" unicode="&#xf027;" horiz-adv-x="1152" 
d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 36
t12 56.5t-12 56.5t-29 36t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142z" />
    <glyph glyph-name="volume_up" unicode="&#xf028;" horiz-adv-x="1664" 
d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 36
t12 56.5t-12 56.5t-29 36t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142zM1408 640q0 -153 -85 -282.5t-225 -188.5q-13 -5 -25 -5q-27 0 -46 19t-19 45q0 39 39 59q56 29 76 44q74 54 115.5 135.5t41.5 173.5t-41.5 173.5
t-115.5 135.5q-20 15 -76 44q-39 20 -39 59q0 26 19 45t45 19q13 0 26 -5q140 -59 225 -188.5t85 -282.5zM1664 640q0 -230 -127 -422.5t-338 -283.5q-13 -5 -26 -5q-26 0 -45 19t-19 45q0 36 39 59q7 4 22.5 10.5t22.5 10.5q46 25 82 51q123 91 192 227t69 289t-69 289
t-192 227q-36 26 -82 51q-7 4 -22.5 10.5t-22.5 10.5q-39 23 -39 59q0 26 19 45t45 19q13 0 26 -5q211 -91 338 -283.5t127 -422.5z" />
    <glyph glyph-name="qrcode" unicode="&#xf029;" horiz-adv-x="1408" 
d="M384 384v-128h-128v128h128zM384 1152v-128h-128v128h128zM1152 1152v-128h-128v128h128zM128 129h384v383h-384v-383zM128 896h384v384h-384v-384zM896 896h384v384h-384v-384zM640 640v-640h-640v640h640zM1152 128v-128h-128v128h128zM1408 128v-128h-128v128h128z
M1408 640v-384h-384v128h-128v-384h-128v640h384v-128h128v128h128zM640 1408v-640h-640v640h640zM1408 1408v-640h-640v640h640z" />
    <glyph glyph-name="barcode" unicode="&#xf02a;" horiz-adv-x="1792" 
d="M63 0h-63v1408h63v-1408zM126 1h-32v1407h32v-1407zM220 1h-31v1407h31v-1407zM377 1h-31v1407h31v-1407zM534 1h-62v1407h62v-1407zM660 1h-31v1407h31v-1407zM723 1h-31v1407h31v-1407zM786 1h-31v1407h31v-1407zM943 1h-63v1407h63v-1407zM1100 1h-63v1407h63v-1407z
M1226 1h-63v1407h63v-1407zM1352 1h-63v1407h63v-1407zM1446 1h-63v1407h63v-1407zM1635 1h-94v1407h94v-1407zM1698 1h-32v1407h32v-1407zM1792 0h-63v1408h63v-1408z" />
    <glyph glyph-name="tag" unicode="&#xf02b;" 
d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5
l715 -714q37 -39 37 -91z" />
    <glyph glyph-name="tags" unicode="&#xf02c;" horiz-adv-x="1920" 
d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5
l715 -714q37 -39 37 -91zM1899 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-36 0 -59 14t-53 45l470 470q37 37 37 90q0 52 -37 91l-715 714q-38 38 -102 64.5t-117 26.5h224q53 0 117 -26.5t102 -64.5l715 -714q37 -39 37 -91z" />
    <glyph glyph-name="book" unicode="&#xf02d;" horiz-adv-x="1664" 
d="M1639 1058q40 -57 18 -129l-275 -906q-19 -64 -76.5 -107.5t-122.5 -43.5h-923q-77 0 -148.5 53.5t-99.5 131.5q-24 67 -2 127q0 4 3 27t4 37q1 8 -3 21.5t-3 19.5q2 11 8 21t16.5 23.5t16.5 23.5q23 38 45 91.5t30 91.5q3 10 0.5 30t-0.5 28q3 11 17 28t17 23
q21 36 42 92t25 90q1 9 -2.5 32t0.5 28q4 13 22 30.5t22 22.5q19 26 42.5 84.5t27.5 96.5q1 8 -3 25.5t-2 26.5q2 8 9 18t18 23t17 21q8 12 16.5 30.5t15 35t16 36t19.5 32t26.5 23.5t36 11.5t47.5 -5.5l-1 -3q38 9 51 9h761q74 0 114 -56t18 -130l-274 -906
q-36 -119 -71.5 -153.5t-128.5 -34.5h-869q-27 0 -38 -15q-11 -16 -1 -43q24 -70 144 -70h923q29 0 56 15.5t35 41.5l300 987q7 22 5 57q38 -15 59 -43zM575 1056q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5
t-16.5 -22.5zM492 800q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5t-16.5 -22.5z" />
    <glyph glyph-name="bookmark" unicode="&#xf02e;" horiz-adv-x="1280" 
d="M1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
    <glyph glyph-name="print" unicode="&#xf02f;" horiz-adv-x="1664" 
d="M384 0h896v256h-896v-256zM384 640h896v384h-160q-40 0 -68 28t-28 68v160h-640v-640zM1536 576q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 576v-416q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-160q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68
v160h-224q-13 0 -22.5 9.5t-9.5 22.5v416q0 79 56.5 135.5t135.5 56.5h64v544q0 40 28 68t68 28h672q40 0 88 -20t76 -48l152 -152q28 -28 48 -76t20 -88v-256h64q79 0 135.5 -56.5t56.5 -135.5z" />
    <glyph glyph-name="camera" unicode="&#xf030;" horiz-adv-x="1920" 
d="M960 864q119 0 203.5 -84.5t84.5 -203.5t-84.5 -203.5t-203.5 -84.5t-203.5 84.5t-84.5 203.5t84.5 203.5t203.5 84.5zM1664 1280q106 0 181 -75t75 -181v-896q0 -106 -75 -181t-181 -75h-1408q-106 0 -181 75t-75 181v896q0 106 75 181t181 75h224l51 136
q19 49 69.5 84.5t103.5 35.5h512q53 0 103.5 -35.5t69.5 -84.5l51 -136h224zM960 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
    <glyph glyph-name="font" unicode="&#xf031;" horiz-adv-x="1664" 
d="M725 977l-170 -450q33 0 136.5 -2t160.5 -2q19 0 57 2q-87 253 -184 452zM0 -128l2 79q23 7 56 12.5t57 10.5t49.5 14.5t44.5 29t31 50.5l237 616l280 724h75h53q8 -14 11 -21l205 -480q33 -78 106 -257.5t114 -274.5q15 -34 58 -144.5t72 -168.5q20 -45 35 -57
q19 -15 88 -29.5t84 -20.5q6 -38 6 -57q0 -5 -0.5 -13.5t-0.5 -12.5q-63 0 -190 8t-191 8q-76 0 -215 -7t-178 -8q0 43 4 78l131 28q1 0 12.5 2.5t15.5 3.5t14.5 4.5t15 6.5t11 8t9 11t2.5 14q0 16 -31 96.5t-72 177.5t-42 100l-450 2q-26 -58 -76.5 -195.5t-50.5 -162.5
q0 -22 14 -37.5t43.5 -24.5t48.5 -13.5t57 -8.5t41 -4q1 -19 1 -58q0 -9 -2 -27q-58 0 -174.5 10t-174.5 10q-8 0 -26.5 -4t-21.5 -4q-80 -14 -188 -14z" />
    <glyph glyph-name="bold" unicode="&#xf032;" horiz-adv-x="1408" 
d="M555 15q74 -32 140 -32q376 0 376 335q0 114 -41 180q-27 44 -61.5 74t-67.5 46.5t-80.5 25t-84 10.5t-94.5 2q-73 0 -101 -10q0 -53 -0.5 -159t-0.5 -158q0 -8 -1 -67.5t-0.5 -96.5t4.5 -83.5t12 -66.5zM541 761q42 -7 109 -7q82 0 143 13t110 44.5t74.5 89.5t25.5 142
q0 70 -29 122.5t-79 82t-108 43.5t-124 14q-50 0 -130 -13q0 -50 4 -151t4 -152q0 -27 -0.5 -80t-0.5 -79q0 -46 1 -69zM0 -128l2 94q15 4 85 16t106 27q7 12 12.5 27t8.5 33.5t5.5 32.5t3 37.5t0.5 34v35.5v30q0 982 -22 1025q-4 8 -22 14.5t-44.5 11t-49.5 7t-48.5 4.5
t-30.5 3l-4 83q98 2 340 11.5t373 9.5q23 0 68 -0.5t68 -0.5q70 0 136.5 -13t128.5 -42t108 -71t74 -104.5t28 -137.5q0 -52 -16.5 -95.5t-39 -72t-64.5 -57.5t-73 -45t-84 -40q154 -35 256.5 -134t102.5 -248q0 -100 -35 -179.5t-93.5 -130.5t-138 -85.5t-163.5 -48.5
t-176 -14q-44 0 -132 3t-132 3q-106 0 -307 -11t-231 -12z" />
    <glyph glyph-name="italic" unicode="&#xf033;" horiz-adv-x="1024" 
d="M0 -126l17 85q22 7 61.5 16.5t72 19t59.5 23.5q28 35 41 101q1 7 62 289t114 543.5t52 296.5v25q-24 13 -54.5 18.5t-69.5 8t-58 5.5l19 103q33 -2 120 -6.5t149.5 -7t120.5 -2.5q48 0 98.5 2.5t121 7t98.5 6.5q-5 -39 -19 -89q-30 -10 -101.5 -28.5t-108.5 -33.5
q-8 -19 -14 -42.5t-9 -40t-7.5 -45.5t-6.5 -42q-27 -148 -87.5 -419.5t-77.5 -355.5q-2 -9 -13 -58t-20 -90t-16 -83.5t-6 -57.5l1 -18q17 -4 185 -31q-3 -44 -16 -99q-11 0 -32.5 -1.5t-32.5 -1.5q-29 0 -87 10t-86 10q-138 2 -206 2q-51 0 -143 -9t-121 -11z" />
    <glyph glyph-name="text_height" unicode="&#xf034;" horiz-adv-x="1792" 
d="M1744 128q33 0 42 -18.5t-11 -44.5l-126 -162q-20 -26 -49 -26t-49 26l-126 162q-20 26 -11 44.5t42 18.5h80v1024h-80q-33 0 -42 18.5t11 44.5l126 162q20 26 49 26t49 -26l126 -162q20 -26 11 -44.5t-42 -18.5h-80v-1024h80zM81 1407l54 -27q12 -5 211 -5q44 0 132 2
t132 2q36 0 107.5 -0.5t107.5 -0.5h293q6 0 21 -0.5t20.5 0t16 3t17.5 9t15 17.5l42 1q4 0 14 -0.5t14 -0.5q2 -112 2 -336q0 -80 -5 -109q-39 -14 -68 -18q-25 44 -54 128q-3 9 -11 48t-14.5 73.5t-7.5 35.5q-6 8 -12 12.5t-15.5 6t-13 2.5t-18 0.5t-16.5 -0.5
q-17 0 -66.5 0.5t-74.5 0.5t-64 -2t-71 -6q-9 -81 -8 -136q0 -94 2 -388t2 -455q0 -16 -2.5 -71.5t0 -91.5t12.5 -69q40 -21 124 -42.5t120 -37.5q5 -40 5 -50q0 -14 -3 -29l-34 -1q-76 -2 -218 8t-207 10q-50 0 -151 -9t-152 -9q-3 51 -3 52v9q17 27 61.5 43t98.5 29t78 27
q19 42 19 383q0 101 -3 303t-3 303v117q0 2 0.5 15.5t0.5 25t-1 25.5t-3 24t-5 14q-11 12 -162 12q-33 0 -93 -12t-80 -26q-19 -13 -34 -72.5t-31.5 -111t-42.5 -53.5q-42 26 -56 44v383z" />
    <glyph glyph-name="text_width" unicode="&#xf035;" 
d="M81 1407l54 -27q12 -5 211 -5q44 0 132 2t132 2q70 0 246.5 1t304.5 0.5t247 -4.5q33 -1 56 31l42 1q4 0 14 -0.5t14 -0.5q2 -112 2 -336q0 -80 -5 -109q-39 -14 -68 -18q-25 44 -54 128q-3 9 -11 47.5t-15 73.5t-7 36q-10 13 -27 19q-5 2 -66 2q-30 0 -93 1t-103 1
t-94 -2t-96 -7q-9 -81 -8 -136l1 -152v52q0 -55 1 -154t1.5 -180t0.5 -153q0 -16 -2.5 -71.5t0 -91.5t12.5 -69q40 -21 124 -42.5t120 -37.5q5 -40 5 -50q0 -14 -3 -29l-34 -1q-76 -2 -218 8t-207 10q-50 0 -151 -9t-152 -9q-3 51 -3 52v9q17 27 61.5 43t98.5 29t78 27
q7 16 11.5 74t6 145.5t1.5 155t-0.5 153.5t-0.5 89q0 7 -2.5 21.5t-2.5 22.5q0 7 0.5 44t1 73t0 76.5t-3 67.5t-6.5 32q-11 12 -162 12q-41 0 -163 -13.5t-138 -24.5q-19 -12 -34 -71.5t-31.5 -111.5t-42.5 -54q-42 26 -56 44v383zM1310 125q12 0 42 -19.5t57.5 -41.5
t59.5 -49t36 -30q26 -21 26 -49t-26 -49q-4 -3 -36 -30t-59.5 -49t-57.5 -41.5t-42 -19.5q-13 0 -20.5 10.5t-10 28.5t-2.5 33.5t1.5 33t1.5 19.5h-1024q0 -2 1.5 -19.5t1.5 -33t-2.5 -33.5t-10 -28.5t-20.5 -10.5q-12 0 -42 19.5t-57.5 41.5t-59.5 49t-36 30q-26 21 -26 49
t26 49q4 3 36 30t59.5 49t57.5 41.5t42 19.5q13 0 20.5 -10.5t10 -28.5t2.5 -33.5t-1.5 -33t-1.5 -19.5h1024q0 2 -1.5 19.5t-1.5 33t2.5 33.5t10 28.5t20.5 10.5z" />
    <glyph glyph-name="align_left" unicode="&#xf036;" horiz-adv-x="1792" 
d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45
t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
    <glyph glyph-name="align_center" unicode="&#xf037;" horiz-adv-x="1792" 
d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h896q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45t-45 -19
h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h640q26 0 45 -19t19 -45z" />
    <glyph glyph-name="align_right" unicode="&#xf038;" horiz-adv-x="1792" 
d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45
t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
    <glyph glyph-name="align_justify" unicode="&#xf039;" horiz-adv-x="1792" 
d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45
t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
    <glyph glyph-name="list" unicode="&#xf03a;" horiz-adv-x="1792" 
d="M256 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM256 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5
t9.5 -22.5zM256 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344
q13 0 22.5 -9.5t9.5 -22.5zM256 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5
t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192
q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5z" />
    <glyph glyph-name="indent_left" unicode="&#xf03b;" horiz-adv-x="1792" 
d="M384 992v-576q0 -13 -9.5 -22.5t-22.5 -9.5q-14 0 -23 9l-288 288q-9 9 -9 23t9 23l288 288q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5
t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088
q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
    <glyph glyph-name="indent_right" unicode="&#xf03c;" horiz-adv-x="1792" 
d="M352 704q0 -14 -9 -23l-288 -288q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v576q0 13 9.5 22.5t22.5 9.5q14 0 23 -9l288 -288q9 -9 9 -23zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5
t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088
q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
    <glyph glyph-name="facetime_video" unicode="&#xf03d;" horiz-adv-x="1792" 
d="M1792 1184v-1088q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-403 403v-166q0 -119 -84.5 -203.5t-203.5 -84.5h-704q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h704q119 0 203.5 -84.5t84.5 -203.5v-165l403 402q18 19 45 19q12 0 25 -5
q39 -17 39 -59z" />
    <glyph glyph-name="picture" unicode="&#xf03e;" horiz-adv-x="1920" 
d="M640 960q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 576v-448h-1408v192l320 320l160 -160l512 512zM1760 1280h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5v1216
q0 13 -9.5 22.5t-22.5 9.5zM1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
    <glyph glyph-name="pencil" unicode="&#xf040;" 
d="M363 0l91 91l-235 235l-91 -91v-107h128v-128h107zM886 928q0 22 -22 22q-10 0 -17 -7l-542 -542q-7 -7 -7 -17q0 -22 22 -22q10 0 17 7l542 542q7 7 7 17zM832 1120l416 -416l-832 -832h-416v416zM1515 1024q0 -53 -37 -90l-166 -166l-416 416l166 165q36 38 90 38
q53 0 91 -38l235 -234q37 -39 37 -91z" />
    <glyph glyph-name="map_marker" unicode="&#xf041;" horiz-adv-x="1024" 
d="M768 896q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1024 896q0 -109 -33 -179l-364 -774q-16 -33 -47.5 -52t-67.5 -19t-67.5 19t-46.5 52l-365 774q-33 70 -33 179q0 212 150 362t362 150t362 -150t150 -362z" />
    <glyph glyph-name="adjust" unicode="&#xf042;" 
d="M768 96v1088q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="tint" unicode="&#xf043;" horiz-adv-x="1024" 
d="M512 384q0 36 -20 69q-1 1 -15.5 22.5t-25.5 38t-25 44t-21 50.5q-4 16 -21 16t-21 -16q-7 -23 -21 -50.5t-25 -44t-25.5 -38t-15.5 -22.5q-20 -33 -20 -69q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 512q0 -212 -150 -362t-362 -150t-362 150t-150 362
q0 145 81 275q6 9 62.5 90.5t101 151t99.5 178t83 201.5q9 30 34 47t51 17t51.5 -17t33.5 -47q28 -93 83 -201.5t99.5 -178t101 -151t62.5 -90.5q81 -127 81 -275z" />
    <glyph glyph-name="edit" unicode="&#xf044;" horiz-adv-x="1792" 
d="M888 352l116 116l-152 152l-116 -116v-56h96v-96h56zM1328 1072q-16 16 -33 -1l-350 -350q-17 -17 -1 -33t33 1l350 350q17 17 1 33zM1408 478v-190q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832
q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-14 -14 -32 -8q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v126q0 13 9 22l64 64q15 15 35 7t20 -29zM1312 1216l288 -288l-672 -672h-288v288zM1756 1084l-92 -92
l-288 288l92 92q28 28 68 28t68 -28l152 -152q28 -28 28 -68t-28 -68z" />
    <glyph glyph-name="share" unicode="&#xf045;" horiz-adv-x="1664" 
d="M1408 547v-259q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h255v0q13 0 22.5 -9.5t9.5 -22.5q0 -27 -26 -32q-77 -26 -133 -60q-10 -4 -16 -4h-112q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832
q66 0 113 47t47 113v214q0 19 18 29q28 13 54 37q16 16 35 8q21 -9 21 -29zM1645 1043l-384 -384q-18 -19 -45 -19q-12 0 -25 5q-39 17 -39 59v192h-160q-323 0 -438 -131q-119 -137 -74 -473q3 -23 -20 -34q-8 -2 -12 -2q-16 0 -26 13q-10 14 -21 31t-39.5 68.5t-49.5 99.5
t-38.5 114t-17.5 122q0 49 3.5 91t14 90t28 88t47 81.5t68.5 74t94.5 61.5t124.5 48.5t159.5 30.5t196.5 11h160v192q0 42 39 59q13 5 25 5q26 0 45 -19l384 -384q19 -19 19 -45t-19 -45z" />
    <glyph glyph-name="check" unicode="&#xf046;" horiz-adv-x="1664" 
d="M1408 606v-318q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-10 -10 -23 -10q-3 0 -9 2q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832
q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v254q0 13 9 22l64 64q10 10 23 10q6 0 12 -3q20 -8 20 -29zM1639 1095l-814 -814q-24 -24 -57 -24t-57 24l-430 430q-24 24 -24 57t24 57l110 110q24 24 57 24t57 -24l263 -263l647 647q24 24 57 24t57 -24l110 -110
q24 -24 24 -57t-24 -57z" />
    <glyph glyph-name="move" unicode="&#xf047;" horiz-adv-x="1792" 
d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-384v-384h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v384h-384v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45
t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h384v384h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45t-19 -45t-45 -19h-128v-384h384v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
    <glyph glyph-name="step_backward" unicode="&#xf048;" horiz-adv-x="1024" 
d="M979 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 10 13 19z" />
    <glyph glyph-name="fast_backward" unicode="&#xf049;" horiz-adv-x="1792" 
d="M1747 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 10 13 19l710 710
q19 19 32 13t13 -32v-710q4 10 13 19z" />
    <glyph glyph-name="backward" unicode="&#xf04a;" horiz-adv-x="1664" 
d="M1619 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-19 19 -19 45t19 45l710 710q19 19 32 13t13 -32v-710q4 10 13 19z" />
    <glyph glyph-name="play" unicode="&#xf04b;" horiz-adv-x="1408" 
d="M1384 609l-1328 -738q-23 -13 -39.5 -3t-16.5 36v1472q0 26 16.5 36t39.5 -3l1328 -738q23 -13 23 -31t-23 -31z" />
    <glyph glyph-name="pause" unicode="&#xf04c;" 
d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45zM640 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45z" />
    <glyph glyph-name="stop" unicode="&#xf04d;" 
d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
    <glyph glyph-name="forward" unicode="&#xf04e;" horiz-adv-x="1664" 
d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q9 -9 13 -19v710q0 26 13 32t32 -13l710 -710q19 -19 19 -45t-19 -45l-710 -710q-19 -19 -32 -13t-13 32v710q-4 -10 -13 -19z" />
    <glyph glyph-name="fast_forward" unicode="&#xf050;" horiz-adv-x="1792" 
d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q9 -9 13 -19v710q0 26 13 32t32 -13l710 -710q9 -9 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-4 -10 -13 -19l-710 -710
q-19 -19 -32 -13t-13 32v710q-4 -10 -13 -19z" />
    <glyph glyph-name="step_forward" unicode="&#xf051;" horiz-adv-x="1024" 
d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q9 -9 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-4 -10 -13 -19z" />
    <glyph glyph-name="eject" unicode="&#xf052;" horiz-adv-x="1538" 
d="M14 557l710 710q19 19 45 19t45 -19l710 -710q19 -19 13 -32t-32 -13h-1472q-26 0 -32 13t13 32zM1473 0h-1408q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19z" />
    <glyph glyph-name="chevron_left" unicode="&#xf053;" horiz-adv-x="1280" 
d="M1171 1235l-531 -531l531 -531q19 -19 19 -45t-19 -45l-166 -166q-19 -19 -45 -19t-45 19l-742 742q-19 19 -19 45t19 45l742 742q19 19 45 19t45 -19l166 -166q19 -19 19 -45t-19 -45z" />
    <glyph glyph-name="chevron_right" unicode="&#xf054;" horiz-adv-x="1280" 
d="M1107 659l-742 -742q-19 -19 -45 -19t-45 19l-166 166q-19 19 -19 45t19 45l531 531l-531 531q-19 19 -19 45t19 45l166 166q19 19 45 19t45 -19l742 -742q19 -19 19 -45t-19 -45z" />
    <glyph glyph-name="plus_sign" unicode="&#xf055;" 
d="M1216 576v128q0 26 -19 45t-45 19h-256v256q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-256h-256q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h256v-256q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v256h256q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5
t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="minus_sign" unicode="&#xf056;" 
d="M1216 576v128q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5
t103 -385.5z" />
    <glyph glyph-name="remove_sign" unicode="&#xf057;" 
d="M1149 414q0 26 -19 45l-181 181l181 181q19 19 19 45q0 27 -19 46l-90 90q-19 19 -46 19q-26 0 -45 -19l-181 -181l-181 181q-19 19 -45 19q-27 0 -46 -19l-90 -90q-19 -19 -19 -46q0 -26 19 -45l181 -181l-181 -181q-19 -19 -19 -45q0 -27 19 -46l90 -90q19 -19 46 -19
q26 0 45 19l181 181l181 -181q19 -19 45 -19q27 0 46 19l90 90q19 19 19 46zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="ok_sign" unicode="&#xf058;" 
d="M1284 802q0 28 -18 46l-91 90q-19 19 -45 19t-45 -19l-408 -407l-226 226q-19 19 -45 19t-45 -19l-91 -90q-18 -18 -18 -46q0 -27 18 -45l362 -362q19 -19 45 -19q27 0 46 19l543 543q18 18 18 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103
t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="question_sign" unicode="&#xf059;" 
d="M896 160v192q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h192q14 0 23 9t9 23zM1152 832q0 88 -55.5 163t-138.5 116t-170 41q-243 0 -371 -213q-15 -24 8 -42l132 -100q7 -6 19 -6q16 0 25 12q53 68 86 92q34 24 86 24q48 0 85.5 -26t37.5 -59
q0 -38 -20 -61t-68 -45q-63 -28 -115.5 -86.5t-52.5 -125.5v-36q0 -14 9 -23t23 -9h192q14 0 23 9t9 23q0 19 21.5 49.5t54.5 49.5q32 18 49 28.5t46 35t44.5 48t28 60.5t12.5 81zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5
t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="info_sign" unicode="&#xf05a;" 
d="M1024 160v160q0 14 -9 23t-23 9h-96v512q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h96v-320h-96q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h448q14 0 23 9t9 23zM896 1056v160q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23
t23 -9h192q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="screenshot" unicode="&#xf05b;" 
d="M1197 512h-109q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h109q-32 108 -112.5 188.5t-188.5 112.5v-109q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v109q-108 -32 -188.5 -112.5t-112.5 -188.5h109q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-109
q32 -108 112.5 -188.5t188.5 -112.5v109q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-109q108 32 188.5 112.5t112.5 188.5zM1536 704v-128q0 -26 -19 -45t-45 -19h-143q-37 -161 -154.5 -278.5t-278.5 -154.5v-143q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v143
q-161 37 -278.5 154.5t-154.5 278.5h-143q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h143q37 161 154.5 278.5t278.5 154.5v143q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-143q161 -37 278.5 -154.5t154.5 -278.5h143q26 0 45 -19t19 -45z" />
    <glyph glyph-name="remove_circle" unicode="&#xf05c;" 
d="M1097 457l-146 -146q-10 -10 -23 -10t-23 10l-137 137l-137 -137q-10 -10 -23 -10t-23 10l-146 146q-10 10 -10 23t10 23l137 137l-137 137q-10 10 -10 23t10 23l146 146q10 10 23 10t23 -10l137 -137l137 137q10 10 23 10t23 -10l146 -146q10 -10 10 -23t-10 -23
l-137 -137l137 -137q10 -10 10 -23t-10 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5
t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="ok_circle" unicode="&#xf05d;" 
d="M1171 723l-422 -422q-19 -19 -45 -19t-45 19l-294 294q-19 19 -19 45t19 45l102 102q19 19 45 19t45 -19l147 -147l275 275q19 19 45 19t45 -19l102 -102q19 -19 19 -45t-19 -45zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198
t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="ban_circle" unicode="&#xf05e;" 
d="M1312 643q0 161 -87 295l-754 -753q137 -89 297 -89q111 0 211.5 43.5t173.5 116.5t116 174.5t43 212.5zM313 344l755 754q-135 91 -300 91q-148 0 -273 -73t-198 -199t-73 -274q0 -162 89 -299zM1536 643q0 -157 -61 -300t-163.5 -246t-245 -164t-298.5 -61t-298.5 61
t-245 164t-163.5 246t-61 300t61 299.5t163.5 245.5t245 164t298.5 61t298.5 -61t245 -164t163.5 -245.5t61 -299.5z" />
    <glyph glyph-name="arrow_left" unicode="&#xf060;" 
d="M1536 640v-128q0 -53 -32.5 -90.5t-84.5 -37.5h-704l293 -294q38 -36 38 -90t-38 -90l-75 -76q-37 -37 -90 -37q-52 0 -91 37l-651 652q-37 37 -37 90q0 52 37 91l651 650q38 38 91 38q52 0 90 -38l75 -74q38 -38 38 -91t-38 -91l-293 -293h704q52 0 84.5 -37.5
t32.5 -90.5z" />
    <glyph glyph-name="arrow_right" unicode="&#xf061;" 
d="M1472 576q0 -54 -37 -91l-651 -651q-39 -37 -91 -37q-51 0 -90 37l-75 75q-38 38 -38 91t38 91l293 293h-704q-52 0 -84.5 37.5t-32.5 90.5v128q0 53 32.5 90.5t84.5 37.5h704l-293 294q-38 36 -38 90t38 90l75 75q38 38 90 38q53 0 91 -38l651 -651q37 -35 37 -90z" />
    <glyph glyph-name="arrow_up" unicode="&#xf062;" horiz-adv-x="1664" 
d="M1611 565q0 -51 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-294 293v-704q0 -52 -37.5 -84.5t-90.5 -32.5h-128q-53 0 -90.5 32.5t-37.5 84.5v704l-294 -293q-36 -38 -90 -38t-90 38l-75 75q-38 38 -38 90q0 53 38 91l651 651q35 37 90 37q54 0 91 -37l651 -651
q37 -39 37 -91z" />
    <glyph glyph-name="arrow_down" unicode="&#xf063;" horiz-adv-x="1664" 
d="M1611 704q0 -53 -37 -90l-651 -652q-39 -37 -91 -37q-53 0 -90 37l-651 652q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l294 -294v704q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-704l294 294q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" />
    <glyph glyph-name="share_alt" unicode="&#xf064;" horiz-adv-x="1792" 
d="M1792 896q0 -26 -19 -45l-512 -512q-19 -19 -45 -19t-45 19t-19 45v256h-224q-98 0 -175.5 -6t-154 -21.5t-133 -42.5t-105.5 -69.5t-80 -101t-48.5 -138.5t-17.5 -181q0 -55 5 -123q0 -6 2.5 -23.5t2.5 -26.5q0 -15 -8.5 -25t-23.5 -10q-16 0 -28 17q-7 9 -13 22
t-13.5 30t-10.5 24q-127 285 -127 451q0 199 53 333q162 403 875 403h224v256q0 26 19 45t45 19t45 -19l512 -512q19 -19 19 -45z" />
    <glyph glyph-name="resize_full" unicode="&#xf065;" 
d="M755 480q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23zM1536 1344v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332
q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45z" />
    <glyph glyph-name="resize_small" unicode="&#xf066;" 
d="M768 576v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45zM1523 1248q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45
t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23z" />
    <glyph glyph-name="plus" unicode="&#xf067;" horiz-adv-x="1408" 
d="M1408 800v-192q0 -40 -28 -68t-68 -28h-416v-416q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v416h-416q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h416v416q0 40 28 68t68 28h192q40 0 68 -28t28 -68v-416h416q40 0 68 -28t28 -68z" />
    <glyph glyph-name="minus" unicode="&#xf068;" horiz-adv-x="1408" 
d="M1408 800v-192q0 -40 -28 -68t-68 -28h-1216q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h1216q40 0 68 -28t28 -68z" />
    <glyph glyph-name="asterisk" unicode="&#xf069;" horiz-adv-x="1664" 
d="M1482 486q46 -26 59.5 -77.5t-12.5 -97.5l-64 -110q-26 -46 -77.5 -59.5t-97.5 12.5l-266 153v-307q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v307l-266 -153q-46 -26 -97.5 -12.5t-77.5 59.5l-64 110q-26 46 -12.5 97.5t59.5 77.5l266 154l-266 154
q-46 26 -59.5 77.5t12.5 97.5l64 110q26 46 77.5 59.5t97.5 -12.5l266 -153v307q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-307l266 153q46 26 97.5 12.5t77.5 -59.5l64 -110q26 -46 12.5 -97.5t-59.5 -77.5l-266 -154z" />
    <glyph glyph-name="exclamation_sign" unicode="&#xf06a;" 
d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM896 161v190q0 14 -9 23.5t-22 9.5h-192q-13 0 -23 -10t-10 -23v-190q0 -13 10 -23t23 -10h192
q13 0 22 9.5t9 23.5zM894 505l18 621q0 12 -10 18q-10 8 -24 8h-220q-14 0 -24 -8q-10 -6 -10 -18l17 -621q0 -10 10 -17.5t24 -7.5h185q14 0 23.5 7.5t10.5 17.5z" />
    <glyph glyph-name="gift" unicode="&#xf06b;" 
d="M928 180v56v468v192h-320v-192v-468v-56q0 -25 18 -38.5t46 -13.5h192q28 0 46 13.5t18 38.5zM472 1024h195l-126 161q-26 31 -69 31q-40 0 -68 -28t-28 -68t28 -68t68 -28zM1160 1120q0 40 -28 68t-68 28q-43 0 -69 -31l-125 -161h194q40 0 68 28t28 68zM1536 864v-320
q0 -14 -9 -23t-23 -9h-96v-416q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v416h-96q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h440q-93 0 -158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5q107 0 168 -77l128 -165l128 165q61 77 168 77q93 0 158.5 -65.5t65.5 -158.5
t-65.5 -158.5t-158.5 -65.5h440q14 0 23 -9t9 -23z" />
    <glyph glyph-name="leaf" unicode="&#xf06c;" horiz-adv-x="1792" 
d="M1280 832q0 26 -19 45t-45 19q-172 0 -318 -49.5t-259.5 -134t-235.5 -219.5q-19 -21 -19 -45q0 -26 19 -45t45 -19q24 0 45 19q27 24 74 71t67 66q137 124 268.5 176t313.5 52q26 0 45 19t19 45zM1792 1030q0 -95 -20 -193q-46 -224 -184.5 -383t-357.5 -268
q-214 -108 -438 -108q-148 0 -286 47q-15 5 -88 42t-96 37q-16 0 -39.5 -32t-45 -70t-52.5 -70t-60 -32q-43 0 -63.5 17.5t-45.5 59.5q-2 4 -6 11t-5.5 10t-3 9.5t-1.5 13.5q0 35 31 73.5t68 65.5t68 56t31 48q0 4 -14 38t-16 44q-9 51 -9 104q0 115 43.5 220t119 184.5
t170.5 139t204 95.5q55 18 145 25.5t179.5 9t178.5 6t163.5 24t113.5 56.5l29.5 29.5t29.5 28t27 20t36.5 16t43.5 4.5q39 0 70.5 -46t47.5 -112t24 -124t8 -96z" />
    <glyph glyph-name="fire" unicode="&#xf06d;" horiz-adv-x="1408" 
d="M1408 -160v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1152 896q0 -78 -24.5 -144t-64 -112.5t-87.5 -88t-96 -77.5t-87.5 -72t-64 -81.5t-24.5 -96.5q0 -96 67 -224l-4 1l1 -1
q-90 41 -160 83t-138.5 100t-113.5 122.5t-72.5 150.5t-27.5 184q0 78 24.5 144t64 112.5t87.5 88t96 77.5t87.5 72t64 81.5t24.5 96.5q0 94 -66 224l3 -1l-1 1q90 -41 160 -83t138.5 -100t113.5 -122.5t72.5 -150.5t27.5 -184z" />
    <glyph glyph-name="eye_open" unicode="&#xf06e;" horiz-adv-x="1792" 
d="M1664 576q-152 236 -381 353q61 -104 61 -225q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 121 61 225q-229 -117 -381 -353q133 -205 333.5 -326.5t434.5 -121.5t434.5 121.5t333.5 326.5zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5
t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1792 576q0 -34 -20 -69q-140 -230 -376.5 -368.5t-499.5 -138.5t-499.5 139t-376.5 368q-20 35 -20 69t20 69q140 229 376.5 368t499.5 139t499.5 -139t376.5 -368q20 -35 20 -69z" />
    <glyph glyph-name="eye_close" unicode="&#xf070;" horiz-adv-x="1792" 
d="M555 201l78 141q-87 63 -136 159t-49 203q0 121 61 225q-229 -117 -381 -353q167 -258 427 -375zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1307 1151q0 -7 -1 -9
q-106 -189 -316 -567t-315 -566l-49 -89q-10 -16 -28 -16q-12 0 -134 70q-16 10 -16 28q0 12 44 87q-143 65 -263.5 173t-208.5 245q-20 31 -20 69t20 69q153 235 380 371t496 136q89 0 180 -17l54 97q10 16 28 16q5 0 18 -6t31 -15.5t33 -18.5t31.5 -18.5t19.5 -11.5
q16 -10 16 -27zM1344 704q0 -139 -79 -253.5t-209 -164.5l280 502q8 -45 8 -84zM1792 576q0 -35 -20 -69q-39 -64 -109 -145q-150 -172 -347.5 -267t-419.5 -95l74 132q212 18 392.5 137t301.5 307q-115 179 -282 294l63 112q95 -64 182.5 -153t144.5 -184q20 -34 20 -69z
" />
    <glyph glyph-name="warning_sign" unicode="&#xf071;" horiz-adv-x="1792" 
d="M1024 161v190q0 14 -9.5 23.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -23.5v-190q0 -14 9.5 -23.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 23.5zM1022 535l18 459q0 12 -10 19q-13 11 -24 11h-220q-11 0 -24 -11q-10 -7 -10 -21l17 -457q0 -10 10 -16.5t24 -6.5h185
q14 0 23.5 6.5t10.5 16.5zM1008 1469l768 -1408q35 -63 -2 -126q-17 -29 -46.5 -46t-63.5 -17h-1536q-34 0 -63.5 17t-46.5 46q-37 63 -2 126l768 1408q17 31 47 49t65 18t65 -18t47 -49z" />
    <glyph glyph-name="plane" unicode="&#xf072;" horiz-adv-x="1408" 
d="M1376 1376q44 -52 12 -148t-108 -172l-161 -161l160 -696q5 -19 -12 -33l-128 -96q-7 -6 -19 -6q-4 0 -7 1q-15 3 -21 16l-279 508l-259 -259l53 -194q5 -17 -8 -31l-96 -96q-9 -9 -23 -9h-2q-15 2 -24 13l-189 252l-252 189q-11 7 -13 23q-1 13 9 25l96 97q9 9 23 9
q6 0 8 -1l194 -53l259 259l-508 279q-14 8 -17 24q-2 16 9 27l128 128q14 13 30 8l665 -159l160 160q76 76 172 108t148 -12z" />
    <glyph glyph-name="calendar" unicode="&#xf073;" horiz-adv-x="1664" 
d="M128 -128h288v288h-288v-288zM480 -128h320v288h-320v-288zM128 224h288v320h-288v-320zM480 224h320v320h-320v-320zM128 608h288v288h-288v-288zM864 -128h320v288h-320v-288zM480 608h320v288h-320v-288zM1248 -128h288v288h-288v-288zM864 224h320v320h-320v-320z
M512 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1248 224h288v320h-288v-320zM864 608h320v288h-320v-288zM1248 608h288v288h-288v-288zM1280 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64
q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47
h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
    <glyph glyph-name="random" unicode="&#xf074;" horiz-adv-x="1792" 
d="M666 1055q-60 -92 -137 -273q-22 45 -37 72.5t-40.5 63.5t-51 56.5t-63 35t-81.5 14.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q250 0 410 -225zM1792 256q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192q-32 0 -85 -0.5t-81 -1t-73 1
t-71 5t-64 10.5t-63 18.5t-58 28.5t-59 40t-55 53.5t-56 69.5q59 93 136 273q22 -45 37 -72.5t40.5 -63.5t51 -56.5t63 -35t81.5 -14.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1792 1152q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5
v192h-256q-48 0 -87 -15t-69 -45t-51 -61.5t-45 -77.5q-32 -62 -78 -171q-29 -66 -49.5 -111t-54 -105t-64 -100t-74 -83t-90 -68.5t-106.5 -42t-128 -16.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q48 0 87 15t69 45t51 61.5t45 77.5q32 62 78 171q29 66 49.5 111
t54 105t64 100t74 83t90 68.5t106.5 42t128 16.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" />
    <glyph glyph-name="comment" unicode="&#xf075;" horiz-adv-x="1792" 
d="M1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22q-17 -2 -30.5 9t-17.5 29v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281
q0 130 71 248.5t191 204.5t286 136.5t348 50.5q244 0 450 -85.5t326 -233t120 -321.5z" />
    <glyph glyph-name="magnet" unicode="&#xf076;" 
d="M1536 704v-128q0 -201 -98.5 -362t-274 -251.5t-395.5 -90.5t-395.5 90.5t-274 251.5t-98.5 362v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-128q0 -52 23.5 -90t53.5 -57t71 -30t64 -13t44 -2t44 2t64 13t71 30t53.5 57t23.5 90v128q0 26 19 45t45 19h384
q26 0 45 -19t19 -45zM512 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45zM1536 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45z" />
    <glyph glyph-name="chevron_up" unicode="&#xf077;" horiz-adv-x="1792" 
d="M1683 205l-166 -165q-19 -19 -45 -19t-45 19l-531 531l-531 -531q-19 -19 -45 -19t-45 19l-166 165q-19 19 -19 45.5t19 45.5l742 741q19 19 45 19t45 -19l742 -741q19 -19 19 -45.5t-19 -45.5z" />
    <glyph glyph-name="chevron_down" unicode="&#xf078;" horiz-adv-x="1792" 
d="M1683 728l-742 -741q-19 -19 -45 -19t-45 19l-742 741q-19 19 -19 45.5t19 45.5l166 165q19 19 45 19t45 -19l531 -531l531 531q19 19 45 19t45 -19l166 -165q19 -19 19 -45.5t-19 -45.5z" />
    <glyph glyph-name="retweet" unicode="&#xf079;" horiz-adv-x="1920" 
d="M1280 32q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-8 0 -13.5 2t-9 7t-5.5 8t-3 11.5t-1 11.5v13v11v160v416h-192q-26 0 -45 19t-19 45q0 24 15 41l320 384q19 22 49 22t49 -22l320 -384q15 -17 15 -41q0 -26 -19 -45t-45 -19h-192v-384h576q16 0 25 -11l160 -192q7 -10 7 -21
zM1920 448q0 -24 -15 -41l-320 -384q-20 -23 -49 -23t-49 23l-320 384q-15 17 -15 41q0 26 19 45t45 19h192v384h-576q-16 0 -25 12l-160 192q-7 9 -7 20q0 13 9.5 22.5t22.5 9.5h960q8 0 13.5 -2t9 -7t5.5 -8t3 -11.5t1 -11.5v-13v-11v-160v-416h192q26 0 45 -19t19 -45z
" />
    <glyph glyph-name="shopping_cart" unicode="&#xf07a;" horiz-adv-x="1664" 
d="M640 0q0 -52 -38 -90t-90 -38t-90 38t-38 90t38 90t90 38t90 -38t38 -90zM1536 0q0 -52 -38 -90t-90 -38t-90 38t-38 90t38 90t90 38t90 -38t38 -90zM1664 1088v-512q0 -24 -16.5 -42.5t-40.5 -21.5l-1044 -122q13 -60 13 -70q0 -16 -24 -64h920q26 0 45 -19t19 -45
t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 11 8 31.5t16 36t21.5 40t15.5 29.5l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t19.5 -15.5t13 -24.5t8 -26t5.5 -29.5t4.5 -26h1201q26 0 45 -19t19 -45z" />
    <glyph glyph-name="folder_close" unicode="&#xf07b;" horiz-adv-x="1664" 
d="M1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
    <glyph glyph-name="folder_open" unicode="&#xf07c;" horiz-adv-x="1920" 
d="M1879 584q0 -31 -31 -66l-336 -396q-43 -51 -120.5 -86.5t-143.5 -35.5h-1088q-34 0 -60.5 13t-26.5 43q0 31 31 66l336 396q43 51 120.5 86.5t143.5 35.5h1088q34 0 60.5 -13t26.5 -43zM1536 928v-160h-832q-94 0 -197 -47.5t-164 -119.5l-337 -396l-5 -6q0 4 -0.5 12.5
t-0.5 12.5v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158z" />
    <glyph glyph-name="resize_vertical" unicode="&#xf07d;" horiz-adv-x="768" 
d="M704 1216q0 -26 -19 -45t-45 -19h-128v-1024h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v1024h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45z" />
    <glyph glyph-name="resize_horizontal" unicode="&#xf07e;" horiz-adv-x="1792" 
d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-1024v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h1024v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
    <glyph glyph-name="bar_chart" unicode="&#xf080;" horiz-adv-x="2048" 
d="M640 640v-512h-256v512h256zM1024 1152v-1024h-256v1024h256zM2048 0v-128h-2048v1536h128v-1408h1920zM1408 896v-768h-256v768h256zM1792 1280v-1152h-256v1152h256z" />
    <glyph glyph-name="twitter_sign" unicode="&#xf081;" 
d="M1280 926q-56 -25 -121 -34q68 40 93 117q-65 -38 -134 -51q-61 66 -153 66q-87 0 -148.5 -61.5t-61.5 -148.5q0 -29 5 -48q-129 7 -242 65t-192 155q-29 -50 -29 -106q0 -114 91 -175q-47 1 -100 26v-2q0 -75 50 -133.5t123 -72.5q-29 -8 -51 -8q-13 0 -39 4
q21 -63 74.5 -104t121.5 -42q-116 -90 -261 -90q-26 0 -50 3q148 -94 322 -94q112 0 210 35.5t168 95t120.5 137t75 162t24.5 168.5q0 18 -1 27q63 45 105 109zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5
t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="facebook_sign" unicode="&#xf082;" 
d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-188v595h199l30 232h-229v148q0 56 23.5 84t91.5 28l122 1v207q-63 9 -178 9q-136 0 -217.5 -80t-81.5 -226v-171h-200v-232h200v-595h-532q-119 0 -203.5 84.5t-84.5 203.5v960
q0 119 84.5 203.5t203.5 84.5h960z" />
    <glyph glyph-name="camera_retro" unicode="&#xf083;" horiz-adv-x="1792" 
d="M928 704q0 14 -9 23t-23 9q-66 0 -113 -47t-47 -113q0 -14 9 -23t23 -9t23 9t9 23q0 40 28 68t68 28q14 0 23 9t9 23zM1152 574q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM128 0h1536v128h-1536v-128zM1280 574q0 159 -112.5 271.5
t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM256 1216h384v128h-384v-128zM128 1024h1536v118v138h-828l-64 -128h-644v-128zM1792 1280v-1280q0 -53 -37.5 -90.5t-90.5 -37.5h-1536q-53 0 -90.5 37.5t-37.5 90.5v1280
q0 53 37.5 90.5t90.5 37.5h1536q53 0 90.5 -37.5t37.5 -90.5z" />
    <glyph glyph-name="key" unicode="&#xf084;" horiz-adv-x="1792" 
d="M832 1024q0 80 -56 136t-136 56t-136 -56t-56 -136q0 -42 19 -83q-41 19 -83 19q-80 0 -136 -56t-56 -136t56 -136t136 -56t136 56t56 136q0 42 -19 83q41 -19 83 -19q80 0 136 56t56 136zM1683 320q0 -17 -49 -66t-66 -49q-9 0 -28.5 16t-36.5 33t-38.5 40t-24.5 26
l-96 -96l220 -220q28 -28 28 -68q0 -42 -39 -81t-81 -39q-40 0 -68 28l-671 671q-176 -131 -365 -131q-163 0 -265.5 102.5t-102.5 265.5q0 160 95 313t248 248t313 95q163 0 265.5 -102.5t102.5 -265.5q0 -189 -131 -365l355 -355l96 96q-3 3 -26 24.5t-40 38.5t-33 36.5
t-16 28.5q0 17 49 66t66 49q13 0 23 -10q6 -6 46 -44.5t82 -79.5t86.5 -86t73 -78t28.5 -41z" />
    <glyph glyph-name="cogs" unicode="&#xf085;" horiz-adv-x="1920" 
d="M896 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1664 128q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1152q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5
t90.5 37.5t37.5 90.5zM1280 731v-185q0 -10 -7 -19.5t-16 -10.5l-155 -24q-11 -35 -32 -76q34 -48 90 -115q7 -11 7 -20q0 -12 -7 -19q-23 -30 -82.5 -89.5t-78.5 -59.5q-11 0 -21 7l-115 90q-37 -19 -77 -31q-11 -108 -23 -155q-7 -24 -30 -24h-186q-11 0 -20 7.5t-10 17.5
l-23 153q-34 10 -75 31l-118 -89q-7 -7 -20 -7q-11 0 -21 8q-144 133 -144 160q0 9 7 19q10 14 41 53t47 61q-23 44 -35 82l-152 24q-10 1 -17 9.5t-7 19.5v185q0 10 7 19.5t16 10.5l155 24q11 35 32 76q-34 48 -90 115q-7 11 -7 20q0 12 7 20q22 30 82 89t79 59q11 0 21 -7
l115 -90q34 18 77 32q11 108 23 154q7 24 30 24h186q11 0 20 -7.5t10 -17.5l23 -153q34 -10 75 -31l118 89q8 7 20 7q11 0 21 -8q144 -133 144 -160q0 -8 -7 -19q-12 -16 -42 -54t-45 -60q23 -48 34 -82l152 -23q10 -2 17 -10.5t7 -19.5zM1920 198v-140q0 -16 -149 -31
q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20
t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31zM1920 1222v-140q0 -16 -149 -31q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68
q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70
q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31z" />
    <glyph glyph-name="comments" unicode="&#xf086;" horiz-adv-x="1792" 
d="M1408 768q0 -139 -94 -257t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224
q0 139 94 257t256.5 186.5t353.5 68.5t353.5 -68.5t256.5 -186.5t94 -257zM1792 512q0 -120 -71 -224.5t-195 -176.5q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7
q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230z" />
    <glyph glyph-name="thumbs_up_alt" unicode="&#xf087;" 
d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 768q0 51 -39 89.5t-89 38.5h-352q0 58 48 159.5t48 160.5q0 98 -32 145t-128 47q-26 -26 -38 -85t-30.5 -125.5t-59.5 -109.5q-22 -23 -77 -91q-4 -5 -23 -30t-31.5 -41t-34.5 -42.5
t-40 -44t-38.5 -35.5t-40 -27t-35.5 -9h-32v-640h32q13 0 31.5 -3t33 -6.5t38 -11t35 -11.5t35.5 -12.5t29 -10.5q211 -73 342 -73h121q192 0 192 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5q32 1 53.5 47t21.5 81zM1536 769
q0 -89 -49 -163q9 -33 9 -69q0 -77 -38 -144q3 -21 3 -43q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5h-36h-93q-96 0 -189.5 22.5t-216.5 65.5q-116 40 -138 40h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h274q36 24 137 155q58 75 107 128
q24 25 35.5 85.5t30.5 126.5t62 108q39 37 90 37q84 0 151 -32.5t102 -101.5t35 -186q0 -93 -48 -192h176q104 0 180 -76t76 -179z" />
    <glyph glyph-name="thumbs_down_alt" unicode="&#xf088;" 
d="M256 1088q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 512q0 35 -21.5 81t-53.5 47q15 17 25 47.5t10 55.5q0 69 -53 119q18 31 18 69q0 37 -17.5 73.5t-47.5 52.5q5 30 5 56q0 85 -49 126t-136 41h-128q-131 0 -342 -73q-5 -2 -29 -10.5
t-35.5 -12.5t-35 -11.5t-38 -11t-33 -6.5t-31.5 -3h-32v-640h32q16 0 35.5 -9t40 -27t38.5 -35.5t40 -44t34.5 -42.5t31.5 -41t23 -30q55 -68 77 -91q41 -43 59.5 -109.5t30.5 -125.5t38 -85q96 0 128 47t32 145q0 59 -48 160.5t-48 159.5h352q50 0 89 38.5t39 89.5z
M1536 511q0 -103 -76 -179t-180 -76h-176q48 -99 48 -192q0 -118 -35 -186q-35 -69 -102 -101.5t-151 -32.5q-51 0 -90 37q-34 33 -54 82t-25.5 90.5t-17.5 84.5t-31 64q-48 50 -107 127q-101 131 -137 155h-274q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5
h288q22 0 138 40q128 44 223 66t200 22h112q140 0 226.5 -79t85.5 -216v-5q60 -77 60 -178q0 -22 -3 -43q38 -67 38 -144q0 -36 -9 -69q49 -73 49 -163z" />
    <glyph glyph-name="star_half" unicode="&#xf089;" horiz-adv-x="896" 
d="M832 1504v-1339l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41z" />
    <glyph glyph-name="heart_empty" unicode="&#xf08a;" horiz-adv-x="1792" 
d="M1664 940q0 81 -21.5 143t-55 98.5t-81.5 59.5t-94 31t-98 8t-112 -25.5t-110.5 -64t-86.5 -72t-60 -61.5q-18 -22 -49 -22t-49 22q-24 28 -60 61.5t-86.5 72t-110.5 64t-112 25.5t-98 -8t-94 -31t-81.5 -59.5t-55 -98.5t-21.5 -143q0 -168 187 -355l581 -560l580 559
q188 188 188 356zM1792 940q0 -221 -229 -450l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5
q224 0 351 -124t127 -344z" />
    <glyph glyph-name="signout" unicode="&#xf08b;" horiz-adv-x="1664" 
d="M640 96q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h320q13 0 22.5 -9.5t9.5 -22.5q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-66 0 -113 -47t-47 -113v-704
q0 -66 47 -113t113 -47h288h11h13t11.5 -1t11.5 -3t8 -5.5t7 -9t2 -13.5zM1568 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45z" />
    <glyph glyph-name="linkedin_sign" unicode="&#xf08c;" 
d="M237 122h231v694h-231v-694zM483 1030q-1 52 -36 86t-93 34t-94.5 -34t-36.5 -86q0 -51 35.5 -85.5t92.5 -34.5h1q59 0 95 34.5t36 85.5zM1068 122h231v398q0 154 -73 233t-193 79q-136 0 -209 -117h2v101h-231q3 -66 0 -694h231v388q0 38 7 56q15 35 45 59.5t74 24.5
q116 0 116 -157v-371zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="pushpin" unicode="&#xf08d;" horiz-adv-x="1152" 
d="M480 672v448q0 14 -9 23t-23 9t-23 -9t-9 -23v-448q0 -14 9 -23t23 -9t23 9t9 23zM1152 320q0 -26 -19 -45t-45 -19h-429l-51 -483q-2 -12 -10.5 -20.5t-20.5 -8.5h-1q-27 0 -32 27l-76 485h-404q-26 0 -45 19t-19 45q0 123 78.5 221.5t177.5 98.5v512q-52 0 -90 38
t-38 90t38 90t90 38h640q52 0 90 -38t38 -90t-38 -90t-90 -38v-512q99 0 177.5 -98.5t78.5 -221.5z" />
    <glyph glyph-name="external_link" unicode="&#xf08e;" horiz-adv-x="1792" 
d="M1408 608v-320q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v320
q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1792 1472v-512q0 -26 -19 -45t-45 -19t-45 19l-176 176l-652 -652q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l652 652l-176 176q-19 19 -19 45t19 45t45 19h512q26 0 45 -19t19 -45z" />
    <glyph glyph-name="signin" unicode="&#xf090;" 
d="M1184 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45zM1536 992v-704q0 -119 -84.5 -203.5t-203.5 -84.5h-320q-13 0 -22.5 9.5t-9.5 22.5
q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q66 0 113 47t47 113v704q0 66 -47 113t-113 47h-288h-11h-13t-11.5 1t-11.5 3t-8 5.5t-7 9t-2 13.5q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="trophy" unicode="&#xf091;" horiz-adv-x="1664" 
d="M458 653q-74 162 -74 371h-256v-96q0 -78 94.5 -162t235.5 -113zM1536 928v96h-256q0 -209 -74 -371q141 29 235.5 113t94.5 162zM1664 1056v-128q0 -71 -41.5 -143t-112 -130t-173 -97.5t-215.5 -44.5q-42 -54 -95 -95q-38 -34 -52.5 -72.5t-14.5 -89.5q0 -54 30.5 -91
t97.5 -37q75 0 133.5 -45.5t58.5 -114.5v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 69 58.5 114.5t133.5 45.5q67 0 97.5 37t30.5 91q0 51 -14.5 89.5t-52.5 72.5q-53 41 -95 95q-113 5 -215.5 44.5t-173 97.5t-112 130t-41.5 143v128q0 40 28 68t68 28h288v96
q0 66 47 113t113 47h576q66 0 113 -47t47 -113v-96h288q40 0 68 -28t28 -68z" />
    <glyph glyph-name="github_sign" unicode="&#xf092;" 
d="M519 336q4 6 -3 13q-9 7 -14 2q-4 -6 3 -13q9 -7 14 -2zM491 377q-5 7 -12 4q-6 -4 0 -12q7 -8 12 -5q6 4 0 13zM450 417q2 4 -5 8q-7 2 -8 -2q-3 -5 4 -8q8 -2 9 2zM471 394q2 1 1.5 4.5t-3.5 5.5q-6 7 -10 3t1 -11q6 -6 11 -2zM557 319q2 7 -9 11q-9 3 -13 -4
q-2 -7 9 -11q9 -3 13 4zM599 316q0 8 -12 8q-10 0 -10 -8t11 -8t11 8zM638 323q-2 7 -13 5t-9 -9q2 -8 12 -6t10 10zM1280 640q0 212 -150 362t-362 150t-362 -150t-150 -362q0 -167 98 -300.5t252 -185.5q18 -3 26.5 5t8.5 20q0 52 -1 95q-6 -1 -15.5 -2.5t-35.5 -2t-48 4
t-43.5 20t-29.5 41.5q-23 59 -57 74q-2 1 -4.5 3.5l-8 8t-7 9.5t4 7.5t19.5 3.5q6 0 15 -2t30 -15.5t33 -35.5q16 -28 37.5 -42t43.5 -14t38 3.5t30 9.5q7 47 33 69q-49 6 -86 18.5t-73 39t-55.5 76t-19.5 119.5q0 79 53 137q-24 62 5 136q19 6 54.5 -7.5t60.5 -29.5l26 -16
q58 17 128 17t128 -17q11 7 28.5 18t55.5 26t57 9q29 -74 5 -136q53 -58 53 -137q0 -57 -14 -100.5t-35.5 -70t-53.5 -44.5t-62.5 -26t-68.5 -12q35 -31 35 -95q0 -40 -0.5 -89t-0.5 -51q0 -12 8.5 -20t26.5 -5q154 52 252 185.5t98 300.5zM1536 1120v-960
q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="upload_alt" unicode="&#xf093;" horiz-adv-x="1664" 
d="M1280 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 288v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h427q21 -56 70.5 -92
t110.5 -36h256q61 0 110.5 36t70.5 92h427q40 0 68 -28t28 -68zM1339 936q-17 -40 -59 -40h-256v-448q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v448h-256q-42 0 -59 40q-17 39 14 69l448 448q18 19 45 19t45 -19l448 -448q31 -30 14 -69z" />
    <glyph glyph-name="lemon" unicode="&#xf094;" 
d="M1407 710q0 44 -7 113.5t-18 96.5q-12 30 -17 44t-9 36.5t-4 48.5q0 23 5 68.5t5 67.5q0 37 -10 55q-4 1 -13 1q-19 0 -58 -4.5t-59 -4.5q-60 0 -176 24t-175 24q-43 0 -94.5 -11.5t-85 -23.5t-89.5 -34q-137 -54 -202 -103q-96 -73 -159.5 -189.5t-88 -236t-24.5 -248.5
q0 -40 12.5 -120t12.5 -121q0 -23 -11 -66.5t-11 -65.5t12 -36.5t34 -14.5q24 0 72.5 11t73.5 11q57 0 169.5 -15.5t169.5 -15.5q181 0 284 36q129 45 235.5 152.5t166 245.5t59.5 275zM1535 712q0 -165 -70 -327.5t-196 -288t-281 -180.5q-124 -44 -326 -44
q-57 0 -170 14.5t-169 14.5q-24 0 -72.5 -14.5t-73.5 -14.5q-73 0 -123.5 55.5t-50.5 128.5q0 24 11 68t11 67q0 40 -12.5 120.5t-12.5 121.5q0 111 18 217.5t54.5 209.5t100.5 194t150 156q78 59 232 120q194 78 316 78q60 0 175.5 -24t173.5 -24q19 0 57 5t58 5
q81 0 118 -50.5t37 -134.5q0 -23 -5 -68t-5 -68q0 -13 2 -25t3.5 -16.5t7.5 -20.5t8 -20q16 -40 25 -118.5t9 -136.5z" />
    <glyph glyph-name="phone" unicode="&#xf095;" horiz-adv-x="1408" 
d="M1408 296q0 -27 -10 -70.5t-21 -68.5q-21 -50 -122 -106q-94 -51 -186 -51q-27 0 -53 3.5t-57.5 12.5t-47 14.5t-55.5 20.5t-49 18q-98 35 -175 83q-127 79 -264 216t-216 264q-48 77 -83 175q-3 9 -18 49t-20.5 55.5t-14.5 47t-12.5 57.5t-3.5 53q0 92 51 186
q56 101 106 122q25 11 68.5 21t70.5 10q14 0 21 -3q18 -6 53 -76q11 -19 30 -54t35 -63.5t31 -53.5q3 -4 17.5 -25t21.5 -35.5t7 -28.5q0 -20 -28.5 -50t-62 -55t-62 -53t-28.5 -46q0 -9 5 -22.5t8.5 -20.5t14 -24t11.5 -19q76 -137 174 -235t235 -174q2 -1 19 -11.5t24 -14
t20.5 -8.5t22.5 -5q18 0 46 28.5t53 62t55 62t50 28.5q14 0 28.5 -7t35.5 -21.5t25 -17.5q25 -15 53.5 -31t63.5 -35t54 -30q70 -35 76 -53q3 -7 3 -21z" />
    <glyph glyph-name="check_empty" unicode="&#xf096;" horiz-adv-x="1408" 
d="M1120 1280h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v832q0 66 -47 113t-113 47zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832
q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="bookmark_empty" unicode="&#xf097;" horiz-adv-x="1280" 
d="M1152 1280h-1024v-1242l423 406l89 85l89 -85l423 -406v1242zM1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289
q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
    <glyph glyph-name="phone_sign" unicode="&#xf098;" 
d="M1280 343q0 11 -2 16t-18 16.5t-40.5 25t-47.5 26.5t-45.5 25t-28.5 15q-5 3 -19 13t-25 15t-21 5q-15 0 -36.5 -20.5t-39.5 -45t-38.5 -45t-33.5 -20.5q-7 0 -16.5 3.5t-15.5 6.5t-17 9.5t-14 8.5q-99 55 -170 126.5t-127 170.5q-2 3 -8.5 14t-9.5 17t-6.5 15.5
t-3.5 16.5q0 13 20.5 33.5t45 38.5t45 39.5t20.5 36.5q0 10 -5 21t-15 25t-13 19q-3 6 -15 28.5t-25 45.5t-26.5 47.5t-25 40.5t-16.5 18t-16 2q-48 0 -101 -22q-46 -21 -80 -94.5t-34 -130.5q0 -16 2.5 -34t5 -30.5t9 -33t10 -29.5t12.5 -33t11 -30q60 -164 216.5 -320.5
t320.5 -216.5q6 -2 30 -11t33 -12.5t29.5 -10t33 -9t30.5 -5t34 -2.5q57 0 130.5 34t94.5 80q22 53 22 101zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z
" />
    <glyph glyph-name="twitter" unicode="&#xf099;" horiz-adv-x="1664" 
d="M1620 1128q-67 -98 -162 -167q1 -14 1 -42q0 -130 -38 -259.5t-115.5 -248.5t-184.5 -210.5t-258 -146t-323 -54.5q-271 0 -496 145q35 -4 78 -4q225 0 401 138q-105 2 -188 64.5t-114 159.5q33 -5 61 -5q43 0 85 11q-112 23 -185.5 111.5t-73.5 205.5v4q68 -38 146 -41
q-66 44 -105 115t-39 154q0 88 44 163q121 -149 294.5 -238.5t371.5 -99.5q-8 38 -8 74q0 134 94.5 228.5t228.5 94.5q140 0 236 -102q109 21 205 78q-37 -115 -142 -178q93 10 186 50z" />
    <glyph glyph-name="facebook" unicode="&#xf09a;" horiz-adv-x="1024" 
d="M959 1524v-264h-157q-86 0 -116 -36t-30 -108v-189h293l-39 -296h-254v-759h-306v759h-255v296h255v218q0 186 104 288.5t277 102.5q147 0 228 -12z" />
    <glyph glyph-name="github" unicode="&#xf09b;" 
d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5q0 -251 -146.5 -451.5t-378.5 -277.5q-27 -5 -40 7t-13 30q0 3 0.5 76.5t0.5 134.5q0 97 -52 142q57 6 102.5 18t94 39t81 66.5t53 105t20.5 150.5q0 119 -79 206q37 91 -8 204q-28 9 -81 -11t-92 -44l-38 -24
q-93 26 -192 26t-192 -26q-16 11 -42.5 27t-83.5 38.5t-85 13.5q-45 -113 -8 -204q-79 -87 -79 -206q0 -85 20.5 -150t52.5 -105t80.5 -67t94 -39t102.5 -18q-39 -36 -49 -103q-21 -10 -45 -15t-57 -5t-65.5 21.5t-55.5 62.5q-19 32 -48.5 52t-49.5 24l-20 3q-21 0 -29 -4.5
t-5 -11.5t9 -14t13 -12l7 -5q22 -10 43.5 -38t31.5 -51l10 -23q13 -38 44 -61.5t67 -30t69.5 -7t55.5 3.5l23 4q0 -38 0.5 -88.5t0.5 -54.5q0 -18 -13 -30t-40 -7q-232 77 -378.5 277.5t-146.5 451.5q0 209 103 385.5t279.5 279.5t385.5 103zM291 305q3 7 -7 12
q-10 3 -13 -2q-3 -7 7 -12q9 -6 13 2zM322 271q7 5 -2 16q-10 9 -16 3q-7 -5 2 -16q10 -10 16 -3zM352 226q9 7 0 19q-8 13 -17 6q-9 -5 0 -18t17 -7zM394 184q8 8 -4 19q-12 12 -20 3q-9 -8 4 -19q12 -12 20 -3zM451 159q3 11 -13 16q-15 4 -19 -7t13 -15q15 -6 19 6z
M514 154q0 13 -17 11q-16 0 -16 -11q0 -13 17 -11q16 0 16 11zM572 164q-2 11 -18 9q-16 -3 -14 -15t18 -8t14 14z" />
    <glyph glyph-name="unlock" unicode="&#xf09c;" horiz-adv-x="1664" 
d="M1664 960v-256q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-192h96q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h672v192q0 185 131.5 316.5t316.5 131.5
t316.5 -131.5t131.5 -316.5z" />
    <glyph glyph-name="credit_card" unicode="&#xf09d;" horiz-adv-x="1920" 
d="M1760 1408q66 0 113 -47t47 -113v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600zM160 1280q-13 0 -22.5 -9.5t-9.5 -22.5v-224h1664v224q0 13 -9.5 22.5t-22.5 9.5h-1600zM1760 0q13 0 22.5 9.5t9.5 22.5v608h-1664v-608
q0 -13 9.5 -22.5t22.5 -9.5h1600zM256 128v128h256v-128h-256zM640 128v128h384v-128h-384z" />
    <glyph glyph-name="rss" unicode="&#xf09e;" horiz-adv-x="1408" 
d="M384 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 69q2 -28 -17 -48q-18 -21 -47 -21h-135q-25 0 -43 16.5t-20 41.5q-22 229 -184.5 391.5t-391.5 184.5q-25 2 -41.5 20t-16.5 43v135q0 29 21 47q17 17 43 17h5q160 -13 306 -80.5
t259 -181.5q114 -113 181.5 -259t80.5 -306zM1408 67q2 -27 -18 -47q-18 -20 -46 -20h-143q-26 0 -44.5 17.5t-19.5 42.5q-12 215 -101 408.5t-231.5 336t-336 231.5t-408.5 102q-25 1 -42.5 19.5t-17.5 43.5v143q0 28 20 46q18 18 44 18h3q262 -13 501.5 -120t425.5 -294
q187 -186 294 -425.5t120 -501.5z" />
    <glyph glyph-name="hdd" unicode="&#xf0a0;" 
d="M1040 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1296 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1408 160v320q0 13 -9.5 22.5t-22.5 9.5
h-1216q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h1216q13 0 22.5 9.5t9.5 22.5zM178 640h1180l-157 482q-4 13 -16 21.5t-26 8.5h-782q-14 0 -26 -8.5t-16 -21.5zM1536 480v-320q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v320q0 25 16 75
l197 606q17 53 63 86t101 33h782q55 0 101 -33t63 -86l197 -606q16 -50 16 -75z" />
    <glyph glyph-name="bullhorn" unicode="&#xf0a1;" horiz-adv-x="1792" 
d="M1664 896q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5v-384q0 -52 -38 -90t-90 -38q-417 347 -812 380q-58 -19 -91 -66t-31 -100.5t40 -92.5q-20 -33 -23 -65.5t6 -58t33.5 -55t48 -50t61.5 -50.5q-29 -58 -111.5 -83t-168.5 -11.5t-132 55.5q-7 23 -29.5 87.5
t-32 94.5t-23 89t-15 101t3.5 98.5t22 110.5h-122q-66 0 -113 47t-47 113v192q0 66 47 113t113 47h480q435 0 896 384q52 0 90 -38t38 -90v-384zM1536 292v954q-394 -302 -768 -343v-270q377 -42 768 -341z" />
    <glyph glyph-name="bell" unicode="&#xf0a2;" horiz-adv-x="1792" 
d="M912 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM246 128h1300q-266 300 -266 832q0 51 -24 105t-69 103t-121.5 80.5t-169.5 31.5t-169.5 -31.5t-121.5 -80.5t-69 -103t-24 -105q0 -532 -266 -832z
M1728 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q190 -28 307 -158.5
t117 -282.5q0 -139 19.5 -260t50 -206t74.5 -158.5t85 -119.5t91 -88z" />
    <glyph glyph-name="certificate" unicode="&#xf0a3;" 
d="M1376 640l138 -135q30 -28 20 -70q-12 -41 -52 -51l-188 -48l53 -186q12 -41 -19 -70q-29 -31 -70 -19l-186 53l-48 -188q-10 -40 -51 -52q-12 -2 -19 -2q-31 0 -51 22l-135 138l-135 -138q-28 -30 -70 -20q-41 11 -51 52l-48 188l-186 -53q-41 -12 -70 19q-31 29 -19 70
l53 186l-188 48q-40 10 -52 51q-10 42 20 70l138 135l-138 135q-30 28 -20 70q12 41 52 51l188 48l-53 186q-12 41 19 70q29 31 70 19l186 -53l48 188q10 41 51 51q41 12 70 -19l135 -139l135 139q29 30 70 19q41 -10 51 -51l48 -188l186 53q41 12 70 -19q31 -29 19 -70
l-53 -186l188 -48q40 -10 52 -51q10 -42 -20 -70z" />
    <glyph glyph-name="hand_right" unicode="&#xf0a4;" horiz-adv-x="1792" 
d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 768q0 51 -39 89.5t-89 38.5h-576q0 20 15 48.5t33 55t33 68t15 84.5q0 67 -44.5 97.5t-115.5 30.5q-24 0 -90 -139q-24 -44 -37 -65q-40 -64 -112 -145q-71 -81 -101 -106
q-69 -57 -140 -57h-32v-640h32q72 0 167 -32t193.5 -64t179.5 -32q189 0 189 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5h331q52 0 90 38t38 90zM1792 769q0 -105 -75.5 -181t-180.5 -76h-169q-4 -62 -37 -119q3 -21 3 -43
q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5q-133 0 -322 69q-164 59 -223 59h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h288q10 0 21.5 4.5t23.5 14t22.5 18t24 22.5t20.5 21.5t19 21.5t14 17q65 74 100 129q13 21 33 62t37 72t40.5 63t55 49.5
t69.5 17.5q125 0 206.5 -67t81.5 -189q0 -68 -22 -128h374q104 0 180 -76t76 -179z" />
    <glyph glyph-name="hand_left" unicode="&#xf0a5;" horiz-adv-x="1792" 
d="M1376 128h32v640h-32q-35 0 -67.5 12t-62.5 37t-50 46t-49 54q-8 9 -12 14q-72 81 -112 145q-14 22 -38 68q-1 3 -10.5 22.5t-18.5 36t-20 35.5t-21.5 30.5t-18.5 11.5q-71 0 -115.5 -30.5t-44.5 -97.5q0 -43 15 -84.5t33 -68t33 -55t15 -48.5h-576q-50 0 -89 -38.5
t-39 -89.5q0 -52 38 -90t90 -38h331q-15 -17 -25 -47.5t-10 -55.5q0 -69 53 -119q-18 -32 -18 -69t17.5 -73.5t47.5 -52.5q-4 -24 -4 -56q0 -85 48.5 -126t135.5 -41q84 0 183 32t194 64t167 32zM1664 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45z
M1792 768v-640q0 -53 -37.5 -90.5t-90.5 -37.5h-288q-59 0 -223 -59q-190 -69 -317 -69q-142 0 -230 77.5t-87 217.5l1 5q-61 76 -61 178q0 22 3 43q-33 57 -37 119h-169q-105 0 -180.5 76t-75.5 181q0 103 76 179t180 76h374q-22 60 -22 128q0 122 81.5 189t206.5 67
q38 0 69.5 -17.5t55 -49.5t40.5 -63t37 -72t33 -62q35 -55 100 -129q2 -3 14 -17t19 -21.5t20.5 -21.5t24 -22.5t22.5 -18t23.5 -14t21.5 -4.5h288q53 0 90.5 -37.5t37.5 -90.5z" />
    <glyph glyph-name="hand_up" unicode="&#xf0a6;" 
d="M1280 -64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 700q0 189 -167 189q-26 0 -56 -5q-16 30 -52.5 47.5t-73.5 17.5t-69 -18q-50 53 -119 53q-25 0 -55.5 -10t-47.5 -25v331q0 52 -38 90t-90 38q-51 0 -89.5 -39t-38.5 -89v-576
q-20 0 -48.5 15t-55 33t-68 33t-84.5 15q-67 0 -97.5 -44.5t-30.5 -115.5q0 -24 139 -90q44 -24 65 -37q64 -40 145 -112q81 -71 106 -101q57 -69 57 -140v-32h640v32q0 72 32 167t64 193.5t32 179.5zM1536 705q0 -133 -69 -322q-59 -164 -59 -223v-288q0 -53 -37.5 -90.5
t-90.5 -37.5h-640q-53 0 -90.5 37.5t-37.5 90.5v288q0 10 -4.5 21.5t-14 23.5t-18 22.5t-22.5 24t-21.5 20.5t-21.5 19t-17 14q-74 65 -129 100q-21 13 -62 33t-72 37t-63 40.5t-49.5 55t-17.5 69.5q0 125 67 206.5t189 81.5q68 0 128 -22v374q0 104 76 180t179 76
q105 0 181 -75.5t76 -180.5v-169q62 -4 119 -37q21 3 43 3q101 0 178 -60q139 1 219.5 -85t80.5 -227z" />
    <glyph glyph-name="hand_down" unicode="&#xf0a7;" 
d="M1408 576q0 84 -32 183t-64 194t-32 167v32h-640v-32q0 -35 -12 -67.5t-37 -62.5t-46 -50t-54 -49q-9 -8 -14 -12q-81 -72 -145 -112q-22 -14 -68 -38q-3 -1 -22.5 -10.5t-36 -18.5t-35.5 -20t-30.5 -21.5t-11.5 -18.5q0 -71 30.5 -115.5t97.5 -44.5q43 0 84.5 15t68 33
t55 33t48.5 15v-576q0 -50 38.5 -89t89.5 -39q52 0 90 38t38 90v331q46 -35 103 -35q69 0 119 53q32 -18 69 -18t73.5 17.5t52.5 47.5q24 -4 56 -4q85 0 126 48.5t41 135.5zM1280 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 580
q0 -142 -77.5 -230t-217.5 -87l-5 1q-76 -61 -178 -61q-22 0 -43 3q-54 -30 -119 -37v-169q0 -105 -76 -180.5t-181 -75.5q-103 0 -179 76t-76 180v374q-54 -22 -128 -22q-121 0 -188.5 81.5t-67.5 206.5q0 38 17.5 69.5t49.5 55t63 40.5t72 37t62 33q55 35 129 100
q3 2 17 14t21.5 19t21.5 20.5t22.5 24t18 22.5t14 23.5t4.5 21.5v288q0 53 37.5 90.5t90.5 37.5h640q53 0 90.5 -37.5t37.5 -90.5v-288q0 -59 59 -223q69 -190 69 -317z" />
    <glyph glyph-name="circle_arrow_left" unicode="&#xf0a8;" 
d="M1280 576v128q0 26 -19 45t-45 19h-502l189 189q19 19 19 45t-19 45l-91 91q-18 18 -45 18t-45 -18l-362 -362l-91 -91q-18 -18 -18 -45t18 -45l91 -91l362 -362q18 -18 45 -18t45 18l91 91q18 18 18 45t-18 45l-189 189h502q26 0 45 19t19 45zM1536 640
q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="circle_arrow_right" unicode="&#xf0a9;" 
d="M1285 640q0 27 -18 45l-91 91l-362 362q-18 18 -45 18t-45 -18l-91 -91q-18 -18 -18 -45t18 -45l189 -189h-502q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h502l-189 -189q-19 -19 -19 -45t19 -45l91 -91q18 -18 45 -18t45 18l362 362l91 91q18 18 18 45zM1536 640
q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="circle_arrow_up" unicode="&#xf0aa;" 
d="M1284 641q0 27 -18 45l-362 362l-91 91q-18 18 -45 18t-45 -18l-91 -91l-362 -362q-18 -18 -18 -45t18 -45l91 -91q18 -18 45 -18t45 18l189 189v-502q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v502l189 -189q19 -19 45 -19t45 19l91 91q18 18 18 45zM1536 640
q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="circle_arrow_down" unicode="&#xf0ab;" 
d="M1284 639q0 27 -18 45l-91 91q-18 18 -45 18t-45 -18l-189 -189v502q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-502l-189 189q-19 19 -45 19t-45 -19l-91 -91q-18 -18 -18 -45t18 -45l362 -362l91 -91q18 -18 45 -18t45 18l91 91l362 362q18 18 18 45zM1536 640
q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="globe" unicode="&#xf0ac;" 
d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1042 887q-2 -1 -9.5 -9.5t-13.5 -9.5q2 0 4.5 5t5 11t3.5 7q6 7 22 15q14 6 52 12q34 8 51 -11
q-2 2 9.5 13t14.5 12q3 2 15 4.5t15 7.5l2 22q-12 -1 -17.5 7t-6.5 21q0 -2 -6 -8q0 7 -4.5 8t-11.5 -1t-9 -1q-10 3 -15 7.5t-8 16.5t-4 15q-2 5 -9.5 11t-9.5 10q-1 2 -2.5 5.5t-3 6.5t-4 5.5t-5.5 2.5t-7 -5t-7.5 -10t-4.5 -5q-3 2 -6 1.5t-4.5 -1t-4.5 -3t-5 -3.5
q-3 -2 -8.5 -3t-8.5 -2q15 5 -1 11q-10 4 -16 3q9 4 7.5 12t-8.5 14h5q-1 4 -8.5 8.5t-17.5 8.5t-13 6q-8 5 -34 9.5t-33 0.5q-5 -6 -4.5 -10.5t4 -14t3.5 -12.5q1 -6 -5.5 -13t-6.5 -12q0 -7 14 -15.5t10 -21.5q-3 -8 -16 -16t-16 -12q-5 -8 -1.5 -18.5t10.5 -16.5
q2 -2 1.5 -4t-3.5 -4.5t-5.5 -4t-6.5 -3.5l-3 -2q-11 -5 -20.5 6t-13.5 26q-7 25 -16 30q-23 8 -29 -1q-5 13 -41 26q-25 9 -58 4q6 1 0 15q-7 15 -19 12q3 6 4 17.5t1 13.5q3 13 12 23q1 1 7 8.5t9.5 13.5t0.5 6q35 -4 50 11q5 5 11.5 17t10.5 17q9 6 14 5.5t14.5 -5.5
t14.5 -5q14 -1 15.5 11t-7.5 20q12 -1 3 17q-4 7 -8 9q-12 4 -27 -5q-8 -4 2 -8q-1 1 -9.5 -10.5t-16.5 -17.5t-16 5q-1 1 -5.5 13.5t-9.5 13.5q-8 0 -16 -15q3 8 -11 15t-24 8q19 12 -8 27q-7 4 -20.5 5t-19.5 -4q-5 -7 -5.5 -11.5t5 -8t10.5 -5.5t11.5 -4t8.5 -3
q14 -10 8 -14q-2 -1 -8.5 -3.5t-11.5 -4.5t-6 -4q-3 -4 0 -14t-2 -14q-5 5 -9 17.5t-7 16.5q7 -9 -25 -6l-10 1q-4 0 -16 -2t-20.5 -1t-13.5 8q-4 8 0 20q1 4 4 2q-4 3 -11 9.5t-10 8.5q-46 -15 -94 -41q6 -1 12 1q5 2 13 6.5t10 5.5q34 14 42 7l5 5q14 -16 20 -25
q-7 4 -30 1q-20 -6 -22 -12q7 -12 5 -18q-4 3 -11.5 10t-14.5 11t-15 5q-16 0 -22 -1q-146 -80 -235 -222q7 -7 12 -8q4 -1 5 -9t2.5 -11t11.5 3q9 -8 3 -19q1 1 44 -27q19 -17 21 -21q3 -11 -10 -18q-1 2 -9 9t-9 4q-3 -5 0.5 -18.5t10.5 -12.5q-7 0 -9.5 -16t-2.5 -35.5
t-1 -23.5l2 -1q-3 -12 5.5 -34.5t21.5 -19.5q-13 -3 20 -43q6 -8 8 -9q3 -2 12 -7.5t15 -10t10 -10.5q4 -5 10 -22.5t14 -23.5q-2 -6 9.5 -20t10.5 -23q-1 0 -2.5 -1t-2.5 -1q3 -7 15.5 -14t15.5 -13q1 -3 2 -10t3 -11t8 -2q2 20 -24 62q-15 25 -17 29q-3 5 -5.5 15.5
t-4.5 14.5q2 0 6 -1.5t8.5 -3.5t7.5 -4t2 -3q-3 -7 2 -17.5t12 -18.5t17 -19t12 -13q6 -6 14 -19.5t0 -13.5q9 0 20 -10.5t17 -19.5q5 -8 8 -26t5 -24q2 -7 8.5 -13.5t12.5 -9.5l16 -8t13 -7q5 -2 18.5 -10.5t21.5 -11.5q10 -4 16 -4t14.5 2.5t13.5 3.5q15 2 29 -15t21 -21
q36 -19 55 -11q-2 -1 0.5 -7.5t8 -15.5t9 -14.5t5.5 -8.5q5 -6 18 -15t18 -15q6 4 7 9q-3 -8 7 -20t18 -10q14 3 14 32q-31 -15 -49 18q0 1 -2.5 5.5t-4 8.5t-2.5 8.5t0 7.5t5 3q9 0 10 3.5t-2 12.5t-4 13q-1 8 -11 20t-12 15q-5 -9 -16 -8t-16 9q0 -1 -1.5 -5.5t-1.5 -6.5
q-13 0 -15 1q1 3 2.5 17.5t3.5 22.5q1 4 5.5 12t7.5 14.5t4 12.5t-4.5 9.5t-17.5 2.5q-19 -1 -26 -20q-1 -3 -3 -10.5t-5 -11.5t-9 -7q-7 -3 -24 -2t-24 5q-13 8 -22.5 29t-9.5 37q0 10 2.5 26.5t3 25t-5.5 24.5q3 2 9 9.5t10 10.5q2 1 4.5 1.5t4.5 0t4 1.5t3 6q-1 1 -4 3
q-3 3 -4 3q7 -3 28.5 1.5t27.5 -1.5q15 -11 22 2q0 1 -2.5 9.5t-0.5 13.5q5 -27 29 -9q3 -3 15.5 -5t17.5 -5q3 -2 7 -5.5t5.5 -4.5t5 0.5t8.5 6.5q10 -14 12 -24q11 -40 19 -44q7 -3 11 -2t4.5 9.5t0 14t-1.5 12.5l-1 8v18l-1 8q-15 3 -18.5 12t1.5 18.5t15 18.5q1 1 8 3.5
t15.5 6.5t12.5 8q21 19 15 35q7 0 11 9q-1 0 -5 3t-7.5 5t-4.5 2q9 5 2 16q5 3 7.5 11t7.5 10q9 -12 21 -2q8 8 1 16q5 7 20.5 10.5t18.5 9.5q7 -2 8 2t1 12t3 12q4 5 15 9t13 5l17 11q3 4 0 4q18 -2 31 11q10 11 -6 20q3 6 -3 9.5t-15 5.5q3 1 11.5 0.5t10.5 1.5
q15 10 -7 16q-17 5 -43 -12zM879 10q206 36 351 189q-3 3 -12.5 4.5t-12.5 3.5q-18 7 -24 8q1 7 -2.5 13t-8 9t-12.5 8t-11 7q-2 2 -7 6t-7 5.5t-7.5 4.5t-8.5 2t-10 -1l-3 -1q-3 -1 -5.5 -2.5t-5.5 -3t-4 -3t0 -2.5q-21 17 -36 22q-5 1 -11 5.5t-10.5 7t-10 1.5t-11.5 -7
q-5 -5 -6 -15t-2 -13q-7 5 0 17.5t2 18.5q-3 6 -10.5 4.5t-12 -4.5t-11.5 -8.5t-9 -6.5t-8.5 -5.5t-8.5 -7.5q-3 -4 -6 -12t-5 -11q-2 4 -11.5 6.5t-9.5 5.5q2 -10 4 -35t5 -38q7 -31 -12 -48q-27 -25 -29 -40q-4 -22 12 -26q0 -7 -8 -20.5t-7 -21.5q0 -6 2 -16z" />
    <glyph glyph-name="wrench" unicode="&#xf0ad;" horiz-adv-x="1664" 
d="M384 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1028 484l-682 -682q-37 -37 -90 -37q-52 0 -91 37l-106 108q-38 36 -38 90q0 53 38 91l681 681q39 -98 114.5 -173.5t173.5 -114.5zM1662 919q0 -39 -23 -106q-47 -134 -164.5 -217.5
t-258.5 -83.5q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q58 0 121.5 -16.5t107.5 -46.5q16 -11 16 -28t-16 -28l-293 -169v-224l193 -107q5 3 79 48.5t135.5 81t70.5 35.5q15 0 23.5 -10t8.5 -25z" />
    <glyph glyph-name="tasks" unicode="&#xf0ae;" horiz-adv-x="1792" 
d="M1024 128h640v128h-640v-128zM640 640h1024v128h-1024v-128zM1280 1152h384v128h-384v-128zM1792 320v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 832v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19
t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
    <glyph glyph-name="filter" unicode="&#xf0b0;" horiz-adv-x="1408" 
d="M1403 1241q17 -41 -14 -70l-493 -493v-742q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-256 256q-19 19 -19 45v486l-493 493q-31 29 -14 70q17 39 59 39h1280q42 0 59 -39z" />
    <glyph glyph-name="briefcase" unicode="&#xf0b1;" horiz-adv-x="1792" 
d="M640 1280h512v128h-512v-128zM1792 640v-480q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v480h672v-160q0 -26 19 -45t45 -19h320q26 0 45 19t19 45v160h672zM1024 640v-128h-256v128h256zM1792 1120v-384h-1792v384q0 66 47 113t113 47h352v160q0 40 28 68
t68 28h576q40 0 68 -28t28 -68v-160h352q66 0 113 -47t47 -113z" />
    <glyph glyph-name="fullscreen" unicode="&#xf0b2;" 
d="M1283 995l-355 -355l355 -355l144 144q29 31 70 14q39 -17 39 -59v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l144 144l-355 355l-355 -355l144 -144q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l144 -144
l355 355l-355 355l-144 -144q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v448q0 26 19 45t45 19h448q42 0 59 -40q17 -39 -14 -69l-144 -144l355 -355l355 355l-144 144q-31 30 -14 69q17 40 59 40h448q26 0 45 -19t19 -45v-448q0 -42 -39 -59q-13 -5 -25 -5q-26 0 -45 19z
" />
    <glyph glyph-name="group" unicode="&#xf0c0;" horiz-adv-x="1920" 
d="M593 640q-162 -5 -265 -128h-134q-82 0 -138 40.5t-56 118.5q0 353 124 353q6 0 43.5 -21t97.5 -42.5t119 -21.5q67 0 133 23q-5 -37 -5 -66q0 -139 81 -256zM1664 3q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5
t43 97.5t62 81t85.5 53.5t111.5 20q10 0 43 -21.5t73 -48t107 -48t135 -21.5t135 21.5t107 48t73 48t43 21.5q61 0 111.5 -20t85.5 -53.5t62 -81t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM640 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75
t75 -181zM1344 896q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5zM1920 671q0 -78 -56 -118.5t-138 -40.5h-134q-103 123 -265 128q81 117 81 256q0 29 -5 66q66 -23 133 -23q59 0 119 21.5t97.5 42.5
t43.5 21q124 0 124 -353zM1792 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181z" />
    <glyph glyph-name="link" unicode="&#xf0c1;" horiz-adv-x="1664" 
d="M1456 320q0 40 -28 68l-208 208q-28 28 -68 28q-42 0 -72 -32q3 -3 19 -18.5t21.5 -21.5t15 -19t13 -25.5t3.5 -27.5q0 -40 -28 -68t-68 -28q-15 0 -27.5 3.5t-25.5 13t-19 15t-21.5 21.5t-18.5 19q-33 -31 -33 -73q0 -40 28 -68l206 -207q27 -27 68 -27q40 0 68 26
l147 146q28 28 28 67zM753 1025q0 40 -28 68l-206 207q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l208 -208q27 -27 68 -27q42 0 72 31q-3 3 -19 18.5t-21.5 21.5t-15 19t-13 25.5t-3.5 27.5q0 40 28 68t68 28q15 0 27.5 -3.5t25.5 -13t19 -15
t21.5 -21.5t18.5 -19q33 31 33 73zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-206 207q-83 83 -83 203q0 123 88 209l-88 88q-86 -88 -208 -88q-120 0 -204 84l-208 208q-84 84 -84 204t85 203l147 146q83 83 203 83q121 0 204 -85l206 -207
q83 -83 83 -203q0 -123 -88 -209l88 -88q86 88 208 88q120 0 204 -84l208 -208q84 -84 84 -204z" />
    <glyph glyph-name="cloud" unicode="&#xf0c2;" horiz-adv-x="1920" 
d="M1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088q-185 0 -316.5 131.5t-131.5 316.5q0 132 71 241.5t187 163.5q-2 28 -2 43q0 212 150 362t362 150q158 0 286.5 -88t187.5 -230q70 62 166 62q106 0 181 -75t75 -181q0 -75 -41 -138q129 -30 213 -134.5t84 -239.5z
" />
    <glyph glyph-name="beaker" unicode="&#xf0c3;" horiz-adv-x="1664" 
d="M1527 88q56 -89 21.5 -152.5t-140.5 -63.5h-1152q-106 0 -140.5 63.5t21.5 152.5l503 793v399h-64q-26 0 -45 19t-19 45t19 45t45 19h512q26 0 45 -19t19 -45t-19 -45t-45 -19h-64v-399zM748 813l-272 -429h712l-272 429l-20 31v37v399h-128v-399v-37z" />
    <glyph glyph-name="cut" unicode="&#xf0c4;" horiz-adv-x="1792" 
d="M960 640q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1260 576l507 -398q28 -20 25 -56q-5 -35 -35 -51l-128 -64q-13 -7 -29 -7q-17 0 -31 8l-690 387l-110 -66q-8 -4 -12 -5q14 -49 10 -97q-7 -77 -56 -147.5t-132 -123.5q-132 -84 -277 -84
q-136 0 -222 78q-90 84 -79 207q7 76 56 147t131 124q132 84 278 84q83 0 151 -31q9 13 22 22l122 73l-122 73q-13 9 -22 22q-68 -31 -151 -31q-146 0 -278 84q-82 53 -131 124t-56 147q-5 59 15.5 113t63.5 93q85 79 222 79q145 0 277 -84q83 -52 132 -123t56 -148
q4 -48 -10 -97q4 -1 12 -5l110 -66l690 387q14 8 31 8q16 0 29 -7l128 -64q30 -16 35 -51q3 -36 -25 -56zM579 836q46 42 21 108t-106 117q-92 59 -192 59q-74 0 -113 -36q-46 -42 -21 -108t106 -117q92 -59 192 -59q74 0 113 36zM494 91q81 51 106 117t-21 108
q-39 36 -113 36q-100 0 -192 -59q-81 -51 -106 -117t21 -108q39 -36 113 -36q100 0 192 59zM672 704l96 -58v11q0 36 33 56l14 8l-79 47l-26 -26q-3 -3 -10 -11t-12 -12q-2 -2 -4 -3.5t-3 -2.5zM896 480l96 -32l736 576l-128 64l-768 -431v-113l-160 -96l9 -8q2 -2 7 -6
q4 -4 11 -12t11 -12l26 -26zM1600 64l128 64l-520 408l-177 -138q-2 -3 -13 -7z" />
    <glyph glyph-name="copy" unicode="&#xf0c5;" horiz-adv-x="1792" 
d="M1696 1152q40 0 68 -28t28 -68v-1216q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v288h-544q-40 0 -68 28t-28 68v672q0 40 20 88t48 76l408 408q28 28 76 48t88 20h416q40 0 68 -28t28 -68v-328q68 40 128 40h416zM1152 939l-299 -299h299v299zM512 1323l-299 -299
h299v299zM708 676l316 316v416h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h512v256q0 40 20 88t48 76zM1664 -128v1152h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h896z" />
    <glyph glyph-name="paper_clip" unicode="&#xf0c6;" horiz-adv-x="1408" 
d="M1404 151q0 -117 -79 -196t-196 -79q-135 0 -235 100l-777 776q-113 115 -113 271q0 159 110 270t269 111q158 0 273 -113l605 -606q10 -10 10 -22q0 -16 -30.5 -46.5t-46.5 -30.5q-13 0 -23 10l-606 607q-79 77 -181 77q-106 0 -179 -75t-73 -181q0 -105 76 -181
l776 -777q63 -63 145 -63q64 0 106 42t42 106q0 82 -63 145l-581 581q-26 24 -60 24q-29 0 -48 -19t-19 -48q0 -32 25 -59l410 -410q10 -10 10 -22q0 -16 -31 -47t-47 -31q-12 0 -22 10l-410 410q-63 61 -63 149q0 82 57 139t139 57q88 0 149 -63l581 -581q100 -98 100 -235
z" />
    <glyph glyph-name="save" unicode="&#xf0c7;" 
d="M384 0h768v384h-768v-384zM1280 0h128v896q0 14 -10 38.5t-20 34.5l-281 281q-10 10 -34 20t-39 10v-416q0 -40 -28 -68t-68 -28h-576q-40 0 -68 28t-28 68v416h-128v-1280h128v416q0 40 28 68t68 28h832q40 0 68 -28t28 -68v-416zM896 928v320q0 13 -9.5 22.5t-22.5 9.5
h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1536 896v-928q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h928q40 0 88 -20t76 -48l280 -280q28 -28 48 -76t20 -88z" />
    <glyph glyph-name="sign_blank" unicode="&#xf0c8;" 
d="M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="reorder" unicode="&#xf0c9;" 
d="M1536 192v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 704v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 1216v-128q0 -26 -19 -45
t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
    <glyph glyph-name="ul" unicode="&#xf0ca;" horiz-adv-x="1792" 
d="M384 128q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 640q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5
t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1152q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z
M1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" />
    <glyph glyph-name="ol" unicode="&#xf0cb;" horiz-adv-x="1792" 
d="M381 -84q0 -80 -54.5 -126t-135.5 -46q-106 0 -172 66l57 88q49 -45 106 -45q29 0 50.5 14.5t21.5 42.5q0 64 -105 56l-26 56q8 10 32.5 43.5t42.5 54t37 38.5v1q-16 0 -48.5 -1t-48.5 -1v-53h-106v152h333v-88l-95 -115q51 -12 81 -49t30 -88zM383 543v-159h-362
q-6 36 -6 54q0 51 23.5 93t56.5 68t66 47.5t56.5 43.5t23.5 45q0 25 -14.5 38.5t-39.5 13.5q-46 0 -81 -58l-85 59q24 51 71.5 79.5t105.5 28.5q73 0 123 -41.5t50 -112.5q0 -50 -34 -91.5t-75 -64.5t-75.5 -50.5t-35.5 -52.5h127v60h105zM1792 224v-192q0 -13 -9.5 -22.5
t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1123v-99h-335v99h107q0 41 0.5 121.5t0.5 121.5v12h-2q-8 -17 -50 -54l-71 76l136 127h106v-404h108zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216
q-13 0 -22.5 9.5t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" />
    <glyph glyph-name="strikethrough" unicode="&#xf0cc;" horiz-adv-x="1792" 
d="M1760 640q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1728q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h1728zM483 704q-28 35 -51 80q-48 98 -48 188q0 181 134 309q133 127 393 127q50 0 167 -19q66 -12 177 -48q10 -38 21 -118q14 -123 14 -183q0 -18 -5 -45l-12 -3l-84 6
l-14 2q-50 149 -103 205q-88 91 -210 91q-114 0 -182 -59q-67 -58 -67 -146q0 -73 66 -140t279 -129q69 -20 173 -66q58 -28 95 -52h-743zM990 448h411q7 -39 7 -92q0 -111 -41 -212q-23 -56 -71 -104q-37 -35 -109 -81q-80 -48 -153 -66q-80 -21 -203 -21q-114 0 -195 23
l-140 40q-57 16 -72 28q-8 8 -8 22v13q0 108 -2 156q-1 30 0 68l2 37v44l102 2q15 -34 30 -71t22.5 -56t12.5 -27q35 -57 80 -94q43 -36 105 -57q59 -22 132 -22q64 0 139 27q77 26 122 86q47 61 47 129q0 84 -81 157q-34 29 -137 71z" />
    <glyph glyph-name="underline" unicode="&#xf0cd;" 
d="M48 1313q-37 2 -45 4l-3 88q13 1 40 1q60 0 112 -4q132 -7 166 -7q86 0 168 3q116 4 146 5q56 0 86 2l-1 -14l2 -64v-9q-60 -9 -124 -9q-60 0 -79 -25q-13 -14 -13 -132q0 -13 0.5 -32.5t0.5 -25.5l1 -229l14 -280q6 -124 51 -202q35 -59 96 -92q88 -47 177 -47
q104 0 191 28q56 18 99 51q48 36 65 64q36 56 53 114q21 73 21 229q0 79 -3.5 128t-11 122.5t-13.5 159.5l-4 59q-5 67 -24 88q-34 35 -77 34l-100 -2l-14 3l2 86h84l205 -10q76 -3 196 10l18 -2q6 -38 6 -51q0 -7 -4 -31q-45 -12 -84 -13q-73 -11 -79 -17q-15 -15 -15 -41
q0 -7 1.5 -27t1.5 -31q8 -19 22 -396q6 -195 -15 -304q-15 -76 -41 -122q-38 -65 -112 -123q-75 -57 -182 -89q-109 -33 -255 -33q-167 0 -284 46q-119 47 -179 122q-61 76 -83 195q-16 80 -16 237v333q0 188 -17 213q-25 36 -147 39zM1536 -96v64q0 14 -9 23t-23 9h-1472
q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h1472q14 0 23 9t9 23z" />
    <glyph glyph-name="table" unicode="&#xf0ce;" horiz-adv-x="1664" 
d="M512 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23
v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 160v192
q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192
q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1664 1248v-1088q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1344q66 0 113 -47t47 -113
z" />
    <glyph glyph-name="magic" unicode="&#xf0d0;" horiz-adv-x="1664" 
d="M1190 955l293 293l-107 107l-293 -293zM1637 1248q0 -27 -18 -45l-1286 -1286q-18 -18 -45 -18t-45 18l-198 198q-18 18 -18 45t18 45l1286 1286q18 18 45 18t45 -18l198 -198q18 -18 18 -45zM286 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM636 1276
l196 -60l-196 -60l-60 -196l-60 196l-196 60l196 60l60 196zM1566 798l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM926 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98z" />
    <glyph glyph-name="truck" unicode="&#xf0d1;" horiz-adv-x="1792" 
d="M640 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM256 640h384v256h-158q-13 0 -22 -9l-195 -195q-9 -9 -9 -22v-30zM1536 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1792 1216v-1024q0 -15 -4 -26.5t-13.5 -18.5
t-16.5 -11.5t-23.5 -6t-22.5 -2t-25.5 0t-22.5 0.5q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-64q-3 0 -22.5 -0.5t-25.5 0t-22.5 2t-23.5 6t-16.5 11.5t-13.5 18.5t-4 26.5q0 26 19 45t45 19v320q0 8 -0.5 35t0 38
t2.5 34.5t6.5 37t14 30.5t22.5 30l198 198q19 19 50.5 32t58.5 13h160v192q0 26 19 45t45 19h1024q26 0 45 -19t19 -45z" />
    <glyph glyph-name="pinterest" unicode="&#xf0d2;" 
d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103q-111 0 -218 32q59 93 78 164q9 34 54 211q20 -39 73 -67.5t114 -28.5q121 0 216 68.5t147 188.5t52 270q0 114 -59.5 214t-172.5 163t-255 63q-105 0 -196 -29t-154.5 -77t-109 -110.5t-67 -129.5t-21.5 -134
q0 -104 40 -183t117 -111q30 -12 38 20q2 7 8 31t8 30q6 23 -11 43q-51 61 -51 151q0 151 104.5 259.5t273.5 108.5q151 0 235.5 -82t84.5 -213q0 -170 -68.5 -289t-175.5 -119q-61 0 -98 43.5t-23 104.5q8 35 26.5 93.5t30 103t11.5 75.5q0 50 -27 83t-77 33
q-62 0 -105 -57t-43 -142q0 -73 25 -122l-99 -418q-17 -70 -13 -177q-206 91 -333 281t-127 423q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="pinterest_sign" unicode="&#xf0d3;" 
d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-725q85 122 108 210q9 34 53 209q21 -39 73.5 -67t112.5 -28q181 0 295.5 147.5t114.5 373.5q0 84 -35 162.5t-96.5 139t-152.5 97t-197 36.5q-104 0 -194.5 -28.5t-153 -76.5
t-107.5 -109.5t-66.5 -128t-21.5 -132.5q0 -102 39.5 -180t116.5 -110q13 -5 23.5 0t14.5 19q10 44 15 61q6 23 -11 42q-50 62 -50 150q0 150 103.5 256.5t270.5 106.5q149 0 232.5 -81t83.5 -210q0 -168 -67.5 -286t-173.5 -118q-60 0 -97 43.5t-23 103.5q8 34 26.5 92.5
t29.5 102t11 74.5q0 49 -26.5 81.5t-75.5 32.5q-61 0 -103.5 -56.5t-42.5 -139.5q0 -72 24 -121l-98 -414q-24 -100 -7 -254h-183q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960z" />
    <glyph glyph-name="google_plus_sign" unicode="&#xf0d4;" 
d="M917 631q0 26 -6 64h-362v-132h217q-3 -24 -16.5 -50t-37.5 -53t-66.5 -44.5t-96.5 -17.5q-99 0 -169 71t-70 171t70 171t169 71q92 0 153 -59l104 101q-108 100 -257 100q-160 0 -272 -112.5t-112 -271.5t112 -271.5t272 -112.5q165 0 266.5 105t101.5 270zM1262 585
h109v110h-109v110h-110v-110h-110v-110h110v-110h110v110zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="google_plus" unicode="&#xf0d5;" horiz-adv-x="2304" 
d="M1437 623q0 -208 -87 -370.5t-248 -254t-369 -91.5q-149 0 -285 58t-234 156t-156 234t-58 285t58 285t156 234t234 156t285 58q286 0 491 -192l-199 -191q-117 113 -292 113q-123 0 -227.5 -62t-165.5 -168.5t-61 -232.5t61 -232.5t165.5 -168.5t227.5 -62
q83 0 152.5 23t114.5 57.5t78.5 78.5t49 83t21.5 74h-416v252h692q12 -63 12 -122zM2304 745v-210h-209v-209h-210v209h-209v210h209v209h210v-209h209z" />
    <glyph glyph-name="money" unicode="&#xf0d6;" horiz-adv-x="1920" 
d="M768 384h384v96h-128v448h-114l-148 -137l77 -80q42 37 55 57h2v-288h-128v-96zM1280 640q0 -70 -21 -142t-59.5 -134t-101.5 -101t-138 -39t-138 39t-101.5 101t-59.5 134t-21 142t21 142t59.5 134t101.5 101t138 39t138 -39t101.5 -101t59.5 -134t21 -142zM1792 384
v512q-106 0 -181 75t-75 181h-1152q0 -106 -75 -181t-181 -75v-512q106 0 181 -75t75 -181h1152q0 106 75 181t181 75zM1920 1216v-1152q0 -26 -19 -45t-45 -19h-1792q-26 0 -45 19t-19 45v1152q0 26 19 45t45 19h1792q26 0 45 -19t19 -45z" />
    <glyph glyph-name="caret_down" unicode="&#xf0d7;" horiz-adv-x="1024" 
d="M1024 832q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
    <glyph glyph-name="caret_up" unicode="&#xf0d8;" horiz-adv-x="1024" 
d="M1024 320q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
    <glyph glyph-name="caret_left" unicode="&#xf0d9;" horiz-adv-x="640" 
d="M640 1088v-896q0 -26 -19 -45t-45 -19t-45 19l-448 448q-19 19 -19 45t19 45l448 448q19 19 45 19t45 -19t19 -45z" />
    <glyph glyph-name="caret_right" unicode="&#xf0da;" horiz-adv-x="640" 
d="M576 640q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19t-19 45v896q0 26 19 45t45 19t45 -19l448 -448q19 -19 19 -45z" />
    <glyph glyph-name="columns" unicode="&#xf0db;" horiz-adv-x="1664" 
d="M160 0h608v1152h-640v-1120q0 -13 9.5 -22.5t22.5 -9.5zM1536 32v1120h-640v-1152h608q13 0 22.5 9.5t9.5 22.5zM1664 1248v-1216q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1344q66 0 113 -47t47 -113z" />
    <glyph glyph-name="sort" unicode="&#xf0dc;" horiz-adv-x="1024" 
d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45zM1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
    <glyph glyph-name="sort_down" unicode="&#xf0dd;" horiz-adv-x="1024" 
d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
    <glyph glyph-name="sort_up" unicode="&#xf0de;" horiz-adv-x="1024" 
d="M1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
    <glyph glyph-name="envelope_alt" unicode="&#xf0e0;" horiz-adv-x="1792" 
d="M1792 826v-794q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v794q44 -49 101 -87q362 -246 497 -345q57 -42 92.5 -65.5t94.5 -48t110 -24.5h1h1q51 0 110 24.5t94.5 48t92.5 65.5q170 123 498 345q57 39 100 87zM1792 1120q0 -79 -49 -151t-122 -123
q-376 -261 -468 -325q-10 -7 -42.5 -30.5t-54 -38t-52 -32.5t-57.5 -27t-50 -9h-1h-1q-23 0 -50 9t-57.5 27t-52 32.5t-54 38t-42.5 30.5q-91 64 -262 182.5t-205 142.5q-62 42 -117 115.5t-55 136.5q0 78 41.5 130t118.5 52h1472q65 0 112.5 -47t47.5 -113z" />
    <glyph glyph-name="linkedin" unicode="&#xf0e1;" 
d="M349 911v-991h-330v991h330zM370 1217q1 -73 -50.5 -122t-135.5 -49h-2q-82 0 -132 49t-50 122q0 74 51.5 122.5t134.5 48.5t133 -48.5t51 -122.5zM1536 488v-568h-329v530q0 105 -40.5 164.5t-126.5 59.5q-63 0 -105.5 -34.5t-63.5 -85.5q-11 -30 -11 -81v-553h-329
q2 399 2 647t-1 296l-1 48h329v-144h-2q20 32 41 56t56.5 52t87 43.5t114.5 15.5q171 0 275 -113.5t104 -332.5z" />
    <glyph glyph-name="undo" unicode="&#xf0e2;" 
d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5
t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298z" />
    <glyph glyph-name="legal" unicode="&#xf0e3;" horiz-adv-x="1792" 
d="M1771 0q0 -53 -37 -90l-107 -108q-39 -37 -91 -37q-53 0 -90 37l-363 364q-38 36 -38 90q0 53 43 96l-256 256l-126 -126q-14 -14 -34 -14t-34 14q2 -2 12.5 -12t12.5 -13t10 -11.5t10 -13.5t6 -13.5t5.5 -16.5t1.5 -18q0 -38 -28 -68q-3 -3 -16.5 -18t-19 -20.5
t-18.5 -16.5t-22 -15.5t-22 -9t-26 -4.5q-40 0 -68 28l-408 408q-28 28 -28 68q0 13 4.5 26t9 22t15.5 22t16.5 18.5t20.5 19t18 16.5q30 28 68 28q10 0 18 -1.5t16.5 -5.5t13.5 -6t13.5 -10t11.5 -10t13 -12.5t12 -12.5q-14 14 -14 34t14 34l348 348q14 14 34 14t34 -14
q-2 2 -12.5 12t-12.5 13t-10 11.5t-10 13.5t-6 13.5t-5.5 16.5t-1.5 18q0 38 28 68q3 3 16.5 18t19 20.5t18.5 16.5t22 15.5t22 9t26 4.5q40 0 68 -28l408 -408q28 -28 28 -68q0 -13 -4.5 -26t-9 -22t-15.5 -22t-16.5 -18.5t-20.5 -19t-18 -16.5q-30 -28 -68 -28
q-10 0 -18 1.5t-16.5 5.5t-13.5 6t-13.5 10t-11.5 10t-13 12.5t-12 12.5q14 -14 14 -34t-14 -34l-126 -126l256 -256q43 43 96 43q52 0 91 -37l363 -363q37 -39 37 -91z" />
    <glyph glyph-name="dashboard" unicode="&#xf0e4;" horiz-adv-x="1792" 
d="M384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM576 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1004 351l101 382q6 26 -7.5 48.5t-38.5 29.5
t-48 -6.5t-30 -39.5l-101 -382q-60 -5 -107 -43.5t-63 -98.5q-20 -77 20 -146t117 -89t146 20t89 117q16 60 -6 117t-72 91zM1664 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 1024q0 53 -37.5 90.5
t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1472 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1792 384q0 -261 -141 -483q-19 -29 -54 -29h-1402q-35 0 -54 29
q-141 221 -141 483q0 182 71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
    <glyph glyph-name="comment_alt" unicode="&#xf0e5;" horiz-adv-x="1792" 
d="M896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5t104.5 255t-104.5 255t-282 187.5t-381.5 69.5zM1792 640
q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281q0 174 120 321.5
t326 233t450 85.5t450 -85.5t326 -233t120 -321.5z" />
    <glyph glyph-name="comments_alt" unicode="&#xf0e6;" horiz-adv-x="1792" 
d="M704 1152q-153 0 -286 -52t-211.5 -141t-78.5 -191q0 -82 53 -158t149 -132l97 -56l-35 -84q34 20 62 39l44 31l53 -10q78 -14 153 -14q153 0 286 52t211.5 141t78.5 191t-78.5 191t-211.5 141t-286 52zM704 1280q191 0 353.5 -68.5t256.5 -186.5t94 -257t-94 -257
t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224q0 139 94 257t256.5 186.5
t353.5 68.5zM1526 111q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129
q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230q0 -120 -71 -224.5t-195 -176.5z" />
    <glyph glyph-name="bolt" unicode="&#xf0e7;" horiz-adv-x="896" 
d="M885 970q18 -20 7 -44l-540 -1157q-13 -25 -42 -25q-4 0 -14 2q-17 5 -25.5 19t-4.5 30l197 808l-406 -101q-4 -1 -12 -1q-18 0 -31 11q-18 15 -13 39l201 825q4 14 16 23t28 9h328q19 0 32 -12.5t13 -29.5q0 -8 -5 -18l-171 -463l396 98q8 2 12 2q19 0 34 -15z" />
    <glyph glyph-name="sitemap" unicode="&#xf0e8;" horiz-adv-x="1792" 
d="M1792 288v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320
q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192q0 52 38 90t90 38h512v192h-96q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-96v-192h512q52 0 90 -38t38 -90v-192h96q40 0 68 -28t28 -68
z" />
    <glyph glyph-name="umbrella" unicode="&#xf0e9;" horiz-adv-x="1664" 
d="M896 708v-580q0 -104 -76 -180t-180 -76t-180 76t-76 180q0 26 19 45t45 19t45 -19t19 -45q0 -50 39 -89t89 -39t89 39t39 89v580q33 11 64 11t64 -11zM1664 681q0 -13 -9.5 -22.5t-22.5 -9.5q-11 0 -23 10q-49 46 -93 69t-102 23q-68 0 -128 -37t-103 -97
q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -28 -17q-18 0 -29 17q-4 6 -14.5 24t-17.5 28q-43 60 -102.5 97t-127.5 37t-127.5 -37t-102.5 -97q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -29 -17q-17 0 -28 17q-4 6 -14.5 24t-17.5 28q-43 60 -103 97t-128 37q-58 0 -102 -23t-93 -69
q-12 -10 -23 -10q-13 0 -22.5 9.5t-9.5 22.5q0 5 1 7q45 183 172.5 319.5t298 204.5t360.5 68q140 0 274.5 -40t246.5 -113.5t194.5 -187t115.5 -251.5q1 -2 1 -7zM896 1408v-98q-42 2 -64 2t-64 -2v98q0 26 19 45t45 19t45 -19t19 -45z" />
    <glyph glyph-name="paste" unicode="&#xf0ea;" horiz-adv-x="1792" 
d="M768 -128h896v640h-416q-40 0 -68 28t-28 68v416h-384v-1152zM1024 1312v64q0 13 -9.5 22.5t-22.5 9.5h-704q-13 0 -22.5 -9.5t-9.5 -22.5v-64q0 -13 9.5 -22.5t22.5 -9.5h704q13 0 22.5 9.5t9.5 22.5zM1280 640h299l-299 299v-299zM1792 512v-672q0 -40 -28 -68t-68 -28
h-960q-40 0 -68 28t-28 68v160h-544q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1088q40 0 68 -28t28 -68v-328q21 -13 36 -28l408 -408q28 -28 48 -76t20 -88z" />
    <glyph glyph-name="light_bulb" unicode="&#xf0eb;" horiz-adv-x="1024" 
d="M736 960q0 -13 -9.5 -22.5t-22.5 -9.5t-22.5 9.5t-9.5 22.5q0 46 -54 71t-106 25q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5q50 0 99.5 -16t87 -54t37.5 -90zM896 960q0 72 -34.5 134t-90 101.5t-123 62t-136.5 22.5t-136.5 -22.5t-123 -62t-90 -101.5t-34.5 -134
q0 -101 68 -180q10 -11 30.5 -33t30.5 -33q128 -153 141 -298h228q13 145 141 298q10 11 30.5 33t30.5 33q68 79 68 180zM1024 960q0 -155 -103 -268q-45 -49 -74.5 -87t-59.5 -95.5t-34 -107.5q47 -28 47 -82q0 -37 -25 -64q25 -27 25 -64q0 -52 -45 -81q13 -23 13 -47
q0 -46 -31.5 -71t-77.5 -25q-20 -44 -60 -70t-87 -26t-87 26t-60 70q-46 0 -77.5 25t-31.5 71q0 24 13 47q-45 29 -45 81q0 37 25 64q-25 27 -25 64q0 54 47 82q-4 50 -34 107.5t-59.5 95.5t-74.5 87q-103 113 -103 268q0 99 44.5 184.5t117 142t164 89t186.5 32.5
t186.5 -32.5t164 -89t117 -142t44.5 -184.5z" />
    <glyph glyph-name="exchange" unicode="&#xf0ec;" horiz-adv-x="1792" 
d="M1792 352v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5q-12 0 -24 10l-319 320q-9 9 -9 22q0 14 9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h1376q13 0 22.5 -9.5t9.5 -22.5zM1792 896q0 -14 -9 -23l-320 -320q-9 -9 -23 -9
q-13 0 -22.5 9.5t-9.5 22.5v192h-1376q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1376v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" />
    <glyph glyph-name="cloud_download" unicode="&#xf0ed;" horiz-adv-x="1920" 
d="M1280 608q0 14 -9 23t-23 9h-224v352q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-352h-224q-13 0 -22.5 -9.5t-9.5 -22.5q0 -14 9 -23l352 -352q9 -9 23 -9t23 9l351 351q10 12 10 24zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088
q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" />
    <glyph glyph-name="cloud_upload" unicode="&#xf0ee;" horiz-adv-x="1920" 
d="M1280 672q0 14 -9 23l-352 352q-9 9 -23 9t-23 -9l-351 -351q-10 -12 -10 -24q0 -14 9 -23t23 -9h224v-352q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5v352h224q13 0 22.5 9.5t9.5 22.5zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088
q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" />
    <glyph glyph-name="user_md" unicode="&#xf0f0;" horiz-adv-x="1408" 
d="M384 192q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM1408 131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190q0 68 5.5 131t24 138t47.5 132.5t81 103t120 60.5q-22 -52 -22 -120v-203q-58 -20 -93 -70t-35 -111q0 -80 56 -136t136 -56
t136 56t56 136q0 61 -35.5 111t-92.5 70v203q0 62 25 93q132 -104 295 -104t295 104q25 -31 25 -93v-64q-106 0 -181 -75t-75 -181v-89q-32 -29 -32 -71q0 -40 28 -68t68 -28t68 28t28 68q0 42 -32 71v89q0 52 38 90t90 38t90 -38t38 -90v-89q-32 -29 -32 -71q0 -40 28 -68
t68 -28t68 28t28 68q0 42 -32 71v89q0 68 -34.5 127.5t-93.5 93.5q0 10 0.5 42.5t0 48t-2.5 41.5t-7 47t-13 40q68 -15 120 -60.5t81 -103t47.5 -132.5t24 -138t5.5 -131zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5
t271.5 -112.5t112.5 -271.5z" />
    <glyph glyph-name="stethoscope" unicode="&#xf0f1;" horiz-adv-x="1408" 
d="M1280 832q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 832q0 -62 -35.5 -111t-92.5 -70v-395q0 -159 -131.5 -271.5t-316.5 -112.5t-316.5 112.5t-131.5 271.5v132q-164 20 -274 128t-110 252v512q0 26 19 45t45 19q6 0 16 -2q17 30 47 48
t65 18q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5q-33 0 -64 18v-402q0 -106 94 -181t226 -75t226 75t94 181v402q-31 -18 -64 -18q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5q35 0 65 -18t47 -48q10 2 16 2q26 0 45 -19t19 -45v-512q0 -144 -110 -252
t-274 -128v-132q0 -106 94 -181t226 -75t226 75t94 181v395q-57 21 -92.5 70t-35.5 111q0 80 56 136t136 56t136 -56t56 -136z" />
    <glyph glyph-name="suitcase" unicode="&#xf0f2;" horiz-adv-x="1792" 
d="M640 1152h512v128h-512v-128zM288 1152v-1280h-64q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h64zM1408 1152v-1280h-1024v1280h128v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h128zM1792 928v-832q0 -92 -66 -158t-158 -66h-64v1280h64q92 0 158 -66
t66 -158z" />
    <glyph glyph-name="bell_alt" unicode="&#xf0f3;" horiz-adv-x="1792" 
d="M912 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM1728 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q50 42 91 88t85 119.5t74.5 158.5
t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q190 -28 307 -158.5t117 -282.5q0 -139 19.5 -260t50 -206t74.5 -158.5t85 -119.5t91 -88z" />
    <glyph glyph-name="coffee" unicode="&#xf0f4;" horiz-adv-x="1920" 
d="M1664 896q0 80 -56 136t-136 56h-64v-384h64q80 0 136 56t56 136zM0 128h1792q0 -106 -75 -181t-181 -75h-1280q-106 0 -181 75t-75 181zM1856 896q0 -159 -112.5 -271.5t-271.5 -112.5h-64v-32q0 -92 -66 -158t-158 -66h-704q-92 0 -158 66t-66 158v736q0 26 19 45
t45 19h1152q159 0 271.5 -112.5t112.5 -271.5z" />
    <glyph glyph-name="food" unicode="&#xf0f5;" horiz-adv-x="1408" 
d="M640 1472v-640q0 -61 -35.5 -111t-92.5 -70v-779q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v779q-57 20 -92.5 70t-35.5 111v640q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45
t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45zM1408 1472v-1600q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v512h-224q-13 0 -22.5 9.5t-9.5 22.5v800q0 132 94 226t226 94h256q26 0 45 -19t19 -45z" />
    <glyph glyph-name="file_text_alt" unicode="&#xf0f6;" 
d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
M384 736q0 14 9 23t23 9h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64zM1120 512q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704zM1120 256q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704
q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704z" />
    <glyph glyph-name="building" unicode="&#xf0f7;" horiz-adv-x="1408" 
d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
M1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
M640 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
M1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
M640 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
M896 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
M896 -128h384v1536h-1152v-1536h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM1408 1472v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280q26 0 45 -19t19 -45z" />
    <glyph glyph-name="hospital" unicode="&#xf0f8;" horiz-adv-x="1408" 
d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
M896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
M896 -128h384v1152h-256v-32q0 -40 -28 -68t-68 -28h-448q-40 0 -68 28t-28 68v32h-256v-1152h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM896 1056v320q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-96h-128v96q0 13 -9.5 22.5
t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5v96h128v-96q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1408 1088v-1280q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1280q0 26 19 45t45 19h320
v288q0 40 28 68t68 28h448q40 0 68 -28t28 -68v-288h320q26 0 45 -19t19 -45z" />
    <glyph glyph-name="ambulance" unicode="&#xf0f9;" horiz-adv-x="1920" 
d="M640 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM256 640h384v256h-158q-14 -2 -22 -9l-195 -195q-7 -12 -9 -22v-30zM1536 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5
t90.5 37.5t37.5 90.5zM1664 800v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM1920 1344v-1152
q0 -26 -19 -45t-45 -19h-192q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-128q-26 0 -45 19t-19 45t19 45t45 19v416q0 26 13 58t32 51l198 198q19 19 51 32t58 13h160v320q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
    <glyph glyph-name="medkit" unicode="&#xf0fa;" horiz-adv-x="1792" 
d="M1280 416v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM640 1152h512v128h-512v-128zM256 1152v-1280h-32
q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h32zM1440 1152v-1280h-1088v1280h160v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h160zM1792 928v-832q0 -92 -66 -158t-158 -66h-32v1280h32q92 0 158 -66t66 -158z" />
    <glyph glyph-name="fighter_jet" unicode="&#xf0fb;" horiz-adv-x="1920" 
d="M1920 576q-1 -32 -288 -96l-352 -32l-224 -64h-64l-293 -352h69q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-96h-160h-64v32h64v416h-160l-192 -224h-96l-32 32v192h32v32h128v8l-192 24v128l192 24v8h-128v32h-32v192l32 32h96l192 -224h160v416h-64v32h64h160h96
q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-69l293 -352h64l224 -64l352 -32q128 -28 200 -52t80 -34z" />
    <glyph glyph-name="beer" unicode="&#xf0fc;" horiz-adv-x="1664" 
d="M640 640v384h-256v-256q0 -53 37.5 -90.5t90.5 -37.5h128zM1664 192v-192h-1152v192l128 192h-128q-159 0 -271.5 112.5t-112.5 271.5v320l-64 64l32 128h480l32 128h960l32 -192l-64 -32v-800z" />
    <glyph glyph-name="h_sign" unicode="&#xf0fd;" 
d="M1280 192v896q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-512v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-896q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h512v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1536 1120v-960
q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="f0fe" unicode="&#xf0fe;" 
d="M1280 576v128q0 26 -19 45t-45 19h-320v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-320q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h320v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h320q26 0 45 19t19 45zM1536 1120v-960
q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="double_angle_left" unicode="&#xf100;" horiz-adv-x="1024" 
d="M627 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23zM1011 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23
t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23z" />
    <glyph glyph-name="double_angle_right" unicode="&#xf101;" horiz-adv-x="1024" 
d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM979 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23
l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
    <glyph glyph-name="double_angle_up" unicode="&#xf102;" horiz-adv-x="1152" 
d="M1075 224q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM1075 608q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393
q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
    <glyph glyph-name="double_angle_down" unicode="&#xf103;" horiz-adv-x="1152" 
d="M1075 672q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23zM1075 1056q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23
t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
    <glyph glyph-name="angle_left" unicode="&#xf104;" horiz-adv-x="640" 
d="M627 992q0 -13 -10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
    <glyph glyph-name="angle_right" unicode="&#xf105;" horiz-adv-x="640" 
d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
    <glyph glyph-name="angle_up" unicode="&#xf106;" horiz-adv-x="1152" 
d="M1075 352q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
    <glyph glyph-name="angle_down" unicode="&#xf107;" horiz-adv-x="1152" 
d="M1075 800q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
    <glyph glyph-name="desktop" unicode="&#xf108;" horiz-adv-x="1920" 
d="M1792 544v832q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1376v-1088q0 -66 -47 -113t-113 -47h-544q0 -37 16 -77.5t32 -71t16 -43.5q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19
t-19 45q0 14 16 44t32 70t16 78h-544q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
    <glyph glyph-name="laptop" unicode="&#xf109;" horiz-adv-x="1920" 
d="M416 256q-66 0 -113 47t-47 113v704q0 66 47 113t113 47h1088q66 0 113 -47t47 -113v-704q0 -66 -47 -113t-113 -47h-1088zM384 1120v-704q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5v704q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5z
M1760 192h160v-96q0 -40 -47 -68t-113 -28h-1600q-66 0 -113 28t-47 68v96h160h1600zM1040 96q16 0 16 16t-16 16h-160q-16 0 -16 -16t16 -16h160z" />
    <glyph glyph-name="tablet" unicode="&#xf10a;" horiz-adv-x="1152" 
d="M640 128q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1024 288v960q0 13 -9.5 22.5t-22.5 9.5h-832q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h832q13 0 22.5 9.5t9.5 22.5zM1152 1248v-1088q0 -66 -47 -113t-113 -47h-832
q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h832q66 0 113 -47t47 -113z" />
    <glyph glyph-name="mobile_phone" unicode="&#xf10b;" horiz-adv-x="768" 
d="M464 128q0 33 -23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t23.5 -56.5t56.5 -23.5t56.5 23.5t23.5 56.5zM672 288v704q0 13 -9.5 22.5t-22.5 9.5h-512q-13 0 -22.5 -9.5t-9.5 -22.5v-704q0 -13 9.5 -22.5t22.5 -9.5h512q13 0 22.5 9.5t9.5 22.5zM480 1136
q0 16 -16 16h-160q-16 0 -16 -16t16 -16h160q16 0 16 16zM768 1152v-1024q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v1024q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
    <glyph glyph-name="circle_blank" unicode="&#xf10c;" 
d="M768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103
t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="quote_left" unicode="&#xf10d;" horiz-adv-x="1664" 
d="M768 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z
M1664 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z" />
    <glyph glyph-name="quote_right" unicode="&#xf10e;" horiz-adv-x="1664" 
d="M768 1216v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136zM1664 1216
v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136z" />
    <glyph glyph-name="spinner" unicode="&#xf110;" horiz-adv-x="1792" 
d="M526 142q0 -53 -37.5 -90.5t-90.5 -37.5q-52 0 -90 38t-38 90q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1024 -64q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM320 640q0 -53 -37.5 -90.5t-90.5 -37.5
t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1522 142q0 -52 -38 -90t-90 -38q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM558 1138q0 -66 -47 -113t-113 -47t-113 47t-47 113t47 113t113 47t113 -47t47 -113z
M1728 640q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1088 1344q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1618 1138q0 -93 -66 -158.5t-158 -65.5q-93 0 -158.5 65.5t-65.5 158.5
q0 92 65.5 158t158.5 66q92 0 158 -66t66 -158z" />
    <glyph glyph-name="circle" unicode="&#xf111;" 
d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="reply" unicode="&#xf112;" horiz-adv-x="1792" 
d="M1792 416q0 -166 -127 -451q-3 -7 -10.5 -24t-13.5 -30t-13 -22q-12 -17 -28 -17q-15 0 -23.5 10t-8.5 25q0 9 2.5 26.5t2.5 23.5q5 68 5 123q0 101 -17.5 181t-48.5 138.5t-80 101t-105.5 69.5t-133 42.5t-154 21.5t-175.5 6h-224v-256q0 -26 -19 -45t-45 -19t-45 19
l-512 512q-19 19 -19 45t19 45l512 512q19 19 45 19t45 -19t19 -45v-256h224q713 0 875 -403q53 -134 53 -333z" />
    <glyph glyph-name="github_alt" unicode="&#xf113;" horiz-adv-x="1664" 
d="M640 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1280 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1440 320
q0 120 -69 204t-187 84q-41 0 -195 -21q-71 -11 -157 -11t-157 11q-152 21 -195 21q-118 0 -187 -84t-69 -204q0 -88 32 -153.5t81 -103t122 -60t140 -29.5t149 -7h168q82 0 149 7t140 29.5t122 60t81 103t32 153.5zM1664 496q0 -207 -61 -331q-38 -77 -105.5 -133t-141 -86
t-170 -47.5t-171.5 -22t-167 -4.5q-78 0 -142 3t-147.5 12.5t-152.5 30t-137 51.5t-121 81t-86 115q-62 123 -62 331q0 237 136 396q-27 82 -27 170q0 116 51 218q108 0 190 -39.5t189 -123.5q147 35 309 35q148 0 280 -32q105 82 187 121t189 39q51 -102 51 -218
q0 -87 -27 -168q136 -160 136 -398z" />
    <glyph glyph-name="folder_close_alt" unicode="&#xf114;" horiz-adv-x="1664" 
d="M1536 224v704q0 40 -28 68t-68 28h-704q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68v-960q0 -40 28 -68t68 -28h1216q40 0 68 28t28 68zM1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320
q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
    <glyph glyph-name="folder_open_alt" unicode="&#xf115;" horiz-adv-x="1920" 
d="M1781 605q0 35 -53 35h-1088q-40 0 -85.5 -21.5t-71.5 -52.5l-294 -363q-18 -24 -18 -40q0 -35 53 -35h1088q40 0 86 22t71 53l294 363q18 22 18 39zM640 768h768v160q0 40 -28 68t-68 28h-576q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68
v-853l256 315q44 53 116 87.5t140 34.5zM1909 605q0 -62 -46 -120l-295 -363q-43 -53 -116 -87.5t-140 -34.5h-1088q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158v-160h192q54 0 99 -24.5t67 -70.5q15 -32 15 -68z
" />
    <glyph glyph-name="expand_alt" unicode="&#xf116;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="collapse_alt" unicode="&#xf117;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="smile" unicode="&#xf118;" 
d="M1134 461q-37 -121 -138 -195t-228 -74t-228 74t-138 195q-8 25 4 48.5t38 31.5q25 8 48.5 -4t31.5 -38q25 -80 92.5 -129.5t151.5 -49.5t151.5 49.5t92.5 129.5q8 26 32 38t49 4t37 -31.5t4 -48.5zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5
t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5
t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="frown" unicode="&#xf119;" 
d="M1134 307q8 -25 -4 -48.5t-37 -31.5t-49 4t-32 38q-25 80 -92.5 129.5t-151.5 49.5t-151.5 -49.5t-92.5 -129.5q-8 -26 -31.5 -38t-48.5 -4q-26 8 -38 31.5t-4 48.5q37 121 138 195t228 74t228 -74t138 -195zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5
t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204
t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="meh" unicode="&#xf11a;" 
d="M1152 448q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h640q26 0 45 -19t19 -45zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5
t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640
q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="gamepad" unicode="&#xf11b;" horiz-adv-x="1920" 
d="M832 448v128q0 14 -9 23t-23 9h-192v192q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-192h-192q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h192v-192q0 -14 9 -23t23 -9h128q14 0 23 9t9 23v192h192q14 0 23 9t9 23zM1408 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5
t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1920 512q0 -212 -150 -362t-362 -150q-192 0 -338 128h-220q-146 -128 -338 -128q-212 0 -362 150
t-150 362t150 362t362 150h896q212 0 362 -150t150 -362z" />
    <glyph glyph-name="keyboard" unicode="&#xf11c;" horiz-adv-x="1920" 
d="M384 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM512 624v-96q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h224q16 0 16 -16zM384 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 368v-96q0 -16 -16 -16
h-864q-16 0 -16 16v96q0 16 16 16h864q16 0 16 -16zM768 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM640 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1024 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16
h96q16 0 16 -16zM896 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1280 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1152 880v-96
q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 880v-352q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h112v240q0 16 16 16h96q16 0 16 -16zM1792 128v896h-1664v-896
h1664zM1920 1024v-896q0 -53 -37.5 -90.5t-90.5 -37.5h-1664q-53 0 -90.5 37.5t-37.5 90.5v896q0 53 37.5 90.5t90.5 37.5h1664q53 0 90.5 -37.5t37.5 -90.5z" />
    <glyph glyph-name="flag_alt" unicode="&#xf11d;" horiz-adv-x="1792" 
d="M1664 491v616q-169 -91 -306 -91q-82 0 -145 32q-100 49 -184 76.5t-178 27.5q-173 0 -403 -127v-599q245 113 433 113q55 0 103.5 -7.5t98 -26t77 -31t82.5 -39.5l28 -14q44 -22 101 -22q120 0 293 92zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9
h-64q-14 0 -23 9t-9 23v1266q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102
q-15 -9 -33 -9q-16 0 -32 8q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" />
    <glyph glyph-name="flag_checkered" unicode="&#xf11e;" horiz-adv-x="1792" 
d="M832 536v192q-181 -16 -384 -117v-185q205 96 384 110zM832 954v197q-172 -8 -384 -126v-189q215 111 384 118zM1664 491v184q-235 -116 -384 -71v224q-20 6 -39 15q-5 3 -33 17t-34.5 17t-31.5 15t-34.5 15.5t-32.5 13t-36 12.5t-35 8.5t-39.5 7.5t-39.5 4t-44 2
q-23 0 -49 -3v-222h19q102 0 192.5 -29t197.5 -82q19 -9 39 -15v-188q42 -17 91 -17q120 0 293 92zM1664 918v189q-169 -91 -306 -91q-45 0 -78 8v-196q148 -42 384 90zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v1266
q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102q-15 -9 -33 -9q-16 0 -32 8
q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" />
    <glyph glyph-name="terminal" unicode="&#xf120;" horiz-adv-x="1664" 
d="M585 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23zM1664 96v-64q0 -14 -9 -23t-23 -9h-960q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h960q14 0 23 -9
t9 -23z" />
    <glyph glyph-name="code" unicode="&#xf121;" horiz-adv-x="1920" 
d="M617 137l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23zM1208 1204l-373 -1291q-4 -13 -15.5 -19.5t-23.5 -2.5l-62 17q-13 4 -19.5 15.5t-2.5 24.5
l373 1291q4 13 15.5 19.5t23.5 2.5l62 -17q13 -4 19.5 -15.5t2.5 -24.5zM1865 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23z" />
    <glyph glyph-name="reply_all" unicode="&#xf122;" horiz-adv-x="1792" 
d="M640 454v-70q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-69l-397 -398q-19 -19 -19 -45t19 -45zM1792 416q0 -58 -17 -133.5t-38.5 -138t-48 -125t-40.5 -90.5l-20 -40q-8 -17 -28 -17q-6 0 -9 1
q-25 8 -23 34q43 400 -106 565q-64 71 -170.5 110.5t-267.5 52.5v-251q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-262q411 -28 599 -221q169 -173 169 -509z" />
    <glyph glyph-name="star_half_empty" unicode="&#xf123;" horiz-adv-x="1664" 
d="M1186 579l257 250l-356 52l-66 10l-30 60l-159 322v-963l59 -31l318 -168l-60 355l-12 66zM1638 841l-363 -354l86 -500q5 -33 -6 -51.5t-34 -18.5q-17 0 -40 12l-449 236l-449 -236q-23 -12 -40 -12q-23 0 -34 18.5t-6 51.5l86 500l-364 354q-32 32 -23 59.5t54 34.5
l502 73l225 455q20 41 49 41q28 0 49 -41l225 -455l502 -73q45 -7 54 -34.5t-24 -59.5z" />
    <glyph glyph-name="location_arrow" unicode="&#xf124;" horiz-adv-x="1408" 
d="M1401 1187l-640 -1280q-17 -35 -57 -35q-5 0 -15 2q-22 5 -35.5 22.5t-13.5 39.5v576h-576q-22 0 -39.5 13.5t-22.5 35.5t4 42t29 30l1280 640q13 7 29 7q27 0 45 -19q15 -14 18.5 -34.5t-6.5 -39.5z" />
    <glyph glyph-name="crop" unicode="&#xf125;" horiz-adv-x="1664" 
d="M557 256h595v595zM512 301l595 595h-595v-595zM1664 224v-192q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v224h-864q-14 0 -23 9t-9 23v864h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224v224q0 14 9 23t23 9h192q14 0 23 -9t9 -23
v-224h851l246 247q10 9 23 9t23 -9q9 -10 9 -23t-9 -23l-247 -246v-851h224q14 0 23 -9t9 -23z" />
    <glyph glyph-name="code_fork" unicode="&#xf126;" horiz-adv-x="1024" 
d="M288 64q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM288 1216q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM928 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1024 1088q0 -52 -26 -96.5t-70 -69.5
q-2 -287 -226 -414q-67 -38 -203 -81q-128 -40 -169.5 -71t-41.5 -100v-26q44 -25 70 -69.5t26 -96.5q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 52 26 96.5t70 69.5v820q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136q0 -52 -26 -96.5t-70 -69.5v-497
q54 26 154 57q55 17 87.5 29.5t70.5 31t59 39.5t40.5 51t28 69.5t8.5 91.5q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136z" />
    <glyph glyph-name="unlink" unicode="&#xf127;" horiz-adv-x="1664" 
d="M439 265l-256 -256q-11 -9 -23 -9t-23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23zM608 224v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM384 448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23t9 23t23 9h320
q14 0 23 -9t9 -23zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-334 335q-21 21 -42 56l239 18l273 -274q27 -27 68 -27.5t68 26.5l147 146q28 28 28 67q0 40 -28 68l-274 275l18 239q35 -21 56 -42l336 -336q84 -86 84 -204zM1031 1044l-239 -18
l-273 274q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l274 -274l-18 -240q-35 21 -56 42l-336 336q-84 86 -84 204q0 120 85 203l147 146q83 83 203 83q121 0 204 -85l334 -335q21 -21 42 -56zM1664 960q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9
t-9 23t9 23t23 9h320q14 0 23 -9t9 -23zM1120 1504v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM1527 1353l-256 -256q-11 -9 -23 -9t-23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23z" />
    <glyph glyph-name="question" unicode="&#xf128;" horiz-adv-x="1024" 
d="M704 280v-240q0 -16 -12 -28t-28 -12h-240q-16 0 -28 12t-12 28v240q0 16 12 28t28 12h240q16 0 28 -12t12 -28zM1020 880q0 -54 -15.5 -101t-35 -76.5t-55 -59.5t-57.5 -43.5t-61 -35.5q-41 -23 -68.5 -65t-27.5 -67q0 -17 -12 -32.5t-28 -15.5h-240q-15 0 -25.5 18.5
t-10.5 37.5v45q0 83 65 156.5t143 108.5q59 27 84 56t25 76q0 42 -46.5 74t-107.5 32q-65 0 -108 -29q-35 -25 -107 -115q-13 -16 -31 -16q-12 0 -25 8l-164 125q-13 10 -15.5 25t5.5 28q160 266 464 266q80 0 161 -31t146 -83t106 -127.5t41 -158.5z" />
    <glyph glyph-name="_279" unicode="&#xf129;" horiz-adv-x="640" 
d="M640 192v-128q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64v384h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-576h64q26 0 45 -19t19 -45zM512 1344v-192q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v192
q0 26 19 45t45 19h256q26 0 45 -19t19 -45z" />
    <glyph glyph-name="exclamation" unicode="&#xf12a;" horiz-adv-x="640" 
d="M512 288v-224q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v224q0 26 19 45t45 19h256q26 0 45 -19t19 -45zM542 1344l-28 -768q-1 -26 -20.5 -45t-45.5 -19h-256q-26 0 -45.5 19t-20.5 45l-28 768q-1 26 17.5 45t44.5 19h320q26 0 44.5 -19t17.5 -45z" />
    <glyph glyph-name="superscript" unicode="&#xf12b;" 
d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3q-1 -3 -2.5 -6.5t-3.5 -8t-3 -6.5q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109z
M1534 846v-206h-514l-3 27q-4 28 -4 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q83 65 188 65q110 0 178 -59.5t68 -158.5q0 -56 -24.5 -103t-62 -76.5t-81.5 -58.5t-82 -50.5
t-65.5 -51.5t-30.5 -63h232v80h126z" />
    <glyph glyph-name="subscript" unicode="&#xf12c;" 
d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3q-1 -3 -2.5 -6.5t-3.5 -8t-3 -6.5q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109z
M1536 -50v-206h-514l-4 27q-3 45 -3 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q80 65 188 65q110 0 178 -59.5t68 -158.5q0 -66 -34.5 -118.5t-84 -86t-99.5 -62.5t-87 -63t-41 -73
h232v80h126z" />
    <glyph glyph-name="_283" unicode="&#xf12d;" horiz-adv-x="1920" 
d="M896 128l336 384h-768l-336 -384h768zM1909 1205q15 -34 9.5 -71.5t-30.5 -65.5l-896 -1024q-38 -44 -96 -44h-768q-38 0 -69.5 20.5t-47.5 54.5q-15 34 -9.5 71.5t30.5 65.5l896 1024q38 44 96 44h768q38 0 69.5 -20.5t47.5 -54.5z" />
    <glyph glyph-name="puzzle_piece" unicode="&#xf12e;" horiz-adv-x="1664" 
d="M1664 438q0 -81 -44.5 -135t-123.5 -54q-41 0 -77.5 17.5t-59 38t-56.5 38t-71 17.5q-110 0 -110 -124q0 -39 16 -115t15 -115v-5q-22 0 -33 -1q-34 -3 -97.5 -11.5t-115.5 -13.5t-98 -5q-61 0 -103 26.5t-42 83.5q0 37 17.5 71t38 56.5t38 59t17.5 77.5q0 79 -54 123.5
t-135 44.5q-84 0 -143 -45.5t-59 -127.5q0 -43 15 -83t33.5 -64.5t33.5 -53t15 -50.5q0 -45 -46 -89q-37 -35 -117 -35q-95 0 -245 24q-9 2 -27.5 4t-27.5 4l-13 2q-1 0 -3 1q-2 0 -2 1v1024q2 -1 17.5 -3.5t34 -5t21.5 -3.5q150 -24 245 -24q80 0 117 35q46 44 46 89
q0 22 -15 50.5t-33.5 53t-33.5 64.5t-15 83q0 82 59 127.5t144 45.5q80 0 134 -44.5t54 -123.5q0 -41 -17.5 -77.5t-38 -59t-38 -56.5t-17.5 -71q0 -57 42 -83.5t103 -26.5q64 0 180 15t163 17v-2q-1 -2 -3.5 -17.5t-5 -34t-3.5 -21.5q-24 -150 -24 -245q0 -80 35 -117
q44 -46 89 -46q22 0 50.5 15t53 33.5t64.5 33.5t83 15q82 0 127.5 -59t45.5 -143z" />
    <glyph glyph-name="microphone" unicode="&#xf130;" horiz-adv-x="1152" 
d="M1152 832v-128q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-217 24 -364.5 187.5t-147.5 384.5v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -185 131.5 -316.5t316.5 -131.5
t316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45zM896 1216v-512q0 -132 -94 -226t-226 -94t-226 94t-94 226v512q0 132 94 226t226 94t226 -94t94 -226z" />
    <glyph glyph-name="microphone_off" unicode="&#xf131;" horiz-adv-x="1408" 
d="M271 591l-101 -101q-42 103 -42 214v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -53 15 -113zM1385 1193l-361 -361v-128q0 -132 -94 -226t-226 -94q-55 0 -109 19l-96 -96q97 -51 205 -51q185 0 316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45v-128
q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-125 13 -235 81l-254 -254q-10 -10 -23 -10t-23 10l-82 82q-10 10 -10 23t10 23l1234 1234q10 10 23 10t23 -10l82 -82q10 -10 10 -23
t-10 -23zM1005 1325l-621 -621v512q0 132 94 226t226 94q102 0 184.5 -59t116.5 -152z" />
    <glyph glyph-name="shield" unicode="&#xf132;" horiz-adv-x="1280" 
d="M1088 576v640h-448v-1137q119 63 213 137q235 184 235 360zM1280 1344v-768q0 -86 -33.5 -170.5t-83 -150t-118 -127.5t-126.5 -103t-121 -77.5t-89.5 -49.5t-42.5 -20q-12 -6 -26 -6t-26 6q-16 7 -42.5 20t-89.5 49.5t-121 77.5t-126.5 103t-118 127.5t-83 150
t-33.5 170.5v768q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
    <glyph glyph-name="calendar_empty" unicode="&#xf133;" horiz-adv-x="1664" 
d="M128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280
q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
    <glyph glyph-name="fire_extinguisher" unicode="&#xf134;" horiz-adv-x="1408" 
d="M512 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 1376v-320q0 -16 -12 -25q-8 -7 -20 -7q-4 0 -7 1l-448 96q-11 2 -18 11t-7 20h-256v-102q111 -23 183.5 -111t72.5 -203v-800q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v800
q0 106 62.5 190.5t161.5 114.5v111h-32q-59 0 -115 -23.5t-91.5 -53t-66 -66.5t-40.5 -53.5t-14 -24.5q-17 -35 -57 -35q-16 0 -29 7q-23 12 -31.5 37t3.5 49q5 10 14.5 26t37.5 53.5t60.5 70t85 67t108.5 52.5q-25 42 -25 86q0 66 47 113t113 47t113 -47t47 -113
q0 -33 -14 -64h302q0 11 7 20t18 11l448 96q3 1 7 1q12 0 20 -7q12 -9 12 -25z" />
    <glyph glyph-name="rocket" unicode="&#xf135;" horiz-adv-x="1664" 
d="M1440 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1664 1376q0 -249 -75.5 -430.5t-253.5 -360.5q-81 -80 -195 -176l-20 -379q-2 -16 -16 -26l-384 -224q-7 -4 -16 -4q-12 0 -23 9l-64 64q-13 14 -8 32l85 276l-281 281l-276 -85q-3 -1 -9 -1
q-14 0 -23 9l-64 64q-17 19 -5 39l224 384q10 14 26 16l379 20q96 114 176 195q188 187 358 258t431 71q14 0 24 -9.5t10 -22.5z" />
    <glyph glyph-name="maxcdn" unicode="&#xf136;" horiz-adv-x="1792" 
d="M1745 763l-164 -763h-334l178 832q13 56 -15 88q-27 33 -83 33h-169l-204 -953h-334l204 953h-286l-204 -953h-334l204 953l-153 327h1276q101 0 189.5 -40.5t147.5 -113.5q60 -73 81 -168.5t0 -194.5z" />
    <glyph glyph-name="chevron_sign_left" unicode="&#xf137;" 
d="M909 141l102 102q19 19 19 45t-19 45l-307 307l307 307q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5
t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="chevron_sign_right" unicode="&#xf138;" 
d="M717 141l454 454q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l307 -307l-307 -307q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5
t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="chevron_sign_up" unicode="&#xf139;" 
d="M1165 397l102 102q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l307 307l307 -307q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5
t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="chevron_sign_down" unicode="&#xf13a;" 
d="M813 237l454 454q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-307 -307l-307 307q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5
t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="html5" unicode="&#xf13b;" horiz-adv-x="1408" 
d="M1130 939l16 175h-884l47 -534h612l-22 -228l-197 -53l-196 53l-13 140h-175l22 -278l362 -100h4v1l359 99l50 544h-644l-15 181h674zM0 1408h1408l-128 -1438l-578 -162l-574 162z" />
    <glyph glyph-name="css3" unicode="&#xf13c;" horiz-adv-x="1792" 
d="M275 1408h1505l-266 -1333l-804 -267l-698 267l71 356h297l-29 -147l422 -161l486 161l68 339h-1208l58 297h1209l38 191h-1208z" />
    <glyph glyph-name="anchor" unicode="&#xf13d;" horiz-adv-x="1792" 
d="M960 1280q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1792 352v-352q0 -22 -20 -30q-8 -2 -12 -2q-12 0 -23 9l-93 93q-119 -143 -318.5 -226.5t-429.5 -83.5t-429.5 83.5t-318.5 226.5l-93 -93q-9 -9 -23 -9q-4 0 -12 2q-20 8 -20 30v352
q0 14 9 23t23 9h352q22 0 30 -20q8 -19 -7 -35l-100 -100q67 -91 189.5 -153.5t271.5 -82.5v647h-192q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h192v163q-58 34 -93 92.5t-35 128.5q0 106 75 181t181 75t181 -75t75 -181q0 -70 -35 -128.5t-93 -92.5v-163h192q26 0 45 -19
t19 -45v-128q0 -26 -19 -45t-45 -19h-192v-647q149 20 271.5 82.5t189.5 153.5l-100 100q-15 16 -7 35q8 20 30 20h352q14 0 23 -9t9 -23z" />
    <glyph glyph-name="unlock_alt" unicode="&#xf13e;" horiz-adv-x="1152" 
d="M1056 768q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v320q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45q0 106 -75 181t-181 75t-181 -75t-75 -181
v-320h736z" />
    <glyph glyph-name="bullseye" unicode="&#xf140;" 
d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM1152 640q0 159 -112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM1280 640q0 -212 -150 -362t-362 -150t-362 150
t-150 362t150 362t362 150t362 -150t150 -362zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640
q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="ellipsis_horizontal" unicode="&#xf141;" horiz-adv-x="1408" 
d="M384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM896 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM1408 800v-192q0 -40 -28 -68t-68 -28h-192
q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" />
    <glyph glyph-name="ellipsis_vertical" unicode="&#xf142;" horiz-adv-x="384" 
d="M384 288v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 1312v-192q0 -40 -28 -68t-68 -28h-192
q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" />
    <glyph glyph-name="_303" unicode="&#xf143;" 
d="M512 256q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM863 162q-13 233 -176.5 396.5t-396.5 176.5q-14 1 -24 -9t-10 -23v-128q0 -13 8.5 -22t21.5 -10q154 -11 264 -121t121 -264q1 -13 10 -21.5t22 -8.5h128
q13 0 23 10t9 24zM1247 161q-5 154 -56 297.5t-139.5 260t-205 205t-260 139.5t-297.5 56q-14 1 -23 -9q-10 -10 -10 -23v-128q0 -13 9 -22t22 -10q204 -7 378 -111.5t278.5 -278.5t111.5 -378q1 -13 10 -22t22 -9h128q13 0 23 10q11 9 9 23zM1536 1120v-960
q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="play_sign" unicode="&#xf144;" 
d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1152 585q32 18 32 55t-32 55l-544 320q-31 19 -64 1q-32 -19 -32 -56v-640q0 -37 32 -56
q16 -8 32 -8q17 0 32 9z" />
    <glyph glyph-name="ticket" unicode="&#xf145;" horiz-adv-x="1792" 
d="M1024 1084l316 -316l-572 -572l-316 316zM813 105l618 618q19 19 19 45t-19 45l-362 362q-18 18 -45 18t-45 -18l-618 -618q-19 -19 -19 -45t19 -45l362 -362q18 -18 45 -18t45 18zM1702 742l-907 -908q-37 -37 -90.5 -37t-90.5 37l-126 126q56 56 56 136t-56 136
t-136 56t-136 -56l-125 126q-37 37 -37 90.5t37 90.5l907 906q37 37 90.5 37t90.5 -37l125 -125q-56 -56 -56 -136t56 -136t136 -56t136 56l126 -125q37 -37 37 -90.5t-37 -90.5z" />
    <glyph glyph-name="minus_sign_alt" unicode="&#xf146;" 
d="M1280 576v128q0 26 -19 45t-45 19h-896q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h896q26 0 45 19t19 45zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5
t84.5 -203.5z" />
    <glyph glyph-name="check_minus" unicode="&#xf147;" horiz-adv-x="1408" 
d="M1152 736v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h832q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5
t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="level_up" unicode="&#xf148;" horiz-adv-x="1024" 
d="M1018 933q-18 -37 -58 -37h-192v-864q0 -14 -9 -23t-23 -9h-704q-21 0 -29 18q-8 20 4 35l160 192q9 11 25 11h320v640h-192q-40 0 -58 37q-17 37 9 68l320 384q18 22 49 22t49 -22l320 -384q27 -32 9 -68z" />
    <glyph glyph-name="level_down" unicode="&#xf149;" horiz-adv-x="1024" 
d="M32 1280h704q13 0 22.5 -9.5t9.5 -23.5v-863h192q40 0 58 -37t-9 -69l-320 -384q-18 -22 -49 -22t-49 22l-320 384q-26 31 -9 69q18 37 58 37h192v640h-320q-14 0 -25 11l-160 192q-13 14 -4 34q9 19 29 19z" />
    <glyph glyph-name="check_sign" unicode="&#xf14a;" 
d="M685 237l614 614q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-467 -467l-211 211q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l358 -358q19 -19 45 -19t45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5
t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="edit_sign" unicode="&#xf14b;" 
d="M404 428l152 -152l-52 -52h-56v96h-96v56zM818 818q14 -13 -3 -30l-291 -291q-17 -17 -30 -3q-14 13 3 30l291 291q17 17 30 3zM544 128l544 544l-288 288l-544 -544v-288h288zM1152 736l92 92q28 28 28 68t-28 68l-152 152q-28 28 -68 28t-68 -28l-92 -92zM1536 1120
v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="_312" unicode="&#xf14c;" 
d="M1280 608v480q0 26 -19 45t-45 19h-480q-42 0 -59 -39q-17 -41 14 -70l144 -144l-534 -534q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l534 534l144 -144q18 -19 45 -19q12 0 25 5q39 17 39 59zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960
q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="share_sign" unicode="&#xf14d;" 
d="M1005 435l352 352q19 19 19 45t-19 45l-352 352q-30 31 -69 14q-40 -17 -40 -59v-160q-119 0 -216 -19.5t-162.5 -51t-114 -79t-76.5 -95.5t-44.5 -109t-21.5 -111.5t-5 -110.5q0 -181 167 -404q11 -12 25 -12q7 0 13 3q22 9 19 33q-44 354 62 473q46 52 130 75.5
t224 23.5v-160q0 -42 40 -59q12 -5 24 -5q26 0 45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="compass" unicode="&#xf14e;" 
d="M640 448l256 128l-256 128v-256zM1024 1039v-542l-512 -256v542zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103
t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="collapse" unicode="&#xf150;" 
d="M1145 861q18 -35 -5 -66l-320 -448q-19 -27 -52 -27t-52 27l-320 448q-23 31 -5 66q17 35 57 35h640q40 0 57 -35zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120
v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="collapse_top" unicode="&#xf151;" 
d="M1145 419q-17 -35 -57 -35h-640q-40 0 -57 35q-18 35 5 66l320 448q19 27 52 27t52 -27l320 -448q23 -31 5 -66zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120v-960
q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="_317" unicode="&#xf152;" 
d="M1088 640q0 -33 -27 -52l-448 -320q-31 -23 -66 -5q-35 17 -35 57v640q0 40 35 57q35 18 66 -5l448 -320q27 -19 27 -52zM1280 160v960q0 14 -9 23t-23 9h-960q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h960q14 0 23 9t9 23zM1536 1120v-960q0 -119 -84.5 -203.5
t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="eur" unicode="&#xf153;" horiz-adv-x="1024" 
d="M976 229l35 -159q3 -12 -3 -22.5t-17 -14.5l-5 -1q-4 -2 -10.5 -3.5t-16 -4.5t-21.5 -5.5t-25.5 -5t-30 -5t-33.5 -4.5t-36.5 -3t-38.5 -1q-234 0 -409 130.5t-238 351.5h-95q-13 0 -22.5 9.5t-9.5 22.5v113q0 13 9.5 22.5t22.5 9.5h66q-2 57 1 105h-67q-14 0 -23 9
t-9 23v114q0 14 9 23t23 9h98q67 210 243.5 338t400.5 128q102 0 194 -23q11 -3 20 -15q6 -11 3 -24l-43 -159q-3 -13 -14 -19.5t-24 -2.5l-4 1q-4 1 -11.5 2.5l-17.5 3.5t-22.5 3.5t-26 3t-29 2.5t-29.5 1q-126 0 -226 -64t-150 -176h468q16 0 25 -12q10 -12 7 -26
l-24 -114q-5 -26 -32 -26h-488q-3 -37 0 -105h459q15 0 25 -12q9 -12 6 -27l-24 -112q-2 -11 -11 -18.5t-20 -7.5h-387q48 -117 149.5 -185.5t228.5 -68.5q18 0 36 1.5t33.5 3.5t29.5 4.5t24.5 5t18.5 4.5l12 3l5 2q13 5 26 -2q12 -7 15 -21z" />
    <glyph glyph-name="gbp" unicode="&#xf154;" horiz-adv-x="1024" 
d="M1020 399v-367q0 -14 -9 -23t-23 -9h-956q-14 0 -23 9t-9 23v150q0 13 9.5 22.5t22.5 9.5h97v383h-95q-14 0 -23 9.5t-9 22.5v131q0 14 9 23t23 9h95v223q0 171 123.5 282t314.5 111q185 0 335 -125q9 -8 10 -20.5t-7 -22.5l-103 -127q-9 -11 -22 -12q-13 -2 -23 7
q-5 5 -26 19t-69 32t-93 18q-85 0 -137 -47t-52 -123v-215h305q13 0 22.5 -9t9.5 -23v-131q0 -13 -9.5 -22.5t-22.5 -9.5h-305v-379h414v181q0 13 9 22.5t23 9.5h162q14 0 23 -9.5t9 -22.5z" />
    <glyph glyph-name="usd" unicode="&#xf155;" horiz-adv-x="1024" 
d="M978 351q0 -153 -99.5 -263.5t-258.5 -136.5v-175q0 -14 -9 -23t-23 -9h-135q-13 0 -22.5 9.5t-9.5 22.5v175q-66 9 -127.5 31t-101.5 44.5t-74 48t-46.5 37.5t-17.5 18q-17 21 -2 41l103 135q7 10 23 12q15 2 24 -9l2 -2q113 -99 243 -125q37 -8 74 -8q81 0 142.5 43
t61.5 122q0 28 -15 53t-33.5 42t-58.5 37.5t-66 32t-80 32.5q-39 16 -61.5 25t-61.5 26.5t-62.5 31t-56.5 35.5t-53.5 42.5t-43.5 49t-35.5 58t-21 66.5t-8.5 78q0 138 98 242t255 134v180q0 13 9.5 22.5t22.5 9.5h135q14 0 23 -9t9 -23v-176q57 -6 110.5 -23t87 -33.5
t63.5 -37.5t39 -29t15 -14q17 -18 5 -38l-81 -146q-8 -15 -23 -16q-14 -3 -27 7q-3 3 -14.5 12t-39 26.5t-58.5 32t-74.5 26t-85.5 11.5q-95 0 -155 -43t-60 -111q0 -26 8.5 -48t29.5 -41.5t39.5 -33t56 -31t60.5 -27t70 -27.5q53 -20 81 -31.5t76 -35t75.5 -42.5t62 -50
t53 -63.5t31.5 -76.5t13 -94z" />
    <glyph glyph-name="inr" unicode="&#xf156;" horiz-adv-x="898" 
d="M898 1066v-102q0 -14 -9 -23t-23 -9h-168q-23 -144 -129 -234t-276 -110q167 -178 459 -536q14 -16 4 -34q-8 -18 -29 -18h-195q-16 0 -25 12q-306 367 -498 571q-9 9 -9 22v127q0 13 9.5 22.5t22.5 9.5h112q132 0 212.5 43t102.5 125h-427q-14 0 -23 9t-9 23v102
q0 14 9 23t23 9h413q-57 113 -268 113h-145q-13 0 -22.5 9.5t-9.5 22.5v133q0 14 9 23t23 9h832q14 0 23 -9t9 -23v-102q0 -14 -9 -23t-23 -9h-233q47 -61 64 -144h171q14 0 23 -9t9 -23z" />
    <glyph glyph-name="jpy" unicode="&#xf157;" horiz-adv-x="1027" 
d="M603 0h-172q-13 0 -22.5 9t-9.5 23v330h-288q-13 0 -22.5 9t-9.5 23v103q0 13 9.5 22.5t22.5 9.5h288v85h-288q-13 0 -22.5 9t-9.5 23v104q0 13 9.5 22.5t22.5 9.5h214l-321 578q-8 16 0 32q10 16 28 16h194q19 0 29 -18l215 -425q19 -38 56 -125q10 24 30.5 68t27.5 61
l191 420q8 19 29 19h191q17 0 27 -16q9 -14 1 -31l-313 -579h215q13 0 22.5 -9.5t9.5 -22.5v-104q0 -14 -9.5 -23t-22.5 -9h-290v-85h290q13 0 22.5 -9.5t9.5 -22.5v-103q0 -14 -9.5 -23t-22.5 -9h-290v-330q0 -13 -9.5 -22.5t-22.5 -9.5z" />
    <glyph glyph-name="rub" unicode="&#xf158;" horiz-adv-x="1280" 
d="M1043 971q0 100 -65 162t-171 62h-320v-448h320q106 0 171 62t65 162zM1280 971q0 -193 -126.5 -315t-326.5 -122h-340v-118h505q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9h-505v-192q0 -14 -9.5 -23t-22.5 -9h-167q-14 0 -23 9t-9 23v192h-224q-14 0 -23 9t-9 23v128
q0 14 9 23t23 9h224v118h-224q-14 0 -23 9t-9 23v149q0 13 9 22.5t23 9.5h224v629q0 14 9 23t23 9h539q200 0 326.5 -122t126.5 -315z" />
    <glyph glyph-name="krw" unicode="&#xf159;" horiz-adv-x="1792" 
d="M514 341l81 299h-159l75 -300q1 -1 1 -3t1 -3q0 1 0.5 3.5t0.5 3.5zM630 768l35 128h-292l32 -128h225zM822 768h139l-35 128h-70zM1271 340l78 300h-162l81 -299q0 -1 0.5 -3.5t1.5 -3.5q0 1 0.5 3t0.5 3zM1382 768l33 128h-297l34 -128h230zM1792 736v-64q0 -14 -9 -23
t-23 -9h-213l-164 -616q-7 -24 -31 -24h-159q-24 0 -31 24l-166 616h-209l-167 -616q-7 -24 -31 -24h-159q-11 0 -19.5 7t-10.5 17l-160 616h-208q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h175l-33 128h-142q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h109l-89 344q-5 15 5 28
q10 12 26 12h137q26 0 31 -24l90 -360h359l97 360q7 24 31 24h126q24 0 31 -24l98 -360h365l93 360q5 24 31 24h137q16 0 26 -12q10 -13 5 -28l-91 -344h111q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-145l-34 -128h179q14 0 23 -9t9 -23z" />
    <glyph glyph-name="btc" unicode="&#xf15a;" horiz-adv-x="1280" 
d="M1167 896q18 -182 -131 -258q117 -28 175 -103t45 -214q-7 -71 -32.5 -125t-64.5 -89t-97 -58.5t-121.5 -34.5t-145.5 -15v-255h-154v251q-80 0 -122 1v-252h-154v255q-18 0 -54 0.5t-55 0.5h-200l31 183h111q50 0 58 51v402h16q-6 1 -16 1v287q-13 68 -89 68h-111v164
l212 -1q64 0 97 1v252h154v-247q82 2 122 2v245h154v-252q79 -7 140 -22.5t113 -45t82.5 -78t36.5 -114.5zM952 351q0 36 -15 64t-37 46t-57.5 30.5t-65.5 18.5t-74 9t-69 3t-64.5 -1t-47.5 -1v-338q8 0 37 -0.5t48 -0.5t53 1.5t58.5 4t57 8.5t55.5 14t47.5 21t39.5 30
t24.5 40t9.5 51zM881 827q0 33 -12.5 58.5t-30.5 42t-48 28t-55 16.5t-61.5 8t-58 2.5t-54 -1t-39.5 -0.5v-307q5 0 34.5 -0.5t46.5 0t50 2t55 5.5t51.5 11t48.5 18.5t37 27t27 38.5t9 51z" />
    <glyph glyph-name="file" unicode="&#xf15b;" 
d="M1024 1024v472q22 -14 36 -28l408 -408q14 -14 28 -36h-472zM896 992q0 -40 28 -68t68 -28h544v-1056q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h800v-544z" />
    <glyph glyph-name="file_text" unicode="&#xf15c;" 
d="M1468 1060q14 -14 28 -36h-472v472q22 -14 36 -28zM992 896h544v-1056q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h800v-544q0 -40 28 -68t68 -28zM1152 160v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704
q14 0 23 9t9 23zM1152 416v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM1152 672v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23z" />
    <glyph glyph-name="sort_by_alphabet" unicode="&#xf15d;" horiz-adv-x="1664" 
d="M1191 1128h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1572 -23
v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -11v-2l14 2q9 2 30 2h248v119h121zM1661 874v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162
l230 -662h70z" />
    <glyph glyph-name="_329" unicode="&#xf15e;" horiz-adv-x="1664" 
d="M1191 104h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1661 -150
v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162l230 -662h70zM1572 1001v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -10v-3l14 3q9 1 30 1h248
v119h121z" />
    <glyph glyph-name="sort_by_attributes" unicode="&#xf160;" horiz-adv-x="1792" 
d="M736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1792 -32v-192q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832
q14 0 23 -9t9 -23zM1600 480v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1408 992v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1216 1504v-192q0 -14 -9 -23t-23 -9h-256
q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23z" />
    <glyph glyph-name="sort_by_attributes_alt" unicode="&#xf161;" horiz-adv-x="1792" 
d="M1216 -32v-192q0 -14 -9 -23t-23 -9h-256q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192
q14 0 23 -9t9 -23zM1408 480v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1600 992v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1792 1504v-192q0 -14 -9 -23t-23 -9h-832
q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832q14 0 23 -9t9 -23z" />
    <glyph glyph-name="sort_by_order" unicode="&#xf162;" 
d="M1346 223q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23
zM1486 165q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5
t82 -252.5zM1456 882v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165z" />
    <glyph glyph-name="sort_by_order_alt" unicode="&#xf163;" 
d="M1346 1247q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9
t9 -23zM1456 -142v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165zM1486 1189q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13
q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5t82 -252.5z" />
    <glyph glyph-name="_334" unicode="&#xf164;" horiz-adv-x="1664" 
d="M256 192q0 26 -19 45t-45 19q-27 0 -45.5 -19t-18.5 -45q0 -27 18.5 -45.5t45.5 -18.5q26 0 45 18.5t19 45.5zM416 704v-640q0 -26 -19 -45t-45 -19h-288q-26 0 -45 19t-19 45v640q0 26 19 45t45 19h288q26 0 45 -19t19 -45zM1600 704q0 -86 -55 -149q15 -44 15 -76
q3 -76 -43 -137q17 -56 0 -117q-15 -57 -54 -94q9 -112 -49 -181q-64 -76 -197 -78h-36h-76h-17q-66 0 -144 15.5t-121.5 29t-120.5 39.5q-123 43 -158 44q-26 1 -45 19.5t-19 44.5v641q0 25 18 43.5t43 20.5q24 2 76 59t101 121q68 87 101 120q18 18 31 48t17.5 48.5
t13.5 60.5q7 39 12.5 61t19.5 52t34 50q19 19 45 19q46 0 82.5 -10.5t60 -26t40 -40.5t24 -45t12 -50t5 -45t0.5 -39q0 -38 -9.5 -76t-19 -60t-27.5 -56q-3 -6 -10 -18t-11 -22t-8 -24h277q78 0 135 -57t57 -135z" />
    <glyph glyph-name="_335" unicode="&#xf165;" horiz-adv-x="1664" 
d="M256 960q0 -26 -19 -45t-45 -19q-27 0 -45.5 19t-18.5 45q0 27 18.5 45.5t45.5 18.5q26 0 45 -18.5t19 -45.5zM416 448v640q0 26 -19 45t-45 19h-288q-26 0 -45 -19t-19 -45v-640q0 -26 19 -45t45 -19h288q26 0 45 19t19 45zM1545 597q55 -61 55 -149q-1 -78 -57.5 -135
t-134.5 -57h-277q4 -14 8 -24t11 -22t10 -18q18 -37 27 -57t19 -58.5t10 -76.5q0 -24 -0.5 -39t-5 -45t-12 -50t-24 -45t-40 -40.5t-60 -26t-82.5 -10.5q-26 0 -45 19q-20 20 -34 50t-19.5 52t-12.5 61q-9 42 -13.5 60.5t-17.5 48.5t-31 48q-33 33 -101 120q-49 64 -101 121
t-76 59q-25 2 -43 20.5t-18 43.5v641q0 26 19 44.5t45 19.5q35 1 158 44q77 26 120.5 39.5t121.5 29t144 15.5h17h76h36q133 -2 197 -78q58 -69 49 -181q39 -37 54 -94q17 -61 0 -117q46 -61 43 -137q0 -32 -15 -76z" />
    <glyph glyph-name="youtube_sign" unicode="&#xf166;" 
d="M919 233v157q0 50 -29 50q-17 0 -33 -16v-224q16 -16 33 -16q29 0 29 49zM1103 355h66v34q0 51 -33 51t-33 -51v-34zM532 621v-70h-80v-423h-74v423h-78v70h232zM733 495v-367h-67v40q-39 -45 -76 -45q-33 0 -42 28q-6 17 -6 54v290h66v-270q0 -24 1 -26q1 -15 15 -15
q20 0 42 31v280h67zM985 384v-146q0 -52 -7 -73q-12 -42 -53 -42q-35 0 -68 41v-36h-67v493h67v-161q32 40 68 40q41 0 53 -42q7 -21 7 -74zM1236 255v-9q0 -29 -2 -43q-3 -22 -15 -40q-27 -40 -80 -40q-52 0 -81 38q-21 27 -21 86v129q0 59 20 86q29 38 80 38t78 -38
q21 -29 21 -86v-76h-133v-65q0 -51 34 -51q24 0 30 26q0 1 0.5 7t0.5 16.5v21.5h68zM785 1079v-156q0 -51 -32 -51t-32 51v156q0 52 32 52t32 -52zM1318 366q0 177 -19 260q-10 44 -43 73.5t-76 34.5q-136 15 -412 15q-275 0 -411 -15q-44 -5 -76.5 -34.5t-42.5 -73.5
q-20 -87 -20 -260q0 -176 20 -260q10 -43 42.5 -73t75.5 -35q137 -15 412 -15t412 15q43 5 75.5 35t42.5 73q20 84 20 260zM563 1017l90 296h-75l-51 -195l-53 195h-78q7 -23 23 -69l24 -69q35 -103 46 -158v-201h74v201zM852 936v130q0 58 -21 87q-29 38 -78 38
q-51 0 -78 -38q-21 -29 -21 -87v-130q0 -58 21 -87q27 -38 78 -38q49 0 78 38q21 27 21 87zM1033 816h67v370h-67v-283q-22 -31 -42 -31q-15 0 -16 16q-1 2 -1 26v272h-67v-293q0 -37 6 -55q11 -27 43 -27q36 0 77 45v-40zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5
h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="youtube" unicode="&#xf167;" 
d="M971 292v-211q0 -67 -39 -67q-23 0 -45 22v301q22 22 45 22q39 0 39 -67zM1309 291v-46h-90v46q0 68 45 68t45 -68zM343 509h107v94h-312v-94h105v-569h100v569zM631 -60h89v494h-89v-378q-30 -42 -57 -42q-18 0 -21 21q-1 3 -1 35v364h-89v-391q0 -49 8 -73
q12 -37 58 -37q48 0 102 61v-54zM1060 88v197q0 73 -9 99q-17 56 -71 56q-50 0 -93 -54v217h-89v-663h89v48q45 -55 93 -55q54 0 71 55q9 27 9 100zM1398 98v13h-91q0 -51 -2 -61q-7 -36 -40 -36q-46 0 -46 69v87h179v103q0 79 -27 116q-39 51 -106 51q-68 0 -107 -51
q-28 -37 -28 -116v-173q0 -79 29 -116q39 -51 108 -51q72 0 108 53q18 27 21 54q2 9 2 58zM790 1011v210q0 69 -43 69t-43 -69v-210q0 -70 43 -70t43 70zM1509 260q0 -234 -26 -350q-14 -59 -58 -99t-102 -46q-184 -21 -555 -21t-555 21q-58 6 -102.5 46t-57.5 99
q-26 112 -26 350q0 234 26 350q14 59 58 99t103 47q183 20 554 20t555 -20q58 -7 102.5 -47t57.5 -99q26 -112 26 -350zM511 1536h102l-121 -399v-271h-100v271q-14 74 -61 212q-37 103 -65 187h106l71 -263zM881 1203v-175q0 -81 -28 -118q-38 -51 -106 -51q-67 0 -105 51
q-28 38 -28 118v175q0 80 28 117q38 51 105 51q68 0 106 -51q28 -37 28 -117zM1216 1365v-499h-91v55q-53 -62 -103 -62q-46 0 -59 37q-8 24 -8 75v394h91v-367q0 -33 1 -35q3 -22 21 -22q27 0 57 43v381h91z" />
    <glyph glyph-name="xing" unicode="&#xf168;" horiz-adv-x="1408" 
d="M597 869q-10 -18 -257 -456q-27 -46 -65 -46h-239q-21 0 -31 17t0 36l253 448q1 0 0 1l-161 279q-12 22 -1 37q9 15 32 15h239q40 0 66 -45zM1403 1511q11 -16 0 -37l-528 -934v-1l336 -615q11 -20 1 -37q-10 -15 -32 -15h-239q-42 0 -66 45l-339 622q18 32 531 942
q25 45 64 45h241q22 0 31 -15z" />
    <glyph glyph-name="xing_sign" unicode="&#xf169;" 
d="M685 771q0 1 -126 222q-21 34 -52 34h-184q-18 0 -26 -11q-7 -12 1 -29l125 -216v-1l-196 -346q-9 -14 0 -28q8 -13 24 -13h185q31 0 50 36zM1309 1268q-7 12 -24 12h-187q-30 0 -49 -35l-411 -729q1 -2 262 -481q20 -35 52 -35h184q18 0 25 12q8 13 -1 28l-260 476v1
l409 723q8 16 0 28zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="youtube_play" unicode="&#xf16a;" horiz-adv-x="1792" 
d="M711 408l484 250l-484 253v-503zM896 1270q168 0 324.5 -4.5t229.5 -9.5l73 -4q1 0 17 -1.5t23 -3t23.5 -4.5t28.5 -8t28 -13t31 -19.5t29 -26.5q6 -6 15.5 -18.5t29 -58.5t26.5 -101q8 -64 12.5 -136.5t5.5 -113.5v-40v-136q1 -145 -18 -290q-7 -55 -25 -99.5t-32 -61.5
l-14 -17q-14 -15 -29 -26.5t-31 -19t-28 -12.5t-28.5 -8t-24 -4.5t-23 -3t-16.5 -1.5q-251 -19 -627 -19q-207 2 -359.5 6.5t-200.5 7.5l-49 4l-36 4q-36 5 -54.5 10t-51 21t-56.5 41q-6 6 -15.5 18.5t-29 58.5t-26.5 101q-8 64 -12.5 136.5t-5.5 113.5v40v136
q-1 145 18 290q7 55 25 99.5t32 61.5l14 17q14 15 29 26.5t31 19.5t28 13t28.5 8t23.5 4.5t23 3t17 1.5q251 18 627 18z" />
    <glyph glyph-name="dropbox" unicode="&#xf16b;" horiz-adv-x="1792" 
d="M402 829l494 -305l-342 -285l-490 319zM1388 274v-108l-490 -293v-1l-1 1l-1 -1v1l-489 293v108l147 -96l342 284v2l1 -1l1 1v-2l343 -284zM554 1418l342 -285l-494 -304l-338 270zM1390 829l338 -271l-489 -319l-343 285zM1239 1418l489 -319l-338 -270l-494 304z" />
    <glyph glyph-name="stackexchange" unicode="&#xf16c;" 
d="M1289 -96h-1118v480h-160v-640h1438v640h-160v-480zM347 428l33 157l783 -165l-33 -156zM450 802l67 146l725 -339l-67 -145zM651 1158l102 123l614 -513l-102 -123zM1048 1536l477 -641l-128 -96l-477 641zM330 65v159h800v-159h-800z" />
    <glyph glyph-name="instagram" unicode="&#xf16d;" 
d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1162 640q0 -164 -115 -279t-279 -115t-279 115t-115 279t115 279t279 115t279 -115t115 -279zM1270 1050q0 -38 -27 -65t-65 -27t-65 27t-27 65t27 65t65 27t65 -27t27 -65zM768 1270
q-7 0 -76.5 0.5t-105.5 0t-96.5 -3t-103 -10t-71.5 -18.5q-50 -20 -88 -58t-58 -88q-11 -29 -18.5 -71.5t-10 -103t-3 -96.5t0 -105.5t0.5 -76.5t-0.5 -76.5t0 -105.5t3 -96.5t10 -103t18.5 -71.5q20 -50 58 -88t88 -58q29 -11 71.5 -18.5t103 -10t96.5 -3t105.5 0t76.5 0.5
t76.5 -0.5t105.5 0t96.5 3t103 10t71.5 18.5q50 20 88 58t58 88q11 29 18.5 71.5t10 103t3 96.5t0 105.5t-0.5 76.5t0.5 76.5t0 105.5t-3 96.5t-10 103t-18.5 71.5q-20 50 -58 88t-88 58q-29 11 -71.5 18.5t-103 10t-96.5 3t-105.5 0t-76.5 -0.5zM1536 640q0 -229 -5 -317
q-10 -208 -124 -322t-322 -124q-88 -5 -317 -5t-317 5q-208 10 -322 124t-124 322q-5 88 -5 317t5 317q10 208 124 322t322 124q88 5 317 5t317 -5q208 -10 322 -124t124 -322q5 -88 5 -317z" />
    <glyph glyph-name="flickr" unicode="&#xf16e;" 
d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM698 640q0 88 -62 150t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150zM1262 640q0 88 -62 150
t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150z" />
    <glyph glyph-name="adn" unicode="&#xf170;" 
d="M768 914l201 -306h-402zM1133 384h94l-459 691l-459 -691h94l104 160h522zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="f171" unicode="&#xf171;" horiz-adv-x="1408" 
d="M815 677q8 -63 -50.5 -101t-111.5 -6q-39 17 -53.5 58t-0.5 82t52 58q36 18 72.5 12t64 -35.5t27.5 -67.5zM926 698q-14 107 -113 164t-197 13q-63 -28 -100.5 -88.5t-34.5 -129.5q4 -91 77.5 -155t165.5 -56q91 8 152 84t50 168zM1165 1240q-20 27 -56 44.5t-58 22
t-71 12.5q-291 47 -566 -2q-43 -7 -66 -12t-55 -22t-50 -43q30 -28 76 -45.5t73.5 -22t87.5 -11.5q228 -29 448 -1q63 8 89.5 12t72.5 21.5t75 46.5zM1222 205q-8 -26 -15.5 -76.5t-14 -84t-28.5 -70t-58 -56.5q-86 -48 -189.5 -71.5t-202 -22t-201.5 18.5q-46 8 -81.5 18
t-76.5 27t-73 43.5t-52 61.5q-25 96 -57 292l6 16l18 9q223 -148 506.5 -148t507.5 148q21 -6 24 -23t-5 -45t-8 -37zM1403 1166q-26 -167 -111 -655q-5 -30 -27 -56t-43.5 -40t-54.5 -31q-252 -126 -610 -88q-248 27 -394 139q-15 12 -25.5 26.5t-17 35t-9 34t-6 39.5
t-5.5 35q-9 50 -26.5 150t-28 161.5t-23.5 147.5t-22 158q3 26 17.5 48.5t31.5 37.5t45 30t46 22.5t48 18.5q125 46 313 64q379 37 676 -50q155 -46 215 -122q16 -20 16.5 -51t-5.5 -54z" />
    <glyph glyph-name="bitbucket_sign" unicode="&#xf172;" 
d="M848 666q0 43 -41 66t-77 1q-43 -20 -42.5 -72.5t43.5 -70.5q39 -23 81 4t36 72zM928 682q8 -66 -36 -121t-110 -61t-119 40t-56 113q-2 49 25.5 93t72.5 64q70 31 141.5 -10t81.5 -118zM1100 1073q-20 -21 -53.5 -34t-53 -16t-63.5 -8q-155 -20 -324 0q-44 6 -63 9.5
t-52.5 16t-54.5 32.5q13 19 36 31t40 15.5t47 8.5q198 35 408 1q33 -5 51 -8.5t43 -16t39 -31.5zM1142 327q0 7 5.5 26.5t3 32t-17.5 16.5q-161 -106 -365 -106t-366 106l-12 -6l-5 -12q26 -154 41 -210q47 -81 204 -108q249 -46 428 53q34 19 49 51.5t22.5 85.5t12.5 71z
M1272 1020q9 53 -8 75q-43 55 -155 88q-216 63 -487 36q-132 -12 -226 -46q-38 -15 -59.5 -25t-47 -34t-29.5 -54q8 -68 19 -138t29 -171t24 -137q1 -5 5 -31t7 -36t12 -27t22 -28q105 -80 284 -100q259 -28 440 63q24 13 39.5 23t31 29t19.5 40q48 267 80 473zM1536 1120
v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="tumblr" unicode="&#xf173;" horiz-adv-x="1024" 
d="M944 207l80 -237q-23 -35 -111 -66t-177 -32q-104 -2 -190.5 26t-142.5 74t-95 106t-55.5 120t-16.5 118v544h-168v215q72 26 129 69.5t91 90t58 102t34 99t15 88.5q1 5 4.5 8.5t7.5 3.5h244v-424h333v-252h-334v-518q0 -30 6.5 -56t22.5 -52.5t49.5 -41.5t81.5 -14
q78 2 134 29z" />
    <glyph glyph-name="tumblr_sign" unicode="&#xf174;" 
d="M1136 75l-62 183q-44 -22 -103 -22q-36 -1 -62 10.5t-38.5 31.5t-17.5 40.5t-5 43.5v398h257v194h-256v326h-188q-8 0 -9 -10q-5 -44 -17.5 -87t-39 -95t-77 -95t-118.5 -68v-165h130v-418q0 -57 21.5 -115t65 -111t121 -85.5t176.5 -30.5q69 1 136.5 25t85.5 50z
M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="long_arrow_down" unicode="&#xf175;" horiz-adv-x="768" 
d="M765 237q8 -19 -5 -35l-350 -384q-10 -10 -23 -10q-14 0 -24 10l-355 384q-13 16 -5 35q9 19 29 19h224v1248q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1248h224q21 0 29 -19z" />
    <glyph glyph-name="long_arrow_up" unicode="&#xf176;" horiz-adv-x="768" 
d="M765 1043q-9 -19 -29 -19h-224v-1248q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1248h-224q-21 0 -29 19t5 35l350 384q10 10 23 10q14 0 24 -10l355 -384q13 -16 5 -35z" />
    <glyph glyph-name="long_arrow_left" unicode="&#xf177;" horiz-adv-x="1792" 
d="M1792 736v-192q0 -14 -9 -23t-23 -9h-1248v-224q0 -21 -19 -29t-35 5l-384 350q-10 10 -10 23q0 14 10 24l384 354q16 14 35 6q19 -9 19 -29v-224h1248q14 0 23 -9t9 -23z" />
    <glyph glyph-name="long_arrow_right" unicode="&#xf178;" horiz-adv-x="1792" 
d="M1728 643q0 -14 -10 -24l-384 -354q-16 -14 -35 -6q-19 9 -19 29v224h-1248q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h1248v224q0 21 19 29t35 -5l384 -350q10 -10 10 -23z" />
    <glyph glyph-name="apple" unicode="&#xf179;" horiz-adv-x="1408" 
d="M1393 321q-39 -125 -123 -250q-129 -196 -257 -196q-49 0 -140 32q-86 32 -151 32q-61 0 -142 -33q-81 -34 -132 -34q-152 0 -301 259q-147 261 -147 503q0 228 113 374q113 144 284 144q72 0 177 -30q104 -30 138 -30q45 0 143 34q102 34 173 34q119 0 213 -65
q52 -36 104 -100q-79 -67 -114 -118q-65 -94 -65 -207q0 -124 69 -223t158 -126zM1017 1494q0 -61 -29 -136q-30 -75 -93 -138q-54 -54 -108 -72q-37 -11 -104 -17q3 149 78 257q74 107 250 148q1 -3 2.5 -11t2.5 -11q0 -4 0.5 -10t0.5 -10z" />
    <glyph glyph-name="windows" unicode="&#xf17a;" horiz-adv-x="1664" 
d="M682 530v-651l-682 94v557h682zM682 1273v-659h-682v565zM1664 530v-786l-907 125v661h907zM1664 1408v-794h-907v669z" />
    <glyph glyph-name="android" unicode="&#xf17b;" horiz-adv-x="1408" 
d="M493 1053q16 0 27.5 11.5t11.5 27.5t-11.5 27.5t-27.5 11.5t-27 -11.5t-11 -27.5t11 -27.5t27 -11.5zM915 1053q16 0 27 11.5t11 27.5t-11 27.5t-27 11.5t-27.5 -11.5t-11.5 -27.5t11.5 -27.5t27.5 -11.5zM103 869q42 0 72 -30t30 -72v-430q0 -43 -29.5 -73t-72.5 -30
t-73 30t-30 73v430q0 42 30 72t73 30zM1163 850v-666q0 -46 -32 -78t-77 -32h-75v-227q0 -43 -30 -73t-73 -30t-73 30t-30 73v227h-138v-227q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73l-1 227h-74q-46 0 -78 32t-32 78v666h918zM931 1255q107 -55 171 -153.5t64 -215.5
h-925q0 117 64 215.5t172 153.5l-71 131q-7 13 5 20q13 6 20 -6l72 -132q95 42 201 42t201 -42l72 132q7 12 20 6q12 -7 5 -20zM1408 767v-430q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73v430q0 43 30 72.5t72 29.5q43 0 73 -29.5t30 -72.5z" />
    <glyph glyph-name="linux" unicode="&#xf17c;" 
d="M663 1125q-11 -1 -15.5 -10.5t-8.5 -9.5q-5 -1 -5 5q0 12 19 15h10zM750 1111q-4 -1 -11.5 6.5t-17.5 4.5q24 11 32 -2q3 -6 -3 -9zM399 684q-4 1 -6 -3t-4.5 -12.5t-5.5 -13.5t-10 -13q-10 -11 -1 -12q4 -1 12.5 7t12.5 18q1 3 2 7t2 6t1.5 4.5t0.5 4v3t-1 2.5t-3 2z
M1254 325q0 18 -55 42q4 15 7.5 27.5t5 26t3 21.5t0.5 22.5t-1 19.5t-3.5 22t-4 20.5t-5 25t-5.5 26.5q-10 48 -47 103t-72 75q24 -20 57 -83q87 -162 54 -278q-11 -40 -50 -42q-31 -4 -38.5 18.5t-8 83.5t-11.5 107q-9 39 -19.5 69t-19.5 45.5t-15.5 24.5t-13 15t-7.5 7
q-14 62 -31 103t-29.5 56t-23.5 33t-15 40q-4 21 6 53.5t4.5 49.5t-44.5 25q-15 3 -44.5 18t-35.5 16q-8 1 -11 26t8 51t36 27q37 3 51 -30t4 -58q-11 -19 -2 -26.5t30 -0.5q13 4 13 36v37q-5 30 -13.5 50t-21 30.5t-23.5 15t-27 7.5q-107 -8 -89 -134q0 -15 -1 -15
q-9 9 -29.5 10.5t-33 -0.5t-15.5 5q1 57 -16 90t-45 34q-27 1 -41.5 -27.5t-16.5 -59.5q-1 -15 3.5 -37t13 -37.5t15.5 -13.5q10 3 16 14q4 9 -7 8q-7 0 -15.5 14.5t-9.5 33.5q-1 22 9 37t34 14q17 0 27 -21t9.5 -39t-1.5 -22q-22 -15 -31 -29q-8 -12 -27.5 -23.5
t-20.5 -12.5q-13 -14 -15.5 -27t7.5 -18q14 -8 25 -19.5t16 -19t18.5 -13t35.5 -6.5q47 -2 102 15q2 1 23 7t34.5 10.5t29.5 13t21 17.5q9 14 20 8q5 -3 6.5 -8.5t-3 -12t-16.5 -9.5q-20 -6 -56.5 -21.5t-45.5 -19.5q-44 -19 -70 -23q-25 -5 -79 2q-10 2 -9 -2t17 -19
q25 -23 67 -22q17 1 36 7t36 14t33.5 17.5t30 17t24.5 12t17.5 2.5t8.5 -11q0 -2 -1 -4.5t-4 -5t-6 -4.5t-8.5 -5t-9 -4.5t-10 -5t-9.5 -4.5q-28 -14 -67.5 -44t-66.5 -43t-49 -1q-21 11 -63 73q-22 31 -25 22q-1 -3 -1 -10q0 -25 -15 -56.5t-29.5 -55.5t-21 -58t11.5 -63
q-23 -6 -62.5 -90t-47.5 -141q-2 -18 -1.5 -69t-5.5 -59q-8 -24 -29 -3q-32 31 -36 94q-2 28 4 56q4 19 -1 18q-2 -1 -4 -5q-36 -65 10 -166q5 -12 25 -28t24 -20q20 -23 104 -90.5t93 -76.5q16 -15 17.5 -38t-14 -43t-45.5 -23q8 -15 29 -44.5t28 -54t7 -70.5q46 24 7 92
q-4 8 -10.5 16t-9.5 12t-2 6q3 5 13 9.5t20 -2.5q46 -52 166 -36q133 15 177 87q23 38 34 30q12 -6 10 -52q-1 -25 -23 -92q-9 -23 -6 -37.5t24 -15.5q3 19 14.5 77t13.5 90q2 21 -6.5 73.5t-7.5 97t23 70.5q15 18 51 18q1 37 34.5 53t72.5 10.5t60 -22.5zM626 1152
q3 17 -2.5 30t-11.5 15q-9 2 -9 -7q2 -5 5 -6q10 0 7 -15q-3 -20 8 -20q3 0 3 3zM1045 955q-2 8 -6.5 11.5t-13 5t-14.5 5.5q-5 3 -9.5 8t-7 8t-5.5 6.5t-4 4t-4 -1.5q-14 -16 7 -43.5t39 -31.5q9 -1 14.5 8t3.5 20zM867 1168q0 11 -5 19.5t-11 12.5t-9 3q-6 0 -8 -2t0 -4
t5 -3q14 -4 18 -31q0 -3 8 2q2 2 2 3zM921 1401q0 2 -2.5 5t-9 7t-9.5 6q-15 15 -24 15q-9 -1 -11.5 -7.5t-1 -13t-0.5 -12.5q-1 -4 -6 -10.5t-6 -9t3 -8.5q4 -3 8 0t11 9t15 9q1 1 9 1t15 2t9 7zM1486 60q20 -12 31 -24.5t12 -24t-2.5 -22.5t-15.5 -22t-23.5 -19.5
t-30 -18.5t-31.5 -16.5t-32 -15.5t-27 -13q-38 -19 -85.5 -56t-75.5 -64q-17 -16 -68 -19.5t-89 14.5q-18 9 -29.5 23.5t-16.5 25.5t-22 19.5t-47 9.5q-44 1 -130 1q-19 0 -57 -1.5t-58 -2.5q-44 -1 -79.5 -15t-53.5 -30t-43.5 -28.5t-53.5 -11.5q-29 1 -111 31t-146 43
q-19 4 -51 9.5t-50 9t-39.5 9.5t-33.5 14.5t-17 19.5q-10 23 7 66.5t18 54.5q1 16 -4 40t-10 42.5t-4.5 36.5t10.5 27q14 12 57 14t60 12q30 18 42 35t12 51q21 -73 -32 -106q-32 -20 -83 -15q-34 3 -43 -10q-13 -15 5 -57q2 -6 8 -18t8.5 -18t4.5 -17t1 -22q0 -15 -17 -49
t-14 -48q3 -17 37 -26q20 -6 84.5 -18.5t99.5 -20.5q24 -6 74 -22t82.5 -23t55.5 -4q43 6 64.5 28t23 48t-7.5 58.5t-19 52t-20 36.5q-121 190 -169 242q-68 74 -113 40q-11 -9 -15 15q-3 16 -2 38q1 29 10 52t24 47t22 42q8 21 26.5 72t29.5 78t30 61t39 54
q110 143 124 195q-12 112 -16 310q-2 90 24 151.5t106 104.5q39 21 104 21q53 1 106 -13.5t89 -41.5q57 -42 91.5 -121.5t29.5 -147.5q-5 -95 30 -214q34 -113 133 -218q55 -59 99.5 -163t59.5 -191q8 -49 5 -84.5t-12 -55.5t-20 -22q-10 -2 -23.5 -19t-27 -35.5
t-40.5 -33.5t-61 -14q-18 1 -31.5 5t-22.5 13.5t-13.5 15.5t-11.5 20.5t-9 19.5q-22 37 -41 30t-28 -49t7 -97q20 -70 1 -195q-10 -65 18 -100.5t73 -33t85 35.5q59 49 89.5 66.5t103.5 42.5q53 18 77 36.5t18.5 34.5t-25 28.5t-51.5 23.5q-33 11 -49.5 48t-15 72.5
t15.5 47.5q1 -31 8 -56.5t14.5 -40.5t20.5 -28.5t21 -19t21.5 -13t16.5 -9.5z" />
    <glyph glyph-name="dribble" unicode="&#xf17d;" 
d="M1024 36q-42 241 -140 498h-2l-2 -1q-16 -6 -43 -16.5t-101 -49t-137 -82t-131 -114.5t-103 -148l-15 11q184 -150 418 -150q132 0 256 52zM839 643q-21 49 -53 111q-311 -93 -673 -93q-1 -7 -1 -21q0 -124 44 -236.5t124 -201.5q50 89 123.5 166.5t142.5 124.5t130.5 81
t99.5 48l37 13q4 1 13 3.5t13 4.5zM732 855q-120 213 -244 378q-138 -65 -234 -186t-128 -272q302 0 606 80zM1416 536q-210 60 -409 29q87 -239 128 -469q111 75 185 189.5t96 250.5zM611 1277q-1 0 -2 -1q1 1 2 1zM1201 1132q-185 164 -433 164q-76 0 -155 -19
q131 -170 246 -382q69 26 130 60.5t96.5 61.5t65.5 57t37.5 40.5zM1424 647q-3 232 -149 410l-1 -1q-9 -12 -19 -24.5t-43.5 -44.5t-71 -60.5t-100 -65t-131.5 -64.5q25 -53 44 -95q2 -5 6.5 -17t7.5 -17q36 5 74.5 7t73.5 2t69 -1.5t64 -4t56.5 -5.5t48 -6.5t36.5 -6
t25 -4.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="skype" unicode="&#xf17e;" 
d="M1173 473q0 50 -19.5 91.5t-48.5 68.5t-73 49t-82.5 34t-87.5 23l-104 24q-30 7 -44 10.5t-35 11.5t-30 16t-16.5 21t-7.5 30q0 77 144 77q43 0 77 -12t54 -28.5t38 -33.5t40 -29t48 -12q47 0 75.5 32t28.5 77q0 55 -56 99.5t-142 67.5t-182 23q-68 0 -132 -15.5
t-119.5 -47t-89 -87t-33.5 -128.5q0 -61 19 -106.5t56 -75.5t80 -48.5t103 -32.5l146 -36q90 -22 112 -36q32 -20 32 -60q0 -39 -40 -64.5t-105 -25.5q-51 0 -91.5 16t-65 38.5t-45.5 45t-46 38.5t-54 16q-50 0 -75.5 -30t-25.5 -75q0 -92 122 -157.5t291 -65.5
q73 0 140 18.5t122.5 53.5t88.5 93.5t33 131.5zM1536 256q0 -159 -112.5 -271.5t-271.5 -112.5q-130 0 -234 80q-77 -16 -150 -16q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5q0 73 16 150q-80 104 -80 234q0 159 112.5 271.5t271.5 112.5q130 0 234 -80
q77 16 150 16q143 0 273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -73 -16 -150q80 -104 80 -234z" />
    <glyph glyph-name="foursquare" unicode="&#xf180;" horiz-adv-x="1280" 
d="M1000 1102l37 194q5 23 -9 40t-35 17h-712q-23 0 -38.5 -17t-15.5 -37v-1101q0 -7 6 -1l291 352q23 26 38 33.5t48 7.5h239q22 0 37 14.5t18 29.5q24 130 37 191q4 21 -11.5 40t-36.5 19h-294q-29 0 -48 19t-19 48v42q0 29 19 47.5t48 18.5h346q18 0 35 13.5t20 29.5z
M1227 1324q-15 -73 -53.5 -266.5t-69.5 -350t-35 -173.5q-6 -22 -9 -32.5t-14 -32.5t-24.5 -33t-38.5 -21t-58 -10h-271q-13 0 -22 -10q-8 -9 -426 -494q-22 -25 -58.5 -28.5t-48.5 5.5q-55 22 -55 98v1410q0 55 38 102.5t120 47.5h888q95 0 127 -53t10 -159zM1227 1324
l-158 -790q4 17 35 173.5t69.5 350t53.5 266.5z" />
    <glyph glyph-name="trello" unicode="&#xf181;" 
d="M704 192v1024q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-1024q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1376 576v640q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-640q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408
q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
    <glyph glyph-name="female" unicode="&#xf182;" horiz-adv-x="1280" 
d="M1280 480q0 -40 -28 -68t-68 -28q-51 0 -80 43l-227 341h-45v-132l247 -411q9 -15 9 -33q0 -26 -19 -45t-45 -19h-192v-272q0 -46 -33 -79t-79 -33h-160q-46 0 -79 33t-33 79v272h-192q-26 0 -45 19t-19 45q0 18 9 33l247 411v132h-45l-227 -341q-29 -43 -80 -43
q-40 0 -68 28t-28 68q0 29 16 53l256 384q73 107 176 107h384q103 0 176 -107l256 -384q16 -24 16 -53zM864 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
    <glyph glyph-name="male" unicode="&#xf183;" horiz-adv-x="1024" 
d="M1024 832v-416q0 -40 -28 -68t-68 -28t-68 28t-28 68v352h-64v-912q0 -46 -33 -79t-79 -33t-79 33t-33 79v464h-64v-464q0 -46 -33 -79t-79 -33t-79 33t-33 79v912h-64v-352q0 -40 -28 -68t-68 -28t-68 28t-28 68v416q0 80 56 136t136 56h640q80 0 136 -56t56 -136z
M736 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
    <glyph glyph-name="gittip" unicode="&#xf184;" 
d="M773 234l350 473q16 22 24.5 59t-6 85t-61.5 79q-40 26 -83 25.5t-73.5 -17.5t-54.5 -45q-36 -40 -96 -40q-59 0 -95 40q-24 28 -54.5 45t-73.5 17.5t-84 -25.5q-46 -31 -60.5 -79t-6 -85t24.5 -59zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103
t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="sun" unicode="&#xf185;" horiz-adv-x="1792" 
d="M1472 640q0 117 -45.5 223.5t-123 184t-184 123t-223.5 45.5t-223.5 -45.5t-184 -123t-123 -184t-45.5 -223.5t45.5 -223.5t123 -184t184 -123t223.5 -45.5t223.5 45.5t184 123t123 184t45.5 223.5zM1748 363q-4 -15 -20 -20l-292 -96v-306q0 -16 -13 -26q-15 -10 -29 -4
l-292 94l-180 -248q-10 -13 -26 -13t-26 13l-180 248l-292 -94q-14 -6 -29 4q-13 10 -13 26v306l-292 96q-16 5 -20 20q-5 17 4 29l180 248l-180 248q-9 13 -4 29q4 15 20 20l292 96v306q0 16 13 26q15 10 29 4l292 -94l180 248q9 12 26 12t26 -12l180 -248l292 94
q14 6 29 -4q13 -10 13 -26v-306l292 -96q16 -5 20 -20q5 -16 -4 -29l-180 -248l180 -248q9 -12 4 -29z" />
    <glyph glyph-name="_366" unicode="&#xf186;" 
d="M1262 233q-54 -9 -110 -9q-182 0 -337 90t-245 245t-90 337q0 192 104 357q-201 -60 -328.5 -229t-127.5 -384q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51q144 0 273.5 61.5t220.5 171.5zM1465 318q-94 -203 -283.5 -324.5t-413.5 -121.5q-156 0 -298 61
t-245 164t-164 245t-61 298q0 153 57.5 292.5t156 241.5t235.5 164.5t290 68.5q44 2 61 -39q18 -41 -15 -72q-86 -78 -131.5 -181.5t-45.5 -218.5q0 -148 73 -273t198 -198t273 -73q118 0 228 51q41 18 72 -13q14 -14 17.5 -34t-4.5 -38z" />
    <glyph glyph-name="archive" unicode="&#xf187;" horiz-adv-x="1792" 
d="M1088 704q0 26 -19 45t-45 19h-256q-26 0 -45 -19t-19 -45t19 -45t45 -19h256q26 0 45 19t19 45zM1664 896v-960q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v960q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1728 1344v-256q0 -26 -19 -45t-45 -19h-1536
q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1536q26 0 45 -19t19 -45z" />
    <glyph glyph-name="bug" unicode="&#xf188;" horiz-adv-x="1664" 
d="M1632 576q0 -26 -19 -45t-45 -19h-224q0 -171 -67 -290l208 -209q19 -19 19 -45t-19 -45q-18 -19 -45 -19t-45 19l-198 197q-5 -5 -15 -13t-42 -28.5t-65 -36.5t-82 -29t-97 -13v896h-128v-896q-51 0 -101.5 13.5t-87 33t-66 39t-43.5 32.5l-15 14l-183 -207
q-20 -21 -48 -21q-24 0 -43 16q-19 18 -20.5 44.5t15.5 46.5l202 227q-58 114 -58 274h-224q-26 0 -45 19t-19 45t19 45t45 19h224v294l-173 173q-19 19 -19 45t19 45t45 19t45 -19l173 -173h844l173 173q19 19 45 19t45 -19t19 -45t-19 -45l-173 -173v-294h224q26 0 45 -19
t19 -45zM1152 1152h-640q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5z" />
    <glyph glyph-name="vk" unicode="&#xf189;" horiz-adv-x="1920" 
d="M1917 1016q23 -64 -150 -294q-24 -32 -65 -85q-40 -51 -55 -72t-30.5 -49.5t-12 -42t13 -34.5t32.5 -43t57 -53q4 -2 5 -4q141 -131 191 -221q3 -5 6.5 -12.5t7 -26.5t-0.5 -34t-25 -27.5t-59 -12.5l-256 -4q-24 -5 -56 5t-52 22l-20 12q-30 21 -70 64t-68.5 77.5t-61 58
t-56.5 15.5q-3 -1 -8 -3.5t-17 -14.5t-21.5 -29.5t-17 -52t-6.5 -77.5q0 -15 -3.5 -27.5t-7.5 -18.5l-4 -5q-18 -19 -53 -22h-115q-71 -4 -146 16.5t-131.5 53t-103 66t-70.5 57.5l-25 24q-10 10 -27.5 30t-71.5 91t-106 151t-122.5 211t-130.5 272q-6 16 -6 27t3 16l4 6
q15 19 57 19l274 2q12 -2 23 -6.5t16 -8.5l5 -3q16 -11 24 -32q20 -50 46 -103.5t41 -81.5l16 -29q29 -60 56 -104t48.5 -68.5t41.5 -38.5t34 -14t27 5q2 1 5 5t12 22t13.5 47t9.5 81t0 125q-2 40 -9 73t-14 46l-6 12q-25 34 -85 43q-13 2 5 24q16 19 38 30q53 26 239 24
q82 -1 135 -13q20 -5 33.5 -13.5t20.5 -24t10.5 -32t3.5 -45.5t-1 -55t-2.5 -70.5t-1.5 -82.5q0 -11 -1 -42t-0.5 -48t3.5 -40.5t11.5 -39t22.5 -24.5q8 -2 17 -4t26 11t38 34.5t52 67t68 107.5q60 104 107 225q4 10 10 17.5t11 10.5l4 3l5 2.5t13 3t20 0.5l288 2
q39 5 64 -2.5t31 -16.5z" />
    <glyph glyph-name="weibo" unicode="&#xf18a;" horiz-adv-x="1792" 
d="M675 252q21 34 11 69t-45 50q-34 14 -73 1t-60 -46q-22 -34 -13 -68.5t43 -50.5t74.5 -2.5t62.5 47.5zM769 373q8 13 3.5 26.5t-17.5 18.5q-14 5 -28.5 -0.5t-21.5 -18.5q-17 -31 13 -45q14 -5 29 0.5t22 18.5zM943 266q-45 -102 -158 -150t-224 -12
q-107 34 -147.5 126.5t6.5 187.5q47 93 151.5 139t210.5 19q111 -29 158.5 -119.5t2.5 -190.5zM1255 426q-9 96 -89 170t-208.5 109t-274.5 21q-223 -23 -369.5 -141.5t-132.5 -264.5q9 -96 89 -170t208.5 -109t274.5 -21q223 23 369.5 141.5t132.5 264.5zM1563 422
q0 -68 -37 -139.5t-109 -137t-168.5 -117.5t-226 -83t-270.5 -31t-275 33.5t-240.5 93t-171.5 151t-65 199.5q0 115 69.5 245t197.5 258q169 169 341.5 236t246.5 -7q65 -64 20 -209q-4 -14 -1 -20t10 -7t14.5 0.5t13.5 3.5l6 2q139 59 246 59t153 -61q45 -63 0 -178
q-2 -13 -4.5 -20t4.5 -12.5t12 -7.5t17 -6q57 -18 103 -47t80 -81.5t34 -116.5zM1489 1046q42 -47 54.5 -108.5t-6.5 -117.5q-8 -23 -29.5 -34t-44.5 -4q-23 8 -34 29.5t-4 44.5q20 63 -24 111t-107 35q-24 -5 -45 8t-25 37q-5 24 8 44.5t37 25.5q60 13 119 -5.5t101 -65.5z
M1670 1209q87 -96 112.5 -222.5t-13.5 -241.5q-9 -27 -34 -40t-52 -4t-40 34t-5 52q28 82 10 172t-80 158q-62 69 -148 95.5t-173 8.5q-28 -6 -52 9.5t-30 43.5t9.5 51.5t43.5 29.5q123 26 244 -11.5t208 -134.5z" />
    <glyph glyph-name="renren" unicode="&#xf18b;" 
d="M1133 -34q-171 -94 -368 -94q-196 0 -367 94q138 87 235.5 211t131.5 268q35 -144 132.5 -268t235.5 -211zM638 1394v-485q0 -252 -126.5 -459.5t-330.5 -306.5q-181 215 -181 495q0 187 83.5 349.5t229.5 269.5t325 137zM1536 638q0 -280 -181 -495
q-204 99 -330.5 306.5t-126.5 459.5v485q179 -30 325 -137t229.5 -269.5t83.5 -349.5z" />
    <glyph glyph-name="_372" unicode="&#xf18c;" horiz-adv-x="1408" 
d="M1402 433q-32 -80 -76 -138t-91 -88.5t-99 -46.5t-101.5 -14.5t-96.5 8.5t-86.5 22t-69.5 27.5t-46 22.5l-17 10q-113 -228 -289.5 -359.5t-384.5 -132.5q-19 0 -32 13t-13 32t13 31.5t32 12.5q173 1 322.5 107.5t251.5 294.5q-36 -14 -72 -23t-83 -13t-91 2.5t-93 28.5
t-92 59t-84.5 100t-74.5 146q114 47 214 57t167.5 -7.5t124.5 -56.5t88.5 -77t56.5 -82q53 131 79 291q-7 -1 -18 -2.5t-46.5 -2.5t-69.5 0.5t-81.5 10t-88.5 23t-84 42.5t-75 65t-54.5 94.5t-28.5 127.5q70 28 133.5 36.5t112.5 -1t92 -30t73.5 -50t56 -61t42 -63t27.5 -56
t16 -39.5l4 -16q12 122 12 195q-8 6 -21.5 16t-49 44.5t-63.5 71.5t-54 93t-33 112.5t12 127t70 138.5q73 -25 127.5 -61.5t84.5 -76.5t48 -85t20.5 -89t-0.5 -85.5t-13 -76.5t-19 -62t-17 -42l-7 -15q1 -4 1 -50t-1 -72q3 7 10 18.5t30.5 43t50.5 58t71 55.5t91.5 44.5
t112 14.5t132.5 -24q-2 -78 -21.5 -141.5t-50 -104.5t-69.5 -71.5t-81.5 -45.5t-84.5 -24t-80 -9.5t-67.5 1t-46.5 4.5l-17 3q-23 -147 -73 -283q6 7 18 18.5t49.5 41t77.5 52.5t99.5 42t117.5 20t129 -23.5t137 -77.5z" />
    <glyph glyph-name="stack_exchange" unicode="&#xf18d;" horiz-adv-x="1280" 
d="M1259 283v-66q0 -85 -57.5 -144.5t-138.5 -59.5h-57l-260 -269v269h-529q-81 0 -138.5 59.5t-57.5 144.5v66h1238zM1259 609v-255h-1238v255h1238zM1259 937v-255h-1238v255h1238zM1259 1077v-67h-1238v67q0 84 57.5 143.5t138.5 59.5h846q81 0 138.5 -59.5t57.5 -143.5z
" />
    <glyph glyph-name="_374" unicode="&#xf18e;" 
d="M1152 640q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192h-352q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h352v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198
t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="arrow_circle_alt_left" unicode="&#xf190;" 
d="M1152 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-352v-192q0 -14 -9 -23t-23 -9q-12 0 -24 10l-319 319q-9 9 -9 23t9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h352q13 0 22.5 -9.5t9.5 -22.5zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198
t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="_376" unicode="&#xf191;" 
d="M1024 960v-640q0 -26 -19 -45t-45 -19q-20 0 -37 12l-448 320q-27 19 -27 52t27 52l448 320q17 12 37 12q26 0 45 -19t19 -45zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5z
M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="dot_circle_alt" unicode="&#xf192;" 
d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5
t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="_378" unicode="&#xf193;" horiz-adv-x="1664" 
d="M1023 349l102 -204q-58 -179 -210 -290t-339 -111q-156 0 -288.5 77.5t-210 210t-77.5 288.5q0 181 104.5 330t274.5 211l17 -131q-122 -54 -195 -165.5t-73 -244.5q0 -185 131.5 -316.5t316.5 -131.5q126 0 232.5 65t165 175.5t49.5 236.5zM1571 249l58 -114l-256 -128
q-13 -7 -29 -7q-40 0 -57 35l-239 477h-472q-24 0 -42.5 16.5t-21.5 40.5l-96 779q-2 17 6 42q14 51 57 82.5t97 31.5q66 0 113 -47t47 -113q0 -69 -52 -117.5t-120 -41.5l37 -289h423v-128h-407l16 -128h455q40 0 57 -35l228 -455z" />
    <glyph glyph-name="vimeo_square" unicode="&#xf194;" 
d="M1292 898q10 216 -161 222q-231 8 -312 -261q44 19 82 19q85 0 74 -96q-4 -57 -74 -167t-105 -110q-43 0 -82 169q-13 54 -45 255q-30 189 -160 177q-59 -7 -164 -100l-81 -72l-81 -72l52 -67q76 52 87 52q57 0 107 -179q15 -55 45 -164.5t45 -164.5q68 -179 164 -179
q157 0 383 294q220 283 226 444zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="_380" unicode="&#xf195;" horiz-adv-x="1152" 
d="M1152 704q0 -191 -94.5 -353t-256.5 -256.5t-353 -94.5h-160q-14 0 -23 9t-9 23v611l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v93l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v250q0 14 9 23t23 9h160
q14 0 23 -9t9 -23v-181l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-93l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-487q188 13 318 151t130 328q0 14 9 23t23 9h160q14 0 23 -9t9 -23z" />
    <glyph glyph-name="plus_square_o" unicode="&#xf196;" horiz-adv-x="1408" 
d="M1152 736v-64q0 -14 -9 -23t-23 -9h-352v-352q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v352h-352q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h352v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-352h352q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832
q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="_382" unicode="&#xf197;" horiz-adv-x="2176" 
d="M620 416q-110 -64 -268 -64h-128v64h-64q-13 0 -22.5 23.5t-9.5 56.5q0 24 7 49q-58 2 -96.5 10.5t-38.5 20.5t38.5 20.5t96.5 10.5q-7 25 -7 49q0 33 9.5 56.5t22.5 23.5h64v64h128q158 0 268 -64h1113q42 -7 106.5 -18t80.5 -14q89 -15 150 -40.5t83.5 -47.5t22.5 -40
t-22.5 -40t-83.5 -47.5t-150 -40.5q-16 -3 -80.5 -14t-106.5 -18h-1113zM1739 668q53 -36 53 -92t-53 -92l81 -30q68 48 68 122t-68 122zM625 400h1015q-217 -38 -456 -80q-57 0 -113 -24t-83 -48l-28 -24l-288 -288q-26 -26 -70.5 -45t-89.5 -19h-96l-93 464h29
q157 0 273 64zM352 816h-29l93 464h96q46 0 90 -19t70 -45l288 -288q4 -4 11 -10.5t30.5 -23t48.5 -29t61.5 -23t72.5 -10.5l456 -80h-1015q-116 64 -273 64z" />
    <glyph glyph-name="_383" unicode="&#xf198;" horiz-adv-x="1664" 
d="M1519 760q62 0 103.5 -40.5t41.5 -101.5q0 -97 -93 -130l-172 -59l56 -167q7 -21 7 -47q0 -59 -42 -102t-101 -43q-47 0 -85.5 27t-53.5 72l-55 165l-310 -106l55 -164q8 -24 8 -47q0 -59 -42 -102t-102 -43q-47 0 -85 27t-53 72l-55 163l-153 -53q-29 -9 -50 -9
q-61 0 -101.5 40t-40.5 101q0 47 27.5 85t71.5 53l156 53l-105 313l-156 -54q-26 -8 -48 -8q-60 0 -101 40.5t-41 100.5q0 47 27.5 85t71.5 53l157 53l-53 159q-8 24 -8 47q0 60 42 102.5t102 42.5q47 0 85 -27t53 -72l54 -160l310 105l-54 160q-8 24 -8 47q0 59 42.5 102
t101.5 43q47 0 85.5 -27.5t53.5 -71.5l53 -161l162 55q21 6 43 6q60 0 102.5 -39.5t42.5 -98.5q0 -45 -30 -81.5t-74 -51.5l-157 -54l105 -316l164 56q24 8 46 8zM725 498l310 105l-105 315l-310 -107z" />
    <glyph glyph-name="_384" unicode="&#xf199;" 
d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM1280 352v436q-31 -35 -64 -55q-34 -22 -132.5 -85t-151.5 -99q-98 -69 -164 -69v0v0q-66 0 -164 69
q-47 32 -142 92.5t-142 92.5q-12 8 -33 27t-31 27v-436q0 -40 28 -68t68 -28h832q40 0 68 28t28 68zM1280 925q0 41 -27.5 70t-68.5 29h-832q-40 0 -68 -28t-28 -68q0 -37 30.5 -76.5t67.5 -64.5q47 -32 137.5 -89t129.5 -83q3 -2 17 -11.5t21 -14t21 -13t23.5 -13
t21.5 -9.5t22.5 -7.5t20.5 -2.5t20.5 2.5t22.5 7.5t21.5 9.5t23.5 13t21 13t21 14t17 11.5l267 174q35 23 66.5 62.5t31.5 73.5z" />
    <glyph glyph-name="_385" unicode="&#xf19a;" horiz-adv-x="1792" 
d="M127 640q0 163 67 313l367 -1005q-196 95 -315 281t-119 411zM1415 679q0 -19 -2.5 -38.5t-10 -49.5t-11.5 -44t-17.5 -59t-17.5 -58l-76 -256l-278 826q46 3 88 8q19 2 26 18.5t-2.5 31t-28.5 13.5l-205 -10q-75 1 -202 10q-12 1 -20.5 -5t-11.5 -15t-1.5 -18.5t9 -16.5
t19.5 -8l80 -8l120 -328l-168 -504l-280 832q46 3 88 8q19 2 26 18.5t-2.5 31t-28.5 13.5l-205 -10q-7 0 -23 0.5t-26 0.5q105 160 274.5 253.5t367.5 93.5q147 0 280.5 -53t238.5 -149h-10q-55 0 -92 -40.5t-37 -95.5q0 -12 2 -24t4 -21.5t8 -23t9 -21t12 -22.5t12.5 -21
t14.5 -24t14 -23q63 -107 63 -212zM909 573l237 -647q1 -6 5 -11q-126 -44 -255 -44q-112 0 -217 32zM1570 1009q95 -174 95 -369q0 -209 -104 -385.5t-279 -278.5l235 678q59 169 59 276q0 42 -6 79zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286
t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM896 -215q173 0 331.5 68t273 182.5t182.5 273t68 331.5t-68 331.5t-182.5 273t-273 182.5t-331.5 68t-331.5 -68t-273 -182.5t-182.5 -273t-68 -331.5t68 -331.5t182.5 -273
t273 -182.5t331.5 -68z" />
    <glyph glyph-name="_386" unicode="&#xf19b;" horiz-adv-x="1792" 
d="M1086 1536v-1536l-272 -128q-228 20 -414 102t-293 208.5t-107 272.5q0 140 100.5 263.5t275 205.5t391.5 108v-172q-217 -38 -356.5 -150t-139.5 -255q0 -152 154.5 -267t388.5 -145v1360zM1755 954l37 -390l-525 114l147 83q-119 70 -280 99v172q277 -33 481 -157z" />
    <glyph glyph-name="_387" unicode="&#xf19c;" horiz-adv-x="2048" 
d="M960 1536l960 -384v-128h-128q0 -26 -20.5 -45t-48.5 -19h-1526q-28 0 -48.5 19t-20.5 45h-128v128zM256 896h256v-768h128v768h256v-768h128v768h256v-768h128v768h256v-768h59q28 0 48.5 -19t20.5 -45v-64h-1664v64q0 26 20.5 45t48.5 19h59v768zM1851 -64
q28 0 48.5 -19t20.5 -45v-128h-1920v128q0 26 20.5 45t48.5 19h1782z" />
    <glyph glyph-name="_388" unicode="&#xf19d;" horiz-adv-x="2304" 
d="M1774 700l18 -316q4 -69 -82 -128t-235 -93.5t-323 -34.5t-323 34.5t-235 93.5t-82 128l18 316l574 -181q22 -7 48 -7t48 7zM2304 1024q0 -23 -22 -31l-1120 -352q-4 -1 -10 -1t-10 1l-652 206q-43 -34 -71 -111.5t-34 -178.5q63 -36 63 -109q0 -69 -58 -107l58 -433
q2 -14 -8 -25q-9 -11 -24 -11h-192q-15 0 -24 11q-10 11 -8 25l58 433q-58 38 -58 107q0 73 65 111q11 207 98 330l-333 104q-22 8 -22 31t22 31l1120 352q4 1 10 1t10 -1l1120 -352q22 -8 22 -31z" />
    <glyph glyph-name="_389" unicode="&#xf19e;" 
d="M859 579l13 -707q-62 11 -105 11q-41 0 -105 -11l13 707q-40 69 -168.5 295.5t-216.5 374.5t-181 287q58 -15 108 -15q44 0 111 15q63 -111 133.5 -229.5t167 -276.5t138.5 -227q37 61 109.5 177.5t117.5 190t105 176t107 189.5q54 -14 107 -14q56 0 114 14v0
q-28 -39 -60 -88.5t-49.5 -78.5t-56.5 -96t-49 -84q-146 -248 -353 -610z" />
    <glyph glyph-name="uniF1A0" unicode="&#xf1a0;" 
d="M768 750h725q12 -67 12 -128q0 -217 -91 -387.5t-259.5 -266.5t-386.5 -96q-157 0 -299 60.5t-245 163.5t-163.5 245t-60.5 299t60.5 299t163.5 245t245 163.5t299 60.5q300 0 515 -201l-209 -201q-123 119 -306 119q-129 0 -238.5 -65t-173.5 -176.5t-64 -243.5
t64 -243.5t173.5 -176.5t238.5 -65q87 0 160 24t120 60t82 82t51.5 87t22.5 78h-436v264z" />
    <glyph glyph-name="f1a1" unicode="&#xf1a1;" horiz-adv-x="1792" 
d="M1095 369q16 -16 0 -31q-62 -62 -199 -62t-199 62q-16 15 0 31q6 6 15 6t15 -6q48 -49 169 -49q120 0 169 49q6 6 15 6t15 -6zM788 550q0 -37 -26 -63t-63 -26t-63.5 26t-26.5 63q0 38 26.5 64t63.5 26t63 -26.5t26 -63.5zM1183 550q0 -37 -26.5 -63t-63.5 -26t-63 26
t-26 63t26 63.5t63 26.5t63.5 -26t26.5 -64zM1434 670q0 49 -35 84t-85 35t-86 -36q-130 90 -311 96l63 283l200 -45q0 -37 26 -63t63 -26t63.5 26.5t26.5 63.5t-26.5 63.5t-63.5 26.5q-54 0 -80 -50l-221 49q-19 5 -25 -16l-69 -312q-180 -7 -309 -97q-35 37 -87 37
q-50 0 -85 -35t-35 -84q0 -35 18.5 -64t49.5 -44q-6 -27 -6 -56q0 -142 140 -243t337 -101q198 0 338 101t140 243q0 32 -7 57q30 15 48 43.5t18 63.5zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191
t348 71t348 -71t286 -191t191 -286t71 -348z" />
    <glyph glyph-name="_392" unicode="&#xf1a2;" 
d="M939 407q13 -13 0 -26q-53 -53 -171 -53t-171 53q-13 13 0 26q5 6 13 6t13 -6q42 -42 145 -42t145 42q5 6 13 6t13 -6zM676 563q0 -31 -23 -54t-54 -23t-54 23t-23 54q0 32 22.5 54.5t54.5 22.5t54.5 -22.5t22.5 -54.5zM1014 563q0 -31 -23 -54t-54 -23t-54 23t-23 54
q0 32 22.5 54.5t54.5 22.5t54.5 -22.5t22.5 -54.5zM1229 666q0 42 -30 72t-73 30q-42 0 -73 -31q-113 78 -267 82l54 243l171 -39q1 -32 23.5 -54t53.5 -22q32 0 54.5 22.5t22.5 54.5t-22.5 54.5t-54.5 22.5q-48 0 -69 -43l-189 42q-17 5 -21 -13l-60 -268q-154 -6 -265 -83
q-30 32 -74 32q-43 0 -73 -30t-30 -72q0 -30 16 -55t42 -38q-5 -25 -5 -48q0 -122 120 -208.5t289 -86.5q170 0 290 86.5t120 208.5q0 25 -6 49q25 13 40.5 37.5t15.5 54.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960
q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="_393" unicode="&#xf1a3;" 
d="M866 697l90 27v62q0 79 -58 135t-138 56t-138 -55.5t-58 -134.5v-283q0 -20 -14 -33.5t-33 -13.5t-32.5 13.5t-13.5 33.5v120h-151v-122q0 -82 57.5 -139t139.5 -57q81 0 138.5 56.5t57.5 136.5v280q0 19 13.5 33t33.5 14q19 0 32.5 -14t13.5 -33v-54zM1199 502v122h-150
v-126q0 -20 -13.5 -33.5t-33.5 -13.5q-19 0 -32.5 14t-13.5 33v123l-90 -26l-60 28v-123q0 -80 58 -137t139 -57t138.5 57t57.5 139zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103
t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="f1a4" unicode="&#xf1a4;" horiz-adv-x="1920" 
d="M1062 824v118q0 42 -30 72t-72 30t-72 -30t-30 -72v-612q0 -175 -126 -299t-303 -124q-178 0 -303.5 125.5t-125.5 303.5v266h328v-262q0 -43 30 -72.5t72 -29.5t72 29.5t30 72.5v620q0 171 126.5 292t301.5 121q176 0 302 -122t126 -294v-136l-195 -58zM1592 602h328
v-266q0 -178 -125.5 -303.5t-303.5 -125.5q-177 0 -303 124.5t-126 300.5v268l131 -61l195 58v-270q0 -42 30 -71.5t72 -29.5t72 29.5t30 71.5v275z" />
    <glyph glyph-name="_395" unicode="&#xf1a5;" 
d="M1472 160v480h-704v704h-480q-93 0 -158.5 -65.5t-65.5 -158.5v-480h704v-704h480q93 0 158.5 65.5t65.5 158.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5
t84.5 -203.5z" />
    <glyph glyph-name="_396" unicode="&#xf1a6;" horiz-adv-x="2048" 
d="M328 1254h204v-983h-532v697h328v286zM328 435v369h-123v-369h123zM614 968v-697h205v697h-205zM614 1254v-204h205v204h-205zM901 968h533v-942h-533v163h328v82h-328v697zM1229 435v369h-123v-369h123zM1516 968h532v-942h-532v163h327v82h-327v697zM1843 435v369h-123
v-369h123z" />
    <glyph glyph-name="_397" unicode="&#xf1a7;" 
d="M1046 516q0 -64 -38 -109t-91 -45q-43 0 -70 15v277q28 17 70 17q53 0 91 -45.5t38 -109.5zM703 944q0 -64 -38 -109.5t-91 -45.5q-43 0 -70 15v277q28 17 70 17q53 0 91 -45t38 -109zM1265 513q0 134 -88 229t-213 95q-20 0 -39 -3q-23 -78 -78 -136q-87 -95 -211 -101
v-636l211 41v206q51 -19 117 -19q125 0 213 95t88 229zM922 940q0 134 -88.5 229t-213.5 95q-74 0 -141 -36h-186v-840l211 41v206q55 -19 116 -19q125 0 213.5 95t88.5 229zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960
q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="_398" unicode="&#xf1a8;" horiz-adv-x="2038" 
d="M1222 607q75 3 143.5 -20.5t118 -58.5t101 -94.5t84 -108t75.5 -120.5q33 -56 78.5 -109t75.5 -80.5t99 -88.5q-48 -30 -108.5 -57.5t-138.5 -59t-114 -47.5q-44 37 -74 115t-43.5 164.5t-33 180.5t-42.5 168.5t-72.5 123t-122.5 48.5l-10 -2l-6 -4q4 -5 13 -14
q6 -5 28 -23.5t25.5 -22t19 -18t18 -20.5t11.5 -21t10.5 -27.5t4.5 -31t4 -40.5l1 -33q1 -26 -2.5 -57.5t-7.5 -52t-12.5 -58.5t-11.5 -53q-35 1 -101 -9.5t-98 -10.5q-39 0 -72 10q-2 16 -2 47q0 74 3 96q2 13 31.5 41.5t57 59t26.5 51.5q-24 2 -43 -24
q-36 -53 -111.5 -99.5t-136.5 -46.5q-25 0 -75.5 63t-106.5 139.5t-84 96.5q-6 4 -27 30q-482 -112 -513 -112q-16 0 -28 11t-12 27q0 15 8.5 26.5t22.5 14.5l486 106q-8 14 -8 25t5.5 17.5t16 11.5t20 7t23 4.5t18.5 4.5q4 1 15.5 7.5t17.5 6.5q15 0 28 -16t20 -33
q163 37 172 37q17 0 29.5 -11t12.5 -28q0 -15 -8.5 -26t-23.5 -14l-182 -40l-1 -16q-1 -26 81.5 -117.5t104.5 -91.5q47 0 119 80t72 129q0 36 -23.5 53t-51 18.5t-51 11.5t-23.5 34q0 16 10 34l-68 19q43 44 43 117q0 26 -5 58q82 16 144 16q44 0 71.5 -1.5t48.5 -8.5
t31 -13.5t20.5 -24.5t15.5 -33.5t17 -47.5t24 -60l50 25q-3 -40 -23 -60t-42.5 -21t-40 -6.5t-16.5 -20.5zM1282 842q-5 5 -13.5 15.5t-12 14.5t-10.5 11.5t-10 10.5l-8 8t-8.5 7.5t-8 5t-8.5 4.5q-7 3 -14.5 5t-20.5 2.5t-22 0.5h-32.5h-37.5q-126 0 -217 -43
q16 30 36 46.5t54 29.5t65.5 36t46 36.5t50 55t43.5 50.5q12 -9 28 -31.5t32 -36.5t38 -13l12 1v-76l22 -1q247 95 371 190q28 21 50 39t42.5 37.5t33 31t29.5 34t24 31t24.5 37t23 38t27 47.5t29.5 53l7 9q-2 -53 -43 -139q-79 -165 -205 -264t-306 -142q-14 -3 -42 -7.5
t-50 -9.5t-39 -14q3 -19 24.5 -46t21.5 -34q0 -11 -26 -30zM1061 -79q39 26 131.5 47.5t146.5 21.5q9 0 22.5 -15.5t28 -42.5t26 -50t24 -51t14.5 -33q-121 -45 -244 -45q-61 0 -125 11zM822 568l48 12l109 -177l-73 -48zM1323 51q3 -15 3 -16q0 -7 -17.5 -14.5t-46 -13
t-54 -9.5t-53.5 -7.5t-32 -4.5l-7 43q21 2 60.5 8.5t72 10t60.5 3.5h14zM866 679l-96 -20l-6 17q10 1 32.5 7t34.5 6q19 0 35 -10zM1061 45h31l10 -83l-41 -12v95zM1950 1535v1v-1zM1950 1535l-1 -5l-2 -2l1 3zM1950 1535l1 1z" />
    <glyph glyph-name="_399" unicode="&#xf1a9;" 
d="M1167 -50q-5 19 -24 5q-30 -22 -87 -39t-131 -17q-129 0 -193 49q-5 4 -13 4q-11 0 -26 -12q-7 -6 -7.5 -16t7.5 -20q34 -32 87.5 -46t102.5 -12.5t99 4.5q41 4 84.5 20.5t65 30t28.5 20.5q12 12 7 29zM1128 65q-19 47 -39 61q-23 15 -76 15q-47 0 -71 -10
q-29 -12 -78 -56q-26 -24 -12 -44q9 -8 17.5 -4.5t31.5 23.5q3 2 10.5 8.5t10.5 8.5t10 7t11.5 7t12.5 5t15 4.5t16.5 2.5t20.5 1q27 0 44.5 -7.5t23 -14.5t13.5 -22q10 -17 12.5 -20t12.5 1q23 12 14 34zM1483 346q0 22 -5 44.5t-16.5 45t-34 36.5t-52.5 14
q-33 0 -97 -41.5t-129 -83.5t-101 -42q-27 -1 -63.5 19t-76 49t-83.5 58t-100 49t-111 19q-115 -1 -197 -78.5t-84 -178.5q-2 -112 74 -164q29 -20 62.5 -28.5t103.5 -8.5q57 0 132 32.5t134 71t120 70.5t93 31q26 -1 65 -31.5t71.5 -67t68 -67.5t55.5 -32q35 -3 58.5 14
t55.5 63q28 41 42.5 101t14.5 106zM1536 506q0 -164 -62 -304.5t-166 -236t-242.5 -149.5t-290.5 -54t-293 57.5t-247.5 157t-170.5 241.5t-64 302q0 89 19.5 172.5t49 145.5t70.5 118.5t78.5 94t78.5 69.5t64.5 46.5t42.5 24.5q14 8 51 26.5t54.5 28.5t48 30t60.5 44
q36 28 58 72.5t30 125.5q129 -155 186 -193q44 -29 130 -68t129 -66q21 -13 39 -25t60.5 -46.5t76 -70.5t75 -95t69 -122t47 -148.5t19.5 -177.5z" />
    <glyph glyph-name="_400" unicode="&#xf1aa;" 
d="M1070 463l-160 -160l-151 -152l-30 -30q-65 -64 -151.5 -87t-171.5 -2q-16 -70 -72 -115t-129 -45q-85 0 -145 60.5t-60 145.5q0 72 44.5 128t113.5 72q-22 86 1 173t88 152l12 12l151 -152l-11 -11q-37 -37 -37 -89t37 -90q37 -37 89 -37t89 37l30 30l151 152l161 160z
M729 1145l12 -12l-152 -152l-12 12q-37 37 -89 37t-89 -37t-37 -89.5t37 -89.5l29 -29l152 -152l160 -160l-151 -152l-161 160l-151 152l-30 30q-68 67 -90 159.5t5 179.5q-70 15 -115 71t-45 129q0 85 60 145.5t145 60.5q76 0 133.5 -49t69.5 -123q84 20 169.5 -3.5
t149.5 -87.5zM1536 78q0 -85 -60 -145.5t-145 -60.5q-74 0 -131 47t-71 118q-86 -28 -179.5 -6t-161.5 90l-11 12l151 152l12 -12q37 -37 89 -37t89 37t37 89t-37 89l-30 30l-152 152l-160 160l152 152l160 -160l152 -152l29 -30q64 -64 87.5 -150.5t2.5 -171.5
q76 -11 126.5 -68.5t50.5 -134.5zM1534 1202q0 -77 -51 -135t-127 -69q26 -85 3 -176.5t-90 -158.5l-12 -12l-151 152l12 12q37 37 37 89t-37 89t-89 37t-89 -37l-30 -30l-152 -152l-160 -160l-152 152l161 160l152 152l29 30q67 67 159 89.5t178 -3.5q11 75 68.5 126
t135.5 51q85 0 145 -60.5t60 -145.5z" />
    <glyph glyph-name="f1ab" unicode="&#xf1ab;" 
d="M654 458q-1 -3 -12.5 0.5t-31.5 11.5l-20 9q-44 20 -87 49q-7 5 -41 31.5t-38 28.5q-67 -103 -134 -181q-81 -95 -105 -110q-4 -2 -19.5 -4t-18.5 0q6 4 82 92q21 24 85.5 115t78.5 118q17 30 51 98.5t36 77.5q-8 1 -110 -33q-8 -2 -27.5 -7.5t-34.5 -9.5t-17 -5
q-2 -2 -2 -10.5t-1 -9.5q-5 -10 -31 -15q-23 -7 -47 0q-18 4 -28 21q-4 6 -5 23q6 2 24.5 5t29.5 6q58 16 105 32q100 35 102 35q10 2 43 19.5t44 21.5q9 3 21.5 8t14.5 5.5t6 -0.5q2 -12 -1 -33q0 -2 -12.5 -27t-26.5 -53.5t-17 -33.5q-25 -50 -77 -131l64 -28
q12 -6 74.5 -32t67.5 -28q4 -1 10.5 -25.5t4.5 -30.5zM449 944q3 -15 -4 -28q-12 -23 -50 -38q-30 -12 -60 -12q-26 3 -49 26q-14 15 -18 41l1 3q3 -3 19.5 -5t26.5 0t58 16q36 12 55 14q17 0 21 -17zM1147 815l63 -227l-139 42zM39 15l694 232v1032l-694 -233v-1031z
M1280 332l102 -31l-181 657l-100 31l-216 -536l102 -31l45 110l211 -65zM777 1294l573 -184v380zM1088 -29l158 -13l-54 -160l-40 66q-130 -83 -276 -108q-58 -12 -91 -12h-84q-79 0 -199.5 39t-183.5 85q-8 7 -8 16q0 8 5 13.5t13 5.5q4 0 18 -7.5t30.5 -16.5t20.5 -11
q73 -37 159.5 -61.5t157.5 -24.5q95 0 167 14.5t157 50.5q15 7 30.5 15.5t34 19t28.5 16.5zM1536 1050v-1079l-774 246q-14 -6 -375 -127.5t-368 -121.5q-13 0 -18 13q0 1 -1 3v1078q3 9 4 10q5 6 20 11q107 36 149 50v384l558 -198q2 0 160.5 55t316 108.5t161.5 53.5
q20 0 20 -21v-418z" />
    <glyph glyph-name="_402" unicode="&#xf1ac;" horiz-adv-x="1792" 
d="M288 1152q66 0 113 -47t47 -113v-1088q0 -66 -47 -113t-113 -47h-128q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h128zM1664 989q58 -34 93 -93t35 -128v-768q0 -106 -75 -181t-181 -75h-864q-66 0 -113 47t-47 113v1536q0 40 28 68t68 28h672q40 0 88 -20t76 -48
l152 -152q28 -28 48 -76t20 -88v-163zM928 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM928 256v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM928 512v128q0 14 -9 23
t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1184 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1184 256v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128
q14 0 23 9t9 23zM1184 512v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 256v128q0 14 -9 23t-23 9h-128
q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 512v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1536 896v256h-160q-40 0 -68 28t-28 68v160h-640v-512h896z" />
    <glyph glyph-name="_403" unicode="&#xf1ad;" 
d="M1344 1536q26 0 45 -19t19 -45v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280zM512 1248v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 992v-64q0 -14 9 -23t23 -9h64q14 0 23 9
t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 736v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 480v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM384 160v64
q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64
q14 0 23 9t9 23zM384 928v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 -96v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9
t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM896 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 928v64
q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 160v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64
q14 0 23 9t9 23zM1152 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 928v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9
t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23z" />
    <glyph glyph-name="_404" unicode="&#xf1ae;" horiz-adv-x="1280" 
d="M1188 988l-292 -292v-824q0 -46 -33 -79t-79 -33t-79 33t-33 79v384h-64v-384q0 -46 -33 -79t-79 -33t-79 33t-33 79v824l-292 292q-28 28 -28 68t28 68q29 28 68.5 28t67.5 -28l228 -228h368l228 228q28 28 68 28t68 -28q28 -29 28 -68.5t-28 -67.5zM864 1152
q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
    <glyph glyph-name="uniF1B1" unicode="&#xf1b0;" horiz-adv-x="1664" 
d="M780 1064q0 -60 -19 -113.5t-63 -92.5t-105 -39q-76 0 -138 57.5t-92 135.5t-30 151q0 60 19 113.5t63 92.5t105 39q77 0 138.5 -57.5t91.5 -135t30 -151.5zM438 581q0 -80 -42 -139t-119 -59q-76 0 -141.5 55.5t-100.5 133.5t-35 152q0 80 42 139.5t119 59.5
q76 0 141.5 -55.5t100.5 -134t35 -152.5zM832 608q118 0 255 -97.5t229 -237t92 -254.5q0 -46 -17 -76.5t-48.5 -45t-64.5 -20t-76 -5.5q-68 0 -187.5 45t-182.5 45q-66 0 -192.5 -44.5t-200.5 -44.5q-183 0 -183 146q0 86 56 191.5t139.5 192.5t187.5 146t193 59zM1071 819
q-61 0 -105 39t-63 92.5t-19 113.5q0 74 30 151.5t91.5 135t138.5 57.5q61 0 105 -39t63 -92.5t19 -113.5q0 -73 -30 -151t-92 -135.5t-138 -57.5zM1503 923q77 0 119 -59.5t42 -139.5q0 -74 -35 -152t-100.5 -133.5t-141.5 -55.5q-77 0 -119 59t-42 139q0 74 35 152.5
t100.5 134t141.5 55.5z" />
    <glyph glyph-name="_406" unicode="&#xf1b1;" horiz-adv-x="768" 
d="M704 1008q0 -145 -57 -243.5t-152 -135.5l45 -821q2 -26 -16 -45t-44 -19h-192q-26 0 -44 19t-16 45l45 821q-95 37 -152 135.5t-57 243.5q0 128 42.5 249.5t117.5 200t160 78.5t160 -78.5t117.5 -200t42.5 -249.5z" />
    <glyph glyph-name="_407" unicode="&#xf1b2;" horiz-adv-x="1792" 
d="M896 -93l640 349v636l-640 -233v-752zM832 772l698 254l-698 254l-698 -254zM1664 1024v-768q0 -35 -18 -65t-49 -47l-704 -384q-28 -16 -61 -16t-61 16l-704 384q-31 17 -49 47t-18 65v768q0 40 23 73t61 47l704 256q22 8 44 8t44 -8l704 -256q38 -14 61 -47t23 -73z
" />
    <glyph glyph-name="_408" unicode="&#xf1b3;" horiz-adv-x="2304" 
d="M640 -96l384 192v314l-384 -164v-342zM576 358l404 173l-404 173l-404 -173zM1664 -96l384 192v314l-384 -164v-342zM1600 358l404 173l-404 173l-404 -173zM1152 651l384 165v266l-384 -164v-267zM1088 1030l441 189l-441 189l-441 -189zM2176 512v-416q0 -36 -19 -67
t-52 -47l-448 -224q-25 -14 -57 -14t-57 14l-448 224q-4 2 -7 4q-2 -2 -7 -4l-448 -224q-25 -14 -57 -14t-57 14l-448 224q-33 16 -52 47t-19 67v416q0 38 21.5 70t56.5 48l434 186v400q0 38 21.5 70t56.5 48l448 192q23 10 50 10t50 -10l448 -192q35 -16 56.5 -48t21.5 -70
v-400l434 -186q36 -16 57 -48t21 -70z" />
    <glyph glyph-name="_409" unicode="&#xf1b4;" horiz-adv-x="2048" 
d="M1848 1197h-511v-124h511v124zM1596 771q-90 0 -146 -52.5t-62 -142.5h408q-18 195 -200 195zM1612 186q63 0 122 32t76 87h221q-100 -307 -427 -307q-214 0 -340.5 132t-126.5 347q0 208 130.5 345.5t336.5 137.5q138 0 240.5 -68t153 -179t50.5 -248q0 -17 -2 -47h-658
q0 -111 57.5 -171.5t166.5 -60.5zM277 236h296q205 0 205 167q0 180 -199 180h-302v-347zM277 773h281q78 0 123.5 36.5t45.5 113.5q0 144 -190 144h-260v-294zM0 1282h594q87 0 155 -14t126.5 -47.5t90 -96.5t31.5 -154q0 -181 -172 -263q114 -32 172 -115t58 -204
q0 -75 -24.5 -136.5t-66 -103.5t-98.5 -71t-121 -42t-134 -13h-611v1260z" />
    <glyph glyph-name="_410" unicode="&#xf1b5;" 
d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM499 1041h-371v-787h382q117 0 197 57.5t80 170.5q0 158 -143 200q107 52 107 164q0 57 -19.5 96.5
t-56.5 60.5t-79 29.5t-97 8.5zM477 723h-176v184h163q119 0 119 -90q0 -94 -106 -94zM486 388h-185v217h189q124 0 124 -113q0 -104 -128 -104zM1136 356q-68 0 -104 38t-36 107h411q1 10 1 30q0 132 -74.5 220.5t-203.5 88.5q-128 0 -210 -86t-82 -216q0 -135 79 -217
t213 -82q205 0 267 191h-138q-11 -34 -47.5 -54t-75.5 -20zM1126 722q113 0 124 -122h-254q4 56 39 89t91 33zM964 988h319v-77h-319v77z" />
    <glyph glyph-name="_411" unicode="&#xf1b6;" horiz-adv-x="1792" 
d="M1582 954q0 -101 -71.5 -172.5t-172.5 -71.5t-172.5 71.5t-71.5 172.5t71.5 172.5t172.5 71.5t172.5 -71.5t71.5 -172.5zM812 212q0 104 -73 177t-177 73q-27 0 -54 -6l104 -42q77 -31 109.5 -106.5t1.5 -151.5q-31 -77 -107 -109t-152 -1q-21 8 -62 24.5t-61 24.5
q32 -60 91 -96.5t130 -36.5q104 0 177 73t73 177zM1642 953q0 126 -89.5 215.5t-215.5 89.5q-127 0 -216.5 -89.5t-89.5 -215.5q0 -127 89.5 -216t216.5 -89q126 0 215.5 89t89.5 216zM1792 953q0 -189 -133.5 -322t-321.5 -133l-437 -319q-12 -129 -109 -218t-229 -89
q-121 0 -214 76t-118 192l-230 92v429l389 -157q79 48 173 48q13 0 35 -2l284 407q2 187 135.5 319t320.5 132q188 0 321.5 -133.5t133.5 -321.5z" />
    <glyph glyph-name="_412" unicode="&#xf1b7;" 
d="M1242 889q0 80 -57 136.5t-137 56.5t-136.5 -57t-56.5 -136q0 -80 56.5 -136.5t136.5 -56.5t137 56.5t57 136.5zM632 301q0 -83 -58 -140.5t-140 -57.5q-56 0 -103 29t-72 77q52 -20 98 -40q60 -24 120 1.5t85 86.5q24 60 -1.5 120t-86.5 84l-82 33q22 5 42 5
q82 0 140 -57.5t58 -140.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v153l172 -69q20 -92 93.5 -152t168.5 -60q104 0 181 70t87 173l345 252q150 0 255.5 105.5t105.5 254.5q0 150 -105.5 255.5t-255.5 105.5
q-148 0 -253 -104.5t-107 -252.5l-225 -322q-9 1 -28 1q-75 0 -137 -37l-297 119v468q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5zM1289 887q0 -100 -71 -170.5t-171 -70.5t-170.5 70.5t-70.5 170.5t70.5 171t170.5 71q101 0 171.5 -70.5t70.5 -171.5z
" />
    <glyph glyph-name="_413" unicode="&#xf1b8;" horiz-adv-x="1792" 
d="M836 367l-15 -368l-2 -22l-420 29q-36 3 -67 31.5t-47 65.5q-11 27 -14.5 55t4 65t12 55t21.5 64t19 53q78 -12 509 -28zM449 953l180 -379l-147 92q-63 -72 -111.5 -144.5t-72.5 -125t-39.5 -94.5t-18.5 -63l-4 -21l-190 357q-17 26 -18 56t6 47l8 18q35 63 114 188
l-140 86zM1680 436l-188 -359q-12 -29 -36.5 -46.5t-43.5 -20.5l-18 -4q-71 -7 -219 -12l8 -164l-230 367l211 362l7 -173q170 -16 283 -5t170 33zM895 1360q-47 -63 -265 -435l-317 187l-19 12l225 356q20 31 60 45t80 10q24 -2 48.5 -12t42 -21t41.5 -33t36 -34.5
t36 -39.5t32 -35zM1550 1053l212 -363q18 -37 12.5 -76t-27.5 -74q-13 -20 -33 -37t-38 -28t-48.5 -22t-47 -16t-51.5 -14t-46 -12q-34 72 -265 436l313 195zM1407 1279l142 83l-220 -373l-419 20l151 86q-34 89 -75 166t-75.5 123.5t-64.5 80t-47 46.5l-17 13l405 -1
q31 3 58 -10.5t39 -28.5l11 -15q39 -61 112 -190z" />
    <glyph glyph-name="_414" unicode="&#xf1b9;" horiz-adv-x="2048" 
d="M480 448q0 66 -47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47t113 47t47 113zM516 768h1016l-89 357q-2 8 -14 17.5t-21 9.5h-768q-9 0 -21 -9.5t-14 -17.5zM1888 448q0 66 -47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47t113 47t47 113zM2048 544v-384
q0 -14 -9 -23t-23 -9h-96v-128q0 -80 -56 -136t-136 -56t-136 56t-56 136v128h-1024v-128q0 -80 -56 -136t-136 -56t-136 56t-56 136v128h-96q-14 0 -23 9t-9 23v384q0 93 65.5 158.5t158.5 65.5h28l105 419q23 94 104 157.5t179 63.5h768q98 0 179 -63.5t104 -157.5
l105 -419h28q93 0 158.5 -65.5t65.5 -158.5z" />
    <glyph glyph-name="_415" unicode="&#xf1ba;" horiz-adv-x="2048" 
d="M1824 640q93 0 158.5 -65.5t65.5 -158.5v-384q0 -14 -9 -23t-23 -9h-96v-64q0 -80 -56 -136t-136 -56t-136 56t-56 136v64h-1024v-64q0 -80 -56 -136t-136 -56t-136 56t-56 136v64h-96q-14 0 -23 9t-9 23v384q0 93 65.5 158.5t158.5 65.5h28l105 419q23 94 104 157.5
t179 63.5h128v224q0 14 9 23t23 9h448q14 0 23 -9t9 -23v-224h128q98 0 179 -63.5t104 -157.5l105 -419h28zM320 160q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47zM516 640h1016l-89 357q-2 8 -14 17.5t-21 9.5h-768q-9 0 -21 -9.5t-14 -17.5z
M1728 160q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47z" />
    <glyph glyph-name="_416" unicode="&#xf1bb;" 
d="M1504 64q0 -26 -19 -45t-45 -19h-462q1 -17 6 -87.5t5 -108.5q0 -25 -18 -42.5t-43 -17.5h-320q-25 0 -43 17.5t-18 42.5q0 38 5 108.5t6 87.5h-462q-26 0 -45 19t-19 45t19 45l402 403h-229q-26 0 -45 19t-19 45t19 45l402 403h-197q-26 0 -45 19t-19 45t19 45l384 384
q19 19 45 19t45 -19l384 -384q19 -19 19 -45t-19 -45t-45 -19h-197l402 -403q19 -19 19 -45t-19 -45t-45 -19h-229l402 -403q19 -19 19 -45z" />
    <glyph glyph-name="_417" unicode="&#xf1bc;" 
d="M1127 326q0 32 -30 51q-193 115 -447 115q-133 0 -287 -34q-42 -9 -42 -52q0 -20 13.5 -34.5t35.5 -14.5q5 0 37 8q132 27 243 27q226 0 397 -103q19 -11 33 -11q19 0 33 13.5t14 34.5zM1223 541q0 40 -35 61q-237 141 -548 141q-153 0 -303 -42q-48 -13 -48 -64
q0 -25 17.5 -42.5t42.5 -17.5q7 0 37 8q122 33 251 33q279 0 488 -124q24 -13 38 -13q25 0 42.5 17.5t17.5 42.5zM1331 789q0 47 -40 70q-126 73 -293 110.5t-343 37.5q-204 0 -364 -47q-23 -7 -38.5 -25.5t-15.5 -48.5q0 -31 20.5 -52t51.5 -21q11 0 40 8q133 37 307 37
q159 0 309.5 -34t253.5 -95q21 -12 40 -12q29 0 50.5 20.5t21.5 51.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="_418" unicode="&#xf1bd;" horiz-adv-x="1024" 
d="M1024 1233l-303 -582l24 -31h279v-415h-507l-44 -30l-142 -273l-30 -30h-301v303l303 583l-24 30h-279v415h507l44 30l142 273l30 30h301v-303z" />
    <glyph glyph-name="_419" unicode="&#xf1be;" horiz-adv-x="2304" 
d="M784 164l16 241l-16 523q-1 10 -7.5 17t-16.5 7q-9 0 -16 -7t-7 -17l-14 -523l14 -241q1 -10 7.5 -16.5t15.5 -6.5q22 0 24 23zM1080 193l11 211l-12 586q0 16 -13 24q-8 5 -16 5t-16 -5q-13 -8 -13 -24l-1 -6l-10 -579q0 -1 11 -236v-1q0 -10 6 -17q9 -11 23 -11
q11 0 20 9q9 7 9 20zM35 533l20 -128l-20 -126q-2 -9 -9 -9t-9 9l-17 126l17 128q2 9 9 9t9 -9zM121 612l26 -207l-26 -203q-2 -9 -10 -9q-9 0 -9 10l-23 202l23 207q0 9 9 9q8 0 10 -9zM401 159zM213 650l25 -245l-25 -237q0 -11 -11 -11q-10 0 -12 11l-21 237l21 245
q2 12 12 12q11 0 11 -12zM307 657l23 -252l-23 -244q-2 -13 -14 -13q-13 0 -13 13l-21 244l21 252q0 13 13 13q12 0 14 -13zM401 639l21 -234l-21 -246q-2 -16 -16 -16q-6 0 -10.5 4.5t-4.5 11.5l-20 246l20 234q0 6 4.5 10.5t10.5 4.5q14 0 16 -15zM784 164zM495 785
l21 -380l-21 -246q0 -7 -5 -12.5t-12 -5.5q-16 0 -18 18l-18 246l18 380q2 18 18 18q7 0 12 -5.5t5 -12.5zM589 871l19 -468l-19 -244q0 -8 -5.5 -13.5t-13.5 -5.5q-18 0 -20 19l-16 244l16 468q2 19 20 19q8 0 13.5 -5.5t5.5 -13.5zM687 911l18 -506l-18 -242
q-2 -21 -22 -21q-19 0 -21 21l-16 242l16 506q0 9 6.5 15.5t14.5 6.5q9 0 15 -6.5t7 -15.5zM1079 169v0v0v0zM881 915l15 -510l-15 -239q0 -10 -7.5 -17.5t-17.5 -7.5t-17 7t-8 18l-14 239l14 510q0 11 7.5 18t17.5 7t17.5 -7t7.5 -18zM980 896l14 -492l-14 -236
q0 -11 -8 -19t-19 -8t-19 8t-9 19l-12 236l12 492q1 12 9 20t19 8t18.5 -8t8.5 -20zM1192 404l-14 -231v0q0 -13 -9 -22t-22 -9t-22 9t-10 22l-6 114l-6 117l12 636v3q2 15 12 24q9 7 20 7q8 0 15 -5q14 -8 16 -26zM2304 423q0 -117 -83 -199.5t-200 -82.5h-786
q-13 2 -22 11t-9 22v899q0 23 28 33q85 34 181 34q195 0 338 -131.5t160 -323.5q53 22 110 22q117 0 200 -83t83 -201z" />
    <glyph glyph-name="uniF1C0" unicode="&#xf1c0;" 
d="M768 768q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127t443 -43zM768 0q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127
t443 -43zM768 384q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127t443 -43zM768 1536q208 0 385 -34.5t280 -93.5t103 -128v-128q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5
t-103 128v128q0 69 103 128t280 93.5t385 34.5z" />
    <glyph glyph-name="uniF1C1" unicode="&#xf1c1;" 
d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
M894 465q33 -26 84 -56q59 7 117 7q147 0 177 -49q16 -22 2 -52q0 -1 -1 -2l-2 -2v-1q-6 -38 -71 -38q-48 0 -115 20t-130 53q-221 -24 -392 -83q-153 -262 -242 -262q-15 0 -28 7l-24 12q-1 1 -6 5q-10 10 -6 36q9 40 56 91.5t132 96.5q14 9 23 -6q2 -2 2 -4q52 85 107 197
q68 136 104 262q-24 82 -30.5 159.5t6.5 127.5q11 40 42 40h21h1q23 0 35 -15q18 -21 9 -68q-2 -6 -4 -8q1 -3 1 -8v-30q-2 -123 -14 -192q55 -164 146 -238zM318 54q52 24 137 158q-51 -40 -87.5 -84t-49.5 -74zM716 974q-15 -42 -2 -132q1 7 7 44q0 3 7 43q1 4 4 8
q-1 1 -1 2q-1 2 -1 3q-1 22 -13 36q0 -1 -1 -2v-2zM592 313q135 54 284 81q-2 1 -13 9.5t-16 13.5q-76 67 -127 176q-27 -86 -83 -197q-30 -56 -45 -83zM1238 329q-24 24 -140 24q76 -28 124 -28q14 0 18 1q0 1 -2 3z" />
    <glyph glyph-name="_422" unicode="&#xf1c2;" 
d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
M233 768v-107h70l164 -661h159l128 485q7 20 10 46q2 16 2 24h4l3 -24q1 -3 3.5 -20t5.5 -26l128 -485h159l164 661h70v107h-300v-107h90l-99 -438q-5 -20 -7 -46l-2 -21h-4q0 3 -0.5 6.5t-1.5 8t-1 6.5q-1 5 -4 21t-5 25l-144 545h-114l-144 -545q-2 -9 -4.5 -24.5
t-3.5 -21.5l-4 -21h-4l-2 21q-2 26 -7 46l-99 438h90v107h-300z" />
    <glyph glyph-name="_423" unicode="&#xf1c3;" 
d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
M429 106v-106h281v106h-75l103 161q5 7 10 16.5t7.5 13.5t3.5 4h2q1 -4 5 -10q2 -4 4.5 -7.5t6 -8t6.5 -8.5l107 -161h-76v-106h291v106h-68l-192 273l195 282h67v107h-279v-107h74l-103 -159q-4 -7 -10 -16.5t-9 -13.5l-2 -3h-2q-1 4 -5 10q-6 11 -17 23l-106 159h76v107
h-290v-107h68l189 -272l-194 -283h-68z" />
    <glyph glyph-name="_424" unicode="&#xf1c4;" 
d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
M416 106v-106h327v106h-93v167h137q76 0 118 15q67 23 106.5 87t39.5 146q0 81 -37 141t-100 87q-48 19 -130 19h-368v-107h92v-555h-92zM769 386h-119v268h120q52 0 83 -18q56 -33 56 -115q0 -89 -62 -120q-31 -15 -78 -15z" />
    <glyph glyph-name="_425" unicode="&#xf1c5;" 
d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
M1280 320v-320h-1024v192l192 192l128 -128l384 384zM448 512q-80 0 -136 56t-56 136t56 136t136 56t136 -56t56 -136t-56 -136t-136 -56z" />
    <glyph glyph-name="_426" unicode="&#xf1c6;" 
d="M640 1152v128h-128v-128h128zM768 1024v128h-128v-128h128zM640 896v128h-128v-128h128zM768 768v128h-128v-128h128zM1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400
v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-128v-128h-128v128h-512v-1536h1280zM781 593l107 -349q8 -27 8 -52q0 -83 -72.5 -137.5t-183.5 -54.5t-183.5 54.5t-72.5 137.5q0 25 8 52q21 63 120 396v128h128v-128h79
q22 0 39 -13t23 -34zM640 128q53 0 90.5 19t37.5 45t-37.5 45t-90.5 19t-90.5 -19t-37.5 -45t37.5 -45t90.5 -19z" />
    <glyph glyph-name="_427" unicode="&#xf1c7;" 
d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
M620 686q20 -8 20 -30v-544q0 -22 -20 -30q-8 -2 -12 -2q-12 0 -23 9l-166 167h-131q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h131l166 167q16 15 35 7zM1037 -3q31 0 50 24q129 159 129 363t-129 363q-16 21 -43 24t-47 -14q-21 -17 -23.5 -43.5t14.5 -47.5
q100 -123 100 -282t-100 -282q-17 -21 -14.5 -47.5t23.5 -42.5q18 -15 40 -15zM826 145q27 0 47 20q87 93 87 219t-87 219q-18 19 -45 20t-46 -17t-20 -44.5t18 -46.5q52 -57 52 -131t-52 -131q-19 -20 -18 -46.5t20 -44.5q20 -17 44 -17z" />
    <glyph glyph-name="_428" unicode="&#xf1c8;" 
d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
M768 768q52 0 90 -38t38 -90v-384q0 -52 -38 -90t-90 -38h-384q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h384zM1260 766q20 -8 20 -30v-576q0 -22 -20 -30q-8 -2 -12 -2q-14 0 -23 9l-265 266v90l265 266q9 9 23 9q4 0 12 -2z" />
    <glyph glyph-name="_429" unicode="&#xf1c9;" 
d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
M480 768q8 11 21 12.5t24 -6.5l51 -38q11 -8 12.5 -21t-6.5 -24l-182 -243l182 -243q8 -11 6.5 -24t-12.5 -21l-51 -38q-11 -8 -24 -6.5t-21 12.5l-226 301q-14 19 0 38zM1282 467q14 -19 0 -38l-226 -301q-8 -11 -21 -12.5t-24 6.5l-51 38q-11 8 -12.5 21t6.5 24l182 243
l-182 243q-8 11 -6.5 24t12.5 21l51 38q11 8 24 6.5t21 -12.5zM662 6q-13 2 -20.5 13t-5.5 24l138 831q2 13 13 20.5t24 5.5l63 -10q13 -2 20.5 -13t5.5 -24l-138 -831q-2 -13 -13 -20.5t-24 -5.5z" />
    <glyph glyph-name="_430" unicode="&#xf1ca;" 
d="M1497 709v-198q-101 -23 -198 -23q-65 -136 -165.5 -271t-181.5 -215.5t-128 -106.5q-80 -45 -162 3q-28 17 -60.5 43.5t-85 83.5t-102.5 128.5t-107.5 184t-105.5 244t-91.5 314.5t-70.5 390h283q26 -218 70 -398.5t104.5 -317t121.5 -235.5t140 -195q169 169 287 406
q-142 72 -223 220t-81 333q0 192 104 314.5t284 122.5q178 0 273 -105.5t95 -297.5q0 -159 -58 -286q-7 -1 -19.5 -3t-46 -2t-63 6t-62 25.5t-50.5 51.5q31 103 31 184q0 87 -29 132t-79 45q-53 0 -85 -49.5t-32 -140.5q0 -186 105 -293.5t267 -107.5q62 0 121 14z" />
    <glyph glyph-name="_431" unicode="&#xf1cb;" horiz-adv-x="1792" 
d="M216 367l603 -402v359l-334 223zM154 511l193 129l-193 129v-258zM973 -35l603 402l-269 180l-334 -223v-359zM896 458l272 182l-272 182l-272 -182zM485 733l334 223v359l-603 -402zM1445 640l193 -129v258zM1307 733l269 180l-603 402v-359zM1792 913v-546
q0 -41 -34 -64l-819 -546q-21 -13 -43 -13t-43 13l-819 546q-34 23 -34 64v546q0 41 34 64l819 546q21 13 43 13t43 -13l819 -546q34 -23 34 -64z" />
    <glyph glyph-name="_432" unicode="&#xf1cc;" horiz-adv-x="2048" 
d="M1800 764q111 -46 179.5 -145.5t68.5 -221.5q0 -164 -118 -280.5t-285 -116.5q-4 0 -11.5 0.5t-10.5 0.5h-1209h-1h-2h-5q-170 10 -288 125.5t-118 280.5q0 110 55 203t147 147q-12 39 -12 82q0 115 82 196t199 81q95 0 172 -58q75 154 222.5 248t326.5 94
q166 0 306 -80.5t221.5 -218.5t81.5 -301q0 -6 -0.5 -18t-0.5 -18zM468 498q0 -122 84 -193t208 -71q137 0 240 99q-16 20 -47.5 56.5t-43.5 50.5q-67 -65 -144 -65q-55 0 -93.5 33.5t-38.5 87.5q0 53 38.5 87t91.5 34q44 0 84.5 -21t73 -55t65 -75t69 -82t77 -75t97 -55
t121.5 -21q121 0 204.5 71.5t83.5 190.5q0 121 -84 192t-207 71q-143 0 -241 -97l93 -108q66 64 142 64q52 0 92 -33t40 -84q0 -57 -37 -91.5t-94 -34.5q-43 0 -82.5 21t-72 55t-65.5 75t-69.5 82t-77.5 75t-96.5 55t-118.5 21q-122 0 -207 -70.5t-85 -189.5z" />
    <glyph glyph-name="_433" unicode="&#xf1cd;" horiz-adv-x="1792" 
d="M896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM896 1408q-190 0 -361 -90l194 -194q82 28 167 28t167 -28l194 194q-171 90 -361 90zM218 279l194 194
q-28 82 -28 167t28 167l-194 194q-90 -171 -90 -361t90 -361zM896 -128q190 0 361 90l-194 194q-82 -28 -167 -28t-167 28l-194 -194q171 -90 361 -90zM896 256q159 0 271.5 112.5t112.5 271.5t-112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5
t271.5 -112.5zM1380 473l194 -194q90 171 90 361t-90 361l-194 -194q28 -82 28 -167t-28 -167z" />
    <glyph glyph-name="_434" unicode="&#xf1ce;" horiz-adv-x="1792" 
d="M1760 640q0 -176 -68.5 -336t-184 -275.5t-275.5 -184t-336 -68.5t-336 68.5t-275.5 184t-184 275.5t-68.5 336q0 213 97 398.5t265 305.5t374 151v-228q-221 -45 -366.5 -221t-145.5 -406q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5
t136.5 204t51 248.5q0 230 -145.5 406t-366.5 221v228q206 -31 374 -151t265 -305.5t97 -398.5z" />
    <glyph glyph-name="uniF1D0" unicode="&#xf1d0;" horiz-adv-x="1792" 
d="M19 662q8 217 116 406t305 318h5q0 -1 -1 -3q-8 -8 -28 -33.5t-52 -76.5t-60 -110.5t-44.5 -135.5t-14 -150.5t39 -157.5t108.5 -154q50 -50 102 -69.5t90.5 -11.5t69.5 23.5t47 32.5l16 16q39 51 53 116.5t6.5 122.5t-21 107t-26.5 80l-14 29q-10 25 -30.5 49.5t-43 41
t-43.5 29.5t-35 19l-13 6l104 115q39 -17 78 -52t59 -61l19 -27q1 48 -18.5 103.5t-40.5 87.5l-20 31l161 183l160 -181q-33 -46 -52.5 -102.5t-22.5 -90.5l-4 -33q22 37 61.5 72.5t67.5 52.5l28 17l103 -115q-44 -14 -85 -50t-60 -65l-19 -29q-31 -56 -48 -133.5t-7 -170
t57 -156.5q33 -45 77.5 -60.5t85 -5.5t76 26.5t57.5 33.5l21 16q60 53 96.5 115t48.5 121.5t10 121.5t-18 118t-37 107.5t-45.5 93t-45 72t-34.5 47.5l-13 17q-14 13 -7 13l10 -3q40 -29 62.5 -46t62 -50t64 -58t58.5 -65t55.5 -77t45.5 -88t38 -103t23.5 -117t10.5 -136
q3 -259 -108 -465t-312 -321t-456 -115q-185 0 -351 74t-283.5 198t-184 293t-60.5 353z" />
    <glyph glyph-name="uniF1D1" unicode="&#xf1d1;" horiz-adv-x="1792" 
d="M874 -102v-66q-208 6 -385 109.5t-283 275.5l58 34q29 -49 73 -99l65 57q148 -168 368 -212l-17 -86q65 -12 121 -13zM276 428l-83 -28q22 -60 49 -112l-57 -33q-98 180 -98 385t98 385l57 -33q-30 -56 -49 -112l82 -28q-35 -100 -35 -212q0 -109 36 -212zM1528 251
l58 -34q-106 -172 -283 -275.5t-385 -109.5v66q56 1 121 13l-17 86q220 44 368 212l65 -57q44 50 73 99zM1377 805l-233 -80q14 -42 14 -85t-14 -85l232 -80q-31 -92 -98 -169l-185 162q-57 -67 -147 -85l48 -241q-52 -10 -98 -10t-98 10l48 241q-90 18 -147 85l-185 -162
q-67 77 -98 169l232 80q-14 42 -14 85t14 85l-233 80q33 93 99 169l185 -162q59 68 147 86l-48 240q44 10 98 10t98 -10l-48 -240q88 -18 147 -86l185 162q66 -76 99 -169zM874 1448v-66q-65 -2 -121 -13l17 -86q-220 -42 -368 -211l-65 56q-38 -42 -73 -98l-57 33
q106 172 282 275.5t385 109.5zM1705 640q0 -205 -98 -385l-57 33q27 52 49 112l-83 28q36 103 36 212q0 112 -35 212l82 28q-19 56 -49 112l57 33q98 -180 98 -385zM1585 1063l-57 -33q-35 56 -73 98l-65 -56q-148 169 -368 211l17 86q-56 11 -121 13v66q209 -6 385 -109.5
t282 -275.5zM1748 640q0 173 -67.5 331t-181.5 272t-272 181.5t-331 67.5t-331 -67.5t-272 -181.5t-181.5 -272t-67.5 -331t67.5 -331t181.5 -272t272 -181.5t331 -67.5t331 67.5t272 181.5t181.5 272t67.5 331zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71
t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
    <glyph glyph-name="uniF1D2" unicode="&#xf1d2;" 
d="M582 228q0 -66 -93 -66q-107 0 -107 63q0 64 98 64q102 0 102 -61zM546 694q0 -85 -74 -85q-77 0 -77 84q0 90 77 90q36 0 55 -25.5t19 -63.5zM712 769v125q-78 -29 -135 -29q-50 29 -110 29q-86 0 -145 -57t-59 -143q0 -50 29.5 -102t73.5 -67v-3q-38 -17 -38 -85
q0 -53 41 -77v-3q-113 -37 -113 -139q0 -45 20 -78.5t54 -51t72 -25.5t81 -8q224 0 224 188q0 67 -48 99t-126 46q-27 5 -51.5 20.5t-24.5 39.5q0 44 49 52q77 15 122 70t45 134q0 24 -10 52q37 9 49 13zM771 350h137q-2 27 -2 82v387q0 46 2 69h-137q3 -23 3 -71v-392
q0 -50 -3 -75zM1280 366v121q-30 -21 -68 -21q-53 0 -53 82v225h52q9 0 26.5 -1t26.5 -1v117h-105q0 82 3 102h-140q4 -24 4 -55v-47h-60v-117q36 3 37 3q3 0 11 -0.5t12 -0.5v-2h-2v-217q0 -37 2.5 -64t11.5 -56.5t24.5 -48.5t43.5 -31t66 -12q64 0 108 24zM924 1072
q0 36 -24 63.5t-60 27.5t-60.5 -27t-24.5 -64q0 -36 25 -62.5t60 -26.5t59.5 27t24.5 62zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="_438" unicode="&#xf1d3;" horiz-adv-x="1792" 
d="M595 22q0 100 -165 100q-158 0 -158 -104q0 -101 172 -101q151 0 151 105zM536 777q0 61 -30 102t-89 41q-124 0 -124 -145q0 -135 124 -135q119 0 119 137zM805 1101v-202q-36 -12 -79 -22q16 -43 16 -84q0 -127 -73 -216.5t-197 -112.5q-40 -8 -59.5 -27t-19.5 -58
q0 -31 22.5 -51.5t58 -32t78.5 -22t86 -25.5t78.5 -37.5t58 -64t22.5 -98.5q0 -304 -363 -304q-69 0 -130 12.5t-116 41t-87.5 82t-32.5 127.5q0 165 182 225v4q-67 41 -67 126q0 109 63 137v4q-72 24 -119.5 108.5t-47.5 165.5q0 139 95 231.5t235 92.5q96 0 178 -47
q98 0 218 47zM1123 220h-222q4 45 4 134v609q0 94 -4 128h222q-4 -33 -4 -124v-613q0 -89 4 -134zM1724 442v-196q-71 -39 -174 -39q-62 0 -107 20t-70 50t-39.5 78t-18.5 92t-4 103v351h2v4q-7 0 -19 1t-18 1q-21 0 -59 -6v190h96v76q0 54 -6 89h227q-6 -41 -6 -165h171
v-190q-15 0 -43.5 2t-42.5 2h-85v-365q0 -131 87 -131q61 0 109 33zM1148 1389q0 -58 -39 -101.5t-96 -43.5q-58 0 -98 43.5t-40 101.5q0 59 39.5 103t98.5 44q58 0 96.5 -44.5t38.5 -102.5z" />
    <glyph glyph-name="_439" unicode="&#xf1d4;" 
d="M809 532l266 499h-112l-157 -312q-24 -48 -44 -92l-42 92l-155 312h-120l263 -493v-324h101v318zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="uniF1D5" unicode="&#xf1d5;" horiz-adv-x="1280" 
d="M842 964q0 -80 -57 -136.5t-136 -56.5q-60 0 -111 35q-62 -67 -115 -146q-247 -371 -202 -859q1 -22 -12.5 -38.5t-34.5 -18.5h-5q-20 0 -35 13.5t-17 33.5q-14 126 -3.5 247.5t29.5 217t54 186t69 155.5t74 125q61 90 132 165q-16 35 -16 77q0 80 56.5 136.5t136.5 56.5
t136.5 -56.5t56.5 -136.5zM1223 953q0 -158 -78 -292t-212.5 -212t-292.5 -78q-64 0 -131 14q-21 5 -32.5 23.5t-6.5 39.5q5 20 23 31.5t39 7.5q51 -13 108 -13q97 0 186 38t153 102t102 153t38 186t-38 186t-102 153t-153 102t-186 38t-186 -38t-153 -102t-102 -153
t-38 -186q0 -114 52 -218q10 -20 3.5 -40t-25.5 -30t-39.5 -3t-30.5 26q-64 123 -64 265q0 119 46.5 227t124.5 186t186 124t226 46q158 0 292.5 -78t212.5 -212.5t78 -292.5z" />
    <glyph glyph-name="uniF1D6" unicode="&#xf1d6;" horiz-adv-x="1792" 
d="M270 730q-8 19 -8 52q0 20 11 49t24 45q-1 22 7.5 53t22.5 43q0 139 92.5 288.5t217.5 209.5q139 66 324 66q133 0 266 -55q49 -21 90 -48t71 -56t55 -68t42 -74t32.5 -84.5t25.5 -89.5t22 -98l1 -5q55 -83 55 -150q0 -14 -9 -40t-9 -38q0 -1 1.5 -3.5t3.5 -5t2 -3.5
q77 -114 120.5 -214.5t43.5 -208.5q0 -43 -19.5 -100t-55.5 -57q-9 0 -19.5 7.5t-19 17.5t-19 26t-16 26.5t-13.5 26t-9 17.5q-1 1 -3 1l-5 -4q-59 -154 -132 -223q20 -20 61.5 -38.5t69 -41.5t35.5 -65q-2 -4 -4 -16t-7 -18q-64 -97 -302 -97q-53 0 -110.5 9t-98 20
t-104.5 30q-15 5 -23 7q-14 4 -46 4.5t-40 1.5q-41 -45 -127.5 -65t-168.5 -20q-35 0 -69 1.5t-93 9t-101 20.5t-74.5 40t-32.5 64q0 40 10 59.5t41 48.5q11 2 40.5 13t49.5 12q4 0 14 2q2 2 2 4l-2 3q-48 11 -108 105.5t-73 156.5l-5 3q-4 0 -12 -20q-18 -41 -54.5 -74.5
t-77.5 -37.5h-1q-4 0 -6 4.5t-5 5.5q-23 54 -23 100q0 275 252 466z" />
    <glyph glyph-name="uniF1D7" unicode="&#xf1d7;" horiz-adv-x="2048" 
d="M580 1075q0 41 -25 66t-66 25q-43 0 -76 -25.5t-33 -65.5q0 -39 33 -64.5t76 -25.5q41 0 66 24.5t25 65.5zM1323 568q0 28 -25.5 50t-65.5 22q-27 0 -49.5 -22.5t-22.5 -49.5q0 -28 22.5 -50.5t49.5 -22.5q40 0 65.5 22t25.5 51zM1087 1075q0 41 -24.5 66t-65.5 25
q-43 0 -76 -25.5t-33 -65.5q0 -39 33 -64.5t76 -25.5q41 0 65.5 24.5t24.5 65.5zM1722 568q0 28 -26 50t-65 22q-27 0 -49.5 -22.5t-22.5 -49.5q0 -28 22.5 -50.5t49.5 -22.5q39 0 65 22t26 51zM1456 965q-31 4 -70 4q-169 0 -311 -77t-223.5 -208.5t-81.5 -287.5
q0 -78 23 -152q-35 -3 -68 -3q-26 0 -50 1.5t-55 6.5t-44.5 7t-54.5 10.5t-50 10.5l-253 -127l72 218q-290 203 -290 490q0 169 97.5 311t264 223.5t363.5 81.5q176 0 332.5 -66t262 -182.5t136.5 -260.5zM2048 404q0 -117 -68.5 -223.5t-185.5 -193.5l55 -181l-199 109
q-150 -37 -218 -37q-169 0 -311 70.5t-223.5 191.5t-81.5 264t81.5 264t223.5 191.5t311 70.5q161 0 303 -70.5t227.5 -192t85.5 -263.5z" />
    <glyph glyph-name="_443" unicode="&#xf1d8;" horiz-adv-x="1792" 
d="M1764 1525q33 -24 27 -64l-256 -1536q-5 -29 -32 -45q-14 -8 -31 -8q-11 0 -24 5l-453 185l-242 -295q-18 -23 -49 -23q-13 0 -22 4q-19 7 -30.5 23.5t-11.5 36.5v349l864 1059l-1069 -925l-395 162q-37 14 -40 55q-2 40 32 59l1664 960q15 9 32 9q20 0 36 -11z" />
    <glyph glyph-name="_444" unicode="&#xf1d9;" horiz-adv-x="1792" 
d="M1764 1525q33 -24 27 -64l-256 -1536q-5 -29 -32 -45q-14 -8 -31 -8q-11 0 -24 5l-527 215l-298 -327q-18 -21 -47 -21q-14 0 -23 4q-19 7 -30 23.5t-11 36.5v452l-472 193q-37 14 -40 55q-3 39 32 59l1664 960q35 21 68 -2zM1422 26l221 1323l-1434 -827l336 -137
l863 639l-478 -797z" />
    <glyph glyph-name="_445" unicode="&#xf1da;" 
d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5
t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298zM896 928v-448q0 -14 -9 -23
t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23z" />
    <glyph glyph-name="_446" unicode="&#xf1db;" 
d="M768 1280q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5t-51 248.5t-136.5 204t-204 136.5t-248.5 51zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103
t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="_447" unicode="&#xf1dc;" horiz-adv-x="1792" 
d="M1682 -128q-44 0 -132.5 3.5t-133.5 3.5q-44 0 -132 -3.5t-132 -3.5q-24 0 -37 20.5t-13 45.5q0 31 17 46t39 17t51 7t45 15q33 21 33 140l-1 391q0 21 -1 31q-13 4 -50 4h-675q-38 0 -51 -4q-1 -10 -1 -31l-1 -371q0 -142 37 -164q16 -10 48 -13t57 -3.5t45 -15
t20 -45.5q0 -26 -12.5 -48t-36.5 -22q-47 0 -139.5 3.5t-138.5 3.5q-43 0 -128 -3.5t-127 -3.5q-23 0 -35.5 21t-12.5 45q0 30 15.5 45t36 17.5t47.5 7.5t42 15q33 23 33 143l-1 57v813q0 3 0.5 26t0 36.5t-1.5 38.5t-3.5 42t-6.5 36.5t-11 31.5t-16 18q-15 10 -45 12t-53 2
t-41 14t-18 45q0 26 12 48t36 22q46 0 138.5 -3.5t138.5 -3.5q42 0 126.5 3.5t126.5 3.5q25 0 37.5 -22t12.5 -48q0 -30 -17 -43.5t-38.5 -14.5t-49.5 -4t-43 -13q-35 -21 -35 -160l1 -320q0 -21 1 -32q13 -3 39 -3h699q25 0 38 3q1 11 1 32l1 320q0 139 -35 160
q-18 11 -58.5 12.5t-66 13t-25.5 49.5q0 26 12.5 48t37.5 22q44 0 132 -3.5t132 -3.5q43 0 129 3.5t129 3.5q25 0 37.5 -22t12.5 -48q0 -30 -17.5 -44t-40 -14.5t-51.5 -3t-44 -12.5q-35 -23 -35 -161l1 -943q0 -119 34 -140q16 -10 46 -13.5t53.5 -4.5t41.5 -15.5t18 -44.5
q0 -26 -12 -48t-36 -22z" />
    <glyph glyph-name="_448" unicode="&#xf1dd;" horiz-adv-x="1280" 
d="M1278 1347v-73q0 -29 -18.5 -61t-42.5 -32q-50 0 -54 -1q-26 -6 -32 -31q-3 -11 -3 -64v-1152q0 -25 -18 -43t-43 -18h-108q-25 0 -43 18t-18 43v1218h-143v-1218q0 -25 -17.5 -43t-43.5 -18h-108q-26 0 -43.5 18t-17.5 43v496q-147 12 -245 59q-126 58 -192 179
q-64 117 -64 259q0 166 88 286q88 118 209 159q111 37 417 37h479q25 0 43 -18t18 -43z" />
    <glyph glyph-name="_449" unicode="&#xf1de;" 
d="M352 128v-128h-352v128h352zM704 256q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM864 640v-128h-864v128h864zM224 1152v-128h-224v128h224zM1536 128v-128h-736v128h736zM576 1280q26 0 45 -19t19 -45v-256
q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM1216 768q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM1536 640v-128h-224v128h224zM1536 1152v-128h-864v128h864z" />
    <glyph glyph-name="uniF1E0" unicode="&#xf1e0;" 
d="M1216 512q133 0 226.5 -93.5t93.5 -226.5t-93.5 -226.5t-226.5 -93.5t-226.5 93.5t-93.5 226.5q0 12 2 34l-360 180q-92 -86 -218 -86q-133 0 -226.5 93.5t-93.5 226.5t93.5 226.5t226.5 93.5q126 0 218 -86l360 180q-2 22 -2 34q0 133 93.5 226.5t226.5 93.5
t226.5 -93.5t93.5 -226.5t-93.5 -226.5t-226.5 -93.5q-126 0 -218 86l-360 -180q2 -22 2 -34t-2 -34l360 -180q92 86 218 86z" />
    <glyph glyph-name="_451" unicode="&#xf1e1;" 
d="M1280 341q0 88 -62.5 151t-150.5 63q-84 0 -145 -58l-241 120q2 16 2 23t-2 23l241 120q61 -58 145 -58q88 0 150.5 63t62.5 151t-62.5 150.5t-150.5 62.5t-151 -62.5t-63 -150.5q0 -7 2 -23l-241 -120q-62 57 -145 57q-88 0 -150.5 -62.5t-62.5 -150.5t62.5 -150.5
t150.5 -62.5q83 0 145 57l241 -120q-2 -16 -2 -23q0 -88 63 -150.5t151 -62.5t150.5 62.5t62.5 150.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="_452" unicode="&#xf1e2;" horiz-adv-x="1792" 
d="M571 947q-10 25 -34 35t-49 0q-108 -44 -191 -127t-127 -191q-10 -25 0 -49t35 -34q13 -5 24 -5q42 0 60 40q34 84 98.5 148.5t148.5 98.5q25 11 35 35t0 49zM1513 1303l46 -46l-244 -243l68 -68q19 -19 19 -45.5t-19 -45.5l-64 -64q89 -161 89 -343q0 -143 -55.5 -273.5
t-150 -225t-225 -150t-273.5 -55.5t-273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5q182 0 343 -89l64 64q19 19 45.5 19t45.5 -19l68 -68zM1521 1359q-10 -10 -22 -10q-13 0 -23 10l-91 90q-9 10 -9 23t9 23q10 9 23 9t23 -9l90 -91
q10 -9 10 -22.5t-10 -22.5zM1751 1129q-11 -9 -23 -9t-23 9l-90 91q-10 9 -10 22.5t10 22.5q9 10 22.5 10t22.5 -10l91 -90q9 -10 9 -23t-9 -23zM1792 1312q0 -14 -9 -23t-23 -9h-96q-14 0 -23 9t-9 23t9 23t23 9h96q14 0 23 -9t9 -23zM1600 1504v-96q0 -14 -9 -23t-23 -9
t-23 9t-9 23v96q0 14 9 23t23 9t23 -9t9 -23zM1751 1449l-91 -90q-10 -10 -22 -10q-13 0 -23 10q-10 9 -10 22.5t10 22.5l90 91q10 9 23 9t23 -9q9 -10 9 -23t-9 -23z" />
    <glyph glyph-name="_453" unicode="&#xf1e3;" horiz-adv-x="1792" 
d="M609 720l287 208l287 -208l-109 -336h-355zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM1515 186q149 203 149 454v3l-102 -89l-240 224l63 323
l134 -12q-150 206 -389 282l53 -124l-287 -159l-287 159l53 124q-239 -76 -389 -282l135 12l62 -323l-240 -224l-102 89v-3q0 -251 149 -454l30 132l326 -40l139 -298l-116 -69q117 -39 240 -39t240 39l-116 69l139 298l326 40z" />
    <glyph glyph-name="_454" unicode="&#xf1e4;" horiz-adv-x="1792" 
d="M448 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM256 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM832 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23
v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM66 768q-28 0 -47 19t-19 46v129h514v-129q0 -27 -19 -46t-46 -19h-383zM1216 224v-192q0 -14 -9 -23t-23 -9h-192
q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1600 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23
zM1408 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1016v-13h-514v10q0 104 -382 102q-382 -1 -382 -102v-10h-514v13q0 17 8.5 43t34 64t65.5 75.5t110.5 76t160 67.5t224 47.5t293.5 18.5t293 -18.5t224 -47.5
t160.5 -67.5t110.5 -76t65.5 -75.5t34 -64t8.5 -43zM1792 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 962v-129q0 -27 -19 -46t-46 -19h-384q-27 0 -46 19t-19 46v129h514z" />
    <glyph glyph-name="_455" unicode="&#xf1e5;" horiz-adv-x="1792" 
d="M704 1216v-768q0 -26 -19 -45t-45 -19v-576q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v512l249 873q7 23 31 23h424zM1024 1216v-704h-256v704h256zM1792 320v-512q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v576q-26 0 -45 19t-19 45v768h424q24 0 31 -23z
M736 1504v-224h-352v224q0 14 9 23t23 9h288q14 0 23 -9t9 -23zM1408 1504v-224h-352v224q0 14 9 23t23 9h288q14 0 23 -9t9 -23z" />
    <glyph glyph-name="_456" unicode="&#xf1e6;" horiz-adv-x="1792" 
d="M1755 1083q37 -38 37 -90.5t-37 -90.5l-401 -400l150 -150l-160 -160q-163 -163 -389.5 -186.5t-411.5 100.5l-362 -362h-181v181l362 362q-124 185 -100.5 411.5t186.5 389.5l160 160l150 -150l400 401q38 37 91 37t90 -37t37 -90.5t-37 -90.5l-400 -401l234 -234
l401 400q38 37 91 37t90 -37z" />
    <glyph glyph-name="_457" unicode="&#xf1e7;" horiz-adv-x="1792" 
d="M873 796q0 -83 -63.5 -142.5t-152.5 -59.5t-152.5 59.5t-63.5 142.5q0 84 63.5 143t152.5 59t152.5 -59t63.5 -143zM1375 796q0 -83 -63 -142.5t-153 -59.5q-89 0 -152.5 59.5t-63.5 142.5q0 84 63.5 143t152.5 59q90 0 153 -59t63 -143zM1600 616v667q0 87 -32 123.5
t-111 36.5h-1112q-83 0 -112.5 -34t-29.5 -126v-673q43 -23 88.5 -40t81 -28t81 -18.5t71 -11t70 -4t58.5 -0.5t56.5 2t44.5 2q68 1 95 -27q6 -6 10 -9q26 -25 61 -51q7 91 118 87q5 0 36.5 -1.5t43 -2t45.5 -1t53 1t54.5 4.5t61 8.5t62 13.5t67 19.5t67.5 27t72 34.5z
M1763 621q-121 -149 -372 -252q84 -285 -23 -465q-66 -113 -183 -148q-104 -32 -182 15q-86 51 -82 164l-1 326v1q-8 2 -24.5 6t-23.5 5l-1 -338q4 -114 -83 -164q-79 -47 -183 -15q-117 36 -182 150q-105 180 -22 463q-251 103 -372 252q-25 37 -4 63t60 -1q4 -2 11.5 -7
t10.5 -8v694q0 72 47 123t114 51h1257q67 0 114 -51t47 -123v-694l21 15q39 27 60 1t-4 -63z" />
    <glyph glyph-name="_458" unicode="&#xf1e8;" horiz-adv-x="1792" 
d="M896 1102v-434h-145v434h145zM1294 1102v-434h-145v434h145zM1294 342l253 254v795h-1194v-1049h326v-217l217 217h398zM1692 1536v-1013l-434 -434h-326l-217 -217h-217v217h-398v1158l109 289h1483z" />
    <glyph glyph-name="_459" unicode="&#xf1e9;" 
d="M773 217v-127q-1 -292 -6 -305q-12 -32 -51 -40q-54 -9 -181.5 38t-162.5 89q-13 15 -17 36q-1 12 4 26q4 10 34 47t181 216q1 0 60 70q15 19 39.5 24.5t49.5 -3.5q24 -10 37.5 -29t12.5 -42zM624 468q-3 -55 -52 -70l-120 -39q-275 -88 -292 -88q-35 2 -54 36
q-12 25 -17 75q-8 76 1 166.5t30 124.5t56 32q13 0 202 -77q71 -29 115 -47l84 -34q23 -9 35.5 -30.5t11.5 -48.5zM1450 171q-7 -54 -91.5 -161t-135.5 -127q-37 -14 -63 7q-14 10 -184 287l-47 77q-14 21 -11.5 46t19.5 46q35 43 83 26q1 -1 119 -40q203 -66 242 -79.5
t47 -20.5q28 -22 22 -61zM778 803q5 -102 -54 -122q-58 -17 -114 71l-378 598q-8 35 19 62q41 43 207.5 89.5t224.5 31.5q40 -10 49 -45q3 -18 22 -305.5t24 -379.5zM1440 695q3 -39 -26 -59q-15 -10 -329 -86q-67 -15 -91 -23l1 2q-23 -6 -46 4t-37 32q-30 47 0 87
q1 1 75 102q125 171 150 204t34 39q28 19 65 2q48 -23 123 -133.5t81 -167.5v-3z" />
    <glyph glyph-name="_460" unicode="&#xf1ea;" horiz-adv-x="2048" 
d="M1024 1024h-384v-384h384v384zM1152 384v-128h-640v128h640zM1152 1152v-640h-640v640h640zM1792 384v-128h-512v128h512zM1792 640v-128h-512v128h512zM1792 896v-128h-512v128h512zM1792 1152v-128h-512v128h512zM256 192v960h-128v-960q0 -26 19 -45t45 -19t45 19
t19 45zM1920 192v1088h-1536v-1088q0 -33 -11 -64h1483q26 0 45 19t19 45zM2048 1408v-1216q0 -80 -56 -136t-136 -56h-1664q-80 0 -136 56t-56 136v1088h256v128h1792z" />
    <glyph glyph-name="_461" unicode="&#xf1eb;" horiz-adv-x="2048" 
d="M1024 13q-20 0 -93 73.5t-73 93.5q0 32 62.5 54t103.5 22t103.5 -22t62.5 -54q0 -20 -73 -93.5t-93 -73.5zM1294 284q-2 0 -40 25t-101.5 50t-128.5 25t-128.5 -25t-101 -50t-40.5 -25q-18 0 -93.5 75t-75.5 93q0 13 10 23q78 77 196 121t233 44t233 -44t196 -121
q10 -10 10 -23q0 -18 -75.5 -93t-93.5 -75zM1567 556q-11 0 -23 8q-136 105 -252 154.5t-268 49.5q-85 0 -170.5 -22t-149 -53t-113.5 -62t-79 -53t-31 -22q-17 0 -92 75t-75 93q0 12 10 22q132 132 320 205t380 73t380 -73t320 -205q10 -10 10 -22q0 -18 -75 -93t-92 -75z
M1838 827q-11 0 -22 9q-179 157 -371.5 236.5t-420.5 79.5t-420.5 -79.5t-371.5 -236.5q-11 -9 -22 -9q-17 0 -92.5 75t-75.5 93q0 13 10 23q187 186 445 288t527 102t527 -102t445 -288q10 -10 10 -23q0 -18 -75.5 -93t-92.5 -75z" />
    <glyph glyph-name="_462" unicode="&#xf1ec;" horiz-adv-x="1792" 
d="M384 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5
t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1152 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5
t37.5 90.5zM384 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1152 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 768q0 53 -37.5 90.5t-90.5 37.5
t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1536 0v384q0 52 -38 90t-90 38t-90 -38t-38 -90v-384q0 -52 38 -90t90 -38t90 38t38 90zM1152 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5z
M1536 1088v256q0 26 -19 45t-45 19h-1280q-26 0 -45 -19t-19 -45v-256q0 -26 19 -45t45 -19h1280q26 0 45 19t19 45zM1536 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1408v-1536q0 -52 -38 -90t-90 -38
h-1408q-52 0 -90 38t-38 90v1536q0 52 38 90t90 38h1408q52 0 90 -38t38 -90z" />
    <glyph glyph-name="_463" unicode="&#xf1ed;" 
d="M1519 890q18 -84 -4 -204q-87 -444 -565 -444h-44q-25 0 -44 -16.5t-24 -42.5l-4 -19l-55 -346l-2 -15q-5 -26 -24.5 -42.5t-44.5 -16.5h-251q-21 0 -33 15t-9 36q9 56 26.5 168t26.5 168t27 167.5t27 167.5q5 37 43 37h131q133 -2 236 21q175 39 287 144q102 95 155 246
q24 70 35 133q1 6 2.5 7.5t3.5 1t6 -3.5q79 -59 98 -162zM1347 1172q0 -107 -46 -236q-80 -233 -302 -315q-113 -40 -252 -42q0 -1 -90 -1l-90 1q-100 0 -118 -96q-2 -8 -85 -530q-1 -10 -12 -10h-295q-22 0 -36.5 16.5t-11.5 38.5l232 1471q5 29 27.5 48t51.5 19h598
q34 0 97.5 -13t111.5 -32q107 -41 163.5 -123t56.5 -196z" />
    <glyph glyph-name="_464" unicode="&#xf1ee;" horiz-adv-x="1792" 
d="M441 864q33 0 52 -26q266 -364 362 -774h-446q-127 441 -367 749q-12 16 -3 33.5t29 17.5h373zM1000 507q-49 -199 -125 -393q-79 310 -256 594q40 221 44 449q211 -340 337 -650zM1099 1216q235 -324 384.5 -698.5t184.5 -773.5h-451q-41 665 -553 1472h435zM1792 640
q0 -424 -101 -812q-67 560 -359 1083q-25 301 -106 584q-4 16 5.5 28.5t25.5 12.5h359q21 0 38.5 -13t22.5 -33q115 -409 115 -850z" />
    <glyph glyph-name="uniF1F0" unicode="&#xf1f0;" horiz-adv-x="2304" 
d="M1975 546h-138q14 37 66 179l3 9q4 10 10 26t9 26l12 -55zM531 611l-58 295q-11 54 -75 54h-268l-2 -13q311 -79 403 -336zM710 960l-162 -438l-17 89q-26 70 -85 129.5t-131 88.5l135 -510h175l261 641h-176zM849 318h166l104 642h-166zM1617 944q-69 27 -149 27
q-123 0 -201 -59t-79 -153q-1 -102 145 -174q48 -23 67 -41t19 -39q0 -30 -30 -46t-69 -16q-86 0 -156 33l-22 11l-23 -144q74 -34 185 -34q130 -1 208.5 59t80.5 160q0 106 -140 174q-49 25 -71 42t-22 38q0 22 24.5 38.5t70.5 16.5q70 1 124 -24l15 -8zM2042 960h-128
q-65 0 -87 -54l-246 -588h174l35 96h212q5 -22 20 -96h154zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
    <glyph glyph-name="_466" unicode="&#xf1f1;" horiz-adv-x="2304" 
d="M1119 1195q-128 85 -281 85q-103 0 -197.5 -40.5t-162.5 -108.5t-108.5 -162t-40.5 -197q0 -104 40.5 -198t108.5 -162t162 -108.5t198 -40.5q153 0 281 85q-131 107 -178 265.5t0.5 316.5t177.5 265zM1152 1171q-126 -99 -172 -249.5t-0.5 -300.5t172.5 -249
q127 99 172.5 249t-0.5 300.5t-172 249.5zM1185 1195q130 -107 177.5 -265.5t0.5 -317t-178 -264.5q128 -85 281 -85q104 0 198 40.5t162 108.5t108.5 162t40.5 198q0 103 -40.5 197t-108.5 162t-162.5 108.5t-197.5 40.5q-153 0 -281 -85zM1926 473h7v3h-17v-3h7v-17h3v17z
M1955 456h4v20h-5l-6 -13l-6 13h-5v-20h3v15l6 -13h4l5 13v-15zM1947 16v-2h-2h-3v3h3h2v-1zM1947 7h3l-4 5h2l1 1q1 1 1 3t-1 3l-1 1h-3h-6v-13h3v5h1zM685 75q0 19 11 31t30 12q18 0 29 -12.5t11 -30.5q0 -19 -11 -31t-29 -12q-19 0 -30 12t-11 31zM1158 119q30 0 35 -32
h-70q5 32 35 32zM1514 75q0 19 11 31t29 12t29.5 -12.5t11.5 -30.5q0 -19 -11 -31t-30 -12q-18 0 -29 12t-11 31zM1786 75q0 18 11.5 30.5t29.5 12.5t29.5 -12.5t11.5 -30.5q0 -19 -11.5 -31t-29.5 -12t-29.5 12.5t-11.5 30.5zM1944 3q-2 0 -4 1q-1 0 -3 2t-2 3q-1 2 -1 4
q0 3 1 4q0 2 2 4l1 1q2 0 2 1q2 1 4 1q3 0 4 -1l4 -2l2 -4v-1q1 -2 1 -3l-1 -1v-3t-1 -1l-1 -2q-2 -2 -4 -2q-1 -1 -4 -1zM599 7h30v85q0 24 -14.5 38.5t-39.5 15.5q-32 0 -47 -24q-14 24 -45 24q-24 0 -39 -20v16h-30v-135h30v75q0 36 33 36q30 0 30 -36v-75h29v75
q0 36 33 36q30 0 30 -36v-75zM765 7h29v68v67h-29v-16q-17 20 -43 20q-29 0 -48 -20t-19 -51t19 -51t48 -20q28 0 43 20v-17zM943 48q0 34 -47 40l-14 2q-23 4 -23 14q0 15 25 15q23 0 43 -11l12 24q-22 14 -55 14q-26 0 -41 -12t-15 -32q0 -33 47 -39l13 -2q24 -4 24 -14
q0 -17 -31 -17q-25 0 -45 14l-13 -23q25 -17 58 -17q29 0 45.5 12t16.5 32zM1073 14l-8 25q-13 -7 -26 -7q-19 0 -19 22v61h48v27h-48v41h-30v-41h-28v-27h28v-61q0 -50 47 -50q21 0 36 10zM1159 146q-29 0 -48 -20t-19 -51q0 -32 19.5 -51.5t49.5 -19.5q33 0 55 19l-14 22
q-18 -15 -39 -15q-34 0 -41 33h101v12q0 32 -18 51.5t-46 19.5zM1318 146q-23 0 -35 -20v16h-30v-135h30v76q0 35 29 35q10 0 18 -4l9 28q-9 4 -21 4zM1348 75q0 -31 19.5 -51t52.5 -20q29 0 48 16l-14 24q-18 -13 -35 -12q-18 0 -29.5 12t-11.5 31t11.5 31t29.5 12
q19 0 35 -12l14 24q-20 16 -48 16q-33 0 -52.5 -20t-19.5 -51zM1593 7h30v68v67h-30v-16q-15 20 -42 20q-29 0 -48.5 -20t-19.5 -51t19.5 -51t48.5 -20q28 0 42 20v-17zM1726 146q-23 0 -35 -20v16h-29v-135h29v76q0 35 29 35q10 0 18 -4l9 28q-8 4 -21 4zM1866 7h29v68v122
h-29v-71q-15 20 -43 20t-47.5 -20.5t-19.5 -50.5t19.5 -50.5t47.5 -20.5q29 0 43 20v-17zM1944 27l-2 -1h-3q-2 -1 -4 -3q-3 -1 -3 -4q-1 -2 -1 -6q0 -3 1 -5q0 -2 3 -4q2 -2 4 -3t5 -1q4 0 6 1q0 1 2 2l2 1q1 1 3 4q1 2 1 5q0 4 -1 6q-1 1 -3 4q0 1 -2 2l-2 1q-1 0 -3 0.5
t-3 0.5zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
    <glyph glyph-name="_467" unicode="&#xf1f2;" horiz-adv-x="2304" 
d="M313 759q0 -51 -36 -84q-29 -26 -89 -26h-17v220h17q61 0 89 -27q36 -31 36 -83zM2089 824q0 -52 -64 -52h-19v101h20q63 0 63 -49zM380 759q0 74 -50 120.5t-129 46.5h-95v-333h95q74 0 119 38q60 51 60 128zM410 593h65v333h-65v-333zM730 694q0 40 -20.5 62t-75.5 42
q-29 10 -39.5 19t-10.5 23q0 16 13.5 26.5t34.5 10.5q29 0 53 -27l34 44q-41 37 -98 37q-44 0 -74 -27.5t-30 -67.5q0 -35 18 -55.5t64 -36.5q37 -13 45 -19q19 -12 19 -34q0 -20 -14 -33.5t-36 -13.5q-48 0 -71 44l-42 -40q44 -64 115 -64q51 0 83 30.5t32 79.5zM1008 604
v77q-37 -37 -78 -37q-49 0 -80.5 32.5t-31.5 82.5q0 48 31.5 81.5t77.5 33.5q43 0 81 -38v77q-40 20 -80 20q-74 0 -125.5 -50.5t-51.5 -123.5t51 -123.5t125 -50.5q42 0 81 19zM2240 0v527q-65 -40 -144.5 -84t-237.5 -117t-329.5 -137.5t-417.5 -134.5t-504 -118h1569
q26 0 45 19t19 45zM1389 757q0 75 -53 128t-128 53t-128 -53t-53 -128t53 -128t128 -53t128 53t53 128zM1541 584l144 342h-71l-90 -224l-89 224h-71l142 -342h35zM1714 593h184v56h-119v90h115v56h-115v74h119v57h-184v-333zM2105 593h80l-105 140q76 16 76 94q0 47 -31 73
t-87 26h-97v-333h65v133h9zM2304 1274v-1268q0 -56 -38.5 -95t-93.5 -39h-2040q-55 0 -93.5 39t-38.5 95v1268q0 56 38.5 95t93.5 39h2040q55 0 93.5 -39t38.5 -95z" />
    <glyph glyph-name="f1f3" unicode="&#xf1f3;" horiz-adv-x="2304" 
d="M119 854h89l-45 108zM740 328l74 79l-70 79h-163v-49h142v-55h-142v-54h159zM898 406l99 -110v217zM1186 453q0 33 -40 33h-84v-69h83q41 0 41 36zM1475 457q0 29 -42 29h-82v-61h81q43 0 43 32zM1197 923q0 29 -42 29h-82v-60h81q43 0 43 31zM1656 854h89l-44 108z
M699 1009v-271h-66v212l-94 -212h-57l-94 212v-212h-132l-25 60h-135l-25 -60h-70l116 271h96l110 -257v257h106l85 -184l77 184h108zM1255 453q0 -20 -5.5 -35t-14 -25t-22.5 -16.5t-26 -10t-31.5 -4.5t-31.5 -1t-32.5 0.5t-29.5 0.5v-91h-126l-80 90l-83 -90h-256v271h260
l80 -89l82 89h207q109 0 109 -89zM964 794v-56h-217v271h217v-57h-152v-49h148v-55h-148v-54h152zM2304 235v-229q0 -55 -38.5 -94.5t-93.5 -39.5h-2040q-55 0 -93.5 39.5t-38.5 94.5v678h111l25 61h55l25 -61h218v46l19 -46h113l20 47v-47h541v99l10 1q10 0 10 -14v-86h279
v23q23 -12 55 -18t52.5 -6.5t63 0.5t51.5 1l25 61h56l25 -61h227v58l34 -58h182v378h-180v-44l-25 44h-185v-44l-23 44h-249q-69 0 -109 -22v22h-172v-22q-24 22 -73 22h-628l-43 -97l-43 97h-198v-44l-22 44h-169l-78 -179v391q0 55 38.5 94.5t93.5 39.5h2040
q55 0 93.5 -39.5t38.5 -94.5v-678h-120q-51 0 -81 -22v22h-177q-55 0 -78 -22v22h-316v-22q-31 22 -87 22h-209v-22q-23 22 -91 22h-234l-54 -58l-50 58h-349v-378h343l55 59l52 -59h211v89h21q59 0 90 13v-102h174v99h8q8 0 10 -2t2 -10v-87h529q57 0 88 24v-24h168
q60 0 95 17zM1546 469q0 -23 -12 -43t-34 -29q25 -9 34 -26t9 -46v-54h-65v45q0 33 -12 43.5t-46 10.5h-69v-99h-65v271h154q48 0 77 -15t29 -58zM1269 936q0 -24 -12.5 -44t-33.5 -29q26 -9 34.5 -25.5t8.5 -46.5v-53h-65q0 9 0.5 26.5t0 25t-3 18.5t-8.5 16t-17.5 8.5
t-29.5 3.5h-70v-98h-64v271l153 -1q49 0 78 -14.5t29 -57.5zM1798 327v-56h-216v271h216v-56h-151v-49h148v-55h-148v-54zM1372 1009v-271h-66v271h66zM2065 357q0 -86 -102 -86h-126v58h126q34 0 34 25q0 16 -17 21t-41.5 5t-49.5 3.5t-42 22.5t-17 55q0 39 26 60t66 21
h130v-57h-119q-36 0 -36 -25q0 -16 17.5 -20.5t42 -4t49 -2.5t42 -21.5t17.5 -54.5zM2304 407v-101q-24 -35 -88 -35h-125v58h125q33 0 33 25q0 13 -12.5 19t-31 5.5t-40 2t-40 8t-31 24t-12.5 48.5q0 39 26.5 60t66.5 21h129v-57h-118q-36 0 -36 -25q0 -20 29 -22t68.5 -5
t56.5 -26zM2139 1008v-270h-92l-122 203v-203h-132l-26 60h-134l-25 -60h-75q-129 0 -129 133q0 138 133 138h63v-59q-7 0 -28 1t-28.5 0.5t-23 -2t-21.5 -6.5t-14.5 -13.5t-11.5 -23t-3 -33.5q0 -38 13.5 -58t49.5 -20h29l92 213h97l109 -256v256h99l114 -188v188h66z" />
    <glyph glyph-name="_469" unicode="&#xf1f4;" horiz-adv-x="2304" 
d="M745 630q0 -37 -25.5 -61.5t-62.5 -24.5q-29 0 -46.5 16t-17.5 44q0 37 25 62.5t62 25.5q28 0 46.5 -16.5t18.5 -45.5zM1530 779q0 -42 -22 -57t-66 -15l-32 -1l17 107q2 11 13 11h18q22 0 35 -2t25 -12.5t12 -30.5zM1881 630q0 -36 -25.5 -61t-61.5 -25q-29 0 -47 16
t-18 44q0 37 25 62.5t62 25.5q28 0 46.5 -16.5t18.5 -45.5zM513 801q0 59 -38.5 85.5t-100.5 26.5h-160q-19 0 -21 -19l-65 -408q-1 -6 3 -11t10 -5h76q20 0 22 19l18 110q1 8 7 13t15 6.5t17 1.5t19 -1t14 -1q86 0 135 48.5t49 134.5zM822 489l41 261q1 6 -3 11t-10 5h-76
q-14 0 -17 -33q-27 40 -95 40q-72 0 -122.5 -54t-50.5 -127q0 -59 34.5 -94t92.5 -35q28 0 58 12t48 32q-4 -12 -4 -21q0 -16 13 -16h69q19 0 22 19zM1269 752q0 5 -4 9.5t-9 4.5h-77q-11 0 -18 -10l-106 -156l-44 150q-5 16 -22 16h-75q-5 0 -9 -4.5t-4 -9.5q0 -2 19.5 -59
t42 -123t23.5 -70q-82 -112 -82 -120q0 -13 13 -13h77q11 0 18 10l255 368q2 2 2 7zM1649 801q0 59 -38.5 85.5t-100.5 26.5h-159q-20 0 -22 -19l-65 -408q-1 -6 3 -11t10 -5h82q12 0 16 13l18 116q1 8 7 13t15 6.5t17 1.5t19 -1t14 -1q86 0 135 48.5t49 134.5zM1958 489
l41 261q1 6 -3 11t-10 5h-76q-14 0 -17 -33q-26 40 -95 40q-72 0 -122.5 -54t-50.5 -127q0 -59 34.5 -94t92.5 -35q29 0 59 12t47 32q0 -1 -2 -9t-2 -12q0 -16 13 -16h69q19 0 22 19zM2176 898v1q0 14 -13 14h-74q-11 0 -13 -11l-65 -416l-1 -2q0 -5 4 -9.5t10 -4.5h66
q19 0 21 19zM392 764q-5 -35 -26 -46t-60 -11l-33 -1l17 107q2 11 13 11h19q40 0 58 -11.5t12 -48.5zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
    <glyph glyph-name="_470" unicode="&#xf1f5;" horiz-adv-x="2304" 
d="M1597 633q0 -69 -21 -106q-19 -35 -52 -35q-23 0 -41 9v224q29 30 57 30q57 0 57 -122zM2035 669h-110q6 98 56 98q51 0 54 -98zM476 534q0 59 -33 91.5t-101 57.5q-36 13 -52 24t-16 25q0 26 38 26q58 0 124 -33l18 112q-67 32 -149 32q-77 0 -123 -38q-48 -39 -48 -109
q0 -58 32.5 -90.5t99.5 -56.5q39 -14 54.5 -25.5t15.5 -27.5q0 -31 -48 -31q-29 0 -70 12.5t-72 30.5l-18 -113q72 -41 168 -41q81 0 129 37q51 41 51 117zM771 749l19 111h-96v135l-129 -21l-18 -114l-46 -8l-17 -103h62v-219q0 -84 44 -120q38 -30 111 -30q32 0 79 11v118
q-32 -7 -44 -7q-42 0 -42 50v197h77zM1087 724v139q-15 3 -28 3q-32 0 -55.5 -16t-33.5 -46l-10 56h-131v-471h150v306q26 31 82 31q16 0 26 -2zM1124 389h150v471h-150v-471zM1746 638q0 122 -45 179q-40 52 -111 52q-64 0 -117 -56l-8 47h-132v-645l150 25v151
q36 -11 68 -11q83 0 134 56q61 65 61 202zM1278 986q0 33 -23 56t-56 23t-56 -23t-23 -56t23 -56.5t56 -23.5t56 23.5t23 56.5zM2176 629q0 113 -48 176q-50 64 -144 64q-96 0 -151.5 -66t-55.5 -180q0 -128 63 -188q55 -55 161 -55q101 0 160 40l-16 103q-57 -31 -128 -31
q-43 0 -63 19q-23 19 -28 66h248q2 14 2 52zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
    <glyph glyph-name="_471" unicode="&#xf1f6;" horiz-adv-x="2048" 
d="M1558 684q61 -356 298 -556q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-180.5 74.5t-75.5 180.5zM1024 -176q16 0 16 16t-16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5zM2026 1424q8 -10 7.5 -23.5t-10.5 -22.5
l-1872 -1622q-10 -8 -23.5 -7t-21.5 11l-84 96q-8 10 -7.5 23.5t10.5 21.5l186 161q-19 32 -19 66q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q124 -18 219 -82.5t148 -157.5
l418 363q10 8 23.5 7t21.5 -11z" />
    <glyph glyph-name="_472" unicode="&#xf1f7;" horiz-adv-x="2048" 
d="M1040 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM503 315l877 760q-42 88 -132.5 146.5t-223.5 58.5q-93 0 -169.5 -31.5t-121.5 -80.5t-69 -103t-24 -105q0 -384 -137 -645zM1856 128
q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-180.5 74.5t-75.5 180.5l149 129h757q-166 187 -227 459l111 97q61 -356 298 -556zM1942 1520l84 -96q8 -10 7.5 -23.5t-10.5 -22.5l-1872 -1622q-10 -8 -23.5 -7t-21.5 11l-84 96q-8 10 -7.5 23.5t10.5 21.5l186 161
q-19 32 -19 66q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q124 -18 219 -82.5t148 -157.5l418 363q10 8 23.5 7t21.5 -11z" />
    <glyph glyph-name="_473" unicode="&#xf1f8;" horiz-adv-x="1408" 
d="M512 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM768 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1024 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704
q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167
q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" />
    <glyph glyph-name="_474" unicode="&#xf1f9;" 
d="M1150 462v-109q0 -50 -36.5 -89t-94 -60.5t-118 -32.5t-117.5 -11q-205 0 -342.5 139t-137.5 346q0 203 136 339t339 136q34 0 75.5 -4.5t93 -18t92.5 -34t69 -56.5t28 -81v-109q0 -16 -16 -16h-118q-16 0 -16 16v70q0 43 -65.5 67.5t-137.5 24.5q-140 0 -228.5 -91.5
t-88.5 -237.5q0 -151 91.5 -249.5t233.5 -98.5q68 0 138 24t70 66v70q0 7 4.5 11.5t10.5 4.5h119q6 0 11 -4.5t5 -11.5zM768 1280q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5
t-51 248.5t-136.5 204t-204 136.5t-248.5 51zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="_475" unicode="&#xf1fa;" 
d="M972 761q0 108 -53.5 169t-147.5 61q-63 0 -124 -30.5t-110 -84.5t-79.5 -137t-30.5 -180q0 -112 53.5 -173t150.5 -61q96 0 176 66.5t122.5 166t42.5 203.5zM1536 640q0 -111 -37 -197t-98.5 -135t-131.5 -74.5t-145 -27.5q-6 0 -15.5 -0.5t-16.5 -0.5q-95 0 -142 53
q-28 33 -33 83q-52 -66 -131.5 -110t-173.5 -44q-161 0 -249.5 95.5t-88.5 269.5q0 157 66 290t179 210.5t246 77.5q87 0 155 -35.5t106 -99.5l2 19l11 56q1 6 5.5 12t9.5 6h118q5 0 13 -11q5 -5 3 -16l-120 -614q-5 -24 -5 -48q0 -39 12.5 -52t44.5 -13q28 1 57 5.5t73 24
t77 50t57 89.5t24 137q0 292 -174 466t-466 174q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51q228 0 405 144q11 9 24 8t21 -12l41 -49q8 -12 7 -24q-2 -13 -12 -22q-102 -83 -227.5 -128t-258.5 -45q-156 0 -298 61
t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q344 0 556 -212t212 -556z" />
    <glyph glyph-name="_476" unicode="&#xf1fb;" horiz-adv-x="1792" 
d="M1698 1442q94 -94 94 -226.5t-94 -225.5l-225 -223l104 -104q10 -10 10 -23t-10 -23l-210 -210q-10 -10 -23 -10t-23 10l-105 105l-603 -603q-37 -37 -90 -37h-203l-256 -128l-64 64l128 256v203q0 53 37 90l603 603l-105 105q-10 10 -10 23t10 23l210 210q10 10 23 10
t23 -10l104 -104l223 225q93 94 225.5 94t226.5 -94zM512 64l576 576l-192 192l-576 -576v-192h192z" />
    <glyph glyph-name="f1fc" unicode="&#xf1fc;" horiz-adv-x="1792" 
d="M1615 1536q70 0 122.5 -46.5t52.5 -116.5q0 -63 -45 -151q-332 -629 -465 -752q-97 -91 -218 -91q-126 0 -216.5 92.5t-90.5 219.5q0 128 92 212l638 579q59 54 130 54zM706 502q39 -76 106.5 -130t150.5 -76l1 -71q4 -213 -129.5 -347t-348.5 -134q-123 0 -218 46.5
t-152.5 127.5t-86.5 183t-29 220q7 -5 41 -30t62 -44.5t59 -36.5t46 -17q41 0 55 37q25 66 57.5 112.5t69.5 76t88 47.5t103 25.5t125 10.5z" />
    <glyph glyph-name="_478" unicode="&#xf1fd;" horiz-adv-x="1792" 
d="M1792 128v-384h-1792v384q45 0 85 14t59 27.5t47 37.5q30 27 51.5 38t56.5 11q24 0 44 -7t31 -15t33 -27q29 -25 47 -38t58 -27t86 -14q45 0 85 14.5t58 27t48 37.5q21 19 32.5 27t31 15t43.5 7q35 0 56.5 -11t51.5 -38q28 -24 47 -37.5t59 -27.5t85 -14t85 14t59 27.5
t47 37.5q30 27 51.5 38t56.5 11q34 0 55.5 -11t51.5 -38q28 -24 47 -37.5t59 -27.5t85 -14zM1792 448v-192q-24 0 -44 7t-31 15t-33 27q-29 25 -47 38t-58 27t-85 14q-46 0 -86 -14t-58 -27t-47 -38q-22 -19 -33 -27t-31 -15t-44 -7q-35 0 -56.5 11t-51.5 38q-29 25 -47 38
t-58 27t-86 14q-45 0 -85 -14.5t-58 -27t-48 -37.5q-21 -19 -32.5 -27t-31 -15t-43.5 -7q-35 0 -56.5 11t-51.5 38q-28 24 -47 37.5t-59 27.5t-85 14q-46 0 -86 -14t-58 -27t-47 -38q-30 -27 -51.5 -38t-56.5 -11v192q0 80 56 136t136 56h64v448h256v-448h256v448h256v-448
h256v448h256v-448h64q80 0 136 -56t56 -136zM512 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5q0 29 9.5 51t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150zM1024 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5
q0 29 9.5 51t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150zM1536 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5q0 29 9.5 51t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150z" />
    <glyph glyph-name="_479" unicode="&#xf1fe;" horiz-adv-x="2048" 
d="M2048 0v-128h-2048v1536h128v-1408h1920zM1664 1024l256 -896h-1664v576l448 576l576 -576z" />
    <glyph glyph-name="_480" unicode="&#xf200;" horiz-adv-x="1792" 
d="M768 646l546 -546q-106 -108 -247.5 -168t-298.5 -60q-209 0 -385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103v-762zM955 640h773q0 -157 -60 -298.5t-168 -247.5zM1664 768h-768v768q209 0 385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="_481" unicode="&#xf201;" horiz-adv-x="2048" 
d="M2048 0v-128h-2048v1536h128v-1408h1920zM1920 1248v-435q0 -21 -19.5 -29.5t-35.5 7.5l-121 121l-633 -633q-10 -10 -23 -10t-23 10l-233 233l-416 -416l-192 192l585 585q10 10 23 10t23 -10l233 -233l464 464l-121 121q-16 16 -7.5 35.5t29.5 19.5h435q14 0 23 -9
t9 -23z" />
    <glyph glyph-name="_482" unicode="&#xf202;" horiz-adv-x="1792" 
d="M1292 832q0 -6 10 -41q10 -29 25 -49.5t41 -34t44 -20t55 -16.5q325 -91 325 -332q0 -146 -105.5 -242.5t-254.5 -96.5q-59 0 -111.5 18.5t-91.5 45.5t-77 74.5t-63 87.5t-53.5 103.5t-43.5 103t-39.5 106.5t-35.5 95q-32 81 -61.5 133.5t-73.5 96.5t-104 64t-142 20
q-96 0 -183 -55.5t-138 -144.5t-51 -185q0 -160 106.5 -279.5t263.5 -119.5q177 0 258 95q56 63 83 116l84 -152q-15 -34 -44 -70l1 -1q-131 -152 -388 -152q-147 0 -269.5 79t-190.5 207.5t-68 274.5q0 105 43.5 206t116 176.5t172 121.5t204.5 46q87 0 159 -19t123.5 -50
t95 -80t72.5 -99t58.5 -117t50.5 -124.5t50 -130.5t55 -127q96 -200 233 -200q81 0 138.5 48.5t57.5 128.5q0 42 -19 72t-50.5 46t-72.5 31.5t-84.5 27t-87.5 34t-81 52t-65 82t-39 122.5q-3 16 -3 33q0 110 87.5 192t198.5 78q78 -3 120.5 -14.5t90.5 -53.5h-1
q12 -11 23 -24.5t26 -36t19 -27.5l-129 -99q-26 49 -54 70v1q-23 21 -97 21q-49 0 -84 -33t-35 -83z" />
    <glyph glyph-name="_483" unicode="&#xf203;" 
d="M1432 484q0 173 -234 239q-35 10 -53 16.5t-38 25t-29 46.5q0 2 -2 8.5t-3 12t-1 7.5q0 36 24.5 59.5t60.5 23.5q54 0 71 -15h-1q20 -15 39 -51l93 71q-39 54 -49 64q-33 29 -67.5 39t-85.5 10q-80 0 -142 -57.5t-62 -137.5q0 -7 2 -23q16 -96 64.5 -140t148.5 -73
q29 -8 49 -15.5t45 -21.5t38.5 -34.5t13.5 -46.5v-5q1 -58 -40.5 -93t-100.5 -35q-97 0 -167 144q-23 47 -51.5 121.5t-48 125.5t-54 110.5t-74 95.5t-103.5 60.5t-147 24.5q-101 0 -192 -56t-144 -148t-50 -192v-1q4 -108 50.5 -199t133.5 -147.5t196 -56.5q186 0 279 110
q20 27 31 51l-60 109q-42 -80 -99 -116t-146 -36q-115 0 -191 87t-76 204q0 105 82 189t186 84q112 0 170 -53.5t104 -172.5q8 -21 25.5 -68.5t28.5 -76.5t31.5 -74.5t38.5 -74t45.5 -62.5t55.5 -53.5t66 -33t80 -13.5q107 0 183 69.5t76 174.5zM1536 1120v-960
q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="_484" unicode="&#xf204;" horiz-adv-x="2048" 
d="M1152 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1920 640q0 104 -40.5 198.5
t-109.5 163.5t-163.5 109.5t-198.5 40.5h-386q119 -90 188.5 -224t69.5 -288t-69.5 -288t-188.5 -224h386q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM2048 640q0 -130 -51 -248.5t-136.5 -204t-204 -136.5t-248.5 -51h-768q-130 0 -248.5 51t-204 136.5
t-136.5 204t-51 248.5t51 248.5t136.5 204t204 136.5t248.5 51h768q130 0 248.5 -51t204 -136.5t136.5 -204t51 -248.5z" />
    <glyph glyph-name="_485" unicode="&#xf205;" horiz-adv-x="2048" 
d="M0 640q0 130 51 248.5t136.5 204t204 136.5t248.5 51h768q130 0 248.5 -51t204 -136.5t136.5 -204t51 -248.5t-51 -248.5t-136.5 -204t-204 -136.5t-248.5 -51h-768q-130 0 -248.5 51t-204 136.5t-136.5 204t-51 248.5zM1408 128q104 0 198.5 40.5t163.5 109.5
t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5z" />
    <glyph glyph-name="_486" unicode="&#xf206;" horiz-adv-x="2304" 
d="M762 384h-314q-40 0 -57.5 35t6.5 67l188 251q-65 31 -137 31q-132 0 -226 -94t-94 -226t94 -226t226 -94q115 0 203 72.5t111 183.5zM576 512h186q-18 85 -75 148zM1056 512l288 384h-480l-99 -132q105 -103 126 -252h165zM2176 448q0 132 -94 226t-226 94
q-60 0 -121 -24l174 -260q15 -23 10 -49t-27 -40q-15 -11 -36 -11q-35 0 -53 29l-174 260q-93 -95 -93 -225q0 -132 94 -226t226 -94t226 94t94 226zM2304 448q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 97 39.5 183.5t109.5 149.5l-65 98l-353 -469
q-18 -26 -51 -26h-197q-23 -164 -149 -274t-294 -110q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q114 0 215 -55l137 183h-224q-26 0 -45 19t-19 45t19 45t45 19h384v-128h435l-85 128h-222q-26 0 -45 19t-19 45t19 45t45 19h256q33 0 53 -28l267 -400
q91 44 192 44q185 0 316.5 -131.5t131.5 -316.5z" />
    <glyph glyph-name="_487" unicode="&#xf207;" 
d="M384 320q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1408 320q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1362 716l-72 384q-5 23 -22.5 37.5t-40.5 14.5
h-918q-23 0 -40.5 -14.5t-22.5 -37.5l-72 -384q-5 -30 14 -53t49 -23h1062q30 0 49 23t14 53zM1136 1328q0 20 -14 34t-34 14h-640q-20 0 -34 -14t-14 -34t14 -34t34 -14h640q20 0 34 14t14 34zM1536 603v-603h-128v-128q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5
t-37.5 90.5v128h-768v-128q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5v128h-128v603q0 112 25 223l103 454q9 78 97.5 137t230 89t312.5 30t312.5 -30t230 -89t97.5 -137l105 -454q23 -102 23 -223z" />
    <glyph glyph-name="_488" unicode="&#xf208;" horiz-adv-x="2048" 
d="M1463 704q0 -35 -25 -60.5t-61 -25.5h-702q-36 0 -61 25.5t-25 60.5t25 60.5t61 25.5h702q36 0 61 -25.5t25 -60.5zM1677 704q0 86 -23 170h-982q-36 0 -61 25t-25 60q0 36 25 61t61 25h908q-88 143 -235 227t-320 84q-177 0 -327.5 -87.5t-238 -237.5t-87.5 -327
q0 -86 23 -170h982q36 0 61 -25t25 -60q0 -36 -25 -61t-61 -25h-908q88 -143 235.5 -227t320.5 -84q132 0 253 51.5t208 139t139 208t52 253.5zM2048 959q0 -35 -25 -60t-61 -25h-131q17 -85 17 -170q0 -167 -65.5 -319.5t-175.5 -263t-262.5 -176t-319.5 -65.5
q-246 0 -448.5 133t-301.5 350h-189q-36 0 -61 25t-25 61q0 35 25 60t61 25h132q-17 85 -17 170q0 167 65.5 319.5t175.5 263t262.5 176t320.5 65.5q245 0 447.5 -133t301.5 -350h188q36 0 61 -25t25 -61z" />
    <glyph glyph-name="_489" unicode="&#xf209;" horiz-adv-x="1280" 
d="M953 1158l-114 -328l117 -21q165 451 165 518q0 56 -38 56q-57 0 -130 -225zM654 471l33 -88q37 42 71 67l-33 5.5t-38.5 7t-32.5 8.5zM362 1367q0 -98 159 -521q17 10 49 10q15 0 75 -5l-121 351q-75 220 -123 220q-19 0 -29 -17.5t-10 -37.5zM283 608q0 -36 51.5 -119
t117.5 -153t100 -70q14 0 25.5 13t11.5 27q0 24 -32 102q-13 32 -32 72t-47.5 89t-61.5 81t-62 32q-20 0 -45.5 -27t-25.5 -47zM125 273q0 -41 25 -104q59 -145 183.5 -227t281.5 -82q227 0 382 170q152 169 152 427q0 43 -1 67t-11.5 62t-30.5 56q-56 49 -211.5 75.5
t-270.5 26.5q-37 0 -49 -11q-12 -5 -12 -35q0 -34 21.5 -60t55.5 -40t77.5 -23.5t87.5 -11.5t85 -4t70 0h23q24 0 40 -19q15 -19 19 -55q-28 -28 -96 -54q-61 -22 -93 -46q-64 -46 -108.5 -114t-44.5 -137q0 -31 18.5 -88.5t18.5 -87.5l-3 -12q-4 -12 -4 -14
q-137 10 -146 216q-8 -2 -41 -2q2 -7 2 -21q0 -53 -40.5 -89.5t-94.5 -36.5q-82 0 -166.5 78t-84.5 159q0 34 33 67q52 -64 60 -76q77 -104 133 -104q12 0 26.5 8.5t14.5 20.5q0 34 -87.5 145t-116.5 111q-43 0 -70 -44.5t-27 -90.5zM11 264q0 101 42.5 163t136.5 88
q-28 74 -28 104q0 62 61 123t122 61q29 0 70 -15q-163 462 -163 567q0 80 41 130.5t119 50.5q131 0 325 -581q6 -17 8 -23q6 16 29 79.5t43.5 118.5t54 127.5t64.5 123t70.5 86.5t76.5 36q71 0 112 -49t41 -122q0 -108 -159 -550q61 -15 100.5 -46t58.5 -78t26 -93.5
t7 -110.5q0 -150 -47 -280t-132 -225t-211 -150t-278 -55q-111 0 -223 42q-149 57 -258 191.5t-109 286.5z" />
    <glyph glyph-name="_490" unicode="&#xf20a;" horiz-adv-x="2048" 
d="M785 528h207q-14 -158 -98.5 -248.5t-214.5 -90.5q-162 0 -254.5 116t-92.5 316q0 194 93 311.5t233 117.5q148 0 232 -87t97 -247h-203q-5 64 -35.5 99t-81.5 35q-57 0 -88.5 -60.5t-31.5 -177.5q0 -48 5 -84t18 -69.5t40 -51.5t66 -18q95 0 109 139zM1497 528h206
q-14 -158 -98 -248.5t-214 -90.5q-162 0 -254.5 116t-92.5 316q0 194 93 311.5t233 117.5q148 0 232 -87t97 -247h-204q-4 64 -35 99t-81 35q-57 0 -88.5 -60.5t-31.5 -177.5q0 -48 5 -84t18 -69.5t39.5 -51.5t65.5 -18q49 0 76.5 38t33.5 101zM1856 647q0 207 -15.5 307
t-60.5 161q-6 8 -13.5 14t-21.5 15t-16 11q-86 63 -697 63q-625 0 -710 -63q-5 -4 -17.5 -11.5t-21 -14t-14.5 -14.5q-45 -60 -60 -159.5t-15 -308.5q0 -208 15 -307.5t60 -160.5q6 -8 15 -15t20.5 -14t17.5 -12q44 -33 239.5 -49t470.5 -16q610 0 697 65q5 4 17 11t20.5 14
t13.5 16q46 60 61 159t15 309zM2048 1408v-1536h-2048v1536h2048z" />
    <glyph glyph-name="_491" unicode="&#xf20b;" 
d="M992 912v-496q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v496q0 112 -80 192t-192 80h-272v-1152q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v1344q0 14 9 23t23 9h464q135 0 249 -66.5t180.5 -180.5t66.5 -249zM1376 1376v-880q0 -135 -66.5 -249t-180.5 -180.5
t-249 -66.5h-464q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h160q14 0 23 -9t9 -23v-768h272q112 0 192 80t80 192v880q0 14 9 23t23 9h160q14 0 23 -9t9 -23z" />
    <glyph glyph-name="_492" unicode="&#xf20c;" 
d="M1311 694v-114q0 -24 -13.5 -38t-37.5 -14h-202q-24 0 -38 14t-14 38v114q0 24 14 38t38 14h202q24 0 37.5 -14t13.5 -38zM821 464v250q0 53 -32.5 85.5t-85.5 32.5h-133q-68 0 -96 -52q-28 52 -96 52h-130q-53 0 -85.5 -32.5t-32.5 -85.5v-250q0 -22 21 -22h55
q22 0 22 22v230q0 24 13.5 38t38.5 14h94q24 0 38 -14t14 -38v-230q0 -22 21 -22h54q22 0 22 22v230q0 24 14 38t38 14h97q24 0 37.5 -14t13.5 -38v-230q0 -22 22 -22h55q21 0 21 22zM1410 560v154q0 53 -33 85.5t-86 32.5h-264q-53 0 -86 -32.5t-33 -85.5v-410
q0 -21 22 -21h55q21 0 21 21v180q31 -42 94 -42h191q53 0 86 32.5t33 85.5zM1536 1176v-1072q0 -96 -68 -164t-164 -68h-1072q-96 0 -164 68t-68 164v1072q0 96 68 164t164 68h1072q96 0 164 -68t68 -164z" />
    <glyph glyph-name="_493" unicode="&#xf20d;" 
d="M915 450h-294l147 551zM1001 128h311l-324 1024h-440l-324 -1024h311l383 314zM1536 1120v-960q0 -118 -85 -203t-203 -85h-960q-118 0 -203 85t-85 203v960q0 118 85 203t203 85h960q118 0 203 -85t85 -203z" />
    <glyph glyph-name="_494" unicode="&#xf20e;" horiz-adv-x="2048" 
d="M2048 641q0 -21 -13 -36.5t-33 -19.5l-205 -356q3 -9 3 -18q0 -20 -12.5 -35.5t-32.5 -19.5l-193 -337q3 -8 3 -16q0 -23 -16.5 -40t-40.5 -17q-25 0 -41 18h-400q-17 -20 -43 -20t-43 20h-399q-17 -20 -43 -20q-23 0 -40 16.5t-17 40.5q0 8 4 20l-193 335
q-20 4 -32.5 19.5t-12.5 35.5q0 9 3 18l-206 356q-20 5 -32.5 20.5t-12.5 35.5q0 21 13.5 36.5t33.5 19.5l199 344q0 1 -0.5 3t-0.5 3q0 36 34 51l209 363q-4 10 -4 18q0 24 17 40.5t40 16.5q26 0 44 -21h396q16 21 43 21t43 -21h398q18 21 44 21q23 0 40 -16.5t17 -40.5
q0 -6 -4 -18l207 -358q23 -1 39 -17.5t16 -38.5q0 -13 -7 -27l187 -324q19 -4 31.5 -19.5t12.5 -35.5zM1063 -158h389l-342 354h-143l-342 -354h360q18 16 39 16t39 -16zM112 654q1 -4 1 -13q0 -10 -2 -15l208 -360l15 -6l188 199v347l-187 194q-13 -8 -29 -10zM986 1438
h-388l190 -200l554 200h-280q-16 -16 -38 -16t-38 16zM1689 226q1 6 5 11l-64 68l-17 -79h76zM1583 226l22 105l-252 266l-296 -307l63 -64h463zM1495 -142l16 28l65 310h-427l333 -343q8 4 13 5zM578 -158h5l342 354h-373v-335l4 -6q14 -5 22 -13zM552 226h402l64 66
l-309 321l-157 -166v-221zM359 226h163v189l-168 -177q4 -8 5 -12zM358 1051q0 -1 0.5 -2t0.5 -2q0 -16 -8 -29l171 -177v269zM552 1121v-311l153 -157l297 314l-223 236zM556 1425l-4 -8v-264l205 74l-191 201q-6 -2 -10 -3zM1447 1438h-16l-621 -224l213 -225zM1023 946
l-297 -315l311 -319l296 307zM688 634l-136 141v-284zM1038 270l-42 -44h85zM1374 618l238 -251l132 624l-3 5l-1 1zM1718 1018q-8 13 -8 29v2l-216 376q-5 1 -13 5l-437 -463l310 -327zM522 1142v223l-163 -282zM522 196h-163l163 -283v283zM1607 196l-48 -227l130 227h-82
zM1729 266l207 361q-2 10 -2 14q0 1 3 16l-171 296l-129 -612l77 -82q5 3 15 7z" />
    <glyph glyph-name="f210" unicode="&#xf210;" 
d="M0 856q0 131 91.5 226.5t222.5 95.5h742l352 358v-1470q0 -132 -91.5 -227t-222.5 -95h-780q-131 0 -222.5 95t-91.5 227v790zM1232 102l-176 180v425q0 46 -32 79t-78 33h-484q-46 0 -78 -33t-32 -79v-492q0 -46 32.5 -79.5t77.5 -33.5h770z" />
    <glyph glyph-name="_496" unicode="&#xf211;" 
d="M934 1386q-317 -121 -556 -362.5t-358 -560.5q-20 89 -20 176q0 208 102.5 384.5t278.5 279t384 102.5q82 0 169 -19zM1203 1267q93 -65 164 -155q-389 -113 -674.5 -400.5t-396.5 -676.5q-93 72 -155 162q112 386 395 671t667 399zM470 -67q115 356 379.5 622t619.5 384
q40 -92 54 -195q-292 -120 -516 -345t-343 -518q-103 14 -194 52zM1536 -125q-193 50 -367 115q-135 -84 -290 -107q109 205 274 370.5t369 275.5q-21 -152 -101 -284q65 -175 115 -370z" />
    <glyph glyph-name="f212" unicode="&#xf212;" horiz-adv-x="2048" 
d="M1893 1144l155 -1272q-131 0 -257 57q-200 91 -393 91q-226 0 -374 -148q-148 148 -374 148q-193 0 -393 -91q-128 -57 -252 -57h-5l155 1272q224 127 482 127q233 0 387 -106q154 106 387 106q258 0 482 -127zM1398 157q129 0 232 -28.5t260 -93.5l-124 1021
q-171 78 -368 78q-224 0 -374 -141q-150 141 -374 141q-197 0 -368 -78l-124 -1021q105 43 165.5 65t148.5 39.5t178 17.5q202 0 374 -108q172 108 374 108zM1438 191l-55 907q-211 -4 -359 -155q-152 155 -374 155q-176 0 -336 -66l-114 -941q124 51 228.5 76t221.5 25
q209 0 374 -102q172 107 374 102z" />
    <glyph glyph-name="_498" unicode="&#xf213;" horiz-adv-x="2048" 
d="M1500 165v733q0 21 -15 36t-35 15h-93q-20 0 -35 -15t-15 -36v-733q0 -20 15 -35t35 -15h93q20 0 35 15t15 35zM1216 165v531q0 20 -15 35t-35 15h-101q-20 0 -35 -15t-15 -35v-531q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM924 165v429q0 20 -15 35t-35 15h-101
q-20 0 -35 -15t-15 -35v-429q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM632 165v362q0 20 -15 35t-35 15h-101q-20 0 -35 -15t-15 -35v-362q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM2048 311q0 -166 -118 -284t-284 -118h-1244q-166 0 -284 118t-118 284
q0 116 63 214.5t168 148.5q-10 34 -10 73q0 113 80.5 193.5t193.5 80.5q102 0 180 -67q45 183 194 300t338 117q149 0 275 -73.5t199.5 -199.5t73.5 -275q0 -66 -14 -122q135 -33 221 -142.5t86 -247.5z" />
    <glyph glyph-name="_499" unicode="&#xf214;" 
d="M0 1536h1536v-1392l-776 -338l-760 338v1392zM1436 209v926h-1336v-926l661 -294zM1436 1235v201h-1336v-201h1336zM181 937v-115h-37v115h37zM181 789v-115h-37v115h37zM181 641v-115h-37v115h37zM181 493v-115h-37v115h37zM181 345v-115h-37v115h37zM207 202l15 34
l105 -47l-15 -33zM343 142l15 34l105 -46l-15 -34zM478 82l15 34l105 -46l-15 -34zM614 23l15 33l104 -46l-15 -34zM797 10l105 46l15 -33l-105 -47zM932 70l105 46l15 -34l-105 -46zM1068 130l105 46l15 -34l-105 -46zM1203 189l105 47l15 -34l-105 -46zM259 1389v-36h-114
v36h114zM421 1389v-36h-115v36h115zM583 1389v-36h-115v36h115zM744 1389v-36h-114v36h114zM906 1389v-36h-114v36h114zM1068 1389v-36h-115v36h115zM1230 1389v-36h-115v36h115zM1391 1389v-36h-114v36h114zM181 1049v-79h-37v115h115v-36h-78zM421 1085v-36h-115v36h115z
M583 1085v-36h-115v36h115zM744 1085v-36h-114v36h114zM906 1085v-36h-114v36h114zM1068 1085v-36h-115v36h115zM1230 1085v-36h-115v36h115zM1355 970v79h-78v36h115v-115h-37zM1355 822v115h37v-115h-37zM1355 674v115h37v-115h-37zM1355 526v115h37v-115h-37zM1355 378
v115h37v-115h-37zM1355 230v115h37v-115h-37zM760 265q-129 0 -221 91.5t-92 221.5q0 129 92 221t221 92q130 0 221.5 -92t91.5 -221q0 -130 -91.5 -221.5t-221.5 -91.5zM595 646q0 -36 19.5 -56.5t49.5 -25t64 -7t64 -2t49.5 -9t19.5 -30.5q0 -49 -112 -49q-97 0 -123 51
h-3l-31 -63q67 -42 162 -42q29 0 56.5 5t55.5 16t45.5 33t17.5 53q0 46 -27.5 69.5t-67.5 27t-79.5 3t-67 5t-27.5 25.5q0 21 20.5 33t40.5 15t41 3q34 0 70.5 -11t51.5 -34h3l30 58q-3 1 -21 8.5t-22.5 9t-19.5 7t-22 7t-20 4.5t-24 4t-23 1q-29 0 -56.5 -5t-54 -16.5
t-43 -34t-16.5 -53.5z" />
    <glyph glyph-name="_500" unicode="&#xf215;" horiz-adv-x="2048" 
d="M863 504q0 112 -79.5 191.5t-191.5 79.5t-191 -79.5t-79 -191.5t79 -191t191 -79t191.5 79t79.5 191zM1726 505q0 112 -79 191t-191 79t-191.5 -79t-79.5 -191q0 -113 79.5 -192t191.5 -79t191 79.5t79 191.5zM2048 1314v-1348q0 -44 -31.5 -75.5t-76.5 -31.5h-1832
q-45 0 -76.5 31.5t-31.5 75.5v1348q0 44 31.5 75.5t76.5 31.5h431q44 0 76 -31.5t32 -75.5v-161h754v161q0 44 32 75.5t76 31.5h431q45 0 76.5 -31.5t31.5 -75.5z" />
    <glyph glyph-name="_501" unicode="&#xf216;" horiz-adv-x="2048" 
d="M1430 953zM1690 749q148 0 253 -98.5t105 -244.5q0 -157 -109 -261.5t-267 -104.5q-85 0 -162 27.5t-138 73.5t-118 106t-109 126t-103.5 132.5t-108.5 126.5t-117 106t-136 73.5t-159 27.5q-154 0 -251.5 -91.5t-97.5 -244.5q0 -157 104 -250t263 -93q100 0 208 37.5
t193 98.5q5 4 21 18.5t30 24t22 9.5q14 0 24.5 -10.5t10.5 -24.5q0 -24 -60 -77q-101 -88 -234.5 -142t-260.5 -54q-133 0 -245.5 58t-180 165t-67.5 241q0 205 141.5 341t347.5 136q120 0 226.5 -43.5t185.5 -113t151.5 -153t139 -167.5t133.5 -153.5t149.5 -113
t172.5 -43.5q102 0 168.5 61.5t66.5 162.5q0 95 -64.5 159t-159.5 64q-30 0 -81.5 -18.5t-68.5 -18.5q-20 0 -35.5 15t-15.5 35q0 18 8.5 57t8.5 59q0 159 -107.5 263t-266.5 104q-58 0 -111.5 -18.5t-84 -40.5t-55.5 -40.5t-33 -18.5q-15 0 -25.5 10.5t-10.5 25.5
q0 19 25 46q59 67 147 103.5t182 36.5q191 0 318 -125.5t127 -315.5q0 -37 -4 -66q57 15 115 15z" />
    <glyph glyph-name="_502" unicode="&#xf217;" horiz-adv-x="1664" 
d="M1216 832q0 26 -19 45t-45 19h-128v128q0 26 -19 45t-45 19t-45 -19t-19 -45v-128h-128q-26 0 -45 -19t-19 -45t19 -45t45 -19h128v-128q0 -26 19 -45t45 -19t45 19t19 45v128h128q26 0 45 19t19 45zM640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5
t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920
q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" />
    <glyph glyph-name="_503" unicode="&#xf218;" horiz-adv-x="1664" 
d="M1280 832q0 26 -19 45t-45 19t-45 -19l-147 -146v293q0 26 -19 45t-45 19t-45 -19t-19 -45v-293l-147 146q-19 19 -45 19t-45 -19t-19 -45t19 -45l256 -256q19 -19 45 -19t45 19l256 256q19 19 19 45zM640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5
t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920
q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" />
    <glyph glyph-name="_504" unicode="&#xf219;" horiz-adv-x="2048" 
d="M212 768l623 -665l-300 665h-323zM1024 -4l349 772h-698zM538 896l204 384h-262l-288 -384h346zM1213 103l623 665h-323zM683 896h682l-204 384h-274zM1510 896h346l-288 384h-262zM1651 1382l384 -512q14 -18 13 -41.5t-17 -40.5l-960 -1024q-18 -20 -47 -20t-47 20
l-960 1024q-16 17 -17 40.5t13 41.5l384 512q18 26 51 26h1152q33 0 51 -26z" />
    <glyph glyph-name="_505" unicode="&#xf21a;" horiz-adv-x="2048" 
d="M1811 -19q19 19 45 19t45 -19l128 -128l-90 -90l-83 83l-83 -83q-18 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83
q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-128 128l90 90l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83
q19 19 45 19t45 -19l83 -83zM237 19q-19 -19 -45 -19t-45 19l-128 128l90 90l83 -82l83 82q19 19 45 19t45 -19l83 -82l64 64v293l-210 314q-17 26 -7 56.5t40 40.5l177 58v299h128v128h256v128h256v-128h256v-128h128v-299l177 -58q30 -10 40 -40.5t-7 -56.5l-210 -314
v-293l19 18q19 19 45 19t45 -19l83 -82l83 82q19 19 45 19t45 -19l128 -128l-90 -90l-83 83l-83 -83q-18 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83
q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83zM640 1152v-128l384 128l384 -128v128h-128v128h-512v-128h-128z" />
    <glyph glyph-name="_506" unicode="&#xf21b;" 
d="M576 0l96 448l-96 128l-128 64zM832 0l128 640l-128 -64l-96 -128zM992 1010q-2 4 -4 6q-10 8 -96 8q-70 0 -167 -19q-7 -2 -21 -2t-21 2q-97 19 -167 19q-86 0 -96 -8q-2 -2 -4 -6q2 -18 4 -27q2 -3 7.5 -6.5t7.5 -10.5q2 -4 7.5 -20.5t7 -20.5t7.5 -17t8.5 -17t9 -14
t12 -13.5t14 -9.5t17.5 -8t20.5 -4t24.5 -2q36 0 59 12.5t32.5 30t14.5 34.5t11.5 29.5t17.5 12.5h12q11 0 17.5 -12.5t11.5 -29.5t14.5 -34.5t32.5 -30t59 -12.5q13 0 24.5 2t20.5 4t17.5 8t14 9.5t12 13.5t9 14t8.5 17t7.5 17t7 20.5t7.5 20.5q2 7 7.5 10.5t7.5 6.5
q2 9 4 27zM1408 131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190q0 61 4.5 118t19 125.5t37.5 123.5t63.5 103.5t93.5 74.5l-90 220h214q-22 64 -22 128q0 12 2 32q-194 40 -194 96q0 57 210 99q17 62 51.5 134t70.5 114q32 37 76 37q30 0 84 -31t84 -31t84 31
t84 31q44 0 76 -37q36 -42 70.5 -114t51.5 -134q210 -42 210 -99q0 -56 -194 -96q7 -81 -20 -160h214l-82 -225q63 -33 107.5 -96.5t65.5 -143.5t29 -151.5t8 -148.5z" />
    <glyph glyph-name="_507" unicode="&#xf21c;" horiz-adv-x="2304" 
d="M2301 500q12 -103 -22 -198.5t-99 -163.5t-158.5 -106t-196.5 -31q-161 11 -279.5 125t-134.5 274q-12 111 27.5 210.5t118.5 170.5l-71 107q-96 -80 -151 -194t-55 -244q0 -27 -18.5 -46.5t-45.5 -19.5h-256h-69q-23 -164 -149 -274t-294 -110q-185 0 -316.5 131.5
t-131.5 316.5t131.5 316.5t316.5 131.5q76 0 152 -27l24 45q-123 110 -304 110h-64q-26 0 -45 19t-19 45t19 45t45 19h128q78 0 145 -13.5t116.5 -38.5t71.5 -39.5t51 -36.5h512h115l-85 128h-222q-30 0 -49 22.5t-14 52.5q4 23 23 38t43 15h253q33 0 53 -28l70 -105
l114 114q19 19 46 19h101q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-179l115 -172q131 63 275 36q143 -26 244 -134.5t118 -253.5zM448 128q115 0 203 72.5t111 183.5h-314q-35 0 -55 31q-18 32 -1 63l147 277q-47 13 -91 13q-132 0 -226 -94t-94 -226t94 -226
t226 -94zM1856 128q132 0 226 94t94 226t-94 226t-226 94q-60 0 -121 -24l174 -260q15 -23 10 -49t-27 -40q-15 -11 -36 -11q-35 0 -53 29l-174 260q-93 -95 -93 -225q0 -132 94 -226t226 -94z" />
    <glyph glyph-name="_508" unicode="&#xf21d;" 
d="M1408 0q0 -63 -61.5 -113.5t-164 -81t-225 -46t-253.5 -15.5t-253.5 15.5t-225 46t-164 81t-61.5 113.5q0 49 33 88.5t91 66.5t118 44.5t131 29.5q26 5 48 -10.5t26 -41.5q5 -26 -10.5 -48t-41.5 -26q-58 -10 -106 -23.5t-76.5 -25.5t-48.5 -23.5t-27.5 -19.5t-8.5 -12
q3 -11 27 -26.5t73 -33t114 -32.5t160.5 -25t201.5 -10t201.5 10t160.5 25t114 33t73 33.5t27 27.5q-1 4 -8.5 11t-27.5 19t-48.5 23.5t-76.5 25t-106 23.5q-26 4 -41.5 26t-10.5 48q4 26 26 41.5t48 10.5q71 -12 131 -29.5t118 -44.5t91 -66.5t33 -88.5zM1024 896v-384
q0 -26 -19 -45t-45 -19h-64v-384q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v384h-64q-26 0 -45 19t-19 45v384q0 53 37.5 90.5t90.5 37.5h384q53 0 90.5 -37.5t37.5 -90.5zM928 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5
t158.5 -65.5t65.5 -158.5z" />
    <glyph glyph-name="_509" unicode="&#xf21e;" horiz-adv-x="1792" 
d="M1280 512h305q-5 -6 -10 -10.5t-9 -7.5l-3 -4l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-5 2 -21 20h369q22 0 39.5 13.5t22.5 34.5l70 281l190 -667q6 -20 23 -33t39 -13q21 0 38 13t23 33l146 485l56 -112q18 -35 57 -35zM1792 940q0 -145 -103 -300h-369l-111 221
q-8 17 -25.5 27t-36.5 8q-45 -5 -56 -46l-129 -430l-196 686q-6 20 -23.5 33t-39.5 13t-39 -13.5t-22 -34.5l-116 -464h-423q-103 155 -103 300q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124
t127 -344z" />
    <glyph glyph-name="venus" unicode="&#xf221;" horiz-adv-x="1280" 
d="M1152 960q0 -221 -147.5 -384.5t-364.5 -187.5v-260h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v260q-150 16 -271.5 103t-186 224t-52.5 292
q11 134 80.5 249t182 188t245.5 88q170 19 319 -54t236 -212t87 -306zM128 960q0 -185 131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5z" />
    <glyph glyph-name="_511" unicode="&#xf222;" 
d="M1472 1408q26 0 45 -19t19 -45v-416q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v262l-382 -383q126 -156 126 -359q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123t223.5 45.5
q203 0 359 -126l382 382h-261q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h416zM576 0q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
    <glyph glyph-name="_512" unicode="&#xf223;" horiz-adv-x="1280" 
d="M830 1220q145 -72 233.5 -210.5t88.5 -305.5q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-217 24 -364.5 187.5
t-147.5 384.5q0 167 88.5 305.5t233.5 210.5q-165 96 -228 273q-6 16 3.5 29.5t26.5 13.5h69q21 0 29 -20q44 -106 140 -171t214 -65t214 65t140 171q8 20 37 20h61q17 0 26.5 -13.5t3.5 -29.5q-63 -177 -228 -273zM576 256q185 0 316.5 131.5t131.5 316.5t-131.5 316.5
t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
    <glyph glyph-name="_513" unicode="&#xf224;" 
d="M1024 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q126 -158 126 -359q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64
q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-149 16 -270.5 103t-186.5 223.5t-53 291.5q16 204 160 353.5t347 172.5q118 14 228 -19t198 -103l255 254h-134q-14 0 -23 9t-9 23v64zM576 256q185 0 316.5 131.5t131.5 316.5t-131.5 316.5
t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
    <glyph glyph-name="_514" unicode="&#xf225;" horiz-adv-x="1792" 
d="M1280 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q126 -158 126 -359q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64
q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-217 24 -364.5 187.5t-147.5 384.5q0 201 126 359l-52 53l-101 -111q-9 -10 -22 -10.5t-23 7.5l-48 44q-10 8 -10.5 21.5t8.5 23.5l105 115l-111 112v-134q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9
t-9 23v288q0 26 19 45t45 19h288q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-133l106 -107l86 94q9 10 22 10.5t23 -7.5l48 -44q10 -8 10.5 -21.5t-8.5 -23.5l-90 -99l57 -56q158 126 359 126t359 -126l255 254h-134q-14 0 -23 9t-9 23v64zM832 256q185 0 316.5 131.5
t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
    <glyph glyph-name="_515" unicode="&#xf226;" horiz-adv-x="1792" 
d="M1790 1007q12 -155 -52.5 -292t-186 -224t-271.5 -103v-260h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-512v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23
t23 9h224v260q-150 16 -271.5 103t-186 224t-52.5 292q17 206 164.5 356.5t352.5 169.5q206 21 377 -94q171 115 377 94q205 -19 352.5 -169.5t164.5 -356.5zM896 647q128 131 128 313t-128 313q-128 -131 -128 -313t128 -313zM576 512q115 0 218 57q-154 165 -154 391
q0 224 154 391q-103 57 -218 57q-185 0 -316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5zM1152 128v260q-137 15 -256 94q-119 -79 -256 -94v-260h512zM1216 512q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5q-115 0 -218 -57q154 -167 154 -391
q0 -226 -154 -391q103 -57 218 -57z" />
    <glyph glyph-name="_516" unicode="&#xf227;" horiz-adv-x="1920" 
d="M1536 1120q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q76 -95 107.5 -214t9.5 -247q-31 -182 -166 -312t-318 -156q-210 -29 -384.5 80t-241.5 300q-117 6 -221 57.5t-177.5 133t-113.5 192.5t-32 230
q9 135 78 252t182 191.5t248 89.5q118 14 227.5 -19t198.5 -103l255 254h-134q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q59 -74 93 -169q182 -9 328 -124l255 254h-134q-14 0 -23 9
t-9 23v64zM1024 704q0 20 -4 58q-162 -25 -271 -150t-109 -292q0 -20 4 -58q162 25 271 150t109 292zM128 704q0 -168 111 -294t276 -149q-3 29 -3 59q0 210 135 369.5t338 196.5q-53 120 -163.5 193t-245.5 73q-185 0 -316.5 -131.5t-131.5 -316.5zM1088 -128
q185 0 316.5 131.5t131.5 316.5q0 168 -111 294t-276 149q3 -28 3 -59q0 -210 -135 -369.5t-338 -196.5q53 -120 163.5 -193t245.5 -73z" />
    <glyph glyph-name="_517" unicode="&#xf228;" horiz-adv-x="2048" 
d="M1664 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q76 -95 107.5 -214t9.5 -247q-32 -180 -164.5 -310t-313.5 -157q-223 -34 -409 90q-117 -78 -256 -93v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23
t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-155 17 -279.5 109.5t-187 237.5t-39.5 307q25 187 159.5 322.5t320.5 164.5q224 34 410 -90q146 97 320 97q201 0 359 -126l255 254h-134q-14 0 -23 9
t-9 23v64zM896 391q128 131 128 313t-128 313q-128 -131 -128 -313t128 -313zM128 704q0 -185 131.5 -316.5t316.5 -131.5q117 0 218 57q-154 167 -154 391t154 391q-101 57 -218 57q-185 0 -316.5 -131.5t-131.5 -316.5zM1216 256q185 0 316.5 131.5t131.5 316.5
t-131.5 316.5t-316.5 131.5q-117 0 -218 -57q154 -167 154 -391t-154 -391q101 -57 218 -57z" />
    <glyph glyph-name="_518" unicode="&#xf229;" 
d="M1472 1408q26 0 45 -19t19 -45v-416q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v262l-213 -214l140 -140q9 -10 9 -23t-9 -22l-46 -46q-9 -9 -22 -9t-23 9l-140 141l-78 -79q126 -156 126 -359q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5
t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123t223.5 45.5q203 0 359 -126l78 78l-172 172q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l172 -172l213 213h-261q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h416zM576 0q185 0 316.5 131.5t131.5 316.5t-131.5 316.5
t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
    <glyph glyph-name="_519" unicode="&#xf22a;" horiz-adv-x="1280" 
d="M640 892q217 -24 364.5 -187.5t147.5 -384.5q0 -167 -87 -306t-236 -212t-319 -54q-133 15 -245.5 88t-182 188t-80.5 249q-12 155 52.5 292t186 224t271.5 103v132h-160q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h160v165l-92 -92q-10 -9 -23 -9t-22 9l-46 46q-9 9 -9 22
t9 23l202 201q19 19 45 19t45 -19l202 -201q9 -10 9 -23t-9 -22l-46 -46q-9 -9 -22 -9t-23 9l-92 92v-165h160q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-160v-132zM576 -128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5
t131.5 -316.5t316.5 -131.5z" />
    <glyph glyph-name="_520" unicode="&#xf22b;" horiz-adv-x="2048" 
d="M1901 621q19 -19 19 -45t-19 -45l-294 -294q-9 -10 -22.5 -10t-22.5 10l-45 45q-10 9 -10 22.5t10 22.5l185 185h-294v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-132q-24 -217 -187.5 -364.5t-384.5 -147.5q-167 0 -306 87t-212 236t-54 319q15 133 88 245.5
t188 182t249 80.5q155 12 292 -52.5t224 -186t103 -271.5h132v224q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-224h294l-185 185q-10 9 -10 22.5t10 22.5l45 45q9 10 22.5 10t22.5 -10zM576 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5
t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
    <glyph glyph-name="_521" unicode="&#xf22c;" horiz-adv-x="1280" 
d="M1152 960q0 -221 -147.5 -384.5t-364.5 -187.5v-612q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v612q-217 24 -364.5 187.5t-147.5 384.5q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5zM576 512q185 0 316.5 131.5
t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
    <glyph glyph-name="_522" unicode="&#xf22d;" horiz-adv-x="1280" 
d="M1024 576q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1152 576q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123
t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5z" />
    <glyph glyph-name="_523" unicode="&#xf22e;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="_524" unicode="&#xf22f;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="_525" unicode="&#xf230;" 
d="M1451 1408q35 0 60 -25t25 -60v-1366q0 -35 -25 -60t-60 -25h-391v595h199l30 232h-229v148q0 56 23.5 84t91.5 28l122 1v207q-63 9 -178 9q-136 0 -217.5 -80t-81.5 -226v-171h-200v-232h200v-595h-735q-35 0 -60 25t-25 60v1366q0 35 25 60t60 25h1366z" />
    <glyph glyph-name="_526" unicode="&#xf231;" horiz-adv-x="1280" 
d="M0 939q0 108 37.5 203.5t103.5 166.5t152 123t185 78t202 26q158 0 294 -66.5t221 -193.5t85 -287q0 -96 -19 -188t-60 -177t-100 -149.5t-145 -103t-189 -38.5q-68 0 -135 32t-96 88q-10 -39 -28 -112.5t-23.5 -95t-20.5 -71t-26 -71t-32 -62.5t-46 -77.5t-62 -86.5
l-14 -5l-9 10q-15 157 -15 188q0 92 21.5 206.5t66.5 287.5t52 203q-32 65 -32 169q0 83 52 156t132 73q61 0 95 -40.5t34 -102.5q0 -66 -44 -191t-44 -187q0 -63 45 -104.5t109 -41.5q55 0 102 25t78.5 68t56 95t38 110.5t20 111t6.5 99.5q0 173 -109.5 269.5t-285.5 96.5
q-200 0 -334 -129.5t-134 -328.5q0 -44 12.5 -85t27 -65t27 -45.5t12.5 -30.5q0 -28 -15 -73t-37 -45q-2 0 -17 3q-51 15 -90.5 56t-61 94.5t-32.5 108t-11 106.5z" />
    <glyph glyph-name="_527" unicode="&#xf232;" 
d="M985 562q13 0 97.5 -44t89.5 -53q2 -5 2 -15q0 -33 -17 -76q-16 -39 -71 -65.5t-102 -26.5q-57 0 -190 62q-98 45 -170 118t-148 185q-72 107 -71 194v8q3 91 74 158q24 22 52 22q6 0 18 -1.5t19 -1.5q19 0 26.5 -6.5t15.5 -27.5q8 -20 33 -88t25 -75q0 -21 -34.5 -57.5
t-34.5 -46.5q0 -7 5 -15q34 -73 102 -137q56 -53 151 -101q12 -7 22 -7q15 0 54 48.5t52 48.5zM782 32q127 0 243.5 50t200.5 134t134 200.5t50 243.5t-50 243.5t-134 200.5t-200.5 134t-243.5 50t-243.5 -50t-200.5 -134t-134 -200.5t-50 -243.5q0 -203 120 -368l-79 -233
l242 77q158 -104 345 -104zM782 1414q153 0 292.5 -60t240.5 -161t161 -240.5t60 -292.5t-60 -292.5t-161 -240.5t-240.5 -161t-292.5 -60q-195 0 -365 94l-417 -134l136 405q-108 178 -108 389q0 153 60 292.5t161 240.5t240.5 161t292.5 60z" />
    <glyph glyph-name="_528" unicode="&#xf233;" horiz-adv-x="1792" 
d="M128 128h1024v128h-1024v-128zM128 640h1024v128h-1024v-128zM1696 192q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM128 1152h1024v128h-1024v-128zM1696 704q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1696 1216
q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1792 384v-384h-1792v384h1792zM1792 896v-384h-1792v384h1792zM1792 1408v-384h-1792v384h1792z" />
    <glyph glyph-name="_529" unicode="&#xf234;" horiz-adv-x="2048" 
d="M704 640q-159 0 -271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5t-112.5 -271.5t-271.5 -112.5zM1664 512h352q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-352v-352q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5
t-9.5 22.5v352h-352q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h352v352q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5v-352zM928 288q0 -52 38 -90t90 -38h256v-238q-68 -50 -171 -50h-874q-121 0 -194 69t-73 190q0 53 3.5 103.5t14 109t26.5 108.5
t43 97.5t62 81t85.5 53.5t111.5 20q19 0 39 -17q79 -61 154.5 -91.5t164.5 -30.5t164.5 30.5t154.5 91.5q20 17 39 17q132 0 217 -96h-223q-52 0 -90 -38t-38 -90v-192z" />
    <glyph glyph-name="_530" unicode="&#xf235;" horiz-adv-x="2048" 
d="M704 640q-159 0 -271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5t-112.5 -271.5t-271.5 -112.5zM1781 320l249 -249q9 -9 9 -23q0 -13 -9 -22l-136 -136q-9 -9 -22 -9q-14 0 -23 9l-249 249l-249 -249q-9 -9 -23 -9q-13 0 -22 9l-136 136
q-9 9 -9 22q0 14 9 23l249 249l-249 249q-9 9 -9 23q0 13 9 22l136 136q9 9 22 9q14 0 23 -9l249 -249l249 249q9 9 23 9q13 0 22 -9l136 -136q9 -9 9 -22q0 -14 -9 -23zM1283 320l-181 -181q-37 -37 -37 -91q0 -53 37 -90l83 -83q-21 -3 -44 -3h-874q-121 0 -194 69
t-73 190q0 53 3.5 103.5t14 109t26.5 108.5t43 97.5t62 81t85.5 53.5t111.5 20q19 0 39 -17q154 -122 319 -122t319 122q20 17 39 17q28 0 57 -6q-28 -27 -41 -50t-13 -56q0 -54 37 -91z" />
    <glyph glyph-name="_531" unicode="&#xf236;" horiz-adv-x="2048" 
d="M256 512h1728q26 0 45 -19t19 -45v-448h-256v256h-1536v-256h-256v1216q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-704zM832 832q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM2048 576v64q0 159 -112.5 271.5t-271.5 112.5h-704
q-26 0 -45 -19t-19 -45v-384h1152z" />
    <glyph glyph-name="_532" unicode="&#xf237;" 
d="M1536 1536l-192 -448h192v-192h-274l-55 -128h329v-192h-411l-357 -832l-357 832h-411v192h329l-55 128h-274v192h192l-192 448h256l323 -768h378l323 768h256zM768 320l108 256h-216z" />
    <glyph glyph-name="_533" unicode="&#xf238;" 
d="M1088 1536q185 0 316.5 -93.5t131.5 -226.5v-896q0 -130 -125.5 -222t-305.5 -97l213 -202q16 -15 8 -35t-30 -20h-1056q-22 0 -30 20t8 35l213 202q-180 5 -305.5 97t-125.5 222v896q0 133 131.5 226.5t316.5 93.5h640zM768 192q80 0 136 56t56 136t-56 136t-136 56
t-136 -56t-56 -136t56 -136t136 -56zM1344 768v512h-1152v-512h1152z" />
    <glyph glyph-name="_534" unicode="&#xf239;" 
d="M1088 1536q185 0 316.5 -93.5t131.5 -226.5v-896q0 -130 -125.5 -222t-305.5 -97l213 -202q16 -15 8 -35t-30 -20h-1056q-22 0 -30 20t8 35l213 202q-180 5 -305.5 97t-125.5 222v896q0 133 131.5 226.5t316.5 93.5h640zM288 224q66 0 113 47t47 113t-47 113t-113 47
t-113 -47t-47 -113t47 -113t113 -47zM704 768v512h-544v-512h544zM1248 224q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47zM1408 768v512h-576v-512h576z" />
    <glyph glyph-name="_535" unicode="&#xf23a;" horiz-adv-x="1792" 
d="M597 1115v-1173q0 -25 -12.5 -42.5t-36.5 -17.5q-17 0 -33 8l-465 233q-21 10 -35.5 33.5t-14.5 46.5v1140q0 20 10 34t29 14q14 0 44 -15l511 -256q3 -3 3 -5zM661 1014l534 -866l-534 266v600zM1792 996v-1054q0 -25 -14 -40.5t-38 -15.5t-47 13l-441 220zM1789 1116
q0 -3 -256.5 -419.5t-300.5 -487.5l-390 634l324 527q17 28 52 28q14 0 26 -6l541 -270q4 -2 4 -6z" />
    <glyph glyph-name="_536" unicode="&#xf23b;" 
d="M809 532l266 499h-112l-157 -312q-24 -48 -44 -92l-42 92l-155 312h-120l263 -493v-324h101v318zM1536 1408v-1536h-1536v1536h1536z" />
    <glyph glyph-name="_537" unicode="&#xf23c;" horiz-adv-x="2296" 
d="M478 -139q-8 -16 -27 -34.5t-37 -25.5q-25 -9 -51.5 3.5t-28.5 31.5q-1 22 40 55t68 38q23 4 34 -21.5t2 -46.5zM1819 -139q7 -16 26 -34.5t38 -25.5q25 -9 51.5 3.5t27.5 31.5q2 22 -39.5 55t-68.5 38q-22 4 -33 -21.5t-2 -46.5zM1867 -30q13 -27 56.5 -59.5t77.5 -41.5
q45 -13 82 4.5t37 50.5q0 46 -67.5 100.5t-115.5 59.5q-40 5 -63.5 -37.5t-6.5 -76.5zM428 -30q-13 -27 -56 -59.5t-77 -41.5q-45 -13 -82 4.5t-37 50.5q0 46 67.5 100.5t115.5 59.5q40 5 63 -37.5t6 -76.5zM1158 1094h1q-41 0 -76 -15q27 -8 44 -30.5t17 -49.5
q0 -35 -27 -60t-65 -25q-52 0 -80 43q-5 -23 -5 -42q0 -74 56 -126.5t135 -52.5q80 0 136 52.5t56 126.5t-56 126.5t-136 52.5zM1462 1312q-99 109 -220.5 131.5t-245.5 -44.5q27 60 82.5 96.5t118 39.5t121.5 -17t99.5 -74.5t44.5 -131.5zM2212 73q8 -11 -11 -42
q7 -23 7 -40q1 -56 -44.5 -112.5t-109.5 -91.5t-118 -37q-48 -2 -92 21.5t-66 65.5q-687 -25 -1259 0q-23 -41 -66.5 -65t-92.5 -22q-86 3 -179.5 80.5t-92.5 160.5q2 22 7 40q-19 31 -11 42q6 10 31 1q14 22 41 51q-7 29 2 38q11 10 39 -4q29 20 59 34q0 29 13 37
q23 12 51 -16q35 5 61 -2q18 -4 38 -19v73q-11 0 -18 2q-53 10 -97 44.5t-55 87.5q-9 38 0 81q15 62 93 95q2 17 19 35.5t36 23.5t33 -7.5t19 -30.5h13q46 -5 60 -23q3 -3 5 -7q10 1 30.5 3.5t30.5 3.5q-15 11 -30 17q-23 40 -91 43q0 6 1 10q-62 2 -118.5 18.5t-84.5 47.5
q-32 36 -42.5 92t-2.5 112q16 126 90 179q23 16 52 4.5t32 -40.5q0 -1 1.5 -14t2.5 -21t3 -20t5.5 -19t8.5 -10q27 -14 76 -12q48 46 98 74q-40 4 -162 -14l47 46q61 58 163 111q145 73 282 86q-20 8 -41 15.5t-47 14t-42.5 10.5t-47.5 11t-43 10q595 126 904 -139
q98 -84 158 -222q85 -10 121 9h1q5 3 8.5 10t5.5 19t3 19.5t3 21.5l1 14q3 28 32 40t52 -5q73 -52 91 -178q7 -57 -3.5 -113t-42.5 -91q-28 -32 -83.5 -48.5t-115.5 -18.5v-10q-71 -2 -95 -43q-14 -5 -31 -17q11 -1 32 -3.5t30 -3.5q1 5 5 8q16 18 60 23h13q5 18 19 30t33 8
t36 -23t19 -36q79 -32 93 -95q9 -40 1 -81q-12 -53 -56 -88t-97 -44q-10 -2 -17 -2q0 -49 -1 -73q20 15 38 19q26 7 61 2q28 28 51 16q14 -9 14 -37q33 -16 59 -34q27 13 38 4q10 -10 2 -38q28 -30 41 -51q23 8 31 -1zM1937 1025q0 -29 -9 -54q82 -32 112 -132
q4 37 -9.5 98.5t-41.5 90.5q-20 19 -36 17t-16 -20zM1859 925q35 -42 47.5 -108.5t-0.5 -124.5q67 13 97 45q13 14 18 28q-3 64 -31 114.5t-79 66.5q-15 -15 -52 -21zM1822 921q-30 0 -44 1q42 -115 53 -239q21 0 43 3q16 68 1 135t-53 100zM258 839q30 100 112 132
q-9 25 -9 54q0 18 -16.5 20t-35.5 -17q-28 -29 -41.5 -90.5t-9.5 -98.5zM294 737q29 -31 97 -45q-13 58 -0.5 124.5t47.5 108.5v0q-37 6 -52 21q-51 -16 -78.5 -66t-31.5 -115q9 -17 18 -28zM471 683q14 124 73 235q-19 -4 -55 -18l-45 -19v1q-46 -89 -20 -196q25 -3 47 -3z
M1434 644q8 -38 16.5 -108.5t11.5 -89.5q3 -18 9.5 -21.5t23.5 4.5q40 20 62 85.5t23 125.5q-24 2 -146 4zM1152 1285q-116 0 -199 -82.5t-83 -198.5q0 -117 83 -199.5t199 -82.5t199 82.5t83 199.5q0 116 -83 198.5t-199 82.5zM1380 646q-105 2 -211 0v1q-1 -27 2.5 -86
t13.5 -66q29 -14 93.5 -14.5t95.5 10.5q9 3 11 39t-0.5 69.5t-4.5 46.5zM1112 447q8 4 9.5 48t-0.5 88t-4 63v1q-212 -3 -214 -3q-4 -20 -7 -62t0 -83t14 -46q34 -15 101 -16t101 10zM718 636q-16 -59 4.5 -118.5t77.5 -84.5q15 -8 24 -5t12 21q3 16 8 90t10 103
q-69 -2 -136 -6zM591 510q3 -23 -34 -36q132 -141 271.5 -240t305.5 -154q172 49 310.5 146t293.5 250q-33 13 -30 34q0 2 0.5 3.5t1.5 3t1 2.5v1v-1q-17 2 -50 5.5t-48 4.5q-26 -90 -82 -132q-51 -38 -82 1q-5 6 -9 14q-7 13 -17 62q-2 -5 -5 -9t-7.5 -7t-8 -5.5t-9.5 -4
l-10 -2.5t-12 -2l-12 -1.5t-13.5 -1t-13.5 -0.5q-106 -9 -163 11q-4 -17 -10 -26.5t-21 -15t-23 -7t-36 -3.5q-6 -1 -9 -1q-179 -17 -203 40q-2 -63 -56 -54q-47 8 -91 54q-12 13 -20 26q-17 29 -26 65q-58 -6 -87 -10q1 -2 4 -10zM507 -118q3 14 3 30q-17 71 -51 130
t-73 70q-41 12 -101.5 -14.5t-104.5 -80t-39 -107.5q35 -53 100 -93t119 -42q51 -2 94 28t53 79zM510 53q23 -63 27 -119q195 113 392 174q-98 52 -180.5 120t-179.5 165q-6 -4 -29 -13q0 -1 -1 -4t-1 -5q31 -18 22 -37q-12 -23 -56 -34q-10 -13 -29 -24h-1q-2 -83 1 -150
q19 -34 35 -73zM579 -113q532 -21 1145 0q-254 147 -428 196q-76 -35 -156 -57q-8 -3 -16 0q-65 21 -129 49q-208 -60 -416 -188h-1v-1q1 0 1 1zM1763 -67q4 54 28 120q14 38 33 71l-1 -1q3 77 3 153q-15 8 -30 25q-42 9 -56 33q-9 20 22 38q-2 4 -2 9q-16 4 -28 12
q-204 -190 -383 -284q198 -59 414 -176zM2155 -90q5 54 -39 107.5t-104 80t-102 14.5q-38 -11 -72.5 -70.5t-51.5 -129.5q0 -16 3 -30q10 -49 53 -79t94 -28q54 2 119 42t100 93z" />
    <glyph glyph-name="_538" unicode="&#xf23d;" horiz-adv-x="2304" 
d="M1524 -25q0 -68 -48 -116t-116 -48t-116.5 48t-48.5 116t48.5 116.5t116.5 48.5t116 -48.5t48 -116.5zM775 -25q0 -68 -48.5 -116t-116.5 -48t-116 48t-48 116t48 116.5t116 48.5t116.5 -48.5t48.5 -116.5zM0 1469q57 -60 110.5 -104.5t121 -82t136 -63t166 -45.5
t200 -31.5t250 -18.5t304 -9.5t372.5 -2.5q139 0 244.5 -5t181 -16.5t124 -27.5t71 -39.5t24 -51.5t-19.5 -64t-56.5 -76.5t-89.5 -91t-116 -104.5t-139 -119q-185 -157 -286 -247q29 51 76.5 109t94 105.5t94.5 98.5t83 91.5t54 80.5t13 70t-45.5 55.5t-116.5 41t-204 23.5
t-304 5q-168 -2 -314 6t-256 23t-204.5 41t-159.5 51.5t-122.5 62.5t-91.5 66.5t-68 71.5t-50.5 69.5t-40 68t-36.5 59.5z" />
    <glyph glyph-name="_539" unicode="&#xf23e;" horiz-adv-x="1792" 
d="M896 1472q-169 0 -323 -66t-265.5 -177.5t-177.5 -265.5t-66 -323t66 -323t177.5 -265.5t265.5 -177.5t323 -66t323 66t265.5 177.5t177.5 265.5t66 323t-66 323t-177.5 265.5t-265.5 177.5t-323 66zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348
t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM496 704q16 0 16 -16v-480q0 -16 -16 -16h-32q-16 0 -16 16v480q0 16 16 16h32zM896 640q53 0 90.5 -37.5t37.5 -90.5q0 -35 -17.5 -64t-46.5 -46v-114q0 -14 -9 -23
t-23 -9h-64q-14 0 -23 9t-9 23v114q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5zM896 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM544 928v-96
q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v96q0 93 65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5v-96q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v96q0 146 -103 249t-249 103t-249 -103t-103 -249zM1408 192v512q0 26 -19 45t-45 19h-896q-26 0 -45 -19t-19 -45v-512
q0 -26 19 -45t45 -19h896q26 0 45 19t19 45z" />
    <glyph glyph-name="_540" unicode="&#xf240;" horiz-adv-x="2304" 
d="M1920 1024v-768h-1664v768h1664zM2048 448h128v384h-128v288q0 14 -9 23t-23 9h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288zM2304 832v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113
v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160q53 0 90.5 -37.5t37.5 -90.5z" />
    <glyph glyph-name="_541" unicode="&#xf241;" horiz-adv-x="2304" 
d="M256 256v768h1280v-768h-1280zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9
h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
    <glyph glyph-name="_542" unicode="&#xf242;" horiz-adv-x="2304" 
d="M256 256v768h896v-768h-896zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9
h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
    <glyph glyph-name="_543" unicode="&#xf243;" horiz-adv-x="2304" 
d="M256 256v768h512v-768h-512zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9
h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
    <glyph glyph-name="_544" unicode="&#xf244;" horiz-adv-x="2304" 
d="M2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9h-1856q-14 0 -23 -9t-9 -23
v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
    <glyph glyph-name="_545" unicode="&#xf245;" horiz-adv-x="1280" 
d="M1133 493q31 -30 14 -69q-17 -40 -59 -40h-382l201 -476q10 -25 0 -49t-34 -35l-177 -75q-25 -10 -49 0t-35 34l-191 452l-312 -312q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v1504q0 42 40 59q12 5 24 5q27 0 45 -19z" />
    <glyph glyph-name="_546" unicode="&#xf246;" horiz-adv-x="1024" 
d="M832 1408q-320 0 -320 -224v-416h128v-128h-128v-544q0 -224 320 -224h64v-128h-64q-272 0 -384 146q-112 -146 -384 -146h-64v128h64q320 0 320 224v544h-128v128h128v416q0 224 -320 224h-64v128h64q272 0 384 -146q112 146 384 146h64v-128h-64z" />
    <glyph glyph-name="_547" unicode="&#xf247;" horiz-adv-x="2048" 
d="M2048 1152h-128v-1024h128v-384h-384v128h-1280v-128h-384v384h128v1024h-128v384h384v-128h1280v128h384v-384zM1792 1408v-128h128v128h-128zM128 1408v-128h128v128h-128zM256 -128v128h-128v-128h128zM1664 0v128h128v1024h-128v128h-1280v-128h-128v-1024h128v-128
h1280zM1920 -128v128h-128v-128h128zM1280 896h384v-768h-896v256h-384v768h896v-256zM512 512h640v512h-640v-512zM1536 256v512h-256v-384h-384v-128h640z" />
    <glyph glyph-name="_548" unicode="&#xf248;" horiz-adv-x="2304" 
d="M2304 768h-128v-640h128v-384h-384v128h-896v-128h-384v384h128v128h-384v-128h-384v384h128v640h-128v384h384v-128h896v128h384v-384h-128v-128h384v128h384v-384zM2048 1024v-128h128v128h-128zM1408 1408v-128h128v128h-128zM128 1408v-128h128v128h-128zM256 256
v128h-128v-128h128zM1536 384h-128v-128h128v128zM384 384h896v128h128v640h-128v128h-896v-128h-128v-640h128v-128zM896 -128v128h-128v-128h128zM2176 -128v128h-128v-128h128zM2048 128v640h-128v128h-384v-384h128v-384h-384v128h-384v-128h128v-128h896v128h128z" />
    <glyph glyph-name="_549" unicode="&#xf249;" 
d="M1024 288v-416h-928q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1344q40 0 68 -28t28 -68v-928h-416q-40 0 -68 -28t-28 -68zM1152 256h381q-15 -82 -65 -132l-184 -184q-50 -50 -132 -65v381z" />
    <glyph glyph-name="_550" unicode="&#xf24a;" 
d="M1400 256h-248v-248q29 10 41 22l185 185q12 12 22 41zM1120 384h288v896h-1280v-1280h896v288q0 40 28 68t68 28zM1536 1312v-1024q0 -40 -20 -88t-48 -76l-184 -184q-28 -28 -76 -48t-88 -20h-1024q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1344q40 0 68 -28t28 -68
z" />
    <glyph glyph-name="_551" unicode="&#xf24b;" horiz-adv-x="2304" 
d="M1951 538q0 -26 -15.5 -44.5t-38.5 -23.5q-8 -2 -18 -2h-153v140h153q10 0 18 -2q23 -5 38.5 -23.5t15.5 -44.5zM1933 751q0 -25 -15 -42t-38 -21q-3 -1 -15 -1h-139v129h139q3 0 8.5 -0.5t6.5 -0.5q23 -4 38 -21.5t15 -42.5zM728 587v308h-228v-308q0 -58 -38 -94.5
t-105 -36.5q-108 0 -229 59v-112q53 -15 121 -23t109 -9l42 -1q328 0 328 217zM1442 403v113q-99 -52 -200 -59q-108 -8 -169 41t-61 142t61 142t169 41q101 -7 200 -58v112q-48 12 -100 19.5t-80 9.5l-28 2q-127 6 -218.5 -14t-140.5 -60t-71 -88t-22 -106t22 -106t71 -88
t140.5 -60t218.5 -14q101 4 208 31zM2176 518q0 54 -43 88.5t-109 39.5v3q57 8 89 41.5t32 79.5q0 55 -41 88t-107 36q-3 0 -12 0.5t-14 0.5h-455v-510h491q74 0 121.5 36.5t47.5 96.5zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90
t90 38h2048q52 0 90 -38t38 -90z" />
    <glyph glyph-name="_552" unicode="&#xf24c;" horiz-adv-x="2304" 
d="M858 295v693q-106 -41 -172 -135.5t-66 -211.5t66 -211.5t172 -134.5zM1362 641q0 117 -66 211.5t-172 135.5v-694q106 41 172 135.5t66 211.5zM1577 641q0 -159 -78.5 -294t-213.5 -213.5t-294 -78.5q-119 0 -227.5 46.5t-187 125t-125 187t-46.5 227.5q0 159 78.5 294
t213.5 213.5t294 78.5t294 -78.5t213.5 -213.5t78.5 -294zM1960 634q0 139 -55.5 261.5t-147.5 205.5t-213.5 131t-252.5 48h-301q-176 0 -323.5 -81t-235 -230t-87.5 -335q0 -171 87 -317.5t236 -231.5t323 -85h301q129 0 251.5 50.5t214.5 135t147.5 202.5t55.5 246z
M2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
    <glyph glyph-name="_553" unicode="&#xf24d;" horiz-adv-x="1792" 
d="M1664 -96v1088q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5v-1088q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5zM1792 992v-1088q0 -66 -47 -113t-113 -47h-1088q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1088q66 0 113 -47t47 -113
zM1408 1376v-160h-128v160q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5v-1088q0 -13 9.5 -22.5t22.5 -9.5h160v-128h-160q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1088q66 0 113 -47t47 -113z" />
    <glyph glyph-name="_554" unicode="&#xf24e;" horiz-adv-x="2304" 
d="M1728 1088l-384 -704h768zM448 1088l-384 -704h768zM1269 1280q-14 -40 -45.5 -71.5t-71.5 -45.5v-1291h608q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1344q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h608v1291q-40 14 -71.5 45.5t-45.5 71.5h-491q-14 0 -23 9t-9 23v64
q0 14 9 23t23 9h491q21 57 70 92.5t111 35.5t111 -35.5t70 -92.5h491q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-491zM1088 1264q33 0 56.5 23.5t23.5 56.5t-23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t23.5 -56.5t56.5 -23.5zM2176 384q0 -73 -46.5 -131t-117.5 -91
t-144.5 -49.5t-139.5 -16.5t-139.5 16.5t-144.5 49.5t-117.5 91t-46.5 131q0 11 35 81t92 174.5t107 195.5t102 184t56 100q18 33 56 33t56 -33q4 -7 56 -100t102 -184t107 -195.5t92 -174.5t35 -81zM896 384q0 -73 -46.5 -131t-117.5 -91t-144.5 -49.5t-139.5 -16.5
t-139.5 16.5t-144.5 49.5t-117.5 91t-46.5 131q0 11 35 81t92 174.5t107 195.5t102 184t56 100q18 33 56 33t56 -33q4 -7 56 -100t102 -184t107 -195.5t92 -174.5t35 -81z" />
    <glyph glyph-name="_555" unicode="&#xf250;" 
d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9
t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM874 700q77 29 149 92.5t129.5 152.5t92.5 210t35 253h-1024q0 -132 35 -253t92.5 -210t129.5 -152.5t149 -92.5q19 -7 30.5 -23.5t11.5 -36.5t-11.5 -36.5t-30.5 -23.5q-77 -29 -149 -92.5
t-129.5 -152.5t-92.5 -210t-35 -253h1024q0 132 -35 253t-92.5 210t-129.5 152.5t-149 92.5q-19 7 -30.5 23.5t-11.5 36.5t11.5 36.5t30.5 23.5z" />
    <glyph glyph-name="_556" unicode="&#xf251;" 
d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9
t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM1280 1408h-1024q0 -66 9 -128h1006q9 61 9 128zM1280 -128q0 130 -34 249.5t-90.5 208t-126.5 152t-146 94.5h-230q-76 -31 -146 -94.5t-126.5 -152t-90.5 -208t-34 -249.5h1024z" />
    <glyph glyph-name="_557" unicode="&#xf252;" 
d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9
t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM1280 1408h-1024q0 -206 85 -384h854q85 178 85 384zM1223 192q-54 141 -145.5 241.5t-194.5 142.5h-230q-103 -42 -194.5 -142.5t-145.5 -241.5h910z" />
    <glyph glyph-name="_558" unicode="&#xf253;" 
d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9
t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM874 700q77 29 149 92.5t129.5 152.5t92.5 210t35 253h-1024q0 -132 35 -253t92.5 -210t129.5 -152.5t149 -92.5q19 -7 30.5 -23.5t11.5 -36.5t-11.5 -36.5t-30.5 -23.5q-137 -51 -244 -196
h700q-107 145 -244 196q-19 7 -30.5 23.5t-11.5 36.5t11.5 36.5t30.5 23.5z" />
    <glyph glyph-name="_559" unicode="&#xf254;" 
d="M1504 -64q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v128q0 14 9 23t23 9h1472zM130 0q3 55 16 107t30 95t46 87t53.5 76t64.5 69.5t66 60t70.5 55t66.5 47.5t65 43q-43 28 -65 43t-66.5 47.5t-70.5 55t-66 60t-64.5 69.5t-53.5 76t-46 87
t-30 95t-16 107h1276q-3 -55 -16 -107t-30 -95t-46 -87t-53.5 -76t-64.5 -69.5t-66 -60t-70.5 -55t-66.5 -47.5t-65 -43q43 -28 65 -43t66.5 -47.5t70.5 -55t66 -60t64.5 -69.5t53.5 -76t46 -87t30 -95t16 -107h-1276zM1504 1536q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9
h-1472q-14 0 -23 9t-9 23v128q0 14 9 23t23 9h1472z" />
    <glyph glyph-name="_560" unicode="&#xf255;" 
d="M768 1152q-53 0 -90.5 -37.5t-37.5 -90.5v-128h-32v93q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-429l-32 30v172q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-224q0 -47 35 -82l310 -296q39 -39 39 -102q0 -26 19 -45t45 -19h640q26 0 45 19t19 45v25
q0 41 10 77l108 436q10 36 10 77v246q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-32h-32v125q0 40 -25 72.5t-64 40.5q-14 2 -23 2q-46 0 -79 -33t-33 -79v-128h-32v122q0 51 -32.5 89.5t-82.5 43.5q-5 1 -13 1zM768 1280q84 0 149 -50q57 34 123 34q59 0 111 -27
t86 -76q27 7 59 7q100 0 170 -71.5t70 -171.5v-246q0 -51 -13 -108l-109 -436q-6 -24 -6 -71q0 -80 -56 -136t-136 -56h-640q-84 0 -138 58.5t-54 142.5l-308 296q-76 73 -76 175v224q0 99 70.5 169.5t169.5 70.5q11 0 16 -1q6 95 75.5 160t164.5 65q52 0 98 -21
q72 69 174 69z" />
    <glyph glyph-name="_561" unicode="&#xf256;" horiz-adv-x="1792" 
d="M880 1408q-46 0 -79 -33t-33 -79v-656h-32v528q0 46 -33 79t-79 33t-79 -33t-33 -79v-528v-256l-154 205q-38 51 -102 51q-53 0 -90.5 -37.5t-37.5 -90.5q0 -43 26 -77l384 -512q38 -51 102 -51h688q34 0 61 22t34 56l76 405q5 32 5 59v498q0 46 -33 79t-79 33t-79 -33
t-33 -79v-272h-32v528q0 46 -33 79t-79 33t-79 -33t-33 -79v-528h-32v656q0 46 -33 79t-79 33zM880 1536q68 0 125.5 -35.5t88.5 -96.5q19 4 42 4q99 0 169.5 -70.5t70.5 -169.5v-17q105 6 180.5 -64t75.5 -175v-498q0 -40 -8 -83l-76 -404q-14 -79 -76.5 -131t-143.5 -52
h-688q-60 0 -114.5 27.5t-90.5 74.5l-384 512q-51 68 -51 154q0 106 75 181t181 75q78 0 128 -34v434q0 99 70.5 169.5t169.5 70.5q23 0 42 -4q31 61 88.5 96.5t125.5 35.5z" />
    <glyph glyph-name="_562" unicode="&#xf257;" horiz-adv-x="1792" 
d="M1073 -128h-177q-163 0 -226 141q-23 49 -23 102v5q-62 30 -98.5 88.5t-36.5 127.5q0 38 5 48h-261q-106 0 -181 75t-75 181t75 181t181 75h113l-44 17q-74 28 -119.5 93.5t-45.5 145.5q0 106 75 181t181 75q46 0 91 -17l628 -239h401q106 0 181 -75t75 -181v-668
q0 -88 -54 -157.5t-140 -90.5l-339 -85q-92 -23 -186 -23zM1024 583l-155 -71l-163 -74q-30 -14 -48 -41.5t-18 -60.5q0 -46 33 -79t79 -33q26 0 46 10l338 154q-49 10 -80.5 50t-31.5 90v55zM1344 272q0 46 -33 79t-79 33q-26 0 -46 -10l-290 -132q-28 -13 -37 -17
t-30.5 -17t-29.5 -23.5t-16 -29t-8 -40.5q0 -50 31.5 -82t81.5 -32q20 0 38 9l352 160q30 14 48 41.5t18 60.5zM1112 1024l-650 248q-24 8 -46 8q-53 0 -90.5 -37.5t-37.5 -90.5q0 -40 22.5 -73t59.5 -47l526 -200v-64h-640q-53 0 -90.5 -37.5t-37.5 -90.5t37.5 -90.5
t90.5 -37.5h535l233 106v198q0 63 46 106l111 102h-69zM1073 0q82 0 155 19l339 85q43 11 70 45.5t27 78.5v668q0 53 -37.5 90.5t-90.5 37.5h-308l-136 -126q-36 -33 -36 -82v-296q0 -46 33 -77t79 -31t79 35t33 81v208h32v-208q0 -70 -57 -114q52 -8 86.5 -48.5t34.5 -93.5
q0 -42 -23 -78t-61 -53l-310 -141h91z" />
    <glyph glyph-name="_563" unicode="&#xf258;" horiz-adv-x="2048" 
d="M1151 1536q61 0 116 -28t91 -77l572 -781q118 -159 118 -359v-355q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v177l-286 143h-546q-80 0 -136 56t-56 136v32q0 119 84.5 203.5t203.5 84.5h420l42 128h-686q-100 0 -173.5 67.5t-81.5 166.5q-65 79 -65 182v32
q0 80 56 136t136 56h959zM1920 -64v355q0 157 -93 284l-573 781q-39 52 -103 52h-959q-26 0 -45 -19t-19 -45q0 -32 1.5 -49.5t9.5 -40.5t25 -43q10 31 35.5 50t56.5 19h832v-32h-832q-26 0 -45 -19t-19 -45q0 -44 3 -58q8 -44 44 -73t81 -29h640h91q40 0 68 -28t28 -68
q0 -15 -5 -30l-64 -192q-10 -29 -35 -47.5t-56 -18.5h-443q-66 0 -113 -47t-47 -113v-32q0 -26 19 -45t45 -19h561q16 0 29 -7l317 -158q24 -13 38.5 -36t14.5 -50v-197q0 -26 19 -45t45 -19h384q26 0 45 19t19 45z" />
    <glyph glyph-name="_564" unicode="&#xf259;" horiz-adv-x="2048" 
d="M459 -256q-77 0 -137.5 47.5t-79.5 122.5l-101 401q-13 57 -13 108q0 45 -5 67l-116 477q-7 27 -7 57q0 93 62 161t155 78q17 85 82.5 139t152.5 54q83 0 148 -51.5t85 -132.5l83 -348l103 428q20 81 85 132.5t148 51.5q89 0 155.5 -57.5t80.5 -144.5q92 -10 152 -79
t60 -162q0 -24 -7 -59l-123 -512q10 7 37.5 28.5t38.5 29.5t35 23t41 20.5t41.5 11t49.5 5.5q105 0 180 -74t75 -179q0 -62 -28.5 -118t-78.5 -94l-507 -380q-68 -51 -153 -51h-694zM1104 1408q-38 0 -68.5 -24t-39.5 -62l-164 -682h-127l-145 602q-9 38 -39.5 62t-68.5 24
q-48 0 -80 -33t-32 -80q0 -15 3 -28l132 -547h-26l-99 408q-9 37 -40 62.5t-69 25.5q-47 0 -80 -33t-33 -79q0 -14 3 -26l116 -478q7 -28 9 -86t10 -88l100 -401q8 -32 34 -52.5t59 -20.5h694q42 0 76 26l507 379q56 43 56 110q0 52 -37.5 88.5t-89.5 36.5q-43 0 -77 -26
l-307 -230v227q0 4 32 138t68 282t39 161q4 18 4 29q0 47 -32 81t-79 34q-39 0 -69.5 -24t-39.5 -62l-116 -482h-26l150 624q3 14 3 28q0 48 -31.5 82t-79.5 34z" />
    <glyph glyph-name="_565" unicode="&#xf25a;" horiz-adv-x="1792" 
d="M640 1408q-53 0 -90.5 -37.5t-37.5 -90.5v-512v-384l-151 202q-41 54 -107 54q-52 0 -89 -38t-37 -90q0 -43 26 -77l384 -512q38 -51 102 -51h718q22 0 39.5 13.5t22.5 34.5l92 368q24 96 24 194v217q0 41 -28 71t-68 30t-68 -28t-28 -68h-32v61q0 48 -32 81.5t-80 33.5
q-46 0 -79 -33t-33 -79v-64h-32v90q0 55 -37 94.5t-91 39.5q-53 0 -90.5 -37.5t-37.5 -90.5v-96h-32v570q0 55 -37 94.5t-91 39.5zM640 1536q107 0 181.5 -77.5t74.5 -184.5v-220q22 2 32 2q99 0 173 -69q47 21 99 21q113 0 184 -87q27 7 56 7q94 0 159 -67.5t65 -161.5
v-217q0 -116 -28 -225l-92 -368q-16 -64 -68 -104.5t-118 -40.5h-718q-60 0 -114.5 27.5t-90.5 74.5l-384 512q-51 68 -51 154q0 105 74.5 180.5t179.5 75.5q71 0 130 -35v547q0 106 75 181t181 75zM768 128v384h-32v-384h32zM1024 128v384h-32v-384h32zM1280 128v384h-32
v-384h32z" />
    <glyph glyph-name="_566" unicode="&#xf25b;" 
d="M1288 889q60 0 107 -23q141 -63 141 -226v-177q0 -94 -23 -186l-85 -339q-21 -86 -90.5 -140t-157.5 -54h-668q-106 0 -181 75t-75 181v401l-239 628q-17 45 -17 91q0 106 75 181t181 75q80 0 145.5 -45.5t93.5 -119.5l17 -44v113q0 106 75 181t181 75t181 -75t75 -181
v-261q27 5 48 5q69 0 127.5 -36.5t88.5 -98.5zM1072 896q-33 0 -60.5 -18t-41.5 -48l-74 -163l-71 -155h55q50 0 90 -31.5t50 -80.5l154 338q10 20 10 46q0 46 -33 79t-79 33zM1293 761q-22 0 -40.5 -8t-29 -16t-23.5 -29.5t-17 -30.5t-17 -37l-132 -290q-10 -20 -10 -46
q0 -46 33 -79t79 -33q33 0 60.5 18t41.5 48l160 352q9 18 9 38q0 50 -32 81.5t-82 31.5zM128 1120q0 -22 8 -46l248 -650v-69l102 111q43 46 106 46h198l106 233v535q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5v-640h-64l-200 526q-14 37 -47 59.5t-73 22.5
q-53 0 -90.5 -37.5t-37.5 -90.5zM1180 -128q44 0 78.5 27t45.5 70l85 339q19 73 19 155v91l-141 -310q-17 -38 -53 -61t-78 -23q-53 0 -93.5 34.5t-48.5 86.5q-44 -57 -114 -57h-208v32h208q46 0 81 33t35 79t-31 79t-77 33h-296q-49 0 -82 -36l-126 -136v-308
q0 -53 37.5 -90.5t90.5 -37.5h668z" />
    <glyph glyph-name="_567" unicode="&#xf25c;" horiz-adv-x="1973" 
d="M857 992v-117q0 -13 -9.5 -22t-22.5 -9h-298v-812q0 -13 -9 -22.5t-22 -9.5h-135q-13 0 -22.5 9t-9.5 23v812h-297q-13 0 -22.5 9t-9.5 22v117q0 14 9 23t23 9h793q13 0 22.5 -9.5t9.5 -22.5zM1895 995l77 -961q1 -13 -8 -24q-10 -10 -23 -10h-134q-12 0 -21 8.5
t-10 20.5l-46 588l-189 -425q-8 -19 -29 -19h-120q-20 0 -29 19l-188 427l-45 -590q-1 -12 -10 -20.5t-21 -8.5h-135q-13 0 -23 10q-9 10 -9 24l78 961q1 12 10 20.5t21 8.5h142q20 0 29 -19l220 -520q10 -24 20 -51q3 7 9.5 24.5t10.5 26.5l221 520q9 19 29 19h141
q13 0 22 -8.5t10 -20.5z" />
    <glyph glyph-name="_568" unicode="&#xf25d;" horiz-adv-x="1792" 
d="M1042 833q0 88 -60 121q-33 18 -117 18h-123v-281h162q66 0 102 37t36 105zM1094 548l205 -373q8 -17 -1 -31q-8 -16 -27 -16h-152q-20 0 -28 17l-194 365h-155v-350q0 -14 -9 -23t-23 -9h-134q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h294q128 0 190 -24q85 -31 134 -109
t49 -180q0 -92 -42.5 -165.5t-115.5 -109.5q6 -10 9 -16zM896 1376q-150 0 -286 -58.5t-234.5 -157t-157 -234.5t-58.5 -286t58.5 -286t157 -234.5t234.5 -157t286 -58.5t286 58.5t234.5 157t157 234.5t58.5 286t-58.5 286t-157 234.5t-234.5 157t-286 58.5zM1792 640
q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
    <glyph glyph-name="_569" unicode="&#xf25e;" horiz-adv-x="1792" 
d="M605 303q153 0 257 104q14 18 3 36l-45 82q-6 13 -24 17q-16 2 -27 -11l-4 -3q-4 -4 -11.5 -10t-17.5 -13.5t-23.5 -14.5t-28.5 -13t-33.5 -9.5t-37.5 -3.5q-76 0 -125 50t-49 127q0 76 48 125.5t122 49.5q37 0 71.5 -14t50.5 -28l16 -14q11 -11 26 -10q16 2 24 14l53 78
q13 20 -2 39q-3 4 -11 12t-30 23.5t-48.5 28t-67.5 22.5t-86 10q-148 0 -246 -96.5t-98 -240.5q0 -146 97 -241.5t247 -95.5zM1235 303q153 0 257 104q14 18 4 36l-45 82q-8 14 -25 17q-16 2 -27 -11l-4 -3q-4 -4 -11.5 -10t-17.5 -13.5t-23.5 -14.5t-28.5 -13t-33.5 -9.5
t-37.5 -3.5q-76 0 -125 50t-49 127q0 76 48 125.5t122 49.5q37 0 71.5 -14t50.5 -28l16 -14q11 -11 26 -10q16 2 24 14l53 78q13 20 -2 39q-3 4 -11 12t-30 23.5t-48.5 28t-67.5 22.5t-86 10q-147 0 -245.5 -96.5t-98.5 -240.5q0 -146 97 -241.5t247 -95.5zM896 1376
q-150 0 -286 -58.5t-234.5 -157t-157 -234.5t-58.5 -286t58.5 -286t157 -234.5t234.5 -157t286 -58.5t286 58.5t234.5 157t157 234.5t58.5 286t-58.5 286t-157 234.5t-234.5 157t-286 58.5zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191
t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71z" />
    <glyph glyph-name="f260" unicode="&#xf260;" horiz-adv-x="2048" 
d="M736 736l384 -384l-384 -384l-672 672l672 672l168 -168l-96 -96l-72 72l-480 -480l480 -480l193 193l-289 287zM1312 1312l672 -672l-672 -672l-168 168l96 96l72 -72l480 480l-480 480l-193 -193l289 -287l-96 -96l-384 384z" />
    <glyph glyph-name="f261" unicode="&#xf261;" horiz-adv-x="1792" 
d="M717 182l271 271l-279 279l-88 -88l192 -191l-96 -96l-279 279l279 279l40 -40l87 87l-127 128l-454 -454zM1075 190l454 454l-454 454l-271 -271l279 -279l88 88l-192 191l96 96l279 -279l-279 -279l-40 40l-87 -88zM1792 640q0 -182 -71 -348t-191 -286t-286 -191
t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
    <glyph glyph-name="_572" unicode="&#xf262;" horiz-adv-x="2304" 
d="M651 539q0 -39 -27.5 -66.5t-65.5 -27.5q-39 0 -66.5 27.5t-27.5 66.5q0 38 27.5 65.5t66.5 27.5q38 0 65.5 -27.5t27.5 -65.5zM1805 540q0 -39 -27.5 -66.5t-66.5 -27.5t-66.5 27.5t-27.5 66.5t27.5 66t66.5 27t66.5 -27t27.5 -66zM765 539q0 79 -56.5 136t-136.5 57
t-136.5 -56.5t-56.5 -136.5t56.5 -136.5t136.5 -56.5t136.5 56.5t56.5 136.5zM1918 540q0 80 -56.5 136.5t-136.5 56.5q-79 0 -136 -56.5t-57 -136.5t56.5 -136.5t136.5 -56.5t136.5 56.5t56.5 136.5zM850 539q0 -116 -81.5 -197.5t-196.5 -81.5q-116 0 -197.5 82t-81.5 197
t82 196.5t197 81.5t196.5 -81.5t81.5 -196.5zM2004 540q0 -115 -81.5 -196.5t-197.5 -81.5q-115 0 -196.5 81.5t-81.5 196.5t81.5 196.5t196.5 81.5q116 0 197.5 -81.5t81.5 -196.5zM1040 537q0 191 -135.5 326.5t-326.5 135.5q-125 0 -231 -62t-168 -168.5t-62 -231.5
t62 -231.5t168 -168.5t231 -62q191 0 326.5 135.5t135.5 326.5zM1708 1110q-254 111 -556 111q-319 0 -573 -110q117 0 223 -45.5t182.5 -122.5t122 -183t45.5 -223q0 115 43.5 219.5t118 180.5t177.5 123t217 50zM2187 537q0 191 -135 326.5t-326 135.5t-326.5 -135.5
t-135.5 -326.5t135.5 -326.5t326.5 -135.5t326 135.5t135 326.5zM1921 1103h383q-44 -51 -75 -114.5t-40 -114.5q110 -151 110 -337q0 -156 -77 -288t-209 -208.5t-287 -76.5q-133 0 -249 56t-196 155q-47 -56 -129 -179q-11 22 -53.5 82.5t-74.5 97.5
q-80 -99 -196.5 -155.5t-249.5 -56.5q-155 0 -287 76.5t-209 208.5t-77 288q0 186 110 337q-9 51 -40 114.5t-75 114.5h365q149 100 355 156.5t432 56.5q224 0 421 -56t348 -157z" />
    <glyph glyph-name="f263" unicode="&#xf263;" horiz-adv-x="1280" 
d="M640 629q-188 0 -321 133t-133 320q0 188 133 321t321 133t321 -133t133 -321q0 -187 -133 -320t-321 -133zM640 1306q-92 0 -157.5 -65.5t-65.5 -158.5q0 -92 65.5 -157.5t157.5 -65.5t157.5 65.5t65.5 157.5q0 93 -65.5 158.5t-157.5 65.5zM1163 574q13 -27 15 -49.5
t-4.5 -40.5t-26.5 -38.5t-42.5 -37t-61.5 -41.5q-115 -73 -315 -94l73 -72l267 -267q30 -31 30 -74t-30 -73l-12 -13q-31 -30 -74 -30t-74 30q-67 68 -267 268l-267 -268q-31 -30 -74 -30t-73 30l-12 13q-31 30 -31 73t31 74l267 267l72 72q-203 21 -317 94
q-39 25 -61.5 41.5t-42.5 37t-26.5 38.5t-4.5 40.5t15 49.5q10 20 28 35t42 22t56 -2t65 -35q5 -4 15 -11t43 -24.5t69 -30.5t92 -24t113 -11q91 0 174 25.5t120 50.5l38 25q33 26 65 35t56 2t42 -22t28 -35z" />
    <glyph glyph-name="_574" unicode="&#xf264;" 
d="M927 956q0 -66 -46.5 -112.5t-112.5 -46.5t-112.5 46.5t-46.5 112.5t46.5 112.5t112.5 46.5t112.5 -46.5t46.5 -112.5zM1141 593q-10 20 -28 32t-47.5 9.5t-60.5 -27.5q-10 -8 -29 -20t-81 -32t-127 -20t-124 18t-86 36l-27 18q-31 25 -60.5 27.5t-47.5 -9.5t-28 -32
q-22 -45 -2 -74.5t87 -73.5q83 -53 226 -67l-51 -52q-142 -142 -191 -190q-22 -22 -22 -52.5t22 -52.5l9 -9q22 -22 52.5 -22t52.5 22l191 191q114 -115 191 -191q22 -22 52.5 -22t52.5 22l9 9q22 22 22 52.5t-22 52.5l-191 190l-52 52q141 14 225 67q67 44 87 73.5t-2 74.5
zM1092 956q0 134 -95 229t-229 95t-229 -95t-95 -229t95 -229t229 -95t229 95t95 229zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="_575" unicode="&#xf265;" horiz-adv-x="1720" 
d="M1565 1408q65 0 110 -45.5t45 -110.5v-519q0 -176 -68 -336t-182.5 -275t-274 -182.5t-334.5 -67.5q-176 0 -335.5 67.5t-274.5 182.5t-183 275t-68 336v519q0 64 46 110t110 46h1409zM861 344q47 0 82 33l404 388q37 35 37 85q0 49 -34.5 83.5t-83.5 34.5q-47 0 -82 -33
l-323 -310l-323 310q-35 33 -81 33q-49 0 -83.5 -34.5t-34.5 -83.5q0 -51 36 -85l405 -388q33 -33 81 -33z" />
    <glyph glyph-name="_576" unicode="&#xf266;" horiz-adv-x="2304" 
d="M1494 -103l-295 695q-25 -49 -158.5 -305.5t-198.5 -389.5q-1 -1 -27.5 -0.5t-26.5 1.5q-82 193 -255.5 587t-259.5 596q-21 50 -66.5 107.5t-103.5 100.5t-102 43q0 5 -0.5 24t-0.5 27h583v-50q-39 -2 -79.5 -16t-66.5 -43t-10 -64q26 -59 216.5 -499t235.5 -540
q31 61 140 266.5t131 247.5q-19 39 -126 281t-136 295q-38 69 -201 71v50l513 -1v-47q-60 -2 -93.5 -25t-12.5 -69q33 -70 87 -189.5t86 -187.5q110 214 173 363q24 55 -10 79.5t-129 26.5q1 7 1 25v24q64 0 170.5 0.5t180 1t92.5 0.5v-49q-62 -2 -119 -33t-90 -81
l-213 -442q13 -33 127.5 -290t121.5 -274l441 1017q-14 38 -49.5 62.5t-65 31.5t-55.5 8v50l460 -4l1 -2l-1 -44q-139 -4 -201 -145q-526 -1216 -559 -1291h-49z" />
    <glyph glyph-name="_577" unicode="&#xf267;" horiz-adv-x="1792" 
d="M949 643q0 -26 -16.5 -45t-41.5 -19q-26 0 -45 16.5t-19 41.5q0 26 17 45t42 19t44 -16.5t19 -41.5zM964 585l350 581q-9 -8 -67.5 -62.5t-125.5 -116.5t-136.5 -127t-117 -110.5t-50.5 -51.5l-349 -580q7 7 67 62t126 116.5t136 127t117 111t50 50.5zM1611 640
q0 -201 -104 -371q-3 2 -17 11t-26.5 16.5t-16.5 7.5q-13 0 -13 -13q0 -10 59 -44q-74 -112 -184.5 -190.5t-241.5 -110.5l-16 67q-1 10 -15 10q-5 0 -8 -5.5t-2 -9.5l16 -68q-72 -15 -146 -15q-199 0 -372 105q1 2 13 20.5t21.5 33.5t9.5 19q0 13 -13 13q-6 0 -17 -14.5
t-22.5 -34.5t-13.5 -23q-113 75 -192 187.5t-110 244.5l69 15q10 3 10 15q0 5 -5.5 8t-10.5 2l-68 -15q-14 72 -14 139q0 206 109 379q2 -1 18.5 -12t30 -19t17.5 -8q13 0 13 12q0 6 -12.5 15.5t-32.5 21.5l-20 12q77 112 189 189t244 107l15 -67q2 -10 15 -10q5 0 8 5.5
t2 10.5l-15 66q71 13 134 13q204 0 379 -109q-39 -56 -39 -65q0 -13 12 -13q11 0 48 64q111 -75 187.5 -186t107.5 -241l-56 -12q-10 -2 -10 -16q0 -5 5.5 -8t9.5 -2l57 13q14 -72 14 -140zM1696 640q0 163 -63.5 311t-170.5 255t-255 170.5t-311 63.5t-311 -63.5
t-255 -170.5t-170.5 -255t-63.5 -311t63.5 -311t170.5 -255t255 -170.5t311 -63.5t311 63.5t255 170.5t170.5 255t63.5 311zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191
t191 -286t71 -348z" />
    <glyph glyph-name="_578" unicode="&#xf268;" horiz-adv-x="1792" 
d="M893 1536q240 2 451 -120q232 -134 352 -372l-742 39q-160 9 -294 -74.5t-185 -229.5l-276 424q128 159 311 245.5t383 87.5zM146 1131l337 -663q72 -143 211 -217t293 -45l-230 -451q-212 33 -385 157.5t-272.5 316t-99.5 411.5q0 267 146 491zM1732 962
q58 -150 59.5 -310.5t-48.5 -306t-153 -272t-246 -209.5q-230 -133 -498 -119l405 623q88 131 82.5 290.5t-106.5 277.5zM896 942q125 0 213.5 -88.5t88.5 -213.5t-88.5 -213.5t-213.5 -88.5t-213.5 88.5t-88.5 213.5t88.5 213.5t213.5 88.5z" />
    <glyph glyph-name="_579" unicode="&#xf269;" horiz-adv-x="1792" 
d="M903 -256q-283 0 -504.5 150.5t-329.5 398.5q-58 131 -67 301t26 332.5t111 312t179 242.5l-11 -281q11 14 68 15.5t70 -15.5q42 81 160.5 138t234.5 59q-54 -45 -119.5 -148.5t-58.5 -163.5q25 -8 62.5 -13.5t63 -7.5t68 -4t50.5 -3q15 -5 9.5 -45.5t-30.5 -75.5
q-5 -7 -16.5 -18.5t-56.5 -35.5t-101 -34l15 -189l-139 67q-18 -43 -7.5 -81.5t36 -66.5t65.5 -41.5t81 -6.5q51 9 98 34.5t83.5 45t73.5 17.5q61 -4 89.5 -33t19.5 -65q-1 -2 -2.5 -5.5t-8.5 -12.5t-18 -15.5t-31.5 -10.5t-46.5 -1q-60 -95 -144.5 -135.5t-209.5 -29.5
q74 -61 162.5 -82.5t168.5 -6t154.5 52t128 87.5t80.5 104q43 91 39 192.5t-37.5 188.5t-78.5 125q87 -38 137 -79.5t77 -112.5q15 170 -57.5 343t-209.5 284q265 -77 412 -279.5t151 -517.5q2 -127 -40.5 -255t-123.5 -238t-189 -196t-247.5 -135.5t-288.5 -49.5z" />
    <glyph glyph-name="_580" unicode="&#xf26a;" horiz-adv-x="1792" 
d="M1493 1308q-165 110 -359 110q-155 0 -293 -73t-240 -200q-75 -93 -119.5 -218t-48.5 -266v-42q4 -141 48.5 -266t119.5 -218q102 -127 240 -200t293 -73q194 0 359 110q-121 -108 -274.5 -168t-322.5 -60q-29 0 -43 1q-175 8 -333 82t-272 193t-181 281t-67 339
q0 182 71 348t191 286t286 191t348 71h3q168 -1 320.5 -60.5t273.5 -167.5zM1792 640q0 -192 -77 -362.5t-213 -296.5q-104 -63 -222 -63q-137 0 -255 84q154 56 253.5 233t99.5 405q0 227 -99 404t-253 234q119 83 254 83q119 0 226 -65q135 -125 210.5 -295t75.5 -361z
" />
    <glyph glyph-name="_581" unicode="&#xf26b;" horiz-adv-x="1792" 
d="M1792 599q0 -56 -7 -104h-1151q0 -146 109.5 -244.5t257.5 -98.5q99 0 185.5 46.5t136.5 130.5h423q-56 -159 -170.5 -281t-267.5 -188.5t-321 -66.5q-187 0 -356 83q-228 -116 -394 -116q-237 0 -237 263q0 115 45 275q17 60 109 229q199 360 475 606
q-184 -79 -427 -354q63 274 283.5 449.5t501.5 175.5q30 0 45 -1q255 117 433 117q64 0 116 -13t94.5 -40.5t66.5 -76.5t24 -115q0 -116 -75 -286q101 -182 101 -390zM1722 1239q0 83 -53 132t-137 49q-108 0 -254 -70q121 -47 222.5 -131.5t170.5 -195.5q51 135 51 216z
M128 2q0 -86 48.5 -132.5t134.5 -46.5q115 0 266 83q-122 72 -213.5 183t-137.5 245q-98 -205 -98 -332zM632 715h728q-5 142 -113 237t-251 95q-144 0 -251.5 -95t-112.5 -237z" />
    <glyph glyph-name="_582" unicode="&#xf26c;" horiz-adv-x="2048" 
d="M1792 288v960q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1248v-960q0 -66 -47 -113t-113 -47h-736v-128h352q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23
v64q0 14 9 23t23 9h352v128h-736q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
    <glyph glyph-name="_583" unicode="&#xf26d;" horiz-adv-x="1792" 
d="M138 1408h197q-70 -64 -126 -149q-36 -56 -59 -115t-30 -125.5t-8.5 -120t10.5 -132t21 -126t28 -136.5q4 -19 6 -28q51 -238 81 -329q57 -171 152 -275h-272q-48 0 -82 34t-34 82v1304q0 48 34 82t82 34zM1346 1408h308q48 0 82 -34t34 -82v-1304q0 -48 -34 -82t-82 -34
h-178q212 210 196 565l-469 -101q-2 -45 -12 -82t-31 -72t-59.5 -59.5t-93.5 -36.5q-123 -26 -199 40q-32 27 -53 61t-51.5 129t-64.5 258q-35 163 -45.5 263t-5.5 139t23 77q20 41 62.5 73t102.5 45q45 12 83.5 6.5t67 -17t54 -35t43 -48t34.5 -56.5l468 100
q-68 175 -180 287z" />
    <glyph glyph-name="_584" unicode="&#xf26e;" 
d="M1401 -11l-6 -6q-113 -113 -259 -175q-154 -64 -317 -64q-165 0 -317 64q-148 63 -259 175q-113 112 -175 258q-42 103 -54 189q-4 28 48 36q51 8 56 -20q1 -1 1 -4q18 -90 46 -159q50 -124 152 -226q98 -98 226 -152q132 -56 276 -56q143 0 276 56q128 55 225 152l6 6
q10 10 25 6q12 -3 33 -22q36 -37 17 -58zM929 604l-66 -66l63 -63q21 -21 -7 -49q-17 -17 -32 -17q-10 0 -19 10l-62 61l-66 -66q-5 -5 -15 -5q-15 0 -31 16l-2 2q-18 15 -18 29q0 7 8 17l66 65l-66 66q-16 16 14 45q18 18 31 18q6 0 13 -5l65 -66l65 65q18 17 48 -13
q27 -27 11 -44zM1400 547q0 -118 -46 -228q-45 -105 -126 -186q-80 -80 -187 -126t-228 -46t-228 46t-187 126q-82 82 -125 186q-15 33 -15 40h-1q-9 27 43 44q50 16 60 -12q37 -99 97 -167h1v339v2q3 136 102 232q105 103 253 103q147 0 251 -103t104 -249
q0 -147 -104.5 -251t-250.5 -104q-58 0 -112 16q-28 11 -13 61q16 51 44 43l14 -3q14 -3 33 -6t30 -3q104 0 176 71.5t72 174.5q0 101 -72 171q-71 71 -175 71q-107 0 -178 -80q-64 -72 -64 -160v-413q110 -67 242 -67q96 0 185 36.5t156 103.5t103.5 155t36.5 183
q0 198 -141 339q-140 140 -339 140q-200 0 -340 -140q-53 -53 -77 -87l-2 -2q-8 -11 -13 -15.5t-21.5 -9.5t-38.5 3q-21 5 -36.5 16.5t-15.5 26.5v680q0 15 10.5 26.5t27.5 11.5h877q30 0 30 -55t-30 -55h-811v-483h1q40 42 102 84t108 61q109 46 231 46q121 0 228 -46
t187 -126q81 -81 126 -186q46 -112 46 -229zM1369 1128q9 -8 9 -18t-5.5 -18t-16.5 -21q-26 -26 -39 -26q-9 0 -16 7q-106 91 -207 133q-128 56 -276 56q-133 0 -262 -49q-27 -10 -45 37q-9 25 -8 38q3 16 16 20q130 57 299 57q164 0 316 -64q137 -58 235 -152z" />
    <glyph glyph-name="_585" unicode="&#xf270;" horiz-adv-x="1792" 
d="M1551 60q15 6 26 3t11 -17.5t-15 -33.5q-13 -16 -44 -43.5t-95.5 -68t-141 -74t-188 -58t-229.5 -24.5q-119 0 -238 31t-209 76.5t-172.5 104t-132.5 105t-84 87.5q-8 9 -10 16.5t1 12t8 7t11.5 2t11.5 -4.5q192 -117 300 -166q389 -176 799 -90q190 40 391 135z
M1758 175q11 -16 2.5 -69.5t-28.5 -102.5q-34 -83 -85 -124q-17 -14 -26 -9t0 24q21 45 44.5 121.5t6.5 98.5q-5 7 -15.5 11.5t-27 6t-29.5 2.5t-35 0t-31.5 -2t-31 -3t-22.5 -2q-6 -1 -13 -1.5t-11 -1t-8.5 -1t-7 -0.5h-5.5h-4.5t-3 0.5t-2 1.5l-1.5 3q-6 16 47 40t103 30
q46 7 108 1t76 -24zM1364 618q0 -31 13.5 -64t32 -58t37.5 -46t33 -32l13 -11l-227 -224q-40 37 -79 75.5t-58 58.5l-19 20q-11 11 -25 33q-38 -59 -97.5 -102.5t-127.5 -63.5t-140 -23t-137.5 21t-117.5 65.5t-83 113t-31 162.5q0 84 28 154t72 116.5t106.5 83t122.5 57
t130 34.5t119.5 18.5t99.5 6.5v127q0 65 -21 97q-34 53 -121 53q-6 0 -16.5 -1t-40.5 -12t-56 -29.5t-56 -59.5t-48 -96l-294 27q0 60 22 119t67 113t108 95t151.5 65.5t190.5 24.5q100 0 181 -25t129.5 -61.5t81 -83t45 -86t12.5 -73.5v-589zM692 597q0 -86 70 -133
q66 -44 139 -22q84 25 114 123q14 45 14 101v162q-59 -2 -111 -12t-106.5 -33.5t-87 -71t-32.5 -114.5z" />
    <glyph glyph-name="_586" unicode="&#xf271;" horiz-adv-x="1792" 
d="M1536 1280q52 0 90 -38t38 -90v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128zM1152 1376v-288q0 -14 9 -23t23 -9
h64q14 0 23 9t9 23v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM384 1376v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM1536 -128v1024h-1408v-1024h1408zM896 448h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224
v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v224q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-224z" />
    <glyph glyph-name="_587" unicode="&#xf272;" horiz-adv-x="1792" 
d="M1152 416v-64q0 -14 -9 -23t-23 -9h-576q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h576q14 0 23 -9t9 -23zM128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23
t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47
t47 -113v-96h128q52 0 90 -38t38 -90z" />
    <glyph glyph-name="_588" unicode="&#xf273;" horiz-adv-x="1792" 
d="M1111 151l-46 -46q-9 -9 -22 -9t-23 9l-188 189l-188 -189q-10 -9 -23 -9t-22 9l-46 46q-9 9 -9 22t9 23l189 188l-189 188q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l188 -188l188 188q10 9 23 9t22 -9l46 -46q9 -9 9 -22t-9 -23l-188 -188l188 -188q9 -10 9 -23t-9 -22z
M128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280
q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
    <glyph glyph-name="_589" unicode="&#xf274;" horiz-adv-x="1792" 
d="M1303 572l-512 -512q-10 -9 -23 -9t-23 9l-288 288q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l220 -220l444 444q10 9 23 9t22 -9l46 -46q9 -9 9 -22t-9 -23zM128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23
t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47
t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
    <glyph glyph-name="_590" unicode="&#xf275;" horiz-adv-x="1792" 
d="M448 1536q26 0 45 -19t19 -45v-891l536 429q17 14 40 14q26 0 45 -19t19 -45v-379l536 429q17 14 40 14q26 0 45 -19t19 -45v-1152q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h384z" />
    <glyph glyph-name="_591" unicode="&#xf276;" horiz-adv-x="1024" 
d="M512 448q66 0 128 15v-655q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v655q62 -15 128 -15zM512 1536q212 0 362 -150t150 -362t-150 -362t-362 -150t-362 150t-150 362t150 362t362 150zM512 1312q14 0 23 9t9 23t-9 23t-23 9q-146 0 -249 -103t-103 -249
q0 -14 9 -23t23 -9t23 9t9 23q0 119 84.5 203.5t203.5 84.5z" />
    <glyph glyph-name="_592" unicode="&#xf277;" horiz-adv-x="1792" 
d="M1745 1239q10 -10 10 -23t-10 -23l-141 -141q-28 -28 -68 -28h-1344q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h576v64q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-64h512q40 0 68 -28zM768 320h256v-512q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v512zM1600 768
q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-1344q-40 0 -68 28l-141 141q-10 10 -10 23t10 23l141 141q28 28 68 28h512v192h256v-192h576z" />
    <glyph glyph-name="_593" unicode="&#xf278;" horiz-adv-x="2048" 
d="M2020 1525q28 -20 28 -53v-1408q0 -20 -11 -36t-29 -23l-640 -256q-24 -11 -48 0l-616 246l-616 -246q-10 -5 -24 -5q-19 0 -36 11q-28 20 -28 53v1408q0 20 11 36t29 23l640 256q24 11 48 0l616 -246l616 246q32 13 60 -6zM736 1390v-1270l576 -230v1270zM128 1173
v-1270l544 217v1270zM1920 107v1270l-544 -217v-1270z" />
    <glyph glyph-name="_594" unicode="&#xf279;" horiz-adv-x="1792" 
d="M512 1536q13 0 22.5 -9.5t9.5 -22.5v-1472q0 -20 -17 -28l-480 -256q-7 -4 -15 -4q-13 0 -22.5 9.5t-9.5 22.5v1472q0 20 17 28l480 256q7 4 15 4zM1760 1536q13 0 22.5 -9.5t9.5 -22.5v-1472q0 -20 -17 -28l-480 -256q-7 -4 -15 -4q-13 0 -22.5 9.5t-9.5 22.5v1472
q0 20 17 28l480 256q7 4 15 4zM640 1536q8 0 14 -3l512 -256q18 -10 18 -29v-1472q0 -13 -9.5 -22.5t-22.5 -9.5q-8 0 -14 3l-512 256q-18 10 -18 29v1472q0 13 9.5 22.5t22.5 9.5z" />
    <glyph glyph-name="_595" unicode="&#xf27a;" horiz-adv-x="1792" 
d="M640 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1408 640q0 53 -37.5 90.5t-90.5 37.5
t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-110 0 -211 18q-173 -173 -435 -229q-52 -10 -86 -13q-12 -1 -22 6t-13 18q-4 15 20 37q5 5 23.5 21.5t25.5 23.5t23.5 25.5t24 31.5t20.5 37
t20 48t14.5 57.5t12.5 72.5q-146 90 -229.5 216.5t-83.5 269.5q0 174 120 321.5t326 233t450 85.5t450 -85.5t326 -233t120 -321.5z" />
    <glyph glyph-name="_596" unicode="&#xf27b;" horiz-adv-x="1792" 
d="M640 640q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1024 640q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 -53 -37.5 -90.5t-90.5 -37.5
t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5
t104.5 255t-104.5 255t-282 187.5t-381.5 69.5zM1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51
t27 59t26 76q-157 89 -247.5 220t-90.5 281q0 130 71 248.5t191 204.5t286 136.5t348 50.5t348 -50.5t286 -136.5t191 -204.5t71 -248.5z" />
    <glyph glyph-name="_597" unicode="&#xf27c;" horiz-adv-x="1024" 
d="M512 345l512 295v-591l-512 -296v592zM0 640v-591l512 296zM512 1527v-591l-512 -296v591zM512 936l512 295v-591z" />
    <glyph glyph-name="_598" unicode="&#xf27d;" horiz-adv-x="1792" 
d="M1709 1018q-10 -236 -332 -651q-333 -431 -562 -431q-142 0 -240 263q-44 160 -132 482q-72 262 -157 262q-18 0 -127 -76l-77 98q24 21 108 96.5t130 115.5q156 138 241 146q95 9 153 -55.5t81 -203.5q44 -287 66 -373q55 -249 120 -249q51 0 154 161q101 161 109 246
q13 139 -109 139q-57 0 -121 -26q120 393 459 382q251 -8 236 -326z" />
    <glyph glyph-name="f27e" unicode="&#xf27e;" 
d="M0 1408h1536v-1536h-1536v1536zM1085 293l-221 631l221 297h-634l221 -297l-221 -631l317 -304z" />
    <glyph glyph-name="uniF280" unicode="&#xf280;" 
d="M0 1408h1536v-1536h-1536v1536zM908 1088l-12 -33l75 -83l-31 -114l25 -25l107 57l107 -57l25 25l-31 114l75 83l-12 33h-95l-53 96h-32l-53 -96h-95zM641 925q32 0 44.5 -16t11.5 -63l174 21q0 55 -17.5 92.5t-50.5 56t-69 25.5t-85 7q-133 0 -199 -57.5t-66 -182.5v-72
h-96v-128h76q20 0 20 -8v-382q0 -14 -5 -20t-18 -7l-73 -7v-88h448v86l-149 14q-6 1 -8.5 1.5t-3.5 2.5t-0.5 4t1 7t0.5 10v387h191l38 128h-231q-6 0 -2 6t4 9v80q0 27 1.5 40.5t7.5 28t19.5 20t36.5 5.5zM1248 96v86l-54 9q-7 1 -9.5 2.5t-2.5 3t1 7.5t1 12v520h-275
l-23 -101l83 -22q23 -7 23 -27v-370q0 -14 -6 -18.5t-20 -6.5l-70 -9v-86h352z" />
    <glyph glyph-name="uniF281" unicode="&#xf281;" horiz-adv-x="1792" 
d="M1792 690q0 -58 -29.5 -105.5t-79.5 -72.5q12 -46 12 -96q0 -155 -106.5 -287t-290.5 -208.5t-400 -76.5t-399.5 76.5t-290 208.5t-106.5 287q0 47 11 94q-51 25 -82 73.5t-31 106.5q0 82 58 140.5t141 58.5q85 0 145 -63q218 152 515 162l116 521q3 13 15 21t26 5
l369 -81q18 37 54 59.5t79 22.5q62 0 106 -43.5t44 -105.5t-44 -106t-106 -44t-105.5 43.5t-43.5 105.5l-334 74l-104 -472q300 -9 519 -160q58 61 143 61q83 0 141 -58.5t58 -140.5zM418 491q0 -62 43.5 -106t105.5 -44t106 44t44 106t-44 105.5t-106 43.5q-61 0 -105 -44
t-44 -105zM1228 136q11 11 11 26t-11 26q-10 10 -25 10t-26 -10q-41 -42 -121 -62t-160 -20t-160 20t-121 62q-11 10 -26 10t-25 -10q-11 -10 -11 -25.5t11 -26.5q43 -43 118.5 -68t122.5 -29.5t91 -4.5t91 4.5t122.5 29.5t118.5 68zM1225 341q62 0 105.5 44t43.5 106
q0 61 -44 105t-105 44q-62 0 -106 -43.5t-44 -105.5t44 -106t106 -44z" />
    <glyph glyph-name="_602" unicode="&#xf282;" horiz-adv-x="1792" 
d="M69 741h1q16 126 58.5 241.5t115 217t167.5 176t223.5 117.5t276.5 43q231 0 414 -105.5t294 -303.5q104 -187 104 -442v-188h-1125q1 -111 53.5 -192.5t136.5 -122.5t189.5 -57t213 -3t208 46.5t173.5 84.5v-377q-92 -55 -229.5 -92t-312.5 -38t-316 53
q-189 73 -311.5 249t-124.5 372q-3 242 111 412t325 268q-48 -60 -78 -125.5t-46 -159.5h635q8 77 -8 140t-47 101.5t-70.5 66.5t-80.5 41t-75 20.5t-56 8.5l-22 1q-135 -5 -259.5 -44.5t-223.5 -104.5t-176 -140.5t-138 -163.5z" />
    <glyph glyph-name="_603" unicode="&#xf283;" horiz-adv-x="2304" 
d="M0 32v608h2304v-608q0 -66 -47 -113t-113 -47h-1984q-66 0 -113 47t-47 113zM640 256v-128h384v128h-384zM256 256v-128h256v128h-256zM2144 1408q66 0 113 -47t47 -113v-224h-2304v224q0 66 47 113t113 47h1984z" />
    <glyph glyph-name="_604" unicode="&#xf284;" horiz-adv-x="1792" 
d="M1584 246l-218 111q-74 -120 -196.5 -189t-263.5 -69q-147 0 -271 72t-196 196t-72 270q0 110 42.5 209.5t115 172t172 115t209.5 42.5q131 0 247.5 -60.5t192.5 -168.5l215 125q-110 169 -286.5 265t-378.5 96q-161 0 -308 -63t-253 -169t-169 -253t-63 -308t63 -308
t169 -253t253 -169t308 -63q213 0 397.5 107t290.5 292zM1030 643l693 -352q-116 -253 -334.5 -400t-492.5 -147q-182 0 -348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71q260 0 470.5 -133.5t335.5 -366.5zM1543 640h-39v-160h-96v352h136q32 0 54.5 -20
t28.5 -48t1 -56t-27.5 -48t-57.5 -20z" />
    <glyph glyph-name="uniF285" unicode="&#xf285;" horiz-adv-x="1792" 
d="M1427 827l-614 386l92 151h855zM405 562l-184 116v858l1183 -743zM1424 697l147 -95v-858l-532 335zM1387 718l-500 -802h-855l356 571z" />
    <glyph glyph-name="uniF286" unicode="&#xf286;" horiz-adv-x="1792" 
d="M640 528v224q0 16 -16 16h-96q-16 0 -16 -16v-224q0 -16 16 -16h96q16 0 16 16zM1152 528v224q0 16 -16 16h-96q-16 0 -16 -16v-224q0 -16 16 -16h96q16 0 16 16zM1664 496v-752h-640v320q0 80 -56 136t-136 56t-136 -56t-56 -136v-320h-640v752q0 16 16 16h96
q16 0 16 -16v-112h128v624q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h96q16 0 16 -16v-112h128v112q0 6 2.5 9.5t8.5 5t9.5 2t11.5 0t9 -0.5v391q-32 15 -32 50q0 23 16.5 39t38.5 16t38.5 -16t16.5 -39q0 -35 -32 -50v-17q45 10 83 10q21 0 59.5 -7.5t54.5 -7.5
q17 0 47 7.5t37 7.5q16 0 16 -16v-210q0 -15 -35 -21.5t-62 -6.5q-18 0 -54.5 7.5t-55.5 7.5q-40 0 -90 -12v-133q1 0 9 0.5t11.5 0t9.5 -2t8.5 -5t2.5 -9.5v-112h128v112q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h96q16 0 16 -16v-624h128v112q0 16 16 16h96
q16 0 16 -16z" />
    <glyph glyph-name="_607" unicode="&#xf287;" horiz-adv-x="2304" 
d="M2288 731q16 -8 16 -27t-16 -27l-320 -192q-8 -5 -16 -5q-9 0 -16 4q-16 10 -16 28v128h-858q37 -58 83 -165q16 -37 24.5 -55t24 -49t27 -47t27 -34t31.5 -26t33 -8h96v96q0 14 9 23t23 9h320q14 0 23 -9t9 -23v-320q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v96h-96
q-32 0 -61 10t-51 23.5t-45 40.5t-37 46t-33.5 57t-28.5 57.5t-28 60.5q-23 53 -37 81.5t-36 65t-44.5 53.5t-46.5 17h-360q-22 -84 -91 -138t-157 -54q-106 0 -181 75t-75 181t75 181t181 75q88 0 157 -54t91 -138h104q24 0 46.5 17t44.5 53.5t36 65t37 81.5q19 41 28 60.5
t28.5 57.5t33.5 57t37 46t45 40.5t51 23.5t61 10h107q21 57 70 92.5t111 35.5q80 0 136 -56t56 -136t-56 -136t-136 -56q-62 0 -111 35.5t-70 92.5h-107q-17 0 -33 -8t-31.5 -26t-27 -34t-27 -47t-24 -49t-24.5 -55q-46 -107 -83 -165h1114v128q0 18 16 28t32 -1z" />
    <glyph glyph-name="_608" unicode="&#xf288;" horiz-adv-x="1792" 
d="M1150 774q0 -56 -39.5 -95t-95.5 -39h-253v269h253q56 0 95.5 -39.5t39.5 -95.5zM1329 774q0 130 -91.5 222t-222.5 92h-433v-896h180v269h253q130 0 222 91.5t92 221.5zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348
t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
    <glyph glyph-name="_609" unicode="&#xf289;" horiz-adv-x="2304" 
d="M1645 438q0 59 -34 106.5t-87 68.5q-7 -45 -23 -92q-7 -24 -27.5 -38t-44.5 -14q-12 0 -24 3q-31 10 -45 38.5t-4 58.5q23 71 23 143q0 123 -61 227.5t-166 165.5t-228 61q-134 0 -247 -73t-167 -194q108 -28 188 -106q22 -23 22 -55t-22 -54t-54 -22t-55 22
q-75 75 -180 75q-106 0 -181 -74.5t-75 -180.5t75 -180.5t181 -74.5h1046q79 0 134.5 55.5t55.5 133.5zM1798 438q0 -142 -100.5 -242t-242.5 -100h-1046q-169 0 -289 119.5t-120 288.5q0 153 100 267t249 136q62 184 221 298t354 114q235 0 408.5 -158.5t196.5 -389.5
q116 -25 192.5 -118.5t76.5 -214.5zM2048 438q0 -175 -97 -319q-23 -33 -64 -33q-24 0 -43 13q-26 17 -32 48.5t12 57.5q71 104 71 233t-71 233q-18 26 -12 57t32 49t57.5 11.5t49.5 -32.5q97 -142 97 -318zM2304 438q0 -244 -134 -443q-23 -34 -64 -34q-23 0 -42 13
q-26 18 -32.5 49t11.5 57q108 164 108 358q0 195 -108 357q-18 26 -11.5 57.5t32.5 48.5q26 18 57 12t49 -33q134 -198 134 -442z" />
    <glyph glyph-name="_610" unicode="&#xf28a;" 
d="M1500 -13q0 -89 -63 -152.5t-153 -63.5t-153.5 63.5t-63.5 152.5q0 90 63.5 153.5t153.5 63.5t153 -63.5t63 -153.5zM1267 268q-115 -15 -192.5 -102.5t-77.5 -205.5q0 -74 33 -138q-146 -78 -379 -78q-109 0 -201 21t-153.5 54.5t-110.5 76.5t-76 85t-44.5 83
t-23.5 66.5t-6 39.5q0 19 4.5 42.5t18.5 56t36.5 58t64 43.5t94.5 18t94 -17.5t63 -41t35.5 -53t17.5 -49t4 -33.5q0 -34 -23 -81q28 -27 82 -42t93 -17l40 -1q115 0 190 51t75 133q0 26 -9 48.5t-31.5 44.5t-49.5 41t-74 44t-93.5 47.5t-119.5 56.5q-28 13 -43 20
q-116 55 -187 100t-122.5 102t-72 125.5t-20.5 162.5q0 78 20.5 150t66 137.5t112.5 114t166.5 77t221.5 28.5q120 0 220 -26t164.5 -67t109.5 -94t64 -105.5t19 -103.5q0 -46 -15 -82.5t-36.5 -58t-48.5 -36t-49 -19.5t-39 -5h-8h-32t-39 5t-44 14t-41 28t-37 46t-24 70.5
t-10 97.5q-15 16 -59 25.5t-81 10.5l-37 1q-68 0 -117.5 -31t-70.5 -70t-21 -76q0 -24 5 -43t24 -46t53 -51t97 -53.5t150 -58.5q76 -25 138.5 -53.5t109 -55.5t83 -59t60.5 -59.5t41 -62.5t26.5 -62t14.5 -63.5t6 -62t1 -62.5z" />
    <glyph glyph-name="_611" unicode="&#xf28b;" 
d="M704 352v576q0 14 -9 23t-23 9h-256q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h256q14 0 23 9t9 23zM1152 352v576q0 14 -9 23t-23 9h-256q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h256q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103
t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="_612" unicode="&#xf28c;" 
d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM768 96q148 0 273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273
t73 -273t198 -198t273 -73zM864 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-192zM480 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-192z" />
    <glyph glyph-name="_613" unicode="&#xf28d;" 
d="M1088 352v576q0 14 -9 23t-23 9h-576q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h576q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5
t103 -385.5z" />
    <glyph glyph-name="_614" unicode="&#xf28e;" 
d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM768 96q148 0 273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273
t73 -273t198 -198t273 -73zM480 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h576q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-576z" />
    <glyph glyph-name="_615" unicode="&#xf290;" horiz-adv-x="1792" 
d="M1757 128l35 -313q3 -28 -16 -50q-19 -21 -48 -21h-1664q-29 0 -48 21q-19 22 -16 50l35 313h1722zM1664 967l86 -775h-1708l86 775q3 24 21 40.5t43 16.5h256v-128q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5v128h384v-128q0 -53 37.5 -90.5t90.5 -37.5
t90.5 37.5t37.5 90.5v128h256q25 0 43 -16.5t21 -40.5zM1280 1152v-256q0 -26 -19 -45t-45 -19t-45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-256q0 -26 -19 -45t-45 -19t-45 19t-19 45v256q0 159 112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" />
    <glyph glyph-name="_616" unicode="&#xf291;" horiz-adv-x="2048" 
d="M1920 768q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5h-15l-115 -662q-8 -46 -44 -76t-82 -30h-1280q-46 0 -82 30t-44 76l-115 662h-15q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5h1792zM485 -32q26 2 43.5 22.5t15.5 46.5l-32 416q-2 26 -22.5 43.5
t-46.5 15.5t-43.5 -22.5t-15.5 -46.5l32 -416q2 -25 20.5 -42t43.5 -17h5zM896 32v416q0 26 -19 45t-45 19t-45 -19t-19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45zM1280 32v416q0 26 -19 45t-45 19t-45 -19t-19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45zM1632 27l32 416
q2 26 -15.5 46.5t-43.5 22.5t-46.5 -15.5t-22.5 -43.5l-32 -416q-2 -26 15.5 -46.5t43.5 -22.5h5q25 0 43.5 17t20.5 42zM476 1244l-93 -412h-132l101 441q19 88 89 143.5t160 55.5h167q0 26 19 45t45 19h384q26 0 45 -19t19 -45h167q90 0 160 -55.5t89 -143.5l101 -441
h-132l-93 412q-11 44 -45.5 72t-79.5 28h-167q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45h-167q-45 0 -79.5 -28t-45.5 -72z" />
    <glyph glyph-name="_617" unicode="&#xf292;" horiz-adv-x="1792" 
d="M991 512l64 256h-254l-64 -256h254zM1759 1016l-56 -224q-7 -24 -31 -24h-327l-64 -256h311q15 0 25 -12q10 -14 6 -28l-56 -224q-5 -24 -31 -24h-327l-81 -328q-7 -24 -31 -24h-224q-16 0 -26 12q-9 12 -6 28l78 312h-254l-81 -328q-7 -24 -31 -24h-225q-15 0 -25 12
q-9 12 -6 28l78 312h-311q-15 0 -25 12q-9 12 -6 28l56 224q7 24 31 24h327l64 256h-311q-15 0 -25 12q-10 14 -6 28l56 224q5 24 31 24h327l81 328q7 24 32 24h224q15 0 25 -12q9 -12 6 -28l-78 -312h254l81 328q7 24 32 24h224q15 0 25 -12q9 -12 6 -28l-78 -312h311
q15 0 25 -12q9 -12 6 -28z" />
    <glyph glyph-name="_618" unicode="&#xf293;" 
d="M841 483l148 -148l-149 -149zM840 1094l149 -149l-148 -148zM710 -130l464 464l-306 306l306 306l-464 464v-611l-255 255l-93 -93l320 -321l-320 -321l93 -93l255 255v-611zM1429 640q0 -209 -32 -365.5t-87.5 -257t-140.5 -162.5t-181.5 -86.5t-219.5 -24.5
t-219.5 24.5t-181.5 86.5t-140.5 162.5t-87.5 257t-32 365.5t32 365.5t87.5 257t140.5 162.5t181.5 86.5t219.5 24.5t219.5 -24.5t181.5 -86.5t140.5 -162.5t87.5 -257t32 -365.5z" />
    <glyph glyph-name="_619" unicode="&#xf294;" horiz-adv-x="1024" 
d="M596 113l173 172l-173 172v-344zM596 823l173 172l-173 172v-344zM628 640l356 -356l-539 -540v711l-297 -296l-108 108l372 373l-372 373l108 108l297 -296v711l539 -540z" />
    <glyph glyph-name="_620" unicode="&#xf295;" 
d="M1280 256q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM512 1024q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1536 256q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5
t112.5 -271.5zM1440 1344q0 -20 -13 -38l-1056 -1408q-19 -26 -51 -26h-160q-26 0 -45 19t-19 45q0 20 13 38l1056 1408q19 26 51 26h160q26 0 45 -19t19 -45zM768 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5
t271.5 -112.5t112.5 -271.5z" />
    <glyph glyph-name="_621" unicode="&#xf296;" horiz-adv-x="1792" 
d="M104 830l792 -1015l-868 630q-18 13 -25 34.5t0 42.5l101 308v0zM566 830h660l-330 -1015v0zM368 1442l198 -612h-462l198 612q8 23 33 23t33 -23zM1688 830l101 -308q7 -21 0 -42.5t-25 -34.5l-868 -630l792 1015v0zM1688 830h-462l198 612q8 23 33 23t33 -23z" />
    <glyph glyph-name="_622" unicode="&#xf297;" horiz-adv-x="1792" 
d="M384 704h160v224h-160v-224zM1221 372v92q-104 -36 -243 -38q-135 -1 -259.5 46.5t-220.5 122.5l1 -96q88 -80 212 -128.5t272 -47.5q129 0 238 49zM640 704h640v224h-640v-224zM1792 736q0 -187 -99 -352q89 -102 89 -229q0 -157 -129.5 -268t-313.5 -111
q-122 0 -225 52.5t-161 140.5q-19 -1 -57 -1t-57 1q-58 -88 -161 -140.5t-225 -52.5q-184 0 -313.5 111t-129.5 268q0 127 89 229q-99 165 -99 352q0 209 120 385.5t326.5 279.5t449.5 103t449.5 -103t326.5 -279.5t120 -385.5z" />
    <glyph glyph-name="_623" unicode="&#xf298;" 
d="M515 625v-128h-252v128h252zM515 880v-127h-252v127h252zM1273 369v-128h-341v128h341zM1273 625v-128h-672v128h672zM1273 880v-127h-672v127h672zM1408 20v1240q0 8 -6 14t-14 6h-32l-378 -256l-210 171l-210 -171l-378 256h-32q-8 0 -14 -6t-6 -14v-1240q0 -8 6 -14
t14 -6h1240q8 0 14 6t6 14zM553 1130l185 150h-406zM983 1130l221 150h-406zM1536 1260v-1240q0 -62 -43 -105t-105 -43h-1240q-62 0 -105 43t-43 105v1240q0 62 43 105t105 43h1240q62 0 105 -43t43 -105z" />
    <glyph glyph-name="_624" unicode="&#xf299;" horiz-adv-x="1792" 
d="M896 720q-104 196 -160 278q-139 202 -347 318q-34 19 -70 36q-89 40 -94 32t34 -38l39 -31q62 -43 112.5 -93.5t94.5 -116.5t70.5 -113t70.5 -131q9 -17 13 -25q44 -84 84 -153t98 -154t115.5 -150t131 -123.5t148.5 -90.5q153 -66 154 -60q1 3 -49 37q-53 36 -81 57
q-77 58 -179 211t-185 310zM549 177q-76 60 -132.5 125t-98 143.5t-71 154.5t-58.5 186t-52 209t-60.5 252t-76.5 289q273 0 497.5 -36t379 -92t271 -144.5t185.5 -172.5t110 -198.5t56 -199.5t12.5 -198.5t-9.5 -173t-20 -143.5t-13 -107l323 -327h-104l-281 285
q-22 -2 -91.5 -14t-121.5 -19t-138 -6t-160.5 17t-167.5 59t-179 111z" />
    <glyph glyph-name="_625" unicode="&#xf29a;" horiz-adv-x="1792" 
d="M1374 879q-6 26 -28.5 39.5t-48.5 7.5q-261 -62 -401 -62t-401 62q-26 6 -48.5 -7.5t-28.5 -39.5t7.5 -48.5t39.5 -28.5q194 -46 303 -58q-2 -158 -15.5 -269t-26.5 -155.5t-41 -115.5l-9 -21q-10 -25 1 -49t36 -34q9 -4 23 -4q44 0 60 41l8 20q54 139 71 259h42
q17 -120 71 -259l8 -20q16 -41 60 -41q14 0 23 4q25 10 36 34t1 49l-9 21q-28 71 -41 115.5t-26.5 155.5t-15.5 269q109 12 303 58q26 6 39.5 28.5t7.5 48.5zM1024 1024q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5z
M1600 640q0 -143 -55.5 -273.5t-150 -225t-225 -150t-273.5 -55.5t-273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5zM896 1408q-156 0 -298 -61t-245 -164t-164 -245t-61 -298t61 -298
t164 -245t245 -164t298 -61t298 61t245 164t164 245t61 298t-61 298t-164 245t-245 164t-298 61zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
    <glyph glyph-name="_626" unicode="&#xf29b;" 
d="M1438 723q34 -35 29 -82l-44 -551q-4 -42 -34.5 -70t-71.5 -28q-6 0 -9 1q-44 3 -72.5 36.5t-25.5 77.5l35 429l-143 -8q55 -113 55 -240q0 -216 -148 -372l-137 137q91 101 91 235q0 145 -102.5 248t-247.5 103q-134 0 -236 -92l-137 138q120 114 284 141l264 300
l-149 87l-181 -161q-33 -30 -77 -27.5t-73 35.5t-26.5 77t34.5 73l239 213q26 23 60 26.5t64 -14.5l488 -283q36 -21 48 -68q17 -67 -26 -117l-205 -232l371 20q49 3 83 -32zM1240 1180q-74 0 -126 52t-52 126t52 126t126 52t126.5 -52t52.5 -126t-52.5 -126t-126.5 -52z
M613 -62q106 0 196 61l139 -139q-146 -116 -335 -116q-148 0 -273.5 73t-198.5 198t-73 273q0 188 116 336l139 -139q-60 -88 -60 -197q0 -145 102.5 -247.5t247.5 -102.5z" />
    <glyph glyph-name="_627" unicode="&#xf29c;" 
d="M880 336v-160q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v160q0 14 9 23t23 9h160q14 0 23 -9t9 -23zM1136 832q0 -50 -15 -90t-45.5 -69t-52 -44t-59.5 -36q-32 -18 -46.5 -28t-26 -24t-11.5 -29v-32q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v68q0 35 10.5 64.5
t24 47.5t39 35.5t41 25.5t44.5 21q53 25 75 43t22 49q0 42 -43.5 71.5t-95.5 29.5q-56 0 -95 -27q-29 -20 -80 -83q-9 -12 -25 -12q-11 0 -19 6l-108 82q-10 7 -12 20t5 23q122 192 349 192q129 0 238.5 -89.5t109.5 -214.5zM768 1280q-130 0 -248.5 -51t-204 -136.5
t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5t-51 248.5t-136.5 204t-204 136.5t-248.5 51zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5
t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="_628" unicode="&#xf29d;" horiz-adv-x="1408" 
d="M366 1225q-64 0 -110 45.5t-46 110.5q0 64 46 109.5t110 45.5t109.5 -45.5t45.5 -109.5q0 -65 -45.5 -110.5t-109.5 -45.5zM917 583q0 -50 -30 -67.5t-63.5 -6.5t-47.5 34l-367 438q-7 12 -14 15.5t-11 1.5l-3 -3q-7 -8 4 -21l122 -139l1 -354l-161 -457
q-67 -192 -92 -234q-15 -26 -28 -32q-50 -26 -103 -1q-29 13 -41.5 43t-9.5 57q2 17 197 618l5 416l-85 -164l35 -222q4 -24 -1 -42t-14 -27.5t-19 -16t-17 -7.5l-7 -2q-19 -3 -34.5 3t-24 16t-14 22t-7.5 19.5t-2 9.5l-46 299l211 381q23 34 113 34q75 0 107 -40l424 -521
q7 -5 14 -17l3 -3l-1 -1q7 -13 7 -29zM514 433q43 -113 88.5 -225t69.5 -168l24 -55q36 -93 42 -125q11 -70 -36 -97q-35 -22 -66 -16t-51 22t-29 35h-1q-6 16 -8 25l-124 351zM1338 -159q31 -49 31 -57q0 -5 -3 -7q-9 -5 -14.5 0.5t-15.5 26t-16 30.5q-114 172 -423 661
q3 -1 7 1t7 4l3 2q11 9 11 17z" />
    <glyph glyph-name="_629" unicode="&#xf29e;" horiz-adv-x="2304" 
d="M504 542h171l-1 265zM1530 641q0 87 -50.5 140t-146.5 53h-54v-388h52q91 0 145 57t54 138zM956 1018l1 -756q0 -14 -9.5 -24t-23.5 -10h-216q-14 0 -23.5 10t-9.5 24v62h-291l-55 -81q-10 -15 -28 -15h-267q-21 0 -30.5 18t3.5 35l556 757q9 14 27 14h332q14 0 24 -10
t10 -24zM1783 641q0 -193 -125.5 -303t-324.5 -110h-270q-14 0 -24 10t-10 24v756q0 14 10 24t24 10h268q200 0 326 -109t126 -302zM1939 640q0 -11 -0.5 -29t-8 -71.5t-21.5 -102t-44.5 -108t-73.5 -102.5h-51q38 45 66.5 104.5t41.5 112t21 98t9 72.5l1 27q0 8 -0.5 22.5
t-7.5 60t-20 91.5t-41 111.5t-66 124.5h43q41 -47 72 -107t45.5 -111.5t23 -96t10.5 -70.5zM2123 640q0 -11 -0.5 -29t-8 -71.5t-21.5 -102t-45 -108t-74 -102.5h-51q38 45 66.5 104.5t41.5 112t21 98t9 72.5l1 27q0 8 -0.5 22.5t-7.5 60t-19.5 91.5t-40.5 111.5t-66 124.5
h43q41 -47 72 -107t45.5 -111.5t23 -96t10.5 -70.5zM2304 640q0 -11 -0.5 -29t-8 -71.5t-21.5 -102t-44.5 -108t-73.5 -102.5h-51q38 45 66 104.5t41 112t21 98t9 72.5l1 27q0 8 -0.5 22.5t-7.5 60t-19.5 91.5t-40.5 111.5t-66 124.5h43q41 -47 72 -107t45.5 -111.5t23 -96
t9.5 -70.5z" />
    <glyph glyph-name="uniF2A0" unicode="&#xf2a0;" horiz-adv-x="1408" 
d="M617 -153q0 11 -13 58t-31 107t-20 69q-1 4 -5 26.5t-8.5 36t-13.5 21.5q-15 14 -51 14q-23 0 -70 -5.5t-71 -5.5q-34 0 -47 11q-6 5 -11 15.5t-7.5 20t-6.5 24t-5 18.5q-37 128 -37 255t37 255q1 4 5 18.5t6.5 24t7.5 20t11 15.5q13 11 47 11q24 0 71 -5.5t70 -5.5
q36 0 51 14q9 8 13.5 21.5t8.5 36t5 26.5q2 9 20 69t31 107t13 58q0 22 -43.5 52.5t-75.5 42.5q-20 8 -45 8q-34 0 -98 -18q-57 -17 -96.5 -40.5t-71 -66t-46 -70t-45.5 -94.5q-6 -12 -9 -19q-49 -107 -68 -216t-19 -244t19 -244t68 -216q56 -122 83 -161q63 -91 179 -127
l6 -2q64 -18 98 -18q25 0 45 8q32 12 75.5 42.5t43.5 52.5zM776 760q-26 0 -45 19t-19 45.5t19 45.5q37 37 37 90q0 52 -37 91q-19 19 -19 45t19 45t45 19t45 -19q75 -75 75 -181t-75 -181q-21 -19 -45 -19zM957 579q-27 0 -45 19q-19 19 -19 45t19 45q112 114 112 272
t-112 272q-19 19 -19 45t19 45t45 19t45 -19q150 -150 150 -362t-150 -362q-18 -19 -45 -19zM1138 398q-27 0 -45 19q-19 19 -19 45t19 45q90 91 138.5 208t48.5 245t-48.5 245t-138.5 208q-19 19 -19 45t19 45t45 19t45 -19q109 -109 167 -249t58 -294t-58 -294t-167 -249
q-18 -19 -45 -19z" />
    <glyph glyph-name="uniF2A1" unicode="&#xf2a1;" horiz-adv-x="2176" 
d="M192 352q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM704 352q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM704 864q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1472 352
q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1984 352q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1472 864q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1984 864
q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1984 1376q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM384 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 192q0 -80 -56 -136
t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 704q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 704q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 1216q0 -80 -56 -136t-136 -56
t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 1216q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM2176 192q0 -80 -56 -136t-136 -56t-136 56
t-56 136t56 136t136 56t136 -56t56 -136zM1664 704q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM2176 704q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 1216q0 -80 -56 -136t-136 -56t-136 56t-56 136
t56 136t136 56t136 -56t56 -136zM2176 1216q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136z" />
    <glyph glyph-name="uniF2A2" unicode="&#xf2a2;" horiz-adv-x="1792" 
d="M128 -192q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM320 0q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM365 365l256 -256l-90 -90l-256 256zM704 384q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45z
M1411 704q0 -59 -11.5 -108.5t-37.5 -93.5t-44 -67.5t-53 -64.5q-31 -35 -45.5 -54t-33.5 -50t-26.5 -64t-7.5 -74q0 -159 -112.5 -271.5t-271.5 -112.5q-26 0 -45 19t-19 45t19 45t45 19q106 0 181 75t75 181q0 57 11.5 105.5t37 91t43.5 66.5t52 63q40 46 59.5 72
t37.5 74.5t18 103.5q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5q0 -26 -19 -45t-45 -19t-45 19t-19 45q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5zM896 576q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45
t45 19t45 -19t19 -45zM1184 704q0 -26 -19 -45t-45 -19t-45 19t-19 45q0 93 -65.5 158.5t-158.5 65.5q-92 0 -158 -65.5t-66 -158.5q0 -26 -19 -45t-45 -19t-45 19t-19 45q0 146 103 249t249 103t249 -103t103 -249zM1578 993q10 -25 -1 -49t-36 -34q-9 -4 -23 -4
q-19 0 -35.5 11t-23.5 30q-68 178 -224 295q-21 16 -25 42t12 47q17 21 43 25t47 -12q183 -137 266 -351zM1788 1074q9 -25 -1.5 -49t-35.5 -34q-11 -4 -23 -4q-44 0 -60 41q-92 238 -297 393q-22 16 -25.5 42t12.5 47q16 22 42 25.5t47 -12.5q235 -175 341 -449z" />
    <glyph glyph-name="uniF2A3" unicode="&#xf2a3;" horiz-adv-x="2304" 
d="M1032 576q-59 2 -84 55q-17 34 -48 53.5t-68 19.5q-53 0 -90.5 -37.5t-37.5 -90.5q0 -56 36 -89l10 -8q34 -31 82 -31q37 0 68 19.5t48 53.5q25 53 84 55zM1600 704q0 56 -36 89l-10 8q-34 31 -82 31q-37 0 -68 -19.5t-48 -53.5q-25 -53 -84 -55q59 -2 84 -55
q17 -34 48 -53.5t68 -19.5q53 0 90.5 37.5t37.5 90.5zM1174 925q-17 -35 -55 -48t-73 4q-62 31 -134 31q-51 0 -99 -17q3 0 9.5 0.5t9.5 0.5q92 0 170.5 -50t118.5 -133q17 -36 3.5 -73.5t-49.5 -54.5q-18 -9 -39 -9q21 0 39 -9q36 -17 49.5 -54.5t-3.5 -73.5
q-40 -83 -118.5 -133t-170.5 -50h-6q-16 2 -44 4l-290 27l-239 -120q-14 -7 -29 -7q-40 0 -57 35l-160 320q-11 23 -4 47.5t29 37.5l209 119l148 267q17 155 91.5 291.5t195.5 236.5q31 25 70.5 21.5t64.5 -34.5t21.5 -70t-34.5 -65q-70 -59 -117 -128q123 84 267 101
q40 5 71.5 -19t35.5 -64q5 -40 -19 -71.5t-64 -35.5q-84 -10 -159 -55q46 10 99 10q115 0 218 -50q36 -18 49 -55.5t-5 -73.5zM2137 1085l160 -320q11 -23 4 -47.5t-29 -37.5l-209 -119l-148 -267q-17 -155 -91.5 -291.5t-195.5 -236.5q-26 -22 -61 -22q-45 0 -74 35
q-25 31 -21.5 70t34.5 65q70 59 117 128q-123 -84 -267 -101q-4 -1 -12 -1q-36 0 -63.5 24t-31.5 60q-5 40 19 71.5t64 35.5q84 10 159 55q-46 -10 -99 -10q-115 0 -218 50q-36 18 -49 55.5t5 73.5q17 35 55 48t73 -4q62 -31 134 -31q51 0 99 17q-3 0 -9.5 -0.5t-9.5 -0.5
q-92 0 -170.5 50t-118.5 133q-17 36 -3.5 73.5t49.5 54.5q18 9 39 9q-21 0 -39 9q-36 17 -49.5 54.5t3.5 73.5q40 83 118.5 133t170.5 50h6h1q14 -2 42 -4l291 -27l239 120q14 7 29 7q40 0 57 -35z" />
    <glyph glyph-name="uniF2A4" unicode="&#xf2a4;" horiz-adv-x="1792" 
d="M1056 704q0 -26 19 -45t45 -19t45 19t19 45q0 146 -103 249t-249 103t-249 -103t-103 -249q0 -26 19 -45t45 -19t45 19t19 45q0 93 66 158.5t158 65.5t158 -65.5t66 -158.5zM835 1280q-117 0 -223.5 -45.5t-184 -123t-123 -184t-45.5 -223.5q0 -26 19 -45t45 -19t45 19
t19 45q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5q0 -55 -18 -103.5t-37.5 -74.5t-59.5 -72q-34 -39 -52 -63t-43.5 -66.5t-37 -91t-11.5 -105.5q0 -106 -75 -181t-181 -75q-26 0 -45 -19t-19 -45t19 -45t45 -19q159 0 271.5 112.5t112.5 271.5q0 41 7.5 74
t26.5 64t33.5 50t45.5 54q35 41 53 64.5t44 67.5t37.5 93.5t11.5 108.5q0 117 -45.5 223.5t-123 184t-184 123t-223.5 45.5zM591 561l226 -226l-579 -579q-12 -12 -29 -12t-29 12l-168 168q-12 12 -12 29t12 29zM1612 1524l168 -168q12 -12 12 -29t-12 -30l-233 -233
l-26 -25l-71 -71q-66 153 -195 258l91 91l207 207q13 12 30 12t29 -12z" />
    <glyph glyph-name="uniF2A5" unicode="&#xf2a5;" 
d="M866 1021q0 -27 -13 -94q-11 -50 -31.5 -150t-30.5 -150q-2 -11 -4.5 -12.5t-13.5 -2.5q-20 -2 -31 -2q-58 0 -84 49.5t-26 113.5q0 88 35 174t103 124q28 14 51 14q28 0 36.5 -16.5t8.5 -47.5zM1352 597q0 14 -39 75.5t-52 66.5q-21 8 -34 8q-91 0 -226 -77l-2 2
q3 22 27.5 135t24.5 178q0 233 -242 233q-24 0 -68 -6q-94 -17 -168.5 -89.5t-111.5 -166.5t-37 -189q0 -146 80.5 -225t227.5 -79q25 0 25 -3t-1 -5q-4 -34 -26 -117q-14 -52 -51.5 -101t-82.5 -49q-42 0 -42 47q0 24 10.5 47.5t25 39.5t29.5 28.5t26 20t11 8.5q0 3 -7 10
q-24 22 -58.5 36.5t-65.5 14.5q-35 0 -63.5 -34t-41 -75t-12.5 -75q0 -88 51.5 -142t138.5 -54q82 0 155 53t117.5 126t65.5 153q6 22 15.5 66.5t14.5 66.5q3 12 14 18q118 60 227 60q48 0 127 -18q1 -1 4 -1q5 0 9.5 4.5t4.5 8.5zM1536 1120v-960q0 -119 -84.5 -203.5
t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="uniF2A6" unicode="&#xf2a6;" horiz-adv-x="1535" 
d="M744 1231q0 24 -2 38.5t-8.5 30t-21 23t-37.5 7.5q-39 0 -78 -23q-105 -58 -159 -190.5t-54 -269.5q0 -44 8.5 -85.5t26.5 -80.5t52.5 -62.5t81.5 -23.5q4 0 18 -0.5t20 0t16 3t15 8.5t7 16q16 77 48 231.5t48 231.5q19 91 19 146zM1498 575q0 -7 -7.5 -13.5t-15.5 -6.5
l-6 1q-22 3 -62 11t-72 12.5t-63 4.5q-167 0 -351 -93q-15 -8 -21 -27q-10 -36 -24.5 -105.5t-22.5 -100.5q-23 -91 -70 -179.5t-112.5 -164.5t-154.5 -123t-185 -47q-135 0 -214.5 83.5t-79.5 219.5q0 53 19.5 117t63 116.5t97.5 52.5q38 0 120 -33.5t83 -61.5
q0 -1 -16.5 -12.5t-39.5 -31t-46 -44.5t-39 -61t-16 -74q0 -33 16.5 -53t48.5 -20q45 0 85 31.5t66.5 78t48 105.5t32.5 107t16 90v9q0 2 -3.5 3.5t-8.5 1.5h-10t-10 -0.5t-6 -0.5q-227 0 -352 122.5t-125 348.5q0 108 34.5 221t96 210t156 167.5t204.5 89.5q52 9 106 9
q374 0 374 -360q0 -98 -38 -273t-43 -211l3 -3q101 57 182.5 88t167.5 31q22 0 53 -13q19 -7 80 -102.5t61 -116.5z" />
    <glyph glyph-name="uniF2A7" unicode="&#xf2a7;" horiz-adv-x="1664" 
d="M831 863q32 0 59 -18l222 -148q61 -40 110 -97l146 -170q40 -46 29 -106l-72 -413q-6 -32 -29.5 -53.5t-55.5 -25.5l-527 -56l-352 -32h-9q-39 0 -67.5 28t-28.5 68q0 37 27 64t65 32l260 32h-448q-41 0 -69.5 30t-26.5 71q2 39 32 65t69 26l442 1l-521 64q-41 5 -66 37
t-19 73q6 35 34.5 57.5t65.5 22.5h10l481 -60l-351 94q-38 10 -62 41.5t-18 68.5q6 36 33 58.5t62 22.5q6 0 20 -2l448 -96l217 -37q1 0 3 -0.5t3 -0.5q23 0 30.5 23t-12.5 36l-186 125q-35 23 -42 63.5t18 73.5q27 38 76 38zM761 661l186 -125l-218 37l-5 2l-36 38
l-238 262q-1 1 -2.5 3.5t-2.5 3.5q-24 31 -18.5 70t37.5 64q31 23 68 17.5t64 -33.5l142 -147q-2 -1 -5 -3.5t-4 -4.5q-32 -45 -23 -99t55 -85zM1648 1115l15 -266q4 -73 -11 -147l-48 -219q-12 -59 -67 -87l-106 -54q2 62 -39 109l-146 170q-53 61 -117 103l-222 148
q-34 23 -76 23q-51 0 -88 -37l-235 312q-25 33 -18 73.5t41 63.5q33 22 71.5 14t62.5 -40l266 -352l-262 455q-21 35 -10.5 75t47.5 59q35 18 72.5 6t57.5 -46l241 -420l-136 337q-15 35 -4.5 74t44.5 56q37 19 76 6t56 -51l193 -415l101 -196q8 -15 23 -17.5t27 7.5t11 26
l-12 224q-2 41 26 71t69 31q39 0 67 -28.5t30 -67.5z" />
    <glyph glyph-name="uniF2A8" unicode="&#xf2a8;" horiz-adv-x="1792" 
d="M335 180q-2 0 -6 2q-86 57 -168.5 145t-139.5 180q-21 30 -21 69q0 9 2 19t4 18t7 18t8.5 16t10.5 17t10 15t12 15.5t11 14.5q184 251 452 365q-110 198 -110 211q0 19 17 29q116 64 128 64q18 0 28 -16l124 -229q92 19 192 19q266 0 497.5 -137.5t378.5 -369.5
q20 -31 20 -69t-20 -69q-91 -142 -218.5 -253.5t-278.5 -175.5q110 -198 110 -211q0 -20 -17 -29q-116 -64 -127 -64q-19 0 -29 16l-124 229l-64 119l-444 820l7 7q-58 -24 -99 -47q3 -5 127 -234t243 -449t119 -223q0 -7 -9 -9q-13 -3 -72 -3q-57 0 -60 7l-456 841
q-39 -28 -82 -68q24 -43 214 -393.5t190 -354.5q0 -10 -11 -10q-14 0 -82.5 22t-72.5 28l-106 197l-224 413q-44 -53 -78 -106q2 -3 18 -25t23 -34l176 -327q0 -10 -10 -10zM1165 282l49 -91q273 111 450 385q-180 277 -459 389q67 -64 103 -148.5t36 -176.5
q0 -106 -47 -200.5t-132 -157.5zM848 896q0 -20 14 -34t34 -14q86 0 147 -61t61 -147q0 -20 14 -34t34 -14t34 14t14 34q0 126 -89 215t-215 89q-20 0 -34 -14t-14 -34zM1214 961l-9 4l7 -7z" />
    <glyph glyph-name="uniF2A9" unicode="&#xf2a9;" horiz-adv-x="1280" 
d="M1050 430q0 -215 -147 -374q-148 -161 -378 -161q-232 0 -378 161q-147 159 -147 374q0 147 68 270.5t189 196.5t268 73q96 0 182 -31q-32 -62 -39 -126q-66 28 -143 28q-167 0 -280.5 -123t-113.5 -291q0 -170 112.5 -288.5t281.5 -118.5t281 118.5t112 288.5
q0 89 -32 166q66 13 123 49q41 -98 41 -212zM846 619q0 -192 -79.5 -345t-238.5 -253l-14 -1q-29 0 -62 5q83 32 146.5 102.5t99.5 154.5t58.5 189t30 192.5t7.5 178.5q0 69 -3 103q55 -160 55 -326zM791 947v-2q-73 214 -206 440q88 -59 142.5 -186.5t63.5 -251.5z
M1035 744q-83 0 -160 75q218 120 290 247q19 37 21 56q-42 -94 -139.5 -166.5t-204.5 -97.5q-35 54 -35 113q0 37 17 79t43 68q46 44 157 74q59 16 106 58.5t74 100.5q74 -105 74 -253q0 -109 -24 -170q-32 -77 -88.5 -130.5t-130.5 -53.5z" />
    <glyph glyph-name="uniF2AA" unicode="&#xf2aa;" 
d="M1050 495q0 78 -28 147q-41 -25 -85 -34q22 -50 22 -114q0 -117 -77 -198.5t-193 -81.5t-193.5 81.5t-77.5 198.5q0 115 78 199.5t193 84.5q53 0 98 -19q4 43 27 87q-60 21 -125 21q-154 0 -257.5 -108.5t-103.5 -263.5t103.5 -261t257.5 -106t257.5 106.5t103.5 260.5z
M872 850q2 -24 2 -71q0 -63 -5 -123t-20.5 -132.5t-40.5 -130t-68.5 -106t-100.5 -70.5q21 -3 42 -3h10q219 139 219 411q0 116 -38 225zM872 850q-4 80 -44 171.5t-98 130.5q92 -156 142 -302zM1207 955q0 102 -51 174q-41 -86 -124 -109q-69 -19 -109 -53.5t-40 -99.5
q0 -40 24 -77q74 17 140.5 67t95.5 115q-4 -52 -74.5 -111.5t-138.5 -97.5q52 -52 110 -52q51 0 90 37t60 90q17 42 17 117zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5
t84.5 -203.5z" />
    <glyph glyph-name="uniF2AB" unicode="&#xf2ab;" 
d="M1279 388q0 22 -22 27q-67 15 -118 59t-80 108q-7 19 -7 25q0 15 19.5 26t43 17t43 20.5t19.5 36.5q0 19 -18.5 31.5t-38.5 12.5q-12 0 -32 -8t-31 -8q-4 0 -12 2q5 95 5 114q0 79 -17 114q-36 78 -103 121.5t-152 43.5q-199 0 -275 -165q-17 -35 -17 -114q0 -19 5 -114
q-4 -2 -14 -2q-12 0 -32 7.5t-30 7.5q-21 0 -38.5 -12t-17.5 -32q0 -21 19.5 -35.5t43 -20.5t43 -17t19.5 -26q0 -6 -7 -25q-64 -138 -198 -167q-22 -5 -22 -27q0 -46 137 -68q2 -5 6 -26t11.5 -30.5t23.5 -9.5q12 0 37.5 4.5t39.5 4.5q35 0 67 -15t54 -32.5t57.5 -32.5
t76.5 -15q43 0 79 15t57.5 32.5t53.5 32.5t67 15q14 0 39.5 -4t38.5 -4q16 0 23 10t11 30t6 25q137 22 137 68zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5
t103 -385.5z" />
    <glyph glyph-name="uniF2AC" unicode="&#xf2ac;" horiz-adv-x="1664" 
d="M848 1408q134 1 240.5 -68.5t163.5 -192.5q27 -58 27 -179q0 -47 -9 -191q14 -7 28 -7q18 0 51 13.5t51 13.5q29 0 56 -18t27 -46q0 -32 -31.5 -54t-69 -31.5t-69 -29t-31.5 -47.5q0 -15 12 -43q37 -82 102.5 -150t144.5 -101q28 -12 80 -23q28 -6 28 -35
q0 -70 -219 -103q-7 -11 -11 -39t-14 -46.5t-33 -18.5q-20 0 -62 6.5t-64 6.5q-37 0 -62 -5q-32 -5 -63 -22.5t-58 -38t-58 -40.5t-76 -33.5t-99 -13.5q-52 0 -96.5 13.5t-75 33.5t-57.5 40.5t-58 38t-62 22.5q-26 5 -63 5q-24 0 -65.5 -7.5t-58.5 -7.5q-25 0 -35 18.5
t-14 47.5t-11 40q-219 33 -219 103q0 29 28 35q52 11 80 23q78 32 144.5 101t102.5 150q12 28 12 43q0 28 -31.5 47.5t-69.5 29.5t-69.5 31.5t-31.5 52.5q0 27 26 45.5t55 18.5q15 0 48 -13t53 -13q18 0 32 7q-9 142 -9 190q0 122 27 180q64 137 172 198t264 63z" />
    <glyph glyph-name="uniF2AD" unicode="&#xf2ad;" 
d="M1280 388q0 22 -22 27q-67 14 -118 58t-80 109q-7 14 -7 25q0 15 19.5 26t42.5 17t42.5 20.5t19.5 36.5q0 19 -18.5 31.5t-38.5 12.5q-11 0 -31 -8t-32 -8q-4 0 -12 2q5 63 5 115q0 78 -17 114q-36 78 -102.5 121.5t-152.5 43.5q-198 0 -275 -165q-18 -38 -18 -115
q0 -38 6 -114q-10 -2 -15 -2q-11 0 -31.5 8t-30.5 8q-20 0 -37.5 -12.5t-17.5 -32.5q0 -21 19.5 -35.5t42.5 -20.5t42.5 -17t19.5 -26q0 -11 -7 -25q-64 -138 -198 -167q-22 -5 -22 -27q0 -47 138 -69q2 -5 6 -26t11 -30.5t23 -9.5q13 0 38.5 5t38.5 5q35 0 67.5 -15
t54.5 -32.5t57.5 -32.5t76.5 -15q43 0 79 15t57.5 32.5t54 32.5t67.5 15q13 0 39 -4.5t39 -4.5q15 0 22.5 9.5t11.5 31t5 24.5q138 22 138 69zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960
q119 0 203.5 -84.5t84.5 -203.5z" />
    <glyph glyph-name="uniF2AE" unicode="&#xf2ae;" horiz-adv-x="2304" 
d="M2304 1536q-69 -46 -125 -92t-89 -81t-59.5 -71.5t-37.5 -57.5t-22 -44.5t-14 -29.5q-10 -18 -35.5 -136.5t-48.5 -164.5q-15 -29 -50 -60.5t-67.5 -50.5t-72.5 -41t-48 -28q-47 -31 -151 -231q-341 14 -630 -158q-92 -53 -303 -179q47 16 86 31t55 22l15 7
q71 27 163 64.5t133.5 53.5t108 34.5t142.5 31.5q186 31 465 -7q1 0 10 -3q11 -6 14 -17t-3 -22l-194 -345q-15 -29 -47 -22q-128 24 -354 24q-146 0 -402 -44.5t-392 -46.5q-82 -1 -149 13t-107 37t-61 40t-33 34l-1 1v2q0 6 6 6q138 0 371 55q192 366 374.5 524t383.5 158
q5 0 14.5 -0.5t38 -5t55 -12t61.5 -24.5t63 -39.5t54 -59t40 -82.5l102 177q2 4 21 42.5t44.5 86.5t61 109.5t84 133.5t100.5 137q66 82 128 141.5t121.5 96.5t92.5 53.5t88 39.5z" />
    <glyph glyph-name="uniF2B0" unicode="&#xf2b0;" 
d="M1322 640q0 -45 -5 -76l-236 14l224 -78q-19 -73 -58 -141l-214 103l177 -158q-44 -61 -107 -108l-157 178l103 -215q-61 -37 -140 -59l-79 228l14 -240q-38 -6 -76 -6t-76 6l14 238l-78 -226q-74 19 -140 59l103 215l-157 -178q-59 43 -108 108l178 158l-214 -104
q-39 69 -58 141l224 79l-237 -14q-5 42 -5 76q0 35 5 77l238 -14l-225 79q19 73 58 140l214 -104l-177 159q46 61 107 108l158 -178l-103 215q67 39 140 58l77 -224l-13 236q36 6 75 6q38 0 76 -6l-14 -237l78 225q74 -19 140 -59l-103 -214l158 178q61 -47 107 -108
l-177 -159l213 104q37 -62 58 -141l-224 -78l237 14q5 -31 5 -77zM1352 640q0 160 -78.5 295.5t-213 214t-292.5 78.5q-119 0 -227 -46.5t-186.5 -125t-124.5 -187.5t-46 -229q0 -119 46 -228t124.5 -187.5t186.5 -125t227 -46.5q158 0 292.5 78.5t213 214t78.5 294.5z
M1425 1023v-766l-657 -383l-657 383v766l657 383zM768 -183l708 412v823l-708 411l-708 -411v-823zM1536 1088v-896l-768 -448l-768 448v896l768 448z" />
    <glyph glyph-name="uniF2B1" unicode="&#xf2b1;" horiz-adv-x="1664" 
d="M339 1318h691l-26 -72h-665q-110 0 -188.5 -79t-78.5 -189v-771q0 -95 60.5 -169.5t153.5 -93.5q23 -5 98 -5v-72h-45q-140 0 -239.5 100t-99.5 240v771q0 140 99.5 240t239.5 100zM1190 1536h247l-482 -1294q-23 -61 -40.5 -103.5t-45 -98t-54 -93.5t-64.5 -78.5
t-79.5 -65t-95.5 -41t-116 -18.5v195q163 26 220 182q20 52 20 105q0 54 -20 106l-285 733h228l187 -585zM1664 978v-1111h-795q37 55 45 73h678v1038q0 85 -49.5 155t-129.5 99l25 67q101 -34 163.5 -123.5t62.5 -197.5z" />
    <glyph glyph-name="uniF2B2" unicode="&#xf2b2;" horiz-adv-x="1792" 
d="M852 1227q0 -29 -17 -52.5t-45 -23.5t-45 23.5t-17 52.5t17 52.5t45 23.5t45 -23.5t17 -52.5zM688 -149v114q0 30 -20.5 51.5t-50.5 21.5t-50 -21.5t-20 -51.5v-114q0 -30 20.5 -52t49.5 -22q30 0 50.5 22t20.5 52zM860 -149v114q0 30 -20 51.5t-50 21.5t-50.5 -21.5
t-20.5 -51.5v-114q0 -30 20.5 -52t50.5 -22q29 0 49.5 22t20.5 52zM1034 -149v114q0 30 -20.5 51.5t-50.5 21.5t-50.5 -21.5t-20.5 -51.5v-114q0 -30 20.5 -52t50.5 -22t50.5 22t20.5 52zM1208 -149v114q0 30 -20.5 51.5t-50.5 21.5t-50.5 -21.5t-20.5 -51.5v-114
q0 -30 20.5 -52t50.5 -22t50.5 22t20.5 52zM1476 535q-84 -160 -232 -259.5t-323 -99.5q-123 0 -229.5 51.5t-178.5 137t-113 197.5t-41 232q0 88 21 174q-104 -175 -104 -390q0 -162 65 -312t185 -251q30 57 91 57q56 0 86 -50q32 50 87 50q56 0 86 -50q32 50 87 50t87 -50
q30 50 86 50q28 0 52.5 -15.5t37.5 -40.5q112 94 177 231.5t73 287.5zM1326 564q0 75 -72 75q-17 0 -47 -6q-95 -19 -149 -19q-226 0 -226 243q0 86 30 204q-83 -127 -83 -275q0 -150 89 -260.5t235 -110.5q111 0 210 70q13 48 13 79zM884 1223q0 50 -32 89.5t-81 39.5
t-81 -39.5t-32 -89.5q0 -51 31.5 -90.5t81.5 -39.5t81.5 39.5t31.5 90.5zM1513 884q0 96 -37.5 179t-113 137t-173.5 54q-77 0 -149 -35t-127 -94q-48 -159 -48 -268q0 -104 45.5 -157t147.5 -53q53 0 142 19q36 6 53 6q51 0 77.5 -28t26.5 -80q0 -26 -4 -46
q75 68 117.5 165.5t42.5 200.5zM1792 667q0 -111 -33.5 -249.5t-93.5 -204.5q-58 -64 -195 -142.5t-228 -104.5l-4 -1v-114q0 -43 -29.5 -75t-72.5 -32q-56 0 -86 50q-32 -50 -87 -50t-87 50q-30 -50 -86 -50q-55 0 -87 50q-30 -50 -86 -50q-47 0 -75 33.5t-28 81.5
q-90 -68 -198 -68q-118 0 -211 80q54 1 106 20q-113 31 -182 127q32 -7 71 -7q89 0 164 46q-192 192 -240 306q-24 56 -24 160q0 57 9 125.5t31.5 146.5t55 141t86.5 105t120 42q59 0 81 -52q19 29 42 54q2 3 12 13t13 16q10 15 23 38t25 42t28 39q87 111 211.5 177
t260.5 66q35 0 62 -4q59 64 146 64q83 0 140 -57q5 -5 5 -12q0 -5 -6 -13.5t-12.5 -16t-16 -17l-10.5 -10.5q17 -6 36 -18t19 -24q0 -6 -16 -25q157 -138 197 -378q25 30 60 30q45 0 100 -49q90 -80 90 -279z" />
    <glyph glyph-name="uniF2B3" unicode="&#xf2b3;" 
d="M917 631q0 33 -6 64h-362v-132h217q-12 -76 -74.5 -120.5t-142.5 -44.5q-99 0 -169 71.5t-70 170.5t70 170.5t169 71.5q93 0 153 -59l104 101q-108 100 -257 100q-160 0 -272 -112.5t-112 -271.5t112 -271.5t272 -112.5q165 0 266.5 105t101.5 270zM1262 585h109v110
h-109v110h-110v-110h-110v-110h110v-110h110v110zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
    <glyph glyph-name="uniF2B4" unicode="&#xf2b4;" 
d="M1536 1024v-839q0 -48 -49 -62q-174 -52 -338 -52q-73 0 -215.5 29.5t-227.5 29.5q-164 0 -370 -48v-338h-160v1368q-63 25 -101 81t-38 124q0 91 64 155t155 64t155 -64t64 -155q0 -68 -38 -124t-101 -81v-68q190 44 343 44q99 0 198 -15q14 -2 111.5 -22.5t149.5 -20.5
q77 0 165 18q11 2 80 21t89 19q26 0 45 -19t19 -45z" />
    <glyph glyph-name="uniF2B5" unicode="&#xf2b5;" horiz-adv-x="2304" 
d="M192 384q40 0 56 32t0 64t-56 32t-56 -32t0 -64t56 -32zM1665 442q-10 13 -38.5 50t-41.5 54t-38 49t-42.5 53t-40.5 47t-45 49l-125 -140q-83 -94 -208.5 -92t-205.5 98q-57 69 -56.5 158t58.5 157l177 206q-22 11 -51 16.5t-47.5 6t-56.5 -0.5t-49 -1q-92 0 -158 -66
l-158 -158h-155v-544q5 0 21 0.5t22 0t19.5 -2t20.5 -4.5t17.5 -8.5t18.5 -13.5l297 -292q115 -111 227 -111q78 0 125 47q57 -20 112.5 8t72.5 85q74 -6 127 44q20 18 36 45.5t14 50.5q10 -10 43 -10q43 0 77 21t49.5 53t12 71.5t-30.5 73.5zM1824 384h96v512h-93l-157 180
q-66 76 -169 76h-167q-89 0 -146 -67l-209 -243q-28 -33 -28 -75t27 -75q43 -51 110 -52t111 49l193 218q25 23 53.5 21.5t47 -27t8.5 -56.5q16 -19 56 -63t60 -68q29 -36 82.5 -105.5t64.5 -84.5q52 -66 60 -140zM2112 384q40 0 56 32t0 64t-56 32t-56 -32t0 -64t56 -32z
M2304 960v-640q0 -26 -19 -45t-45 -19h-434q-27 -65 -82 -106.5t-125 -51.5q-33 -48 -80.5 -81.5t-102.5 -45.5q-42 -53 -104.5 -81.5t-128.5 -24.5q-60 -34 -126 -39.5t-127.5 14t-117 53.5t-103.5 81l-287 282h-358q-26 0 -45 19t-19 45v672q0 26 19 45t45 19h421
q14 14 47 48t47.5 48t44 40t50.5 37.5t51 25.5t62 19.5t68 5.5h117q99 0 181 -56q82 56 181 56h167q35 0 67 -6t56.5 -14.5t51.5 -26.5t44.5 -31t43 -39.5t39 -42t41 -48t41.5 -48.5h355q26 0 45 -19t19 -45z" />
    <glyph glyph-name="uniF2B6" unicode="&#xf2b6;" horiz-adv-x="1792" 
d="M1792 882v-978q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v978q0 15 11 24q8 7 39 34.5t41.5 36t45.5 37.5t70 55.5t96 73t143.5 107t192.5 140.5q5 4 52.5 40t71.5 52.5t64 35t69 18.5t69 -18.5t65 -35.5t71 -52t52 -40q110 -80 192.5 -140.5t143.5 -107
t96 -73t70 -55.5t45.5 -37.5t41.5 -36t39 -34.5q11 -9 11 -24zM1228 297q263 191 345 252q11 8 12.5 20.5t-6.5 23.5l-38 52q-8 11 -21 12.5t-24 -6.5q-231 -169 -343 -250q-5 -3 -52 -39t-71.5 -52.5t-64.5 -35t-69 -18.5t-69 18.5t-64.5 35t-71.5 52.5t-52 39
q-186 134 -343 250q-11 8 -24 6.5t-21 -12.5l-38 -52q-8 -11 -6.5 -23.5t12.5 -20.5q82 -61 345 -252q10 -8 50 -38t65 -47t64 -39.5t77.5 -33.5t75.5 -11t75.5 11t79 34.5t64.5 39.5t65 47.5t48 36.5z" />
    <glyph glyph-name="uniF2B7" unicode="&#xf2b7;" horiz-adv-x="1792" 
d="M1474 623l39 -51q8 -11 6.5 -23.5t-11.5 -20.5q-43 -34 -126.5 -98.5t-146.5 -113t-67 -51.5q-39 -32 -60 -48t-60.5 -41t-76.5 -36.5t-74 -11.5h-1h-1q-37 0 -74 11.5t-76 36.5t-61 41.5t-60 47.5q-5 4 -65 50.5t-143.5 111t-122.5 94.5q-11 8 -12.5 20.5t6.5 23.5
l37 52q8 11 21.5 13t24.5 -7q94 -73 306 -236q5 -4 43.5 -35t60.5 -46.5t56.5 -32.5t58.5 -17h1h1q24 0 58.5 17t56.5 32.5t60.5 46.5t43.5 35q258 198 313 242q11 8 24 6.5t21 -12.5zM1664 -96v928q-90 83 -159 139q-91 74 -389 304q-3 2 -43 35t-61 48t-56 32.5t-59 17.5
h-1h-1q-24 0 -59 -17.5t-56 -32.5t-61 -48t-43 -35q-215 -166 -315.5 -245.5t-129.5 -104t-82 -74.5q-14 -12 -21 -19v-928q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1792 832v-928q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v928q0 56 41 94
q123 114 350 290.5t233 181.5q36 30 59 47.5t61.5 42t76 36.5t74.5 12h1h1q37 0 74.5 -12t76 -36.5t61.5 -42t59 -47.5q43 -36 156 -122t226 -177t201 -173q41 -38 41 -94z" />
    <glyph glyph-name="uniF2B8" unicode="&#xf2b8;" 
d="M330 1l202 -214l-34 236l-216 213zM556 -225l274 218l-11 245l-300 -215zM245 413l227 -213l-48 327l-245 204zM495 189l317 214l-14 324l-352 -200zM843 178l95 -80l-2 239l-103 79q0 -1 1 -8.5t0 -12t-5 -7.5l-78 -52l85 -70q7 -6 7 -88zM138 930l256 -200l-68 465
l-279 173zM1173 267l15 234l-230 -164l2 -240zM417 722l373 194l-19 441l-423 -163zM1270 357l20 233l-226 142l-2 -105l144 -95q6 -4 4 -9l-7 -119zM1461 496l30 222l-179 -128l-20 -228zM1273 329l-71 49l-8 -117q0 -5 -4 -8l-234 -187q-7 -5 -14 0l-98 83l7 -161
q0 -5 -4 -8l-293 -234q-4 -2 -6 -2q-8 2 -8 3l-228 242q-4 4 -59 277q-2 7 5 11l61 37q-94 86 -95 92l-72 351q-2 7 6 12l94 45q-133 100 -135 108l-96 466q-2 10 7 13l433 135q5 0 8 -1l317 -153q6 -4 6 -9l20 -463q0 -7 -6 -10l-118 -61l126 -85q5 -2 5 -8l5 -123l121 74
q5 4 11 0l84 -56l3 110q0 6 5 9l206 126q6 3 11 0l245 -135q4 -4 5 -7t-6.5 -60t-17.5 -124.5t-10 -70.5q0 -5 -4 -7l-191 -153q-6 -5 -13 0z" />
    <glyph glyph-name="uniF2B9" unicode="&#xf2b9;" horiz-adv-x="1664" 
d="M1201 298q0 57 -5.5 107t-21 100.5t-39.5 86t-64 58t-91 22.5q-6 -4 -33.5 -20.5t-42.5 -24.5t-40.5 -20t-49 -17t-46.5 -5t-46.5 5t-49 17t-40.5 20t-42.5 24.5t-33.5 20.5q-51 0 -91 -22.5t-64 -58t-39.5 -86t-21 -100.5t-5.5 -107q0 -73 42 -121.5t103 -48.5h576
q61 0 103 48.5t42 121.5zM1028 892q0 108 -76.5 184t-183.5 76t-183.5 -76t-76.5 -184q0 -107 76.5 -183t183.5 -76t183.5 76t76.5 183zM1664 352v-192q0 -14 -9 -23t-23 -9h-96v-224q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v1472q0 66 47 113t113 47h1216
q66 0 113 -47t47 -113v-224h96q14 0 23 -9t9 -23v-192q0 -14 -9 -23t-23 -9h-96v-128h96q14 0 23 -9t9 -23v-192q0 -14 -9 -23t-23 -9h-96v-128h96q14 0 23 -9t9 -23z" />
    <glyph glyph-name="uniF2BA" unicode="&#xf2ba;" horiz-adv-x="1664" 
d="M1028 892q0 -107 -76.5 -183t-183.5 -76t-183.5 76t-76.5 183q0 108 76.5 184t183.5 76t183.5 -76t76.5 -184zM980 672q46 0 82.5 -17t60 -47.5t39.5 -67t24 -81t11.5 -82.5t3.5 -79q0 -67 -39.5 -118.5t-105.5 -51.5h-576q-66 0 -105.5 51.5t-39.5 118.5q0 48 4.5 93.5
t18.5 98.5t36.5 91.5t63 64.5t93.5 26h5q7 -4 32 -19.5t35.5 -21t33 -17t37 -16t35 -9t39.5 -4.5t39.5 4.5t35 9t37 16t33 17t35.5 21t32 19.5zM1664 928q0 -13 -9.5 -22.5t-22.5 -9.5h-96v-128h96q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-96v-128h96
q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-96v-224q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v1472q0 66 47 113t113 47h1216q66 0 113 -47t47 -113v-224h96q13 0 22.5 -9.5t9.5 -22.5v-192zM1408 -96v1472q0 13 -9.5 22.5t-22.5 9.5h-1216
q-13 0 -22.5 -9.5t-9.5 -22.5v-1472q0 -13 9.5 -22.5t22.5 -9.5h1216q13 0 22.5 9.5t9.5 22.5z" />
    <glyph glyph-name="uniF2BB" unicode="&#xf2bb;" horiz-adv-x="2048" 
d="M1024 405q0 64 -9 117.5t-29.5 103t-60.5 78t-97 28.5q-6 -4 -30 -18t-37.5 -21.5t-35.5 -17.5t-43 -14.5t-42 -4.5t-42 4.5t-43 14.5t-35.5 17.5t-37.5 21.5t-30 18q-57 0 -97 -28.5t-60.5 -78t-29.5 -103t-9 -117.5t37 -106.5t91 -42.5h512q54 0 91 42.5t37 106.5z
M867 925q0 94 -66.5 160.5t-160.5 66.5t-160.5 -66.5t-66.5 -160.5t66.5 -160.5t160.5 -66.5t160.5 66.5t66.5 160.5zM1792 416v64q0 14 -9 23t-23 9h-576q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h576q14 0 23 9t9 23zM1792 676v56q0 15 -10.5 25.5t-25.5 10.5h-568
q-15 0 -25.5 -10.5t-10.5 -25.5v-56q0 -15 10.5 -25.5t25.5 -10.5h568q15 0 25.5 10.5t10.5 25.5zM1792 928v64q0 14 -9 23t-23 9h-576q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h576q14 0 23 9t9 23zM2048 1248v-1216q0 -66 -47 -113t-113 -47h-352v96q0 14 -9 23t-23 9
h-64q-14 0 -23 -9t-9 -23v-96h-768v96q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-96h-352q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1728q66 0 113 -47t47 -113z" />
    <glyph glyph-name="uniF2BC" unicode="&#xf2bc;" horiz-adv-x="2048" 
d="M1024 405q0 -64 -37 -106.5t-91 -42.5h-512q-54 0 -91 42.5t-37 106.5t9 117.5t29.5 103t60.5 78t97 28.5q6 -4 30 -18t37.5 -21.5t35.5 -17.5t43 -14.5t42 -4.5t42 4.5t43 14.5t35.5 17.5t37.5 21.5t30 18q57 0 97 -28.5t60.5 -78t29.5 -103t9 -117.5zM867 925
q0 -94 -66.5 -160.5t-160.5 -66.5t-160.5 66.5t-66.5 160.5t66.5 160.5t160.5 66.5t160.5 -66.5t66.5 -160.5zM1792 480v-64q0 -14 -9 -23t-23 -9h-576q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h576q14 0 23 -9t9 -23zM1792 732v-56q0 -15 -10.5 -25.5t-25.5 -10.5h-568
q-15 0 -25.5 10.5t-10.5 25.5v56q0 15 10.5 25.5t25.5 10.5h568q15 0 25.5 -10.5t10.5 -25.5zM1792 992v-64q0 -14 -9 -23t-23 -9h-576q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h576q14 0 23 -9t9 -23zM1920 32v1216q0 13 -9.5 22.5t-22.5 9.5h-1728q-13 0 -22.5 -9.5
t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h352v96q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-96h768v96q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-96h352q13 0 22.5 9.5t9.5 22.5zM2048 1248v-1216q0 -66 -47 -113t-113 -47h-1728q-66 0 -113 47t-47 113v1216q0 66 47 113
t113 47h1728q66 0 113 -47t47 -113z" />
    <glyph glyph-name="uniF2BD" unicode="&#xf2bd;" horiz-adv-x="1792" 
d="M1523 197q-22 155 -87.5 257.5t-184.5 118.5q-67 -74 -159.5 -115.5t-195.5 -41.5t-195.5 41.5t-159.5 115.5q-119 -16 -184.5 -118.5t-87.5 -257.5q106 -150 271 -237.5t356 -87.5t356 87.5t271 237.5zM1280 896q0 159 -112.5 271.5t-271.5 112.5t-271.5 -112.5
t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM1792 640q0 -182 -71 -347.5t-190.5 -286t-285.5 -191.5t-349 -71q-182 0 -348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
    <glyph glyph-name="uniF2BE" unicode="&#xf2be;" horiz-adv-x="1792" 
d="M896 1536q182 0 348 -71t286 -191t191 -286t71 -348q0 -181 -70.5 -347t-190.5 -286t-286 -191.5t-349 -71.5t-349 71t-285.5 191.5t-190.5 286t-71 347.5t71 348t191 286t286 191t348 71zM1515 185q149 205 149 455q0 156 -61 298t-164 245t-245 164t-298 61t-298 -61
t-245 -164t-164 -245t-61 -298q0 -250 149 -455q66 327 306 327q131 -128 313 -128t313 128q240 0 306 -327zM1280 832q0 159 -112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5z" />
    <glyph glyph-name="uniF2C0" unicode="&#xf2c0;" 
d="M1201 752q47 -14 89.5 -38t89 -73t79.5 -115.5t55 -172t22 -236.5q0 -154 -100 -263.5t-241 -109.5h-854q-141 0 -241 109.5t-100 263.5q0 131 22 236.5t55 172t79.5 115.5t89 73t89.5 38q-79 125 -79 272q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5
t198.5 -40.5t163.5 -109.5t109.5 -163.5t40.5 -198.5q0 -147 -79 -272zM768 1408q-159 0 -271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5t-112.5 271.5t-271.5 112.5zM1195 -128q88 0 150.5 71.5t62.5 173.5q0 239 -78.5 377t-225.5 145
q-145 -127 -336 -127t-336 127q-147 -7 -225.5 -145t-78.5 -377q0 -102 62.5 -173.5t150.5 -71.5h854z" />
    <glyph glyph-name="uniF2C1" unicode="&#xf2c1;" horiz-adv-x="1280" 
d="M1024 278q0 -64 -37 -107t-91 -43h-512q-54 0 -91 43t-37 107t9 118t29.5 104t61 78.5t96.5 28.5q80 -75 188 -75t188 75q56 0 96.5 -28.5t61 -78.5t29.5 -104t9 -118zM870 797q0 -94 -67.5 -160.5t-162.5 -66.5t-162.5 66.5t-67.5 160.5t67.5 160.5t162.5 66.5
t162.5 -66.5t67.5 -160.5zM1152 -96v1376h-1024v-1376q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1280 1376v-1472q0 -66 -47 -113t-113 -47h-960q-66 0 -113 47t-47 113v1472q0 66 47 113t113 47h352v-96q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v96h352
q66 0 113 -47t47 -113z" />
    <glyph glyph-name="uniF2C2" unicode="&#xf2c2;" horiz-adv-x="2048" 
d="M896 324q0 54 -7.5 100.5t-24.5 90t-51 68.5t-81 25q-64 -64 -156 -64t-156 64q-47 0 -81 -25t-51 -68.5t-24.5 -90t-7.5 -100.5q0 -55 31.5 -93.5t75.5 -38.5h426q44 0 75.5 38.5t31.5 93.5zM768 768q0 80 -56 136t-136 56t-136 -56t-56 -136t56 -136t136 -56t136 56
t56 136zM1792 288v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM1408 544v64q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1792 544v64q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23
v-64q0 -14 9 -23t23 -9h192q14 0 23 9t9 23zM1792 800v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM128 1152h1792v96q0 14 -9 23t-23 9h-1728q-14 0 -23 -9t-9 -23v-96zM2048 1248v-1216q0 -66 -47 -113t-113 -47h-1728
q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1728q66 0 113 -47t47 -113z" />
    <glyph glyph-name="uniF2C3" unicode="&#xf2c3;" horiz-adv-x="2048" 
d="M896 324q0 -55 -31.5 -93.5t-75.5 -38.5h-426q-44 0 -75.5 38.5t-31.5 93.5q0 54 7.5 100.5t24.5 90t51 68.5t81 25q64 -64 156 -64t156 64q47 0 81 -25t51 -68.5t24.5 -90t7.5 -100.5zM768 768q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136z
M1792 352v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23zM1408 608v-64q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h320q14 0 23 -9t9 -23zM1792 608v-64q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v64
q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 864v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23zM1920 32v1120h-1792v-1120q0 -13 9.5 -22.5t22.5 -9.5h1728q13 0 22.5 9.5t9.5 22.5zM2048 1248v-1216q0 -66 -47 -113t-113 -47
h-1728q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1728q66 0 113 -47t47 -113z" />
    <glyph glyph-name="uniF2C4" unicode="&#xf2c4;" horiz-adv-x="1792" 
d="M1255 749q0 318 -105 474.5t-330 156.5q-222 0 -326 -157t-104 -474q0 -316 104 -471.5t326 -155.5q74 0 131 17q-22 43 -39 73t-44 65t-53.5 56.5t-63 36t-77.5 14.5q-46 0 -79 -16l-49 97q105 91 276 91q132 0 215.5 -54t150.5 -155q67 149 67 402zM1645 117h117
q3 -27 -2 -67t-26.5 -95t-58 -100.5t-107 -78t-162.5 -32.5q-71 0 -130.5 19t-105.5 56t-79 78t-66 96q-97 -27 -205 -27q-150 0 -292.5 58t-253 158.5t-178 249t-67.5 317.5q0 170 67.5 319.5t178.5 250.5t253.5 159t291.5 58q121 0 238.5 -36t217 -106t176 -164.5
t119.5 -219t43 -261.5q0 -190 -80.5 -347.5t-218.5 -264.5q47 -70 93.5 -106.5t104.5 -36.5q61 0 94 37.5t38 85.5z" />
    <glyph glyph-name="uniF2C5" unicode="&#xf2c5;" horiz-adv-x="2304" 
d="M453 -101q0 -21 -16 -37.5t-37 -16.5q-1 0 -13 3q-63 15 -162 140q-225 284 -225 676q0 341 213 614q39 51 95 103.5t94 52.5q19 0 35 -13.5t16 -32.5q0 -27 -63 -90q-98 -102 -147 -184q-119 -199 -119 -449q0 -281 123 -491q50 -85 136 -173q2 -3 14.5 -16t19.5 -21
t17 -20.5t14.5 -23.5t4.5 -21zM1796 33q0 -29 -17.5 -48.5t-46.5 -19.5h-1081q-26 0 -45 19t-19 45q0 29 17.5 48.5t46.5 19.5h1081q26 0 45 -19t19 -45zM1581 644q0 -134 -67 -233q-25 -38 -69.5 -78.5t-83.5 -60.5q-16 -10 -27 -10q-7 0 -15 6t-8 12q0 9 19 30t42 46
t42 67.5t19 88.5q0 76 -35 130q-29 42 -46 42q-3 0 -3 -5q0 -12 7.5 -35.5t7.5 -36.5q0 -22 -21.5 -35t-44.5 -13q-66 0 -66 76q0 15 1.5 44t1.5 44q0 25 -10 46q-13 25 -42 53.5t-51 28.5q-5 0 -7 -0.5t-3.5 -2.5t-1.5 -6q0 -2 16 -26t16 -54q0 -37 -19 -68t-46 -54
t-53.5 -46t-45.5 -54t-19 -68q0 -98 42 -160q29 -43 79 -63q16 -5 17 -10q1 -2 1 -5q0 -16 -18 -16q-6 0 -33 11q-119 43 -195 139.5t-76 218.5q0 55 24.5 115.5t60 115t70.5 108.5t59.5 113.5t24.5 111.5q0 53 -25 94q-29 48 -56 64q-19 9 -19 21q0 20 41 20q50 0 110 -29
q41 -19 71 -44.5t49.5 -51t33.5 -62.5t22 -69t16 -80q0 -1 3 -17.5t4.5 -25t5.5 -25t9 -27t11 -21.5t14.5 -16.5t18.5 -5.5q23 0 37 14t14 37q0 25 -20 67t-20 52t10 10q27 0 93 -70q72 -76 102.5 -156t30.5 -186zM2304 615q0 -274 -138 -503q-19 -32 -48 -72t-68 -86.5
t-81 -77t-74 -30.5q-16 0 -31 15.5t-15 31.5q0 15 29 50.5t68.5 77t48.5 52.5q183 230 183 531q0 131 -20.5 235t-72.5 211q-58 119 -163 228q-2 3 -13 13.5t-16.5 16.5t-15 17.5t-15 20t-9.5 18.5t-4 19q0 19 16 35.5t35 16.5q70 0 196 -169q98 -131 146 -273t60 -314
q2 -42 2 -64z" />
    <glyph glyph-name="uniF2C6" unicode="&#xf2c6;" horiz-adv-x="1792" 
d="M1189 229l147 693q9 44 -10.5 63t-51.5 7l-864 -333q-29 -11 -39.5 -25t-2.5 -26.5t32 -19.5l221 -69l513 323q21 14 32 6q7 -5 -4 -15l-415 -375v0v0l-16 -228q23 0 45 22l108 104l224 -165q64 -36 81 38zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71
t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
    <glyph glyph-name="uniF2C7" unicode="&#xf2c7;" horiz-adv-x="1024" 
d="M640 192q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 60 35 110t93 71v907h128v-907q58 -21 93 -71t35 -110zM768 192q0 77 -34 144t-94 112v768q0 80 -56 136t-136 56t-136 -56t-56 -136v-768q-60 -45 -94 -112t-34 -144q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5
t93.5 226.5zM896 192q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 182 128 313v711q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5v-711q128 -131 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192
v128h192z" />
    <glyph glyph-name="uniF2C8" unicode="&#xf2c8;" horiz-adv-x="1024" 
d="M640 192q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 60 35 110t93 71v651h128v-651q58 -21 93 -71t35 -110zM768 192q0 77 -34 144t-94 112v768q0 80 -56 136t-136 56t-136 -56t-56 -136v-768q-60 -45 -94 -112t-34 -144q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5
t93.5 226.5zM896 192q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 182 128 313v711q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5v-711q128 -131 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192
v128h192z" />
    <glyph glyph-name="uniF2C9" unicode="&#xf2c9;" horiz-adv-x="1024" 
d="M640 192q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 60 35 110t93 71v395h128v-395q58 -21 93 -71t35 -110zM768 192q0 77 -34 144t-94 112v768q0 80 -56 136t-136 56t-136 -56t-56 -136v-768q-60 -45 -94 -112t-34 -144q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5
t93.5 226.5zM896 192q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 182 128 313v711q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5v-711q128 -131 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192
v128h192z" />
    <glyph glyph-name="uniF2CA" unicode="&#xf2ca;" horiz-adv-x="1024" 
d="M640 192q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 60 35 110t93 71v139h128v-139q58 -21 93 -71t35 -110zM768 192q0 77 -34 144t-94 112v768q0 80 -56 136t-136 56t-136 -56t-56 -136v-768q-60 -45 -94 -112t-34 -144q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5
t93.5 226.5zM896 192q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 182 128 313v711q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5v-711q128 -131 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192
v128h192z" />
    <glyph glyph-name="uniF2CB" unicode="&#xf2cb;" horiz-adv-x="1024" 
d="M640 192q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 79 56 135.5t136 56.5t136 -56.5t56 -135.5zM768 192q0 77 -34 144t-94 112v768q0 80 -56 136t-136 56t-136 -56t-56 -136v-768q-60 -45 -94 -112t-34 -144q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5t93.5 226.5z
M896 192q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 182 128 313v711q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5v-711q128 -131 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192v128h192z" />
    <glyph glyph-name="uniF2CC" unicode="&#xf2cc;" horiz-adv-x="1920" 
d="M1433 1287q10 -10 10 -23t-10 -23l-626 -626q-10 -10 -23 -10t-23 10l-82 82q-10 10 -10 23t10 23l44 44q-72 91 -81.5 207t46.5 215q-74 71 -176 71q-106 0 -181 -75t-75 -181v-1280h-256v1280q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5q106 0 201 -41
t166 -115q94 39 197 24.5t185 -79.5l44 44q10 10 23 10t23 -10zM1344 1024q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1600 896q-26 0 -45 19t-19 45t19 45t45 19t45 -19t19 -45t-19 -45t-45 -19zM1856 1024q26 0 45 -19t19 -45t-19 -45t-45 -19
t-45 19t-19 45t19 45t45 19zM1216 896q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1408 832q0 26 19 45t45 19t45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45zM1728 896q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1088 768
q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1344 640q-26 0 -45 19t-19 45t19 45t45 19t45 -19t19 -45t-19 -45t-45 -19zM1600 768q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1216 512q-26 0 -45 19t-19 45t19 45t45 19t45 -19
t19 -45t-19 -45t-45 -19zM1472 640q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1088 512q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1344 512q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1216 384
q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1088 256q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19z" />
    <glyph glyph-name="uniF2CD" unicode="&#xf2cd;" horiz-adv-x="1792" 
d="M1664 448v-192q0 -169 -128 -286v-194q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v118q-63 -22 -128 -22h-768q-65 0 -128 22v-110q0 -17 -9.5 -28.5t-22.5 -11.5h-64q-13 0 -22.5 11.5t-9.5 28.5v186q-128 117 -128 286v192h1536zM704 864q0 -14 -9 -23t-23 -9t-23 9
t-9 23t9 23t23 9t23 -9t9 -23zM768 928q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM704 992q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM832 992q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM768 1056q0 -14 -9 -23t-23 -9t-23 9
t-9 23t9 23t23 9t23 -9t9 -23zM704 1120q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM1792 608v-64q0 -14 -9 -23t-23 -9h-1728q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v640q0 106 75 181t181 75q108 0 184 -78q46 19 98 12t93 -39l22 22q11 11 22 0l42 -42
q11 -11 0 -22l-314 -314q-11 -11 -22 0l-42 42q-11 11 0 22l22 22q-36 46 -40.5 104t23.5 108q-37 35 -88 35q-53 0 -90.5 -37.5t-37.5 -90.5v-640h1504q14 0 23 -9t9 -23zM896 1056q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM832 1120q0 -14 -9 -23t-23 -9
t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM768 1184q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM960 1120q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM896 1184q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM832 1248q0 -14 -9 -23
t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM1024 1184q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM960 1248q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM1088 1248q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23z" />
    <glyph glyph-name="uniF2CE" unicode="&#xf2ce;" 
d="M994 344q0 -86 -17 -197q-31 -215 -55 -313q-22 -90 -152 -90t-152 90q-24 98 -55 313q-17 110 -17 197q0 168 224 168t224 -168zM1536 768q0 -240 -134 -434t-350 -280q-8 -3 -15 3t-6 15q7 48 10 66q4 32 6 47q1 9 9 12q159 81 255.5 234t96.5 337q0 180 -91 330.5
t-247 234.5t-337 74q-124 -7 -237 -61t-193.5 -140.5t-128 -202t-46.5 -240.5q1 -184 99 -336.5t257 -231.5q7 -3 9 -12q3 -21 6 -45q1 -9 5 -32.5t6 -35.5q1 -9 -6.5 -15t-15.5 -2q-148 58 -261 169.5t-173.5 264t-52.5 319.5q7 143 66 273.5t154.5 227t225 157.5t272.5 70
q164 10 315.5 -46.5t261 -160.5t175 -250.5t65.5 -308.5zM994 800q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5zM1282 768q0 -122 -53.5 -228.5t-146.5 -177.5q-8 -6 -16 -2t-10 14q-6 52 -29 92q-7 10 3 20
q58 54 91 127t33 155q0 111 -58.5 204t-157.5 141.5t-212 36.5q-133 -15 -229 -113t-109 -231q-10 -92 23.5 -176t98.5 -144q10 -10 3 -20q-24 -41 -29 -93q-2 -9 -10 -13t-16 2q-95 74 -148.5 183t-51.5 234q3 131 69 244t177 181.5t241 74.5q144 7 268 -60t196.5 -187.5
t72.5 -263.5z" />
    <glyph glyph-name="uniF2D0" unicode="&#xf2d0;" horiz-adv-x="1792" 
d="M256 128h1280v768h-1280v-768zM1792 1248v-1216q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
    <glyph glyph-name="uniF2D1" unicode="&#xf2d1;" horiz-adv-x="1792" 
d="M1792 224v-192q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v192q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
    <glyph glyph-name="uniF2D2" unicode="&#xf2d2;" horiz-adv-x="2048" 
d="M256 0h768v512h-768v-512zM1280 512h512v768h-768v-256h96q66 0 113 -47t47 -113v-352zM2048 1376v-960q0 -66 -47 -113t-113 -47h-608v-352q0 -66 -47 -113t-113 -47h-960q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h608v352q0 66 47 113t113 47h960q66 0 113 -47
t47 -113z" />
    <glyph glyph-name="uniF2D3" unicode="&#xf2d3;" horiz-adv-x="1792" 
d="M1175 215l146 146q10 10 10 23t-10 23l-233 233l233 233q10 10 10 23t-10 23l-146 146q-10 10 -23 10t-23 -10l-233 -233l-233 233q-10 10 -23 10t-23 -10l-146 -146q-10 -10 -10 -23t10 -23l233 -233l-233 -233q-10 -10 -10 -23t10 -23l146 -146q10 -10 23 -10t23 10
l233 233l233 -233q10 -10 23 -10t23 10zM1792 1248v-1216q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
    <glyph glyph-name="uniF2D4" unicode="&#xf2d4;" horiz-adv-x="1792" 
d="M1257 425l-146 -146q-10 -10 -23 -10t-23 10l-169 169l-169 -169q-10 -10 -23 -10t-23 10l-146 146q-10 10 -10 23t10 23l169 169l-169 169q-10 10 -10 23t10 23l146 146q10 10 23 10t23 -10l169 -169l169 169q10 10 23 10t23 -10l146 -146q10 -10 10 -23t-10 -23
l-169 -169l169 -169q10 -10 10 -23t-10 -23zM256 128h1280v1024h-1280v-1024zM1792 1248v-1216q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
    <glyph glyph-name="uniF2D5" unicode="&#xf2d5;" horiz-adv-x="1792" 
d="M1070 358l306 564h-654l-306 -564h654zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
    <glyph glyph-name="uniF2D6" unicode="&#xf2d6;" horiz-adv-x="1794" 
d="M1291 1060q-15 17 -35 8.5t-26 -28.5t5 -38q14 -17 40 -14.5t34 20.5t-18 52zM895 814q-8 -8 -19.5 -8t-18.5 8q-8 8 -8 19t8 18q7 8 18.5 8t19.5 -8q7 -7 7 -18t-7 -19zM1060 740l-35 -35q-12 -13 -29.5 -13t-30.5 13l-38 38q-12 13 -12 30t12 30l35 35q12 12 29.5 12
t30.5 -12l38 -39q12 -12 12 -29.5t-12 -29.5zM951 870q-7 -8 -18.5 -8t-19.5 8q-7 8 -7 19t7 19q8 8 19 8t19 -8t8 -19t-8 -19zM1354 968q-34 -64 -107.5 -85.5t-127.5 16.5q-38 28 -61 66.5t-21 87.5t39 92t75.5 53t70.5 -5t70 -51q2 -2 13 -12.5t14.5 -13.5t13 -13.5
t12.5 -15.5t10 -15.5t8.5 -18t4 -18.5t1 -21t-5 -22t-9.5 -24zM1555 486q3 20 -8.5 34.5t-27.5 21.5t-33 17t-23 20q-40 71 -84 98.5t-113 11.5q19 13 40 18.5t33 4.5l12 -1q2 45 -34 90q6 20 6.5 40.5t-2.5 30.5l-3 10q43 24 71 65t34 91q10 84 -43 150.5t-137 76.5
q-60 7 -114 -18.5t-82 -74.5q-30 -51 -33.5 -101t14.5 -87t43.5 -64t56.5 -42q-45 4 -88 36t-57 88q-28 108 32 222q-16 21 -29 32q-50 0 -89 -19q19 24 42 37t36 14l13 1q0 50 -13 78q-10 21 -32.5 28.5t-47 -3.5t-37.5 -40q2 4 4 7q-7 -28 -6.5 -75.5t19 -117t48.5 -122.5
q-25 -14 -47 -36q-35 -16 -85.5 -70.5t-84.5 -101.5l-33 -46q-90 -34 -181 -125.5t-75 -162.5q1 -16 11 -27q-15 -12 -30 -30q-21 -25 -21 -54t21.5 -40t63.5 6q41 19 77 49.5t55 60.5q-2 2 -6.5 5t-20.5 7.5t-33 3.5q23 5 51 12.5t40 10t27.5 6t26 4t23.5 0.5q14 -7 22 34
q7 37 7 90q0 102 -40 150q106 -103 101 -219q-1 -29 -15 -50t-27 -27l-13 -6q-4 -7 -19 -32t-26 -45.5t-26.5 -52t-25 -61t-17 -63t-6.5 -66.5t10 -63q-35 54 -37 80q-22 -24 -34.5 -39t-33.5 -42t-30.5 -46t-16.5 -41t-0.5 -38t25.5 -27q45 -25 144 64t190.5 221.5
t122.5 228.5q86 52 145 115.5t86 119.5q47 -93 154 -178q104 -83 167 -80q39 2 46 43zM1794 640q0 -182 -71 -348t-191 -286t-286.5 -191t-348.5 -71t-348.5 71t-286.5 191t-191 286t-71 348t71 348t191 286t286.5 191t348.5 71t348.5 -71t286.5 -191t191 -286t71 -348z" />
    <glyph glyph-name="uniF2D7" unicode="&#xf2d7;" 
d="M518 1353v-655q103 -1 191.5 1.5t125.5 5.5l37 3q68 2 90.5 24.5t39.5 94.5l33 142h103l-14 -322l7 -319h-103l-29 127q-15 68 -45 93t-84 26q-87 8 -352 8v-556q0 -78 43.5 -115.5t133.5 -37.5h357q35 0 59.5 2t55 7.5t54 18t48.5 32t46 50.5t39 73l93 216h89
q-6 -37 -31.5 -252t-30.5 -276q-146 5 -263.5 8t-162.5 4h-44h-628l-376 -12v102l127 25q67 13 91.5 37t25.5 79l8 643q3 402 -8 645q-2 61 -25.5 84t-91.5 36l-127 24v102l376 -12h702q139 0 374 27q-6 -68 -14 -194.5t-12 -219.5l-5 -92h-93l-32 124q-31 121 -74 179.5
t-113 58.5h-548q-28 0 -35.5 -8.5t-7.5 -30.5z" />
    <glyph glyph-name="uniF2D8" unicode="&#xf2d8;" 
d="M922 739v-182q0 -4 0.5 -15t0 -15l-1.5 -12t-3.5 -11.5t-6.5 -7.5t-11 -5.5t-16 -1.5v309q9 0 16 -1t11 -5t6.5 -5.5t3.5 -9.5t1 -10.5v-13.5v-14zM1238 643v-121q0 -1 0.5 -12.5t0 -15.5t-2.5 -11.5t-7.5 -10.5t-13.5 -3q-9 0 -14 9q-4 10 -4 165v7v8.5v9t1.5 8.5l3.5 7
t5 5.5t8 1.5q6 0 10 -1.5t6.5 -4.5t4 -6t2 -8.5t0.5 -8v-9.5v-9zM180 407h122v472h-122v-472zM614 407h106v472h-159l-28 -221q-20 148 -32 221h-158v-472h107v312l45 -312h76l43 319v-319zM1039 712q0 67 -5 90q-3 16 -11 28.5t-17 20.5t-25 14t-26.5 8.5t-31 4t-29 1.5
h-29.5h-12h-91v-472h56q169 -1 197 24.5t25 180.5q-1 62 -1 100zM1356 515v133q0 29 -2 45t-9.5 33.5t-24.5 25t-46 7.5q-46 0 -77 -34v154h-117v-472h110l7 30q30 -36 77 -36q50 0 66 30.5t16 83.5zM1536 1248v-1216q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113
v1216q0 66 47 113t113 47h1216q66 0 113 -47t47 -113z" />
    <glyph glyph-name="uniF2D9" unicode="&#xf2d9;" horiz-adv-x="2176" 
d="M1143 -197q-6 1 -11 4q-13 8 -36 23t-86 65t-116.5 104.5t-112 140t-89.5 172.5q-17 3 -175 37q66 -213 235 -362t391 -184zM502 409l168 -28q-25 76 -41 167.5t-19 145.5l-4 53q-84 -82 -121 -224q5 -65 17 -114zM612 1018q-43 -64 -77 -148q44 46 74 68zM2049 584
q0 161 -62 307t-167.5 252t-250.5 168.5t-304 62.5q-147 0 -281 -52.5t-240 -148.5q-30 -58 -45 -160q60 51 143 83.5t158.5 43t143 13.5t108.5 -1l40 -3q33 -1 53 -15.5t24.5 -33t6.5 -37t-1 -28.5q-126 11 -227.5 0.5t-183 -43.5t-142.5 -71.5t-131 -98.5
q4 -36 11.5 -92.5t35.5 -178t62 -179.5q123 -6 247.5 14.5t214.5 53.5t162.5 67t109.5 59l37 24q22 16 39.5 20.5t30.5 -5t17 -34.5q14 -97 -39 -121q-208 -97 -467 -134q-135 -20 -317 -16q41 -96 110 -176.5t137 -127t130.5 -79t101.5 -43.5l39 -12q143 -23 263 15
q195 99 314 289t119 418zM2123 621q-14 -135 -40 -212q-70 -208 -181.5 -346.5t-318.5 -253.5q-48 -33 -82 -44q-72 -26 -163 -16q-36 -3 -73 -3q-283 0 -504.5 173t-295.5 442q-1 0 -4 0.5t-5 0.5q-6 -50 2.5 -112.5t26 -115t36 -98t31.5 -71.5l14 -26q8 -12 54 -82
q-71 38 -124.5 106.5t-78.5 140t-39.5 137t-17.5 107.5l-2 42q-5 2 -33.5 12.5t-48.5 18t-53 20.5t-57.5 25t-50 25.5t-42.5 27t-25 25.5q19 -10 50.5 -25.5t113 -45.5t145.5 -38l2 32q11 149 94 290q41 202 176 365q28 115 81 214q15 28 32 45t49 32q158 74 303.5 104
t302 11t306.5 -97q220 -115 333 -336t87 -474z" />
    <glyph glyph-name="uniF2DA" unicode="&#xf2da;" horiz-adv-x="1792" 
d="M1341 752q29 44 -6.5 129.5t-121.5 142.5q-58 39 -125.5 53.5t-118 4.5t-68.5 -37q-12 -23 -4.5 -28t42.5 -10q23 -3 38.5 -5t44.5 -9.5t56 -17.5q36 -13 67.5 -31.5t53 -37t40 -38.5t30.5 -38t22 -34.5t16.5 -28.5t12 -18.5t10.5 -6t11 9.5zM1704 178
q-52 -127 -148.5 -220t-214.5 -141.5t-253 -60.5t-266 13.5t-251 91t-210 161.5t-141.5 235.5t-46.5 303.5q1 41 8.5 84.5t12.5 64t24 80.5t23 73q-51 -208 1 -397t173 -318t291 -206t346 -83t349 74.5t289 244.5q20 27 18 14q0 -4 -4 -14zM1465 627q0 -104 -40.5 -199
t-108.5 -164t-162 -109.5t-198 -40.5t-198 40.5t-162 109.5t-108.5 164t-40.5 199t40.5 199t108.5 164t162 109.5t198 40.5t198 -40.5t162 -109.5t108.5 -164t40.5 -199zM1752 915q-65 147 -180.5 251t-253 153.5t-292 53.5t-301 -36.5t-275.5 -129t-220 -211.5t-131 -297
t-10 -373q-49 161 -51.5 311.5t35.5 272.5t109 227t165.5 180.5t207 126t232 71t242.5 9t236 -54t216 -124.5t178 -197q33 -50 62 -121t31 -112zM1690 573q12 244 -136.5 416t-396.5 240q-8 0 -10 5t24 8q125 -4 230 -50t173 -120t116 -168.5t58.5 -199t-1 -208
t-61.5 -197.5t-122.5 -167t-185 -117.5t-248.5 -46.5q108 30 201.5 80t174 123t129.5 176.5t55 225.5z" />
    <glyph glyph-name="uniF2DB" unicode="&#xf2db;" 
d="M192 256v-128h-112q-16 0 -16 16v16h-48q-16 0 -16 16v32q0 16 16 16h48v16q0 16 16 16h112zM192 512v-128h-112q-16 0 -16 16v16h-48q-16 0 -16 16v32q0 16 16 16h48v16q0 16 16 16h112zM192 768v-128h-112q-16 0 -16 16v16h-48q-16 0 -16 16v32q0 16 16 16h48v16
q0 16 16 16h112zM192 1024v-128h-112q-16 0 -16 16v16h-48q-16 0 -16 16v32q0 16 16 16h48v16q0 16 16 16h112zM192 1280v-128h-112q-16 0 -16 16v16h-48q-16 0 -16 16v32q0 16 16 16h48v16q0 16 16 16h112zM1280 1440v-1472q0 -40 -28 -68t-68 -28h-832q-40 0 -68 28
t-28 68v1472q0 40 28 68t68 28h832q40 0 68 -28t28 -68zM1536 208v-32q0 -16 -16 -16h-48v-16q0 -16 -16 -16h-112v128h112q16 0 16 -16v-16h48q16 0 16 -16zM1536 464v-32q0 -16 -16 -16h-48v-16q0 -16 -16 -16h-112v128h112q16 0 16 -16v-16h48q16 0 16 -16zM1536 720v-32
q0 -16 -16 -16h-48v-16q0 -16 -16 -16h-112v128h112q16 0 16 -16v-16h48q16 0 16 -16zM1536 976v-32q0 -16 -16 -16h-48v-16q0 -16 -16 -16h-112v128h112q16 0 16 -16v-16h48q16 0 16 -16zM1536 1232v-32q0 -16 -16 -16h-48v-16q0 -16 -16 -16h-112v128h112q16 0 16 -16v-16
h48q16 0 16 -16z" />
    <glyph glyph-name="uniF2DC" unicode="&#xf2dc;" horiz-adv-x="1664" 
d="M1566 419l-167 -33l186 -107q23 -13 29.5 -38.5t-6.5 -48.5q-14 -23 -39 -29.5t-48 6.5l-186 106l55 -160q13 -38 -12 -63.5t-60.5 -20.5t-48.5 42l-102 300l-271 156v-313l208 -238q16 -18 17 -39t-11 -36.5t-28.5 -25t-37 -5.5t-36.5 22l-112 128v-214q0 -26 -19 -45
t-45 -19t-45 19t-19 45v214l-112 -128q-16 -18 -36.5 -22t-37 5.5t-28.5 25t-11 36.5t17 39l208 238v313l-271 -156l-102 -300q-13 -37 -48.5 -42t-60.5 20.5t-12 63.5l55 160l-186 -106q-23 -13 -48 -6.5t-39 29.5q-13 23 -6.5 48.5t29.5 38.5l186 107l-167 33
q-29 6 -42 29t-8.5 46.5t25.5 40t50 10.5l310 -62l271 157l-271 157l-310 -62q-4 -1 -13 -1q-27 0 -44 18t-19 40t11 43t40 26l167 33l-186 107q-23 13 -29.5 38.5t6.5 48.5t39 30t48 -7l186 -106l-55 160q-13 38 12 63.5t60.5 20.5t48.5 -42l102 -300l271 -156v313
l-208 238q-16 18 -17 39t11 36.5t28.5 25t37 5.5t36.5 -22l112 -128v214q0 26 19 45t45 19t45 -19t19 -45v-214l112 128q16 18 36.5 22t37 -5.5t28.5 -25t11 -36.5t-17 -39l-208 -238v-313l271 156l102 300q13 37 48.5 42t60.5 -20.5t12 -63.5l-55 -160l186 106
q23 13 48 6.5t39 -29.5q13 -23 6.5 -48.5t-29.5 -38.5l-186 -107l167 -33q27 -5 40 -26t11 -43t-19 -40t-44 -18q-9 0 -13 1l-310 62l-271 -157l271 -157l310 62q29 6 50 -10.5t25.5 -40t-8.5 -46.5t-42 -29z" />
    <glyph glyph-name="uniF2DD" unicode="&#xf2dd;" horiz-adv-x="1792" 
d="M1473 607q7 118 -33 226.5t-113 189t-177 131t-221 57.5q-116 7 -225.5 -32t-192 -110.5t-135 -175t-59.5 -220.5q-7 -118 33 -226.5t113 -189t177.5 -131t221.5 -57.5q155 -9 293 59t224 195.5t94 283.5zM1792 1536l-349 -348q120 -117 180.5 -272t50.5 -321
q-11 -183 -102 -339t-241 -255.5t-332 -124.5l-999 -132l347 347q-120 116 -180.5 271.5t-50.5 321.5q11 184 102 340t241.5 255.5t332.5 124.5q167 22 500 66t500 66z" />
    <glyph glyph-name="uniF2DE" unicode="&#xf2de;" horiz-adv-x="1792" 
d="M948 508l163 -329h-51l-175 350l-171 -350h-49l179 374l-78 33l21 49l240 -102l-21 -50zM563 1100l304 -130l-130 -304l-304 130zM907 915l240 -103l-103 -239l-239 102zM1188 765l191 -81l-82 -190l-190 81zM1680 640q0 159 -62 304t-167.5 250.5t-250.5 167.5t-304 62
t-304 -62t-250.5 -167.5t-167.5 -250.5t-62 -304t62 -304t167.5 -250.5t250.5 -167.5t304 -62t304 62t250.5 167.5t167.5 250.5t62 304zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71
t286 -191t191 -286t71 -348z" />
    <glyph glyph-name="uniF2E0" unicode="&#xf2e0;" horiz-adv-x="1920" 
d="M1334 302q-4 24 -27.5 34t-49.5 10.5t-48.5 12.5t-25.5 38q-5 47 33 139.5t75 181t32 127.5q-14 101 -117 103q-45 1 -75 -16l-3 -2l-5 -2.5t-4.5 -2t-5 -2t-5 -0.5t-6 1.5t-6 3.5t-6.5 5q-3 2 -9 8.5t-9 9t-8.5 7.5t-9.5 7.5t-9.5 5.5t-11 4.5t-11.5 2.5q-30 5 -48 -3
t-45 -31q-1 -1 -9 -8.5t-12.5 -11t-15 -10t-16.5 -5.5t-17 3q-54 27 -84 40q-41 18 -94 -5t-76 -65q-16 -28 -41 -98.5t-43.5 -132.5t-40 -134t-21.5 -73q-22 -69 18.5 -119t110.5 -46q30 2 50.5 15t38.5 46q7 13 79 199.5t77 194.5q6 11 21.5 18t29.5 0q27 -15 21 -53
q-2 -18 -51 -139.5t-50 -132.5q-6 -38 19.5 -56.5t60.5 -7t55 49.5q4 8 45.5 92t81.5 163.5t46 88.5q20 29 41 28q29 0 25 -38q-2 -16 -65.5 -147.5t-70.5 -159.5q-12 -53 13 -103t74 -74q17 -9 51 -15.5t71.5 -8t62.5 14t20 48.5zM383 86q3 -15 -5 -27.5t-23 -15.5
q-14 -3 -26.5 5t-15.5 23q-3 14 5 27t22 16t27 -5t16 -23zM953 -177q12 -17 8.5 -37.5t-20.5 -32.5t-37.5 -8t-32.5 21q-11 17 -7.5 37.5t20.5 32.5t37.5 8t31.5 -21zM177 635q-18 -27 -49.5 -33t-57.5 13q-26 18 -32 50t12 58q18 27 49.5 33t57.5 -12q26 -19 32 -50.5
t-12 -58.5zM1467 -42q19 -28 13 -61.5t-34 -52.5t-60.5 -13t-51.5 34t-13 61t33 53q28 19 60.5 13t52.5 -34zM1579 562q69 -113 42.5 -244.5t-134.5 -207.5q-90 -63 -199 -60q-20 -80 -84.5 -127t-143.5 -44.5t-140 57.5q-12 -9 -13 -10q-103 -71 -225 -48.5t-193 126.5
q-50 73 -53 164q-83 14 -142.5 70.5t-80.5 128t-2 152t81 138.5q-36 60 -38 128t24.5 125t79.5 98.5t121 50.5q32 85 99 148t146.5 91.5t168 17t159.5 -66.5q72 21 140 17.5t128.5 -36t104.5 -80t67.5 -115t17.5 -140.5q52 -16 87 -57t45.5 -89t-5.5 -99.5t-58 -87.5z
M455 1222q14 -20 9.5 -44.5t-24.5 -38.5q-19 -14 -43.5 -9.5t-37.5 24.5q-14 20 -9.5 44.5t24.5 38.5q19 14 43.5 9.5t37.5 -24.5zM614 1503q4 -16 -5 -30.5t-26 -18.5t-31 5.5t-18 26.5q-3 17 6.5 31t25.5 18q17 4 31 -5.5t17 -26.5zM1800 555q4 -20 -6.5 -37t-30.5 -21
q-19 -4 -36 6.5t-21 30.5t6.5 37t30.5 22q20 4 36.5 -7.5t20.5 -30.5zM1136 1448q16 -27 8.5 -58.5t-35.5 -47.5q-27 -16 -57.5 -8.5t-46.5 34.5q-16 28 -8.5 59t34.5 48t58 9t47 -36zM1882 792q4 -15 -4 -27.5t-23 -16.5q-15 -3 -27.5 5.5t-15.5 22.5q-3 15 5 28t23 16
q14 3 26.5 -5t15.5 -23zM1691 1033q15 -22 10.5 -49t-26.5 -43q-22 -15 -49 -10t-42 27t-10 49t27 43t48.5 11t41.5 -28z" />
    <glyph glyph-name="uniF2E1" unicode="&#xf2e1;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="uniF2E2" unicode="&#xf2e2;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="uniF2E3" unicode="&#xf2e3;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="uniF2E4" unicode="&#xf2e4;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="uniF2E5" unicode="&#xf2e5;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="uniF2E6" unicode="&#xf2e6;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="uniF2E7" unicode="&#xf2e7;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="_698" unicode="&#xf2e8;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="uniF2E9" unicode="&#xf2e9;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="uniF2EA" unicode="&#xf2ea;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="uniF2EB" unicode="&#xf2eb;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="uniF2EC" unicode="&#xf2ec;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="uniF2ED" unicode="&#xf2ed;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="uniF2EE" unicode="&#xf2ee;" horiz-adv-x="1792" 
 />
    <glyph glyph-name="lessequal" unicode="&#xf500;" horiz-adv-x="1792" 
 />
  </font>
</defs></svg>
libs/better-framework/assets/fonts/bs-icons.ttf000064400000044600151214002620015641 0ustar00
�PFFTMz�.IdGDEFzID OS/2��
�XVcmapv	gT�gasp��I<glyfzv"�?thead�bM�6hhea0�$hmtx	����locau��:<�maxp�)8 name���DL�post�06�F'�~�_<�����������.M&@�LfGLf��	PfEd@��a��.�7%3+nI77a&#Ml%C"GE@IrN'���)�9�I�Y�a����0�@�P�`��O�O�^p	
<
=+ !"#$%&'()*,-./0123456789:;>?@(|x����N�j�h��R4�	>	�	�
jVR�
^
�
���FX�n��h�Z���&p�b����&`���
T��@j��� Dn���%n�3##5#535476;#"$J	Aa118A(aQ��Q14Q
I��7#"'327"&'327&'&=3&'&547&54632676�!!)*2MA?40	
#1386'(
�)!&!*($!+
&6!	��
!"+3=S`&'&/263&'#676767676#/&#"67"&462'327&'72164'67.'&'&�
+
_t
_o3
iP�;J*!I$������n0:B'( 	%-		G	C0%%.+M9
�_,28=,�}�����?%W+BVPF8		PJE1U5��;'&'&'&'&'&'67676763276'&676�FF8  

	($	-'
=5(*j_TS'mj

 
"U'@ B7I��	(J6"&462+"'&5&'&'&'&=476;+"'&5&'.'&'"'&=476;�.  .�	'/.B,+)! �	)R79<MBC74 �* . J	A/.'	!,'1@57R)	74EH%��/S�7#"'&'&54767632#"'&'&547676324'&#""'&#";2767676767+&'&'&'&'&'&547&54726326763�						�						.!
+0+
!	

0

	@!)	'(1)''�
		
		

		

		!!		L;$

$;D- 
	 /V�y�4?637213263476767>56'4'&/&'"767623327676767674763?367633#'&/&'&'&'&""+'&'&'&/&'&'&'&'&'&I
1

M.	'E

	
	
a	
			&=
&		

			'0%%��7463!2#!"&733276=#5#"%0""00"��"0ɉɉw"00"��"00�����q!+7N7#"/7632#"5'7432"5'742"5'742#"/7632"=47632632#'	,-./		!-!!
��$%%88UU68qq66rr55��<�,X�%/[lq2+32'327654'&/254'&/#%2#3276?3"'&'&'&=4767676'454'&'&'&#"7#53�



��'
�W
&			\G$		�



7%

T

v��
K+[J�+
X�	
	*

c	
�((3����S4767676762#"'&'#&54?&547632327654'&#"'&'&3	#$T$%
.-I	"'	
,"!<D()4
! [;;P%/#�#

//C4 !+)>$!"�\3276767676767275#"'&547623327654'&#"&'&'&'&'&'
			
		#3!

 		
6%+#5
	�E2;&)""
  =!!:
%'1:" !%70.G6!%%-%B�7CQ5326?2>4'&'&#"&#"'3767654'&/632#"'&64762"/32654'&#"%'>�'@&"!&'"WN?&
	 
..�N8J, , q#8'c&@N &~ �

	
. .�N8&%C,, �t264&"264&"D`DD`�D`DD`0`DD`DD`DD`D+�;5'753773+�4,3*2PV��m$X9
'(
,T%�R=2767>76767#!"&463!2"'.'&'./.'.'&'&
t\2
�\�b$		
3R�O		@"�DE		$
	
n��"%&'&=35#5#3327675#"(llB'?$ "$n
*wRj%
A�!
H��zo��37676"#"'&/#"3276?32767>76327676'&'&#"'&'&'&#&'&'&#"#47>75;5#2'&'&'&5476762'&'&5"7676+



		-	


$

21��	

		�
:>	


$*,	
!
's	
	
X��1S%'654&#"326=4%67&547&#";547/67654'.#"3!26=4�S!$		59	��
$"T		7 H	((
K
�(+*&
F	B,%
*,'B	F"
$#
#
RR%�3f#"'#"'&=?25767>767>767&'&547676222#'&'&'#"'3276767654'�/05#-"-0j0/�#-#M:0(+!$&*MP"!!(!"!�!&
"$%<I%��'=D%54'&+";276=4'&+";2767#!"'&5476;37#5n����I
��

���
YwMi���$�Y'/7#";26=4&+"&=46;2&"264"&4626"&462g�@YY@�@YY%;*�*;;*�*;�nMMnMbD//D/SY@�@YY@�@Y��*;;*�*;;*MnMMn�/D//D�R#"'7&5462"732654&&'&'&'&'&'&7>7676'&'&+"?>7>�hB8�-$��hX|)Q6?W||( 

	%


	


nΓ,�:Gg�({VE6N#{WV{��
	)
!


	��+9D\s51'=#&'&'&#"332?67676%#"=4632327"&=432#"/#"&=476542#"=4;2+32+32�	)(;26L=;@(#=.$U4��, 
"

m	,		,X<:.%%096,+!k:=0-
	>&B]Q]]	<5Z<8g]
>� '/8#32656&#32654'#32654&#3254'#3254#32654'#32654&vGK(#]IK(#�IK(#0HKLIKK�HK($IK(#�a ��a *�a aX2&�X2&5a *�a ��8cz��.'&?327>76'"&574#.'&7>76&'&'&'&'&76763>76#"'4'.'&"'"'&3"'5&54'&'&'.#"5431"'4'&'&'"&'&6�	D&yx%E	A$6A7&D	B3=C
*33op3�
M,
	
.

P-C1!

	^
			%%&�%BB%fe#@
69B%e[1+I2[\21\� 1)

5	
	
6,	"2v	+	
&��r%654&#"&#"32732654#"'&'&547632327654'&'&'&'&'&54767632#"'&'&'&#"�~X $5L}X&5L�
#+
	


!

#
	
		�X~K6$ Y}K6%!
	


	
	
				

Z�P#54&+"#";;2=32=4%2?64/#&#"32767='&+";#"'&476� + 

 +
 ��(!C1101GH+#
�H$#!!!+ 

 +6	(/1EF010$9!1K*�� ?676&"/&7%6�-w,>xOH�	#ֶ#�>X	}Z�Ko�7%�&6%#"'&"#"'&5476323276326767�
&$&-)* 2 	!!
S

3�'!8
	
	JIF@+)	

!#H+7��&F^m2764'&#"3264&#"2"'&=47%+"'&=#"'&5'#"'&=7!4767'&766276"'&=462�}�		D		
			(		
		�!�� <t		v



5
{
		{
�	A
		AA		A	

�t!"%&&�{		
{

a�*76'&?7676'&'&'&54'&'&�&C
%B*Q 
+
V!	8E�92[E(b04=4+M8
pv-]+6&�*3.67>?>'>.'./&'�
E.&NE	,.
&&"p55"9$)(W0�L,qc^7;,G&b�6  k=\�	264&#"75464&/�+<<+*<<�y/"x/m/!y/"x2<V<<V<4�%G3�$Hl$H
4�%G3��##!T��������#�Q%&'&6?5>././967674&/.>?&7>?3676&�-
$	<	1
N	&+�*/		
%2;6=61="'0qY6!!..$#.+f
 ,W�Xb'&5&>'747.'&67&'&>'&'.>77>767>75476&7>?�$%%$'.	'H&*	"%//-
!!


&3W6�`	3<mC	/ 0#',+'%	F=$6	))'/G/



4#	v
j:0SDH&L:7!�� #3264&'"732654&#532	%%f�)kFXe��^kk4$%I@~%4%��f41b9�ef����$%34IM�'7654&#"32?6&�y=�y>	

��F��	F�
�	l�!)1%67>'."'&2?264'2"&4264&"5,!	 
)a(
 	!,J
"
II �,!!,!nMMnM�	

	I!HH!p!,!!,�MnMMn%2��2#7#"'&47632#54'&#"#6='3676767632�^dM^^^


1M��X

,
壘�LmU
)  CL��I>322'&"'&&'&'&'&5&67676'&/&76=676p-
#1#
0

8%O
 	

0
	4

67#%�#!;4&54&#!"7!26�$���nT��n��%
II����I�4#"'"'&'&754?>76767>7&'&5476767632"";;F
9K
."#//4F;;"3f)*1


%&*$#"
*	�M64&#"3264&"264'&#"3276#"'"'&5&?>376767>76?.5476762�




��




x"";;F 0M)0"";;�;;"�
 
 
Mf)*0	
H)3)**-=N^nz�����#+"&=#+"&=#+"&=#"3!2654&#!"&=463!2'3276=4&+";26=4&+"!326=4&+"32+"=432+"=4732+"=432+"=4732+"=432+"=4�
;
1
$

�

	��


}	
�
		


�



	
��



BBBB�BBBB�BBBB�IIIIII
�e

�
�g	

	�


SU

U

U

U

U

U
h44o44o44o44o44o44�%'#"&462#"�Y:Le��ʏ"
	�ʏ�e5�
� *4>%4#!";232?32'#"'4+!"&54632"&5462"&4632
�

c�
�m
c�� �  � yw

��
WaTI[� ' /�1!"3!&'4&"&46327.4623"&54327.4632u���W	��
*$y$���=)��(5>
(5>*� ,%#!&'&54763!2";264&#264&+"3�G
�Z*���h

�

�c
	*A�"�%++"+"+"+"#"#"#+""#####"1##1#1##"33332;;
;;322322232322122332233233333
####"##"##+###*"+++4+"&+&+&#"'#&"'"'"/"#'&+/#/"1'&'"&+"4'"5#'1/4#4"5#4#&/&#'5&5&'4'4'54#54#5#5&5'4'54#4'45'4'541'5'4=&=&=4'=4#=4'=2=47=7=7=47=7=647546=6=6=4?547474656=254347543756154676?45753572474353534757467567>?465756?65742525?6534357342535352525?343573525343525376357367567672763>36736373637325?27;7324;6272727;727;7;7;4;4;!+++"+#""##"""+#"###1""#1####1221323332;;
;2;3322;3323233333332
##1"######"##""####"++++
5+'+"1'+&#"'#&"/*/"#'"5#4#'"'#'"'&/"'4#4#/4#'4#1'4#'5/&'4'4#'5'5'5/45&'4'54#5&41'54'=&=&=&=#='=&=6=47=2=43=47=2=64354647=6=4756=74>5256543475657464676767475656574?=7657>76?>5675672567374725635?6537535353525725253535734352534363576?6?627676?24257372736362761273636342536;427;7327;7;7;���/	/	1�	5463"3#%463"3#qobo� qobo��svgTۭsvgT�8�%#"&54?"&547#7F12F*�I!(��FbF*�I!(�1EE15%��;$1EE16$��;Z��?%73'�Aq#��Bq$����lr��mJ��
%#5733!733#�זS��R�JϤ����e�'&=6767&=6767�	
")A.4L�	��")A.4L�	x>&-CG4	
h8	>>&-CG4	
h8	D�&7"'&54623"'&547632#o'%#�>;:%$�'&$XW)!9$%OD$o�AB%' O$oXX
$<R OI�9$4/&32?"'&'&'&'&=4767676762n	�	
		��K�KK�K�\�\+++"��&'.67>74>7>�-'QWT3%*
+-r�v�Z2=
>Ws9	o'<8I+	3��7	��3��f3��	���f�G��3/#/#'+###2?3265264'�"NN"��
(


Y��0Y
';54'5'454#4'4#'45&5'4/&'#/#'#'!";27265��  ��� .2!. � .!��. 3� !#E�0%#+'#'#/&462462762�"N"N"�
(
Y0��Y

&;%###!"&46;&47625462��  ���.2!. 2 .!2.�͝ !��t�y32?2?654/&#"�����t�������7'&54?632762#"����������@�7.5462"&264&"�="
p�p
"=B//B/
#X$5"PppP"5$X#
�/B//BI�3	Io��E��:32"'&4?!"&463!'&4762��!R��IR!��!R Q!�F�'7'#7'#/{t?/��tu?/"�� D��t"�� D��rx�'&#"32?64s��������
N��%7'7!5!'7'!5!!{{A��o!{{A���vo<-Iop=-'�:65#754&'54&"!5�*f�H7 8H3�|�:ZZ:�3�	;(���%		'	PE	�	�	bs-icons-v10bs-icons-v10icons-v10icons-v10FontForge 2.0 : bs-icons-v10 : 31-3-2018FontForge 2.0 : bs-icons-v10 : 31-3-2018bs-icons-v10bs-icons-v10Version 1.0Version 1.0bs-icons-v10bs-icons-v10M	

� !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJfacebooktwitterdribbblevimeorssgithubvk	delicious
soundcloudbehance	pinterestvinesteamflickrforrst	mailchimptumblr500pxmemberscommentsposts	instagramwhatsappline
blackberryviberskypegplustelegramandroidfire-1fire-2	publisherbetterstudiofire-3fire-4disqus
better-ampok-rulinkedinsnapchat
comments-1
comments-2
comments-3calender
comments-4
comments-5
comments-6
comments-7quote-1quote-2quote-3quote-4quote-5quote-6quote-7youtubeenvatoarrow3-narrow3-sarrow-narrow-nearrow-sarrow-searrow2-narrow2-s
map-markerarrow3-earrow-e
arrow-up-downarrow2-earrow-left-rightbell��L�=��������libs/better-framework/assets/fonts/better-studio-admin-icons.woff000064400000021464151214002620021264 0ustar00wOFFOTTO#4/�CFF �)R�w�FFTM �yT�GDEF � iOS/2 �J`0L�cmap!����head!�06�C�hhea!� $�Phmtx!�#|Cmaxp" <Pname"(�4�post#$ x�}zt\řf7��!�LHw��$L!�!�����@�<dIX�֣[�R���}����˒l�6�`��bvXfH�ɞ�	dfw3��9Wg���ղe�93}Տ[U�������J�@KK ~~GG<�1�y8�h�mnm��������7���ʶ3W>ۢ�$g�I�n�l|��?B��f�Y��J]t���(8�3���E��/�j���
T�9��>�b�k�́�7�l
ll���@&�Ԁ��{���^�8x#��>���
�C���M����_
~=xU��m�;�������h�
�FpW��;k�[]gGk{���-�j���:4к�cs�#����ij���h�%7��㱾����@Gj 6o�%�{c��]}��p/�Z���ߑh��7?���j��pg�P����x�G|t �s�u�stgolGk�N�n�mx�[�í�����ᡎLJ:�;w�Z{�[A�����ގx������������H�P{W[��+����oޑ����C�vh��h���u��]��]�ցd,��1�c�H�����ƻb���������k����G��E]E�H�^;�dt���+�����3�3:���j�v�o�9��V�]s��ֶ�������kA1(�$A5�u�q3h�t��`9X	V��`=8�N�7Lg�����<��Bp1����\��>|2x0x(�T�����3�#���c���?z>�B���K��3����������r�̙�3=s���-���}h9܇��:��7��͞{�S?=����?=�����}�Ц��W��/x�/��~�[>����aۅ�|᷑�F��?_�_���Kn���K޻�/M~�s��Vtƻn�����u�w���eWj��4�V�
��:Ĭ��=�zw�ܕ��@��Ҁj���Y��z�VTW����jce&|��=(��⴬����z�0�r��M�7���3_�����Yf�{a1�p��?6��l��?��y���o�3�ݸ�ܕK�/n���"����v�L��T/. G.����A��Jxp�4)qo�8���86�R
����G��^2���^fi5��7���A�dIN�G��d�,O7��ch��L)�!V/����Q�Hҥ^D��)���%d�zIvq_��lR�m���"�*��y��8�����	o�S#��_d]��aQ�Ĉ_
I�nD�†��o�f6�˚�!$ɲM�%M�#�tMӣޙޖ5	w��ZH�^���S�_\�y-��,O��t��+�����FfC�����{�d[%b�>�l�@}��oAЇ,������?˿��h�ɦ��`��l|�+ 
Y�I����F��{�}����)day�ʚAbʺ�.=��\����;�|�
d
�x��!A`	o��lj�x����8޲��۶oG_$���$X�1M��H�M':1dM���[�o�	&q�m��L�%���o'ޭȱ,;2�-���z�8�L�VW�T�� �+��H�H$"��nj��+̞��������={v������T�F�P/̘�I��{�<9����U�4�f���C)�W����.���?��E�!���%���[����D��^:q=��&��<[��n��:���)�;�����,�_�ۖ�����{��k�E�#����S�v�l?��Ƌ��/���`ܢ��r�`lpG*�#��T}�6�KD�$�ۃDI �D�&�A�NL]Ǧ5G�d�}(��\�na]����L�%ͱ�r����.���%��3;��7�^�?y�>k�n��1n��pc|�e�V�\��0x�Wqdl4��y���=�P�TIì�WTS�͒Y�M�2l(�)���"�"0�P��8��'S�aIQ+����������a����}K���:L�zRy2��x�79L�rلyr-[stWwt�U�MQ��>����RLŔLA�4:�/��$*�&��.��eڛMlð���Lj �%��P�YpY�-O6����RݩK*�c
�jPe��ɏƱ�6��q˕�E4{�D�ٓ����0�NJ�J�蠰|RaL5��rD����`2x��ŏ=�C�%�R�֚ch/A�S����V��
ކ���������@"10��]���h��ޓ�
�Qd��%��x�c��xf<�(2Q���X�DK0EC�E�ic���U�\��j�Ņ����/=3]�uM����uF�	2\��ix���Cl�f��dd<��$�!C�T\�j٪���#��'��%��(�*�n�@68�b��6gq��-i�)�rx�O0�›��#^)�i��:�R!��x�O!��??�-1�b�
����Wȕ��SjE����
�r*�oއ8��H�Қjc�T��+��юNi|�j�ٻ0��38��3������:��	T�rB�`Z���k9Z%���?�@�㉎i�g#�3�6�l+j� z�"���NŨ�u��/]^k�@Lŗ_� �)���?0�����s$O
JQ��.s"k��yA�%nX��a���+�#E�E��7���p�tQ�h.7m�"*N`���7f����~��}���k:��4��.��ٽ��^�@��
���ΐFgo"ğG��i
�iE���ã	$KtlДM3�J�����z�4E>zJ�~�"S�z�<\�H����P~x<1�J��Cp3 � � �J�S�T#3��/���Y�K���Y�@��l}��P^4i͢�+��0;(�˿�y-$�.'�\��
f�R�_zW1��'�Im����O:���$;:��'�)�`��RB��7QSz�Ŀ���#����l�
}F�}-�JZJK���i�`ڙ���K�c���_�a�i}V��w�04�LKS���7Cʜ4+L�
I)��?���V��1���`u^�4�5\�6��f�K�9[pEW�,݆���i�;�1�L�܉_��.k.kf��O1�i����]��&?'�R0jn"?�	�舎dI�l���	ػ����'��
g͢.�'�"+���|��^�.��Cʠ8$īB�+s��R\=�1
A�fÂ(��a�E�X\K!]��.�B@��:N�TI���8��%
gB����*h�5q2y�W%C>I��O!��m7� ��Uæn��9i.5
�B�֐�K%A�nd�m�`��9���a\��UqT�J���F�0Eq�@�$��":)������n��J6��S���Fj>�^�����1�ʰ�e\,"��@tYD�*�Q����r$�E�-6�Hk�-̃�`�@/�H��'X�#����9�|F4�VMp��
�d	7-uԱ�"Őa@8o Iѵ�j#XۚFp%P���%f*�a���vYdj�jl���-C-hMr.�Ʒ1%[��%���
\��3N�.Ԕ���֭�Fo���À�:zȇ�*">�����ِV�Z�S�d��9x��s����
�oB�<������6~
�%y�$&��i�ұ�4-��4s��h�[�(��`��'-�k�U�Ȑu�p�^��ju�̖�Z���q'���r�92����(y����^���+���������~��_�r�~~�g$~��X��=7��R"L%L�	ڀo��`@��%@�!��	���B���F�*Ҙ���B�ϒ12\��X�#�)��&�E��u�RZe���t�t���Bh��Lv�h+5b�SZ�*�+%�F�HYvD�?��g7���kX���u,���x���4�
<˫2rҵ�?�Ϫ�ִS�4va��ͺ%�^�������ﱑ(͘�X��s�[whVter�¡�ɔ�S�!��ȳ�@�`�L�F��{r&��ӥ�Ҹ��T��K�qzx�m�W4�;N���Q!q�Ǟ���ӕ��]��)h1�PH~����=/�����ce�:h�8=,Q暥�5A��sJ���:������0υ���}}���p�3�|:MH�PpT�c���H��G�\Ta�9��Ɵ7�훙q��Z}��o�r�U�l��-���_��A�_ny��_����mw��G����}�G?|�����gG��<��e/5��=C�v
-Gw��Ld��l6=V�NNT���������J�+��n�94��RC'�AI���-�+��,���g�^zv�� @�~1l�+��G!�4�ȋ!�pp�G ��O3��P�P�N�)��0 l�"�x�q�o@����';�!Qp���;�Aӏ��l�Q�v�w�I3�T�q����?�+S)rQ��\�P�x�P�-�����J�ȳ��ի�I�c��'?Bl1��^='�+���J�ZSo�<�,�}�Zr+��B�R1�6�-s���?Z�����(�W�@J�Q�>VN9)7i�##b��b����si6ɦ�$I`�0�N�IVҵLm|2�`�q�TIU���b�-\�Jv�q]�d��&�h,	�-B0��z��Q.f��eǥ4ɒ��7�f�f�K\I(�e�B��lVl��8 ф�Jp�+�$Wp8,H�)��Js�b�:P�g��
�k�4�8L ���KR�qk�(����T_���mu�N��fz��qx�d��&��tZݵ�j��\|.�8�7�7��;wF�6�͆�(�)w�R�MԪ�)�q!x���r����i�����X"���A�$Ic�u��L
g��	v�m�
<m�s�J@��e��@�SdR�|�� �=֋DY��V�%C���	A�t�fW���}u�ϓ�r��P�4{-�U����ۃ���)K�I�;���P��LJE��c|��]�kE�P�0��lA�+�bM����jQ�OsOϪ�|i�|K/	M�F&N.VCJ��}�}k�y2���s���c���݇#�)�^�^���>.��r���;N�i�Fƿs���?�|y�w�߲����=��ϱ����vt)�X����`.۰m��'��>���3�w�����������hLJ;�
��H�����D,4;�V�MD
�hp��GDB�ѱ��Iץ��!ı1O����0��rtjY��[\Կ�[+@��;���-��Uh)�L�m��Û\����5��u��>
�����7!@�2�(��V�L9⤌��/����a�Ww��s��W��-�^˓K�����ۅ�Y�+�,ۉ�=�}����H"KH�JH"�z��M�K �Q

+sE���Y�>1;�8���.?u1�KJ!��BwW:6��H�\T��f+3%�$g+��,�xHu�
������ɝ�_+��@P!�˂N���ږI��rD�g�`�[�i��"T�DX���^��@Ś @�"0�8?>6�efk
����E��w���[3����&�c�#��`'�f�ܺ�,�U�7��c���7|�/�x�wVdY2J��~�ڻw�9�޼���!H2�^���^��Α9|�[�?��so݆��<;������[iE}��'���:�k����z��͜x`�IA�l�L`��{�A�� ��Y�{h�c����L�a�p�e��P�uJ�C�D�H�P�
1r�R�?hu��`n1�^
�U[���ʥ���J=�/��';�a���6��c�[�,�ȃ���Wr� 䔎��&c�dȘ�.��2lzmWD�iE�+�T&UL��	�V������T$���8��Q
��[�X�I��r*/	Ex��)"�՘��x��AC �b�p�2��8c��i�e�>�Z��A��)
F�d]���<h�E�@� S����40�~�׌D7Z����cnBg
���J
��L�gݞ�p=�M��Ӛ�D����Ys��mM[U�k4EФ(�k����%Yȧ�^�1~��g�h�
�"���=�
��"�S����#�_Üx��{�>���(,^=��{�m'������	yݻл�U����>�jd�������Lz2�h���]_���[�r��>�g�M�A��BU�����X�k)�z���JC��g��!��k�#:���{;Y�fN�8�{��TqjF���̑��>���c:�9r�3�1һ�͈��G�a]Ӎ�'D7�"5���({4�dk�a`�RDɐ�G�K�2g�Q�E���"S�``7k��٣�c9N��A!X�4 �\�t[L�����Df����Qj�����h9׌��M:�Z{��g0��(
�p��		Q��踸���}�Xp:kn�[��A�S�{oH�;w~�ffI���O�EQ��B��U��aDU�������������%��5��Zr:W+N��B��	ګJi2������	&$� 	k��=��'�z�{�<S�F
��7�լ�>�l<Kf�Fn99ӭw`"U%�R��]iУ�5RiST����iƦ4Z^e	s���J�Mi�'y9O�."������;�w^MĢm��=��n�gv)�Tx���w"��-o�_L����Z�b�?����yу���y�d��'N��_3�-�eizD��W�נ!u��yq�Lc>$77�eX�*��k1��<� �&��R�4Ou�n���פ�o��L�m�F�n瀗ş�*A���A\-��Ipm��g��X��E�I�u���3��ڦ9Y��'U��M�RD�ݝ�	?��
2��&�E��BUq���U�9Xt���-�����y8F�;�_���Nt2�<$�˼w2`S��(�D4q�a�q��E�!�7�9�7[[OU�ʈ�>����4�)uzN���g��~G�&��
�7��"~�$ ^���m�|z8|�Tu9Gi4��_'��e�#:�A%�"Q�3/
X�o�g�3�!;Gw�r񙇁Ke�Ҥ<���XW6�=�2�G� ��t�m��C�噥Z��8,8/�7�w�Z�lK��u��e�P���t9�%�Q�_��g@w��j����9�m�VL��8&@HwH�
y.��cȀ*A����a��c��PB�A��B
�K��
��bc~?׳V����YU0q�fW��3HpŒ\�]&�4�"6n����e���*�2N-"�)z�\�!Ӵ�%��*���ck=B�R<�*A�Ս�b�����tG�����sl�ljA0�H��9�`,-�[��ź:�b���z���{��c�~������z��GGw����j������/�g�wu؟�of�ԇ�G;i)��ن��>A���u��V�՛Vo>�㲰�b!or�f�[^>���e�����}F;H��!��QB�oԏ����_�� y�����Uw�6���-���1eS��XB�4�1��D���­�~�l �D��5@���>���S�w�w+��F��^���^�|�_���Pz�����+���s�g��W6���1��Wa��}�B�s~��6�p�zV���~ϩo�@	�{�i�@ҒzL+4�:g��7gm𥼓)���Tu������E�h�s�pF�y���x���E�"W��#��x.����,��'����ɋ�I�,�De�eV\���w�n�,�X�N�Jʆ/��5��^d>AbyO�H�[;�D�ʀ�>��B��8\0]0�7X�D����H�8@�~�q�v2��SM]ޝ�7�Đ��˻�-��)Z�-aG�d&��x�n�n���Z������#�`�����Dw�	=��1��~p�z���Ǚ�tv��7�Q>;ƍ�����6<�ҋh|��ov{��:���GW ��K��Ƕ��{�Q7f��
�L�������l��o��VCHY�W\�6~"���כo��C�Π�Ϡ7�Y��O��=�wH�H;�Û�I�A�I"����'��>���o��2�P�x�c```d�3��΃�kݍ�`4N�tx�c`d``�b	`b`Bk f��nx�c`fb`������Ø�����2H2�0001�r2�������������B�Œp
@��v+x��΋RAq����DȥB�vC*���x���š��5��^N�9j\���&0I�[��ΉI*N�
;�ː͸���w�����ƭ;U5��<��-O�:�z���x�����؇OS_f����gej�_>_Dm�x�c`d``b�J�x~���L p��q����j�8&6 ��,
5G�x�c`d``b���A��������"(�	�)�x�cb```b``��1�8����* �@�PHP<x����JC1��������-��C.7AA��9���Dh�)}G7ʇ��Ϩ�Є$_�9�90�NCa�;��P�Ǹǧp��z��R�
Oi�`�j.hqUu�n�(<�3^�8u+<��:
Oi������t@���ۚ�'Gr����l|)>����̺߇h�6E����I���Rό��l�E�s���2�u��r9�e�T)�e�;�]�����3ָ�RvޏZ�w������^��y)j�vg�i�y�x�c`f@�h�libs/better-framework/assets/fonts/fontawesome-webfont.eot000064400000503556151214002620020121 0ustar00n����LPYxϐFontAwesomeRegular$Version 4.7.0 2016FontAwesome
�PFFTMk�G���GDEF��p OS/2�2z@X`cmap
�:��gasp���hglyf���M�L�head��-�6hhea
�$hmtxEy��
�loca��\�maxp,8 name㗋�gh�post����k�uː�xY_<��3�2�3�2���	�	����	��'@i��3��3s�pyrs@ �� �pU�]�����y�n�����2��@������
��������z���Z@�5�5
���z���ZZ����@���������,_���@������s���@	��@��(������@�����@��@-
�M�M�-�
�M�M�����@�����@@�
�-����`��b����
���$����6�4�8�"�"""""���@�D@���,,@� ���������	m��)@�@	 	' D9>dY*	'						�	��	��T										�@	f�	%RE	 		$!k(D�'	��	�%��	�%	��	��0%�/�&��p@0 �����!"""`���>�N�^�n�~��������������.�>�N�^�n�~��������������>�N�^�n�~������������ �����!"""`���!�@�P�`�p�������������� �0�@�P�`�p��������������!�@�P�`�p�������������\�X�S�B�1����ݬ

	����������������������������������
�
	,,,,,,,,,,,,,��t�L�T$�l	x	�
T(��
d����l,����4d�pH�$d,t( � �!�"0# $,$�&D'�(�)T**�,,�-�.@.�/`/�00�1�2�3d444�5 5�5�6 6\6�7H7�88`8�9L9�:h:�;�<p=p><>�?h?�@H@�A0A�BXB�CdC�DLD�E�F�G0G�H�I�J8K�L�MdN,N�N�O�P`P�Q4Q�RRlS,S�T`U0W�X�Z[@[�\<\�]�^(^�_�`pb,b�dd�ePe�f�g`g�iLi�jDkk�l�m@n,oLp�q�r�sxtt�uD{`||�}}�~��������H��������l�@����������l�H� ���T��H�������`����@�����$�\�X��D�������T�X�����D�P�,���8���d�\����������������H���x��� �t���X���p��d��������x�t�������������@������Œ�\� ļ�ŸƔ�0���d��ʨˀ����͔�x��ϰЌ�,ш�҈�ӌ���8�,՜�`���l�Hش�`���Tڸ�۔�@���l��ބ�߬��l�p� ������������������������������4�����X���$�l���(����`����������	d

��
,�,��8��(�X���x|T�@��| �!�"x##l$$�'h(�*L,T.L1t1�2�303�4�5t6T7$89H::�;�<�<�?X@A�B�C�D�EHFHGpHHIxJ J�K�L�MN@P@Q�R�SDT ULV`V�WXX4X�ZZ�[d[�\|]�^�`�aHa�b�cXd�etfhg�h�i\jxn�p@s�vw�x�y�z�{h|�}}�\���l�t���4���������t���8�8���L���T�������������|�������|�������4�x�����L����������X�(� ������� ������@�����l���t����$����x�L�L��� �H������Ġ�T�(����ʈˠ��ϔ�l�d���P�Մ�x�p���ڬ�T�T���ވ�L�����<�H��$���l������4����������� �P�l����,���x���p�,�x�t��d����4���4,h�P	4
��
�4�<,,408$�8�T� |!h"�$L%0&H'�(�)�*0*�+�,�.$.�0�1�2@2�3�4t5$6�9 :�:�;;�<(<�=4?�@�A�C�D�F�H`H�I�L�L�L�L�L�L�L�L�L�L�L�L�L�L�L�L�p7!!!���@p�p �p�]���!2#!"&463!&54>3!2�+��@&&��&&@��+$(�($F#+���&4&&4&x+#��+".4>32".4>32467632DhgZghDDhg-iW�DhgZghDDhg-iW&@(8 ��2N++NdN+'�;2N++NdN+'�3
8���!  #"'#"$&6$ �������rL46$���܏���oo��o|W%r��������4L&V|o��oo����ܳ��%��=M%+".'&%&'3!26<.#!";2>767>7#!"&5463!2� %��3@m00m@3���% 
�
�@
���:"7..7":�6]�^B�@B^^B�B^ $΄+0110+��$�
(	

�t��1%%1��+�`��B^^B@B^^���"'.54632>32�4��
#L</��>�oP$$Po�>���Z$_d�C�+I@$$@I+��������"#"'%#"&547&547%62���V�?�?V��8��<��8y���
���b%	I�))�9I	����	+	%%#"'%#"&547&547%62q2�Z���Z2Izy���V)�?�?V��8��<��8)>~��>��[��
���
2���b%	I�))�9I	���%#!"&54>3 72 &6 }X��X}.GuL�l�LuG.�����>�m��mU��mE��Em�������>����/?O_o���54&+";2654&+";2654&+";264&#!"3!2654&+";2654&+";264&#!"3!2654&+";2654&+";2654&+";267#!"&5463!2�&�&&�&&�&&�&&�&&�&&�&&&�&�&&�&�&�&&�&��&�&&&�&�&&�&&�&&�&&�&&�&�^B��B^^B@B^@�&&�&&��&&�&&��&&�&&�&&�&&��&&�&&���&&�&&&&�&&���&&�&&��&&�&&��&&�&&���B^^B@B^^��/?#!"&5463!2#!"&5463!2#!"&5463!2#!"&5463!2L4�4LL44LL4�4LL44L�L4�4LL44LL4�4LL44L��4LL4�4LL��4LL4�4LL���4LL4�4LL��4LL4�4LL	�/?O_o�#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!28(��(88(@(88(��(88(@(8�8(��(88(@(8��8(��(88(@(8�8(��(88(@(8�8(��(88(@(8��8(��(88(@(8�8(��(88(@(88(��(88(@(8 �(88(�(88�(88(�(88��(88(�(88�(88(�(88��(88(�(88��(88(�(88�(88(�(88��(88(�(88�(88(�(88�/?O_#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!28(��(88(@(88(��(88(@(88(�@(88(�(8�8(��(88(@(88(�@(88(�(88(�@(88(�(8 �(88(�(88�(88(�(88��(88(�(88�(88(�(88��(88(�(88�(88(�(88y��"/&4?62	62��,�P����P&�P��P�,��jP�����n���#$"'	"/&47	&4?62	62	�P���P�&���P&&P���&�P�&���P&&P���&�P������#+D++"&=#"&=46;546;232  #"'#"$&6$ 
�
@
�

�
@
�
�������rK56$���܏���oo��o|W�@
�

�
@
�

��r��������jK&V|o��oo����ܳ�����0#!"&=463!2  #"'#"$&6$ 
��

@
�������rK56$���܏���oo��o|W�@

@
�r��������jK&V|o��oo����ܳ����)5 $&54762>54&'.7>"&5462z�����z��+i *bkQ��н�Qkb* j*����LhLLhL�����zz���Bm +*i J�yh��QQ��hy�J i*+ m��J��4LL4�4LL���/?O%+"&=46;2%+"&546;2%+"&546;2+"&546;2+"&546;2��������������`��r��@�@r�@��@����n4&"2#"/+"&/&'#"'&'&547>7&/.=46?67&'&547>3267676;27632�Ԗ����#H
	��,/
�1)�
~'H�
�(C
	�

�,/
�1)�	
�$H�
Ԗ�Ԗm�6%2X
%�	l�2
�k	r6

[21
�..9Q

$�
k�2
�k	
w3[20����/;Cg+"&546;2+"&546;2+"&546;2!3!2>!'&'!+#!"&5#"&=463!7>3!2!2@@@@@@���@�`�0
��
o`^B��B^`5FN(@(NF5 ��@��@��@���L%%Ju		�@�LSyuS�@�%44%�f5#!!!"&5465	7#"'	'&/&6762546;2�&�����&??�>

�L�L
>
� X ���
 � &���&��&AJ	A��	J
W���h��##!"&5463!2!&'&!"&5!�(8(��(88(�(`�x
��c�`(8��`(��(88(@(8(D��9�8(����� ,#!"&=46;46;2.  6 $$ ����@��������(�r���^����a�a�@@`��(��������_�^����a�a��2NC5.+";26#!26'.#!"3!"547>3!";26/.#!2W
�
��.�@

��

�@.�$S

�

S$�@

���9I


�
I6>
��
��>�%=$4&"2$4&"2#!"&5463!2?!2"'&763!463!2!2&4&&4&&4&&4�8(�@(88(ч:�:��(8���@6�@*&&*�4&&4&&4&&4& ��(88(@(8�88�8)�@�)'�&&�@���$0"'&76;46;232  >& $$ `
������������(���r���^����a�a`��		@`��2�������(���^����a�a�����$0++"&5#"&54762  >& $$ ^���
?@�����(���r���^����a�a���`?		����������(���^����a�a��
#!.'!!!%#!"&547>3!2�<�<�<_@`&��&�
5@5
�@����&&�>=(""��=���'#"'&5476.  6 $$ � ��  ! ��������(�r���^����a�a�J��	%�%���(��������_�^����a�a�����3#!"'&?&#"3267672#"$&6$3276&�@*���h��QQ��hw�I
�	m�ʬ����zz���k�)'�@&('��Q��н�Qh_
	�
��z�8�zoe����$G!"$'"&5463!23267676;2#!"&4?&#"+"&=!2762�@�h���k�4&&�&�G�a��F*�
&�@&��Ɇ�F*�
A��k�4&���nf�&�&&4�BH�rd�@&&4���rd
Moe�&�/?O_o+"&=46;25+"&=46;25+"&=46;2#!"&=463!25#!"&=463!25#!"&=463!24&#!"3!26#!"&5463!2�
@

@

@

@

@

@
�
�@

�

�@

�

�@

�
�
�@

�
�^B�@B^^B�B^`@

@
�@

@
�@

@
��@

@
�@

@
�@

@
�3@

��
M��B^^B@B^^��!54&"#!"&546;54 32@�Ԗ@8(�@(88( p (8�j��j��(88(@(8������8@���7+"&5&5462#".#"#"&5476763232>32@@
@
@KjK�ך=}\�I���&:�k�~&26]S
&H&�

�&H5KKu�t,4,�	&� x:;*4*&��K#+"&546;227654$ >3546;2+"&="&/&546$ �<��X@@Gv"D�����װD"vG@@X��<��4L4����1!Sk @ G<_b������b_<G �� kS!1����zz�� �"'!"&5463!62&4����&&M4&���&M&�&M& ��-"'!"&5463!62#"&54>4.54632&4����&&M4&�UF
&""""&
F���&M&�&M&���%/B/%���G-Ik"'!"&5463!62#"&54>4.54632#"&54767>4&'&'&54632#"&547>7676'&'.'&54632&4����&&M4&�UF
&""""&
FU��
&'8JSSJ8'&

����

&'.${��{$.'&

����&M&�&M&���%/B/%7���;&'6���6'&;��4�[&$
[2[
$&[��#/37#5#5!#5!!!!!!!#5!#5!5##!35!!!����������������������������������������������������������������������������#'+/37;?3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3????  ^��>>~??�??�??~??~??^??�^^?  ^??������������������������������������4&"2#"'.5463!2�KjKKjv%�'45%�5&5L4�5�&�%jKKjK�@5%�%%�%�5�4L5&�6'��k�54&"2#"'.5463!2#"&'654'.#32�KjKKjv%�'45%�5&5L4�5�&�%�%�'4$.�%%�5&�5�5�&�%jKKjK�@5%�%%�%�5�4L5&�6'45%�%�%54'�&55&�6'
��y�Tdt#!"&'&74676&7>7>76&7>7>76&7>7>76&7>7>63!2#!"3!2676'3!26?6&#!"3!26?6&#!"g(��sA�eM�,*$/
!'&
�JP��$G]��
x�6,&��`
��
h`
��
"9H�v@WkNC<.
&k&
("$p"	.
#u&#	%!'	pJ�vwEF�#

@

��

@

���2#"'	#"'.546763�!''!0#�G�G$/!''!�	
8"��"8
 ��X!	
8"	"8
	����<)!!#"&=!4&"27+#!"&=#"&546;463!232������(8���&4&&4�
�8(�@(8�
qO@8(�(`�(@Oq��8(��&4&&4&@�`
�(88(�
�Oq (8(�`(�q���!)2"&42#!"&546;7>3!2  I��j��j��j��j�3e55e3�gr������`��I�j��j��j�j��1GG1���r��������P2327&7>7;"&#"4?2>54.'%3"&#"#ժ!�9&W��B03&�K5�!�)V�?�@L��'�	
>R�>e;&L:�:%P�>��vO
'h�� N��_"�:-&+#
��:��	'	����+a%3 4'.#"32>54.#"7>7><5'./6$3232#"&#"+JBx)EB_I:I*CRzb3:dtB2P���$$5.3b�ZF�|\8!-T>5��Fu��\,�,j�n OrB,<!
5�4wJ]�?tTFi;
2�3j.�p^%/2�+
	S:T}K4W9: #ƕd�fE���:7>7676'5.'732>7"#"&#&#"OA
zj=N!�}:0e��%	y�
+t�D3�~U#B4#
g		'2
%/!:
���T	bRU,7����}%2"/&6;#"&?62+326323!2>?23&'.'.#"&"$#"#&=>764=464.'&#"&'�!~:~!PP!~:~!P��6�,�,$�$%*'
c2N 	
(�$"L��A2�3Yl�!x!*�%��%%��%��
p�P,T	NE	Q7^���oH!+(
3	 *Ue�eu
wg��a�32632$?23&'.5&'&#"&"5$#"#&=>7>4&54&54>.'&#"&'2#".465!#".'&47>32!4&4>Q6�,�,Faw!*'
=~Pl*	
(�$"L��A2�3Yl	�)�!*<7@@7<
�
<7@@7<
 p�P,T	MF
Q7�47ƢHoH!+(
3	 t���JHQ6wh��',686,'$##$',686,'$##$�/?%#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2&��&&�&��&�&&&&�&&&��&��&&�&��&&�&&f�&&�&&f�&&�&&f�&&�&&�/?%#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2&��&&�&��&��&&�&&��&&�&��&��&&�&��&&�&&f�&&�&&f�&&�&&f�&&�&&�/?%#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2&��&&�&&�&&&&�&&&&��&&�&��&&�&&f�&&�&&f�&&�&&f�&&�&&�/?%#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2&��&&�&&��&&�&&��&&�&&��&&�&��&&�&&f�&&�&&f�&&�&&f�&&�&&�/?O_o%+"&=46;2+"&=46;2+"&=46;2#!"&=463!2+"&=46;2#!"&=463!2#!"&=463!2#!"&=463!2
�

�

�

�

�

�

��

@
�
�

�

��

@

��

@

��

@
�

�
s�

�
s�

�
��

�
s�

�
��

�
s�

�
s�

�
�/?O#"'&47632#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2�
	��		 	
�
�@

�

��

@

��

@

�@

�
�
	 		 	��

�
s�

�
s�

�
s�

�
�/?O#"&54632	#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2`	��	

	 �
�@

�

��

@

��

@

�@

�
�	��	
@
	��	�

�
s�

�
s�

�
s�

�
#"'#!"&5463!2632'
�m�w�@w��w�w��
'���*��w��w�w��w������."&462!5	!"3!2654&#!"&5463!2�p�pp�p��@���

@
�^B��B^^B@B^�pp�p���@�@� 
�@

�
 �@B^^B�B^^���k%!7'34#"3276'	!7632k[�[�v
��
6����`�%��`�$65&�%[�[k����
�`����5%���&&�'���4&"2"&'&54 �Ԗ���!��?H?��!,�,Ԗ�ԖmF��!&&!Fm�,�����%" $$ ���������^����a�a`@������^����a�a���-4'.'&"26% 547>7>2"KjK��X��QqYn	243nYqQ�$!+!77!+!$5KK���,ԑ�	���]""]ً�	��9>H7'3&7#!"&5463!2'&#!"3!26=4?6	!762xt�t` �� ^Q�w��w��w@?61��B^^B@B^	@(` �`��\\��\P�`t�t8`� �� ^�Ͼw��w@w�1^B��B^^B~
	@��` \ \�P�+Z#!"&5463!12+"3!26=47676#"'&=# #"'.54>;547632��w��w��w�
M8
pB^^B@B^�
'���sw-

9*##;No��j�'
�#��w��w@w�
"^B��B^^B�

	��*�����
"g`�81T`PSA:'�*��4�/D#!"&5463!2#"'&#!"3!26=4?632"'&4?62	62��w��w��w@?61

��B^^B@B^	@

��B�RnB�Bn^��w��w@w�1
^B��B^^B�
	@
���Bn���nB�C"&=!32"'&46;!"'&4762!#"&4762+!5462�4&���&�4�&���&4�4&��&4&��&4�4�&���&4�4&��&4&��&4�4&���&����6'&'+"&546;267��:	&�&&�&	s�@�	
�Z&&�&&�Z
	���+6'&''&'+"&546;267667��:	�:	&�&&�&	�	s�@�	
�:�	
�Z&&�&&�Z
	��:
	z����6'&''&47667S�:	�:�	s�@�	
�:�4��:
	�|�	&546h��!!0a�
�
�
$���#!"&5463!2#!"&5463!2&�&&&��&�&&&@��&&�&&��&&�&&���#!"&5463!2&��&&�&@��&&�&&���&54646&5-�	��:	s��:	
��:4�:�
	���+&5464646;2+"&5&5-�	�	&�&&�&	�:	s��:	
��:	
�&&��&&�
	�:�
	���&54646;2+"&5-�	&�&&�&	s��:	
�&&��&&�
	62#!"&!"&5463!2�4��@��&&�&&-��:��&&&�&�����	"'&4762����4��4����4��4��4Z��f�	"/&47	&4?62S�4����4����44��4���#/54&#!4&+"!"3!;265!26 $$ �&�&�&�&&&�&&@���^����a�a@�&&&�&�&�&&&+�^����a�a�����54&#!"3!26 $$ �&�&&&@���^����a�a@�&&�&&+�^����a�a�����+74/7654/&#"'&#"32?32?6 $$ }��Z��Z��Z��Z����^����a�a���Z��Z��Z��Z�^����a�a�����#4/&"'&"327> $$ [4�h�4[j����^����a�a"Z�i�Z��J�^����a�a�����:F%54&+";264.#"32767632;265467>$ $$ ���o�W��	5!"40K(0?i�+! ":����^����a�a����X�R�dD4!&.uC$=1/J=�^����a�a�����.:%54&+4&#!";#"3!2654&+";26 $$ `��``��������^����a�a�����������^����a�a�����/_#"&=46;.'+"&=32+546;2>++"&=.'#"&=46;>7546;232�m&&m �l&�&l� m&&m �l&�&l�s&�%�&�&��%�&&�%�&�&��%�&&�&l� m&&m �l&�&l� m&&m �,�&��%�&&�%�&�&��%�&&�%�&���#/;"/"/&4?'&4?627626.  6 $$ I�

��

�

��

�

��

�

��
͒������(�r���^����a�aɒ

��

�

��

�

��

�

��
(��������_�^����a�a����� ,	"'&4?6262.  6 $$ ��Z4��f4�4fz�������(�r���^����a�a�Z&4f�f4�(��������_�^����a�a�����	"4'32>&#" $&6$  W���oɒV�󇥔�� z�����zz�8�����YW�˼�[����?����zz�:�zz�@�5K #!#"'&547632!2A4�@%&&K%54'�u%%�&54&K&&���4A��5K��$l$L%%�%54'�&&J&j&��K�5�K #"/&47!"&=463!&4?632�%�u'43'K&&%�@4AA4���&&K&45&�%@6%�u%%K&j&%K5�5K&$l$K&&�u#5��K@!#"'+"&5"/&547632K%K&56$��K5�5K��$l$K&&�#76%�%53'K&&%�@4AA4���&&K&45&�%%�u'5��K�"#"'&54?63246;2632K%�u'45%�u&&J'45%&L4�4L&%54'K%�5%�t%%�$65&K%%���4LL4�@&%%K'���,"&5#"#"'.'547!3462�4&�b��qb>#5���&4�4�&6Uu�e7D#		"�dž�&����/#!"&546262"/"/&47'&463!2�
���&�@&&4�L

r&4���

r

L�&�&�
���4&&�&�L

rI�@&���

r

L�4&&
���s/"/"/&47'&463!2#!"&546262&4���

r

L�&�&�
���&�@&&4�L

r@�@&���

r

L�4&&�
���4&&�&�L

r��##!+"&5!"&=463!46;2!2�8(�`8(�(8�`(88(�8(�(8�(8 �(8�`(88(�8(�(8�(88(�`8��#!"&=463!2�8(�@(88(�(8 �(88(�(88z���5'%+"&5&/&67-.?>46;2%6�.@g.��L4�4L��.g@.
��.@g.
L4�4L
.g@.���g.n.���4LL43�.n.g��g.n.�34LL4�͙.n.g����-  $54&+";264'&+";26/�a����^�����
�

�


�

�����^����a�a��
�
fm��
@
J%55!;263'&#"$4&#"32+#!"&5#"&5463!"&46327632#!2���$�$�8�~+(88�8(+}�(�`8(��(8`�]��]k=��=k]��]��8���,8e�8P88P8�����`(88(�@���M��M����N4&#"327>76$32#"'.#"#"&'.54>54&'&54>7>7>32&����z&^��&.������/+>+)>J>	W��m7����'
'"''? &4&c��&^|h_b��ml/J@L@#*
#M6:D
35sҟw$	'%
'	\�t��3#!"&=463!2'.54>54''�
��

@
�1O``O1CZ��Z71O``O1BZ��Z7�@

@
N�]SHH[3`�)Tt��bN�]SHH[3^�)Tt���!1&' 547 $4&#"2654632 '&476 ���=������=嘅�����}�(zVl��'��'���ٌ@�uhy����yhu����9(�}Vz��D#���#D#�������	=CU%7.5474&#"2654632%#"'&547.'&476!27632#76$7&'7+NWb=嘧�}�(zV�j�\i1
z,��X��
Y[6
$!%���'F��u�J�iys�?_�9ɍ?�kyhu�n(�}Vz����YF
KA؉L�a
�0��2�-�F"@Q���sp@�_���!3%54&+";264'&+";26#!"&'&7>2
�

�


�
�
#%;"�";%#<F<������7


���??""??�$$ll2#"'&'	+&/&'&?632	&'&?67>`,@L�����5
`		��
`	�����L�`4�L��H`
����`	��
a	5�
��L@��#37;?Os!!!!%!!!!%!!!!!!!!%!!4&+";26!!%!!!!74&+";26%#!"&546;546;2!546;232� ��`@���� ��`@���� ���@����@�� ��@����
@

@
� ��@��� �� 
@

@
�L4��4LL4�^B@B^�^B@B^�4L� �� @@��@@ � � � @@  

��
��@@ �� � 

��
M�4LL44L`B^^B``B^^B`L���7q.+"&=46;2#"&=".'673!54632#"&=!"+"&=46;2>767>3!54632�<M33K,��	��	
 j8Z4L2B4:;M33K,?		��	
�0N<* .)C=W]xD��0N<* .)C=W]xD?\�-7H)��	��	
�".=']�-7H)�
��w	��	
�<?.>mBZxPV3!�<?.>mBZxPV3!�
���&#"'&'5&6&>7>7&54>$32�d�FK��1A
0)����L���.���٫�C58.H(Y���e����#3C $=463!22>=463!2#!"&5463!2#!"&5463!2���H���&�&/<R.*.R</&�&�&��&&�&&��&&�&������Bɀ&&�4L&&L4�&&f��&&�&&��&&�&&Z� %"'	"/&4762��4���4��4�ͥ���5��5Z����	"'&4?62	62��4��44���5����5��%K%#!".<=#"&54762+!2"'&546;!"/&5463!232
�@�&@<@&�@	����:��&���	�
��& 

��&���&���
����&��	

��`&���:$"&462"&462!2#!"&54>7#"&463!2!2�LhLLh�LhLLh�!��
�&&�&��&&�&4hLLhLLhLLhL��%z<
0&4&&)17&4&
&&��#!"&5463!2!2��\�@\��\@\��\���@\��\�\��\ �W�*#!"&547>3!2!"4&5463!2!2W��+�B��"5P+�B@"5����^�=���\@\� \�H#�t3G#�3G:�_H�t�\��\ �@��+32"'&46;#"&4762�&��&�4�&��&4�4&�&4�4&&4�@�"&=!"'&4762!5462�4&�&4�4&&4�4�&��&4&��&����
!!!3!!��������������������������0@67&#".'&'#"'#"'32>54'6#!"&5463!28ADAE=\W{��O[/5dI
kDt���pČe1?*�w�@w��w�w��	(M&
B{Wta28r=Ku?RZ^Gw��T	-�@w��w�w�����$2+37#546375&#"#3!"&5463�w��w���/Dz?s�����w��w��w�@w�S�88�	�����w�w����#'.>4&#"26546326"&462!5!&  !5!!=!!%#!"&5463!2�B^8(�Ԗ���������>��������@�|�K5�5KK55K�^B(8Ԗ�Ԗ�€>�������v����5KK55KK�H��G4&"&#"2654'32#".'#"'#"&54$327.54632@p�p)*Ppp�p)*P�b	'"+`�N*(�a���;2��̓c`." b
PTY9��ppP*)p�ppP*)�b ".`�(*N��ͣ�2�ͣ����`+"'	b
MRZB�����4&"24&"264&"26#"/+"&/&'#"'&547>7&/.=46?67&'&547>3267676;27632#"&'"'#"'&547&'&=4767&547>32626?2#"&'"'#"'&547&'&=4767&547>32626?2��Ԗ���LhLKjKLhLKjK��	�"8w
s%(�")v

�
>�
	�"8x
s"+�")v
�<�
��3zLLz3��
3>8L3)x3
��3zLLz3��
3>8L3)x3
�Ԗ�Ԗ�4LL45KK54LL45KK���
#)0C	wZl/
�
Y�	
N,&�
#)0C	vZl.
�
Y�L0"��qG^^Gq�q$ ]G)Fq�qG^^Gq�q$ ]G)Fq��%O#"'#"&'&4>7>7.546$ '&'&'# '32$7>54'�����VZ|�$2$
|��E~E<�|
$2$�|ZV���:�(t}�������X(	
&%(H�w�쉉��x�H(%&	(X�ZT\�MKG���<m$4&"24&#!4654&#+32;254'>4'654&'>7+"&'&#!"&5463!6767>763232&4&&4�N2��`@`%)7&,$)'  
%/0Ӄy�#5 +�1	&<��$]`�{t��5KK5$e:1&+'3T�F0�h��4&&4&�3M:�;b^v�+D2 5#$��I�IJ 2E=\$YJ!$MCeM��-+(K5�5K�K5y�*%A�u]c���>q4&"24&'>54'654&'654&+"+322654&5!267+#"'.'&'&'!"&5463!27>;2&4&&4�+ 5#bW���0/%
  ')$,&7)%`@``2N��h�0##�T3'"(0;e$��5KK5 t��ip��<&	1&4&&4&�#\=E2&%IURI��$#5 2D+�v^b;�:M2g�c]vDEA%!bSV2M�K5�5K(,,��MeCM$!I��@�#"&547&547%6@�?V��8������b%	I�)���94.""'."	67"'.54632>32�+C`\hxeH>Hexh\`C+�ED���4��
#L</��>�oP$$Po�>��Q|I.3MCCM3.I|Q����/����Z$_d�C�+I@$$@I+� (@%#!"&5463!2#!"3!:"&5!"&5463!462�
��w��w@

��B^^B 
���4&�@&&�&4 ` 
�w�w�
 
^B�@B^24��& &�& &�����%573#7.";2634&#"35#347>32#!"&5463!2���FtIG9;HI�x�I��<,tԩw�@w��w�w�z��4DD43EE�����ueB���&#1�s�@w��w�w�����.4&"26#!+"'!"&5463"&463!2#2��&�S3L�l&�c4LL4�4LL4c����@��&��&{�LhLLhL��'?#!"&5463!2#!"3!26546;2"/"/&47'&463!2��w��w��w��@B^^B@B^@�&4��t

r

��&&`��w��w@w�@^B��B^^B@R�&��t

r

��4&&@"&5!"&5463!462	#!"&54&>3!2654&#!*.54&>3!2���4&�@&&�&4 s�w��

@B^^B��

@w��4��& &�& &��3�@w�
 
^B�B^ 
�����
I&5!%5!>732#!"&=4632654&'&'.=463!5463!2!2�J���J���S��q*5&=CKu��uKC=&5*q͍S8( ^B@B^ (8���`N��`Ѣ�΀G�tO6)"M36J[E@@E[J63M")6Ot�G�(8`B^^B`8	���',2��6'&'&76'6'&6&'&6'&4#"7&64 654'.'&'.63226767.547&7662>76#!"&5463!2		/[		.
=���X��Ě4,+"*+, 1JH'5G:�:#L5+@=&#���w�@w��w�w�P.1GE�,��ԧ��44+	;/5cFO:>JJ>:O9W5$@(b4��@w��w�w������'?$4&"2$4&"2#!"&5463!3!267!2#!#!"&5!"'&762&4&&4&&4&&4�8(�@(88(�c==c�(8��*�&�&�*�6�&4&&4&&4&&4& ��(88(@(88HH88`(�@&&�('��@����1c4&'.54654'&#"#"&#"32632327>7#"&#"#"&54654&54>76763232632


	N<�;+gC8�A`1a9�9�g��w����|�9�8aIe$I�VN��z<�:LQJ
�,�-[%	061I��(�)W,$-������7,oIX(�)o�ζA;=N0
eTZ
	 (���O#".'&'&'&'.54767>3232>32�e^\4?P	bM��O0#382W#& 9C9
Lĉ"	82<*9FF(W283#0OMb	P?4\^eFF9*<28	"��L
9C9 &#��!"3!2654&#!"&5463!2`��B^^B@B^^ީw��w��w@w�^B��B^^B@B^���w��w@w�����#!72#"'	#"'.546763���YY�!''!0#�G�G$/!''!�&�UU�jZ	
8"��"8
 ��X!	
8"	"8
	���GW4.'.#"#".'.'.54>54.'.#"32676#!"&5463!2 1.-
+$)
c�8
)1)

05.D
<9�0)$9��w�@w��w�w�W

)1)
7�c
)$+
-.1 �9$)0���<
D.59�@w��w�w��,T1# '327.'327.=.547&54632676TC_L��Ҭ���#+�i�!+*p�DNBN,y[����`m`%i]hbE����m��}a�u&,�SXK��
&$��f9s?
_���#"!#!#!54632��V<%'����Э��HH���	�(ں����T\dksz�� &54654'>54'6'&&"."&'./"?'&546'&6'&6'&6'&6'&74"727&6/�a���49[aA)O%-j'&]�]5r-%O)@a[9'
0BA;+


>HC���U


	#	
	
$				2	
AC: �����oM�=a-6O�UwW[q	( -	q[WwU�P6$C

+) (	
8&/
&eM���a�	
&
$	

��%+"&54&"32#!"&5463!54 �&@&�Ԗ`(88(�@(88(�r��&&j��j�8(��(88(@(8��������#'+2#!"&5463"!54&#265!375!35!�B^^B��B^^B
�

��
`���^B�@B^^B�B^�
��
�
`��
�������!="&462+"&'&'.=476;+"&'&$'.=476;�p�pp�p�$���!�$qr�
�%���}�#ߺ���pp�p��!�E$�
�rq�ܢ#���
%�
ֻ��!)?"&462"&4624&#!"3!26!.#!"#!"&547>3!2/B//B//B//B�
�@

�
�2�����^B�@B^�\77\�aB//B//B//B/�@

��
��

�~��B^^B@2^5BB5��2���.42##%&'.67#"&=463! 2�5KK5L4�_�u:B&1/&��.-
zB^^B���4L��v��y�KjK��4L[!^k'!A3;):2*�<vTq6^B�B^�L4�$���)��*@��A4#"&54"3!4."#!"&5!"&5>547&5462�;U gI�v��0Z���Z0�L4�@�Ԗ�@4L2RX='�8P8��'=XR� U;Ig0,3lb??bl3���4Lj��jL4*\���(88(�����\���}I/#"/'&/'&?'&'&?'&76?'&7676767676`�
(�5)�0
)��*)
0�)5�(
��
(�5)�0
))��))
0�)5�(
��*)
0�)5�(��
)�5)�0
)*��*)
0�)5�)
��
)�5)�0
)*���5h$4&"24&#!4>54&#"+323254'>4'654&'!267+#"'&#!"&5463!2>767>32!2&4&&4�N2��$YGB
(HGEG  H��Q�#5K4L��i�!<�����;��5KK5 
A#
("/?&}�vh��4&&4&�3M95S+C=�,@QQ9��@@�IJ 2E=L5i�>9eM��E;K5�5K	J7R>@#�zD<����5=q%3#".'&'&'&'.#"!"3!32>$4&"2#!"#"&?&547&'#"&5463!&546323!2`  #A<(H(GY$��2NL4K5#aWTƾh&4&&4�K5��;����=!�i��hv�}&?/"(
#A
 5K��2*!	Q@.'!&=C+S59M34L=E2 JI UR@@&4&&4&���5K;E��Lf9>�ig�<Dz�#@>R7J	K�5h4&"24#"."&#"4&#"".#"!54>7#!"&54.'&'.5463246326326&4&&4��IJ 2E=L43M95S+C=�,@QQ9�@@�E;K5��5K	J7R>@#�zD<�gi�>9eM��Z4&&4&<�#5K4LN2��$YGB
(HGEG  H��V���;��5KK5 
A#
("/?&}�vh��i�!<��4<p4.=!32>332653272673264&"2/#"'#"&5#"&54>767>5463!2�@@��2*!	Q@.'!&=C+S59M34L.9E2 JI UR�&4&&4&��Lf6A�ig�6Jy�#@>R7J	K5�5K;E@TƾH  #A<(H(GY$��2NL4K#5#a=4&&4&�D��=�i��hv�}&?/"(
#A
 5KK5��;�����+54&#!764/&"2?64/!26 $$ &�
�[6��[[j6[��&���^����a�a@�&�4[��[6[��[6�&+�^����a�a�����+4/&"!"3!277$ $$ [��6[��
&&��[6j[
���^����a�ae6[j[6�&�&�4[j[��^����a�a�����+4''&"2?;2652?$ $$ ��[6[��[6�&�&�4[���^����a�af6j[[��6[��
&&��[��^����a�a�����+4/&"4&+"'&"2? $$ [6�&�&�4[j[6[j���^����a�ad6[��&&�
�[6��[[j��^����a�a������  $2>767676&67>?&'4&'.'.'."#&6'&6&'3.'.&'&'&&'&6'&>567>#7>7636''&'&&'.'"6&'6'..'/"&'&76.'7>767&.'"76.7"7"#76'&'.'2#22676767765'4.6326&'.'&'"'>7>&&'.54>'>7>67&'&#674&7767>&/45'.67>76'27".#6'>776'>7647>?6#76'6&'676'&67.'&'6.'.#&'.&6'&.5/�a����^����D&"	


	4
	$!	#
	
		
	



 
.0"�Y
	+


!	
	

$	
	"
+


		
	�Α	
		
����^����a�a��

	

			
	

	

		
	
		P� '-(	#	*	$

"
!				
*
!	

(				

	
��$�
		
2
�~�/$4&"2	#"/&547#"32>32�&4&&4��V%54'j&&�'��/덹���:,���{	&4&&4&�V%%l$65&�b��'C��r!"��k[G�+;%!5!!5!!5!#!"&5463!2#!"&5463!2#!"&5463!2����������&��&&�&&��&&�&&��&&�&�������@�&&&&�&&&&�&&&&��{#"'&5&763!2{�'
��**�)��*��)'/!5!#!"&5!3!26=#!5!463!5463!2!2���^B�@B^�&@&`��^B`8(@(8`B^��� B^^B�&&�����B^�(88(�^���G	76#!"'&?	#!"&5476	#"'&5463!2	'&763!2#"'��c�)'&�@*������*�@&('�c���(&�*�cc�*�&'
����*�@&('�c���'(&�*�cc�*�&('���c�'(&�@*��19AS[#"&532327#!"&54>322>32"&462 &6 +&'654'32>32"&462Q�g�Rp|Kx;CB��y��y� 6Fe=
BP���PB
=eF6 ��Ԗ��V����>!pR�g�QBC;xK|��Ԗ���{QNa*+%��x��x5eud_C(+5++5+(C_due2Ԗ�Ԗ�����>�NQ{u�%+*jԖ�Ԗ��p�!Ci4/&#"#".'32?64/&#"327.546326#"/&547'#"/&4?632632��(* 8(!�)(��A�('��)* 8(!U�SxyS�SXXVzxT�TU�SxyS�SXXVzxT�@(� (8 *(���(��'(�(8 ���S�SU�Sx{VXXT�T�S�SU�Sx{VXXT���#!"5467&5432632�������t,Ԟ;F`j�)��������6�,��>�jK?�s��
�!%#!"&7#"&463!2+!'5#�8Ej��jE8�@&&&&@������XYY�&4&&4&�qD�S�%��q%��N\jx��2"&4#"'#"'&7>76326?'&'#"'.'&676326326&'&#"32>'&#"3254?''7�4&&4&l��
�NnbS���VZbR��SD	
zz
	DS��Rb)+U���Sbn�
��\.2Q\dJ'.2Q\dJ.Q2.'Jd\Q2.'Jd`!O�`��	`�����&4&&4�r$#@�B10M�5TNT{L�5T
	II	
T5�L;l'OT4�M01B�@#$�*�3;$*�3;�;3�*$;3�*$�:$/� @@�Qq`��@���"%3<2#!"&5!"&5467>3!263!	!!#!!46!#!�(88(�@(8��(8(�`(�(8D<���+����+�<��8(�`(��8(�`�8(�@(88( 8(�(`�(8(��(������<��`(8��(`����`(8����||?%#"'&54632#"'&#"32654'&#"#"'&54632|�u�d��qܟ�s]
=
��Ofj�L?R@T?��"&�
>
�f?rRX=Ed�u�ds���q��
=
_M�jiL��?T@R?E& �f
>
�=XRr?��b���!1E)!34&'.##!"&5#3463!24&+";26#!"&5463!2����
��
08(��(8��8(@(8��
�

�
�8(��(88(�(`(����1

�`(88(���(88(@

��
�`(88(@(8(��`���#!"&5463!2�w�@w��w�w�`�@w��w�w��/%#!"&=463!2#!"&=463!2#!"&=463!2&��&&�&&��&&�&&��&&�&��&&�&&�&&�&&�&&�&&��@'7G$"&462"&462#!"&=463!2"&462#!"&=463!2#!"&=463!2�p�pp�pp�pp��
�@

�
��p�pp��
�@

�

�@

�
Рpp�p��pp�p���

�
�pp�p���

�
�

�
��<L\l|#"'732654'>75"##5!!&54>54&#"'>3235#!"&=463!2!5346=#'73#!"&=463!2#!"&=463!2}mQjB919+i1$AjM_3<��/BB/.#U_:IdDRE�
�@
�
����k*G�j�
�@
�

�@

�
TP\BX-@8
C)5�XsJ@�$3T4+,:;39SG2S.7<���

�vcc)�)%L�l�}�

��

�
���5e2#!"&=463%&'&5476!2/&'&#"!#"/&'&=4'&?5732767654'&��@�0��2uBo
T25XzrDCBB�Eh:%��)0%HPIP{rQ�9f#-+>;I@KM-/Q"�@@@#-bZ��$&P{<�8[;:XICC>.�'5oe80#.0(
l0&%,"J&9%$<=DTI���cs&/6323276727#"327676767654./&'&'737#"'&'&'&54'&54&#!"3!260%
<4�"VRt8<@<
-#=XYhW8+0$"+dT�Lx-'I&JKkm��uw<=V�@�!X@		v
'��|N;!/!$8:I�Ob�V;C#V

&
(���mL.A:9 !./KLwP�M�$��@@
��/?O_o��%54&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!26#!"&5463!2��@��@��@���@��@��@���@��@��@�^B��B^^B@B^�����������������������������N��B^^B@B^^���#+3	'$"/&4762%/?/?/?/?�%k��*��6�6��bbbb|��<<��<�bbbb��bbbb�%k���6���6Ƒbbb��<<��<<�^bbbbbb@��M$4&"2!#"4&"2&#"&5!"&5#".54634&>?>;5463!2�LhLLh����
	�	LhLLhL!'�Ԗ���Ԗ@'!&	
�?�&&LhLLhL�	�	
��hLLhL��	j��jj��j	&@6/"
��&&���J#"'676732>54.#"7>76'&54632#"&7>54&#"&54$ ���ok;	-j=y�hw�i�[+PM3ѩ���k=J%62>Vc��a�aQ�^��� ]G"�'9��r�~:`}�Ch�  0=Z�٤���W=#uY2BrUI1�^Fk[|��a�����L2#!67673254.#"67676'&54632#"&7>54&#"#"&5463�w��w�+U	,i<��F{�jh�}Z+OM

2ϧ���j<J%51=Ub�w��w��w�@w�zX"�'8'�T�yI9`{�Bf� 
,>X�բ���W<"uW1AqSH1�bd��w�w����'74'!3#"&46327&#"326%35#5##33#!"&5463!2����0U6c��c\=hl���ࠥ�Ymmnnnn�w�@w��w�w�w&�46#�Ȏ;ed����wnnnnn��@w��w�w����	]#/#"$&6$3 &#"32>7!5!%##5#5353����Е���tt����u�{�zz�{S�ZC�`�c�����o���t�*�t��q|��|.EXN#�??�������,<!5##673#$".4>2"&5!#2!46#!"&5463!2��r�M*
�*M~�~M**M~�~M*j����jj����&�&&&�`��P%��挐|NN|���|NN|�*�jj���jj�@��&&�&&@�
"'&463!2�@4�@&�Z4�@�4&@
#!"&4762&��&�4�Z4&&4��@@���
"'&4762�&4�@�4&@��&�4�&�@�
"&5462@�@4&&4��4�@&�&�@����
3!!%!!26#!"&5463!2�`��m��`
�^B��B^^B@B^���
 `���@B^^B�B^^��@
"'&463!2#!"&4762�@4�@&�&&��&�4��4�@�4&Z4&&4��@��
"'&463!2�@4�@&��4�@�4&@
#!"&4762&��&�4�Z4&&4��@��:#!"&5;2>76%6+".'&$'.5463!2^B�@B^,9j�9Gv33vG9�H9+bI��\
A+=66=+A
[��">nSM�A_:��B^^B1&�c*/11/*{�'VO�3��@/$$/@�*�?Nh^��l+!+"&5462!4&#"!/!#>32]��_gTRdg�d���QV?U��I*Gg?����!�2IbbIJaa���iwE33����00� 08����4#"$'&6?6332>4.#"#!"&54766$32z�䜬��m�
I�wh��QQ��hb�F�*�@&('�k�������z��
�	
_hQ��н�QGB�'(&�*�eoz�(���q!#"'&547"'#"'&54>7632&4762.547>32#".'632�%k'45%��&+�~(
(�h		&

\(
(�		&

~+54'k%5%l%%l$65+~

&		�(
(\

&		�h(
(~�+%��'��!)19K4&"24&"26.676&$4&"24&"24&"2#!"'&46$ �KjKKjKjKKj�e2.e<^P��,bKjKKj��KjKKjKjKKj��#��#���LlL�KjKKjKjKKjK��~-��M<M�(PM<rjKKjK�jKKjKujKKjK�������L���< 6?32$6&#"'#"&'5&6&>7>7&54$ L�h��я�W.�{+9E=�c��Q�d�FK��1A
0)���������p�J2`[Q?l&������٫�C58.H(Y��'����:d 6?32$64&$ #"'#"&'&4>7>7.546'&'&'# '32$7>54'Y����j`a#",5NK�
����~E�����VZ|�$2$
|��:
$2$�|ZV���:�(t}�����h�fR�88T
h�̲����X(	
&%(H�w��(%&	(X�ZT\�MKG�{x��|�!#"'.7#"'&7>3!2%632u��

�j
�H����{(e9
�1b���U#!"&546;5!32#!"&546;5!32#!"&546;5463!5#"&5463!2+!2328(��(88(`�`(88(��(88(`�`(88(��(88(`L4`(88(@(88(`4L`(8 ��(88(@(8��8(��(88(@(8��8(��(88(@(8�4L�8(@(88(��(8�L4�8����OY"&546226562#"'.#"#"'.'."#"'.'.#"#"&5476$32&"5462��И&4&NdN!>!
1X:Dx++w�w++xD:X1
-�U��
�!�*,*&4&��h��h&&2NN2D&

..J<
$$
<JJ<
$$
<J..

��P���bb&&�7!!"&5!54&#!"3!26!	#!"&=!"&5463!2��`(8��
�@

�
+��8(�@(8��(88(@(8�(��8(� @

@
�m+�U�`(88(�8(@(88(��
�h`���(\"&54&#"&46324."367>767#"&'"&547&547&547.'&54>2�l4

2cK�Eo���oED
)
�
�
�
)
D�g-;</-
?.P^P.?
-/<;-gY�����Y�

.2 L4H|O--O|HeO,����,Oe�q1Ls26%%4.2,44,2.4%%62sL1q�c�qAAq����4#!#"'&547632!2#"&=!"&=463!54632
��
��		@	
`
	��	
��

`?`�
�

@	
	@	
�!	��	
�
�
�
����54&+4&+"#"276#!"5467&5432632�
�
�
	`		_
�������v,Ԝ;G_j�)��``

��
	��		_ԟ����7
�,��>�jL>���54'&";;265326#!"5467&5432632	��		��
�
�
�
�������v,Ԝ;G_j�)���	`		����

`������7
�,��>�jL>�����X`$"&462#!"&54>72654&'547 7"2654'54622654'54&'46.' &6 �&4&&4&�y��y�%:hD:Fp�pG9�F�j� 8P8 LhL 8P8 E;
Dh:%������>�4&&4&}y��yD~�s[4D�d=PppP=d�>hh>@�jY*(88(*Y4LL4Y*(88(*YDw"
A4*[s�~����>�����M4&"27 $=.54632>32#"' 65#"&4632632 65.5462&4&&4�G9��������&
<#5KK5!��!5KK5#<
&ܤ��9Gp�p&4&&4&@>b�u��ោؐ&$KjK�nj��j�KjK$&����j��j�b>Ppp���
%!5!#"&5463!!35463!2+32����@\��\���8(@(8�\@@\������\@\���(88(��\��@��34#"&54"3#!"&5!"&5>547&5462�;U gI@L4�@�Ԗ�@4L2RX='�8P8��'=XR� U;Ig04Lj��jL4*\���(88(�����\��@"4&+32!#!"&+#!"&5463!2�pP@@P���j�j�@�@�\�@\�&��0�p����j��	��� \��\�&��-B+"&5.5462265462265462+"&5#"&5463!2�G9L4�4L9G&4&&4&&4&&4&&4&L4�4L�
��&���=d��4LL4d=�&&�`&&�&&�`&&�&&��4LL4
 ��&�#3CS#!"&5463!2!&'&!"&5!463!2#!"&52#!"&=4632#!"&=463�(8(��(88(�(`�x
��c�`(8���@��@��@�`(��(88(@(8(D��9�8(��`@�@@�@@��/?O_o��������-=%+"&=46;25+"&=46;2+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2%+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2%+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2+"&=46;2!!!5463!2#!"&5463!2�
@

@

@

@

@

@
�
@

@

@

@
�
@

@
�
@

@
�
@

@

@

@
�
@

@
�
@

@
�
@

@

@

@
�
@

@
�
@

@

@

@
�
@

@

@

@
�����
@
&�&&&�@

@
�@

@

@

@
�@

@
��@

@
�@

@
�@

@
�@

@
��@

@
�@

@
�@

@
�@

@
��@

@
�@

@
�@

@
��@

@
�@

@

@

@
����

`��&&�&&
��/?O_o�����%+"&=46;25+"&=46;2+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2+"&=46;2!!#!"&=!!5463!24&+"#54&+";26=3;26%#!"&5463!463!2!2�
@

@

@

@

@

@
�
@

@

@

@
�
@

@
�
@

@

@

@
�
@

@

@

@
���8(�@(8��
@

@
�
@

@
�
@
&�&&@8(�(8@&�@

@
�@

@

@

@
�@

@
��@

@
�@

@
�@

@
��@

@
�@

@

@

@
��� (88( ���

�@

``

��

``
-�&&& (88(��&@����<c$4&"2!#4&"254&+54&+"#";;26=326+"&5!"&5#"&46346?>;463!2�KjKKj�����KjKKj�������&��Ԗ���Ԗ�&&�@�&�&KjKKjK��
��jKKjK ������.��&j��jj��j&4&�@�@&&���#'1?I54&+54&+"#";;26=326!5!#"&5463!!35463!2+32����������� \��\����8(@(8�\  \����������\@\���(88(��\����:
#32+53##'53535'575#5#5733#5;2+3����@��E&&`�@@��`  ����  `��@@�`&&E%@�`��@ @ @��		 �� � � � �� 		��@ 0
@��!3!57#"&5'7!7!��K5�������@ � � @���5K�@����@@��� �����#3%4&+"!4&+";265!;26#!"&5463!2&�&�&�&&�&&�&�w�@w��w�w���&&��@&&��&&@��&&��@w��w�w�����#354&#!4&+"!"3!;265!26#!"&5463!2&��&�&��&&@&�&@&�w�@w��w�w�@�&@&&��&�&��&&@&:�@w��w�w��-M�3)$"'&4762	"'&4762	s
2

�.

�

2

�w��
2

�.

�

2

�w��
2

�

�

2

�w�w

2

�

�

2

�w�w
M�3)"/&47	&4?62"/&47	&4?62S
�.

2

��w

2

��
�.

2

��w

2

�M
�.

2

��

2

�.

�.

2

��

2

�.M�3S)$"'	"/&4762"'	"/&47623
2

�w�w

2

�

�

2

�w�w

2

�

��
2

��w

2

�

�.v
2

��w

2

�

�.M�3s)"'&4?62	62"'&4?62	623
�.

�.

2

��

2

�.

�.

2

��

2�
�.

�

2

�w�

2v
�.

�

2

�w�

2-Ms3	"'&4762s
�w�

2

�.

�

2�
�w�w

2

�

�

2
MS3"/&47	&4?62S
�.

2

��w

2

�M
�.

2

��

2

�.M
3S"'	"/&47623
2

�w�w

2

�

�m
2

��w

2

�

�.M-3s"'&4?62	623
�.

�.

2

��

2-
�.

�

2

�w�

2���/4&#!"3!26#!#!"&54>5!"&5463!2
��

@
�^B��  &�&  ��B^^B@B^ @

��
M��B^%Q=
&&<P&^B@B^^�+3"&5463!2#3!2654&#!"3#!"&=324+"3�B^^B@B^^B��
@

��
`�^B��B^�p�^B�B^^B�@B^`�@

�
�S`(88(``  ��'$4&"2%4&#!"3!26#!"&5463!2�&4&&4�
��

@
�^B��B^^B@B^f4&&4&��

�@
��B^^B@B^^/$4&"2%4&#!"3!264+";%#!"&5463!2�/B//B�
�


���0L4�4LL44L_B//B/��

�@
M   �4LL44LL���  >& $$ ������(���r���^����a�a��������(���^����a�a����!C#!"&54>;2+";2#!"&54>;2+";2pP��PpQ��h@&&@j�8(�Pp�pP��PpQ��h@&&@j�8(�Pp@��PppP�h��Q&�&�j (8pP��PppP�h��Q&�&�j (8p��!C+"&=46;26=4&+"&5463!2+"&=46;26=4&+"&5463!2Q��h@&&@j�8(�PppP�Pp�Q��h@&&@j�8(�PppP�Pp��@h��Q&�&�j (8pP�PppP�@h��Q&�&�j (8pP�Ppp@�@�	#+3;G$#"&5462"&462"&462#"&462"&462"&462"&462#"&54632K54LKj=KjKKj��KjKKj�L45KKjK�<^�^^��KjKKj��p�pp���\]��]\��jKL45K��jKKjKujKKjK��4LKjKK�^^�^��jKKjK��pp�p�r]��]\����� $$ ���^����a�aQ�^����a�a�����,#"&5465654.+"'&47623 #>bq��b�&4�4&�ɢ5����"		#D7e�uU6�&4&��m����1X".4>2".4>24&#""'&#";2>#".'&547&5472632>3�=T==T=�=T==T=��v)�G�G�+v�@b��R�R��b@�=&����\N����j!>�3l�k����i�k3�hPTDDTPTDDTPTDDTPTDD|x��xX�K--K��|Mp<#	)>dA{��RXtfOT# RNftWQ���,%4&#!"&=4&#!"3!26#!"&5463!2!28(�@(88(��(88(�(8��\�@\��\@\��\���(88(@(88(�@(88�@\��\�\��\ �u�'E4#!"3!2676%!54&#!"&=4&#!">#!"&5463!2!232�5��([��5@(\&��8(��(88(��(8,�9.��+�C��\��\@\� \��6Z]#+��#,k��(88(@(88(��;5E�>:��5E�\�\��\ �\�1. ���$4@"&'&676267>"&462"&462.  > $$ n%��%/���02�
KjKKjKKjKKjKf���ff�������^����a�a�y��y/PccP/�jKKjKKjKKjK���ff���ff�@�^����a�a�����$4@&'."'.7>2"&462"&462.  > $$ n20���/%��7KjKKjKKjKKjKf���ff�������^����a�a3/PccP/y��	jKKjKKjKKjK���ff���ff�@�^����a�a�����+7#!"&463!2"&462"&462.  > $$ �&��&&��&KjKKjKKjKKjKf���ff�������^����a�a�4&&4&�jKKjKKjKKjK���ff���ff�@�^����a�a���#+3C54&+54&+"#";;26=3264&"24&"2$#"'##"3!2@������@KjKKjKKjKKjK����ܒ���,����������gjKKjKKjKKjK�X�Ԁ�,�,��#/;GS_kw�����+"=4;27+"=4;2'+"=4;2#!"=43!2%+"=4;2'+"=4;2+"=4;2'+"=4;2+"=4;2+"=4;2+"=4;2+"=4;2+"=4;54;2!#!"&5463!2�``����``��`��``�``�``�``�``�``�````�p`���K5��5KK5�5Kp``�``�``��``�``�``��``�``��``��``�````��`��������5KK5�5KK@���*V#"'.#"63232+"&5.5462#"/.#"#"'&547>32327676���R?d�^��7ac77,9x�m#@#KjK�#
ڗXF@Fp:f��_ #W��Ip�p&3z�	�h[ 17��q%q#:��:#5KKu�'t#!X:	%�#+=&>7p@���*2Fr56565'5&'.	#"32325#"'+"&5.5462#"/.#"#"'&547>32327676@��ͳ�����8
2.,#,f�k*1x���-!���#@#KjK�#
ڗXF@Fp:f��_ #W��Ip�p&3z�	�e�`��v�o�8�t-�	�:5	��[�*�#:��:#5KKu�'t#!X:	%�#+=&>7p
�3$	"/&47	&4?62#!"&=463!2I�.

2

��w

2

�
-�@�)�.

2

��

2

�.
�-@@-��S�$9%"'&4762		/.7>	"/&47	&4?62i2

�.

�

2

�w�
E��>

u>

��.

2

��w

2

�
�2

�

�

2

�w�w
!��




�h�.

2

��

2

�.
���;#"'&476#"'&7'.'#"'&476�'
�)'�s
"+5+�@ա'
�)'����F*4*E�r4�M:�}}8��GO
�*4*������~�
(-/'	#"'%#"&7&67%632���B�;><���V�?�?V�� -����-C�4
<B�=�cB5���!%��%!�b 7I�))�9I7���	#"'.5!".67632y��(
��#

��##@,(
�)���8!	!++"&=!"&5#"&=46;546;2!76232-S��S����������S�

		��S��S�`���`���		

������K$4&"24&"24&"27"&5467.546267>5.5462 8P88P88P88P�8P88P�4,�C��S,4p�p4,,4p�p4,6d7AL*',4p�pP88P8�P88P8HP88P8`4Y��&+(>EY4PppP4Y4Y4PppP4Y�%*<O4Y4Ppp���
%@\ht�	"'&4762"&5462&#!"&463!2#"'&'7?654'7&#"&'&54?632#!"&463!2"&5462"'&4762��		

	����@U�SxyS���R���#PT����('�#��TU�SxySN���@����		

		�		

		
3��@��xS�SUO#���'(���V^�'(���PVvxS�SU��i��@��		

		
`�<+"&=46;2+"&=467>54&#"#"/.7!2���<'G,')7��N;2]=A+#H

�
�0P��R��H6^;<T%-S�#:/*@Z}


>h���.%#!"&=46;#"&=463!232#!"&=463!2�&�&&@@&&�&@&�&�&&&��&&�&�&�&&��&f�&&�&&b�#!"&=463!2#!"&'&63!2&�&&&'�'%@% �&&�&&�&&&&�k%J%#/&'#!53#5!36?!#!'&54>54&#"'6763235���
����Ź���}���4NZN4;)3.i%Sin�1KXL7觧�*		��#��&		*������@jC?.>!&1'\%Awc8^;:+<!P��%I%#/&'#!53#5!36?!#!'&54>54&#"'6763235���
����Ź���}���4NZN4;)3.i%Pln�EcdJ觧�*		��#��&		*������-@jC?.>!&1'\%AwcBiC:D'P%!	#!"&'&6763!2�P������&:�&?�&:&?����5"K�,)""K,)���h#".#""#"&54>54&#"#"'./"'"5327654.54632326732>32�YO)I-D%n "h.=T#)#lQTv%.%P_�	%	
%�_P%.%vUPl#)#T=@�/#,-91P+R[�Ql#)#|'�'
59%D-I)OY[R+P19-,##,-91P+R[YO)I-D%95%�_P%.%v���'3!2#!"&463!5&=462 =462 &546 ����&&��&&��&4&r&4&�������@����&4&&4&�G݀&&������&&f��������
��sCK&=462	#"'32=462!2#!"&463!5&'"/&4762%4632e*&4&i����76`al�&4&���&&��&&}n�

R

�

R
�z����f�Oego�&&�5�����`3��&&����&4&&4&�
D�

R

�

R
z����v���"!676"'.5463!2@�@w^�Cc�t~55~t�cC&�&@���?J���V��|RIIR|��V&&��#G!!%4&+";26%4&+";26%#!"&546;546;2!546;232�����@@@@�L4��4LL4�^B@B^�^B@B^�4L�� �� ��N�4LL44L`B^^B``B^^B`L����L4&"2%#"'%.5!#!"&54675#"#"'.7>7&5462!467%632&4&&4��@�o�&�&}c ;pG=(
8Ai8^�^.�&4&&4&`��	`f�s��&& j�o/;J!#2
 KAE*,B^^B!`	$� ��-4&"2#"/&7#"/&767%676$!2�8P88P��Qr��	@
U���	@�
{`P�TP88P8�����P`��
�	@U	@�rQ���!6'&+!!!!2Ѥ���
8�������̙�e�;<*��@8 !�G��G�GQII���� %764'	64/&"2 $$ �f��3f4�:�4����^����a�a�f4334f�:4�:�^����a�a����� %64'&"	2 $$ ���:4f3��f4F���^����a�a��4�f4���4f�^����a�a����� 764'&"27	2 $$ �f�:4�:f4334����^����a�a�f4��:4f3���^����a�a����� %64/&"	&"2 $$ -�f4���4f�4����^����a�a��4f��3f4�:w�^����a�a���@��7!!/#35%!'!%j��/d��
�jg2�|�8�����������55���dc ��b���@��!	!%!!7!���FG)��D�H:�&�H����d���S)��U4&"2#"/ $'#"'&5463!2#"&=46;5.546232+>7'&763!2�&4&&4f]w�q�4�qw]	`dC���&&�:F�ԖF:�&&���Cd`�4&&4&����	]����]	`d[}�&�&�"uFj��jFu"�&�&�y}[d�#2#!"&546;4 +"&54&" (88(�@(88( r&@&�Ԗ8(��(88(@(8@����&&j��j�����'3"&462&    .  > $$ �Ԗ������>a��X��,��f���ff�������^����a�a�Ԗ�Ԗ�a>����T�X��,�,�~�ff���ff�@�^����a�a����/+"&=46;2+"&=46;2+"&=46;2�8(�(88(�(88(�(88(�(88(�(88(�(8 �(88(�(88(�(88(�(88(�(88(�(88��/+"&=46;2+"&=46;2+"&=46;2�8(�(88(�(88(�(88(�(88(�(88(�(8 �(88(�(88�(88(�(88�(88(�(88���5E$4&"2%&'&;26%&.$'&;276#!"&5463!2KjKKj�
���
��
�
f���	

�\�
�
�w�@w��w�w��jKKjK"�G

�
ܚ

��f


�
���

	�@w��w�w�����  $64'&327/�a����^�����  ��!  ����^����a�a��J@%��%	6�5��/	64'&"2	"/64&"'&476227<���ij��6��j6��u%k%~8p�8}%%�%k%}8p�8~%<���<�ij4j��4����t%%~8�p8~%k%�%%}8�p8}%k���54&#!"3!26#!"&5463!2&��&&�&�w�@w��w�w�@�&&�&&:�@w��w�w����/#!"&=463!24&#!"3!26#!"&5463!2���@�^B��B^^B@B^��w��w��w@w��@@�2@B^^B��B^^���w��w@w���+#!"'&?63!#"'&762�(��@�	@�(@>@�%����%%��� ���!232"'&76;!"/&76 �
�($��>��(����
		��J ���&%�����$%64/&"'&"2#!"&5463!2�ff4�-�4ff4f�w�@w��w�w��f4f�-�f4����@w��w�w�����/#5#5'&76	764/&"%#!"&5463!2��48`���
#�� ����\�P\��w�@w��w�w���4`8�
��
#�@  ���`\P�\`�@w��w�w�����)4&#!"273276#!"&5463!2&� *���f4�
'�w�@w��w�w�`�&')���4f�*�@w��w�w�����%5	64'&"3276'7>332#!"&5463!2�`��'(wƒa8!
�,j.��(&�w�@w��w�w��`4`*�'?_`ze<��	bw4/�*��@w��w�w�����-.  6 $$ ���� �������(�r���^����a�a���O����(��������_�^����a�a�����
-"'&763!24&#!"3!26#!"&5463!2y��B��(�(�
�@

�
�w�@w��w�w�]#�@�##� �

�@
�@w��w�w�����
-#!"'&7624&#!"3!26#!"&5463!2y(��(@B@u
�@

�
�w�@w��w�w��###��@���

�@
�@w��w�w�����
-'&54764&#!"3!26#!"&5463!2@�@####���@��w�@w��w�w��B��(�(������@�@w��w�w����`%#"'#"&=46;&7#"&=46;632/.#"!2#!!2#!32>?6�#
!"'�?_

BCbCa�f\	+
~�2�	
��
	�}0�$

��
q
90r�
�

�pr%Dpu���?#!"&=46;#"&=46;54632'.#"!2#!!546;2��D
a__����	g	

*`-Uh1

��������

�߫�}
	$^L��
���
4��b+"&=.'&?676032654.'.5467546;2'.#"�ǟ�
B{PDg	q�%%Q{%P46'-N/B).ĝ
�9kC<Q
7>W*_x*%K./58`7E%_���
�	,-3�
cVO2")#,)9;J)���
�"!*�
#VD,'#/&>AX��>++"''&=46;267!"&=463!&+"&=463!2+32��Ԫ�$
�	��	
p���U�9ӑ
@�/�*f�����o�	

VRfq
�f=S��E!#"&5!"&=463!5!"&=46;&76;2>76;232#!!2#![�
��

 ��

��
�
�%
)��
	���

��"

��Jg
Uh
B�W&WX���
hU
g��
�84&#!!2#!!2#!+"&=#"&=46;5#"&=46;463!2�j��@jo�����
������g�|�@��~�v����v�
u�n#467!!3'##467!++"'#+"&'#"&=46;'#"&=46;&76;2!6;2!6;232+32Q�Kt#�� ��#F�N�Qo!��"�դ��ѧ����!�mY

�Zga~bm]�

[o�"�U+��������,����� @��h��
h@�@X
��h��h
��@�8���3H\#5"'#"&+73273&#&+5275363534."#22>4.#2>��ut
3NtR�P*�H�o2

Lo�@!�R(�Ozh=�,G<X2O:&D1A.1G$<2I+A;"B,;&$��L��GlF/�����3�D�����;a��$8$��".�!3!
��.�3!#!"&5463!���8( 8(��(88( ��h (8��(88(@(8�(8H!!#!"&5463!54&#!"3!2654&#!"3!2654&#!"3!26��(D 8(��(88( 8��@��@��@�$����(88(@(8��(8� @@@@@@"�}
$BR3/&5##"'&76;46;232!56?5"#+#5!76;5!53'#3!533��H��
��

�����D��q		�x7��	���K/�/K��F��h�/"���		@`����Z		s�Y��w�jj��jj��j"�}
$4R%3/&5##"'&76;46;232!53'#3!533!56?5"#+#5!76;5��H��
��

��������K/�/K��F����q		�x7��	�h�/"���		@`����jj��jj��j�Z		s�Y��
w"�)9IY%#"'&76;46;232#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2�
��

����� ��@������@���`��		@`�����������"�)9IY#!"&=463!2%#"'&76;46;232#!"&=463!2#!"&=463!2#!"&=463!2��� 
��

�������@��������@ ��r��		@`��r������"��
$CV%4&#"326#"'&76;46;232%#"'&'73267##"&54632!5346=#'73BX;4>ID2F��
��

������8PuE>.'%&TeQ,j��m{��+�>R�{�?jJrL6V��		@`��7>wmR1q
uW�ei��/rr�
:V��r"��
$7V4&#"326#"'&76;46;232!5346=#'73#"'&'73267##"&54632BX;4>ID2F��
��

������+�>R�{�8PuE>.'%&TeQ,j��m{��?jJrL6����		@`���rr�
:V��r3>wmR1q
uW�ei����@�\%4&#"326#!"&5463!2+".'&'.5467>767>7>7632!2&%%&�&��&& &�7.'	:@�$LB�WM{#&$h1D!		.I/!	Nr�&&%%��&&�&&V?, L=8=9%pEL+%�%r@W!<%*',<2(<&L,"r�@\#"&546324&#!"3!26%#!#"'.'.'&'.'.546767>;&%%&�&��&& &i7qN��	!/I.		!D1h$&#{MW�BL$�@:	'.�&&%%���&&��&&�=XNr%(M&<(2<,'*%<!W@r%�%+LEp%9=8=L ���	+=\d����%54#"327354"%###5#5#"'&53327#"'#3632#"'&=4762#3274645"=424'.'&!  7>76#'#3%54'&#"32763##"'&5#327#!"&5463!2��BB��PJN�C'%!	B?)#!CC $)�54f�"��@@
B+����,A

A+�&�+A
�
ZK35N #J!1331�CCC $)��w�@w��w�w��2��"33�F�Y�F~��(-%"��o�4*)$�(*�	(&;�;&&9LA38�33�4��S,;;,W��T+<<+T;(��\g7�x�:&&:�:&&<r����%-�@w��w�w����	+=[c}���#"'632#542%35!33!3##"'&5#327%54'&#"5#353276%5##"=354'&#"32767654"2 '.'&547>76 3#&'&'3#"'&=47632%#5#"'&53327�''RZZ�:k��id YYY.06�	62+YY-06	R[!.�'CD''EH$��VV�X:���:Y
X;��:Y
�fyd/%jG�&DC&&CD&O[52.
[$�C-D..D�^^���* l�y1%=^�I86�i077S
3
$EWgO%33%O�O%35	��EE�F�W�t;PP;p��t;PP;p�q��J�gT��F�Q%33&P�P%33%R�
7>%3���!+}��{�'+"&72'&76;2+"'66;2U
�&�
��	�(���P

�*��'�e�J."�-d�Z��-n �-���'74'&+";27&+";276'56#!"&5463!2�~�}�		�7��e �	���۩w�@w��w�w��"���
$Q#�'�!#
����@w��w�w��
�I-22#!&$/.'.'.'=&7>?>36����9II ! '	$ !�����01$$%A'	$ ! ����g	
\7@�)(���7Y
	
 \7@�)(���7Y
@����	'5557	���,���VW�QV���.R���W��=���?��l��%l`��������~����0��!#!#%777	5!	������R!!�XC�C��fff�݀�#�� `��,��������{��{{�`��������Og4&"2 &6 $"&462$"&62>7>7>&46.'.'. '.'&7>76 �Ԗ�� ���HR6L66L�G�HyU2LL2UyH��HyU2LL2UyHn
��X�6X��

��X�X��
Ԗ�Ԗ�����H�6L66L6�L2UyH��HyU2LL2UyH��HyU2L�n�6X��

��X�X��

�����2#!"&54634&"2$4&"2�w��w�@w��w�|�||��|�||���w�@w��w�w����||�||�||�|���	!3	37! $$ �n6^�5�5^h
����^����a�a������M�1�^����a�a���P��
*Cg'.676.7>.'$7>&'.'&'? 7%&'.'.'>767$/u5'&$I7o�b?K�\[z�H,1���+.@\7<��?5\V
,$V��g.GR@ �7��U,+!�����
	#	"8$}�{)�<�?L RR;kr,yE[��z#	/1
"#	#�eCI0/"5#`�	��"8���4~&p)4	2�{�H-.%W.L>���':Yi4&67&'&676'.'>7646&' '7>6'&'&7>7#!"&5463!2PR$++'TJX�j7-F��C',��,&C
."��!$28��h�/���"�	+p��^&+3$
i��0(�w�@w��w�w��+.i6=Bn\C1XR:#"�'jj�8Q.cAj�57!?"0D��$4"P[
&2�@w��w�w��D��"%.5#5>7>;!!76�P�Yh�pN!�HrD0�M��
 C0N��#>8\xx: �W]oW-�X���45���/%'#.5!5!#"37>#!"&5463!2p>,;$4
��5eD�+W�cE���w�@w��w�w�K�()��F
,VhV��^9tjA0/�@w��w�w���@�#"'&76;46;23�
��


��
	���&��

��� ���++"&5#"&7632�	���
^


c
� �&�

��@�#!'&5476!2� &��

����
^


b	���'&=!"&=463!546�
��� �&�
�
��	���
��
��q&8#"'&#"#"5476323276326767q'T��1[VA=QQ3���qq�Hih"-bfGw^44O#A���?66%CKJ�A}}�  !"�䒐""A$@C3^q|�z=KK?6�lk)���%!%!��V��V��u��u�u^-�m5�w��}�n�����~7M[264&"264&"2"&546+"&=##"&5'#"&5!467'&766276#"&54632�  �  ��*<;V<<O@-K<V<�<+*<J.@�k��c�lG
H_�_H
�<+*<<*+<    �<*�R+<<+�*<�f.@�+<<+��+<<+�@.��7�uu�7�
�**�
���R+<<+�+;;	��"%3I�#5472&6&67><&4'>&4.'.'.'.'.'&6&'.'.6767645.'#.'6&'&7676"&'&627>76'&7>'&'&'&'&766'.7>7676>76&6763>6&'&232.'.6'4."7674.'&#>7626'.'&#"'.'.'&676.67>7>5'&7>.'&'&'&7>7>767&'&67636'.'&67>7>.'.67�	\
��
	U7	
J#!W!'	

"';%

k	)"	
	'


/7* 		I	,6
*&"!

O6*
O $.(�	*.'

.x�,	$CN��	
�		*	�
6
		
7%&&_f&
",VL,G$3�@@$+
"


V5 3"	
""�#dA++
y0D-%&n4P'A5j$9E#"c7Y
6"	&
8Z(;=I50' !!e
�R
��
"+0n?�t(-z.'<>R$A"24B@(	~	9B9,	*$		
		<>	?0D�9f?Ae �	.(;1.D	4H&.Ct iY% *	�
7��


��
J	 <
W0%$	
""I!
*D	 ,4A'�4J"	.0f6D�4p�Z{+*�D_wqi;�W1G("%%T7F}AG!1#% JG3��� '.2>Vb%&#'32&'!>?>'&' &>"6&#">&'>26 $$ *b6�~�#��= ���XP2��{&%gx|�� .���W)o���O��LO�sEzG<��	CK}E	$MFD<5+
z���^����a�a$�MW�M��1>]|�YY�^D
�եA��<��K�m����E6<�"�@9I5*�^����a�a�����>^4./.543232654.#"#".#"32>#"'#"$&547&54632632�':XM1h*�+D($,/9p�`D�oC&JV<�Z PA3Q1*223�I�oBkែhMI����oPែhMI��oP�2S6,M!"@-7Y.?oI=[<%$('3 -- <-\�%Fu���Po��IMh���Po����IMh,���#?D76&#!"7>;267676&#!"&=463!267
#!"'&5463!26�%�8#!�
��&&Z"�M>2!��
	�^I7LRx_@�>MN�""��`�=&&*%�I�}��,
	�	L�7_jj��9����/%4&#!"3!264&#!"3!26#!"&5463!2�� ��� ��&��&&�&��������&&�&&��19#"'#++"&5#"&5475##"&54763!2"&4628(3�-�	&�B.�.B�&	�-�3(8Ig�gI�`������(8+U��e&��.BB.&����+8(�kk��`�������%-"&5#"&5#"&5#"&5463!2"&4628P8@B\B@B\B@8P8pP�Pp�����@�`(88(`�p.BB.�0.BB.���(88(�Pppͺ�������!%>&'&#"'.$ $$ ^/(V=$<;$=V).X���^����a�a��J`"(("`J��^����a�a��,���I4."2>%'%"/'&5%&'&?'&767%476762%6�[���՛[[���՛o��
�ܴ
 
���
��	��	$
$�	"	�$
$	��	�՛[[���՛[[�5`��

^�

�^

2`��
`2

^��^

��`
�����1%#"$54732$%#"$&546$763276�68��ʴh�f�킐&^�����zs��,!V[���vn)�	�6���<��ׂ�f{���z����}))N�s���3(@����+4&#!"3!2#!"&5463!2#!"&5463!2@&�&&f&��&&�&@&�&&&�4&&4&�@&&�&&��&&&& ��`�BH+"/##"./#"'.?&5#"&46;'&462!76232!46 `&�C�6�@Bb0�3eI;��:�&&�&4�L�4&���F���
�Z4&�w�4�) ���''
�5�r�&4&&�4&��&4��������}G�#&/.#./.'&4?63%27>'./&'&7676>767>?>%6}�)(."�2*&�@P9A
#sG�q]
#lh�<*46+(
	
<
5�R5"*>%</
 '2�@� 53*9*,�Z&VE/#E+)AC
(���	2k<X1$:hI(B
"	!:4Y&>"/	+[>hy
	���K
!/Ui%6&'&676&'&6'.7>%.$76$% $.5476$6?62'.76&&'&676%.76&'..676�#"NDQt	
�-�okQ//�jo_	������	���%&J�������Ղ���YJA-��.--
9\DtT+X?*<UW3'	26$>>�W0{�"F!"E �

^f`$"�_]\�<`�F�`�F�D��h>Cw�ls���J@�;=?s
:i_^{8+?`
)
O`�s2R�DE58/K��r	#"'>7&4$&5m��ī��"#���̵�$5���$�"^^W����=���ac��E�*���c������zk./"&4636$7.'>67.'>65.67>&/>z X^hc^O<q����+f$H^XbVS!rȇr?5GD_RV@-FbV=3!G84&3Im<$/6X_�D'=NUTL;2KPwt��Pt= 

�&ռ
,J~S/#NL,��8JsF);??1zIEJpq�DIPZXSF6\?5:NR=��;.&1��+!"&=!!%!5463!2�sQ9����Qs�*�*�*sQNQsBUw��
wUBF��H���CCTww���%1#"&=!"&=463!54632.  6 $$ �	��	
��

`?��������(�r���^����a�a�	��	
�
�
�
���(��������_�^����a�a�����%1#!#"'&47632!2.  6 $$ �
����		@	
`
��������(�r���^����a�a�
�
?		@	
���(��������_�^����a�a�����/#"'&476324&#!"3!26#!"&5463!2&�@�&
�@

�
�w�@w��w�w����&@B@&���

�@
�@w��w�w�����"&462  >& $$ �Ԗ��*�����(���r���^����a�a�Ԗ�Ԗ �������(���^����a�a���]�6#"$54732>%#"'!"&'&7>32'!!!2�f:�л����Ѫz��~�u:�
(�(%`V6B^hD%��i�(�]̳ޛ	��*>�6߅�����r�#�!3?^BEa�߀�#�9���#36'&632#"'&'&63232#!"&5463!2
��Q,&U�#+'
 �;il4L92<D`����w�@w��w�w�����`9ܩ6ɽ]`C4�7�7�&�@w��w�w����D+"&5#"'&=4?5#"'&=4?546;2%6%66546;2�������
	
��
	
��w�ww�w�������cB
�G]B
�G��t�y]t�y�
���#3C#!+"&5!"&=463!46;2!24&#!"3!26#!"&5463!2���@��`@`�^B��B^^B@B^��w��w��w@w��@��`@`���2@B^^B��B^^���w��w@w�����'/?P+5#"&547.467&546;532!764'!"+32#323!&ln��@
:MM:
@��nY*�Yz--zY�*55QDD�U���9p��Y-`]��]`.X /2I$�	t�@@/!!/@@3,$,3�$p$0�0��&*0��&���&��
!P@���RV2#"&/#"&/#"&546?#"&546?'&54632%'&54632763276%�>S]�8T;/M7��7T</L7�=Q7,�i�<R7,�5T</L666U;/M5�<U<,�i���6i���Q=a!;�;V6-�j�;V6-�5	P=/L596Q</L5�<U6-�i�;V7,�7O;-I6��8��i;k���)I2#!"&5463#9"'.'.'3!264&#!"2>7%>�w��w�@w��w�!"�5bBBb/�/*
8(@(87)��(8=%/�'#?��w�@w��w�w����#~$EE y &�L(88e):8(%O r		

		�O�?GQaq47&67>&&'&67>&"&#6$32#"#"'654  $&6 $6&$ Co��L��.*�KPx���.*� 
iSƓi
7J?��~�pi{_Я�;��lL�������UZ=刈�����刈�����_t'<Z
�:!
	���@!
��j`Q7$k�y, R����f��k*4�������LlL��=Z=刈��������&$&546$7%7&'5>�����]���5��%��w�����������&��P�?�zrSF�!|��&0	##!"&5#5!3!3!3!32!546;2!5463���)�
)����;)��);;)��)���&&������&@@&�&��&��	�
6 $&727"'%+"'&7&54767%&4762������֬>4P���t+8?::
	�	
::AW��``���EvEEvE<�.���"�e$IE&�O�&EI&�{h.`��m���"&#"&'327>73271[
>+)@
(���]:2,C?��*%�Zx/658:@#N
�C�=�E�(�o��E=��W'c:������#!#"$&6$3 &#"32>7!����ڝ���yy��,��{��ۀ�ہW�^F!�L�C=���y�:�y��w���߂0H\R%�"N^ '&76232762$"&5462"&46274&"&'264&#"'&&#"32$54'>$ $&6$ G>��>0yx1��4J55J�5J44J5�Fd$��?�4J55%6�E��#42F%��$f�������LlL�q>>11�J44%&4Z%44J54R1F$Z-%45J521��Z%F1#:��ʎ 9�������LlL�����#Qa"'&7622762%"&5462"&546274&#"&'73264&#"'&&#"32654'>#!"&5463!2�

5�5

*�*��.>.-@-R.>.-@-�<+*q�6�- -- 0�<�o,+< ��3�w�@w��w�w��

55

**�.. -- .. --G*<N�' ,-@-+*��M <*2
z��z
1�@w��w�w�����0<754&""&=#326546325##"&='26 $$ bZt�t&�sRQs��Z<t�sQ���^����a�a�>OpoO��xzRrqP6�z~{{Prr��^����a�a�����]054&"#"&5!2654632!#"&57265&<T<����H<T<������H������<T<8v*<<*������
��+;;+l���:�������=:��*;;*���
%!!"!!26#!"&5463!2��@� ]���]�@�w�@w��w�w�����]� �@��@w��w�w���	
%)3!!#335!!5!5!%#!!5!5!%#H��H{����R��H��H{���G��G{�)���q���G����R�R�q���R�R�q�����	#0@#"'632#"'632&#"7532&#"#7532#!"&5463!2L5+*5��L5+*5~�}7W|�3B}��}JC��7=}�w�@w��w�w�D�ZQ�[�1�N:_��)�i�$��)���@w��w�w��
)�	�����������6.#&#"'&547>'&#".'&'#"&5467%&4>7>3263232654.547'654'63277.'.*#">7?67>?>32#"'7'>3'>3235?�K�cgA+![<E0y�$,<'.cI
	,#� '!;7$�=ep���	��/�/7/
D+R>,7*
2(-#=
	/~[(D?G  �|,)"#+)O��8,+�'�6	y{=@��0mI�#938OA�E`
-�
)y_/FwaH8j7=7?%����a	%%!?)L
J
9=5]~�pj

 %(��1$",I 
$@((�
+!.S		-L__$'-9L	5V��+	
	6�T+6.8-$�0��+
t�|S1��6]�&#"'&#"67>76'&'&#"67>32764.#"#.32>67>7 $&54>7>7>7�rJ�@"kb2)W+,5/1		#

Z
-!��$IOXp7s�LCF9�vz NAG#/ 5|����Հ';RKR/J#=$,�9,�+$UCS7'2"1
 !�/
,

/--ST(::(�ep4AM@=I>".)x��ls��Y�|qK@
%(YQ�&N
EHv~����<Zx'#"&5467&6?2?'&"/.7.546326#"&'&/7264/7'764&"'?>>32.��A�UpIUxYE.A�%%%h%����%hJ%�����D,FZxULsT�gxUJrV�D�%hJ%�����@/LefL.C�%Jh%�����C�VsNUxϠ�@.FZyUHpV�A�%h&%%���%Ji%�����C�WpIUybJ/��Uy^G,D�%Jh%�����@�UsMtU�C�%hJ%�����C-Kfy�EX[_gj��&/&'.''67>7>7&'&'&'>76763>7>#&'&'767672'%'7'+"&'&546323267>7%#"'4'6767672,32�,+DCCQL�Df'
%:/d
B	4@}
�&!0$�?�����J�f�d�f-�.=���6(��:!TO�?
!I�G_�U%
����.
k*.=;�	5gN_X��	"
##
292Q41�
��*����6���nA;�|�
�BSN.	%1$����
6	$��nk�^�'7GWgw�����2+"&5463#!"&5463!254&+";2654&+";2654&+";2654&+";2654&+";2654&+";2654&+";2654&+";2654&+";26#"&=! B^^B�B^^B�:F�j��B^8(�(`�(� ������������������`�(8���^B��B^^B@B^�"vE�j�^B(8(�`(�����������������������8(����/?O_o��������/?2#!"&5463;26=4&+";26=4&+";26=4&+";26=4&+"54&+";2654&+";2654&+";2654&+";2654&+";2654&#!"3!2654&+";2654&+";2654&+";2654&+";2654&+";2654&+";2654&+";2654&+";2654&+";26@&&�&&�@@@@@@@@�@@@@@@@@@@��@@@@@@@@@@@@@@@@@@@&��&&�&��@@��@@��@@��@@��@@@@@@@@@@���@@@@@@@@�@@@@@@@@@@@��`'	"&5#"&5&4762!762$"&462���B\B@B\B��O�p�P����������.BB.���.BB.8$P��O広�������3CQ#".54>32#".546322#"&#"#"54>%".54>32%2#"&54>&X=L|<&X=M{<��TML�FTML�F�v�"?B+D�?B�J�p��H=X&<{M=X&<|dMTF�LMTF�(<kNs�I<kNs���Pvo�JPwo�/��s.=ZY�VӮv�Nk<J�sNk<I�shwPJ�ovPJ�o@��+"&7.54>2�r_-$�$-_rU���U��%��&&5%ő������'-
"'.546762����@��F�F�$�@B�@$.&�,�&.]]|�q����#<���<#(B�B��B%'-%'-'%'-"'%&'"'%.5467%467%62����@��l�l����@��l�l,���@��G�G�&!�@@�@�@@�@!&+#�+#�6�#+�$*`�:�p������:�p���x�
�p����=�`$>����>$�&@��&@�

�@&�p�@��	&.A!!"!&2673!"5432!%!254#!5!2654#!%!2#!8���Zp��?v�d���Ί�e�ns�6(���N[�����RW�u?�rt1Sr�F���|��iZ��@7�����މoy2���IM��C~[�R �yK{T:���%,AGK2#!"&5463!!2654'654.#532#532"&5!654&#"327#2#>!!�w��w�@w��w��~u��k'JTM��wa��|
DH��������>�I1q�Fj?����w�@w��w�w�����sq�*4p9O*�¸Z^���qh LE
�������"(nz8B
M���'?"&4624&#"'.'324&#"3267##"&/632632.�ʏ����hhMA�LR vGhг~��~������K„y���O^
��ʏ�ʏ��В*�LM@!<I�~��~����������t\��0�������CM4&"2#"&'676&/632#!"&=3267%2654&#"&#"%463!2"&4632�r�qq��tR8^4.<x3=RR��w�@w���_h�
Y��Ӗ���	K>�שw�w���ȍ�de�)�qrOPq�Ȧs:03=<x!m�@w��w�E\x�g�ӕ��є��%w�w����d��Ȏ��V��
-<K\%.'.>7'.?67'67%'>&%'7%7./6D�\$>	"N,��?a0�#O���1G�����9�'/���P(1#00��
($=!F"�9|��]�"RE<�6'o��9%8J$\:��\H�iTe<?}V��#�oj��?���d,6���%N#"
Hl��S��VY�]C

=�@�C4&"2!.#!"4&"2+"&=!"&=#"&546;>3!232�^�^^���Y	�	^�^^��`p�p�p�p`�]i�bb�i]�~�^^�^�e��^^�^���PppP��PppP��]��^^�]��3;EM2+"&=!"&=#"&546;>;5463!232264&"!.#!"264&" ]�`p�p�p�p`�]i�b���b�i���^^�^d�Y	�	!�^^�^��]��@PppP@@PppP@�]��^��^�]� ^�^^��e��^�^^� ��3$#!#!"&5467!"&47#"&47#"&4762++�&�2
$��$
�2&��&��&�4�&��&��Z4&�&##&�&4�&4�&4���4&�m4&�m���+DP4'&#"32763232674'&!"32763 3264'&$#"32763232> $$ g����* �o�`#�ə�0#z��#l(~���̠)���-g+����^����a�aF s"	+g�(�*
3#!|
#/IK/%*%D=)[�^����a�a����	!!!'!!77!���,���/���,�-���a��/G��	t%/;<HTbcq������%7.#"32%74'&"32765"/7627#"5'7432#"/7632#"5'7432#"&5'74632	#"/6327#"/6327#"/46329"&/462"&/>21"&/567632#!.547632632
	
	*


			��X		�

^

`		���

^b
	��c�
	f�u��
U`�59u���

���

4�J���
	
l�~		~�	F��	
��	�2�����

�
�	��	�m����|O�,��� ����	

���
��������

ru|	��u�
�
"�����
)9 $7 $&= $7 $&= $7 $&=  $&=46��w���`���w���w���`���w���w���`���w��b����`����VT�EvEEvE�T��VT�EvEEvE�T*VT�EvEEvE�T*EvE�EvEEvE�Ev�#^ct�#!"&5463!2!&'&!"&5!632#"&'#"/&'&7>766767.76;267674767&5&5&'67.'&'&#3274�(8(��(88(�(`�x
��c�`(8��!3;:�A0�?ݫ�Y

	^U	47D$

	7�4U3I�
|��L38wtL0�`(��(88(@(8(D��9�8(��Q1&(!;��
(g-	Up�~R�2(/{E���(Xz*Z%(�i6CmVo8�#T#!"&5463!2!&'&!"&5!3367653335!3#4.5.'##'&'35�(8(��(88(�(`�x
��c�`(8�iF������F��Zc�r�cZ�`(��(88(@(8(D��9�8(���k�k�"	��kk�J	 	!��	�k�#S#!"&5463!2!&'&!"&5!%!5#7>;#!5#35!3#&'&/35!3�(8(��(88(�(`�x
��c�`(8�-Kg
kL#D��C��JgjL��D���`(��(88(@(8(D��9�8(���jj�	�jjkk��kk����#8C#!"&5463!2!&'&!"&5!%!5#5327>54&'&#!3#32�(8(��(88(�(`�x
��c�`(8� G]�L*COJ?0R��\wx48>�`(��(88(@(8(D��9�8(���jj��RQxk��!RY�#*2#!"&5463!2!&'&!"&5!!57"&462�(8(��(88(�(`�x
��c�`(8�������P�pp�p�`(��(88(@(8(D��9�8(����������p�pp�	�#*7JR5#5#5#5##!"&5463!2!&'&!"&5##5!"&54765332264&"�����<(8(��(88(�(`�x
��c�`(8����k�ޑc�O"�jKKjK�������������`(��(88(@(8(D��9�8(������SmmS?M���&4&&4�#9L^#!"&5463!2!&'&!"&5!#"/#"&=46;76276'.'2764'.�(8(��(88(�(`�x
��c�`(8���������6dd�WW6&44�`(��(88(@(8(D��9�8(��.��	����G���5{��{5�]�]$59�95�#3C#!"&5463!2!&'&!"&5!2#!"&5463#"'5632�(8(��(88(�(`�x
��c�`(8��4LL4��4LL4l	��		�`(��(88(@(8(D��9�8(���L4��4LL4�4L��	
Z
	�#7K[#!"&5463!2!&'&!"&5!>&'&7!/.?'&6?6.7>'�(8(��(88(�(`�x
��c�`(8�`3��3��3��3�v
�
?
�
�`(��(88(@(8(D��9�8(���&��&-��&��&�
?


��
'���6#'.
'!67&54632".'654&#"32�eaAɢ/PRAids`WXyzO�v��д��:C;A:25@Ң>�����-05r��n������`��H(�����' gQWZc[���
-%7'	%'-'%	%"'&54762�[������3[��M���N�����
��3"��,��""3,3"o�ng�$������߆���]�g�n��$����+��)��

")")"

��x#W#"&#!+.5467&546326$32327.'#"&5463232654&#"632#".#"o���G��n\�u_MK'����̨|�g?CM7MM5,QAAIQqAy��{�b]BL4PJ9+OABIRo?z��.�z��
�n�6'+s�:�������z�cIAC65D*DRRD*�wy�al@B39E*DRRD*��'/7  $&6$ 6277&47' 7'"' 6& 6'�lL������������R�R����ZB|��R�R��>����d�ZZ��������LlL�Z����R�R«����Z��&�>���«|��R� � ��! $&54$7 >54'5��������P���f���f����P�����牉�@��s��-����ff���`-����c6721>?>././76&/7>?>?>./&31#"$&��(@8!IH2hM>'

)-*
h'N'��!'Og,R"/!YQG<I *1)

(-O1D+0�n�������z�3fw���G2'3�rd1!sF0o ��.q"!%GsH8��@-!5|w|pgS=
"B2PJfh�G���d�R	�(P]ly��&$'77&7567'676'"'7&'&'7&47'6767'627''6$'67'654'7&'7'&'&'7&'5&$  $6 $&6$ j��j:,A��A��S9bb9R#:j���8AܔA,z��C�9Z04\40Z9�C��!B�;X0,l,0X;�B�*A8ܔA&#9j`b9S$#R99#&A��8A�`
������䇇�<Z<䳎������LlL�fBϬ"129�,V<4!���!88dpm��"��BV,�92[P*V*P\M�C�

�C�M\P*V*P]L�D�

�D�L&BV*�8*8!����f�!4<gmpd88!&!8*8�*VB�Z<䇇�����䇇��������LlL�����9Eis�%#"5432#"543275#&#"3254&'.547>54'63&547#5#"=3235#47##6323#324&"26%#!"&5463!2F]kbf$JMM$&�N92<Vv;,&)q(DL+�`N11MZ
%G���&54	#	i�<$8&@��0H12F1d�w�@w��w�w��B?@�UTZ3%}rV2hD5%f-C#�C@,nO	�a7�.0�x2	yR�uR/u�%6;&�$76%$56S�@w��w�w��D��<Hlw%4#"324&#"32!".5475&5475.546322#654'3%#".535"&#"5354'33"&+32#"&54632S����;<;||w
$+�|('-GVVG-��EznA�C?H_��`Rb���]Gg>Z2&`��9UW=��N9:PO;:dhe\=R����
+)�&')-S9��9kJ�<)Um�Q��/��-Ya^"![��Y��'(<`X;_�L6#)|����tWW:;X���	#'#3#!"&5463!2)
p�*�xeשw�@w��w�w���0,\8�����@w��w�w��9��I#"'#"&'&>767&5462#"'.7>32>4."&'&54>32JrO<3>5�-&FD(=Gq���@C$39a��LL��²�L4

&)
@]��v�
�q#CO���!~󿵂<ZK#*Pq.���%
L��²�LL��arh({�w؜\���i&5467&6747632#".'&##".'&'.'#".5467>72765'./"#"&'&5
�}����1R<2"7MW'$	;IS7@�5sQ@@)�R#DvTA;
0x
I)�!:>�+<B76:NFcP:SC4r�l+r �E%.*a-(6%('�>)C	6.�>�
!-I[4&#"324&#"3264&#"324&#"326&#"#".'7$4$32'#"$&6$32D2)+BB+)3(--(3�1)+BB+)�4'--'4��'���#!0>R	�H���MŰ9�o�u7ǖD��䣣���
R23('3�_,--,�R23('3�_,--,�����NJ
������?u�W�m%������#"'%#"'.5	%&'&7632�!�
�;�
	`��u%"��(����!]#�c�)(�	��� #"'%#"'.5%&'&76	�!�
���	�(%#�#���fP_�"�(���!�)'��+�ʼn�����4I#"$'&6?6332>4.#"#!"&54766$32#!"&=46;46;2z�䜬��m�
I�wh��QQ��hb�F�*�@&('�k�������@����z��
�	
_hQ��н�QGB�'(&�*�eozΘ�@@`���  >. $$ ����ff���ff�����^����a�af���ff�����^����a�a��>�����"&#"#"&54>7654'&#!"#"&#"#"&54>765'46.'."&54632326323!27654'.5463232632�,�-,�,",:!
%�]&
%@2(/�.+�*)6!	<.$.�.*�*"+8#
�
#Q3,�,+�+#-:#"</$�)

w�

���
,*

x9-.2"'
,,
���@�&,,
��Qw
,����,#"+"&5#+"&5&'&'&547676)2�%2$l$�#l#�b~B@XXyo2�$CI@5��$$�>$$�/:yu��xv)%$	��/?CG%!5%2#!"&5463!5#5!52#!"&54632#!"&5463#5!5`���&&�&&������ �&&�&&�&&�&&@������&�&&&���������&�&&&�&�&&&��������%2 &547%#"&632%&546 #"'6���������\~����~\h�
���~\��h\�������V�
�V�������V��V���%5$4&#"'64'73264&"&#"3272#!"&5463!2}XT=��=TX}}�~�>SX}}XS>�~�}�w�@w��w�w���~:xx:~�}}Xx9}�}9xX}�@w��w�w���/>LXds.327>76 $&6$32762#"/&4762"/&47626+"&46;2'"&=462#"'&4?62E0l�,

*"�T�.�D@Yo������oo����@5D�

[		

Z
�Z

		[	 ``��[



Z

	�2
,�l0
(T�"�.�D5@������oo��oY@D,

Z

		[	�		[		

Z
��``EZ

		[		
�5%!  $&66='&'%77'727'%am��lL�������m�f�?���5���5>�f�F�tu�ut�F������������LlL�H�Y�C�L|��|L����Y�˄(��E''E*(�/?IYiy����%+"&=46;2+"&=46;2+"&=46;2+"&=46;2%"&=!#+"&=46;2+"&=46;2+"&=46;2+"&=46;2!54!54>$ +"&=46;2#!"&=������@�������&&������@��������������3P��
>��P3��&��&��r���r��r���&��&���r���r��r���
he

4LKM:%%:MKL4�W��T�&&��%/9##!"&563!!#!"&5"&5!2!5463!2!5463!2�&&�&��&�&&���� ��� ��&��&&i�@����&&@&7�����'#5&?6262�%%�o����;����j|/����&jJ%�p��&j;&i&�p���/|���j�ţ���%Jk%�o��%��	:g"&5462#"&546324&#!"263662>7'&75.''&'&&'&6463!276i���~ZYYZ~�@O��S;+[G[3YUD#o?D&G3I=J�y�TkBuhNV!WOhuAiS�y*'^C�C^'*SwwSTvvTSwwSTvv���WID\�_"[�g��q# /3qF��r2/ $r�g�%4
�HffH�J4d���#!#7!!7!#5!������VF��N����rmN�N��N����������N���!Y���+?Ne%&'&'&7>727>'#&'&'&>2'&'&676'&76$7&'&767>76'6�#
<�;1�1x��#*#
�G,T9�3%�/#0v�N�Z;:8��)M:(	&���C.J}2	%0����
 	^*
J�F	
&�7'X"2L�DM"	+��6�
M2+'BQfXV#+]
#���'
L/(e�B�9
�#,8!!!5!!5!5!5!5#26%!!26#!"&5!5���������������&4&���&�pP��Pp������������������@��@&&@��!&�@PppP@�*
��	9Q$"&54627"."#"&547>2"'.#"#"&5476$ "'&$ #"&5476$ (�}R}hL�K�
N���N
����U�d:�
�x�x�
�����8���
��
�
� ,, |2222�
MXXM

�ic,>>,�
����
�	����	�
��̺

�
��'/7?KSck{4&"2$4&"24&"24&"24&"24&"24&"24&"24&"264&"24&#!"3!264&"2#!"&5463!2�KjKKj�KjKKj��KjKKjKKjKKj��KjKKj��KjKKjKKjKKj��KjKKjKLhLLhL��KjKKj�&�&&&KjKKj�L4��4LL4�4L5jKKjKKjKKjK�jKKjK��jKKjK�jKKjK�jKKjK��jKKjK�jKKjK���4LL4��4LL�jKKjK�&&�&&��jKKjK�4LL44LL	��'E!#"+"&7>76;7676767>'#'"#!"&7>3!2�W�",&7'�	#$	&��g�pf5O�.P�q�ZZdS���-V"0kqzTx�D!��!8�p�8%'i_�F?;�k��R(`��
!�&)�'�
(2!&6367!	&63!2�!
`�B��1LO�(���+#�=)�heC��Qg#s`���f�4#����6�������q�'���X�|0-�g��	�>IY#6?>7&#!%'.'33#&#"#"/3674'.54636%#"3733#!"&5463!2��4��:@��7�vH��%�h��EP{��0&<'VFJo���1,1.F6��A��#���L4�4LL44L"%�	
 
7x'6
O\�JYFw���~�v^fH$ !�"xdjD"!�6��`J�4LL44LL��	�+3@GXcgqz�����-<JX{�&#"327&76'32>54.#"35#3;5#'#3537+5;3'23764/"+353$4632#"$2#462#"6462""'"&5&5474761256321##%354&'"&#"5#35432354323=#&#"32?4/&54327&#"#"'326'#"=35#5##3327"327'#"'354&3"5#354327&327''"&46327&#"3=#&#"32?"5#354327&3=#&"32?"#3274?67654'&'4/"&#!"&5463!2_��g��QQ��h���^_�~\[[\]�_^���h��QQ��g�e��<F�$�$$��� !!�&&�/!/

!!�

00/e&'!"e$�
		'!!�''�
	8''NgL4�4LL44L�UQ��gh��QUk=<Sc���cc,-{k���jUQ��hg��Q��



�9

,&W &$U�K$$KK$$KDC(>("
!
=))=2�( '! '�L#(>(
&�DC(>(z�L#�DzG)<)�4LL44LL��	�
BWbjq}��+532%+5324&+32763#4&'.546327&#"#"'3265#"&546325&#"32!264&"2%#'#735#535#535#3'654&+353#!"&5463!29$<=$�@?�SdO__J-<AA@)7")9,<$.%0*,G3@%)1??.+&((JgfJ*�A�������!&��j�jj��GZYG�иwssw��PiL>8aA	!M7�7MM7�7M�3!�
4erJ]��&3YM�(,
,%7(#)
,(@=)M%A20C&Me�e��(X���0&Ėjj�jV��	8Z8J9���N/4���$�8NN8�8NN��	�#&:O[���	$?b3'7'#3#%54+32%4+324+323'%#5#'#'##337"&##'!!732%#3#3##!"&53733537!572!56373353#'#'#"5#&#!'#'#463!2#"5#"5!&+&+'!!7353273532!2732%#54&+#32#46.+#2#3#3##+53254&".546;#"67+53254&.546;#"#'#'##"54;"&;7335wY-AJF���=c�(TS)!*RQ+��*RQ+�Y,�B^9^��Ft`njUM�')	~PS�PR�m���٘���M7�7Mo7�q

@)U	8�"����E(�1��++��NM7�7Mx3�7��8�D�62��W74�;�9�<�-A"EA�0:��AF@�1:�ؗ����B�f~~""12"4(�w$#11#�@}}!%+%5(�v$:O�\z��K��?*$\amcrVl��OO176Nn�<!E(=�<&l/������<<������
[ZZYY�89176���7OO7�==..//cV==::z,,,,aa,,��7OO7�Z::��;;Y
fcW�(		"6-!c�(		!5	#
b�t88176����tV:
&$'*9	%e#:
%'*9B����<<��;
&(�����	�#:Sn�����#"&54632%#76;2#"&54632%4&+";2?>23266&+"&#"3267;24&+"'&+";27%4&+";2?>23266&+"&#"3267;254+";27#76;2#!"&5463!2�3%#2%%,, _3$$2%%��M>�ALVb5)LDHeE:<
E�Mj,K'-R
M�~M>�ARVb5)LEHeE:<
E�
JAB�I*'!($rL4�4LL44Lv%1 %3!x*k�$2 %3!�;5�h
n
a�
!(lI;F	
	
��	r�p
p8;5�h

t
a�
!(lI;F��`	#k�4LL44LL
��	�
2HW[lt��#"'5632#6324&'.54327&#"#"&'32767#533275#"=5&#"'#36323#4'&#"'#7532764&"24'&#"327'#"'&'36#!"&5463!2=!9�n23��BD$ &:BCRM.0AC'0RH`Q03'`�.>,&I / *�
 /

��8/��n-(G@5��$ S3=�,.B..B�02^`o?7je;9G+��L4�4LL44LyE%#	�Vb�;A
!p &'F:Aq)%)#o�rg�T$v2�� 8�)2����z948/�{�8A�B..B/��q?@�r�<7(g/��4LL44LL��?#!"&'24#"&54"&/&6?&5>547&54626=�L4�@�ԕ;U g3
��
T
�2RX='�8P8|�5�
����4Lj��j� U;Ig@
	��
`
� "*\���(88(�]k
��&N4#"&54"3	.#"#!"&'7!&7&/&6?&5>547&54626;U gI��m*��]�Z0�L4�@�ԕ���=o=CT
��
T
�2RX='�8P8|�5�
� U;Ig��Xu?bl3���@4Lj��j��a���`
	��
`
� "*\���(88(�]k����/7[%4&+";26%4&+";26%4&+";26!'&'!+#!"&5#"&=463!7>3!2!2@@@@@@���0
��
o`^B��B^`5FN(@(NF5���@��@��@�u		�@�LSyuS�@�%44%����,<H#"5432+"=4&#"326=46;2  >. $$ ~Isy9���"SgR8v�H����D�	w
����ff���ff�����^����a�a�m2N+��	)H-mF+1����0*F		+f���ff�����^����a�a�����b4&#"32>"#"'&'#"&54632?>;23>5!"3276#"$&6$3 �k^?zb=ka`�U4J{�K_/4�^����W�&	vx :XB0���܂�ff���)
f������zz��X��lz=l�apz��o�b35!2BX���
�G@8��'	'=vN$\f���f�	1
	SZz�8�z�X�#("/+'547'&4?6276	'D�^�h

�

i��%5�@�%[i

�

h�]��@������]�h

�

i��%�@�5%[i

�

h�^�@@������)2#"&5476#".5327>OFi-���ay~�\~;��'�S���{�s:D8>)AJfh]F?X��{[��TC6��LlG��]��v2'"%B];$�-o��%!2>7>3232>7>322>7>32".'.#"#"&'.#"#"&'.#"#546;!!!!!32#"&54>52#"&54>52#"&54>52�-P&+#($P.-P$'#+&PZP&+#"+&P-($P-.P$(#+$P.-P$'#+&P-.P$+#pP@@Pp�H85K"&ZH85K"&ZH85K"&Z����@��Pp��@��@��@pMSK5, :&�LMSK5, :&�LMSK5, :&����!!3	!	�����@�����@@�����	#"$$3!!2"j������aѻxl���a����lx�a�a����j������!!3/"/'62'&63!2��'y��

�`�I

��y�����My��

�`�I

��y'W`#".'.#"32767!"&54>3232654.'&546#&'5&#"

4$%Eӕ;iNL291 ;XxR`�f՝�Q8T������W��iW�gW:;*:`�Qs&?RWXJ8�oNU0�J1F@#)
[�%6_PO�QiX(o�`��_?5�"$���iʗ\&>bd�s�6�aP*< -;iFn�*-c1B���Wg4'.'4.54632#7&'.#"#"'.#"32767'#"&54632326#!"&5463!2��#$(	1$6]'
!E3P|ad(2S;aF9'EO�Se�j]�m�]<*rYs��hpt.#)$78L*k�h�w�@w��w�w��B

%
$/$G6
sP`X):F�/�fwH1p�dl�qnmPH�ui�kw_:[9D'��@w��w�w��34."2>$4.#!!2>#!".>3!2�Q��н�QQ��н�QQ��h�~w��w�h���f����ff����н�QQ��н�QQ��н�QZ����ZQ�����ff���ff�#>3!2#!".2>4."f����ff�����н�QQ��н�QQ���ff���ff��Q��н�QQ��н�	,\!"&?&#"326'3&'!&#"#"'  5467'+#"327#"&463!!'#"&463!2632���(#�AH����s���9q � ci��<=�
#�]�<������OFA��!�������re��&&��U�&&![e��F �������U?���g�����4_���������a�?b�+��r7�&4&��&4&�p,�+K4&"2$4&"2.#!"3!264&#!"3!2#"&=!"&=#47>$ �KjKKjKKjKKjH#�j#H&&&������KjK�KjK�g	�V�	ijKKjKKjKKjK���..n((�[���5KK5��5KK5�[po�Nv<<vN�:f���.R#!"&463!24'!"&5463!&$#"!2#!32>+#"'#"&546;&546$3232�2$�B$22$�$�*$22$�X�ڭ��ӯ�$22$�tX'���hs2$���ϧ��kc�$22$���1���c�$2�F33F3VVT2#$2����ԱVT2#$2��g���#2UU���݃
�2$#2UU�1݃���2��,u�54#"67.632&#"32654'.#"32764.'&$#"7232&'##"&54732654&#"467&5463254632>32#"'&�ru�&9��%"*#�͟ <yK0Og�" 
&9B3�;��㛘8��s%+DWXRD= @Y%�	!Q6R�!4M8�+6rU^z=)�RN��.)C>O%GR�=O&^���op������C8�pP*�b�Y
_�#��$��N Pb@6��)?����+0L15"4$.�Es
�5I�Q"!@h"�Y7e|J>z�iPe��n�eHbIl�F>^]@����n*9
���6[_3#"&54632#.#"32%3#"&54632#.#"326%4&'.'&! ! 7>7>!���������
�=39?
6'_����������
�>29?
5'17m-V����U--,�bW.�������뮠@Fyu0HC$������뮠@Fyu0HC$L���=??
<����=! A	<��`�;+"&54&#!+"&5463!2#!"&546;2!26546;2���p���Ї����0�p�����p���@��I�������pp���>Sc+"&=46;254&+"&+";2=46;2;2=46;2;2%54&#!";2=;26#!"&5463!2���A5�DD�5A7^6a7MB5��5B7?�5B~�`��`��`0`��rr��5A44A5�����v�5AA5�f�*A���`��`0`�����	!!!!	#!"&5463!2��ړ�7���H��7j�v�@v��v�v��'���:��@v��v�v���MUahmrx���������������#"'!"'!#"&547.547.54674&547&54632!62!632!#!627'!%!"67'#77!63!!7357/7'%#	%'3/&=&'	5#?&5476��!�p4�q"���"�"�6�"� ��'������h*�[���
��|�*��,�@���?wA�UM�pV���@�˝�����)��Ϳw����7(�{��*U%���K6������=0�(���M���		��"!O		dX$k
!!��!
����b��	
���[�����TDOi
��@��6��b��xBA�ݽ�5
�
�ɝ:����J���+���3����,��p
x�1���������Fi
(��R��
463!#!"&5%'4&#!"3���`����а@.�.@A-X��f�B����$��.BB.�.C��}
)&54$32&'%&&'67���"w�`�Rd]G�{��o]>p6��sc(��@wg����mJ�PAjy���YW�a͊AZq���{HZ�:�<dv\gx�>��2AT�Kn������+;"'&#"&#"+6!263 2&#"&#">3267&#">326e��~�└�Ȁ|��隚���Ν|����ū|iy�Zʬ��7Ӕ�ް�r|�uѥ��x�9[��[9�jj��9A�N��N�+,#ll"���B�S32fk��[/?\%4&+";26%4&+";26%4&+";26%4&+";26%#!"&5467&546326$32�]]��ee��ee��ee��$��~i
�qfN-*���������#����Sj������t�2"'q�C���B8!�'�>	
!%)-159=AEIMQUY]agkosw{��������!	%!	5!#5#5#5#5#57777????#5!#5!#5!#5!#5!#5!#5!#5#537#5!#5!#5!#5!#5!#55#535353535353%"&546326#"'#32>54.&54>3237.#"����������Q%%%%%%%%%?iiihOiixiiyiixii�Arssrrssr��%s�ssrrss�Ns%%%%%%%%%%�����������'<D<'paC_78#7PO7)("I$	75!����RA��b��(���ss�ss�ss�ss�ss�"/!".""."
!."".!/^.".^.".]/".�$$$$$$$$$$$$$$$$��Os$$$$$$$$$$$$$$sO$s�ss�ss�ss�ss�ss#��������}$)	13?*
,./:
-�s�*4&"2$4&"2#!"&5463!2!5463!2_��������?-��-??-�,@�@,�-?����pq�8��,??,D,??,��,??(�Z2#".#"3267>32#".543232654&#"#"&54654&#"#"&547>326���ڞU�zrhgrx�S��Пd�U <e�����x՞����Zf��_gן:k=2;�^��9��Œ��7\x��x\7����K=5Xltֆ�W����W{e_�%N��%,%CI��%���#+W4&+54&"#";26=32"&462"&462!2#!"&54>7#"&463!2!2�&�&4&�&&�&4&���KjKKj�KjKKj� ���&&�&%��&&�&&4&�&&�&4&�&&��5jKKjKKjKKjK��%z
0&4&&3D7&4&
%&���'S4&"4&"'&"27"&462"&462!2#!"&54>7#"&463!2!2&4�&4&�4&4��KjKKj�KjKKj� ���&&�&%��&&�&&4&�%&&�ے&4��"jKKjKKjKKjK��%z
0&4&&3D7&4&
%&��	&	!'!	!%!!!!%"'.763!2�o���]�F������o�������oZ��Y��@:�@�!�!�g���������������f�/�/��I��62'"/"/"/"/"/"/"/7762762762762762762%"/77627&6?35!5!!3762762'"/"/"/"/"/"/%5#5!4�ZSS6SS4SS4SS4SS4SS4SS4�ZSS4SS4SS4SS4SS4SS4S�-4�ZSS4S@������4SS4�ZSS6SS4SS4SS4SS4SS4S@�����ZSSSSSSSSSSSSSS�ZSSSSSSSSSSSSSy�ZRRR@%:=
:+������:
=���RR�ZSSSSSSSSSSSSS���������Cv!/&'&#""'&#"	32>;232>7>76#!"&54>7'3&547&547>763226323@``����`
VFaaFV


$.


.$

��y��y�	.Q5Z���E$ ,l<l, $E���R?Y*��@���@�2	!#""#!	��y��y=r�na�@@(89*>�*%>>%*�>*98(QO�!���L\p'.'&67'#!##"327&+"&46;2!3'#"&7>;276;2+6267!"'&7&#"(6&#"#"'�D��g��OOG`n%�E������LL{�@&&�N�c,sU�&&�!Fre&&�s�����s���#�/,�������<=�
#�]�g��L�o�GkP�'��r-n&4&2�-ir&�&�?���o 
��������4_�����5OW! .54>762>7.'.7>+#!"&5#"&5463!2"&462�{�����{BtxG,:`9(0b��Կ�b0(9`:,GxtB��&@&�&@&K5�5K`�����?e==e?1O6#,
#$
,#6OO��&��&&�&�5KK���������?!"'&'!2673267!'.."!&54632>321
��4��q#F�""�8'g��o#-��#,"t�Yg��>�oP$$Po�>�	��Z�e�p#����)�R��0���+I@$$@I+����+332++"&=#"&=46;.7>76$  ������@����ᅪ*��r���������@��@�����������r���'/2+"&5".4>32!"&=463  �&@��~[���՛[[��u˜~���gr�������&�`����u՛[[���՛[~~@��r������=E32++"&=#"&=46;5&547&'&6;22676;2  >�����``@``�ٱ��?E,��,=?��r�������H�����@``@�GݧH`�j��j���r������BJ463!2+"&=32++"&=#"&=46;5.7676%#"&5   &@�~���``@``�� �v�X����r�������&���������@``@����+BF��`r������ks463!2+"&=32++"&=#"&=46;5&547'/.?'+"&5463!2+7>6 %#"&5   &@�~���``@``��~4e	
0
	io@& �jV	
0
	Z9�������r�������&���������@``@�G�ɞ5o
,
sp� &@k^
,
c8~~��`r�������8>KR_32++"&=!+"&=#"&=46;.767666'27&547&#"&'2#"�����@�@���'�Ϋ���'������sg��gs�����ww�@����sg��g����@����@���-ss��ʃl������9���9��������OO���r9���9��FP^l463!2+"&=$'.7>76%#"&=463!2+"&=%#"&54'>%&547.#"254&' &@�L?����CuГP	��v�Y�� &@�;"����������ޥ�5݇�����ޥ���5�`&����_��ڿg��w��BF�@&����J_	s���&��&�����?%x���������%x��JP\h463!2+"&='32++"&=#"&=46;5.7676632%#"&56'327&7&#"2#"� &@�L? ���ߺu�``@``��}
�ຒ�ɞ���������ue��eu�9����ue��e�&����_��"|N�@``@��"��"|a~���l����o����9���9��r9��@�9���;C2+"&5"/".4>327'&4?627!"&=463  �&@Ռ		.	
�N~[���՛[[��u˜N�		.	
����gr�������&�`֌
	.		�O��u՛[[���՛[~N�
	.		��@��r������9A'.'&675#"&=46;5"/&4?62"/32+  ��'��֪�����\
	.		�4�		.	
\���r������|��ݧ���憛��@�\		.	
��
	.		\�@��r�����~9A"/&4?!+"&=##"$7>763546;2!'&4?62  m��		-

���@���ݧ���憛��@&�

-		�@r������m4��

-		����ٮ*�������		-

��r������+"&5&54>2  ����@��[���՛[�r�����������dG�u՛[[���r������  ".4>2������r�[���՛[[���՛�r������5�՛[[���՛[[����$2#!37#546375&#"#3!"&5463�#22#�y��/Dz?s����!#22#�2#��#2S�88�	����2#V#2��L4>32#"&''&5467&5463232>54&#"#"'.K���g��&Rv�gD�
$*2%	+Z hP=DXZ@7^?1
۰��3O+�l��h4���`���M@8'�+c+RI2
�\�ZAhS�Q>B�>?S2Vhui/�����,R0+	ZRkm�z�+>Q2#"'.'&756763232322>4."7 #"'&546��n/9�b�LHG2E"D8_
p�dd���dxO�"2�xx��ê�_�lx�2X	
!+'5>-�pkW[C
�I
I@50�Od���dd��˥�Mhfx�����x^���ә�	�#'+/7!5!!5!4&"2!5!4&"24&"2!!!��� 8P88P�� 8P88P88P88P����������P88P8 ���P88P88P88P8� ������������+N &6 !2#!+"&5!"&=463!46;23!#!"&54>32267632#"_����>�@`

��
�
��

`
�
� L4Dg��y� 6Fe=O���O�U�4L��>����
�
��

`
�
`

��4L�2�y5eud_C(====`L4����3V &6 #"/#"/&54?'&54?6327632#!"&54>32 7632_����>���		�	
	��	
	�		��		�	
	��	
	�		��%%S��y� 6Fe=�J�%��>����	
	�		��		�	
	��	
	�		��		�	
	��%65%S�y5eud_C(zz.!6%$!2!!!46;24&"2!54&#!"�&���&�&@�Ԗ��V�@&&�@��&&�Ԗ�Ԗ@��&���3!!!	!5!'!53!!	#����7I�e�����eI7��CzC�l��@�����@������@�#2#!"&?.54$3264&"!@������մ���pp�p���������((��������p�pp����#+/2#!"&?.54$3264&"!264&"!@������մ���^^�^@����^^�^@���������((��������^�^^�����^�^^�����v(#"'%.54632	"'%	632U�/�@��k0�G��,�zD#[�k#�
/t�g��
F��
����Gz�����	#'#3!)
p�*�xe���0,\8�����T���#/DM�%2<GQ^lw�����
&'&676676&'&7654&'&&546763"#"'3264&7.>&'%'.767&7667&766747665"'.'&767>3>7&'&'47.'.7676767&76767.'$73>?>67673>#6766666&'&6767.'"'276&67&54&&671&'6757>7&"2654&57>&>&'5#%67>76$7&74>=.''&'&'#'#''&'&'&'65.'&6767.'#%&''&'#2%676765&'&'&7&5&'6.7>�&5R4&5S9
W"-J�0(/�r
V"-J�0(.�)#"6&4pOPpp�c�|o}vQ�[�60X�Q��W1V�	
#5X		N"&
.
)
D>q J:102(z/=f��*4!>S5b<U$:I o<G*	,
&"O	X5
#!

��	R N#
C
83J*��R	!(D
#%37	�;$-.�
(,��覦�6ij
�	���"���)9
E�%����!B83
	j9�6/,	:QD')yX#�63V
��b�a	,
Ue��LPA@���*	̳�`Xx*&E
V36��%	B3%	B3XA	
#!.mU"A	
#!.mUB-#2+Jii�i�m-C<I(m��8qF/*)0�S
		
I
E5&+>!%
(!$p8~5..:5I

~��T�
4~9p# !
)& ?()5F	1	
	
� d%{v*�:
 @e
s|D�1d {�:�*dAA|oYk'&��<��tu��ut�&vHC�XXTR�;w��
��71™
Z*&'
1	9?	.

$��Gv5k65P<�?8q=4�a	
SC"��1#<�/6B&!ML	�^;�6k5wF1<P�C	�;$"&462"&46232>.$.�`�aa��sa�``��Z9k����'9؋ӗa-*Gl|M�e_]`F&O������ܽ�sDD!/+�``�aa�``�a1<YK3(
 /8HQelA�Z3t_fQP<343J;T7Q�+?Kgw  $6&$  $&62+"5432+"&=.54  $;26=462;26=4& 4&#!"3!26)����߄��4R4߄��mlL�������r {jK#@#Q�a����^�����@���@���`&��&&�&�������߄��4R4�Ď������LlL�N� �@K5#:rr:#5K���^����a�a��``]��]``����&&�&&	/!3#4&#!"3!265##!"&5463!22�������@K5^B��B^^B@B^5K���� �@���5K�B^^B�B^^B�K	/!2##!"&5463!2#4&#!"3!265�5KK5^B��B^^B@B^���@��K5��5K�B^^B�B^^B�`� �@ 	/!2##!"&5463!2#4&#!"3!265�5KK5^B��B^^B@B^���@��K5��5K�B^^B�B^^B�`� �@ 	/!2##!"&5463!2#4&#!"3!265�5KK5^B��B^^B@B^���@��K5��5K�B^^B�B^^B�`� �@ 	+2##!"&5463!2#4&#!"3!265�5KK5^B��B^^B@B^���@�K5��5K�B^^B�B^^B�`� �@ �{#!&'#"'&547632m*���
�0���((�'(�$0K
��*�*��% 3#!3# '!#53 5#534!#53 6!3@����@@@��pp��@@@����@@pp@��`������� �����	�+/7;A#3!5!!3#!!5!35!355#%53#5!#35#!!!!!!!!����������������������������������������������������������������������
�	#'+/3?CGW#3!5!!35!!3#!!5!#!5!3535!355#%#3%!53#5!#35#!5##5!3!5!3!5	����������������������������������������������������������������������������������������������������������������!"&5463!2!"!�`(88(@(8�`(8�}2�2R �`8(@(88(�`8HR2�2���##6?6%!!!46#!"&5463!2x���� ��8�(�`(�(88(@(8�
���� (8��(`�(8(@(88��	�'ATd+5326+5323##"' %5&465./&76%4&'5>54&'"&#!!26#!"&5463!2�
��

���i�LCly5�)*H�celzzlec0h�b,,b�eIVB9@RB�9�J_�L4�4LL44L44%��2"��4��:I;p!q4b�b3p(P`t`P(�6EC.7B�I6�4LL44LL��	�.>$4&'6#".54$ 4.#!"3!2>#!"&5463!2Zj��b�jj[���wٝ]�>o��Ӱ�ٯ�*�-���oXL4�4LL44L'�)�꽽�)�J)���]��w����L���`��ֺ��۪e���4LL44LL�;4&#!"3!26#!"&5463!2#54&#!";#"&5463!2�
��

@
�^B��B^^B@B^���
��

��B^^B@B^`@

��
M��B^^B@B^^>��

��
�^B@B^^��5=Um	!	!!2#!"&=463!.'!"&=463!>2!2#264&"".54>762".54>762��������?(`��`(?��b|b��?B//B/�]�����]FrdhLhdrF�]�����]FrdhLhdrF@�@��@�(?��@@?(@9GG9@/B//B�aItB!!BtI�Ѷ�!!��ьItB!!BtI�Ѷ�!!��ь�-M32#!"&=46;7&#"&=463!2#>5!!4.'.46�ՠ��`�@`ՠ��`���M�sF�Fs�MM�sFFs�M����ojj�o��@@�jj�@@�<���!(!���!(!�-3?32#!"&=46;7&#"&=463!2+!!64.'#�ՠ��`�@`ՠ��`��	�	Dq�L�L�qD����ojj�o��@@�jj�@@B>=�C�����-3;32#!"&=46;7&#"&=463!2+!!6.'#�ՠ��`�@`ՠ��`��UVU96�g�g�6����ojj�o��@@�jj�@@β����**ɍ�-G32#!"&=46;7&#"&=463!2#>5!!&'.46�ՠ��`�@`ՠ��`���M�sF�Fs�M�k�k�����ojj�o��@@�jj�@@�<���!(!3��3!(!�9I2#!"&=4637>7.'!2#!"&=463��@b":1P4Y,++,Y4P1:"�":1P4Y,++,Y4P1:"b�@@��@7hVX@K-AA-K@XVh77hVX@K-AA-K@XVh7����Aj"#54&#"'54&#"3!26=476=4&#"#54&'&#"#54&'&'2632632#!"&5&=4632>3265K @0.B @0.B#6'&�&
l
@0.B 2'	.B A2TA9B;h" d�
mpP��Tl��L�c�_4.H�K5�]0CB.�S�0CB.�/#��'?&&)$�$)�0CB. }(AB.�z3M�2"61�d�39�L/PpuT(If�c�_�E�`1X"#4&"'&#"3!267654&"#4&"#4&26326#!"&'&5463246326�\B B\B�&@5K�&@�"6LB\B B\B ��sc�i�L}Q�P<m$��3�jN2�c�B.�p.BB.���3K5+"�3,"� �.BB.��.BB.���.�G=�c�i�(+�lOh7/DVj�"�c�=���&5Jb�#"'&=.547!"&46;'.54632!2327%.54&#"327%>%&#"!"3!754?27%>54&#!26=31��?>I��j��jq,J[�j.-t�j�lV��\���$B.R1?@B.��+?2`$�v5K-%��5KK5�.olRIS+6K5�̈$B\B 94E.&�ʀ�15uE&
�Ԗ�Pj��j�dX�U�GJ7!.B
�
P2�.B
�
%2@	�7�K5(B�@KjKj�?+f�UE,�5K~!1��.>F.��F,Q5*H��$b2#!"&=%!"&=463!7!"&'&=4634'&#!">3!!"3!32#!"3!23!26=n$<vpP��Pp���Pp�w�*�Rd�ApP�]��'@�A&
3@��&H-�[(8@
2�EB^&1
=&�&81����PppP��pP w���cOg Pp��c�
4& #.& &,,:8(�%^B &�
.�&&��2t"&'&54'&5467>32>32>32#"#.#"#.#"3!27654&#"547654&#"#654&�Mye
t|]�WS�Sg�SY�\x{
70"1i�92�DU1&=	��	=&0@�c	>&/Btd4!�*"�8K4+"��@H@/'=	t�?�_K�93-�]�
UlgQ���QgsW
�]#�+�i>p&��3�0&�VZ&0B/
���%3B.�"t�o ){+C4I��(
/D0&�p0D��3[_cg"'&#"3!2676=4&"#54&#"#54&#"#4&'2632632632#!"&'&5463246#!#!#�5K�)B4J�&@�#\8P8 @0.B J65K J6k�
cJ/4qG^�\hB�2<m$��3�iG;��     �K5����6L4+"�3p`b�)<8(=0CB.@Z7OK5`:7O��k�EW�^�tm��@Q7/DVi�##j�������������%4Ia�2#!"&5&546325462632"32654&"3267654&76;74&"#.#"2676=#"&'+53264&#!"3</�U�X�dj���jP��ԖEu�!7JG72P
�
B�%
�
B.!7�	@�A�f+?�jKjK@�B(5K,EU�H*5Q,F��.F>.��1!~K5y?��^\��Vl�j�t-.j�[J,qj��j��I7$��?1R.B�+��.B$`2?g�vEo.�5KK5��%-K��6+SIR[��&.E49 B\B$���5K�G#!+"&5!"&=463!2+"&'+"'+"'&5>;2>76;2Y
��
�
��

M	

�.�x	�-�
	N�	�


�	�
�u
��
,
u
�?

L�W���

���#	�	*:J4'&+326+"'#+"&5463!2  $6& $&6$ <!T{�BH4�	�›�&�>UbUI-����uu�,�uu�ڎ������LlL�AX!��J��m����f\�$
6u�����uu�,�K������LlL���-[k{276/&'&#"&5463276?6'.#"!276/&'&#"&5463276?6'.#"  $6&  $&6]�h-%Lb`J%E5
,5R-����h
-%Lb`J%E5
,5R-���'����uu�,�uu��lL�������/hR

dMLcN����hR
dMLcN����1u�����uu�,��������LlL�@��� 	'	7	'7	�����`��`H� �����`�`H� �!`��������`H� � ���`�`�`H���`��'%		7'	7'7	' $&6$ ���X�`��(W�:,�:��X�`��(WL�������LlL�X�`(W��:�B����X�`���(X�������LlL��
��	$%/9ES[�#"&54632$"&4624&"26$4&#"2%#"&462$#"&4632#"32&! 24>  !#"&'.'#"$547.'!6$32�7&'77'&7�7N77N�'q�qq�q�qPOrq��E�st�����ts��st���}�||�}�������uԙ[W��Q���~,>	n������P/RU P酛���n	>,m�����'77'&77N77N6^Orq�qq�qq�q�t��棣棣�(~|��|on[��usј^�~���33������pc8{y%cq����33dqpf��	L 54 "2654"'&'"/&477&'.67>326?><����
x
�������,

(-'s�IVC��VH�r'-(

$0@!BHp9[�%&!@0$u
��
������]\��\]��-$)!IH��V
D��
VHI!)$-#3���6>N"&462."&/.2?2?64/67>&  #!"&5463!2�]�]]�3
$;
&|�v;$
(CS�3�1	=�rM=	�4�TC(G���z�w�@w��w�w���]]�]��($-;,54�0=	�sL	=�45,;�����@w��w�w������(2#"$&546327654&#"	&#"AZ�������\@�/#�%E1/#����#.1E$�!�[A�����懇�@�@\��!�#21E!��6!E13"�|!��	gL&5&'.#4&5!67&'&'5676&'6452>3.'5����A5R��V[t,G'Q4}-��&�<C!l n?D_@Փ>r!�
��G;��>��!g�1�����2sV&2:#;��d=�*'�5E2/..F�D֕71$1>2�F!���&12,��@K�
r��#"&5462>%.#"'&#"#"'>54#".'7654&&5473254&/>7326/632327?&$  $6 $&6$ �!&"2&^	u��_��x��^�h
;J݃HJǭ
q�E
Dm!
M�
G?̯'%o�8
9U�������(F(�ߎ������LlL��&!&!SEm|�[��n{�[<ɪ
"p� C
Di%
(K�HCέp�C
B
m8	
@Kނ
H�F(���������������LlL���"*6%&6$	7&$5%%6'$2"&4}���x����3��n��QH������:dΏ���Xe�8�����z��'	������l�i���=!��7�����S�o�?v�������M '&7>>7'7>''>76.'6'���El:F�gr
*�t6�K3UZ8�3P)3^I%=9	)<�}J���k+C-Wd��	&U���-��TE+]��Qr-�<Q#0
�C+M8	3':$
_Q=+If5[ˮ&&SG�ZoM�k���ܬc�#7&#"327#"'&$&546$;#"'654'632ե›��fKYYKf�¥y�ͩ���䆎�L��1���hv�v��ƚw�wk��n�]��*��]�nlx��D��L�w�����~?T8b��b9SA}����+5?F!3267!#"'#"4767%!2$324&#"6327.'!.#"��۔c�2�8�Ψ����-\���?���@hU0KeFjTl�y�E3��aVs�z�.b��؏��W80��]T��Sts�<�h�O��_u7bBt���SbF/�o��|V]SHކ�J�������34&#!"3!26#!!2#!"&=463!5!"&5463!2
��

@
�^B� `��`� B^^B@B^ �

�@
�@B^�@@�^B�B^^����>3!"&546)2+6'.'.67>76%&��F8$.39_��0DD�40DD0���+*M7{L *="#
U<-M93#�D�@U8v�k�_Y	�[�hD00DD0��0D�ce-JF1BD����N&)@
/1 d��y%F��#"'&'&'&'&763276?6#"/#"/&54?'&763276"&'&'&5#&763567632#"'&7632654'&#"32>54'&#"'.5463!2#!3>7632#"'&'&#"'&767632yq������oq>*432fb������a
$�B?
	>B
BB
AA�.-QP���PR+	42
%<ci���ђ:6&h�HGhkG@n�`��I���Ȍ5
!m��(|.mzy�PQ-.	
	je����	
�����q>@@?pp�gVZE|fb6887a
%RB?
=B
ABBAJvniQP\\PRh!cDS�`gΒ��23�geFGPHX�cCI��_ƍ��5"	
�n�*T.\PQip�
[*81
/
9@:��>t�%6#".'.>%6%&7>'.#*.'&676./&'.54>754'&#"%4>327676=
>���vwd"

�l����"3	/!,+	j2.|��%&
�(N&w���h>8X}x�c2"W<4<��,Z~�fd�aA�`FBIT;hmA<7QC1>[u])		u1�V(�k1S)
-�	0�B2*�%M;W(0S�[T�]I)	A 5%R7<vlR12I]O"��V/,b-8�/_��#3CGk2#!"&546;546;2!546;2%;2654&+";2654&+"!32++"&=#"&=46;546;24LL4��4LL4�^B@B^�^B@B^�@@�@@�����@��@L4�4LL44L`B^^B``B^^B``�� �� ��@@��@���#3W#!"&=463!2!!%4&+";26%4&+";26%#!"&546;546;2!546;232���@�����@@@@�L4��4LL4�^B@B^�^B@B^�4L�@@��� �� ��N�4LL44L`B^^B``B^^B`L��#'7Gk%"/"/&4?'&4?62762!!%4&+";26%4&+";26%#!"&546;546;2!546;232W.	
��
	.		��		.	
��
	.		��	� ����@@@@�L4��4LL4�^B@B^�^B@B^�4L�.		��		.	
��
	.		��		.	
��
��� �� ��N�4LL44L`B^^B``B^^B`L��(8\	"'&4?6262!!%4&+";26%4&+";26%#!"&546;546;2!546;232�

��		.	
��
	.	�`����@@@@�L4��4LL4�^B@B^�^B@B^�4L<�		 
	.		��		.	�:� �� ��N�4LL44L`B^^B``B^^B`L�2632632#!"&5463�&&&&��&&&���&���&��&&�&�#27+"&5  %264&#"26546��>&�&T�,��X�������q&&�1��X��,�LΒw�%��%;#!"&5463!546;2!2!+"&52#!"/&4?63!5!�

�(��&&@&�&(��&�&@&&��(�

�(�

�&&@&&@��&&�&�&�

�����#''%#"'&54676%6%%�������
�hh �@�` ���!�� ���!� ��
��
��
�
������
�#52#"&5476!2#"&5476!2#"'&546
� 
��
� 
���
�
�@�
�
�@�
��
�@

�
� 84&"2$4&"2$4&"2#"'&'&7>7.54$ �KjKKj�KjKKj�KjKKj��d�ne���4"%!������KjKKjKKjKKjKKjKKjK.���٫�8
!%00C'Z���'���.W"&462"&462"&462 6?32$6&#"'#"&'5&6&>7>7&54>$ �KjKKj�KjKKj�KjKKj�h��я�W.�{+9E=�c��Q�d�FK��1A
0)����LlL��jKKjKKjKKjKKjKKjK���p�J2`[Q?l&�����٫�C58.H(Y���ee���	�

			���Y'����w��(�����O��'��R���@$#"&#"'>7676327676#"�
�����b,XHUmM�.�U_t,7A3ge
z9@xS���a�Q�BLb�(�	����V���U�����
!!!�=�����=���w)��������AU!!77'7'#'#274.#"#32!5'.>537#"76=4>5'.465!��KkkK_5 5�� �#BH1��`L

I���&�v6��SF���!Sr99rS!``� /7K%s}H���XV
��P��V	e��		V�d/9Q[ $547.546326%>>32"&5%632264&#"64'&""&'&"2>&2654&#";2���P���3>tSU<�)tqH+>XX|W��h,�:USt��W|XX>=X*
)���)
+�^X^�|WX=>X�:_.2������//a:Ru?�
	
Q%-W|XW>J�(	�=u��>XX|WX�`

*((*


+2		2�X>=XW|E��03>$32!>7'&'&7!6./EU����noh��i����I\�������0<{ >ORD��ƚ�~�˕V�ƻ��o�R C3��7J6I`��Tb<�^M~M8O����	�	
5!#!"&!5!!52!5463	^B�@B^���`B^�^B `��B^^"�����^B��B^��0;%'#".54>327&$#"32$	!"$&6$3 ##320�J�����U��n��L�n��ʡ���~~�&��q�@�t�K�����L��}�'`� -
-�ox����nǑUyl}��~������~�F����ڎ�LlL��t�`(88( ��	7!'	!���\W�������\���d;����tZ�`_��O��;���}54+";2%54+";2!4&"!4;234;2354;2354>3&546263232632#"&#"26354;2354;2354;2�````��p�p��`�`�`� !,! -&M<FI(2�`�`�`�����@PppP���pppppp�#  #
�
�pppp��p	�j#"'&=!;5463!2#!"&=#".'.#!#"&463232>7>;>32#"&'#"!546���	��%. `@��` :,.',-���Xj��jX�h-,'.,: kb>PppP>bk .%Z �&�
�:k%$> $`��`6&L')59I"Tl�ԖlT"I95)'L&69Gp�pG9$ >$%k:��!+32&#!332 $&6$ ~O8��8���O�����������LlL�>pN
�����
i������LlL����	'':Ma4&'#"'.7654.#""'&#"3!267#!"&54676$32#"'.76'&>$#"'.7654'&676mD5)
z�{��6lP,@Kij��jOo�Ɏ���ȕ>>��[t��a)GG4?a�)
ll
>�;_-/
9GH{�z�yN@,K�ԕoN��繁������y��!
?hh>$
�D��"
>��â?$��	n"&5462'#".54>22654.'&'.54>32#"#*.5./"�~��~�s�!��m�{b6#	-SjR,l'(s�-6^]It�g))[��zxȁZ&+6,4$.X%%Dc*
&D~WL}]I0"

YYZ��vJ@N*CVTR3/A3$#/;'"/fR-,&2-"
7Zr�^N��a94Rji3.I+

&6W6>N%&60;96@7F6I3���+4&#!"3!26%4&#!"3!26 $$ ��������^����a�a`@��@����^����a�a�����'7  $ >. %"&546;2#!"&546;2#/�a����^�����(�����������������^����a�a����(������N@��@�����4&#!"3!26 $$ @��@����^����a�a`@����^����a�a�����'  $ >. 7"&5463!2#/�a����^�����(��������n@����^����a�a����(������N@���%=%#!"'&7!>3!26=!26=!2%"&54&""&546 �#��#]V�TV$KjK�KjK$��&4&�Ԗ&4&�>��9G��!�5KK5��5KK5�!��&&j��j�&&����#/;Im2+#!"&'#"&463>'.3%4&"26%4&"26%6.326#>;463!232#.+#!"&5#"�5KK5sH.�.Hs5KK5e# )4# %�&4&&4&�&4&&4&` #4) #%�~]�e�Z�&�&�Z�e�]E-�&��&�-EKjK�j.<<.�KjK��)�#)�`"@�&&�`&&�&&�`&&�)#�`)"�d�Xo&&oX�G�,8&&8!����O##!!2#!+"'&7#+"'&7!"'&?63!!"'&?63!6;236;2!2�@�@�8��@7

8��Q�
	N�Q�
	N��
	8G@��

8GQ�
	N�Q�
	N7
	�������8��8��H��H��k��%		".>2I�������2�0�]@��]��@o�����o@@o�����o㔕����a�22���]����]�p�^���|11|�9�9�|11|�(��%7'7'	'	7T���� d���lt��l)q��n�������luul�������)1$4&"24&"2 &6 +"&5476;2 &6 LhLLh�LLhLLhL����>�
�� �&
  �&�`����>�hLLhLLhLLhL�����>����&�&�����>��G��
	.7)1!62	1!62h��e�������2�20e���2�2>�	v
+4�	[��d����+
���d� �135#5&'72!5!#"&'"'#"$547&54$ ���Eh���`X����(����cY���z�:L:�z���Yc��������\$_K`Pa}��f��iXXiޝf���a���	���(+.>#5#5!5!5!54&+'#"3!267!7!#!"&5463!2����U�`��`' ����� �����j��j�V>�(>VV>�>Vq����������������(^����(>VV>�>VV�=&'&'&'&76'&'&.' #.�h8��"$Y
''>eX5,	,Pts�K�25M�RLqS;:.K'�5�R

Ch���h�����R�t(+e�^TT���u B"$:2�~<�����2�Hp����wTT�� V�/7GWg. %&32?673327>/.'676$4&"2 $&6$   $6& $&6$ d-����-�m	
	,6*6,	
	m���KjKKj�o������oo���K����zz�8�zz�Ȏ������LlL�U4>>4-.��YG0
)�xx�)
0GYޞ.�jKKjKq���oo��oo�lz�����zz�8�0������LlL��D��/7H#"'.7'654&#"'67'.6?>%"&46227#".547|D,=),9#�7��[͑�f�x���!X: �D�$+�s)�hh�i��jZ������t�<��F/��*8C,�q؜�e���\�r,W�BX���/C2��h�hh���=�t������Xm�����>NZ+"&=46;2+"&=4>7>54&#"#"/.7632  >. $$ p��=+& �35,W48'3	l
z����ff���ff�����^����a�aP���2P: D#;$#
$*;?R
��Cf���ff�����^����a�a��'�Y	>O`"&5462&'.'.76.5632.'#&'.'&6?65��\\�[�<C��z�C
25�U#
.�ZK ��m+[$/#>(	|�	r���[A@[[@A�#2#�
����7�*
<Y���$
+}"(��
�q�87] F 	_��1)
��	�	#1Ke34&+326+"&=!#!"&763!2#!"&5463!2#>?4.'3#>?4.'3#>?4.'3��Xe`64[l�����7
��
,	L;�����=+3&98&+)>�>+3&98&+)>�=+3&88&+)>	�Wj�|r�>Q$��~���d$kaw+-wi[[\�;/xgY$kaw+-wi[[\�;/xgY$kaw+-wi[[\�;/xgY���J\m�4.'.'&#"#"'.'&47>7632327>7>54&'&#"327>"&47654'&462"'&476'&462"'&47>&'&462i$		$^"

%%

"^$		$W "@9O?1&&18?t@" W�&%%&4KK�6pp&4���6ZaaZ&4mttm�^x	-���-	x^=/U7Ck���kz'[$=�&5%54'4&K�K�4r<r4&��X��4[��[4&m����m��'/7?GOW_gow����"264$"264"264"264$"264"264$"264"264"&462"&462"&462"&462"&462"&462"&462"&462"&462"&462"&462"&462�^^�^��^^�^^�^^�^��^^�^��^^�^���^^�^��^^�^^�^^�^� p�pp�pp�pp��pp�pp�pp�pp��pp�pp�pp�pp��pp�pp�pp�pp��pp�pp�pp�pp��pp�pp�pp�pp�`^�^^�^^�^^�^^�^^��^^�^^�^^�^^�^^�^^�^^�^^�^^�^^���pp�pp�pp�p��pp�pp�pp�p��pp�p���pp�p��pp�p���pp�p��pp�pp�pp�p��pp�pp�pp�p	��LTi{�"&4626"&462$"&462#"&4632654>7>54 "&54>2"&462%"&54&#""&546 %#"&'&'.7>#"'&'.7>�&4&&4�&4&&4SZ��&4&&4�4$#&�&&j�3$"('$������&4&[���՛[��&4&&4F&4&�]\�&4&�$��
	!D�4�%	,\�4�4&&4&�4&&4&-�Z�4&&4&;cX/)#&>B)��&4&�j9aU0'.4a7����&&u՛[[���4&&4&@&&]��]&&��Ώ0
�u4��0
)�4���#g�&'.#"32676%4/&#"326'&#"2632#2+&'%#"'&6?676676632%#"'&6767#"&'&6767#"'.7>327"#"&'&6763"'.7>;7632;>%5K$
"0%>s$
"0%>;;>%5K�VL#>H30
\�($$(�\���(�є�yO2F/{�(?0(TK.5sg$��є�y#-F/{�$70(TK.5sg$L#>H30
\�($$(�\#�(@5"'K58!'"5�8!'"55"'K#dS$K		K$Sdx#@1
w�d>N;ET0((?
-
2K|��1
w�����d#N;ET0$(?
-
2K$#dS$K		K$Sdx�DN\2654& 265462"2654 #"32654>7>54."/&47&'?62 &4&���&4&���h�՛[&4&r$'("$3�j&&��&#$4[����"�@��GB�[�
"�&&��Β&&]���[��u&&����7a4.'0Ua9j�&4&�)B>&#)/Xc;u՛����"�"
�G�i[����Xh#"&54676324&'&#"'>54#"32#"54>54'.#"32>7>767632326#!"&5463!2b
)
:4FD�N

[�1�,^�J��K-*E#9gWR�Yvm0O	��w�@w��w�w��C2�2c@X�&!�9{M�A���_��"S4b// DR"Xlj�PY<	�@w��w�w��%���e4.#"32>7676#'.#"#"&54>3232>754&*#"&54>763 >32�
''il$E/
@�P@��
^��`��'W6&�!.. ! -P5+


�E{�n46vLe�Vz�:���,SN/
M5M[��
	]$�[��^��5�iC'2H&!(?]v`*	��l�	��b��$9>
���=R�2
#"&5467%!"&7>3-.7>;%.7>322326/.76/.'&6766/&/&#"&676	&676&6766/&672? �=1�(H/ ��	'96&�@)9<'���)29%
�&06#���#��$� J� �07j)�5@�"*3%�"!M
��%#K�"%N�e8)'8_�(9�.<�c +8 8(%6 <)'4@@)#-<^
?%$-`%.
}Q!&�}%&N�-l���IJ�;6>/�=*�%8!Q ���#P"�\Q#N&�a��)<9�bR]mp%"'.'&54>76%&54763263 #"/7#"'#"&/%$%322654&#"%'OV�9
�nt
|\d
ϓ[��nt
|@�D:)��	
;9�8'+|�j�," �41����CH^�nVz(�~R	�9�\'	�r�

@����L��@�
	@�w4�6�HI(+�C
,��55,��
f[op@�\j�;(zV~����i/5O#"'&54>32&#" 654'67'"'>54''&'"'6767&546767>7���蒓��`V BM���R� B9)̟�!SH-77I�Xm�SM�H*�k#".o;^J q�ן���ד��>@�����YM
$bK���d ��ү[E"����;���Kx%^�6;%T,U:i�m=Mk���).DT4'"&5463267&#" 6;64'.'4'>732676%#!"&5463!2),�蛜s5-<A���4ϲ
2W9
�&P:\�3)SEPJ��D4:3NI�w�@w��w�w��NE	2@u��us�+,�����/?x�sa�tmP�'�)fHVEA(%dA4w&4J5*�@w��w�w�����O[4'.'&54>54&#"#"'654'.#"#"&#"3263232>3232>76 $$ �Cf'/'%($�U�L
(
#'/'@��3#@,G)+H+@#3
����^����a�a�X@_O#NW�#O_�.*	##(��^����a�a����q�[632632#"&#"#".'&#"#".'&54767>7654.54632327&547>P��9	B6?K?%�O4�T% >6>Z64Y=6>%S�4N�$?L?4B	@���{:y/�$ ,'R�!F!8%
#)(()#%:!F �Q'+%�0z:�z���O_4'.'&54>54&#"#"'654'.#"#"&#"3263232>3232>76#!"&5463!2Cf'.'%($�V�M
)
#'.'@��
3
#A,G)+H+A#
4
��w�@w��w�w��XA?4N$NW�&M&L�/*
##	+�@w��w�w����	O$>?>762'&#"./454327327>7>	EpB5
3FAP/h����\�/NG�S�L�	� ���R�P*��m�95F84f&3Ga4B|wB.\FI*/�.?&,��5~K %
&��Y."7n<	"-I.�M`{�ARwJ!�FX^dj''''"'7&'7&'7&'7&547'67'67'67'63277774$#"32$			*��'ֱ,?�g=OO&L&NJBg�;1��'����'ֱ.=�gCIM
$'&&NJBg�=.��%�����w؝\\��w�
�I�o�o��<�<���-NIDg�=/��%����(ײ+A�hEHO*"#*OICh�=/��'����(ֲ/=�h>ON.��]��xwڝ]��������7��e��[���@�����)6!!"3#"&546%3567654'3!67!4&'7S��gn�y]K-�����#75LSl>�9���V��%�cPe}&H�n��_�HȌ����=UoLQ1!��4564���7U�C"�
�!-9[nx��"&46254&"326754&"326754&"26754&"26#".547632632626326'4#"#"54732764&"264.#"327632>#"'"'#"'#"&5#"'67&'327&'&54>3267>7>7>32632632T"8""8�)<())�(<)))�)<))<)�)<))<)T�د{ՐRh�x=8 78 n 81
p��H_6�S��oc
�F@b@?d?uK�bM�70[f5Y$35KUC<:��[;+8 n 87 8/8Zlv]64qE 'YK�0-AlB;
W��#;WS9
&�(#-7Z�://:/�Tr++r,,r++r,,r++r,,r++r,,ʠ�g��xXV�ע��e9222222^�K�Vv���F0�2OO23OO��`�lF;�mhj84D�ro��B@�r+@222222C0DP`.�r8h9��~T4.&o�@9��1P���%14'!3#"&46327&#"326%35#5##33 $$ ����}Pc��c]<hl���ࠥ�Ymmnnnn���^����a�aw!�LY�Ə;ed����wnnnnnv�^����a�a��%�'#"$#"#.5462632327>321��I��U�Π?L���L?��cc�4MX�&��04;0��XpD[��[DpD,)&&�Q	9V\�26&".'&'&6?.#"#26327677>'32>&3#'&+"?626&"#!'.'!"&5463!>;26;2!2�P  P 	
92#.}S�P9:�:%L\B�� )spN/9oJ5 
!+D�`]�Bg�Y9�+�,�9%
Pk4P  P &�NnF!_7*}B<�{o0��&&�B;*<@$ucRRc�#@16#37c&�@@@
J"@*4�^`E�D�B�����o/8927
*@O�LC�!T!32�3X$�BJ@@@��&AS
0C59"'D/&�&D488$5A&�%O#!"&547>7>2$7>/.".'&'&2>^B�@B^>FFz�n_0P:P2\n�zFF>��R&�p^1P:P1^��&R
P2NMJMQ0Rr�.B^^B�	7:5]yPH!%%"FPy]5:7	���=4�QH!%%!H�t4=�<"-/ ?�1Pp+".'.'.?>;2>7$76&'&%.+"3!26#!"&54767>;2�'
+�~'*OJ%%JN,&x�'%^�M,EE,M7�ZE[��P*FF*P��:5
�
�^B�@B^){�$.MK%%KM.$+��X)o3"�a  22!]�4	I�>"">�,�&�S8J�B##B��12�`
��`B^^B�8&ra#11#$��R&��"&.2v%/%''%/%7%7'%7'/#&5'&&?&'&?&'&7%27674?6J�"�����0�<=���_gNU�?D��f���u�Y����G�b���7=^H^�`	�=v~yT������3����G���D��P�O	4F��ѭ����q������i_w\ހ�!1u�S���%V_-d�
���1=U{J8n~�r����'U4.#".'"3!264&"26+#!"&5463!232+32+32�0P373/./373P0T=@=T��֙�֙|`^B�@B^^B�B^`````*9deG-!

!-Ged9Iaa�l��lk���O��B^^B�B^^B�������	+Yi"&54622#!"&54>;2>+32+32+#!"&5463!2324&#!"3!26�֙�֙0.I/ OB��BO	-Q52-)&)-2�
``

``

`^B�@B^^B�B^`
�
�@

�
|k��kl����"=IYL)CggC0[jM4				
�
�
�
�
�B^^B�B^^B�
�@�

�@
���!1AQu4.#".'"3!24&"254&#!"3!2654&#!"3!2654&#!"3!26#!54&+"!54&+"!"&5463!2)P90,***,09P)J66S�����"��@��8��@^B��@�@��B^^B�B^U�kc9		9ck�U?�������@@88@@N�@B^````^B�B^^���!1AQu�#!"&4>32>72"&462#!"&=463!25#!"&=463!25#!"&=463!24&#!"3!546;2!546;2!26#!"&5463!2J6�6J)P90,***,09P)������"��@��8��@�
�@

`@@`
�^B�@B^^B�B^ՀUU�kc9		9c�������`@@�88�@@�2�

�@
````�@B^^B�B^^�(%.'"&' $&  #"$&6$ ��wC�ιCw�jJ~J�����>��������LlL�ś�JSSJ͛����>����6������LlL���$,  $&6654&$ 3 72&&  �lL������m�z�����z�B�l������>�������KlL�G���zz���G���>�����'7#!"&54>7&54>2  62654' '3�/U]B,ȍ����,B]U/OQ��н�Q������>�+X}��������}X�0b�Ӄ��ۚ�Ӆb0}�h��QQ��h�����>��f����f��#=#!"&4>3272"&462!3!26#!"&5463!;26=!2J6�6J)Q8P�P8Q)��������
�
�^B�@B^^B`�`B^V�VV�ld9KK9d��������`��
�@B^^B�B^``^���+;K[eu4.#"'"3!264&"254&#!"3!2654&#!"3!26%54&+";2654&#!"3!26!54&#!"!#!"&5463!2�"D/@�@/D"?,�,?�p�pp�p�@�����@����@����@�^B�@B^^B�B^D6]W2@@2W]67MM��pp�p��@@@@@@@@n`�@B^^B�B^^���+;K[eu#!"&54>3272"&462#!"&=463!2%#!"&=463!2+"&=46;25#!"&=463!2!3!26#!"&5463!2�?,�V,?"D/@�@/D"�p�pp�p�@�����@����@���
�
�^B�@B^^B�B^D7MM76]W2@@2W]֠pp�p��@@�@@@@�@@��`��
�@B^^B�B^^��A#"327.#"'63263#".'#"$&546$32326�������J9"65I).!1i���CC�u
+I�\Gw\B!al���݇���y�ǙV��/]:=B�>9�����+<F+a[le���Pn[A&JR7t�)��+�tH�������kFIK�e	� .��#"'&'>32%#!"&5463!2#"&54>54'&#"#"54654'.#"#"'.54>54'&'&543232654&432#"&54>764&'&'.54632� ?c��'p& ?b1w{2V	?#��&#9&�CY'&.&#+B

: &65&*2w�1GF1)2<)<'

(
BH=ӊ:NT :O	�)4:i F~b`e!}�U3i?fR����UX|'&'&I�c&Q
	*2U.L6*/
L:90%>..>%b>++�z7ymlw45)0	33J@0!!TFL����� P]=GS�-��kwm	!����*�(%6&692? $&6$ ��	' ����al�@l�������LlL���,&��EC
���h�$�������LlL���
/37;%"&546734&'4&" 67 54746 #5#5#5�p�pF:�:F�D<p�p<D�
����������
���������PppP<d��ud<M�-PppP�-�M����������Dž����9���������
/37;%"&546734&'4&" 67 54746 #5#5#5�p�pF:�:F�D<p�p<D�
����������
���������PppP<d��ud<M�-PppP�-�M����������Dž����9���������
/37;%"&546734&'4&" 67 54746 #5#5#5�p�pF:�:F�D<p�p<D�
����������
���������PppP<d��ud<M�-PppP�-�M����������Dž����9���������
/37;%"&5467534&'4&" 67 54746 #5#5#5�p�pF:�:F�D<p�p<D�
����������
���������PppP<d��d<M�-PppP�-�M����������Dž����9���������	+/37%"&54624&'4&" 67 54746 #5#5#5�p�pp�p�D<p�p<D�
����������
���������PppPOqqOM�-PppP�-�M����������Dž����9����������&.6>FNV^fnv~����"/&4?.7&#"!4>3267622"&4"&46262"&42"&4462"$2"&42"&4"&46262"&4"&46262"&42"&4$2"&42"&42"&4�

��

R

,H8Jfj��Q��hj�G^�R,

!4&&4&Z4&&4&�4&&4&��4&&4&&4&&44&&4&��4&&4&Z4&&4&�4&&4&��4&&4&�4&&4&��4&&4&&4&&4&Z4&&4&Z4&&4&

��

R

,[�cG�j�h��QRJ'A,

��&4&&4Z&4&&4Z&4&&4Z&4&&444&&4&�&4&&4Z&4&&4Z&4&&4Z&4&&4�&4&&4Z&4&&4Z&4&&4&&4&&4Z&4&&4Z&4&&4�%-5=EM}���������+"&=#!"'+"&=&="&4626"&462&"&462"&462&"&462&"&462#!"&=46;4632676/&?.7&#"!2"&462&"&462&"&462"&462&"&462&"&462"&462&"&462"&462��@?A�A?
@
�@R.�..R�@`�jlL.h)*��*$	%35K���..�..�.����u�vn�u���....��@@�j�N *��*.t2#K5���..R..R.��
@Hq '&'&54 &7676767654$'.766$76"&462&'&'&7>54.'.7>76�����������ȵ|�_ğ��yv���/ۃ�⃺����k]
:Bu�q��
CA
_k�ނ���XVo�bZZb�nW��|V	0 	Q2��-�
l��}���O		/	:�1���z	
q��%������z�G
4(

6�Ro�aą\�<

)4	J�}�������%!!#!"&5463!2�^B�@B^^B�B^�`�@B^^B�B^^���%#!"&=463!2^B�@B^^B�B^�B^^B�B^^�&))!32#!#!"&5463!463!2��`B^^B��^B�@B^^B`^B�B^�^B�@B^��B^^B�B^`B^^���#3%764/764/&"'&"2?2#!"&5463!2��

��

�

��

�

��

�

��
s^B�@B^^B�B^ג

��

�

��

�

��

�

��
�@B^^B�B^^���#'7"/"/&4?'&4?62762!!%#!"&5463!2�

��

�

��

�

��

�

��
�
�^B�@B^^B�B^��

��

�

��

�

��

�

��
��`�@B^^B�B^^�	! $&6$ .2�r��`�������LlL�f4��������LlL���#.C��&>"'&4762"/&4?62'"'&4762%'.>6.'.>6'>/>76&'&.'&7&'">?4'.677>7.>37654'&'67>776 $&6$ (4�Z�##
&##
&y�"�6&.JM@&� "(XE*$+8
jT<l$3-V<
2'.


-1
%#e"!Z�
+*)H	 8
(j

	#*
-ƷVv/kh?'��������MlM�$($�R#

&
"
#'#vZ@+&MbV$
�
G7
--)

R2T�
313dJ6@8lr2_�5m/."�G:=	)%5f0gt*2)?;CB66&, �	`48]USy������LlL���G6?>?3#'.'&!3!2>?3.'#!57>7'./5!27#'.#!"g�%%D-!gg<6W��WZe#1=/2*]Y3��-,����C1/Dx���] VF��I�q-H�����D2��NK'>*�%�R=f
07���=.
fD�]\|yu���,0>Seu#2#"'&5<>323#3#&'#334'."#"+236'&54.#"5#37326#!"&5463!2�		<	��zz�j��k-L+� )[$�8=".un/2 �^B�@B^^B�B^�5cy	
�
��(�ݔI�(8��?C�(3�>�� #"��($=�@B^^B�B^^0�K�S�&'.'&'./674&$#">&>?>'76'# "&#./.'7676767>76$w
.~ku�BR�]� T%z+",�|�ޟ���j<���)(!(	~ˣzF8"{���%%#5����)��}''�x��JF��0"H[$%��EJ#%
.Gk29(B13"?�@S)�5" �#9����dm�W"��;L�65R�A0@T.���$�}i`:f3A%%
BM<$q�:)BD	aa%`�]A&c|	�M��s!
Z
2}i[F&���**
< ��ʣsc"J<&Ns�F%���0@Wm6&'.6$.7>7$76".4>2.,&>6'"'&7>=GV:�e#:$?+%

q4����g
&3h�T`Zt�Q��м�QQ��м�pA������P1L������K!:<��}҈`d��l��b�,�9'


%%($!
���a3���)W)x
�������
о�QQ��о�QQ���cQ����ǡ-�җe)U�s2����XD\���ϼ�Yd����/?O_o���#"=#"=4;543#"=#"=4;543#"=#"=4;543#"=#"=4;543#"=#"=4;543%#!"&5463!2++532325++532325++532325++532325++53232�p00pp00pp00pp00pp00�8(��(88(@(80pp00pp00pp00pp00pp0� � � � � ��@(88(�(88� �� �� �� �� �/�Q�/&'%&/"&=.6?&?&'&6?'.>-#".6?'.>'&6'.>54627>%>76#"'%
%6��

2�7
2G
f���!)p&4&p)!��f
G2
7�2

��	*6���	"��
4�7
2G
f�!)p&4&p)!�f
G2
7�2

��"	���6*	�!k
3

j�&3
%,����*��&&ր*�9���%
3&�j

3
k!./!>��>$,*!k
3.j�&3
%�Ԝ9�*��&&ր*�ǜ,%
3&�j

3
k!*,$>��>!/.�&6.'&$	&76$76$�P��utۥiP��u��G��xy
��Զ�[xy
�-���_v١eN��uv١e	��=��u�ʦ�����[t7��8�X�
&6##'7-'%'&$  $6 $&6$ ��3��1�N��E0�����g��R�=|�����||�">"��������LlL����^��v!1f2i��Ђwg�fZQ�Q^>"�||�����||�w������LlL��&�Z�Xblw��������.'&>'&'&".'.'&&'&'&7>767>67>7626&'&>&'&>'.7>.676'&'&'&'.67.>7>6&'&676&'&676.676&'&>&'&676'.>6/4-LJg-$	6)j2%+QF)�b3FSP21DK2�AW")")�$??8A&A�E5lZm��=g�G2Sw*&>$5jD ���GH�yX/4F �r	1
	1�"�"!�l=6>��	6
,5./��'e



.*�|�Ed!
u&�&%&��	&��5d	
���))66@�C&8B@q��L?P^7	G-hI[q��:<�rS	U~97A_�IR`gp1	1	�;"("j?>"�T�6
,6 
&/`���LwQ'�	
��A	^	�	�	"�		$&	_	��	y		�	*�	<Copyright Dave Gandy 2016. All rights reserved.Copyright Dave Gandy 2016. All rights reserved.FontAwesomeFontAwesomeRegularRegularFONTLAB:OTFEXPORTFONTLAB:OTFEXPORTFontAwesomeFontAwesomeVersion 4.7.0 2016Version 4.7.0 2016FontAwesomeFontAwesomePlease refer to the Copyright section for the font trademark attribution notices.Please refer to the Copyright section for the font trademark attribution notices.Fort AwesomeFort AwesomeDave GandyDave Gandyhttp://fontawesome.iohttp://fontawesome.iohttp://fontawesome.io/license/http://fontawesome.io/license/����������	

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab�
cdefghijklmnopqrstuvwxyz{|}~��������������������������������������������������������������������������������������������������������������������������������"	

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRS�TUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~��������������������������������������������������������������������������������������������������������������������������������	

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~���������������������������������������������������glassmusicsearchenvelopeheartstar
star_emptyuserfilmth_largethth_listokremovezoom_inzoom_outoffsignalcogtrashhomefile_alttimeroaddownload_altdownloaduploadinboxplay_circlerepeatrefreshlist_altlockflag
headphones
volume_offvolume_down	volume_upqrcodebarcodetagtagsbookbookmarkprintcamerafontbolditalictext_height
text_width
align_leftalign_centeralign_right
align_justifylistindent_leftindent_rightfacetime_videopicturepencil
map_markeradjusttinteditsharecheckmove
step_backward
fast_backwardbackwardplaypausestopforwardfast_forwardstep_forwardejectchevron_left
chevron_right	plus_sign
minus_signremove_signok_sign
question_sign	info_sign
screenshot
remove_circle	ok_circle
ban_circle
arrow_leftarrow_rightarrow_up
arrow_down	share_altresize_fullresize_smallexclamation_signgiftleaffireeye_open	eye_closewarning_signplanecalendarrandomcommentmagnet
chevron_upchevron_downretweet
shopping_cartfolder_closefolder_openresize_verticalresize_horizontal	bar_charttwitter_sign
facebook_signcamera_retrokeycogscomments
thumbs_up_altthumbs_down_alt	star_halfheart_emptysignout
linkedin_signpushpin
external_linksignintrophygithub_sign
upload_altlemonphonecheck_emptybookmark_empty
phone_signtwitterfacebookgithubunlockcredit_cardrsshddbullhornbellcertificate
hand_right	hand_lefthand_up	hand_downcircle_arrow_leftcircle_arrow_rightcircle_arrow_upcircle_arrow_downglobewrenchtasksfilter	briefcase
fullscreengrouplinkcloudbeakercutcopy
paper_clipsave
sign_blankreorderulol
strikethrough	underlinetablemagictruck	pinterestpinterest_signgoogle_plus_signgoogle_plusmoney
caret_downcaret_up
caret_leftcaret_rightcolumnssort	sort_downsort_upenvelope_altlinkedinundolegal	dashboardcomment_altcomments_altboltsitemapumbrellapaste
light_bulbexchangecloud_downloadcloud_uploaduser_mdstethoscopesuitcasebell_altcoffeefood
file_text_altbuildinghospital	ambulancemedkitfighter_jetbeerh_signf0fedouble_angle_leftdouble_angle_rightdouble_angle_updouble_angle_down
angle_leftangle_rightangle_up
angle_downdesktoplaptoptabletmobile_phonecircle_blank
quote_leftquote_rightspinnercirclereply
github_altfolder_close_altfolder_open_alt
expand_altcollapse_altsmilefrownmehgamepadkeyboardflag_altflag_checkeredterminalcode	reply_allstar_half_emptylocation_arrowcrop	code_forkunlink_279exclamationsuperscript	subscript_283puzzle_piece
microphonemicrophone_offshieldcalendar_emptyfire_extinguisherrocketmaxcdnchevron_sign_leftchevron_sign_rightchevron_sign_upchevron_sign_downhtml5css3anchor
unlock_altbullseyeellipsis_horizontalellipsis_vertical_303	play_signticketminus_sign_altcheck_minuslevel_up
level_down
check_sign	edit_sign_312
share_signcompasscollapsecollapse_top_317eurgbpusdinrjpyrubkrwbtcfile	file_textsort_by_alphabet_329sort_by_attributessort_by_attributes_alt
sort_by_ordersort_by_order_alt_334_335youtube_signyoutubexing	xing_signyoutube_playdropbox
stackexchange	instagramflickradnf171bitbucket_signtumblrtumblr_signlong_arrow_down
long_arrow_uplong_arrow_leftlong_arrow_rightwindowsandroidlinuxdribbleskype
foursquaretrellofemalemalegittipsun_366archivebugvkweiborenren_372stack_exchange_374arrow_circle_alt_left_376dot_circle_alt_378vimeo_square_380
plus_square_o_382_383_384_385_386_387_388_389uniF1A0f1a1_392_393f1a4_395_396_397_398_399_400f1ab_402_403_404uniF1B1_406_407_408_409_410_411_412_413_414_415_416_417_418_419uniF1C0uniF1C1_422_423_424_425_426_427_428_429_430_431_432_433_434uniF1D0uniF1D1uniF1D2_438_439uniF1D5uniF1D6uniF1D7_443_444_445_446_447_448_449uniF1E0_451_452_453_454_455_456_457_458_459_460_461_462_463_464uniF1F0_466_467f1f3_469_470_471_472_473_474_475_476f1fc_478_479_480_481_482_483_484_485_486_487_488_489_490_491_492_493_494f210_496f212_498_499_500_501_502_503_504_505_506_507_508_509venus_511_512_513_514_515_516_517_518_519_520_521_522_523_524_525_526_527_528_529_530_531_532_533_534_535_536_537_538_539_540_541_542_543_544_545_546_547_548_549_550_551_552_553_554_555_556_557_558_559_560_561_562_563_564_565_566_567_568_569f260f261_572f263_574_575_576_577_578_579_580_581_582_583_584_585_586_587_588_589_590_591_592_593_594_595_596_597_598f27euniF280uniF281_602_603_604uniF285uniF286_607_608_609_610_611_612_613_614_615_616_617_618_619_620_621_622_623_624_625_626_627_628_629uniF2A0uniF2A1uniF2A2uniF2A3uniF2A4uniF2A5uniF2A6uniF2A7uniF2A8uniF2A9uniF2AAuniF2ABuniF2ACuniF2ADuniF2AEuniF2B0uniF2B1uniF2B2uniF2B3uniF2B4uniF2B5uniF2B6uniF2B7uniF2B8uniF2B9uniF2BAuniF2BBuniF2BCuniF2BDuniF2BEuniF2C0uniF2C1uniF2C2uniF2C3uniF2C4uniF2C5uniF2C6uniF2C7uniF2C8uniF2C9uniF2CAuniF2CBuniF2CCuniF2CDuniF2CEuniF2D0uniF2D1uniF2D2uniF2D3uniF2D4uniF2D5uniF2D6uniF2D7uniF2D8uniF2D9uniF2DAuniF2DBuniF2DCuniF2DDuniF2DEuniF2E0uniF2E1uniF2E2uniF2E3uniF2E4uniF2E5uniF2E6uniF2E7_698uniF2E9uniF2EAuniF2EBuniF2ECuniF2EDuniF2EE����=���O<0�1h�libs/better-framework/assets/fonts/fontawesome-webfont.woff2000064400000226550151214002620020351 0ustar00wOF2-h
��-�?FFTM `�r
��(��X6$�p� ��u[R	rGa���*�
�'�=�:�&��=r�*
��]t�E�n�������1F��@���|��f�m�`�$ؑ�@d[BQ$([U<+(��@P�5�`���>�P;�(��1��l�hԨ��)��Yy��Ji�����|%ہ�^�G��3�n���ڕ�
�͐D��p\Yr �L�P���t�)����6R�^"SL~�YR�CXR	�4���F�y\[��7n��|s໌q�M��%K�.ۺ,����L�t�'���M,c��+b��ׇ�O�s�^�$���z.�mŠ�h&gb���v���'�6�:����s�m�b�1بm0"ǂ��*V����c�$,0ATPT�1��<�;���`�'�H?�sΩ:�ND����I�$�T�[��b4�����,�μ�」bl6��IL�i}ی&�4�m,'���#�ץ�Rw�bu��,K����v��m_-���\H����HH������?���m�9P���)9�J��$ƽ����8������~�;�r�n�=$��Nddn!'����;��8��'�N��!-Jʶ�.����X�=,��"`:��		 {�����K!'��-FH��	�#$~�Z_����N5VU8Fȯ��%P�ݫ���Cp$Q�����r��ʽ��k�k��3ٷ�:R%��2{�ީ��h%�)8����
ILK�6v�#��,;Ц6��N�2�hv�����OO��t#��xT��Bf���q^#����?{�5b�I��%-WZ��b�A�^�1��n5���צNQ�Y'�������S��!t" `b3�%���35��fv;����lά�9�:jgf?gr��p�x� �|� $ e��Z(�$w(ZrS��v+�Z���q�M������ݙm?&s[��t�S�Sj��9���?�|��
���>G�,bDշ^��^���:l�3��NA�`�5�26�L�pS�	Aߧ/U�
�֘����'9\��Նt���!������l� PMR���9n�
�`(�@� Hy)M�dM�
�5�ԤH'ґ��mS<���q&k�)\�{;�1��m��8�{��X�1�-3ǚ��)�B(��,�%���������w�o~��t��HW8l��Z	r��=e���1+�/Ɏ1W?ְr�89PL��>uo9 �1 tØ��uc�����@��]KR�bN���v������(�"��y뽻{c�����scz�&�p5���,j�n �kN�!�.�n^��Uu@|�?v�>�����rUa�HR ����Ց��I
D��ˋQ��~p�
�܍;;�n���L$�t�	:	hFCY���TO�FNN~}�1"`�����a��(�?H ����\���u�0LԵ��'���͔PbnmO������Jl�?��s���0,8�x�B�B��F��_�RiZ����~e#j��w�hOc*&F6�Yq��{�}?��>�u��.�4�h%g�`�&�� ��)��R5�H�}���ˤ�kܩ��'J��O�I����_��qOb'�HǟBYEM�6�v��5�NJ
�O�NFNx(1�:\�߫C�k�c�b8Q�	d�[L(el+2u-��a֘d��5;�N$�"�H���SF�o�2i�"��\�h7I���<SCO���ȐH��Ew!.��!BSC�gĝ�c���s*էs�(5m�=q�ʊe���Y�$�\>fN8�q��x�#v
�6um�	���`�NM-J\�F��r�D��Z�0�#'ꥈn��GjL�چXʌ�A���gYs�*�Y���^ٵ�;"�$hb=�ϛ�0�vH<�Vv�c�_\Y���w;dB��N��3!$������I|P� ~&�d�.�԰�-a�a	++��9�.mR��4�cy���#�U��FW�u�
�	i/𜯔f~�4��l��XS�9Ä�1E��3@���k��@'#���c���n� ���S_;�%��I��+��.�L�Cx�����ꆱw	��Vۂ������Exf~H`��0�!d��@Q{Oh1��H��Fë�zs�7�݉��Ɯtrv���k���heS3�ۇv�9�q|�O��K)�U\�A�%����o{l<��K����͎���i���H�G�I�z�=6�WWo0��|�%A�jdD)!
��pw���_���;���c�D#�ˁM���Nz���p�^�CDx��xj)�5O�9�
�`��EDX�x� ݒGU��˯ę����ډ�.%
���Έ�~��=�Co�)
F�7���$Z��(�g��oB��
�Ɯ�@��&���e�{��厣�l��f�_�Rx�N[�]��8`-3�s����{Pj��Wuc9���[>�-�.D�܎Y����d������+^{���C��m����,��@N<������.��V��M��S�+�\D�+��R�|�6��'q\T�����9�D�X<$�p���"�酦��$�ҷ�,�p�s��T����b���NkI�_�`��
F��W��V��%��w�~���DԐ����*�xi��y[rZ���[S%�G��s`F<ㅣ��� ��V�+��!+������؍�9y�k�fb�82�s�}l;[)e$��T���k����)�v���9����{�u�u�t��޳@E��>|C��<\4%�Rv���������@׺C�8\��~)#k|��.a�o����00G�q0%����hp���
L���"�+>���%�^Mˊ�N�s��q��=�����䦆�K4r�-*��%��h#�%;pP馔h�C=����
��&)�ba��KL�@����t�!�~2�S]rYl�Z6�3ўJ�o��O�V�;�h&gO5�RT�/}����{���AZ�&�S���t����ͯ�P��C���0��D,�pbpз�z)� ]�I�>Q\Bl�"��^3R>r�*��C>����xPU�z�}Y=�̕�}�ж��
�
6-`/"H
o�&�D�I0�E2Xa��-�{5���<
,}��``6����ji���im<UujY�Z�jB\@�g�3Ejfp����:����W�Ǯ���߳����p�ij3ao���1�da�� ��ݫ����J�ײ? j�q7��M���ff�Y�f��s�$��	��H���l��������(%.�r��w?�m=~�y�cY�bg)<�W� /Vx�k���$��B�r~����9�6�0�&��_vMY�%��ҝ{�E�6<������%�%�4���ߠO�@��N����"Z��OD{u3S��W�M��R��3s<���س
����\I0��.��-2ݭ��ㄭ;�	�0��}N�/b���N{�I��|b_r�e��_pSi���>'�w�5��RF,ч�%SY����Wh�6L_i샣=���i1�3�YI7N�Cp�I��Ĕ��(�r���0��{j����r�K����Тo)l���3na�T1\��IE(�m����߃���D�l��e����$Å�wX���U��(@����M�a"n�,�*vG���̨x���>�G�S����g�̉"�Q�v�b0*z��PE�y�ɉ�?7�$����%��G����p�dY�&f�!��a6��|�)�;u7#�3�4�mJij�
o���O�p�ȁ�v8j��x(K�/Z�d���x�Ń�m7V�_\�f�L�7p�X�z�H7�-���,(1KHb�e��,r-��p�L����3=�T��2�t�2ټX�k:����Z�5��s�p��SsT����:.]��D"�@��-�E�̑!�A��2�ɶ-�F}�˒�2Bǃ��Q���)t�ç|�#4�|�\�㨀��`�fc,��#�g��1:�-����ty �]�����2�Z~��.)�����nj�����%R�K����(y�`�8��C��֍���z���K-N����`^+����n���3��ϴ����T��3�tQ�أ�4<>:J0È%�ݑZab`��vͬ��a�T/Z��aޝ�ГIi	�W1���_��>)���H"�����p���|7mF�^Z��~f�0J��^�I��3V�!���{�<e�/=�p`���q��8^����K8��O�9�w0��Z��|��v?�n�	�3��f�!��߷�~��T� ������ Jӛ����5��p���V	��3�˫����.=����-}��[�g�R�5���n�B8���3.��8	Yg�#0�&���S�/.fg\
E�f�}��,k����g��$�?XY�*������1��p��E(����RS��Q��t��6,�Q�j\��</]N�s���;�'HX]�E�29��d�kY�
�j���R6���Q!���� V���
%"^�`�N3O�����[�v:�ʄ:��^ڜr׿�@���
�F�_���Nc�B���8p�\i����7��g�*���,�C����[�6�T�?����%�z��@jApBN5�"4T����"�}0uJ􇏞�Ȝ~3���{}uW����M�j�9�-�]����'lS� /�R><�+�O����eB#�Bc���jL\��-�Zh�[�I<����q�v�~�k]�G���TD�?S����/�-��%ݒ����7��w�i|C�I��q�wc��W�x�� �/7�x��HO/���o]���G]�y�߃��#��7��b��$�t��R�$ ���]�a7�F�Ѯ���,n!r��I|2���8�x�6�gS�h�	��R^^�D.�x�M�MS?漞'G�#�~�+�����v4�d!FyT�9�-�fVa7h�B��4�����,�2�Ɖ�&vTHMqp�4?R\�����Xa<��4�@Mi�H�D_��	�Eg��R�y�M���lT�ؠJݮ
��yc��"�HJ�, 6�u�/ڴ��������y��V���nJn۟H\P�R�Bd|�4�_�$k����.��w��™I�pS��$��|}j���9������m�|�1�ߘ����n�93�9���5qS�|���xW�9�����B��VZ!����m�K/�Ln;i��u��$�*�t3�Ͷ��@}���B{�Y���ԑ�z�2J�u@�a�\M���R7o��dz����e��7�/$4]^���2k�h$�=%��1�I�B�؃ ��H|�N.[�M\L���b����1Mg��:�NV._0�,�+�,��h�t7�l8�s~IV^
N�˼M���ؑj��ك-�	oܮůQ�o[m��j�=r��m>�~z4$M��}z �s�h""���u7�V{Rûݦ�O-��D9V�٥g�IʎK�Lg۶B�T��P�'�K��̦�
qW�֒�3e����p�&���ے��L�hp����N�aS��w��
&���;e(�,-7v�x�-��w$W��nX�U��������t8�����Y���?KM�ct�Y؃�p*Շ�����-���БfL�|�[nL��
}4�{5�頠�3᧌�n���$$,+�DNԄ-H�V>��H����Os\���-�;�W6N��M��8��Fi���;���7k�2�6%֒�a],:!�ʲڽE,��{U��naw����Ng��.��I9r:j������<IE�1�`$`Lbrǒ��ם��]�x�9=Rv&*Q5�0z��y<���`M|�ԙ�dO�٥iZ���$���+#KH�F
��������	������)-	�:M$�yc��E�%Ai��2]���l嶨����8�I�y��ZGJ����\�2֙Xb�L���I�A-�GrR!�0���L+�Qh�S�Y����S�5�_�(�poF��T���#kN۾�l|r�n�d�H���yۊ����&ۆx�p�����[�8G���dt�����z찃٦	8��B��KP"@2e�e��y�x��j����JKˆh�XŬB�}��6�â��`?�i�*�[9e+b�VL�aL͙����dBYp.�ψ
�n\4�糅Ƥ���d�<w��W"��? �'�O%�a2N�9��,�ߟ���!���.�y�Z��%�4�U�^��u�φ�g�)M%��C��V����M!z�&�����|D�,�i�~R,%��|O"�����h\3+��a����������i8��\$!1�L��a6s�
z+M�R�b��_
k�v�j���U��裒-��jX�Gt������b�~�˚��ꖺwt���͝�SkP�2���(=cvt�"�[3��&��h�DN�=�򈎋Pɛ�A�G���'_�R#��M:.���3�	���tJ~��3zwx ���;�7��O�8��Y)
�DSE����/����7�i��!wy�6��$��8E0�Taތ�|@�
g����.;m���9�9�s�HrL7&�����3Bs�|[o&ou�Sg�խ�+{�AE���kZ�	�"N�d�5��:��IV��ڊ�>�F�b�K��Ψf)*c��G5<��C����.g�]��k��
��� A0�-��٣��v�T �d4K(��Yq`���(u��{,�:0*$|2����/I��,�`E�����xP��#q�����`��/�:�����';�ىV�D)˴�r��89�w�}[��F����ޜη���+��šh�KH�\�ǚU���䬂J�V$pUj�|c0���{���L��A��?�V�=�4���S�Ŵt`���d���o��d�bUP���J�x�g��JR�r�O���s	�����4Mw���
�""�42����`M��D�/N!��v�3չ���.�f+�@xO�V�q�j^�Cߪ�Km���,�8H9�Z��<&�o��(�@��k����M5����]�M��U2=vpB6DXj`�r��<�w��1�Y�:� �o�<�9�;����F���$;2֜�j���޺�x,�ʁ�C�Rĉt��$�VJf�f��9�)�a�9P��&���6Oo��l�<������ds=#3�s��P-�bD��"��[:�wɺ^j��Ӂ��Qej`���Tq�=����H&�o��kĉLD�W�O������*J3s[�6�j1�@��nr<�ξۇ�#���@	�0��c	���?ﵝ<2�D�Ӧ	��}��Ts��S��"�R�
���.}�oZ���Fo*���ݗ������:�������7��H��䍚�x��]���a6v5�R��̾e1��$XL����
J�aa�݆,��섐�"3-�G�!˥8���8
|�T:S�P������pMR�Y�b��{�+�O�eۛ2���g���u��V=�U>-�kb6U���ЩpZ�M��O�`���$W�D�y���A߻�[�4��a��J?�fD?=�d��(KD䴱:�D�/[�#��$A�#KH.:��x?%��V�r�@[B$�}�c�o��S6`LPfM&ɔ��A<:��v��Ú
Q�~P�w���[��+�������`+j� V��+��R*���u�l!���|�+'�KY�6�6��_�ud�}_���[�yuۘ�j����o$��Y=�yjR�i)��b�ԋLaD(�X�U�wI�ڻZ�$�7ڻ�9��&��4Z���'��DF���[N]�~�dD?V�Q�W��Ͳ�}vS>�Nm���+S�q�H��a���U!�Β����Wb_+�����U�O]�^���l59	@��1�'���A�^��m����o�:��9�ף�s�-�N:���tD-�zkS��j�a4�rc�zF�ۻ ޿�x��v��7[�äC8�#7�p5�+��� �~*�bJJY�zֳw+�����-��p�/L�L[cg���n�lc��a�P����H�F����$}�9`������\
��83�Ym�1b>�~ƽJ��؂�Ϗ�yBs="�����f�(zK��M�"�H`��w�c�Ed��:b8�6(9��<��c�l�ݘ/���k��g�G���������^ESE)5�G�_^��k߇�v���̚�}T3�;6� WvTCP_���k���._e��єNJ�L{T�!��6�j>h��0��#���[��㗚����K��z�,�!�3���2����:6d>�himE�\�=�H��Z+{6��@W�ʯ&lC'�,��rX !8�(\�̭2�-�P8h��@�C4��<~����Z7j%)e����eF�pZ�'15��^6B���3�nc�o#~���²q��R�@!ա�� z�^�Ks]T�@�TN�T �,S*@7��C���ī�Ʌ����L��iQ�N�,��	#:��RѪ���j��9��1�-�Y��P�N¿�\&�yL8�ӹ��&0�c��v�Ɖ\�����J�A��;��Q;�]���I�M8	�s���Mf�?԰�I��r�r!�K�9я8p�}Q�콍��g�-�*sm�~�X�P0d�M^��?D�dI�m<��p;�y�,"ۦ�6��v�pT\^�n���3m�>8�eC���N}����cà�٭$s7ۼ��#յ<SF-A����z��≱�
�B�	*{�6cg���Tz�GX2+�����a��0����;� �EEaG�d�Θ׿�[�M���
�i���g��:B�[�	U���3�J9�
0��I�2'	o����\e�%4^5}����5��� �0=�
��J�}m�y�&����"��.cւ	V��}e�J���:42q`G�O�-���-B���J�F��Y�۾�3|��|)��������IG��a����+�*��ttPb��A�Do?C��g�t��;��I�]G��2RE<^�mK3����+��;�
�[���3���[1����y�v���
#��p�<j�iC�af�~\�G�C�4���dubt B�K��бQm�=�a���Tq<��^z�ء�(�޹�G~QۼZoO��c��r>R�{b��4���vM�q���l)<�V�{ě晐�2P��T�'D�
Vt�������oP�aU���6`���"�Qe�]ka-�^<xj�<�G.���~��������5۹�ۯ]�V��`8Ϧ����%���r�y�v����;��pc���������`�٘�uҙ��9q��q�E���ҹ���B�����6�Ǒa�e��E�ثO�Y���Ǒ#:y�p���/!/��5s���U'! ��"|���B㡪�
�t\�T#���ҝM�$+2n_��� ���b���^�&��������e��i��c�I�=��u%E���ȭ�֓
���fj�aظ֐����E�ӝ��_�e���(r}�mo9��UP6zH$g�4�ٺ6�P�@@�X
(1�Θ��x_	Jy�{�3���',����M�1n���>v�O��ճ����j���ְr�1�f4cs�_%v%l��K�ZNi�+V��3�'�����~��N�M�G@H��B�b+���v�VFq@�ݱuKZ�h�p@��E0�����ua����SXd��U���K}ԯ�8G�X�KiI���%���uR)�E��I-�ږ8��|1��G�Ξ��f6�Ȁ�=!K�F6�Qf[X���~��_��j�\^�͋^k����`����D��s�G]~�㤛yo�}��;+i%�N}�Q��0��ԥ�U��u)M��[�Z`"�7
��?/[C�{�l�)�$Mr����|^��	a�����:���"�֊��a	�l�>�h��y��a��{�2>��CP����L� �j?�ntg���]��S����{�UӇ�('��b�'f��g0Ӄ����LPA�Mtd�)�2ú�Y!�v�&`o���2P[�aޔ��5��S�|#+��7J��
#ȸ�_��dU��6#VD����B"K���|�����)o���tk�l���,��l���U�)ݹe�5�<A��\0��_�7���^~{�$
qR�ΰf���P
a!f���XU���hX�l۽^��:(�m�?��@=bhg��O͖{-�i�:�'�A�8?g��zHFz0�[D#�A�.��%'��w�=23�ɸ��Z'�Hx�����&I��4�1I�Ji����e�z����͏��o�ٴ��{�����i�ß8	0[�K�/�n*�a5���ᰉ�,c������+��A��BDrlDo���"$Th�T����9�$�岣�'���0V�'|�"������
���S�AJ!�Տߑ�6�F6R\�6\��9�-�_=��Q�"9IW.\.zmkz�F͵U�x<9��ɑ�$�7i�FS����ʧb߂@�ۨ�}��u��o���Ͼ��Ѫj�4=���oeUK�xd�W�뻸1nD�X���y�"���5倘�ʂ����K�����-�o7B"��ě)��uW��E�h9��b)P�%.�$�G��(@(��u��R��fLT ϪJ6
���)H*y����=���Q/����uI.��<���,��r#�y|�l�<`��Q��=���F$��A�t阍2��d6c��Wǥ䇣4~�%�vb�a�Е_Cծ�Y�l�̨�vq��s$m:�G���\�W[����C	�l��}�R�^�2J�I6�X�l9��=��`t�ӑ�/���P��jes"��_�
L��w�m��~��X���N�M�1x���ٛ#��NmzS�%b��,���Ž�~�B��	`�9�Vu6U�}ֺG��u�n�wO�����fsC�\������g�������V��Φ��@����:�_`c+}�L�<�[��#U��*|�歺[��[姙�ԧo��ɼ��\=GR�K,![<��H�?��;�9���:��Iͣ+��a���!���*��?#�'G��=���Q6�,�g�m&;���������X故0��
�������;qW�q�'�4��I�C�g���΃Y�`�~`6ix0OG�g`���[~��?NC�Q@�Ȅ6�N΁���A}j��Ba�3�ť)���˴:q�I���gZ�2�vlf,�У��Y��Ѯ��bԩ����Xo�Iė˜�X���_'���5��]J���2P�92��C͉���@�C�����6E�e�B@���A�9�߇���Ǵ�y]�H�	�-� �b��9
��O�0uw��I���7J�x�ū2��\�Vf=nV�V����"#9���v8x
��mpAh���y�3��pQ	%��t^��� |�‚]�YB8jC׬n�#&�ɇ��ʴv�˒P�>�O�������y�UAt2�_�������n53e*��1���v����(K_H�vV�ʉ3},��A�C�Uƍ؂�Cu���t��i�-]�`�����7�]R�
!zs�N��t���&��̉̄k)��SL����̹�y7��$��ϥDJ�N�d��"��9�
�31 I��Z(^(
lw6
/�@�Y�B�^���}�OT~9c�c��]���{�)��}�D8�${����yc�,ʤ�{�tA�W3zHI��m��D�4ܤU��T3d�I���D�)
��I۬�.d�~�[-�K�^2�Zc��
�8��u�,Y�^\�_��ԁ�_�+�cJ��$�\2:ZW��b�B��w=��[1'N�YVz4�;��(�fzN���U��f(p֙�!x�#����L�=#ŋT�hn�b��a˳"��,�T�\o�!��@@sN%��|
���t��Xj�	j��	�Qo5��������o�eF)o�� �9˷�:�h*'cJ�孏��[��{ȄNf�nz�]8F�/�|��1�v��g@�J:�Y��նNu�:�d��hH���o
����t�M��`��R̍�R�i�:|N�_P"����B@���� m`a����:M���	c2�Ũ<���ؓ��U�O�S�\��%a\A�p���ꄯ�e�\��A�����.̰{���w�ǿ~<dXIh��RN�gkv��o�{n�Ԝ�}���H|e�iV�W����?��#�(K:��m`�&�L�x^F��+'�����؜Z慉��ŏ1?^�E�(�ݝ�D��u��6��T˜��LS��6O�am��d�ʙy�2���|�^�S�K�}*�2L/Ř)�h~����\1�� 
D�̅���$��1�G/Εo��0^����_|q,��|��`�ܷ*z�|���'�usv�j(q�R��zL>��6������	�;s2�ŋ`���W�`�TyP�g�ee0����00�}/ǔ��;h[tG�D�5�^E��#�h�ȍ:f?	�u3z0�ڎ�$�T���^T�Ahz�	�x
�I{��5�������'�r��K
��z�o l֢<���Nl���f��M*�~�Uʏ�W��_�?�v;(A���ͺ�R�^� 3�=6�6=2�n�~}c���O7�X���d��J�|��LP�ޝ~ͅ���8�+QD���\���ҭíS�\�=�U�v�
M䅚c"a��K;�A�=ԨĚ����k�J�N�p��M%AR`�و;�(���5�W���=���Y �g-�^v4��X�ى��J�@��=�c�3���}�*)u���b�T�F�'�|�N3����E����9��ڪ)1��!G���k8��6�D�
~H���Gp�%�Fz3�2��M�J�aZ��?�c��n0�)?�h�N��u�����m3H�~����1rD�'����1������Kr�t�sJ�Js������ָU�����2��r^�+hNzg��l0'\/e��tXԐ�v�l �j�cm}!Q�ϼ��t#��z��#]����ϕ��O��ׇjE�:�#	�6�n:<�N���u�i�����{�z���1ʞ����UV��l�+�a�N��W���h��)O�2ymEl٤�A��7���YQp���fB��<8����;����'gKR5n�����T@	�n�*��!=a5��������Z~CW��P^DX-Xf�j�N�ű�q4�O�I@��S����}�Xh/�>�,b����89����-:G|W��)��b��A��5G��<*ٕ��:ğ�!]gj~�O�&��U�N뢹8�� ����g�]-WW(W�NI�3��N��gr�3|��m
�m��'=[n�힬M,?�$��HD��D�-��O?5uX�]˓��3�7�>�*�w�g?���*!��JyT�@U�g��z��I��_��7�&�\t��H.Y�Z�(4Y'�d��T�
�F��s�-�qy�a�7�
[��67K&�J�/$�c/��x���[���ᶏ;�Ī�z1Fv��]G�'ڏ�Q�BSO�������І$�y�(��TS��-;�hűz��T��%D��ts��"��=�gwU�uD?b�$Zr�9�G���<��&�Ña<�v5��0�]f%S��an*���؊���oмb���8pJ9����⠚�'�-s�@�r��넅��T���AX��I�\8m]{�Of�`#��X�T^f�5��''������W�2Ϸ v�sE�\��Qs��(�ː@A�jR*Z���a��̳�Slі�R�[�ܜd�*)�ɩ���P�¢ĽHt�o��5��8��.��]�h�\s�І؋����?�Vs���h-U�'�#E�g�m]��2NjWl�rm�Z������#2�BE75^^��a4��wU��K�'g?ge���213����Ǹ�o`��lKzP6^� �$�$9N���Wvg2�HϏ���CR�ߜa7F�/��3�\8���F�\�/zP��/?������{x��Ӽ�]�������/�^9�@7c�ޥG<Ho~�F��!�6�:�j�*��Nb�lNy����C�cG��d2[d7�W4]�
�5�4i�2���*��h��p�*�9���mYmط��kh"ɋŊ�W�!��A�an��J�|�V�N�c|�u���j+�'���7������('tcnV��d�Uc���)�I╵��8()�K�Ζ9�U'���պ�j��?Vפ@B�O�E�G
,�cC�"Q[b�$�9td҆�=��X� �dL���M���͋��h��~���l�c�.��ж�t�q�?Y'{'ވ�A�cS�V�M�%�kD�
�{Ʀ�X�=�:��*|�ͼe"������~��Ov	;�G_RϞ��\���G�$4<��ie�f3���Ph�H��b0��6ĎU����s����LӨ���Q�|_P�����3�0����D���C��H���,A1^'�M4������]%�EJ53�蕂
+ͪBP�^$R��R
DB+�M-�	�s��b�R�VFeP�;7����I��o��m��^��M����k��++_�����[9K����W��R�vۧ�?f�q2�s��}�X�@y�f��������H�/=�����֯�A~ ��0�̜�xra� GD�v�l�Q���Z\\�D,h�i�J�]&(A/�"Fb��a�ƚ�
��m2�l]��x$��E5x�Ð1x��{�����A�1>^2���_���Be�;b��~�փ)�Ό2�j��� �r�8]'�7��
���� b�C�h�T��d���)�+���mD)���.5�1�-���|Yy���*��o�ڤ�L ���4A她=
��T���@|�X$�in.K�I|�R���@�P����@���P��*���a����k@�۟�������=I��	�=�l����[���ג"�h�X0�QҜf��˒��펖�c�<#9`|cO}$o>e�X<�`,�o���_��K�3�����p�{Y����An[�9�M�
�T(!"��?Z�]�iE�m�Ğ�>�'����{G�t�� ��*~���y���`�'�A�?٘#��)�o�($��ȉەL���vYO1o���_<�/ǐ�M�(���W�藑Q�'^�#0�M|�3}x7t��<��a��@�̻�H�l�1�>���& .�m�v��!*��)$�z��mr��t���(�:���G�G�beV�w�i$C�O1� ���c�Z�Z�<Gc<z��@�:�J-����_`�8���~�چ��M�	���)
uE����sY1�B��7�4w�0�G��5��z��A0�|Р��[��@��V��ܟ�Q�q^@W�r-���U��O���$9'��IBjf`5
�"ѦYx�Z�� �U�O/&83��,�8�k�2�&�� '�?�eEv�$��L`�B�%�=�T��ftF5対8�.���<1=>�0�G� 7z@Jy��~��p)g�,g��YL.$�,�� ��-�<�k��{�y�c*0�2�/q1��������g������K���M&�R<���7xC�y[M�ʛ
#ͺ����Dya���3\��wf�wr�F<G�W>�ĸ��M�]\��N���s�Wݍd�<ӡ���W����064�t�ȴ��v�Ȼ0>ԯ����; ��)f�#�*	�2<�h�� �~'B�w���m�H/��������wqM����o�gC)̵67�#�B�S��>_-[��L|R�R����lQ�}�\T�H)
�9Fa��"^�b�A:�ݳQ4��' �=�sO	���'�@.���Y&8z
�,i7����3y�;���U}p/�I��xV�x��il�F�Z��f���hX�c����.b��B*�|&��|g��e/�k�u��v\_H����b���d�p�G��/�A�}�㬬'�xȜ�Ջ�;�E����
�!W�����j��{���ZI$�z�{O�p�;�x��=׺�q�{�����5�l2�3O��=�@�j�j#�GY�T�n�>�&ެ��#��CBϩ�zLuy���lS�a�a���0�LTv��3��,�2
�sdTr�U}E����l1�z�`Xa*h{�qiuU�\��"L��д@�T��X�RU��Fg�]s���E���5�V0��X��/��u��k�z��B��'ك�J�x����	�Iz����7�������Y��Ε�1t���y���Κ_}��|�xm�[�xJ}z�l��D��V���r��csdsq�v�[��&��`�oU���l�?<j�C�!	OeqB��=�J�\�`��Lr�孈�d1Mh�o�w�ѹKi�ģ�d��*;^ҋ��$��xH���U��U`]G�kC�ꆂ�����O��QS�C��w�o�g~�yG8P�{{H��.$���6�!}d4,q>�`�ll�UMBR��Pe�2�A�1R���H�q��lB�Q���$�W�%��b�hB���ÚV@(?��F��A�Q}<GD�2�:�e@�f�$"�8�ȍF����f��5`��{���K�uv�\��X�+���vj��^4=��03O��(���0-I��fK�R���o���O���i�2�)؆�G�Ǟ
X<�ǘe�l��m��S�\��P��!!�ox�$�+��>dl���+��b���NIM�dT"+�ƌ��o0��`�89����\|5 ޣ�ئ(������y�j�q�m(����<\G�	�2���dT��P��0���$���n��@�
Ē!�X�㺕�����N��kճ�xiki����ݝͨћ"0?�^2�XF�,{s��r_e@V�����y�g����N�_�i����wq�;X��ED��\��b1G��(����Rs���T����<\ډQ���2tT	�;��`���[�,��Ak��K��bDl#�b8�,]�i\����|kC����xLq~r�
�Ά>|�ž�B����a��b�?a��ag3�0����(	j��"F�A*�{ߣ�d�]ř+XH�z�s����Z�S��L�u:��˅�)�Ҳ��n�J�EBnS����>Ħ�����	m�h,�R����T�~}�9,	�/������.��H�~�!���`��E���x��O�ۖ �mwI�l꧴ёUz�z�k*�*|m��*.?���~�
��c��hp��?e�Y�]�*H|̛1���e?�V;	ا	2�PQV���lW6m5O�3'�^���x�,�ҹ�a)T��eU��s10����ft9�����T��{�!��L���@�OL���tǽ!���^�L!t��i ���^��:C��R��	����K��
?2T��Yx�۩Fq#0���
<��hѭ����)���kes�a�T�l��
x����9���d��%+��b8X�Z� ��;g�v8n7�ϻ��a��&�^���o�b{w	OO��7�jϯ�زΞ��,�~��WY��ػqÎz����Voλ�g�'5�(��"ե�
�A�Ӄ[�:��P��|�Ӓ+>��#�2?$Mnd�u�e�S�J%����e؞~��U�q����
�޳�҈z�Rn�п,7��˱������>`�
�/�uFg��Og)P�J�\)X�k VF"��\t����r�#��wE]�s�:Y�#n��8��Lm"6D��
�Vġ�H`Q ௢��ү�QkG�]�<2�N�?����U
��&��|�a���_G܏�}�di�!�:`Ⱦ�����[�\,Y��]J����Ϲߐ���ì~���O���A%>���]��2P�l5p��O��ѐ��[ʀ4O@�¡,�Ҭ���-�,�4��X7�-#?�3��{���M·�C��1�8�a��Y)�M�"k��a�_=4�JqM��?��nh6�k�ɜ��P� 	�2�;�3�g�4ՍZЦө�GZ�k(m�p�v��riZF�}���i:�/��czP��uV�Q9E��&'�/���v��<�2���ۊ����YQ)�j.�HN����11�s��ʗ���؋�{�
��'|�k��lT�%�1�ꪋC���g�QUJ[�'��U�ؔ�̝�ֶ{�81� ��r�n���ҹ��}��
:,�й�6X7����f��e�'
NM�2p|�4��p6��Vn듁p&S=�[- ߞ��~�Nj�I���Y�/c`YAq6�-��Y�30#V~hs��EPT;�u��b6��WD#�N1o>��)Θ��Cx4�$�/jl1�
y�.�/���,���Rr���[YE*GЕ�Km/�|7�����SI��SƗ�q�F��㍹���6��:c�Vs�@��w��+�k�1��c��aí�����w0:Y5�Q�"
���+g"%*�2�t��`�G��ݴ�
�f:hN3�3�^�~<PM��Z�*w�����Ґ�I0�p!"`�PS�L�6
6�O��{&���`(�ۅ���Mq�aP����=P��Z_]��pv�W�{m�h:
�Uu,
A�j9�^��*��7#�C�f��]��gr�{NY��� 5���$�O�e�
Gn��s��$��\�i�`�D�����?�߾;���w���5U�xj~�̦�ܵ����֝�>�yө��)�o)l*��H�-�;���+�|��+[��-��ZG�X�f~<F���_��̝����r�f^R��
߂�4/)+��1La1PEv~�:+L>�M�e�b75���[	�Ho}pi8�;`�$�7��~�Yw�4��RypJ�s�������}�!*Yf�~����W��]�TKV�0Fy��l��$"��\��A��E?���W
,�[b�0q���.�|��x�Z�/�ˁ���]���P*4�$*(����R7��L�&����`goTܑ.�$�V̇�h�U�L�Hn�e��i_�"���o߁��e*mb��D2���u{��ݹш
߶\����ؿ����Z�D�ܚ��
v�z�1Ul��Rl-wk2V�x�Ց;�؀4�00�=ԑx�~޽ګ��o2R�mԔ��=��_��r���Z&�ן/߸�����(��[��C{�%b[f�.��<Nc0G2�ڼj��~H��iDP��ce�|:P�7i�/q���-ڏ���\�b�7R�>�\l$}�V����چU���*B3�l�RPf�	�d�'���<j�E����x���}�6f�s�(İS���e~4�U���)�C1�i�s%C��r�H"�3���؃)	��L[��ө)�mj��U��ٜ"����I��R��6�W3��nP���H����ߛ5Q7s\�@��Sw���RhƄ�eq�܍G0?޽~�ؑZ>���GL������c[�d�N
�%C9�X�<�Q��^i����p,U ȑTÉ�~��U�2('w|�/��B3�����J,�t
���WgLN$� [�V�|޾�v�h0X�X�����<�j�h���j0��{rLNm���[[L�3S�$Y����ʈ~
߇���K������!�QE(؋�����P:&��{�ƼӬ4sœ��WL3A�6�R
iv-7S:�L�3��e���=^�����Ŧ4˳�4�OC��R~ܐ��NK0+c$&3�M����u<:�"Z���,���n2N����EG���%Wթ!`�4ى‡��_��`��}�.�Kq���~�J�k��t��k�S�y*�
��)�I��k$Q��r�q3�T��)A
Rs��=[D�
j9q���v�C�no�KR2�v�)���1d�c}D�2k<9?�];�8����BR)x�ˣ;H�i�}{�74���4Ϗ[��:g�V-}@� ݡ_׀JPz�������X;�)aDJ�?���\#X���r��w�m���A�Ў2\�
�=�69j�R�Lm���.I�eG��R�'��v�$�	P�>5h_
��c�ҠW�?��+��������`ރχ�#C�����B��W'B��~����c�b
���5~}`��A�E((r�{2me5�
t>`v���d,p*=�ϕƼ'�� o�$ݥ�;f�`�̢�t��ɟJ�$��H��Z�K��Ԋ���k�+Lm����R2��1�,�q������F���p�̹-��J%b�����=g�V���^�y���~��׼�0~-P��ת{�ƛB���2X�Z�?�oG!x�n.��}%�}Oo	_�?b�J���N��v�$bl;z��`�&K��x^]"���d�+�geI2����� �B#�(ijNN>SwF�W��|�b�	���W�oW^\q�?��1>BL�/=�iR��,����cykW�Z)�BU����kjy�4X���K��,
3�
�F��9�pK�u���շ����q�@���OAv�yG4����.,m��#D"^�ѣ�8l�QZ��1���C����\�4oJܨ��힊������dD6�h[��|��L�]�V�~�.��:������0z*��HX�,�Ͽ�7��z��U�QN�e.7$:���.��0֣M��j��9�g�{2ڬC���O��墸���N٘�@.��W�1D�z[���[�M%V�5�r!4&U�r�
s�7%y�N�J(?�nYm�"T�C�Mmr�.�ݴ{bSNT��]*}�v`������1�^H����v�No�UۆAS6W�Oىe[(��B�͝�to1bϫZH��{���~�N�}Vˋٹo��<�>#��o���TFD"�%7�3���.�(?�f������]��`!��������1%U��qL:蜧�ϸ|��@8'�+��V��Wu۠��0��} +T/��Qn���l�~�c��{�p��a�=��V:#vm��~���1���t	0�SPH�]�/�j�g/!���{/�c �j���h���[�=�U�@ʍq�Ig6�M������mq�%Y8�dc�`"��X�t�������>�"��{��ri���P�O?��0=�/�9��F�nV}�OY[՜���"I��
�{GEz	`)Ӈr���OoK�Y꺧�S����4;�������L'�>�c���N@����8 �ʋ�{삕zb�8_xV������(X"]Δ�ěM6w�,�f�gf��+͜)T��JUt>
-�]z}�o�*�mGŶ�1�S��<����۵��&��:��Q�z�H��j��l�j��L�
�F,����a�Y�"'Lˬ�ɴ��bJp{���6�ի�h���]��m�
�E�=��~��f���Fv���E�`EWinux�8!GVY�??7K^�+�[2���%_�mw�s�Z���MZ?�v�l���9��f��O��{���,�'9�/}
T}�����6��V�zô�vU�[��dT,_u�V���E�+B:�x��a�Y.L4�r�P�1�"��n��j[)Xs�54��� �4s�S�6����{�(,�kW���
�:Dm�3����/
�T�*���z'�1�o�'3��o�w|Ћ��=�Y�<
a�D�m�?F_�Y3�f^�L�f�f'@�&M7�F0{���G���T�B����/�f��zqc�].L.I�n^����W�k��(�h��c�!Ȝ��|�%�?%��\��6�Q��n*��0��'�'����W�hĩ�=��ŝL��CgR񛙌��9V��玫؛A�ӚT�Q��y�č&i�٣h���QJ,#�|d驺z���|yYH�����{�FI%��O���RD�&�k�'�	��(����k�ͷ_�u�XT��4�J�o���tǠ��`X����l�/��-�ԩ����
TBIj�ԛ/�
��J�n0,�ħXB��U��H�h�Fe�%�6�%�/���:&zLl�dKT��
�^�Gv͊��SA4�:�D�I����ʯ���<��!.�1?nT���zhԓ尵�Z�B�����Cn���I������~+��sm�8�T��=f!c�(�KH���S���H7!L�S�.D�4�$��~]��ٴa�G��s�iK7���"dϸ}�����|�{���ܰQ�7�r-�y����̂z�RaV�]v4t��������2�����-��讨YD�ی�S�@�%_�B(F���Hke%&5��='�jF,�����G��oW�9�;�(�ڤ���X�3z`�f�M��<�~�1��bR�6t��0l�u�F���Ij˯���Jo��I�q���Ĵ(��cǘ�U��@���Ѣ#e�&��V������y(�	�{̧Ku���WKe��Z
^>(wDI���߹}x��
��ƺ�5�gY�G2�2��&���sσ!q��\	�������C�P%U�
fb���S����'�H�Lbi�,�s��F���6���7߼D�
�g̣oGa)j�S-&�>7��y���CCΖi�]MR���A��0��
Kf��F=z��gg��tf�7Kx �[��L^.[��ԭ>�Z�c�7���36�c͗��q��w��*CC�V<��])E��9��)�ϛ�0l�SM�.$�bAS��Hib%z�qݓV��޷ʀ7�+8�{
\�H�A�Z#[�8��0�*��r[-�swn�xP+HEl���Y./�k6wKb�?�8�8G�I.�u���r޼�l9�Eiޜ����`�"�ƃ���ȇ�˺�&v��I��բu*J\[�^en�Q%j	?{�nW+��1��Z���C��	�$��3��!��6���/�SG� @�4ΌE�!�Rd�8hg?��J~���u?Zi��D��4��K{j%)�'�x��Ma��YvkEt�,l���c:��w�Xk||2��$�.Ey�=x��*-LM��_���xC���{�t��4.��<�P�r�͙��s�1��/��N8�uu��.ӿS�_r�j�]�\���av^�����s��Q��ZŜ�-��D�u�S��g�6����{${�r�2����5�>���,	��hc�b�J֊�?${ou�o>ͨ��vCl��(��<�/0�x�(D'aԧ�R�0��"�o@����>N�9ߖQ�]��}��3�(� z^)(Үe�}E1\�p�B�(y��f̷�H����Y��/HI��;,���q«=���d��<zl�hi f|A��f�g]y\��:e���}���կ�F��M�.M�-L�C��E�f麬��u��\Q(K�ۄ�Rj���R�Ǐ��/��[��uTOb��D;Cطc�E���E�TSq��h3d��-{�fXp���6��h]���V�Ha3<���v��J@X�����M�zdR�Lb�3��/�����dz�"���?Ԁg�:D_���P��7���_٠�Sc}����ߨ�ʕ�0�$��0��s���MG%^��X��5��Tn;���>&T�<��)3SfV1��ړ'���vh���D���n�$4n���'�r}b0��D�xo�V���U�JgIN����}��4��/��|ߥ\��$M��y��"�j�}j����ib�!�NӽSB�v�C9�wp�7}��5�����q2�Ѫ��Ҵ�UÍ�,��鼁I��}�;��Y͜ȝ�DJm[���O��sޥ$Fl�X��~�=/_��S�L��J���&��^(
qwv#��	�꒎��.�P���:bB��fV�2q�gn�ٙ��l8VӅ��b��0�aG-OTlO=A�f��W�O׭OJ��{��̑Ͳ�g�� k:���I��3��*z�A$���̊k�P
�`��n�FGx)�G�RPE%�5�\�}������3۵Ruu��W�-�������2�����G��������%v�oM���k x��B�uF��N7ׂkV)12�dB!4
��.
��N�8O,f����2TiV
u����d�L��zy���u�g��’�;�Ks�'^���y+�7UUO���B��ж�+�$�%O�9elե*��c@��F��c6gg�MU_�~1f��v�V�5
��-V
��0�� )_D�{��Գb1�#Q|�k�9=�?���Po���c�s��$&��}�BoWT��"M���=�Dy$,I��N,چ�	w�I�x�E���6��x�n�C�C-���,�ϕ��̲Y
:�y�~��ʝ�،��=Y���c�,Txe�qU�k���*O��Tq�\�E���*��/ؒ/��NS�Uf:��b��?�ī�H�t$ٶUfu��dH"��$�2kQ�/���WiX���N��x
�r6���_y{?2�ڽ��C~{���u�8�|�܁�Sf��+��{��3�0`�wbcC���Q��+zƪ\T�-�{�]��ξ6�Ѯ�c�?�8�Z~|�&�e��D��9qW�2R,Y+���y<`Ow�A�bz6|�]�:q��Z�O�V�gM��̥ic�kJ�0�=,������4�,am"����RC#��,c�f���Z6RcG�Ţ:�)e�		���eI��r6.��Z;��P�+O�)��$\�wI�V��(h�`z�{%�fp��xl	}�o��nr
��7�%ӧ��{��
��x�m���1o��i��q�� J���O��'V!��"��=�$

ї4��KS�+���&Z�ۙ��'�憥Y���^��e���~���}�,��x'"s�o߮d����߽}{.�k���TJY;ff��j�KV���B�+�j��qM�WL�"�e�/�׶�߻Yf����xw�I��:k�I��q.��Dz�dLWim��]ɗ���]
f��)�B��{l�ֻ��`�j�~�ކ��;ā;~�7��-zA����X�'��tb����WO�.��$�GS0R��a�#�Q���P�O�|�P[����%`C)c���"�ͽdD1�xp_s*5�ac<�v��P��c�q`{D8�Shv��i ���W�	��w�pk���R|��O�2/n�@�6M��R�իB|��\Un��^�l�s���=[{���A�?��zJ_R6��SA���	�������o���wn���~��GK+�(uhK�7���,���H��⺔���Q��/��,���Z��y�(NZ��y
����ɧ���e+u�h�C�<�/�,s	wy��#�j��I��诵�{�Ҏ����,ٿ�%�`S"[;��_~`!>�]�܎*��t]8J�u׷�uO�
��աH>��h�Lkq7g��R2�,ʪ��Z]�|��$�CZ���m
������q�X��	�LrS���Kb��홞���%H���/���w�>G�9�(|�v�v�NnNvX
N
Ѐ`p�����+�{(��u\� s��Q��p�ݨ3��q�\��͟��$�ﵧ�;Q�Sřz��[jl	�6n� 8�DT�}��㔨�P�E	%��BW�ح�Y�w��.�����!����/^�mdSZ~j=�*Qgd�⨎�0t���]�����q�-�.P�JBp��1	�ث��at�l�/���y�p�q�{~��TOH���6���	u�N���wY�|�
A�Vr��wDh4Kk���+
�/�@
@��O�����J��ZB1[�?l{�JՊ���q�9Pv�oY6�CJ������������$���H`7Ei���)*eK��؂Y8��{V���)b��pNv/A�%�;�uh�(w̃�l}�*�4�y|uV:&�*P;L�Q���g*}O��W;xT�!���F�[���o�
l���*�����K��K��Uv�ܼƌ٫NY4�$Gd+�3�$K�VZ���F&FuR��j.GN��ۖ�5ƴ�revv�v���Ȭ2M��C[�)�|��eGyb�{�)ڻ���.I{l�1����C��e�sZ�t��h��ɻ�RæGp��7?��(�d��W�^=�

���&�f�V��͞�iϟ\���G��6$��$��uP=o�u87����[�%>`<�.��$�Mtӗ�B)G�jS�Q���Ud�`��S�"��3��ɽ�}Mױ�Tth?�7���]�����i�EH���zş��|�-���td���ۑ,�:�D�����j7l��D6٧-�����+�}ZU4�^��xO�ݼ��f��QH����U;"I{�)��1��Z���.����@�2󄖩b+q�z�V��s^�>��V[ŵ���-5�v�����]蚮���c��"��"f���\�߬��<�ۋcy��#��Qj�6dr#�ȑ���J��4l�O���(y��N��}$m�[�-�|�Ԉ*��S�\�ќ��臉@��@
���ie'�m��'q$��s'B���੻A��d�)��.�*	�_y��#z_Ы_����{��_a�_=+䊒ӌϞ'P�ܺw
G�J��l.���r�q�Z�vD(�DCG�&�C�ر�!��=�ǣz4���v(�$;�{�2 @�iǘ�u��pc�E��
	hh	s��>
��L�^�f�ڻw�
TWޟ��R�
�/_�I�Ħ�M'B.���,P�-�H�j)��%P����Dp2��^�^w�`K֫�K�Pa>ξ﫥jϨg�)�KS��ټ�dGFYG�$����X`�7%�Ҁc�K��QO����"BաB�'��^.�`"�;�G����leԒ�O^l��:�Q�>�45e�=[7$z�����i��F�\*B�'ǝ�A�ko����MFc�������3|�Ӭ%v�>!���]�€����'!	��}:xi�/�xcR�^W��I������C��z��_`~c���V��Fvf�]5On��C��?��ҷ�7�9��']�/g}��փi��UIȃ��O�t��̒�?��k���:����[��>TSi������E<7�E-�N	ؐw;�mD��u���[�����z�+9��g_PO$��UYN��[�#j���I&���3�\e4n����)Rvcx�/�V�C�?�K�����g{G��X����"b��(�6��ʛ�|����	R�r�I���&�-Nձ��*�?��2BpEYP�[��.���r?�gO�h��/%l�RO�E�
�f N=d&�u_qb�?X°��f:��J/��}?(u�6����P�"��L~�iV-�g1��YBg�	�����}H�K2�4鵖r)�ۡ�#|ti�@@��J�R[��k
x����cE^����I2߸�dVo�qP���kZa2��H�/�=(�c[lW%i����cX�c���hP�q���6�c�M�?�}iSh�Rm��]��6;���?'����B}g��M�m��Ǟ���Cj,v���Ա��>����G��+zYl?G�ܦ*{��.�m7�A�T�^1D�"�;R�Ur��"bh��lqw$���/gy�R�mZp�%�0B�ϝ#4�b���\q0n�	�N]M�<�q��N��{Ԉ��h�@��1?��~�t����6͜��T��k���̆ҙ҇�\M�|�t �5O<4> J�}��,�QrQ*ͯ��A\'�)yz�'�KdخD��Wdi�@gzu'1\}�^q���I<>e^�h)�Q*��lz�B�l?g�������G��Z���0`��~���9�<!:���+��xۣ""p�[�W�}��"�Y|ʒ��>�/ie+U�r�W���Ws6
�g�*�D}�z�yn+ህwUӋ։��f�G�%!���L[#��"�h2�fmh��|Fqb}*�H��#z���nV˴��]�xA �1����m��k�
	ׂV|=�@�=��OB�z�P�d��5Vrl$���ZՄ8����8^Ϗ�qp(:A6J5PY2		èV��'G����pe�᝭\��hj���p�1a���w�ʓS�A$�|�H��E#7ч����|��p��*���
�`�D]Z�B-��\6�iWẍG������GG��׮~�Y�J��T7Mq^��#�0����õq������b�0�KVot�[
�Ֆm^�k k��-d�p�ݟ��^J��d�3��ݕF�F�T�Ϻۗ�9o�\S�8��qk�"�σxL_:��P��Lh��0!��iˌ�{��8�:���zE
 �Oy���/�l
,)�G�����q��Q��R�`��\J�>[����ip&Հ@�����
��$��:�Q8���Bt:@`{>���'�a�ޝu9��9�'��L�cи�đHh��d͞���YG�f�������/�	N�=�Sf�0T�;WJ&� �I�2����31��kÉr`��}��A̶���������d���@\q-�9(�B�,vѣ�ALX�q�H[�!�f�-t|����n�PΤR^�b����GO�f�=+����h���W�D;Kf�x1��^U�]�3�@j�K8{V�. "k5���h�G¾�pC鹒�*�6i��S+п�u4495�dj�+��Kk��Nq�B��M�++?{�2M��NJV�u�90�$#dV�/�,)��
Ak0�Ƃ^����F�ߛ����n������<%��J�����vq$������d	@�ww��?��R��s�
D1�F-�_�E1}�zc�ƝZ�h��[����$��&DWx&fe�%�� ~)	~��XL�t˛�҅��JK�//(�F[�KY=;��ؕb����~$Vd�]��8��|��bJ�):v ���3R�R�Q��}˺�O��	k�UP��}��SV����xsQ�ro���3��z�2�F���'֯���nN?��{"]�1B+�յ�
�;*�
���eO]���-��N~���2�̜�u%l�(Z�����b�9M�h]Z3')�9�#�>�*�<c�;�Ԛ}l>�%�)�V`leY�.5*���D~�-��d5J��Z�!Q��Ӧ�^fP��/fj��T�X��X&(f!�Ý^�g/j<	�/��륃S'J֓5�V^	���ߟ��^�m�{��2��;��
0i7$�&⩵�ӵ�����XEOS��x�5DZ�يt"�h��v�_C���S���~A$�<�@���f�\;S�a�)��6C��_���Ίg0(4i-k�<
#5t�\CC��h�>;�!`���� 3��-�6�ht�D]�S�eN����
�}�}�����"����#Qn����`F:��>�79$lV��e~���̈Ja�%��q~�ܣ�˴��^l�C��
f+/����eBa��<�'� \*F�C�;��|�c
��ڀ�N��f�!�L2i~�<[
����p�&�ѕA�kn�n��r�틧���n&�fvnjn�-��2�5(!�������rC~��D���"`\T�'j	��P`�0i�O͚�F�krf�uə��کj\'�3�!B�IEl�Q?��m12<T���R礥|�X}���v��f�*�?_�K|IY������{�%m`*5�D���`��N��9$#�c�����z�K����t�؀d��k؁�7��[�3�z�ܐ,����b<�|S<�~غ-VE�l̤��iA@O[��.5>�pQ����e�>��R�w�تD�.ۋ���
XN#�'N���jj��о4�!��tK_���f�R��!@棼C�J-�ja�H*�����N��p�@w�V�[;��
��➄s�q���H��l��ڜA�?�y�	"�j�!���<�U�?�h����k�1��oa޻���e�8S��1�Н䋄��!���9�h��I
��B��
9K�o_([f0���o!����31�C���;X�Ih$�ɀ禹@��@0Wl
�]�&)s6��4w�Y�3c.��Mg^��1���O�qs#Ms�3ZNLMi�}���
�9�U�~��x~{�$6���F�ɬQ�Ei�2Wv�YF�A��Vl�����VDXer�(���Z�e���Ͱ�3)��\t��5\^�"r�Ш�s�
�w�P�5��f7�N�K$f��^q{�"L���]��z`@��DQh���6f���~h�G�5�uU7G�����~�
���.�#3�P��TV�!�n���ژPf6�Չ>l�6	9@�Җ������5Ϛ62�t@7
��L��2	�� t���'ԯ�bH���Լ�w��Wf��Ɋ7=��.=bx
%d?
���a��� �9�e�p����H�ҩK��\��ۏ������$����C%�0����
������ntv��:��M�`᳑B���asp�&)"-qc���	��@�I����bk������3eP�F8��ZmUL(�(qP05�n'���C���V���i��������j���ɿX?q�g^:ӛ�[[P�V8�����6��=Iɉ(�c�G���@���Lb!l�l��8߬Mv���vVb�q�~��/���%�Ii����҂ϡ֣T�=�!B��PS:�m�u�v��P��s�ϥ�;����Z|s,G��:��pH���g��Vu��ZR>f��@��e⋮@F�<6�Ͳ�.��L�
�/�)�X�3"LN>�^�m��w'����>��\�C<��C�Kb`�(.��u�ְ����T�'� �o���MG�{x�$
v��9�
�|�F���x�ʀa@QI�֧�'�=�z|Q�o�^B�f��,�Zf�W�4�#�4��y�I���9#��5ZڭE���2�p�'��B��~���U�j}ۣWwE�`�	
m�'?�!�@ ��C 2C���pc��lݻOš�{(�C2��kC����k��'�U�"��C?�T�Q^��ڝ��kK��m�3��m��$�۝��ͮ��]�<i(Q&wldmY�1� s��3�hOJ����:�N�I��7N��$�zڸ��##ot4zϊ�p��驚�0��k�x�ȬU����ÜF~:(|�B�����n��m�	`N-���d�l��9�/\T�&1����9�V<vn�:};B+ׇd�S�\H���l5� j���fe_�����Ńa�8��||g���x��WF�i��%C�F#�Mk��1����wJ%"�\Ӿ7����R
��6�;�{<�UK�9`�;$�Ѿ�<�{b�a*MwfԱ���O_�g�2��Ej�]V��4�X�*��g�S0�K���c��A��T�P�ݏ�`~�e?�F�[��n�jX�nر�U��5Z �"��p�ss���41�@�����Gi�<J��<{��z���ޢM�}�a��!Be:�܍o�`-�C\�.yk��$��exdz�N�H���(���_����!�KF���otvW��w-��s�L�>��]9b�	�Jn�)sn�t_���_xEK��D� ��B	�$gY�A�V>g$�%L�0L#��{&Ν��Ftd�\��P�=��a4��
�8"�<ܝ��s�L^^N���Ec��v���H-_>���֋��;|+�c��!�������8�O/�.规��Jn�8�&�,���%�s�t�]6(k�H6��Fq#(ۉ[�y����{��0(�^��ֿ�b��ף�Ŭ�����������&f��zCqI���<Μ$��((h\�ED�C�������c_�x�/��E�.:���i^��+�Ο�1צ��҂Ji4@`l�xN�L$搘6��T���.��?���4]�X�1h|}g8<1Ȥ<�@K��/��/��5�p�ל�o��t��p�a j�t�bE��E�y��&Ц4`د���$�L���"����Jvi��l�j�Z%=')��8�e���`8�T����*�M�8���.������w�~��\(H�t�vr�"jDo�GG
�i���lHe��%ia&9�d���d>�-i
�lM�ܰ��TA�$��VHG|��
�$��:�1Rs\�Z $�Pj�ۇ��]ً�g�8`簆 �zߒ��V�X��ݕx�rtX/�A�p�2�^[1~R{�뚬���ɇ�:kCU'5n��%�'�CXP06G�ۮ��l[�<�N�scOFeQ��-�gi$�RN���o7�Wz�
_t��"?�z<Q��l&��B,5�"�}\��i^�|}��R�����l;$��ѻ�'dxw��A*�ͺ1_w�f$or�w�V�$
��T�Hi�����L����lVc\����7O슚��ŹR�D)�]��B����=3���qF�MM��ȓ�B�g����
�OM[�԰`�W[pBΉt��i�\��`�{X���/)�ƩcD�R��Pvz�x��49H�_��ه�#�1��&��P�/��֡��&�U��u���)��l9�Э�:!�}ɑ�=[�*��;����u{����.��p��"�!��,��|v�nN�K�63ud>��6����y/H�}���ё�{qL���$��
��-���a��[���st�nS�n2�ğ�@���ѷ�����xHNp�������2���&��3	�����f��x�)�WP'h�7f�>�� �s!�;�p��&Q����cN>OgdH�E�1u	{��^�گ�V�}���2�@�J�H�S��>!~��L�^d	��r��5/��GyNW�-�`����ɚLJ��=��(R�V2�ȏ�M;�:�-��A0<Ȥ	L�1L<F(�J��L��Cl�Y���N��_7�:*�\8͏�w��
d5'L�����H�s5M �2ID�%��WP\pyr�~��ҍ�)qN0�E�|)�(�@��(";�JGZ�!���U��,WL�#E׬�E�����O5.K��������Slso��z�d�7��ӳ;%n<�5�*���iu���?o��mI��"m��.�XL���F������r��s������
8�!���{N�c�yٗ����Nf��2�!�n"5hU�F��J'�d�B�2��sv5�	�����C�r>~.���ܤ�kg��LinN�d����u'����f]��B�sL��A�5S�h�K�v�vn-�_e�9e�V"m���B:�GΫ�x�c�ZX
���o��y����HKgT�~cN¸���OZK:�b�A�%9C	]��o�ʗ����w�1��)(�t��^�?��u�Ʀ�-A���9�����9N�لL����#�A2Yu����5��/_=fql��j���އ���ˡ?u��Ar�Z����]�A�X _�v�M��1V��&P\���6X��2��m7䥱[lҏ'�A��Q6R�S�Q}�딭S��e���S\D-wLrTC]�ӎorly�݂X���J^fo�-���˰��(�X3�R>\�#�	9��VP饘QՐۑ,a�e���X�#�*���gV�Tnq���GL�(��Z)�o�M�i��!#Z��H.��$�ɀW�����\�p���*ȶ��/��.g��y 9��L2��p�(�#Z-)i�����j��jԭ=�0b���`n�0�a]�k2�I)�X�E�8f�nD�η�%8�CS.�o��ě�Ng�'d�p�-��J�=a���Y<l��Ǡ�OYdb�Hl_LC
^]����o����>�ɹب��Nk�Y	��Ե=�����f��N���H�^�����f�<���(|�E��(SL��\���>�u�4vdN��~�HN��[�nD���eh/ڈ(2�1�he_ʔQnV=�C��H�E��gi~�%�B��15���czŕv
�>a�Y��%�e�&c!��pIB
�8г]~A-l�64�1���/�[\\ZI�
T4�W���aa8'l��xRY��N�e��j3:��-:G��6�v��ad$$`�M,ܔC�z�3�!q�1�����]Ӌ��n#x��B����l]��K�^�t����_@Y�u�gS��k��]�OƤ�&v:��N��a�L�ewɋ��-hY}:��xi O� ��x|+^�ñ�Cq%��]{[[�q"�	�x@L�upՔ��j����-��[=�����ئ�\�e��jq[�%��^W���'�Hj�y�c��%J8�Imx���=�C/�].&�w4�D��,Ƙ��3���"�z���`�U���
|M:3Qc!�_ǣ��W(Wj���q��S�#f(G4GޗI>�����n�ڄE��٩����^�����˗��<D$>n�HG[�M�'�C�&�Ǹ'o�rUm�����N��ݾwJ?��6�\A<��N���ZK5�D�)����Hi=�i�qlS��:�B2�&yY��^�bخu}�Y+lc��Z�mL��%9��s��̪Y�O�1�ߺYD2L�
���ʢ%���c+7�V�_.rsIq
pש�� >�bG�Nz�Ž2�q�X��D�I��a����'H�V�T��으���E�t�|��G�3�(
oOtrJl�s<�;���3)YQ��`gw�8"o�&��7>�cѭ��^��@&��t�T�}g��$�}��0h�h�)�GT���s��y4r��
 o�
M�H;Φw�~|� !(���������ad�"	���-sQg#�,1M��|��/�u�h�R���-�.k$G�K,݅1a=a���YP�A�,q�%!�
ONzvN6�^��>��ƬA�v�J�F�ӽ�)��
/���ުl̒�B3GM��'[�,n\��\k�ѣ
m1�hm�o�>!����jM0C <����埵��ߎ\������`K|_xN�`ǀ���pWJ�jHL�M�<��_���=����C��M@Wޅ�%ꉷ��dž���f���%�Mn�p�Z�3�@>'�M��d
�Y�,BT��u��J�:����o>��b^չ�ȑ�ދGx��_W�`�H��"=�ϟ��z&=�@�%ӌH���qi�x�DH�Xx�jꄯK |@QT��P��+�:u�c�}О�T�����B5�ڨ�81��hȩ����a��Fu�XLc[�nNרxtN�D�X��*N8������s7�|����2
�R{>}78��.��G���yՂ��Og�#�Q���q�'�g
�f����K�Y��`�9�h�2�„�6�$}�� ��(�T?��}A�`�7�8��LHFR�G�
E�FJXw!S�K�r���@EKa��2�'��ʌ�%v[؟[7��S�F�j��j��[5�h�Mt,���^���i#��Co���q§�Z�e���t��e�Wi�����p_�t��^*>����Vlh�Z�Q�jX��B�㨪�9�q7�@������'������[=e��H+^ї����a/�G�6�z�<�6)yж��DH�wF����v�2nF�)%�d�����.�)��ەP6^÷r	��{�h��<�L�?�Ih.�����dht[$���]	��fŘ�9&4.�;�s;�B�����
�k�����~�>�j)ϰy"T�㝼j�MU��d΂M�ݱ��[��D�g4{+�ݝ���:�<�9q���A��w	L}��A=£6�۠ev��Au�+U�_��Q�3f�?���R�\�0R�
�R^ �,���V�w��W����2�`A	�v�G�<9��4nX;�?��?�*uV0�����{[4"��΂,���qӼ��<��RK�+���k5�WxcF��PO�=*��;E����D�~��:�	�m\A��p�����\XX�d����+�Hk6��Zb���WsX�/��$_��Q��Z_���hh�L�u|��8�
	���Z����}�IH�:ƋoK}��
�a/-�k��xVq0��r��LC�_�D6h&軓S�q}pߨ�=��~38���^x�Sߡc���8Um��e~7����VUZ�:�vƯ�[m�>���?�
��p}�_�gKB���_
%�_�g=�Ih|.ݥą�V^1䓺0	"{��7��m�s�9�ꛦ���B��N��I�p��i{
]J� ��:M����y�%��u�����G��Vց����kk<o)�{<O�GJץ�xCNj3-˪���W-739�Bƒ(T
`�P���X�i��wQ�:����6�)"S #�-��,�"v	��\��d~n��2rr2Ob�6�[�T���
R�Kc�Y�犋��4c]�>����py��jp:G]�Z����$0
��_�N+M7�Y2l
@x��6q��	��4���59O�Т�}T��r�f5��2�k t�߲�}�p�U\�ur����sVl�ת�a���޲�
}Vm���~3�gm���,\7m}�-���*�,EH�q�$Yx�=E���_V'��C��R�i�ND��9���/Cb����x��@8`�2I̪,!���f݄�nE��8�b�+Q��2쪘�CZ^?G��Vf��砱��(B��Ie�+�9��:
A���
��v����4�RB�H �z�ѳy�|�x���֣�W?�E�t��FO�ܔ�c��=��1E�$V(T��}�rY�!HhQ!.F/
d���իG���0����;j86t��������	8��y��QG��/Z��a3=
���O����_�ؤJ��Pג�I�Rs�Z=��|ڼA#������#�su��曻;.�����.t�ש:�KIT'�6���m7��"�:���s�b�q�yL�@Z,Y�	bg����,���n����{O�;]�ɪ!_�"=c�Ӻ���dij�2�G�B�X�$���|��i�!���*nT�%��;�*���^3�/c�E��s�4��CwLj})���<(��YpHw���W�^��HL�-v��p��đ@w��Пp�̹�U�K����>1뷀��L˾�f�0p��Ύ�=�_��!	9�q�[���ƭ��t�-c\
�	@�q�]���CAJ��p�Pao|y�lN��{F��*3�F��xLTv���0ԛV,�������jH�A(\���x�����xtP�
���R�^����S��h"�H��Jn#_p�.�$���s2�i��B����{T�uZKt\�LI�%���*���P�={�b�"U�Q�"V�R}	>Z������ŊN��Vݮ�-�J��hσ��
�^����;��FQ��,*+�"�"�00)�:;:V��P8*e(7�Jl�����0oHe^Ɗ��y%�`��4��Y�[eX}�6K�J˩���^#<ɝ��I�_/�23-@�l�4��`��P�=�K&=.)��՜XvL���f�o���BG]ޮ��+��؂Py��I�n�V`�k-~S��d��d��cU��.�gƗ'� 1N����0P!��ί��H��]Hf��[�Z�x���\.� ��+�\_4b��Ov�����#������v!�l�,�x<�DxIN-F��e,/�\m���d�Py��Ir��ǐ&$�G�K�K��և1�q�zG�!����A��38�̍�97U;ȴVe�g ��݌�L��ΐo�tp�R<s��k0U�-������=C���C����WjA����Oi�ퟌ��il0Gtc=T�	�u5�<ل�'M�>#��
�A�D���䶅�)�m�"Ǜ�X!-�Μa�R�����_��});�;6��П�(��o:֔�qC^��Ǖ��۵�A=�z�O�b�	�d�~���������hz�n/J~�ǪŤzS�,J��J#2ŭ��i�Z~_�{c��]o�bR:�v:��?e?	tZ]ָ�ՠ�gժMk�&�zz�q��%�UCW\Y�ڻes���7iv����Z�d��T�V�Q�C�$mČk�i�w�ƿ#��;�̋�	%y�G�8@5:yq)���|⌬N��=������Bց�^\��S�8]�]�?{��rW����[-�+W�q�)^2���-��KK�0g4�LҼ�&O��SP�d���Ş-m���>����n�x�QyY崎b��y�CQ����A��)��B��D`<`���������7����%f"�Y����>���ШG]�T}�_�����T�,a���^&xԠ���,v�4�EpW�¶��S�A�N�Ⅽgj�)����&��d��5�4��(���$���sD�Bݦx��O�h�XQ��L�w��`�q�nP�sT�s��'@�Tz��,�2��J�*njވ�4_�}3�����י�j�ҫ-�%i����
����P�O�F?��kjS�#�G�'��p�1��J�m�b���a[�2��?kKq��!��@-^Y97�*��o0�i�M�l�=�ߺ��������(�7g���_��Ǚ�W�أ��..��
�p���k�����#��c]@��q�o�s]�vK��i]�C+�K6�-�/'S���{V��F#pƦuO&��g�z��u��t��xeL�.��v�s�Mf�џ@/��)�u����A�)0!۽�)/Y���_$mU?S^�	Gq����Vċj.v���UH��0��mǕ��*3����bt3����(��$F#��P�hzZ���o��\��d�沠pmL�~�Ljb�mmK���	�qsN�"Q_Qh9�	-��㳟CU�џ��O�=ކ�y�5��Yk�����N.eu�i�#u��ڒࠠ���p�*��!��C_߻3��Q�p�azm�g�-���	�-���k
8��Z��莧�YP�d�M����`TG���hѤ]:�d���VN�vc�W:w��|kҁ.:ӫ�O�ڑs�w pT����%z΁ه�*�0)��A&3��PPQ_i.�-Z�!���%�Tt���f3�k״�+��f���6������6mP�яH4�ׇ��2��
�umMCͥ�pm*Y˭���9�_����J[���.9��&��,r�H�i߃8Ʌ��a������[�N�n��<�CrxL��r�J2�vc��>x�	�����J�#u��:nY���}l�z�Ӯ��^Y;���z��Ӊ�1�`7z�v/��_眓��{��='T� `Jټ]�ȇU�)K{v�[���՝y�`�-0-�?���^����[�mSƐ�=�O#_D���q�q�mR0���)�
i�bJ��}���<�w�o�a�6�[����^D���Zz`����̶.D�K���=b�	����b��l�޲w헂M���7dֆ������#wQ]!���˘��g1}BJ�9�����Ԏ�I��=CVR��%�L�MU�]C(�+#O�1Q�dj�2��~&�B'٩p��c�Q�4�1#���qʸL��̮�L�➒��GZt*j�I�`��Q���/�HJe�l���豎���x[0�D�֌1�STK�af�;���3`L��}�{اJ&5������J�^����G������&���x��%n�q##�G��7���p(/8����ʶJGy���8�?�����+>I�����克W�T�m
Aj��/b����YFNG�uc����\�����:�i%���fU,p�I�p ��^y���B�cx�2�����
Vb�6N�d�ٍәT���l�W�{tĈT{��S/�Q�Y��K���7��#��pQcGo���g�Q��G?e<���t���J���8�3�Y��ި�F^:�̊�|�ʚ8`r}�Q�hF�4�뢺j"�:k�2;k��.,�&��z�TIF�Ty�=�K��;�pr$�Ѳ�8f_��TIV[��[�ź`���.N0�U���8IY��
�D5�7�o-
!�mv9��\/�KR����!���6���b��\�+'I�e/��a��Fzͷ��{���P|�w��4ej-��t�۠^�\�SK�+'�J�R��S�f����4��Ԗ+�e���"Ӄ�j\��ʌ�E�.�>p���!�\�B���}vچN!"f���R�0r�G�߻�*�� ����/J����6�M���n���~��}}<��o���lϸ�p�f%��n~��W�X�U�lA!�ˍ!ӫ��8�iD*�z3��@��EYo�J�N�C8f���,�R	�Ə�m�w�E��(�i�wL��e��7�xЬ���2��Lz� B��,�'\n@Oޤl�o<i���YU��ʣ�:�8��p�u��Z�8�&>�s4PcX�Y��������}t�p�-�	��yC&��z���
Z`7�)�<i���6Oggtx�
hTI�w1a�r���3;e����0t����Ysmv�YE����{)�K���Yh�&�ۑǶ��X����>T)�0�jJ���ׯ�$7
�����۷o�Uck��w��Y;8��>���+g�6w&$�>ނu���>�
�VZ�J�����g�˿�=���>O��i�]@����QY������O�����ƽAI�N%F(��Y�9�9��J�C4�Q@J���9��u�3p=�0A��1
��,^�>�(��HR��Bx��Lԇ�j-���a�p3���7ub�NV4|u��砋ale��z���J@��5���y�C�Q@RRq�O���</�&�IG&-p@_S/�mn�����c��Z5;�<y	��/骞P��e ��������P.Wk�Y�D4�<�A������NǬ��i�D��N$�7 �.� �+�gI�g��:�#?ḤPuG�q+5<(��ڮ-H�JD����U1&g�ξ#Y�#}ă��-�s�<I�ʹ�`�{6p�S���uA�mm�G�p<��s�Oic0ʶ�u�����f�5o#������.�o]�l�<(I�Ֆ+� [D-���d���qꝻ�)�<UPqyoQ^49K�#	*���%^��"Vv�*-���s�y1"N�!�4��\U$џʋ[��M}�ߑO�r=��K-�
��82I��+��(�Ydmh����La��$U�T��
��C�(����' H(x��
��=��<XU��Q�����L)FM��^�>�¼�p����1�B��j�*�O��|O�,������0�߰�ʹн�,u����
�Hs�5��IJ��R���(���+��F�L�?Fh#~J��1�������p)O"�-J��q
�Ƀ7�u6��(ۄ������!P@��>Á1�
�&'�s3�ه�X,�9Y�|�s��A�CEvp�|̺%��3�7�_*xC��8�
<�"�'"G�����!�£���V�볩�s�&<6D-m�������t�t�z�q5��"m����J���}_�(^�m�'V����s�۴F�>}*s�V�Ӈ"����m��������9oq�����{��o��!<�]w�@a�#a���Y�Y}i����|#�r��\��I�_ߙ�W+��"푎��Nܞ�0�|��9�8�ֽ
.�yf����n�sˡ�b���~p*5E#�s
�vN�9>�c���QG�!�Ú��8��Њ�y�6&���-2�~Q����[�aṖ��о)5�����_[��z�_i�t���b(߭O��=�C/�����P4?9�T�,�1��լ��9��"�f���P]S���Ԝ(0v4�s�Jsb��nQ�{��}�#�@����ɏ���U����^��R+�/6�'
������Kh��-��F�s�5�X��ޖX�yXQ�3����
����WK���b"��&�â�{�[�m�p��Z���ֶ/ʲ��Z[��Z-l$�N�e�WHW�M�_�
Vӧ�x�s�䀱X
)���o�C&�6�l�ktIp��].@?wS���h�s-�$�9��n�P[������p�Y�ӲG�:������E�t����b&�<
�E�_���p�0Jtz�X��B����.R��
.E��Ď��u-0OSBþm	���Ǣ�����]v��d�`��ÝX�P���[
��V�C�4O�������0&z��u��4�&��E�ʙ't�A��B��%�+�DˎG~A�x��CPKZ��n���Rg��x�+��i|�o�ʜ��8��o�qJ�`��G��~��ɕo P
�8�yuq�뢵����𐠵�������Ռ=ƶ��T�·n2p���aA/�F[
]+p^��F���(���?ɬ3gg���Q)���Ċ�DLm4��G;�?81�[ѫ�T�> =�Q8��)ʒ�5��ck+gdR�����A|�v��a�kBcz���[���C8�^'�դ���O�S0��* )�5r��|��Ȥ��^�?�z}�[�SWU�����T}��?L���U�^����}L	�6h�8�
�b�ǎEڰn�/�M��A��6����6Mk<��u9�o5)?q�	#�019u�A.�mX�iȪ�fg�Q���Wo�g�@��u�;�	�o#���&�o4�O�:on��M^���;>��r�0�.'�}�)X��"�9��O����~�.7@3����_~I*���`���֣��q���^Q(T����ߠ1�``��w2����u���Փ��أ���0�F�(zc<��mL�hc�-p�:�|m��.Ǣ�VfhJ��M�~� �[е�}��r��2��~��wzJ�:Ս{�s	�3��xԺ�,G� �MKd���v%b�o���|��l6�z	^aCG;zVl� |_����m௷E�ZQl��Z��>g��sSo���l���P��8�C�4>@���e1bς���	 ��z���F]�5�Qƃ�/Y
�vAfG�WJ;��=�yw@�R���q�\kK0{2tv�0="w
0�N����r
�D�n��J`3�7�%/-�*�R��.U+�[l�Q��7H����0x�/{džq���8>6F��'0*G\�Q�a�$;�h�fEB���C����-`0��)�y�[hʑ����V�
H2�pC��xQ�P¥��9�>&zgိ�*�+kɼ�'���W_�~I����Pg_�CO{b���̖���aշ�N�� ���
��~A'�/I��팟o����"��ܬ*0w�����K�OLx���i1�M*ˀzܗ�{� �m�eJ�!,O'��Z2N�m��:���ܢ*G�`��x]sҶ#fD\�����FI��Hw��]���I���?�7#ȂU�.�5w5ɮ�R?7�����0�:�3��np&9&�Vup���AFs���Uc;I}�!\��Uv���}��b���z:���9y�! R����ξ�����
N@)�0ߗDd;(A�Xr�[B�N�a+��{��?X����/��Jڽ՜v�ݶ�6�lҤg���O%���P
(�/V�� �j��>MT��c74bɤ^�~^�()y�I����Єe7a'x�U$u8���/����N�Ψ'n���h贑�51��;�^n4�8�ߖS�q�F;� Jx�����]�]��Y ��MG-WM���_�	K���V�gGg����>���W&��i�&
�əۣκ5�X�n��F>gla�⧲�0���x){���8��}>;|��9	i� 7?��kN���W����� ��A��P�Ej��p�Y�rҊ���J�p7�~V����8��o�?������� ����3#JF	;Sl6QA�i����C��fT0Y�w�I���+~��[��kB��4�1L��[�*��;/j�LAM0X�}>������.�tغu��tj���iZ���6��)���u�d���n�������?������
�|n4oZ��8H�/��h�!��}�I>����d��	�_�Y�3�rD�wc6�Z���K�ج���A�;��T�� GXKb4�p:I9��m��{#?{��X%��C��KM;���E�({vT6La�Y}�j�O��ѭT�в�`u ������J��ۃ�2f�1��D���/�M��R�1�Cb� @#�^$yH"�c�%߀��.Mt��B��l7 ��^���]]]�*��e�g^1:��	v"t���2��=M@f]�M�̟D_��w`tј������m�����uJw�"Bh����O;��ֽ.��w�3,�eJ�VKm�C2LCyӝO�L��U�{�/\"����K�	h����	�bxZ���LR���i�O�(=�|���V}��)�׾��[[��P�[����n���2�6Y�K��	�UL�}�W0$ڃR:���O�3Ij�(ΒRօJ���)��������H�I���n�S�(�g�K�p���2�\���oN��ya軚����8�'��p��%�K�EE�gO�[:*�׸�p��ⳇW�����F��t��!W�o�ڧ�"�˲"Cրo��o��B�J�d��;'K͒�__���h�v�+���d�����ލ�� '������V���m���I.^�˅	��8��B��s�f�G0�8�ռ�*ʮ ��꩐�Tҕ��c��6�s~���Jim���xY~��V�)�I��ƛ��+��h���Μ�;]��E���BAАQ��l"�U����,�C�)��'f�C{�KD�]�p#(^�����y�s=��=U��jon��lVe�u�iJ+$��d�U�#�;��O��
	?9�2��<�;�q>o	T�r�x&�
[��'-�x�p�0j�[�;3�Iw����6N?;��<m'*�xD�?$A�ʂ�8�f""0���ZI�;�� _ߢUcGk�"�#�+QE	��p�Xd|ĭ̧�!x3�f2��[��F����K��oa���K~�۷R�6	�Y�cj��<��L]��%���TS˶R�O��Wöbc�£�e�P�}�S���\��
��T���u� h���Ыk��.x�{���zZ	JTo�;�8��H�����P^EsT
'K�@�����
�t��B�%Fj�dC���ת
o����@XV+���z.�T��"!"�����B����F�.~�_��ac�a;��
�;%#	O6�L��=B
dX���o�
�ߡ�s���L�!.�A2�R�  �4
����:g�_�*[t���S*]��6�,�O9�3����5��ؖ#^��l��m��[�e��П��W�
=�68u�P�ݤ�_��
��M��p�"K�}q��fn�V}[�[�!q�e���*`g if��|T��/\w�G3�	��zC�Ulr������QH�$q�}r`���og�՚g�O3�=���+����ƻ��{�N�b��-p�g[r�:�􏃽����~Df,�!�>��K���9YR2��v�r�D3��'�
��K�gՂ?h?�r_��K&`t͡񟞉���y7��&.�>�t��u�4�ߛ�G�
���:�^M�pv��wڴ�Yz~ڇձ�M٪�!�RW�d�;�#��	^�z�ʈ����Q��t\�Wy�\OJ14��:5�\���SXT��� ݓ��g�v�V9�UkX,m�iM�\����(n��>E�I� a���I�i�_��,������(�
;.s�)�=5�A�I��(��wX�g�}4Y����Dp�4��{�jq(Q
̷ZJ�U�Zf�K��*�xC~p"�2��r�#�$!�J��zZY�.�^|h�}���z���Xa�I���E�Xg�t^4�R{��f�L�y�p�ᚚ�1ި|�O
�2��5�"�t�U�A�ޗ�@��u�R�PN�X�1�ZN���/�ܨ�x�����IQ�×��_�y6�EK���� /������ cuD�o���7դ�	���|2��V�C��f+H��
�:`�w��i��y�~wk���t@�4OE],�<����ͦ?s��b1-��
�J����A�������A2��-=��t�칙C�õ̍�:�
�Ba�;�W�CE�Ξr��{�`�&��,'��t�����[8�q�u�
-(�J�]��4
����ʹ5���ay��
hh�Y����.��4�j&���4��a����q�'(��5���s�X�G�jWB���~����cm۶�/��.6�a�_A5���+=d���>Ĺ_.�h����8tB�s��0�HJ��l��l[UH4�v.	��>]�(
k�9.� U�A:,A-���w�yʰ�҉��V�jVU�^���}�|wTH�Ә,Aq�0;,�ZD*��#{���l�H7��bRX�0C��d�uBѢ�5�d�=�V�\T=�Q3�7o�qA̐A���O��l�ܿ���!��{_uDG_���rk��ߘT�^���}W�o).8����|gWP�Ce�J����x�6N����(�~v�_�;�Ξ���S?���W#M�˿��^��S����mG�
θJ��Q50 �i�<�&+��;��V=�K�rU��
�e������#��,�t��F�jë��Γ�U��|N'uL�����x��&�)
�6wrroG�4
���L�R��	gn��Za�����#t+2�>if!ϥ�)Ǿ�>0$&��q�����qJY\���I�S(�ˤ7�^+�'����w�ٚ�ze�!�e��-���ݙ{��a��wτ� ��K"�Jd
��Ly"F��ջ�P�n�)�ж��w�-YU��6L�8"�!ѡ��|�F�j=c��Ƞ���E����R���z!�<�nU<�Qc������o+�-`(|ɍ ���O,�tcR҇�ӆ���/j�n�@<�Q�g�����4�6���W=Z�ڒ�9���4cK���&{���}�8#Z�X��WUU+�QG��Q�����3,��/�%�Eo�����އռ���d�7z}
#O�t{yD"3����K��d��� {Cu7��'�
C)n�0{�4�k���(|	u(5��u)"�|�V ��Wr���e��n�n���XW�O�{���Bu�WU���,2L!�(�K}���=��	�[�MP)�s2��l�6%�j
#\Jg1a^9Q�.���F�/
�
y|x��&�>z�|%%N��{�9��c׉S'I�#�ܳ&�QF��n�๕��!JƄe�e�o},��X�M0c�s9]��e08u�x���޾�B䦂��@h~T$�%
?��-&�=���Es��nϨ��f'$��Є`9��w����vȒ�ߖ���$sNy�7zԯ�3.ɉA�>��c���,v��A���?p-?�#�G�v˧�hm,�Qv��G�=KԾ	��n�k@p*�;r��Q���w�Z�*ړ�Ǥ��� �3ν�եwR�-�`Qz\�ӧ�v��c�<�s���*)���%m�gNܦIy�~#��+U`~�U����獫l'�-q�'��֣����h&ɚ,�B�L��<�g�MIM	٧����@nf��\��}��do�‡���[6[�B$��9-��R]Ղ��T�}�uA$�+�eҢ4�k���v'����^K����6
a;8d-x+���J_�u_2΢G��re=�?���(�����w��//�(�_`�5�w�/�/+:X}�Z�X��.ruȐQ����W&��eUs?�z�N��|jj_�Mw31���#qJ[u�WF�x�Ԏ�}�y}M�r�.)r�1+��)	�Qn�"|D�U)^8s6���c��#���A�;}�/�
��	���?��K��θĻ�G���Mg�i��9^#0��;؎�Jb��ꘙ��#�<���M�z}tum��k��p��aS����� 2�p.A^S1�_.wGao%7�,SUW��Օ
7�md�%E�=,�P���[Ұ�劚���l����K�=3�>h:pZ7ן�g~��#��;xD�t��O���|��tҺ}��&Y9����ƮpbuU[]���T���ι#��U�Fo~�y�ե��j��`a����~�.;&\UB�D����<��j���5y�уo�)]���,���+�]�*�D��89�ż���mS��T�I�9⺹���"����_KKgh��&�\^a=�X���(�u`��mgO,�Ӊ�h}����y�$�ے�$�E�[��b����\ڊ�xl~[����l:�鈼�,����g�\j��gY�	��'��&f)�GL|�ƭ*�Q��pr���~�;�Z��I]��
!<�aPB�I��b�CUxЏ��Eg��C�(�<g�d���РrM{LWҮGh7�9�W�Fɜ,sR��ߕzH7�zϙ�FrcHK����oS���Fa0��z���h�C���:+/����ҭ�[-W�� p���3v��\uq�GG+ԛDX)��'��&M�uƗ�Û~E��ވ�Wp���5J�pGՠ���0��_�ԍ���qW�Ę��
]5�x�����1�yu�&��8Hȏ'��;��@�<Q�v�8�����uV�<�ɦEY)+��tn��|�߲�K������3*����"���ޫ##���
�ЎN�i"MC�F�Z�uT
���7���y\=�ц�ёc�XY$*�^�IN�h�q��h�<��쇢��[�筆��%���UY��A�G�8�m^��s��u�¶��$6	y�7YVP�߾���tF�(j�:���ڸ�$j����{w%ph�B�L���\=@�"0���4)U�w�' �O�w4��#��N>q��٘���>��0S|�_Ae�g�<2�8�@�+�5�	3�gKp:���E�L�Bv�K����j�:��*&z����0�V >��G�X�CJ��I�O��Er����W����b�$�W+�^j�ɒ�����ϖ����6�H�X#18�ˌ5����ԋ���`�֩�wG�U�,�03	�������̵1��Q�&���g;!��]v�X��~0�a������	��\�M�����F4C&h� �V�Ӿӗ|���怙w9�}��9�/��H�Y����1��˚�W�(�u2igo�}9�~!V7�;�:H�	�xǗ�~㲿��vW�ز�j��
�w�$��kʪe���1Z^�W$S�+ļњ,�-�3��!�cm�h��9����% Q*;%�_���8�FV(����s�߷f�8d�����شgm5@@7V։��!)���^`��#m�܊����G�k�!��y�u訦���(+�q��:�­�D݉5/��b��w������b+�b��ᎁ���6�}�H�Л�m$��te�1-ě
���G]i�ܘ��$��Q:npy�s�ǩ��B��q8��H�r-;�-c�N�*�r�J]c����G�Y���ucyUk�u���DQ�)��:4^���K<|�XE�ޚ.Hx�r亞�j�Κơ���-�]��eU6���x�bk���_lo��Ⱟuv��oL�zA+�$^ҕ\w�%>�[�P��G<����2���<�U����w�����+=ܧT�2bwݠwx����
�ay�#G���t�s+�s������[�U�Y1��n,�,(�4��c$�U�S��9���B�%�Z�H�\R�׮��m�YZ�,]�KH�[�E�ÿ��/l;�f��
�$�6��![aB�r���d�Z���V�zoْ��n�H��K�VU�%����)G��B�$�E7\f�YֵT���
�Kg��ɷ;�7� w��Bh�)�k���4�����\�r<�zu��t�S�o�?(#�"�*G����<K?�'<i��T?����Zm
l��ױ�k�ưC��d�	@�P�J�����uU� 7"C*����l�e����A�I����̮BZ|G�~ۙ���Q����ec)XH��#�����k�����3��KV� =[����X�_��ߐ���W�Co����F�x�#)ȁt8�6�]��H��w3,ky��ѡx���,A�׷	e��#��/��t�su��#���8������;g̗��]�[�d`�o��A�l��g#� o�@�^��vI�C������k��r��k�Mp�Ԁ��K���mnJ�6���!�	{�zQIVN�r�rE�Z��p��W�w([y����
*
N�C�S��!!�أc�����-q���UwJ�=j,�������l�[^sM��u�;כΧ�:}�Ҝ�	�	qg������cNh����T�v�)W��d���]�]�*I����n����M�:�2�ұ�ux�v�>����F��n�D!�$S�x8��;����;�(���~
�Wou�\�Ht�*GĞv�:��[�L�r��-���y�G�m
k�-6K�=�9�D>�Gk����aD�l9�<j�U�r��7����j��*�Nl�����)8�j�2��b��S�-a��s���4d ,�`�8j0_FC*�6���*�[$_\ q';C2lD�I�=#��:�Vp-(_��Ha̹$�$=w�#mC*A�1J��P�%�s�d*�:��%	}���4�AR8������zø���=�?Eu,q-��أ����÷���,!�p��N��:��Ő5��V�I4����?>�*K2����J8Os������P"偙�bN�%�
�p�xc��N�&ay�{M�lƪ3#L�mN̕&�>��4w��ՙި���|3����}+�e�}����_���,�,A�L��u�[����ϲQJ5�'z���@Nԝ�Z̉�ED�@�(PVdl��\8N�&,��)I]�d��N���Y8+�ʞ�_�w���u⥊�8�#��+�1d�8s6����Ǭ}壯����Uy��fc����+��!)�Ȧ��1���[�N����}3ǮIG��u]��x~�^�ʔ�4
���qd���[>�,{�1#�^3��ID��=�q$�%�ɥ��:A*��Cg
R��@�B��H���@�!Tn���w�l��˭��a�]���ɬ���z5����{z���1�R&��l�\Wџ��g���EIّt)���8�R�Tp*YM�ڋ�FfR�8V�Y�bJir5Fč	N4e�gH%�<�ټ�
��n�j�c*v��<᧼ /���U��jao.lG��vA�vP���ؠ�Z�j����9�IdA��v�Ɖ<��jO��3��j�5�Kh�iMt|��en�*=-AB��Q����׍.|�"?��Ïs���\Z��%�g��t2^L�#;K�0>;���!���SSI��!!��H�>�S��|�B�ϵŵQN�,$�,J��,��y�a�>A���"T�S�M���K�����"�I쫈�+�;;�Ӽ�[���5��*^�1!��;m�--?wb^e��Ci�O{�*���N�C/���.M�s'������f+v�S�'�̘��
T�kO�H�L��T�pR��s�#2�Y��@�2��N�6^T��)u[�>4(n#�*w�²Jb����$Ȥ��F�TxM3,"&
�ܴy��Wm�����k!o� ��	��,˒�e����6�G�G\r]U2%��8�WH��
C����Qo娣�)���*�[zb�2�n����ʹ�.CL?��g��l�2�\��#�.W���Y`�WG��>r8��e1����j��B����
��U���q8�`{l_d<C�hj�h��|�v�o��L9����g���䇄�b�%�&��h� �x��L��){(fo���P�H���~l����8� -s�3�(!���Ckb���er�
A�E�H��Њm�q�ؠ̮�x���+9&V��HLa������jK##0c�e��[abh�@�/9�����Jy1�MK��:�5b�oN�K�T��hw���Q��	��)坁�(
�i�Ƕ&p9������F�d�I���S�z��Ԣ���uq�g�ݴ�VD�Z�&`�W�::�*�^�!�V��p}�����a���,?���8��晛�K��_���7�g�?�r�W.U�[���c�>��9)\�<����r�.-�^�
�BtR@�͓�f�8�w��<_I���a���Ɵ̢��(��C�U��/)�\R�~���?~ۨ
ÿ�dZ��ZەGƐ�����rg���Jp_�"}�Ie�g�����̒6-G�;����K�>�$n�����+��L�[��o�"�N�>��e��Y�f��C-��\Qz��%��se�g����@��%��� I���^؄������*�Ӭ����D��<�����!��0�O!
�w!����ޞ{����D�S����r.��~���B�z��+�B�mA�*�+y����(k����w�_�3d���V��y��4/ܺ��Y���hs�v�zJ�0�a�p67��X��6����	��y�n�o���}l��k�n�r7
yyh�D�bK��S�OR5p�8�.T�a[��Y�hKHCJ]c@�/�s-`ϼ���E��a�Gk�Yr�ʇ�K<�E�e��W�V�RP���t�G+$�д� ����R��b��͇P��TE[j҅�
���*���NU��Z��{�V<�����Q�����w�*�?�Ӄ7N�s�O��	j�$�0`۱���/�N�K�]ϫ�]
iZ?;:w���<����7҆�҇��ߦ�٨nV�wl�}D��A�%�yv���+�w$,��Xl>�/j�1�'$Y�F���\��(���AЃ�]x�i�Zk���$5��U܈�?Z��N�:5�Z��C�'Z�ܤ�}w���~HE���VN'�O:�R��|J%�ء��C.^��ڎ�`��g͐(3!��a
�[0ɘ»#��c]j��)��`��rsJ!�*j�c�f`��o�+�
���;mx���x�� �2<s�5��@�HT�}��^��P��:u{��P'����/���>=
}JKo���
a
��XN�-��K�;xL@@����a��,�����u]Ϻ��U,Y�;I�a�˯�%y��\	��#�2"�d���aE޵>P�~�?nŠv]wZ���Y׬���a)���3�3t2������T��۷MN�6=�?Cݹ�ސ�d�}1�y"9�gV��˚!Z1�qz&�W��w��-f�R��C|K�>���'�cwA?`6$,�|C�kٝ��0�->\�#�˽�����5K�Li�Tom��\[کNJXu�}ꕵۡ�x���[@4�u�	�g�����@���+�"��R.AS�T�+�8S���3r
P,qݕV^�f���b��ڝ]d|k�
xtQ�ä=�:�qC/Ѿ�K�6�9@�̦��8ۃ�)��6m�k�ϋ�z{�v����C��G���v�̠d���
lC�ȇ�`�h��r�����.�S�F�m�إ>2푈��n��\�y
���3�k��43b�?��s�Nj����T����%�a�)���2��}7
��� I���
}A6m�"o'�iLI��I5��y��?����|��Ue-�Ң�hb��=Ϫ۱_�*'�{��h�3r����y":�U@>�q��|J�!����׎���72ZΝ��	]�p%}��,r	�T���āe�u�1't�̖X�m�٩X$:Dl>�O������KX[�;���4E�h!�BA���j�Z�<|:f����^�O��h5��a� ����K�����u����/bz�t��w~�8i$��oo��t�^3Q?r��Lˊ�f��o��In�H���i�qUgg��)Ӈ�i�-a��ui��4,a{� n�Y$����H�kJc��J8@�t1A�y��8�RQ�)(�
�qr�<���'T��2QUE��T�����ԫ
���*D<!�⥘`��]�0^ߢ+=ǫ��I|	^�O�ax��'��D�TSR<=�O+_.��㨊����d��'��	tl�9���e5��,ƙOv'zz�{�S�]���x����j
D]�âKqo"
���M~���7��*5ׯ��S�p�E���B>WV-J(��YWZ~]�^��oP�6{
�[���=<ozQ%��g�fx��>���ʤ�Ɣڗ��>�����!���C�/�9���ky�y�r�L+>;��ʒ����[�/�	�f�n��>�O<�1�#r��y�w�70"���a�YM��0Ib�8H^-r�i�
a�޴B��7�N9�!��gI 2�iOB���*{Ȫ!�&�F�s��S�����mt�*V��ch|��ʢ�&E=��E�+��BJ�&Q"/q�d��"�8Yn�����$�:����W�|�8���a�%	�F������~�\����\� ���=��w��帙�"��i�4��}B��W3�߬���[o4Yf��"����31Doڔ��r�]C���pϼAyl��k�7S L��j��
�@�>��s�%���0�)u�A� �9��-^{#x�/�ަL[`�0/��(��?¨Y�)�؛a
�wI{�d�dC1������ڐ�G�d�j��<����R��0�*eYC�NsI(~.�D<��ouwϪ/۟EP�q�{��cۉX$6����i��E���<�-����o�mp�V�tX�b�K�ͻ���/�mjh��o��2,;W�́�x�I�gƭ،90s��Q�NO�� �HP�1�'�gK�,-���"�z2��ט�m���q
Z�(Ez�QNe�sD���=Ն;�,c�P�_"bpy�Ik<Ɖt�,_��B����-�q��� ��ܐ.�_����h�"{��g�G�j����y����;!X�;����C
H��*g�r-��;2I;���d�T��X��%\�fT����ǚRs��m��-�/,���;U��U�����v-{���=�nO	9���k�U�땐������(�ndz�Ii���P_�
�k��a��6d>*;��	ڻ�{�V���q��S���[�B�O�l]yW��MRZ�$.��%������qj"�̙��.��9*����H*�:�H��fc�Ep��R��o���Q#"h��tL��\�V�	���Of������}=Q]��L���H��|�<l�%��C�6h�%`t4�5{�)�D�$�C���W2M���F���D���p����VI4e@� ���G"�����S�]}��ۅ��M�b�F�)�Ktݸ�����Mq9%qc+���9����sf�
Ѷ����b�!�t�Oe�
�^7u|�P����^g-jъ(B�	q
7�~���?V\x]�oF�og&�w5O��o�,3�۪lLT���õ��Nn�U`z�\T����d��S���\��k��+](PX����x%2��_�垘�2g@�E����g��Hj��t�M��M�6�FN�
�c^���ٲ���c���-J�D�_�.+�LQl�O��d�`u����;��֦U�b�h�+�}O�]�����ډõ!�bh�	�����y2/�$}-4���-�����}��|�~\��/m�ڈϱ� ^�$2�͔�5#��\�P\�kX����txM�)ƕOl�)^�V9f+�ts�j���˗##��x���?g�B�P|�Cv
޶�q�?/�&�����yt�g"�g']�OIi�W�vd��/����n����)�0���P#X2?�Bdž��)�5�sb�b{t�c�zc�7�U�A�Ԓ1)!��(����S���,�4���H�C�$np?$�=��i[��~�׉�����YX���A#�_0�����j�%#J��8_���f.�����-Ί^�.��'
�du�����x,=r�#�e������*AZ��݅�[S*k����촀��HN�T��%�E����v�A���c�R�Y�6��d�̻�Yܲ��������G&�c�<��o���&�l�wu��?LHZ���n���M)D/�U�qֲ;���;�
�쏌���g������)��ݢ�������yw|^~d�l�&ɾ@��S
�lև�΍r�S�Z�.b~��
�~��ey�ye���f�i���S��ԑDT�����M���O%�,%d,�L�=�B��-��1�;,��{�}�,Ҝ�=��s��n��=ǺOI;�$���p���'i&k��7���G.�����t�0�r��
'��b\9��r���
lgjO��-r��l�c���7icm+�!�D�]���a1=Ѥ5q��l��l��գ�%���ґ�j�	G�dT
�v/��	��#����N޾�^�x���B�:��W�ڼɏ��E�vR4q�U=zjUdARK�]����hl!�W���uB��
m(c��'
He��t��o{R�}$oEb��?����ˬ�A�y�f���C/Ο�{�ֳu7z䒏���XG�v�����-W>���_~�kϣ��񏈔�v�rți�&!�*)��rI���b@�쪖%M5Нs�!N���=�3h�%`�U3����yV|���p��k,6��խ�]+{���EΗ\��^����yn۔.*Qz�MO��տ��D���'�T��S\�0�WU'5���:�#�h΅A%�EZ�ʜ5b�Ҝ�6M.�^q���Ӷ�X��(��1���]l���(4��A���Ң�ۋ���VXkv)^ۚ�n6�e�Q�~�q`�a4E������l�Z{!����e�ٹ�R��fm��wš|���N�wda{%Q�	c�y��g��R�����A9z�X�BN�|5�ّ��O��49_w��9������.���f�o��(�D��\EPl��~�P��ˢA�'��Ǐm���� |��)�]ˍ��1��<|`){��y?�J;|Ɠ�=���J7��M��MA���~we����H��b^;+��4���T��1纲ѳ�'ZNWR�f�Z�x��
R���}�����E�ڢu^���}�
����=ּ3�CA�lC\�'EΩ)�.�b.-��GB���؄��HA|ZE�y�˭�y�H��:��$��'�X��v�3&�y�VQJ/����I^����	�'4Z�Y[}>�ēn�����ѭ�ţv�To�w(�kxǂ� ��Կ�^gWzۼ�r�1k
}Pc�.f�ŝ��L@�^�-��7�pj�o����rͤ�DⶴppKt��r��U}�$gmJt�AP���v���h*ٲ�͛-���Z�v&�dH�j|4�P�9���?]]zw�� �w���L�����z� z�����Щ!�.+',z�b8����*߮$����jΆ,��7�bC���o�/�]�E�h+��#PN��:
��<�D�S_S4;��LG������V_�!G��8��ʜ%���gq]�wX���\z]�B�W���λ�z��TS�v��l�������V�+#��ᡜ��������L ��W����ϛ=�u5�f�]�Y:�5tgq8hĢ)����+��<5d��P�:9�?tun$�{`�Y���?!�&]ܳ��p�a���R�<�ұ�nk}�DpzawY��$�z�:�ߓ�Hz�����dY�Gj�a�r�>��q͸E@��G�4�����+������5|��"�E@������8�x�y>�XqI��3%�4&���Ueѣx�ޜ+�V[
W�?�$�U����7���H���2�ܘ�m
�&�{}�3�}�������`RU��=}ii*��"Q:��, !8��6�ܤP�'�T�s���rvw���MDKOx���inM�'\W��	mF���f�P��O�V�
	��\����`���%~�J�JvCm�8�kv9�E��g�fv�G١�w2�0�$�-�\��I�MD7�Oۺ��rU��:Qڃ�1<;�	-���:�z�^%�q��B�ZK�QD���{җ�x�oe%�*p�7|�-t<^�xأ�bT��*n��}�ۙo��˞�(��ﴲ����\���^(�Zn��3�f��Z�,2��:����"��n�@{��8,�-�^��wQ���R����E~����'>�@^U�>���W5��%3#X�5�"߶縵�mw���#,�,�C�8閅�W��O=Ļ��H�7��=ζ��:+�
ᓞ(N�<��n"];٬�D


+�M}�Y`��*L��vl �q����Zf���u&��-��A8�M���������6u
t2i{�5���k���
	�v@����Jgv;1ph�Pu�2[�p��C��Um��
�^H��n�|:�}���Jt�8��2E����l=�U-�ӭ}����0��s�	.>Q����x��T��a7$�m�}�;aÿ�mk.�4���7���Kt݋�B�{����Z=���+�I�����w��oN�.��R�"k�O5h��a��C�K�0O���P�$�/�{q�u[��_f�_".�w�y$�8)"oX�;3�4Z'��G&���o��5��gȬ	[�푂p�x�$~VlYy�?A:�O0O.?Iv�{��~l�z]%��x��դ�1�G2��
ͯ�4`1w����^��"B�~��<׎k�h�:���&�9D�ɗ��@	�I���4<�l�C"�`��6���7Ћ�콀{�=V�+��
`��T�U0딎��s*Oʏ�tj���y�2�Ϡ��|*(Tw�l�d��b�nQ/��7Z[�i}�hím^��W�L�m�?�,/okkX�Ft�����+�-��{V���X7�NFd���39�ȑ�V��{\��o��o���7*:�^�.f��=g���
;:uP[�u�+�Z��P��ϸ�u~({��������R���ʑг%�?�L��'m�O#��8�x
��$N>�|�ߖ^��y~r���׮ۙ|�,y-�n��Q�ߖB�N�"n���%;Ts��B֭f� =3�EXX�7�W
��s	��i*(*+"AC.��ڥ�+�:����WR^m�SQM��z+�.� �sS��!�F]��bZxL�}N��N�
�$��pgv��E��mA~D���Ph#�.�0k���㲧�o�n��?��֭l���/Ox��$]��L�`.\(�P�+:rj{�x}cO���#V ��̥)�:��f���(ý�Q�� �ǀ�*��[�յ����~�-`h��1):����ҙ���n@-��݁�'>c(�����>,����U0�.Q����/��sU*�k�ޑR1&&;{�=<�	Q���dÅR%����R�	�����F@"��z��EG1�M�}<*:Q�5	��zW���՟���D��Kj~�_������[#������Z���/��9XMF��ۇ{��7�ș���ک�����+�h����sDf!!/���y��{ܸ��=��g0<���)�8�4�T�Mʦzj�^K"��$L�+�܏�!^��\*��d%\��%��N��s���$���Z��:˼��&�,�t'U�}�~�#���
�\���ɝ��/!-�mY�V�B-Ei8ɷ9���2<��S~N	K۩�p�'�Â���*�֜�wcWF�c���K?�ZAJ�ƺ�p7Է��b �i����KL�`]��gɎp$l)�q�����ҍV�B�C�*c�K�irz!�3�ڇ���|0��F��
`�Z�B�Q^��z}"!թM���r"�[�R���M?����� �7���	�dLdH+X��Tp�����;��߻W����3��k>j��W]�[��т�QT~�79�E�<�r���jO>�3�Sѧ�B0�n+�\q�\Xh�;ed���I�x��6�>� ��XC���Vr�pN�F��K�|99QP�ba-�~
$�GnX��?:a.pf.!®C�f��߄Z$����
���ݞ\؉j����rv�b�1��F4
%B �B
k"�r�,$��$��\�7K��5�s��n_���+����v��� ��P$�ϩ3�/��x�>J��aw/��T�i�X�F�N��)@��ԅA����K$r>�G�nc	Q�R]
��]e\C w^�ʺ�𑞯W6ު}LB|��ұ���61�R
��pn=��b�>@k��D�R��ƌB�<d�D�OK���gzJ�2�mo��zMnE�}EKG�W�䷔H�C�	i���3��<I>�MQ����n�h��5�0�qb9jC_�~P�o��a��ʀ�1�>bש����i�v���63u_��;fj�/1'y�9�D8�a� ��n+.Z��fq��>�Z���T��Οά�s6����
���w�V�@)������w1����`�h�	�|Zw������U��i�a�{�]�"��5�X� �M��DXfl|6�b��3��Z=c�d�dž/��bWO�����g�L �Á^�~Їo�;Lx��0e�_�Z��,���Cõݷ%�"����({���>��9�6?���������C��`/���}�G�(?���Zi�	�6�m��	v{L��3�Z�[a��x���'�96!��1�2�'�p���ͥ�[�˔�)�)�L@ƙV~+r���2��ʑkk��9�Z��	0NG����2�5r�aQJ�#�+�Z�,�O���h�O
�:��X=`�O��0���ߋ��W<�N�;��{[�����e0�^�G���ݬ�-{:�&ܖ�V�O=t]����4ƏKF}1Q�WP�y�@O�~k��[�+��c��D�����@��k,�UB�#ű&�rC��e�,�/at[XOd�Ԛ{-�@�a�i` Q�/�
��B�X�I�HU�,}�Ȥ]�Oy�,�����tGd���.@�뾄���}�ۀ���9S�U�W�!O��ҕ��`h��?�/�=���
 �o�"���:8��A6VK�#��X�����Iq�q�K����y,Ѹ�:^PAu~���[��5���<�`d��l2u���v
6�5b��ǭ���K�v����o�����
�o��
Iѐ�8��0���M����	S��N����&Q�%�����x["��:�v�EbJړ�0��K"�`�G^���!�ܾ�3#G����WT�b�Aý'���4I��Io��5�K@�d)ƻ�H9eW�`��p�[��':��q�\}���4=�@D7�Z���w�Y5����06���Ә��В� �*)����z�G�S<.F9"��Ca�!z����[�~�P>��ݴc��ZB��b�4l’ٟ��s���ԳܻY���j(J��՜�:�qZo%9" ����]c,:�Zr�PA<�@p�/�"����
��g�]�[u�o�W�(�AǸ3aI�L/��)^j��_��s��;�_"����K�Y�		mĄ�"�oj��=1H��f�Τ;F ��
U\V>��{��9Yc6J�?x�̀W�0M-��7�ؙ���HrV�2
��I��<�����(�����
5uywjBt����A���֏o��\e3Y��L\�ʺkl#s�s���˯�G�b�/k���BZ0��r�D�h�D�q9�W���z�C�8 @���C�4������.7��U�{_�\���_}#!|z�(12�O������d�@�C?�x7�N.?y�jvGC��Ҍ��"�ʚY�lC�`���2�'%��b[iܫ6���hLF�
�HO]������
�M���"��U��1�P��
[���9���������X��
�|U��B���� S~z|.�4���TP��{.��b9�p�y�-�~^z��
�\��@J��X`n�bDWpk9_c,:�2�Ya��FμҦ׭b�1���DLc�a�u"ҝT�T�7+ov�z�Ӏƣ<�n�siDw١/�ţ�����3mW.�{2+ا���t�b��J���c�"��9����ʓ�����8�lɭ@��Ѥ̤%�>i�����O��������~��}$��f}e���]�Է��9��9y2�6WL���u�SMv����q��9t�)iG׉��0���6��G	-0I�#�u��1��}ŭ[c���z���6WŁ!-pi?K����8�'`�PCrr������p\���B;�k�i��~8�߯I��{'�D����ʪ�J�"am@!�B��S҂��� �?{���łk}�Mq�W���W�,/���R+O��C�[��Yw3|c����k=}Q����c;Y�4���������ed6n���گlc`��,�ɩߤ@7iM��=���Gs��4g��%�rG���p�H�C5p�#��S/ڝ*���	ϓ]6��}�N�x����������Er�P?Sr��b���O�{Q��p���h*L���b���YS�n�
/�BZ�;}�m~9a�4����-�h�[�����͎ϭ�J$�1��N�&�|'�c�䬥/ʺ��&᧥�,��/�94�
�g��)^D��/�P"�܈Edӽ&S#��pK���D��D��
�Ț���M�9B��4G��e@�f�~޻;a~�WOk
�CL�� T��|�;��v�)␳aH������z�=lyN��S^���xG��0�f��x!e�Ƹ.�9����\(
�(noAiO�@ut:)�S�P�U6�&*��B�v���pF~�[����@���]���J��a0��dT�x͊Z�С���q0.�W2v���1hd�-CZ�V�A@�G�ñ|g;��=E�4�'K<�@��|��4^�q	|�\���V���1p�%[�#S���#�F����#��-�C�I����̥�+\),�Wyy�:#��s�Q�����P^<���E�/�P����Ny����ߞ�?)��e��S��b:	jw�na����\�T�]n>,��Jz���F "穼�ƹ0-���h�����q�(B?���Z{)���6{�o���ݔ��2WC��tˋ��g�5�T8�����,+O�e0HU�ܺ�vRrA�D�
��6���ř��!��D)n:��nc	�a��=2�ݫ��ws9�O�Y�V@^��XI�{+���#��b�����W��y+@%
��0.�{�'~{d�z�r��/�ێl����L��*b��d�_����Ec�f����a�"�sص�-	��v�$�95�]�&,�̋�P��L�Y��$8�>���=��[��w�<*	C~�$\���Y�Y7��W$Y���^��q�F%E����A�W�Q�7�{����EH2�C�)C��u͔��.w9A�Yȓ�K������c������d
�Ị�<����w��TPN�wb���ԡ���"~H��6�6�_�0wnDKAAN���e9������iFVg�?����#���|�����ּ^2�|�Ś{�A&�X�|��[QhY�^���oG|���#W*��fe`-�ޣ�\�6�i��˺�.tu/^��y���kA�������/�˙��5��n�nמz�]1���Z[ϝomV95˅_�6�	e^�^��!M���M���H�чVx]m$��Տ�KJM�4F-��oQ�C����2����3q/�T�]�)�<6.jxo�/|CA^�[cB�2��|A	�{o�1��K{�2A`O��F8��;��' ��9ƀ@bR�]ʷ�q,V�o�<*�l�^�ܫ�QcT��_�5?$�U�0_9׊ f��)��C��ץ��)���י�P�["q,6��
���<sZ�mNv.
���.'��
Ԝ����}9��P̂�$
���h?���˃2=��+.�#G=wO��G>�#�a���cd$�\�ـ����ݻ���g�y�Z�g��v�b���Էaz8�{ț}Bh�A�{mD�����.��'*K��Oik;��D �#�����/h����;�@��±
!��+�ګ�-�c�kn.���v�$?:���ܗ���b�{��az�K���ޣd�GkyVֶ����Z��ͥ:��'Z�sg�.�O\/+�i�.��5j�>(��=��>��v
��w=7\�4���߈y�~)��qNKs�s~�9<��k
��{d����o�Þ;���Z荄��A�R�4�vríḾ�Ѳ�ʀ���&�_>�p<a\&�R�_q���o
@X"P]TU�0y��v�v�w��t�]�U՗�i��<C���i�x=c1v79�(f�
�M�k�ڄ:�'ڪ
�I���`|y�9D��5�n��U:�C+/>9U�F(#eI�|�K!����l0��36��n�LG�e*6Ne
/ˌ�Ԏ�Ūjj՚�w����e��7r|т���֔������讞��
�A�Z�S�Cr
֔B�I��nt���~�-�#Z�V����v��L��Br��"9ŗ5���9��8V��x�h�_d^�:�|xmW(��~��
�M�y�+�)#%ʂ��u�����~ޯ���щ�*���K��X����<���g��7|`����z��H0���ikY�=2�����n
_��u�X��GWVҹ����Y]/K<J�Tdn���Y���JM6@��rݍ��N�bj���D8�| ��'�+^�j��t}���΁�bFAGĊ���̃��/��c�D�;'f�{s�)y��'�	�K17���E��m�蘷Ҕ�k�<#���ꨏS�I��V�:�	�e�8Z�(t i��@>�8[���4XL��{��J.��.
5|E��^]sҝc�C~���L@�!=�I�uz�m�ʐ^��IU:���d���݌a?a2h/���i�y�;��nQ����o �(�����&�=X;-�?�vkC�)���fm9��ҟE��f^��-MזJ��=�4o,q�˒�i^�X\lX޳�ۓ����{-:�������V{��??�&��*_i��]�Ţ@����T~�9{��U�p��M��Xא�j���S雩W::��@V�Vپ��=-��}_e���y{�Ď�^�g�if�h�j�r�Ԯ���0(��w90���{�T�,OT�<~
����>ϷXVX���8��^tΪ���/�����y
�F&��$ZL����ȏ!D����Hn˃8�m�����L����:�d�J'�!c\?�<ƶ}���@}���������݁
"'�||�2�_}��W	3:����}6)X�.�邈�I���e�mś�[�:ޝ��r�m��L#hd ��c^o����;�6��a�!m����L�S���
>�n��N-���j'�9BP�B��"7�%"���J�<��Z���)�
}�B	�[S�����gԓd%���7
�O�M�mf�Z�dQ?��8k����
��8V��jW��{z�
�5�zՄ���ff2!�]�J�7�����3��Cƅ2P����,�Mw��ǹ���*)��5H�����% s�9ҏt�I�TH��'�~�ic��K�"�~X��=~KH�^�!O�q&�
�"�^���S9c*l`t��12�2�Q�d�@���Z1�N���[
:����H\��t܆���Ce�S�S�R|D��XECyd�hp�9@<(�+�����$̙4���;.9댋)5��d�e�s׷z$���U��f����{��<&�v�$���b�)K��W��T�����R�8Y�j���'��?K^GW��{�o%8���dw������J�g�M�z	3.��7S�[�^�n�?�ԣ��l���C9�Xd��C?��5{/�����{/���{� �2D{D
u�wo����̧���
�Cj�c���T�#Ț����y+L��@w1�����c�@�]��?�|���K��9��d�X�����e,r���755���뼼�ِ���\\5A���	�7�	�[��B�~����b��s�^w�E)`sOrя)eަlCZ�@Kg���ߝ��z��/mi�M)�|D�R�ѿ��=���/��|��pzW�PC<��x�u=(9�m8m؊�-LW��.n:�Z}w杠6�
w�$"��O5��t�5����Nց�;&̢� '|^0���R�.�T(|$p��Ȳ���!��M:�
toTĦK���MH'������O��|2�6N�5�k 1J-�1�YYs��ViU�8o��fYp�s�*�l	�/�Evs2J��/�?|��Ÿ�F�b-�VAcF��:���l�l��{类�.K�M(6MYW��,3��w���Ec©Q���<
���CT?�l�7UZ�����*��{E��ipCT�4�c)f�(1/�Z,�O��,��T�eE��C���kؖ��K�,�KH:�&��#H���D5mrH���?3�Q�F"���D�Љ���6��ŷP�>���	!�Uq�u�.��f�c�^�t��X�\ZZ�J��9V]�бو+|�f��q�,��ҏ��A�_/儘�(#� :�Γ��k�Q�n��~C�
����<�ϳM�f��ɥ�$<;���e����ڤ1%��i���EUg�q*;�R��1=X��hW`�VU�r7���.Y"�q��y�W�(�M��&��q��ψ��b�)�c�����Anj�I�W4y��tҝ�1���Q�܃��j�	6���W!h�d77�"N���˴��:�C�M\t��i1r��[?Ѓo�{�TEz�r�	�6��k?Z���Q[���7�/�����V�{.�=ծ�"�+����9=� K�Le,`S��w�9oW͡ɓ�l��
�_��G�׆aR�0��e����_ǁu���5��X2��k�>���[�:��k�ї/7:�YÒ���+W.1Ad�e;�f��4�����Y.����H:��^����θ`"<�H�W��G!�u�M�,�Z@LT7�cC����ގ���
��>�7%1��$E5��:D�kP����2r�@����5�����ݕ+�Z����f}��G�
7���R=�4GOb��T˷�
��ώ�#_�w�Taҳ�j���t��[����H�	�-ys���G�d�h�Au.Z�54N^�����R�ӲG�2Qё��\I����>�]zP����=�>';��r���?�8D�x[k5j�4I�T�U	�W�0�*����hڬ�Fg��LRg�X,���cA�!����*��}%��s�Y|�{�F����+���u]�$�_oI�r+sź�v8��s����R���?,%_��'N,�8+ ���kħ�F�gd/$[�5�'��Z�ǡ)���A�{P���
{�2d��fܥ�C(���QU�g1�r�\;�H��b��b�τ�����e+lI�"�"�Ӝ��
�.�?��>ik����V2Y�r.��6�ы�<�OF}K��lc�+$�#˧{ɘ
6S�9Ґu����d���`���*�ٕX���5�=��e���ou7~�4�-�x��f��&�|ۼc���;¼�,�Z�_ݥ�&k㯩���\&��cwF��c렮7��ؔ���WK��]�}Q�Y�:��HA=r/KuWT�7���Voi�������;�Ս��+�ݖO?e������m�+�9W���*�3���M��u=��-�ZR)����Q�v!E�Qa�(9�P+Bv�{@�E5�*q�]?�����vS���!W㐸�7g!�N���£Ir��WO���ԇdmb���W�B���M�!��*I��>t�3<Z��o��30X������ܧ�?�y��I=�5`ռ�4�j�M,��Cy�=�o݉�TpGX��Fo���~U�o���+ZmG��z-�V-���;z�i���ʁ@�5~c8{���n�PL�T�{���+�<�T4��B��-ܾ[�@A��d/y@e��A�*m�hɛ��03�N>�9� �3��D��˓���ʬ�������y�*{+�I�fD$5w����[E�G�e��L�e�ur�H����1�����T�~ΧtWyw�$vsj�f2(�d���F�g]kSz!~�']:4`�lyi1�Yʸ��7y��T��)IJ��u�� ����^��ճ�ķ�'^D��v������IwN{+$>�|��ؿ�z�Fd����a�����O��bDL�{̬��o���<5|�ʐ��-DI��ߚk���y�BoW�+�o���^��'^N?�� =8\|7rp0�~Iq��X��������3�
X���dyz��l���0�E�p)��K�d��BĔ,�D�K��Ξk���m���?^$�fRd9M"Q��%��ƨѣf�H��ç�]�9_R�U��Aq�}<����=�^��F-ڋ�V���욽Vq�*ĝ�/s�r��������u!`D����[I�w�=)	Ek�v���kȿgou�S�,`����*糣:�g<�N����Ͼ${֩ڗm��ߕ�˻:7m�L̝VP�	���Zo�x��\�b'C��L}zq!=Ew�
h8���t��[�F3Xc���Xru�.�$K|�3�b��8���r�ҋ���?Mzbި�A�ԧ?�k+Q��=�JZ;T�gr��]M{C�}BK��&0��F~~�Y��:�P]�\��
B���T�*&��,F�u�U�y���`H��n�
n��
F��|�K�ln��x��\.���H|���Im�,�i]�&�+C��9�DZ���7�+�g����Ds��>���������mb�|{�{q�Ouye�ڬ(+7��oʈz0'�#2�VQ���ǗM�E��}�
��LK�4��~�I�:�ֲnj5'J�e9wse>{hP��g���,��f!�k���土^��Ɔ��l|�w�u|Ñ߬�<e��͛�ԝ|wZ@O�iP��	�l�ns��S�֔���L��|���Br��%I�Р�u֡;E��R,���Mj7���l}�-[���`�p���ɮ�0ف.u��I"uCC6�L���N��-�J�b�;B�!� ��~)����4dn�dNj7s�'�E	o�9J�	n0���p�3�;����̝�07*]�R݇�Ɖ�C�� ܙ<?��4���?�{t�q����������b�X��ݰ���e��m�7��	�	w�v�C��l�W�j�m'�|[d��>���D�Q�x3Ck�p)���e���C>��Ԟ$�2f=����:H�h5ڢ��hF��L�,@��:�����E��~7��BV?Q#���3QA�.јڬ��xW�uj�T�a7`N�"�*�kKbY��JD�:
��,T����3sq�%̓!L�ooP�M�Z~8_BU�h�2|��H@�����m�Ej]<��m��	wFɇ�|�![��$��Q��#�z����T�֞N��6�		�讎�HNb!b'r�V���!R�n�&>w���w�������)�rR`�><\��|�a� 	��+��Q۹o���=b$Jh��ܒ"A丄�uu?�\��hG!�7�˽&K>��p50�E��*���~#>ĤR�>p8%�q��{��}�#��p����q�Ϳ�fOG[pVa��rN�v�
@`H�r�r��UHk�έ|z��g,t��Q����ͭ�Nb��)��Y�0G�}ws=�?1�]�Ο.:����X��ӻ$��V�ލځsw�/��@�@���{W,}v✥"Ըz����EIIK�U��ŏIe�P�`��fq�4ꒀ<Et�\|4:C(zm�;n	�ih07��1(�XX�b>�y]%]� �-"Փ9�s��zRi� 
٪Ӎ럤1�!�Sj�3
��^��-S`Y9����%̥ʒ�>�2�.�-}�pѷ��7��^�-R��2�U�[��KV�^����j��]�N牅�a��"}���-��|����� k�2a�^����!b)-D��*5�7ho�Ѡ��J���?\ζn<�o��Q���0^�06�%g�>)�f��U�*7���U��'��M$+���6_7	Ԥ��Y�|j���ip��UzǵA�������[���.`�{f�"[ꨃ����H17�0��u eeɲH�k.���a0<�bGQ�Ji�%��_�+!���}W�jۑu(Gkf��EsF�/�r�yy�#�X5�F��H�Ʈ5��Y�e��8<�1g휨�}fP�}�,-�^_�J��Ϸ&}$��6�vƸ����e���o�0��?�
{�d–�"�+�=����*��c�y��xy�Z%�=vS#C��9
p"8*�^Zx��7S�͊;���s���_"�̯i��#'�+*�q2I��yl%��E����^[Ɖ��7�8A�-�4�㋲�.��A�uF�EOZ�a�;R3G�F����~#�ž�T�]\{jg�W�X�~�<�pDm�E�ݭ���Q��G�C���=p�$sC�T"���Y�uG?��1zˠx��i�v�5:�h�`��亟#�*�����,����f�#>3e�Tu��u+(�l�:��*o�w����Q���ʑ��GwE��8���w����U��՛�n�K�-� �͎K�M��r�9�]�ay��+��2���p+ҹ����x��?�_Q{��(Ƕ;
�-!��1FR9n�f��!������?n��
 cD$=K��n,P�Yg��xq�ͩ�'C�� 
�}�G�%3Cg�Q�Ӝc$�n�%lcf�Uˌ�N�^�ޤ��M�-�'KV�Ϛ�9�y��e�z�bQ��ȵ��ƏxT�R�Q���5~
^��u9g��3�f �{��&#T��u�H�8%���2t�):�N#�s�??%��?05����љ�T*�R��g�)Sאy"҇SAܻ�錪�)q���R�K=W�H���=��.(<���>L}�,�7�汫�Ǝ��P��� s�+�fI��X\h���;s�b)�.V��Ħ,��|pU����YY�
��}�0ӐT�z��q�M�eRp���-NS\ �.�]���H�d�v�i�dK9}�dqz���K�5�nX e���5bF���6�ʍm�C��@;�?�{R,l�=���p�e��(��FM-��c�<�:G�Нn��喊����&R�aRV��z*/�ҴT�#�H6����v���#�I�(����V!QҠ��G���߄�+x�m2k3����zU�35հ����2o�~Gq��r�v �����*�
��[Ւ�C�[~:�m&��$�4ij��B8�4|���؍pH��r���+ƺQ)��؂�I�
�<Dmh��	l��H�7Iy�C��j�����AG�@���^�rUe5��ôc�G#[!C�"J�Tܻr7+LUʻ��|%�#N�M�6�t?&���B��D�o��;�<>��g�H�S��ba-ui-��l����/о�0�\M�}K�?�FdD��{=�{<ԍ���^Ѡ��;��|x�݋	��]94j���Fa��f�|�l\�Q�!�r5��3L�c6�?a�a���5�c��G|�-����ls^���8�%�6u�O��9�Q��ǟ��nXIx����4paܽf�ζ�K~�?+2yIb)��;�(��J���Ε�FH�����+�*1&"ɰ��ɍ���P�a�%'o�f?���cO�O�K����8�Vz��M��é�cg��֧�6Y_}�	�o��m��+zgT|�VQ?'����"�x��R�;gO^�L��8;��q���a��ߘl�Lb�L\�Ww�>k���~[gwk��:��>2}Z�B�{��W
,�w�&�S� k��a@�Ը�?�6>3����n=)?{�2���������H2,)q��H`��ޕ�3jkTĞB���?��Qm$%�)�����}bU�q_�c�qY	-����_�1Ӂ�)j�?���E=7>��-9�6�l���.�� s�x"�h��c���[��y��7�?�N
-������ T��K�����7�9�|�Ѱxz�j�gmh�I�n�H�o�g)�v���~����
C�;L�Jq�u��p��mW�<���˗=l+(�lCP���m-�[I�H�HK(��|LQk�g�ª?C�EBx��}QN�"��;��FNU��cE�\k5E�G
н�^Jv�<�+��Dk���r�K�C�N
�w¹*�{�����Ϛ�>��j��h��É�W~{�|�k�ÿ��$a�=�����g�1�iz���f҆M��m�� ���z`��0X�*��+G��n�� ?J�>�[St�d�>)�`zdM���+�9���,Z', į>cu}n��mĐ�N�=�z8$Rգ�3�c��1ME��K�Y�$����������
5�
�]Y<z�(�����:�Ob�N��A�E�5إ,��/��-���D�ʰ���sU�2
b�C=���(�F�sU�;ˏ(.��&��@÷?K�*ؕ�1���E<�
�|g�<�%u"
���kC�D%ʫ��p�zE�]�h?�*d�Pg�\�R
D�ć�U�$F��&�i�橇�Z>^=xܠ�KHUNy����xU���q��Y��d*�gg�mnL�%��r䰼!�@��Z"��["(�͘pf��k��"v���$�ρ9&L�I�Q����V�:���WIZ�k�7��TT�!�X�52Q���I��e(�Z���P��
b��}LL�ϰ�:�.'���T/�k�S-�>���l��T��5�}T�r��#�e�(��S�G��:�'Wm�P 8��oV�V����7S*��6⋫��-���7k�I�5P|-�w����S�X�����-g���`(�T��zI(j�aZ�c^�w.��8��g-�fV���]hl�3.yO�u�2&������8EAD|L|Z�3�ɡ���2�]�ۑ�5�KqO�[�شܵ,Մ>�k*���j��sέ�	*��Ѯ|\�A[
��T����O��=5�@'����z��=]Z(CGE��fM��8�G�W��P+q�NE��m�F06�8Z:b7���-�Ь��%�{��Ch����1��^t��m,R��\��H�T�Z#x�㮽���`��Y�'���}?����}��iou8�K��P1�����㥙夆C����������Z�"�8������@x�
µ-�``�Pj�}6Ll�R����U\�6[��CZ�����N�"��*Y���=3C�Ⱦ3���ڣ��x~���,ce�G��;�,5�R>U�w�6Լ�SAR7|aq��u��^�ځ;V�`ۼ<��V�����V�HɪE-�3��t9Ʌh��G�;��~V�n<r-˥������V��?�%�asR�1��>:����{�~۔x�9:�7N�+m1����f75dGr��z��ZFݬ(:��%�P�
9�G��a�xLI�rl2}���>M�n?��K�wE/��:T�@��Y_���a���^O�ME^3�	����O��\��������s

_�^��9$-�Q���5��y�'��m��s���с
�c�v�V �I����߇�!?�I���$7�ܡ�\ód[�#���mH��܁���F��&8�$*����p��w,意�hiḩt�-,6�i0��I�^�,`�Ś7��{~�5Q�R<?OȊc%S���(��D<�Cɓά����*��r���W/�<5�IT���,�y�P�	��4�M^�V˿�׏��e?1�M��BO�P��<qBT}��6Z	|.<��3p�G�2q�Zoݹ�p|UNbUqk��w~m��9`�L�E�E@Ka}��!,��/��p���7���b�� ]��G�{�����O1�R1��
;č��A��&���u³F��?�m	��]��1���ϛ�Gg����돾��IY���ƃ�#J��j�aZ��z"L(�Bz~Fq���i�eU7m��4/��u?��@��H���	D�B��L�����0}*�X"��J�Z���
F��b��N�����@FP'H�fX�DIVTM7L�v\��(N�,/ʪnڮ�i^�m?��~����(N�,/ʪnڮaBRic�0N�n�q^��~?��yd��=#?��j��ߴl�|�`�p���B�XB�+��J�Z���
F��b��N���q ���$
����")�Pit���py|�P$�Her�R��huz��d�Xmv����z@��H���	D�B�Y��`��.�/���L�P���No0�����p����?_ �%R�\�T�5Z�!A1� )�a9��d�Xmv���x}~�	e\H��u�Ӳ]n��)�&�q!=?�8Q��4ˋ�����q��uۏ�s���I���(Ɋ��iَ�A�I��EY�M��8�˺��yݟ� #(�$E3,��$+���e;��a'i�eU7m��/!��m)hrYzb��3�3�S�H`]A�Mx1A���>]���5�j��^F�i�T\?8E|ӕ��_�e��oH{U��Ġ��T�&L�-3�QW�n��Ԥu����M������*
ۥ����D��+�%�j;�b�ͮ�' Y�>
(؟�4��w�]|���/���JW#Ȥ�Zca7�����B'8:{�} ��N�$�8�o��Q|W���� �mOnL�)��Q^!W��CM8�}:N�hۑc&4ٝq�o���_��@�xމ�ɐ��5����
Q�+�t�*\��]�w	�C!�W��^"�yw��n������e�/��R�=�`���*��5b�J����z�MwZ���N	h��PQ�7޴���-�␜�E��g�����C�29��*X����YK�Uk�&D���\�4����]�aw�-�5�&_kD�@�;���I1f�ͫ�{�C�[ŏY}E��xd�S�9ɇ��@�~��$�`�K��P����K}���=�wv��ZR
?P��h{�%���Zdϙ�'�bi��ys-KhO�ü���.�� [4/%0y�]�|�(��珫D���Bˀ(�D��뺹�"�c��fw��8��Ng�P�m���zd�o*Ģj6h�n�i[�}�iY
L�ٱ�E�f�9��eF�8�d�ǣ��O�k�@�p����#B\���'Mo�=�)�
uĐE�B>:��6Qlo�����6��]�Z* �)�
˸k�ֿ����� �/�d?6�
Q���7D��x����'ey:��K��CaM�۽�T&�uf��T����x_�����W�D�){5�PJ7�A�����2��wW�q��o-C��g*�����te�
���j^"�~�4�{;fo-�W�?��*w�W�1�{���|���k�.Q�Z"�
X�-��J��/~������۵�dp��;�<W����4�M�S��/��+�En���ش�0�;��=��N���{�3����!�Q)9]=$}���޵���2����K��Pg(۫PY�)k�揚�f�,�}�eK��fh��#�*�3W��A+�����xv��fe��+�+�,��fTr�~j��)	�[Tn����*��4p��]���W1dz�%�f��5*y�����W	��	@Y�9~����Ë���Ʉ�T5�X�ٳi_�q# �;�����K(�56�9L�FQ�/�R���L��EE&Rz��O�EK��-�Q}Y�kv���
������qsOLc�G�2�h����n⪻� :`�֥��$����ǘ7UѬr���_J�Q!wJ������:6���m�纏h�%��b��4����	�T�M��_�3\j�z��Fs1g�.�c�b��G�d?2RY`o��;�����2u��%�{��^r�)`+�v��۳������7�Fs=���CuC�{�C.�=Z8kV�Ye���`�Ԯ_Y�ꓣUu@�i��R|:��^�y��%�����}.ӀT4O���.]qq�Z-v.w�e��i��������o���:��f/1I|F�b���D�X����CE��?{���U�-Nx���0�w���6�~U�~}.x�����c��f�!�6�x�>�}�WAD<i��3��״)�>�|Qķ��~������X���C�����}���<A�>�������6cT���;k���#7.{7c��8�T����_���4��X��;B*bm���#"""*��RJ)EDDDD����̛?9��7���t3Zk�g�с�hz�������t&ޯw.���Y�N�ˋվ�gH@E���!�6����~b�rݴ���z��]DDDDDDDfffffffVUUUUUUU�i��{z�����6�Nd�libs/better-framework/assets/fonts/better-studio-admin-icons.ttf000064400000032454151214002630021122 0ustar00
�PFFTMyT�5GDEFk4� OS/2/�L�XVcmap�;4�gasp��4�glyf�^�t+xhead�C��6hhea�R$hmtxF��loca8-L�~maxp��8 name4�/�post�ot�2l|_�_<�֋��֋������^��.����^>�@�LfGLf��	PfEd@��:��.U������	/���:�����	

 !"#$%&'()*+,-./0123465789:;<=*BX�L��L���b<�d���Nz		l	�
$
X
�
��T�

�^��PT���l�B��.b������##!T������������!!
� ���
� ������!!���I
���� ����!!!!��
� �����I�!!!!!!3#3#73#3#��*���R��+�Հ�hh���������,��T�g%^X �	'EO5!35#!'&"7&?62'2?64"/&4?67&"2?64'?6'&�vM�,)1)0�
*/,*/:P

P�q�*�Ix+/)
/)�.*,-)

O

P�	!-5!35#!!"3!2=4+"=4;27!"3!2=4�vM�
��]NNo��6�q�*�I���I�AA�	$5!35#!32?6/&54&+"'&�vM�bp9
	:

�q�*�I�xp

:�

�:�	$5!35#!&#"?;26=?6'�vM�Kq:	
9�q�*�IFq

9�

�:�	-5!35#!#";2=4&"?;2=?6'�vM��

�
}
\		
	/

/
	
		�q�*�I��\	
/�

�/		
	�	-5!35#!#";2=4'2?6/&54+"'&�vM��

�
�[		
	
/

/	

		�q�*�I��[	

		/��/		
	�	&5!35#!"&46323!26/.'&�vM�� .  A3
&
X3�q�*�I�  . �<
�

R
�	
%5!35#!#5%!!'3''7"2654'35!5�wM�
���'��<7$�!�q�*�I����EO6J{��#�	
5!35#!#5%!!35!5�wM�
���'��!�q�*�I����@��#�	9@5!35#!772?'7&'&/?6'&767676'&6�wM���		/$U��
)
�C
	
	�q�*�I��
	/'T�p
B
� !	(	

�	FVgt��5!35#!&'"&'&'#"327676/43632727676765675676#"'&'&763267676'"'.7632632#"'&'&7632#"'&'&�wM�#"(<CV	8

"	
$
�
� 
E
�q�*�I	+fAF 	""
-
	
	,	##-	- 

-
	
	�		�	!=P5!35#!264&"&264&"264&"7&3276767676764'&#&�wM�8((((�((�=C+*:4��'�q�*�I��((Y((�((�	07)	*A<��	$<5!35#!&?6#&576/4&'&6576?6'�wM��
�	
�	�	�
�	
��q�*�I��
E��
'''!
T
"	��	25!35#!"'654'73264&#"&#"3273264&�wM�ee"""d""d"""�q�*�I��<<"0!!<!0"<""0!�	C5!35#!'&#"#"3276=&54&54767676767676;32?64�wM�&_*�


*_�q�*�I�`/K"5	/_
�	&5!35#!4#!";2?3;253;265�wM�*
��

J*
K�q�*�II

:
����^�	'.38>DINTZbjqx���5!35#!&'&#"327676764'&&'67''&'6#6&'&'657&'53'5677&'&''&'6#6&'67&67677&'673�wM�L%$,*&$$&*,$%>	 �CBC / CA$�
+?<!9
�
+	?�q�*�I�'(P('$(P($e"()4�5HH5Q8 >8! VH5GH5Q8#A8#s	


	* *2P* +2s	



		*("4�	Q[����5!35#!'&'76/&&/&+"'&"3?;2?67?6/6?2=4"&54627'54#'""'&#"3??27?6/6732574#'&'76/&'&76&'74#'""'&#"?3?27?6/6732?4/&'76/&&76�wM�!



	


b$$3
			

		
�


	



	�q�*�I��
		

	


			


<�
			<

I
	

	

B&�	5!35#!3#3'7#7�wM�����
^R:��3�q�*�IW9%:A  E44�	F^5!35#!'&'&1463327656'&'&'&547673&/&'&#&'3'&/?3276?=�wM�$+"	! 
��q�*�I��"
#
			

vOR&
	
ON�	G5!35#!272654'>72327264&#"'654&"&#".'654&"�wM���	+ /	#	 1 $
 �q�*�I��$
H	 
)5 �	$?5!35#!>7;2=4&&3&'76&+"767676'�wM��DE
+n'.1�FF
+n'.�q�*�I�	`!	'-B,-		`!	'.A�	%1=5!35#!"264"&462'"32654&"&546327#"&54632�wM�4�__�^pbEEbEv*;;*);;)!!""

�q�*�IJ^�__��EbDDb�;)*;;*);�!""!9

�	!5!35#!!26=4/##5#"3#�wM��	<�/�++�q�*�I�s	�
	=qq
��	+[�	%5!35#!3;2=32=4+54+"#"�wM��]
5
]

]
5
]
�q�*�I��]

]
5
]

]
5
�	%5!35#!??6/76/&'&�wM��BB&BB%BB%BB&�q�*�I�AB&BB&BA&BB&	��!1#"3!2?654&+"#!"&=4&326=4&+"[<	

	y0
1	
	��	

�(	

	(	

�
	�0
7y	

	�	

	�	
�
T

T
�	U5!35#!/&'4?&'&#"32767672#"'&'&'&47676762?6�wM�*q(	"

D�q�*�I�&
"






<


��J/&5&?&'&#"32767672#"'&'&'&47>762?6��+

6&! @ 30/""D/,n,/!*>	!,
""/,n,/D#�	05!35#!767''.?66&'&7'"'&4�wM���q

 ITH	p

�q�*�I��q
 ITI 
q�	&,7@5!35#!5#5733#'547#7"&54632324#5#5733#'547#�wM��<3'�22F{<3'�q�*�I�v SO 8	

 '('\\q SO 8	�	!/;GU5!35#!#";2=4#";2=4#";26=4'#";2=4#";2=4#";26=4�wM���������q�*�Itpq		�pq		�	-17=HS5!35#!27326=73264&"&#"'54&"$2"2#"4&2"5"'35'#"'35.�wM���
b_ ]\ I�
�?
C�	�F


��q�*�I�'7
 6$O>=
@']�*�]	�	15IN5!35#!#53##7#"54325373#;#"&=#53573#7327#"&54632'4#"�wM���%j% u;	

BE�q�*�I��p��dd�$(�( 	�	=5!35#!'6'&#'&#7676727654'&?67>276�wM�(/	.M1	
	(
#	�q�*�I�DD
J3!	<			#	�	5!35#!'#"&54632�wM�03K'-X{{XW{�q�*�I�?3KfIHff�	$25!35#!&#'?6.'&/?6/&�wM�	&F23FBB
.'.'��<=<�q�*�I�F23F%BB�
-'.<=<�	`5!35#!#54&+532=4+";#"#";26=4&+54;#";26=4&+532#";26=4&�wM�
j2w	2j


(


j


'
j
'

�q�*�I��'*<	<*'''
'/
''
/'
''
�	1F[�5!35#!&'"&#"327654'.547676'&'"&#"327654'&'&5465676'672763667632"'&'"'&'&�wM�"
	W
	


�

%


�q�*�I��!	

	'#
		
		F0+G
C'%.&b�	(5!35#!"35353732654&"&462�wM�C.@�@&':-@@
 �q�*�I1@.�A'&:@-.@t �	&3?5!35#!72!.>?6#4.'">54&#"&54632�wM��9#��* �"
7 )#..! .. !.�q�*�I��87&,#1$�4!*!.j .. !..�	D\_��5!35#!3&'&+";276772576'&'6732=4+54+"#"&+";2?3;276/7%312?5/&"#"'&/3256/&#5"7;632'1##31?654#'5&'&#1"�wM���U
	 -,�&'	K��3#

(� (
3!�q�*�I�$	

% n|277+<	
$8*�
$8*; 	�	"/5!35#!"26=4"&'26=#"&'265�wM�&pPPpP�5OPpPNRN65OPpP�q�*�IC((�DD2C�	&*28@Z5!35#!#'&+"#3#!5#76=&'3#3#73#6%#675#"54;'27632#"#676/3�wM��	WUBo3H�#J#c�!
"#)]!) (+C��q�*�I�&&�[4LN22	+4'
��	-G5!35#!!"3!2=4&"?;2=?6'32?6/&54+"'&�vM���

,
KR**��Q	*)			�q�*�I��Q	

*��*

	�R*��*	/��=E%'6'&'&>7676764.>?676276567'7'7�E
F1
J
!	

=)++(:"	��ff	&F3	/!2Z3

��	QY5!35#!'&'76/&&/&+"'&?;2?67?6/6?6=4"&462�wM�!

	
""
	
!�4$$4%�q�*�I�

!!
	

	
	""	
U%4$$4�	264&#"75464&/�+<<+*<<�y/"x/m/!y/"x2<V<<V<4�%G3�$Hl$H
4�%G3�	!35#!3#5#53#?3#'#53�e<�*�-9�9�.2@D4.--��)�|���&&W1F\B3�d�	#5!3#!"/&4?62762*�TMw�e<��I�T*����f=��#3##3#3lll���ړll���6���$���3#3#35353#7353#(�����I��?���� �o����L�ܘ��ݙ�Eٹ�����H�#!"&547276?>7>?676767>7623367654/&#""'&'&'&'&'&#"276767>7>7�\

/


/

�P\	

	4.P	
	E��

!

	!

�:C$#:	
�	"5!35#!7''732?'7'7�wM�]###v63w##\LL/�q�*�I�]###w-54
w##sM/�4t5�]��	2	$N	j�	2)	w	2�better-studio-admin-iconsbetter-studio-admin-iconsstudio-admin-iconsstudio-admin-iconsFontForge 2.0 : better-studio-admin-icons : 22-1-2018FontForge 2.0 : better-studio-admin-icons : 22-1-2018better-studio-admin-iconsbetter-studio-admin-iconsVersion 1.0Version 1.0better-studio-admin-iconsbetter-studio-admin-icons>	

 !"#$%&'()*+,-./0123456789:;<betterstudioheaderfootersidebar	page-textlinkarchivearrow-bottom	arrow-topexportdownloadimageslider
slider-newpaintpaint1paint2images	share-altshare
typographyglobalgearscss3js	analyticsrefreshgoalsaveadddelete
save-cleanresetreset-cleanverdict404list-bullet
analytics1title	advertisecommentpinsitemapwookeybbpresstranslationdatabasefont
export-import
advertise2gear	publishertypekitcheck
skyscraperchecked-gridnewsletter-packinject��=�=��֋��֋��libs/better-framework/oculus/exceptions.php000064400000002051151214002630015151 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! class_exists( 'BF_API_Exception' ) ) {

	/**
	 * Custom Exception except error code as string
	 *
	 * Class BF_API_Exception
	 */
	Class BF_API_Exception extends Exception {

		public function __construct( $message = '', $code = '' ) {

			parent::__construct( $message, 0 );
			$this->code = $code;
		}
	}
}libs/better-framework/oculus/class-bf-oculus.php000064400000022067151214002630016003 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


/**
 * Class BS_API
 */
final class BetterFramework_Oculus {

	/**
	 * Better Studio API URI
	 *
	 * @var string
	 */
	private $base_urls = array(

		'https://core.betterstudio.com/api/%group%/v1/%action%',
		'https://core-cf.betterstudio.com/api/%group%/v1/%action%',
		//
		'http://core.betterstudio.com/api/%group%/v1/%action%',
		'http://core-cf.betterstudio.com/api/%group%/v1/%action%',
	);

	/**
	 * self instance
	 *
	 * @var array
	 */
	protected static $instance;

	/**
	 * Oculus base slug
	 *
	 * Created to be flexible for future updates
	 */
	public static $slug = 'oculus';

	/**
	 * Store Authentication params - array {
	 *
	 * @type string|int $item_id       the item id in envato marketplace
	 * @type string     $purchase_code envato purchase code
	 * }
	 *
	 * @var array
	 */
	protected $auth = array();

	/**
	 * Oculus Version
	 */
	const VERSION = '1.2.0';


	/**
	 * Initialize
	 */
	public static function Run() {

		global $bs_oculus;

		if ( $bs_oculus === false ) {
			return;
		}

		if ( ! $bs_oculus instanceof self ) {
			$bs_oculus = new self();
			$bs_oculus->init();
		}

		return $bs_oculus;
	}


	/**
	 * apply filters/actions
	 */
	public function init() {

		$this->include_files();

		add_action( 'admin_init', array( $this, 'register_schedule' ) );
		add_action( 'better-framework/oculus/check-update/init', array( $this, 'check_for_update' ) );
	}


	public function check_for_update() {

		$status       = array(
			'is-rtl'    => is_rtl() ? '1' : '0',
			'languages' => bf_get_all_languages(),
		);
		$slug         = self::$slug;
		$data         = apply_filters( "better-framework/$slug/check-update/data", $status );
		$use_wp_error = false;
		$response     = self::request( 'check-update', compact( 'data', 'use_wp_error' ) );

		if ( $response && ! empty( $response->success ) ) {
			do_action( 'better-framework/oculus/check-update/done', $response, $data );
		}
	}


	/**
	 * Callback: register sync cron job
	 * action  : admin_init
	 */
	public function register_schedule() {

		if ( ! wp_next_scheduled( 'better-framework/oculus/check-update/init' ) ) {
			wp_schedule_event( time(), 'daily', 'better-framework/oculus/check-update/init' );
		}
	}


	/**
	 * Include oculus additional classes
	 */
	protected function include_files() {

		require BS_OCULUS_PATH . 'includes/class-bf-oculus-logger.php';
		require BS_OCULUS_PATH . 'includes/class-bf-oculus-message-manager.php';
	}


	/**
	 * Connect Better Studio API and Retrieve Data From Server
	 *
	 * @param string $action       {@see handle_request}
	 * @param array  $args         {
	 *
	 * @type array   $auth         authentication info {@see $auth}
	 * @type array   $data         array of data to send
	 * @type string  $group        API group name
	 * @type bool    $use_wp_error use wp_error object on failure or always return false
	 * }
	 *
	 * @return bool|WP_Error|array|object bool|WP_Error on failure.
	 */
	public static function request( $action, $args = array() ) {

		try {
			$args = bf_merge_args( $args, array(
				'auth'         => array(),
				'data'         => array(),
				'group'        => 'default',
				'json_assoc'   => false,
				'use_wp_error' => true,
			) );

			$auth = bf_merge_args( $args['auth'], apply_filters( 'better-framework/oculus/request/auth', array() ) );

			if ( ! isset( $auth['item_id'] ) || ! isset( $auth['purchase_code'] ) ) {
				throw new BF_API_Exception( 'invalid authentication data', 'invalid-auth-data' );
			}

			$instance = self::get_instance();
			$instance->set_auth_params( $auth );
			$response = $instance->handle_request( $action, $args['group'], $args['data'], $args['json_assoc'] );

			// auto clean product registration info if purchase-code was not valid!
			if ( isset( $response->result ) && isset( $response->{'error-code'} ) &&
			     $response->result === 'error' && $response->{'error-code'} === 'invalid-purchase-code'
			) {
				if ( function_exists( 'bf_register_product_clear_info' ) ) {
					bf_register_product_clear_info( $auth['item_id'] );
				}
			}

			return $response;
		} catch( Exception $e ) {

			if ( $args['use_wp_error'] ) {
				return new WP_Error( 'error-' . $e->getCode(), $e->getMessage() );
			}

			return false;
		}
	}


	/**
	 * Fetch a remove url
	 *
	 * @param string $url
	 * @param array  $args wp_remote_get() $args
	 *
	 * @return string|false string on success or false|Exception on failure.
	 * @throws Exception
	 */
	public function fetch_data( $url, $args = array() ) {

		global $wp_version;

		if ( is_callable( 'Theme_Name_Translation::factory' ) ) {
			$current_panel_lang = get_option( Theme_Name_Translation::factory()->option_panel_id . bf_get_current_language_option_code() . '-current' );
		} else {
			$current_panel_lang = 'unavailable';
		}

		$defaults = array(
			'timeout'    => 30,
			'user-agent' => 'BetterStudioApi Domain:' . home_url( '/' ) .
			                '; WordPress/' . $wp_version . '; Oculus/' . self::VERSION . ';',
			'headers'    => array(
				'better-studio-item-id'      => $this->auth['item_id'],
				'better-studio-item-version' => isset( $this->auth['version'] ) ? $this->auth['version'] : 0,
				'envato-purchase-code'       => $this->auth['purchase_code'],
				'panel-language'             => $current_panel_lang,
				'locale'                     => get_locale(),
			)
		);

		$args         = bf_merge_args( $args, $defaults );
		$raw_response = wp_remote_post( $url, $args );

		if ( is_wp_error( $raw_response ) ) {
			$error_message = $raw_response->get_error_message();

			if ( preg_match( '/^\s*cURL\s*error\s*(\d+)\s*\:?\s*$/i', $error_message, $match ) && function_exists( 'curl_strerror' ) ) {
				$error_message .= curl_strerror( $match[1] );
			}

			throw new BF_API_Exception( $error_message, $raw_response->get_error_code() );
		}

		$response_code = wp_remote_retrieve_response_code( $raw_response );

		if ( 200 == $response_code ) {
			return wp_remote_retrieve_body( $raw_response );
		} elseif ( 403 == $response_code ) {

			$parse_url = parse_url( $url );
			throw new BF_API_Exception( sprintf( __( 'Server cannot connect to %s', 'better-studio' ), $parse_url['host'] ), $response_code );
		}

		return false;
	}


	/**
	 * Handle API Remove Request
	 *
	 * @param string $action Api action. EX: register_product, check_update,....
	 * @param string $group  Api group
	 * @param array  $data   array of data
	 * @param bool   $assoc  json_decode second parameter
	 *
	 * @return array|false|object array or object on success, false|Exception on failure
	 * @throws Exception
	 */

	public function handle_request( $action, $group, $data, $assoc = false ) {

		$url = str_replace(
			array( '%group%', '%action%' ),
			array( $group, $action ),
			$this->the_base_url()
		);

		$args = array(
			'body' => $data
		);

		if ( $received = $this->fetch_data( $url, $args ) ) {

			return json_decode( $received, $assoc );
		}

		return false;
	}


	/**
	 * Returns live instance of BS_API
	 *
	 * @return self
	 */
	public static function get_instance() {

		if ( empty( self::$instance ) ) {
			self::$instance = new self();
		}

		return self::$instance;
	}


	/**
	 * Set Authentication Params
	 *
	 * @param array $args
	 *
	 * @see   $auth
	 */
	public function set_auth_params( $args ) {

		$this->auth = $args;
	}


	/**
	 * Is given url accessible
	 *
	 * @param string $url
	 *
	 * @since 1.1.0
	 * @return bool true if it does
	 */
	public static function is_host_accessible( $url ) {

		$request = wp_remote_get( $url, array( 'timeout' => bf_is_localhost() ? 10 : 2 ), array( 'sslverify' => false ) );

		return $request && ! is_wp_error( $request ) && 200 === wp_remote_retrieve_response_code( $request );
	}


	/**
	 * Choose an accessible core url from available servers
	 *
	 * @since 1.1.0
	 * @return string
	 */
	protected function the_base_url() {

		static $base_url;

		if ( isset( $base_url ) ) {

			return $base_url;
		}

		// check cache storage
		if ( $url = get_transient( 'bf-oculus-base-url' ) ) {

			return $url;
		}

		reset( $this->base_urls );

		do {

			$base_url   = current( $this->base_urls );
			$parsed_url = parse_url( $base_url );
			$test_url   = sprintf( '%s://%s', $parsed_url['scheme'], $parsed_url['host'] );

			if ( $this->is_host_accessible( $test_url ) ) {

				break;
			}

		} while( next( $this->base_urls ) !== false );

		if ( $base_url ) {

			set_transient( 'bf-oculus-base-url', $base_url, HOUR_IN_SECONDS * 2 );
		}

		return $base_url;
	}
}


BetterFramework_Oculus::Run();libs/better-framework/oculus/better-framework-oculus-loader.php000064400000016622151214002630021035 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


if ( ! class_exists( 'BetterFramework_Oculus_Loader' ) ) {

	class BetterFramework_Oculus_Loader {

		static $libraries = array();

		static $active_library;


		/**
		 * Load newest oculus library
		 */
		public static function setup_library() {

			self::$libraries = apply_filters( 'better-framework/oculus/loader', array() );

			$count = bf_count( self::$libraries );

			if ( ! $count ) {
				return false;
			}

			if ( $count == 1 ) {
				self::load_library( current( self::$libraries ) );
			} else {

				$latest_version = null;

				foreach ( self::$libraries as $lib ) {

					if ( $latest_version == null ) {
						$latest_version = $lib;
						continue;
					}

					if ( version_compare( $latest_version['version'], $lib['version'] ) <= 0 ) {
						$latest_version = $lib;
					}

				}

				self::$active_library = $latest_version;
				self::load_library( $latest_version );
			}

			do_action( 'better-framework/oculus/after_setup' );
		}


		/**
		 * Loads framework
		 *
		 * @param $library
		 */
		public static function load_library( $library ) {

			define( 'BS_OCULUS_URI', trailingslashit( $library['uri'] ) );
			define( 'BS_OCULUS_PATH', trailingslashit( $library['path'] ) );

			include_once BS_OCULUS_PATH . 'exceptions.php';
			include_once BS_OCULUS_PATH . 'class-bf-oculus.php';
		}


		/**
		 * Register PHP Error Log System Functions
		 */
		public static function register_custom_error_handler() {

			add_action( 'better-framework/oculus/check-update/done', array(
				'BetterFramework_Oculus_Loader',
				'flush_log'
			) );

			register_shutdown_function( 'BetterFramework_Oculus_Loader::bs_custom_fatal_error_handler' );
			set_error_handler( 'BetterFramework_Oculus_Loader::bs_custom_error_handler' );

			add_filter( "better-framework/oculus/check-update/data", array(
				'BetterFramework_Oculus_Loader',
				'_data'
			) );
		}


		/**
		 * Store errors in DB error source belongs to BetterStudio products
		 *
		 * @param $message
		 * @param $file
		 * @param $line
		 * @param $type
		 */
		public static function bs_log_error( $message, $file, $line, $type ) {

			if ( defined( 'BF_DEV_MODE' ) && BF_DEV_MODE ) {
				return;
			}

			$abs  = wp_normalize_path( ABSPATH );
			$file = wp_normalize_path( $file );
			if ( ! preg_match( '#^/*' . trim( $abs, '/' ) . '/*wp-content/([^/]+)/*([^/]+)#', $file, $match ) ) {
				return;
			}
			$type_dir    = &$match[1];
			$product_dir = &$match[2];

			if ( apply_filters( 'better-framework/oculus/logger/turn-off', true, $product_dir, $type_dir, $file, $line, $type, $message ) ) {
				return;
			}

			if ( is_int( $type ) ) {
				switch ( $type ) {
					case E_CORE_WARNING:
					case E_WARNING:
						$type = 'warning';
						break;
					case E_ERROR:
						$type = 'error';
						break;
					case E_PARSE:
						$type = 'parse';
						break;
					case E_NOTICE:
						$type = 'notice';
						break;
					case E_CORE_ERROR:
					case E_COMPILE_ERROR:
						$type = 'core_error';
						break;
					case E_COMPILE_WARNING:
						$type = 'compile_warning';
						break;
					//TODO: enable user trigger errors logging
					case E_USER_ERROR:
						$type = 'user_error';

						return;
						break;
					case E_USER_WARNING:
						$type = 'user_warning';

						return;
						break;
					case E_USER_NOTICE:
						$type = 'user_notice';

						return;
						break;
					case E_STRICT:
						$type = 'strict';

						//TODO: enable strict errors logging
						return;
						break;
					case E_RECOVERABLE_ERROR:
						$type = 'recoverable_error';
						break;
					case E_DEPRECATED:
					case E_USER_DEPRECATED:
						$type = 'deprecated';

						//TODO: enable deprecated errors logging
						return;
						break;
				}
			}

			$errors   = get_option( 'bs-backend-error-log', array() );
			$errors[] = array(
				'msg'       => $message,
				'file'      => self::wp_content_basename( $file ),
				'timestamp' => time(),
				'line'      => $line,
				'type'      => $type,
				'trace'     => $type === 'fatal' ? '' : print_r( self::get_debug_backtrace(), true )
			);


			$logged = update_option( 'bs-backend-error-log', array_slice( $errors, - 15 ), 'no' );

			do_action( 'better-framework/oculus/logger/logged', $logged );
		}


		/**
		 * Get debug backtrace summary
		 *
		 * @return array
		 */
		public static function get_debug_backtrace() {

			$result = array();
			foreach ( array_slice( debug_backtrace(), 3, 3 ) as $idx => $trace ) {
				if ( isset( $trace['object'] ) ) {
					$trace['object'] = get_class( $trace['object'] );
				}
				$result[ $idx ] = $trace;
			}

			unset( $result[0]['args'][4] ); // unset bs_custom_error_handler fifth argument

			return $result;
		}


		/**
		 * Log all php errors except fatal errors
		 *
		 * @param integer $errno
		 * @param string  $errstr
		 * @param string  $errfile
		 * @param integer $errline
		 *
		 * @see set_error_handler
		 *
		 * @return boolean false
		 */
		public static function bs_custom_error_handler( $errno, $errstr, $errfile, $errline ) {

			self::bs_log_error( $errstr, $errfile, $errline, $errno );

			return false;
		}


		/**
		 * Log only php fatal errors
		 */
		public static function bs_custom_fatal_error_handler() {

			$last_error = error_get_last();

			if ( $last_error && isset( $last_error['type'] ) && $last_error['type'] === E_ERROR ) {
				self::bs_log_error( $last_error['message'], $last_error['file'], $last_error['line'], 'fatal' );
			}
		}


		/**
		 * @param array $data
		 *
		 * @return array|mixed
		 */
		public static function _data( $data ) {

			if ( $errors = get_option( 'bs-backend-error-log' ) ) {
				$data['backend'] = $errors;
			}

			return $data;
		}


		/**
		 * @param object $obj
		 */
		public static function flush_log( $obj ) {

			if ( ! empty( $obj->clean_backend_log ) ) {
				update_option( 'bs-backend-error-log', array(), 'no' );
			}
		}


		/**
		 * Catch file path after wp-content dir.
		 *
		 * @param string $file full path to file
		 *
		 * @return string
		 */
		public static function wp_content_basename( $file ) {

			$file        = wp_normalize_path( $file );
			$content_dir = wp_normalize_path( WP_CONTENT_DIR );

			$file = preg_replace( '#^' . preg_quote( $content_dir, '#' ) . '/#', '', $file ); // get relative path from wp-content dir
			$file = trim( $file, '/' );

			return $file;
		}
	}


	BetterFramework_Oculus_Loader::register_custom_error_handler();
	add_action( 'after_setup_theme', array( 'BetterFramework_Oculus_Loader', 'setup_library' ), 11 );
}

libs/better-framework/oculus/index.php000064400000000053151214002630014077 0ustar00<?php
// Silence is golden and we believe ilibs/better-framework/oculus/includes/class-bf-oculus-message-manager.php000064400000021461151214002630022640 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

BetterFramework_Oculus_Message_Manager::init();


class BetterFramework_Oculus_Message_Manager {

	/**
	 * Apply hooks
	 */
	public static function init() {

		add_action( 'init', array( __CLASS__, 'append_fixed_message_menu' ) );
		add_action( 'switch_theme', array( __CLASS__, 'theme_change_notification' ), 9, 3 );
		add_action( 'admin_head', array( __CLASS__, 'display_custom_messages' ) );
		add_action( 'admin_head', array( __CLASS__, 'register_admin_notices' ) );


		$ocs_slug = BetterFramework_Oculus::$slug;

		add_action( "better-framework/$ocs_slug/check-update/done", array( __CLASS__, 'save_messages' ) );
		add_filter( "better-framework/$ocs_slug/check-update/data", array( __CLASS__, 'check_data' ) );
	}


	/**
	 * @param array $data
	 *
	 * @return array
	 */
	public static function check_data( $data ) {

		$data['watched-messages'] = get_option( 'oculus-messages-watched' );

		return $data;
	}


	/**
	 *  Callback: Register menu for 'fixed page' Message
	 *  action   : init
	 */
	public static function append_fixed_message_menu() {

		$messages = get_option( 'oculus-messages' );
		if ( ! empty( $messages['fixed_page'] ) ) {
			$default_id    = 'bs-product-pages-message-';
			$default_menu  = array(
				'parent'       => 'bs-product-pages-welcome',
				'name'         => __( 'Message', 'better-studio' ),
				'icon'         => '\\E034',
				'callback'     => array( __CLASS__, 'menu_callback' ),
				'capability'   => 'edit_theme_options',
				'position'     => '9.5',
				'on_admin_bar' => true,
				'id'           => 'betterstudio-message',
				'slug'         => 'betterstudio-message',
			);
			$page_settings = &$messages['fixed_page'];
			if ( ! empty( $page_settings->menu ) ) {
				$default_menu['id'] = $default_menu['slug'] = $default_id . $page_settings->id;

				$menu    = wp_parse_args( $page_settings->menu, $default_menu );
				$watched = get_option( 'oculus-messages-watched', array() );

				/**
				 * Hide menu if watched previously.
				 */
				if ( ! empty( $page_settings->menu['message_id'] ) ) {
					$nid = &$page_settings->menu['message_id'];
					if ( ! empty( $watched[ $nid ] ) ) {
						if ( $GLOBALS['pagenow'] !== 'admin.php' || ! isset( $_GET['page'] ) || $_GET['page'] !== $menu['slug'] ) {
							$menu['parent'] = null;
						} // null parent make menu invisible
					}
				}

				Better_Framework()->admin_menus()->add_menupage( $menu );
			}
		}
	}


	/**
	 * Callback: report theme changes
	 * action  : switch_theme
	 *
	 * @param string   $new_name
	 * @param WP_Theme $new_theme
	 * @param WP_Theme $old_theme
	 */
	public static function theme_change_notification( $new_name, $new_theme, $old_theme = null ) {

		$new_theme_headers = array(
			'Name'        => $new_theme->get( 'Name' ),
			'ThemeURI'    => $new_theme->get( 'ThemeURI' ),
			'Description' => $new_theme->get( 'Description' ),
			'Author'      => $new_theme->get( 'Author' ),
			'AuthorURI'   => $new_theme->get( 'AuthorURI' ),
			'Version'     => $new_theme->get( 'Version' ),
			'Template'    => $new_theme->get( 'Template' ),
		);

		if ( $old_theme instanceof WP_Theme ) {

			$old_theme_headers = array(
				'Name'     => $old_theme->get( 'Name' ),
				'Version'  => $old_theme->get( 'Version' ),
				'Template' => $old_theme->get( 'Template' ),
			);
		}

		BetterFramework_Oculus::request( 'product-disabled', array(
			'data'         => array(
				'new-theme-headers' => $new_theme_headers,
				'old-theme-headers' => $old_theme_headers,
			),
			'use_wp_error' => false,
		) );
	}


	/**
	 * Display custom remote messages to user
	 */
	public static function display_custom_messages() {

		if ( ! function_exists( 'bf_enqueue_style' ) ) {
			return;
		}

		$watched = get_option( 'oculus-messages-watched', array() );
		$message = get_option( 'oculus-messages', array() );

		if ( ! $message ) {
			return;
		}

		$need_update = false;

		if ( ! empty( $message['custom'] ) ) {
			/*
						bf_enqueue_script( 'bf-modal' );
						bf_enqueue_style( 'bf-modal' );
			*/

			foreach ( (array) $message['custom'] as $index => $custom ) {
				if ( empty( $custom->id ) || isset( $watched[ $custom->id ] ) ) {
					continue;
				}
				self::mark_as_watched( $custom->id );
				self::enqueue_dependencies( $custom );
				self::print_html_css( $custom );

				$need_update = true;
				unset( $message['custom'][ $index ] );
				break;
			}
		}

		if ( $need_update ) {
			update_option( 'oculus-messages', $message, 'no' );
		}
	}


	/**
	 * Register custom remote admin notices
	 */
	public static function register_admin_notices() {

		if ( ! function_exists( 'bf_add_notice' ) ) {
			return;
		}

		$watched = get_option( 'aoculus-messages-watched', array() );
		$message = get_option( 'oculus-messages', array() );

		if ( ! $message ) {
			return;
		}

		$need_update = false;

		if ( ! empty( $message['notices'] ) ) {

			foreach ( (array) $message['notices'] as $index => $notice ) {

				if ( empty( $notice->id ) ) {
					continue;
				}

				$notice = get_object_vars( $notice );

				bf_add_notice( $notice );

				$need_update = true;
				unset( $message['notices'][ $index ] );
				break;
			}
		}

		if ( $need_update ) {
			update_option( 'oculus-messages', $message, 'no' );
		}
	}


	/**
	 * Enqueue static file dependencies
	 *
	 * @param object $object
	 */
	protected static function enqueue_dependencies( $object ) {

		if ( ! empty( $object->js_deps ) && is_array( $object->js_deps ) ) {
			foreach ( $object->js_deps as $args ) {
				$function = sizeof( $args ) === 1 ? 'bf_enqueue_script' : 'wp_enqueue_script';
				call_user_func_array( $function, $args );
			}
		}

		if ( ! empty( $object->css_deps ) && is_array( $object->css_deps ) ) {
			foreach ( $object->css_deps as $args ) {
				$function = sizeof( $args ) === 1 ? 'bf_enqueue_style' : 'wp_enqueue_style';
				call_user_func_array( $function, $args );
			}
		}
	}


	/**
	 * mark a message as watched
	 *
	 * @param string|int $message_id
	 */
	protected static function mark_as_watched( $message_id ) {

		$watched                = get_option( 'oculus-messages-watched', array() );
		$watched[ $message_id ] = time();

		update_option( 'oculus-messages-watched', $watched, 'no' );
	}


	/**
	 * Fixed page message, menu callback
	 */
	public static function menu_callback() {

		$messages = get_option( 'oculus-messages' );
		if ( ! empty( $messages['fixed_page'] ) ) {
			$message = &$messages['fixed_page'];
			if ( ! empty( $message->menu['message_id'] ) ) {
				self::mark_as_watched( $message->menu['message_id'] );
			}

			self::print_html_css( $message );
			echo $message->html;  // escaped before
			self::mark_as_watched( $message->id );

		}
	}


	/**
	 * @param object $msg_object message object
	 */
	protected static function print_html_css( $msg_object ) {

		if ( isset( $msg_object->css ) ) {
			echo '<style>', $msg_object->css, '</style>'; // escaped before
		}
		if ( isset( $msg_object->js ) ) {
			echo '<script>', $msg_object->js, '</script>'; // escaped before
		}
	}


	/**
	 * @param object $response
	 */
	public static function save_messages( $response ) {

		if ( empty( $response->messages ) ) {
			return;
		}
		$messages = $response->messages;
		$db       = get_option( 'oculus-messages', array() );

		if ( isset( $messages->fixed_page ) ) {
			$page_data = &$messages->fixed_page;

			if ( isset( $page_data->html ) && isset( $page_data->id ) ) {
				if ( isset( $page_data->menu ) ) {
					$page_data->menu = (array) $page_data->menu;
				}
				$db['fixed_page'] = $page_data;
			}
		}
		if ( isset( $messages->custom ) && is_array( $messages->custom ) ) {
			if ( ! isset( $db['custom'] ) ) {
				$db['custom'] = array();
			}

			foreach ( $messages->custom as $custom ) {
				if ( isset( $custom->id ) ) {
					$id                  = &$custom->id;
					$db['custom'][ $id ] = $custom;
				}
			}
		}
		if ( isset( $messages->admin_notices ) && is_array( $messages->admin_notices ) ) {
			if ( ! isset( $db['notices'] ) ) {
				$db['notices'] = array();
			}

			foreach ( $messages->admin_notices as $notice ) {
				if ( isset( $notice->id ) ) {
					$id                   = &$notice->id;
					$db['notices'][ $id ] = $notice;
				}
			}
		}

		update_option( 'oculus-messages', $db, 'no' );
	}
}
libs/better-framework/oculus/includes/index.php000064400000000054151214002630015706 0ustar00<?php
// Silence is golden and we believe itlibs/better-framework/oculus/includes/class-bf-oculus-logger.php000064400000007055151214002630021066 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


BetterFramework_Oculus_Logger::Run();


class BetterFramework_Oculus_Logger {

	/**
	 * Store log data
	 * Initialize
	 */
	public static function Run() {

		global $bs_oculus_logger;

		if ( $bs_oculus_logger === false ) {
			return;
		}

		if ( ! $bs_oculus_logger instanceof self ) {
			$bs_oculus_logger = new self();
			$bs_oculus_logger->init();
		}

		return $bs_oculus_logger;
	}


	public function init() {

		add_action( 'better-framework/oculus/check-update/done', array( $this, 'clean_data' ) );

		// log demo installation process
		add_action( 'better-framework/product-pages/install-demo/import-finished', array(
			$this,
			'log_demo_install'
		), 9, 2 );
		add_action( 'better-framework/product-pages/install-demo/rollback-finished', array(
			$this,
			'log_demo_uninstall'
		), 9, 2 );

		$o_slug = BetterFramework_Oculus::$slug;

		add_filter( "better-framework/$o_slug/check-update/data", array( $this, 'check_data' ) );
	}


	/**
	 * Get logged data
	 *
	 * @return array
	 */
	protected function get_data() {

		return get_option( 'bs-oculus-logger', array() );
	}


	/**
	 * callback: saved imported demo list in database
	 * action: bs-product-pages/install-demo/import-finished
	 *
	 * @param string                    $demo_ID
	 * @param BF_Product_Demo_Installer $_this
	 */
	function log_demo_install( $demo_ID, $_this ) {

		$log = $this->get_data();
		if ( ! isset( $log['demo'] ) ) {
			$log['demo'] = array();
		}

		$log['demo'][] = array(
			'action'  => 'install',
			'demo-id' => $demo_ID,
			'time'    => time(),
			'context' => $_this->demo_context
		);
		$this->save( $log );
	}


	/**
	 * callback: remove imported demo from database after demo uninstalled successfully
	 * action: bs-product-pages/install-demo/rollback-finished
	 *
	 * @param string                    $demo_ID
	 * @param BF_Product_Demo_Installer $_this
	 */
	function log_demo_uninstall( $demo_ID, $_this ) {

		$log = $this->get_data();
		if ( ! isset( $log['demo'] ) ) {
			$log['demo'] = array();
		}

		$log['demo'][] = array(
			'action'  => 'uninstall',
			'demo-id' => $demo_ID,
			'time'    => time(),
			'context' => $_this->demo_context
		);
		$this->save( $log );
	}


	/**
	 * callback: save $log array info into db
	 * action  : admin_footer
	 *
	 * @param array $log
	 */
	public function save( $log ) {

		if ( is_array( $log ) ) {
			update_option( 'bs-oculus-logger', array_slice( $log, - 30 ), 'no' );
		}
	}


	/**
	 * @param array $data
	 *
	 * @return array
	 */
	public function check_data( $data ) {

		$logger_data = $this->get_data();
		$data        = array_merge( $data, $logger_data );

		return $data;
	}


	public function clean_data( $obj ) {

		if ( ! empty( $obj->clean_demo_log ) ) {
			// clean demo log
			$log = $this->get_data();
			if ( isset( $log['demo'] ) ) {
				unset( $log['demo'] );
				$this->save( $log );
			}
		}
	}
}libs/better-framework/admin-page/class-bf-admin-page.php000064400000014232151214002630017156 0ustar00<?php
/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */


// Prevent Direct Access
defined( 'ABSPATH' ) or die;


/**
 * BF Admin Pages Main Class
 *
 * @package BetterFramework
 * @since   2.0
 */
abstract class BF_Admin_Page {


	/**
	 * Holds everything about the front-end template
	 *
	 * @since   2.0
	 *
	 * @access  protected
	 * @var     string
	 */
	protected $template = array();


	/**
	 * Holds all arguments
	 *
	 * @since   2.0
	 *
	 * @access  protected
	 * @var     string
	 */
	protected $args = array();


	/**
	 * contains page id
	 *
	 * @since   2.0
	 *
	 * @access  protected
	 * @var string
	 */
	protected $page_id = '';


	/**
	 * Constructor Function
	 *
	 * @since   2.0
	 * @access  public
	 *
	 * @param   array $args         Page arguments ( preserved for future )
	 * @param   bool  $only_backend Run page only in backend
	 *
	 * @return  BF_Admin_Page
	 */
	public function __construct( $args = array(), $only_backend = true ) {

		// Run only in admin
		if ( $only_backend && ! is_admin() ) {
			return;
		}

		if ( ! isset( $args['dir-uri'] ) ) {
			$args['dir-uri'] = '';
		}

		// Prepare ID
		if ( isset( $args['id'] ) ) {
			$this->page_id = $args['id'];
		}

		// Prepare Slug
		if ( ! isset( $args['slug'] ) ) {
			$args['slug'] = $args['id'];
		}


		// Prepare template
		if ( isset( $args['template'] ) ) {

			if ( $args['template'] == 'custom' && isset( $args['template-file'] ) ) {
				$this->template['type']          = 'custom';
				$this->template['template-file'] = $args['template-file'];
			} else {
				$this->template['type'] = $args['template'];
			}

		} else {
			$this->template['type'] = 'minimal-1';
		}

		// Save args
		$this->args = $args;

		// Callback for adding admin menu
		add_action( 'better-framework/admin-menus/admin-menu/before', array( $this, 'add_menu' ) );

		// Callback for adding page custom classes
		add_filter( 'admin_body_class', array( $this, 'admin_body_class' ), 999 );

		// Callback for enqueue BF admin pages style
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );

	}


	/**
	 * Callback: Used for enqueue scripts in WP backend
	 *
	 * Action: admin_enqueue_scripts
	 *
	 * @since   2.0
	 */
	function admin_enqueue_scripts() {

		Better_Framework()->assets_manager()->enqueue_style( 'bf-admin-pages' );

	}


	/**
	 * Used for detecting current page is a BF admin page or not
	 *
	 * @since   2.0
	 *
	 * @return bool
	 */
	function is_current_admin_page() {

		if ( ! isset( $_GET['page'] ) ) {
			return false;
		}

		$page = explode( '/', $_GET['page'] );

		if ( empty( $page[1] ) ) {

			return 'better-studio' === $page[0];
		}

		if ( $page[1] == $this->args['slug'] ) {
			return true;
		} else {
			return false;
		}

	}


	/**
	 * Callback: Used for adding page custom classes to admin body
	 *
	 * @since   2.0
	 *
	 * @param $classes
	 *
	 * @return string
	 */
	function admin_body_class( $classes ) {


		if ( ! $this->is_current_admin_page() ) {
			return $classes;
		}

		$classes = explode( ' ', $classes );

		$classes = array_flip( $classes );

		$classes['bf-admin-page']                                       = 'bf-admin-page';
		$classes[ 'bf-admin-page-template-' . $this->template['type'] ] = 'bf-admin-page-template-' . $this->template['type'];

		// Custom classes per page
		if ( isset( $this->args['class'] ) ) {

			if ( is_array( $this->args['class'] ) ) {

				$custom_classes = $this->args['class'];

			} else {

				$custom_classes = explode( ' ', $this->args['class'] );

			}

			foreach ( $custom_classes as $class ) {

				$classes[ $class ] = $class;

			}

		}

		return implode( ' ', $classes );
	}


	/**
	 * Callback: Used for registering menu to WordPress
	 *
	 * Action: better-framework/admin-menus/admin-menu/before
	 *
	 * @since   2.0
	 * @access  public
	 *
	 * @return  void
	 */
	public function add_menu() {

		return;

	}


	/**
	 * Page Title
	 *
	 * @since   2.0
	 * @return string
	 */
	protected function get_title() {

		return '';

	}


	/**
	 * Page header description
	 *
	 * @since   2.0
	 * @return string
	 */
	protected function get_desc() {

		return '';

	}


	/**
	 * Page body
	 *
	 * @since   2.0
	 * @return string
	 */
	protected function get_body() {

		return '';

	}


	/**
	 * Used for getting page directory that is useful to enqueue scripts and styles
	 *
	 * @since   2.0
	 * @return mixed
	 */
	public function get_dir_uri() {

		return $this->args['dir-uri'];
	}


	/**
	 * Used for render page
	 *
	 * @since 2.0
	 * @return void
	 */
	public function display() {


		$output = '';

		/**
		 * Fires before display page
		 *
		 * @since   2.0
		 *
		 * @param   string $args arguments
		 */
		do_action( 'better-framework/admin-page/' . $this->page_id . '/before', $this, $output );

		switch ( $this->template['type'] ) {

			// Custom template file
			case 'custom':

				$template_file = $this->template['template-file'];

				$title = $this->get_title();

				$desc = $this->get_desc();

				$body = $this->get_body();

				break;

			default:

				$template_file = bf_get_dir( 'admin-page/templates/' . $this->template['type'] . '.php' );

				$title = $this->get_title();

				$desc = $this->get_desc();

				$body = $this->get_body();
		}


		// Capture output
		ob_start();

		require $template_file;

		$output .= ob_get_clean();

		/**
		 * Fires after display page
		 *
		 * @since   2.0
		 *
		 * @param   string $args arguments
		 */
		do_action( 'better-framework/admin-page/' . $this->page_id . '/after', $this, $output );


		// Print output
		echo $output; // escaped before

	}

}libs/better-framework/admin-page/templates/minimal-1.php000064400000002233151214002630017244 0ustar00<?php

/***
 *  BetterFramework is BetterStudio framework for themes and plugins.
 *
 *  ______      _   _             ______                                           _
 *  | ___ \    | | | |            |  ___|                                         | |
 *  | |_/ / ___| |_| |_ ___ _ __  | |_ _ __ __ _ _ __ ___   _____      _____  _ __| | __
 *  | ___ \/ _ \ __| __/ _ \ '__| |  _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
 *  | |_/ /  __/ |_| ||  __/ |    | | | | | (_| | | | | | |  __/\ V  V / (_) | |  |   <
 *  \____/ \___|\__|\__\___|_|    \_| |_|  \__,_|_| |_| |_|\___| \_/\_/ \___/|_|  |_|\_\
 *
 *  Copyright © 2017 Better Studio
 *
 *
 *  Our portfolio is here: https://betterstudio.com/
 *
 *  \--> BetterStudio, 2018 <--/
 */

?>
<div class="bf-admin-page-wrap bf-admin-template-minimal-1">

	<header class="bf-page-header">
		<h2 class="page-title"><?php echo esc_html( $title ); ?></h2>

		<?php if ( ! empty( $desc ) ) {
			echo '<div class="page-desc">' . wp_kses( $desc, bf_trans_allowed_html() ) . '</div>';
		} ?>
	</header>

	<div class="bf-page-postbox">
		<div class="inside">

			<?php echo $body; // escaped before  ?>

		</div>
	</div>

</div>libs/better-framework/gutenberg/class-bf-gutenberg-shortcode-render.php000064400000001174151214002630022364 0ustar00<?php


class BF_Gutenberg_Shortcode_Render {

	public static function __callStatic( $shortcode_id, $arguments ) {

		$attrs   = &$arguments[0];
		$content = &$arguments[1];

		if ( ! $attrs ) {
			$attrs = array();
		}

		if ( ! is_array( $attrs ) ) {
			settype( $attrs, 'array' );
		}

		$rendered = BF_Shortcodes_Manager::handle_shortcodes( $attrs, $content, $shortcode_id );
		$rendered = trim( $rendered );

		if ( $rendered === '' || trim( strip_tags( html_entity_decode( $rendered ) ) ) === '' ) {

			return sprintf( '<h4 class="bf-gutenberg-shortocde-empty">[%1$s][/%1$s]</h4>', $shortcode_id );
		}

		return $rendered;
	}
}
libs/better-framework/gutenberg/dev/.eslintignore000064400000000145151214002630016212 0ustar00**/*.min.js
**/*.build.js
**/node_modules/**
**/vendor/**
build
coverage
cypress
node_modules
vendor
libs/better-framework/gutenberg/dev/plugin.php000064400000001056151214002630015520 0ustar00<?php
/**
 * Plugin Name: dev — CGB Gutenberg Block Plugin
 * Plugin URI: https://github.com/ahmadawais/create-guten-block/
 * Description: dev — is a Gutenberg plugin created via create-guten-block.
 * Author: mrahmadawais, maedahbatool
 * Author URI: https://AhmadAwais.com/
 * Version: 1.0.0
 * License: GPL2+
 * License URI: http://www.gnu.org/licenses/gpl-2.0.txt
 *
 * @package CGB
 */

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Block Initializer.
 */
require_once plugin_dir_path( __FILE__ ) . 'src/init.php';
libs/better-framework/gutenberg/dev/package.json000064400000000372151214002630015777 0ustar00{
  "name": "dev-cgb-guten-block",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "start": "cgb-scripts start",
    "build": "cgb-scripts build",
    "eject": "cgb-scripts eject"
  },
  "dependencies": {
    "cgb-scripts": "1.9.8"
  }
}
libs/better-framework/gutenberg/dev/README.md000064400000003763151214002630014777 0ustar00This project was bootstrapped with [Create Guten Block](https://github.com/ahmadawais/create-guten-block).

Below you will find some information on how to run scripts.

>You can find the most recent version of this guide [here](https://github.com/ahmadawais/create-guten-block).

## 👉  `npm start`
- Use to compile and run the block in development mode.
- Watches for any changes and reports back any errors in your code.

## 👉  `npm run build`
- Use to build production code for your block inside `dist` folder.
- Runs once and reports back the gzip file sizes of the produced code.

## 👉  `npm run eject`
- Use to eject your plugin out of `create-guten-block`.
- Provides all the configurations so you can customize the project as you want.
- It's a one-way street, `eject` and you have to maintain everything yourself.
- You don't normally have to `eject` a project because by ejecting you lose the connection with `create-guten-block` and from there onwards you have to update and maintain all the dependencies on your own.

---

###### Feel free to tweet and say 👋 at me [@MrAhmadAwais](https://twitter.com/mrahmadawais/)

[![npm](https://img.shields.io/npm/v/create-guten-block.svg?style=flat-square)](https://www.npmjs.com/package/create-guten-block) [![npm](https://img.shields.io/npm/dt/create-guten-block.svg?style=flat-square&label=downloads)](https://www.npmjs.com/package/create-guten-block)  [![license](https://img.shields.io/github/license/mashape/apistatus.svg?style=flat-square)](https://github.com/ahmadawais/create-guten-block) [![Tweet for help](https://img.shields.io/twitter/follow/mrahmadawais.svg?style=social&label=Tweet%20@MrAhmadAwais)](https://twitter.com/mrahmadawais/) [![GitHub stars](https://img.shields.io/github/stars/ahmadawais/create-guten-block.svg?style=social&label=Stars)](https://github.com/ahmadawais/create-guten-block/stargazers) [![GitHub followers](https://img.shields.io/github/followers/ahmadawais.svg?style=social&label=Follow)](https://github.com/ahmadawais?tab=followers)libs/better-framework/gutenberg/dev/package-lock.json000064400000750625151214002630016742 0ustar00{
  "name": "dev-cgb-guten-block",
  "version": "1.0.0",
  "lockfileVersion": 1,
  "requires": true,
  "dependencies": {
    "@babel/code-frame": {
      "version": "7.0.0-beta.44",
      "resolved": "http://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz",
      "integrity": "sha512-cuAuTTIQ9RqcFRJ/Y8PvTh+paepNcaGxwQwjIDRWPXmzzyAeCO4KqS9ikMvq0MCbRk6GlYKwfzStrcP3/jSL8g==",
      "requires": {
        "@babel/highlight": "7.0.0-beta.44"
      }
    },
    "@babel/generator": {
      "version": "7.0.0-beta.44",
      "resolved": "http://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.44.tgz",
      "integrity": "sha512-5xVb7hlhjGcdkKpMXgicAVgx8syK5VJz193k0i/0sLP6DzE6lRrU1K3B/rFefgdo9LPGMAOOOAWW4jycj07ShQ==",
      "requires": {
        "@babel/types": "7.0.0-beta.44",
        "jsesc": "2.5.1",
        "lodash": "4.17.10",
        "source-map": "0.5.7",
        "trim-right": "1.0.1"
      },
      "dependencies": {
        "jsesc": {
          "version": "2.5.1",
          "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.1.tgz",
          "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4="
        },
        "source-map": {
          "version": "0.5.7",
          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
        }
      }
    },
    "@babel/helper-function-name": {
      "version": "7.0.0-beta.44",
      "resolved": "http://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz",
      "integrity": "sha512-MHRG2qZMKMFaBavX0LWpfZ2e+hLloT++N7rfM3DYOMUOGCD8cVjqZpwiL8a0bOX3IYcQev1ruciT0gdFFRTxzg==",
      "requires": {
        "@babel/helper-get-function-arity": "7.0.0-beta.44",
        "@babel/template": "7.0.0-beta.44",
        "@babel/types": "7.0.0-beta.44"
      }
    },
    "@babel/helper-get-function-arity": {
      "version": "7.0.0-beta.44",
      "resolved": "http://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.44.tgz",
      "integrity": "sha512-w0YjWVwrM2HwP6/H3sEgrSQdkCaxppqFeJtAnB23pRiJB5E/O9Yp7JAAeWBl+gGEgmBFinnTyOv2RN7rcSmMiw==",
      "requires": {
        "@babel/types": "7.0.0-beta.44"
      }
    },
    "@babel/helper-split-export-declaration": {
      "version": "7.0.0-beta.44",
      "resolved": "http://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz",
      "integrity": "sha512-aQ7QowtkgKKzPGf0j6u77kBMdUFVBKNHw2p/3HX/POt5/oz8ec5cs0GwlgM8Hz7ui5EwJnzyfRmkNF1Nx1N7aA==",
      "requires": {
        "@babel/types": "7.0.0-beta.44"
      }
    },
    "@babel/highlight": {
      "version": "7.0.0-beta.44",
      "resolved": "http://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.44.tgz",
      "integrity": "sha512-Il19yJvy7vMFm8AVAh6OZzaFoAd0hbkeMZiX3P5HGD+z7dyI7RzndHB0dg6Urh/VAFfHtpOIzDUSxmY6coyZWQ==",
      "requires": {
        "chalk": "2.4.1",
        "esutils": "2.0.2",
        "js-tokens": "3.0.2"
      }
    },
    "@babel/template": {
      "version": "7.0.0-beta.44",
      "resolved": "http://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.44.tgz",
      "integrity": "sha512-w750Sloq0UNifLx1rUqwfbnC6uSUk0mfwwgGRfdLiaUzfAOiH0tHJE6ILQIUi3KYkjiCDTskoIsnfqZvWLBDng==",
      "requires": {
        "@babel/code-frame": "7.0.0-beta.44",
        "@babel/types": "7.0.0-beta.44",
        "babylon": "7.0.0-beta.44",
        "lodash": "4.17.10"
      },
      "dependencies": {
        "babylon": {
          "version": "7.0.0-beta.44",
          "resolved": "http://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz",
          "integrity": "sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g=="
        }
      }
    },
    "@babel/traverse": {
      "version": "7.0.0-beta.44",
      "resolved": "http://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.44.tgz",
      "integrity": "sha512-UHuDz8ukQkJCDASKHf+oDt3FVUzFd+QYfuBIsiNu/4+/ix6pP/C+uQZJ6K1oEfbCMv/IKWbgDEh7fcsnIE5AtA==",
      "requires": {
        "@babel/code-frame": "7.0.0-beta.44",
        "@babel/generator": "7.0.0-beta.44",
        "@babel/helper-function-name": "7.0.0-beta.44",
        "@babel/helper-split-export-declaration": "7.0.0-beta.44",
        "@babel/types": "7.0.0-beta.44",
        "babylon": "7.0.0-beta.44",
        "debug": "3.1.0",
        "globals": "11.7.0",
        "invariant": "2.2.4",
        "lodash": "4.17.10"
      },
      "dependencies": {
        "babylon": {
          "version": "7.0.0-beta.44",
          "resolved": "http://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz",
          "integrity": "sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g=="
        },
        "debug": {
          "version": "3.1.0",
          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
          "requires": {
            "ms": "2.0.0"
          }
        },
        "globals": {
          "version": "11.7.0",
          "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz",
          "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg=="
        }
      }
    },
    "@babel/types": {
      "version": "7.0.0-beta.44",
      "resolved": "http://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.44.tgz",
      "integrity": "sha512-5eTV4WRmqbaFM3v9gHAIljEQJU4Ssc6fxL61JN+Oe2ga/BwyjzjamwkCVVAQjHGuAX8i0BWo42dshL8eO5KfLQ==",
      "requires": {
        "esutils": "2.0.2",
        "lodash": "4.17.10",
        "to-fast-properties": "2.0.0"
      },
      "dependencies": {
        "to-fast-properties": {
          "version": "2.0.0",
          "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
          "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
        }
      }
    },
    "abbrev": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
      "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
    },
    "acorn": {
      "version": "5.7.2",
      "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.2.tgz",
      "integrity": "sha512-cJrKCNcr2kv8dlDnbw+JPUGjHZzo4myaxOLmpOX8a+rgX94YeTcTMv/LFJUSByRpc+i4GgVnnhLxvMu/2Y+rqw=="
    },
    "acorn-dynamic-import": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz",
      "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=",
      "requires": {
        "acorn": "4.0.13"
      },
      "dependencies": {
        "acorn": {
          "version": "4.0.13",
          "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz",
          "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c="
        }
      }
    },
    "acorn-jsx": {
      "version": "3.0.1",
      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
      "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
      "requires": {
        "acorn": "3.3.0"
      },
      "dependencies": {
        "acorn": {
          "version": "3.3.0",
          "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
          "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo="
        }
      }
    },
    "ajv": {
      "version": "5.5.2",
      "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
      "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
      "requires": {
        "co": "4.6.0",
        "fast-deep-equal": "1.1.0",
        "fast-json-stable-stringify": "2.0.0",
        "json-schema-traverse": "0.3.1"
      }
    },
    "ajv-keywords": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz",
      "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I="
    },
    "align-text": {
      "version": "0.1.4",
      "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
      "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
      "requires": {
        "kind-of": "3.2.2",
        "longest": "1.0.1",
        "repeat-string": "1.6.1"
      },
      "dependencies": {
        "kind-of": {
          "version": "3.2.2",
          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
          "requires": {
            "is-buffer": "1.1.6"
          }
        }
      }
    },
    "amdefine": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
      "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU="
    },
    "ansi-align": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz",
      "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=",
      "requires": {
        "string-width": "2.1.1"
      }
    },
    "ansi-escapes": {
      "version": "3.1.0",
      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
      "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw=="
    },
    "ansi-regex": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
      "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
    },
    "ansi-styles": {
      "version": "3.2.1",
      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
      "requires": {
        "color-convert": "1.9.3"
      }
    },
    "anymatch": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
      "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
      "requires": {
        "micromatch": "3.1.10",
        "normalize-path": "2.1.1"
      }
    },
    "aproba": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
      "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
    },
    "are-we-there-yet": {
      "version": "1.1.5",
      "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
      "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
      "requires": {
        "delegates": "1.0.0",
        "readable-stream": "2.3.6"
      }
    },
    "argparse": {
      "version": "1.0.10",
      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
      "requires": {
        "sprintf-js": "1.0.3"
      }
    },
    "aria-query": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz",
      "integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=",
      "requires": {
        "ast-types-flow": "0.0.7",
        "commander": "2.18.0"
      }
    },
    "arr-diff": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
      "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="
    },
    "arr-flatten": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
      "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg=="
    },
    "arr-union": {
      "version": "3.1.0",
      "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
      "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ="
    },
    "array-find-index": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
      "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E="
    },
    "array-includes": {
      "version": "3.0.3",
      "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz",
      "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=",
      "requires": {
        "define-properties": "1.1.3",
        "es-abstract": "1.12.0"
      }
    },
    "array-union": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
      "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
      "requires": {
        "array-uniq": "1.0.3"
      }
    },
    "array-uniq": {
      "version": "1.0.3",
      "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
      "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY="
    },
    "array-unique": {
      "version": "0.3.2",
      "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
      "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="
    },
    "arrify": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
      "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0="
    },
    "asn1": {
      "version": "0.2.4",
      "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
      "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
      "requires": {
        "safer-buffer": "2.1.2"
      }
    },
    "asn1.js": {
      "version": "4.10.1",
      "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
      "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
      "requires": {
        "bn.js": "4.11.8",
        "inherits": "2.0.3",
        "minimalistic-assert": "1.0.1"
      }
    },
    "assert": {
      "version": "1.4.1",
      "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz",
      "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=",
      "requires": {
        "util": "0.10.3"
      },
      "dependencies": {
        "inherits": {
          "version": "2.0.1",
          "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
          "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE="
        },
        "util": {
          "version": "0.10.3",
          "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
          "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
          "requires": {
            "inherits": "2.0.1"
          }
        }
      }
    },
    "assert-plus": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
      "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
    },
    "assign-symbols": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
      "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c="
    },
    "ast-types-flow": {
      "version": "0.0.7",
      "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
      "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0="
    },
    "async": {
      "version": "2.6.1",
      "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz",
      "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==",
      "requires": {
        "lodash": "4.17.10"
      }
    },
    "async-each": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
      "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0="
    },
    "async-foreach": {
      "version": "0.1.3",
      "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
      "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI="
    },
    "asynckit": {
      "version": "0.4.0",
      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
      "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
    },
    "atob": {
      "version": "2.1.2",
      "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
      "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg=="
    },
    "autoprefixer": {
      "version": "7.2.6",
      "resolved": "http://registry.npmjs.org/autoprefixer/-/autoprefixer-7.2.6.tgz",
      "integrity": "sha512-Iq8TRIB+/9eQ8rbGhcP7ct5cYb/3qjNYAR2SnzLCEcwF6rvVOax8+9+fccgXk4bEhQGjOZd5TLhsksmAdsbGqQ==",
      "requires": {
        "browserslist": "2.11.3",
        "caniuse-lite": "1.0.30000885",
        "normalize-range": "0.1.2",
        "num2fraction": "1.2.2",
        "postcss": "6.0.23",
        "postcss-value-parser": "3.3.0"
      }
    },
    "aws-sign2": {
      "version": "0.7.0",
      "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
      "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
    },
    "aws4": {
      "version": "1.8.0",
      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
      "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
    },
    "axobject-query": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.1.tgz",
      "integrity": "sha1-Bd+nBa2orZ25k/polvItOVsLCgc=",
      "requires": {
        "ast-types-flow": "0.0.7"
      }
    },
    "babel-code-frame": {
      "version": "6.26.0",
      "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
      "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
      "requires": {
        "chalk": "1.1.3",
        "esutils": "2.0.2",
        "js-tokens": "3.0.2"
      },
      "dependencies": {
        "ansi-styles": {
          "version": "2.2.1",
          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
        },
        "chalk": {
          "version": "1.1.3",
          "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
          "requires": {
            "ansi-styles": "2.2.1",
            "escape-string-regexp": "1.0.5",
            "has-ansi": "2.0.0",
            "strip-ansi": "3.0.1",
            "supports-color": "2.0.0"
          }
        },
        "supports-color": {
          "version": "2.0.0",
          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
        }
      }
    },
    "babel-core": {
      "version": "6.26.3",
      "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz",
      "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==",
      "requires": {
        "babel-code-frame": "6.26.0",
        "babel-generator": "6.26.1",
        "babel-helpers": "6.24.1",
        "babel-messages": "6.23.0",
        "babel-register": "6.26.0",
        "babel-runtime": "6.26.0",
        "babel-template": "6.26.0",
        "babel-traverse": "6.26.0",
        "babel-types": "6.26.0",
        "babylon": "6.18.0",
        "convert-source-map": "1.6.0",
        "debug": "2.6.9",
        "json5": "0.5.1",
        "lodash": "4.17.10",
        "minimatch": "3.0.4",
        "path-is-absolute": "1.0.1",
        "private": "0.1.8",
        "slash": "1.0.0",
        "source-map": "0.5.7"
      },
      "dependencies": {
        "source-map": {
          "version": "0.5.7",
          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
        }
      }
    },
    "babel-eslint": {
      "version": "8.2.6",
      "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-8.2.6.tgz",
      "integrity": "sha512-aCdHjhzcILdP8c9lej7hvXKvQieyRt20SF102SIGyY4cUIiw6UaAtK4j2o3dXX74jEmy0TJ0CEhv4fTIM3SzcA==",
      "requires": {
        "@babel/code-frame": "7.0.0-beta.44",
        "@babel/traverse": "7.0.0-beta.44",
        "@babel/types": "7.0.0-beta.44",
        "babylon": "7.0.0-beta.44",
        "eslint-scope": "3.7.1",
        "eslint-visitor-keys": "1.0.0"
      },
      "dependencies": {
        "babylon": {
          "version": "7.0.0-beta.44",
          "resolved": "http://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.44.tgz",
          "integrity": "sha512-5Hlm13BJVAioCHpImtFqNOF2H3ieTOHd0fmFGMxOJ9jgeFqeAwsv3u5P5cR7CSeFrkgHsT19DgFJkHV0/Mcd8g=="
        }
      }
    },
    "babel-generator": {
      "version": "6.26.1",
      "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz",
      "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==",
      "requires": {
        "babel-messages": "6.23.0",
        "babel-runtime": "6.26.0",
        "babel-types": "6.26.0",
        "detect-indent": "4.0.0",
        "jsesc": "1.3.0",
        "lodash": "4.17.10",
        "source-map": "0.5.7",
        "trim-right": "1.0.1"
      },
      "dependencies": {
        "source-map": {
          "version": "0.5.7",
          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
        }
      }
    },
    "babel-helper-builder-binary-assignment-operator-visitor": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz",
      "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=",
      "requires": {
        "babel-helper-explode-assignable-expression": "6.24.1",
        "babel-runtime": "6.26.0",
        "babel-types": "6.26.0"
      }
    },
    "babel-helper-builder-react-jsx": {
      "version": "6.26.0",
      "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz",
      "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=",
      "requires": {
        "babel-runtime": "6.26.0",
        "babel-types": "6.26.0",
        "esutils": "2.0.2"
      }
    },
    "babel-helper-call-delegate": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz",
      "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=",
      "requires": {
        "babel-helper-hoist-variables": "6.24.1",
        "babel-runtime": "6.26.0",
        "babel-traverse": "6.26.0",
        "babel-types": "6.26.0"
      }
    },
    "babel-helper-define-map": {
      "version": "6.26.0",
      "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz",
      "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=",
      "requires": {
        "babel-helper-function-name": "6.24.1",
        "babel-runtime": "6.26.0",
        "babel-types": "6.26.0",
        "lodash": "4.17.10"
      }
    },
    "babel-helper-explode-assignable-expression": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz",
      "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=",
      "requires": {
        "babel-runtime": "6.26.0",
        "babel-traverse": "6.26.0",
        "babel-types": "6.26.0"
      }
    },
    "babel-helper-function-name": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz",
      "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=",
      "requires": {
        "babel-helper-get-function-arity": "6.24.1",
        "babel-runtime": "6.26.0",
        "babel-template": "6.26.0",
        "babel-traverse": "6.26.0",
        "babel-types": "6.26.0"
      }
    },
    "babel-helper-get-function-arity": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz",
      "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=",
      "requires": {
        "babel-runtime": "6.26.0",
        "babel-types": "6.26.0"
      }
    },
    "babel-helper-hoist-variables": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz",
      "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=",
      "requires": {
        "babel-runtime": "6.26.0",
        "babel-types": "6.26.0"
      }
    },
    "babel-helper-optimise-call-expression": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz",
      "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=",
      "requires": {
        "babel-runtime": "6.26.0",
        "babel-types": "6.26.0"
      }
    },
    "babel-helper-regex": {
      "version": "6.26.0",
      "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz",
      "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=",
      "requires": {
        "babel-runtime": "6.26.0",
        "babel-types": "6.26.0",
        "lodash": "4.17.10"
      }
    },
    "babel-helper-remap-async-to-generator": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz",
      "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=",
      "requires": {
        "babel-helper-function-name": "6.24.1",
        "babel-runtime": "6.26.0",
        "babel-template": "6.26.0",
        "babel-traverse": "6.26.0",
        "babel-types": "6.26.0"
      }
    },
    "babel-helper-replace-supers": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz",
      "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=",
      "requires": {
        "babel-helper-optimise-call-expression": "6.24.1",
        "babel-messages": "6.23.0",
        "babel-runtime": "6.26.0",
        "babel-template": "6.26.0",
        "babel-traverse": "6.26.0",
        "babel-types": "6.26.0"
      }
    },
    "babel-helpers": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz",
      "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=",
      "requires": {
        "babel-runtime": "6.26.0",
        "babel-template": "6.26.0"
      }
    },
    "babel-loader": {
      "version": "7.1.5",
      "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.5.tgz",
      "integrity": "sha512-iCHfbieL5d1LfOQeeVJEUyD9rTwBcP/fcEbRCfempxTDuqrKpu0AZjLAQHEQa3Yqyj9ORKe2iHfoj4rHLf7xpw==",
      "requires": {
        "find-cache-dir": "1.0.0",
        "loader-utils": "1.1.0",
        "mkdirp": "0.5.1"
      }
    },
    "babel-messages": {
      "version": "6.23.0",
      "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
      "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
      "requires": {
        "babel-runtime": "6.26.0"
      }
    },
    "babel-plugin-check-es2015-constants": {
      "version": "6.22.0",
      "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz",
      "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=",
      "requires": {
        "babel-runtime": "6.26.0"
      }
    },
    "babel-plugin-syntax-async-functions": {
      "version": "6.13.0",
      "resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
      "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU="
    },
    "babel-plugin-syntax-class-properties": {
      "version": "6.13.0",
      "resolved": "http://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz",
      "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94="
    },
    "babel-plugin-syntax-exponentiation-operator": {
      "version": "6.13.0",
      "resolved": "http://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz",
      "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4="
    },
    "babel-plugin-syntax-jsx": {
      "version": "6.18.0",
      "resolved": "http://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
      "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY="
    },
    "babel-plugin-syntax-object-rest-spread": {
      "version": "6.13.0",
      "resolved": "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
      "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U="
    },
    "babel-plugin-syntax-trailing-function-commas": {
      "version": "6.22.0",
      "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz",
      "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM="
    },
    "babel-plugin-transform-async-to-generator": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz",
      "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=",
      "requires": {
        "babel-helper-remap-async-to-generator": "6.24.1",
        "babel-plugin-syntax-async-functions": "6.13.0",
        "babel-runtime": "6.26.0"
      }
    },
    "babel-plugin-transform-class-properties": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz",
      "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=",
      "requires": {
        "babel-helper-function-name": "6.24.1",
        "babel-plugin-syntax-class-properties": "6.13.0",
        "babel-runtime": "6.26.0",
        "babel-template": "6.26.0"
      }
    },
    "babel-plugin-transform-es2015-arrow-functions": {
      "version": "6.22.0",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz",
      "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=",
      "requires": {
        "babel-runtime": "6.26.0"
      }
    },
    "babel-plugin-transform-es2015-block-scoped-functions": {
      "version": "6.22.0",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz",
      "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=",
      "requires": {
        "babel-runtime": "6.26.0"
      }
    },
    "babel-plugin-transform-es2015-block-scoping": {
      "version": "6.26.0",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz",
      "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=",
      "requires": {
        "babel-runtime": "6.26.0",
        "babel-template": "6.26.0",
        "babel-traverse": "6.26.0",
        "babel-types": "6.26.0",
        "lodash": "4.17.10"
      }
    },
    "babel-plugin-transform-es2015-classes": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz",
      "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=",
      "requires": {
        "babel-helper-define-map": "6.26.0",
        "babel-helper-function-name": "6.24.1",
        "babel-helper-optimise-call-expression": "6.24.1",
        "babel-helper-replace-supers": "6.24.1",
        "babel-messages": "6.23.0",
        "babel-runtime": "6.26.0",
        "babel-template": "6.26.0",
        "babel-traverse": "6.26.0",
        "babel-types": "6.26.0"
      }
    },
    "babel-plugin-transform-es2015-computed-properties": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz",
      "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=",
      "requires": {
        "babel-runtime": "6.26.0",
        "babel-template": "6.26.0"
      }
    },
    "babel-plugin-transform-es2015-destructuring": {
      "version": "6.23.0",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz",
      "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=",
      "requires": {
        "babel-runtime": "6.26.0"
      }
    },
    "babel-plugin-transform-es2015-duplicate-keys": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz",
      "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=",
      "requires": {
        "babel-runtime": "6.26.0",
        "babel-types": "6.26.0"
      }
    },
    "babel-plugin-transform-es2015-for-of": {
      "version": "6.23.0",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz",
      "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=",
      "requires": {
        "babel-runtime": "6.26.0"
      }
    },
    "babel-plugin-transform-es2015-function-name": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz",
      "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=",
      "requires": {
        "babel-helper-function-name": "6.24.1",
        "babel-runtime": "6.26.0",
        "babel-types": "6.26.0"
      }
    },
    "babel-plugin-transform-es2015-literals": {
      "version": "6.22.0",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz",
      "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=",
      "requires": {
        "babel-runtime": "6.26.0"
      }
    },
    "babel-plugin-transform-es2015-modules-amd": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz",
      "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=",
      "requires": {
        "babel-plugin-transform-es2015-modules-commonjs": "6.26.2",
        "babel-runtime": "6.26.0",
        "babel-template": "6.26.0"
      }
    },
    "babel-plugin-transform-es2015-modules-commonjs": {
      "version": "6.26.2",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz",
      "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==",
      "requires": {
        "babel-plugin-transform-strict-mode": "6.24.1",
        "babel-runtime": "6.26.0",
        "babel-template": "6.26.0",
        "babel-types": "6.26.0"
      }
    },
    "babel-plugin-transform-es2015-modules-systemjs": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz",
      "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=",
      "requires": {
        "babel-helper-hoist-variables": "6.24.1",
        "babel-runtime": "6.26.0",
        "babel-template": "6.26.0"
      }
    },
    "babel-plugin-transform-es2015-modules-umd": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz",
      "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=",
      "requires": {
        "babel-plugin-transform-es2015-modules-amd": "6.24.1",
        "babel-runtime": "6.26.0",
        "babel-template": "6.26.0"
      }
    },
    "babel-plugin-transform-es2015-object-super": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz",
      "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=",
      "requires": {
        "babel-helper-replace-supers": "6.24.1",
        "babel-runtime": "6.26.0"
      }
    },
    "babel-plugin-transform-es2015-parameters": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz",
      "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=",
      "requires": {
        "babel-helper-call-delegate": "6.24.1",
        "babel-helper-get-function-arity": "6.24.1",
        "babel-runtime": "6.26.0",
        "babel-template": "6.26.0",
        "babel-traverse": "6.26.0",
        "babel-types": "6.26.0"
      }
    },
    "babel-plugin-transform-es2015-shorthand-properties": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz",
      "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=",
      "requires": {
        "babel-runtime": "6.26.0",
        "babel-types": "6.26.0"
      }
    },
    "babel-plugin-transform-es2015-spread": {
      "version": "6.22.0",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz",
      "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=",
      "requires": {
        "babel-runtime": "6.26.0"
      }
    },
    "babel-plugin-transform-es2015-sticky-regex": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz",
      "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=",
      "requires": {
        "babel-helper-regex": "6.26.0",
        "babel-runtime": "6.26.0",
        "babel-types": "6.26.0"
      }
    },
    "babel-plugin-transform-es2015-template-literals": {
      "version": "6.22.0",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz",
      "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=",
      "requires": {
        "babel-runtime": "6.26.0"
      }
    },
    "babel-plugin-transform-es2015-typeof-symbol": {
      "version": "6.23.0",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz",
      "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=",
      "requires": {
        "babel-runtime": "6.26.0"
      }
    },
    "babel-plugin-transform-es2015-unicode-regex": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz",
      "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=",
      "requires": {
        "babel-helper-regex": "6.26.0",
        "babel-runtime": "6.26.0",
        "regexpu-core": "2.0.0"
      }
    },
    "babel-plugin-transform-exponentiation-operator": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz",
      "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=",
      "requires": {
        "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1",
        "babel-plugin-syntax-exponentiation-operator": "6.13.0",
        "babel-runtime": "6.26.0"
      }
    },
    "babel-plugin-transform-object-rest-spread": {
      "version": "6.26.0",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz",
      "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=",
      "requires": {
        "babel-plugin-syntax-object-rest-spread": "6.13.0",
        "babel-runtime": "6.26.0"
      }
    },
    "babel-plugin-transform-react-jsx": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz",
      "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=",
      "requires": {
        "babel-helper-builder-react-jsx": "6.26.0",
        "babel-plugin-syntax-jsx": "6.18.0",
        "babel-runtime": "6.26.0"
      }
    },
    "babel-plugin-transform-regenerator": {
      "version": "6.26.0",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz",
      "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=",
      "requires": {
        "regenerator-transform": "0.10.1"
      }
    },
    "babel-plugin-transform-runtime": {
      "version": "6.23.0",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz",
      "integrity": "sha1-iEkNRGUC6puOfvsP4J7E2ZR5se4=",
      "requires": {
        "babel-runtime": "6.26.0"
      }
    },
    "babel-plugin-transform-strict-mode": {
      "version": "6.24.1",
      "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz",
      "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=",
      "requires": {
        "babel-runtime": "6.26.0",
        "babel-types": "6.26.0"
      }
    },
    "babel-preset-cgb": {
      "version": "1.5.0",
      "resolved": "https://registry.npmjs.org/babel-preset-cgb/-/babel-preset-cgb-1.5.0.tgz",
      "integrity": "sha512-kFkGgj0hM8iLimtYiq3xcjuidbu8+VJu5EcFvKb9natpZqJJZD4Gcq0UrTZjt+ZrK93VHU9B2KaqvmTh4acqOw==",
      "requires": {
        "babel-plugin-syntax-async-functions": "6.13.0",
        "babel-plugin-transform-class-properties": "6.24.1",
        "babel-plugin-transform-object-rest-spread": "6.26.0",
        "babel-plugin-transform-react-jsx": "6.24.1",
        "babel-plugin-transform-runtime": "6.23.0",
        "babel-preset-env": "1.7.0",
        "update-notifier": "2.5.0"
      }
    },
    "babel-preset-env": {
      "version": "1.7.0",
      "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz",
      "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==",
      "requires": {
        "babel-plugin-check-es2015-constants": "6.22.0",
        "babel-plugin-syntax-trailing-function-commas": "6.22.0",
        "babel-plugin-transform-async-to-generator": "6.24.1",
        "babel-plugin-transform-es2015-arrow-functions": "6.22.0",
        "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0",
        "babel-plugin-transform-es2015-block-scoping": "6.26.0",
        "babel-plugin-transform-es2015-classes": "6.24.1",
        "babel-plugin-transform-es2015-computed-properties": "6.24.1",
        "babel-plugin-transform-es2015-destructuring": "6.23.0",
        "babel-plugin-transform-es2015-duplicate-keys": "6.24.1",
        "babel-plugin-transform-es2015-for-of": "6.23.0",
        "babel-plugin-transform-es2015-function-name": "6.24.1",
        "babel-plugin-transform-es2015-literals": "6.22.0",
        "babel-plugin-transform-es2015-modules-amd": "6.24.1",
        "babel-plugin-transform-es2015-modules-commonjs": "6.26.2",
        "babel-plugin-transform-es2015-modules-systemjs": "6.24.1",
        "babel-plugin-transform-es2015-modules-umd": "6.24.1",
        "babel-plugin-transform-es2015-object-super": "6.24.1",
        "babel-plugin-transform-es2015-parameters": "6.24.1",
        "babel-plugin-transform-es2015-shorthand-properties": "6.24.1",
        "babel-plugin-transform-es2015-spread": "6.22.0",
        "babel-plugin-transform-es2015-sticky-regex": "6.24.1",
        "babel-plugin-transform-es2015-template-literals": "6.22.0",
        "babel-plugin-transform-es2015-typeof-symbol": "6.23.0",
        "babel-plugin-transform-es2015-unicode-regex": "6.24.1",
        "babel-plugin-transform-exponentiation-operator": "6.24.1",
        "babel-plugin-transform-regenerator": "6.26.0",
        "browserslist": "3.2.8",
        "invariant": "2.2.4",
        "semver": "5.5.1"
      },
      "dependencies": {
        "browserslist": {
          "version": "3.2.8",
          "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz",
          "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==",
          "requires": {
            "caniuse-lite": "1.0.30000885",
            "electron-to-chromium": "1.3.64"
          }
        }
      }
    },
    "babel-register": {
      "version": "6.26.0",
      "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz",
      "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=",
      "requires": {
        "babel-core": "6.26.3",
        "babel-runtime": "6.26.0",
        "core-js": "2.5.7",
        "home-or-tmp": "2.0.0",
        "lodash": "4.17.10",
        "mkdirp": "0.5.1",
        "source-map-support": "0.4.18"
      }
    },
    "babel-runtime": {
      "version": "6.26.0",
      "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
      "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
      "requires": {
        "core-js": "2.5.7",
        "regenerator-runtime": "0.11.1"
      }
    },
    "babel-template": {
      "version": "6.26.0",
      "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz",
      "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=",
      "requires": {
        "babel-runtime": "6.26.0",
        "babel-traverse": "6.26.0",
        "babel-types": "6.26.0",
        "babylon": "6.18.0",
        "lodash": "4.17.10"
      }
    },
    "babel-traverse": {
      "version": "6.26.0",
      "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz",
      "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=",
      "requires": {
        "babel-code-frame": "6.26.0",
        "babel-messages": "6.23.0",
        "babel-runtime": "6.26.0",
        "babel-types": "6.26.0",
        "babylon": "6.18.0",
        "debug": "2.6.9",
        "globals": "9.18.0",
        "invariant": "2.2.4",
        "lodash": "4.17.10"
      }
    },
    "babel-types": {
      "version": "6.26.0",
      "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
      "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
      "requires": {
        "babel-runtime": "6.26.0",
        "esutils": "2.0.2",
        "lodash": "4.17.10",
        "to-fast-properties": "1.0.3"
      }
    },
    "babylon": {
      "version": "6.18.0",
      "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
      "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ=="
    },
    "balanced-match": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
    },
    "base": {
      "version": "0.11.2",
      "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
      "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
      "requires": {
        "cache-base": "1.0.1",
        "class-utils": "0.3.6",
        "component-emitter": "1.2.1",
        "define-property": "1.0.0",
        "isobject": "3.0.1",
        "mixin-deep": "1.3.1",
        "pascalcase": "0.1.1"
      },
      "dependencies": {
        "define-property": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
          "requires": {
            "is-descriptor": "1.0.2"
          }
        },
        "is-accessor-descriptor": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
          "requires": {
            "kind-of": "6.0.2"
          }
        },
        "is-data-descriptor": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
          "requires": {
            "kind-of": "6.0.2"
          }
        },
        "is-descriptor": {
          "version": "1.0.2",
          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
          "requires": {
            "is-accessor-descriptor": "1.0.0",
            "is-data-descriptor": "1.0.0",
            "kind-of": "6.0.2"
          }
        }
      }
    },
    "base64-js": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz",
      "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw=="
    },
    "bcrypt-pbkdf": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
      "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
      "optional": true,
      "requires": {
        "tweetnacl": "0.14.5"
      }
    },
    "big.js": {
      "version": "3.2.0",
      "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz",
      "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q=="
    },
    "binary-extensions": {
      "version": "1.11.0",
      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz",
      "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU="
    },
    "block-stream": {
      "version": "0.0.9",
      "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
      "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
      "requires": {
        "inherits": "2.0.3"
      }
    },
    "bn.js": {
      "version": "4.11.8",
      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
      "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA=="
    },
    "boxen": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz",
      "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==",
      "requires": {
        "ansi-align": "2.0.0",
        "camelcase": "4.1.0",
        "chalk": "2.4.1",
        "cli-boxes": "1.0.0",
        "string-width": "2.1.1",
        "term-size": "1.2.0",
        "widest-line": "2.0.0"
      }
    },
    "brace-expansion": {
      "version": "1.1.11",
      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
      "requires": {
        "balanced-match": "1.0.0",
        "concat-map": "0.0.1"
      }
    },
    "braces": {
      "version": "2.3.2",
      "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
      "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
      "requires": {
        "arr-flatten": "1.1.0",
        "array-unique": "0.3.2",
        "extend-shallow": "2.0.1",
        "fill-range": "4.0.0",
        "isobject": "3.0.1",
        "repeat-element": "1.1.3",
        "snapdragon": "0.8.2",
        "snapdragon-node": "2.1.1",
        "split-string": "3.1.0",
        "to-regex": "3.0.2"
      },
      "dependencies": {
        "extend-shallow": {
          "version": "2.0.1",
          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
          "requires": {
            "is-extendable": "0.1.1"
          }
        }
      }
    },
    "brorand": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
      "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8="
    },
    "browserify-aes": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
      "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
      "requires": {
        "buffer-xor": "1.0.3",
        "cipher-base": "1.0.4",
        "create-hash": "1.2.0",
        "evp_bytestokey": "1.0.3",
        "inherits": "2.0.3",
        "safe-buffer": "5.1.2"
      }
    },
    "browserify-cipher": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz",
      "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==",
      "requires": {
        "browserify-aes": "1.2.0",
        "browserify-des": "1.0.2",
        "evp_bytestokey": "1.0.3"
      }
    },
    "browserify-des": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz",
      "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==",
      "requires": {
        "cipher-base": "1.0.4",
        "des.js": "1.0.0",
        "inherits": "2.0.3",
        "safe-buffer": "5.1.2"
      }
    },
    "browserify-rsa": {
      "version": "4.0.1",
      "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
      "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
      "requires": {
        "bn.js": "4.11.8",
        "randombytes": "2.0.6"
      }
    },
    "browserify-sign": {
      "version": "4.0.4",
      "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz",
      "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=",
      "requires": {
        "bn.js": "4.11.8",
        "browserify-rsa": "4.0.1",
        "create-hash": "1.2.0",
        "create-hmac": "1.1.7",
        "elliptic": "6.4.1",
        "inherits": "2.0.3",
        "parse-asn1": "5.1.1"
      }
    },
    "browserify-zlib": {
      "version": "0.2.0",
      "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
      "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
      "requires": {
        "pako": "1.0.6"
      }
    },
    "browserslist": {
      "version": "2.11.3",
      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz",
      "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==",
      "requires": {
        "caniuse-lite": "1.0.30000885",
        "electron-to-chromium": "1.3.64"
      }
    },
    "buffer": {
      "version": "4.9.1",
      "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
      "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
      "requires": {
        "base64-js": "1.3.0",
        "ieee754": "1.1.12",
        "isarray": "1.0.0"
      }
    },
    "buffer-from": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
      "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
    },
    "buffer-xor": {
      "version": "1.0.3",
      "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
      "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk="
    },
    "builtin-modules": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
      "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8="
    },
    "builtin-status-codes": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
      "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug="
    },
    "cache-base": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
      "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
      "requires": {
        "collection-visit": "1.0.0",
        "component-emitter": "1.2.1",
        "get-value": "2.0.6",
        "has-value": "1.0.0",
        "isobject": "3.0.1",
        "set-value": "2.0.0",
        "to-object-path": "0.3.0",
        "union-value": "1.0.0",
        "unset-value": "1.0.0"
      }
    },
    "caller-path": {
      "version": "0.1.0",
      "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
      "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=",
      "requires": {
        "callsites": "0.2.0"
      }
    },
    "callsites": {
      "version": "0.2.0",
      "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
      "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo="
    },
    "camelcase": {
      "version": "4.1.0",
      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
      "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
    },
    "camelcase-keys": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
      "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
      "requires": {
        "camelcase": "2.1.1",
        "map-obj": "1.0.1"
      },
      "dependencies": {
        "camelcase": {
          "version": "2.1.1",
          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
          "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8="
        }
      }
    },
    "caniuse-lite": {
      "version": "1.0.30000885",
      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000885.tgz",
      "integrity": "sha512-cXKbYwpxBLd7qHyej16JazPoUacqoVuDhvR61U7Fr5vSxMUiodzcYa1rQYRYfZ5GexV03vGZHd722vNPLjPJGQ=="
    },
    "capture-stack-trace": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz",
      "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw=="
    },
    "caseless": {
      "version": "0.12.0",
      "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
      "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
    },
    "center-align": {
      "version": "0.1.3",
      "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
      "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
      "requires": {
        "align-text": "0.1.4",
        "lazy-cache": "1.0.4"
      }
    },
    "cgb-dev-utils": {
      "version": "1.4.0",
      "resolved": "https://registry.npmjs.org/cgb-dev-utils/-/cgb-dev-utils-1.4.0.tgz",
      "integrity": "sha512-7rbMj5ynviHcKy22fOvsEK6vYc+l10HWEfBHqBVEoX6Q6VCk0YylcoQQCpHZfJW9tKKx35hUTgLnrWh1OI1M5Q==",
      "requires": {
        "chalk": "2.3.0",
        "cross-spawn": "5.1.0",
        "update-notifier": "2.5.0"
      },
      "dependencies": {
        "chalk": {
          "version": "2.3.0",
          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
          "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
          "requires": {
            "ansi-styles": "3.2.1",
            "escape-string-regexp": "1.0.5",
            "supports-color": "4.5.0"
          }
        },
        "has-flag": {
          "version": "2.0.0",
          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
          "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
        },
        "supports-color": {
          "version": "4.5.0",
          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
          "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
          "requires": {
            "has-flag": "2.0.0"
          }
        }
      }
    },
    "cgb-scripts": {
      "version": "1.9.8",
      "resolved": "https://registry.npmjs.org/cgb-scripts/-/cgb-scripts-1.9.8.tgz",
      "integrity": "sha512-6lH+PV7dOX1NDTiMDSRyS2xCJ4dXeLHxjGXY7QqUXsW3lRwcStEGF20SEq94Icux65su2Ta3kBj6ZEQWn4sgqA==",
      "requires": {
        "autoprefixer": "7.2.6",
        "babel-core": "6.26.3",
        "babel-eslint": "8.2.6",
        "babel-loader": "7.1.5",
        "babel-preset-cgb": "1.5.0",
        "cgb-dev-utils": "1.4.0",
        "chalk": "2.4.1",
        "cross-env": "5.2.0",
        "cross-spawn": "5.1.0",
        "eslint": "4.19.1",
        "eslint-config-wordpress": "2.0.0",
        "eslint-plugin-jest": "21.22.0",
        "eslint-plugin-jsx-a11y": "6.1.1",
        "eslint-plugin-react": "7.11.1",
        "eslint-plugin-wordpress": "0.1.0",
        "extract-text-webpack-plugin": "3.0.2",
        "filesize": "3.6.1",
        "fs-extra": "5.0.0",
        "gzip-size": "4.1.0",
        "inquirer": "5.2.0",
        "node-sass": "4.9.3",
        "ora": "1.4.0",
        "postcss-loader": "2.1.6",
        "raw-loader": "0.5.1",
        "resolve-pkg": "1.0.0",
        "sass-loader": "6.0.7",
        "shelljs": "0.8.2",
        "style-loader": "0.19.1",
        "update-notifier": "2.5.0",
        "webpack": "3.12.0"
      }
    },
    "chalk": {
      "version": "2.4.1",
      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
      "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
      "requires": {
        "ansi-styles": "3.2.1",
        "escape-string-regexp": "1.0.5",
        "supports-color": "5.5.0"
      }
    },
    "chardet": {
      "version": "0.4.2",
      "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz",
      "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I="
    },
    "chokidar": {
      "version": "2.0.4",
      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz",
      "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==",
      "requires": {
        "anymatch": "2.0.0",
        "async-each": "1.0.1",
        "braces": "2.3.2",
        "fsevents": "1.2.4",
        "glob-parent": "3.1.0",
        "inherits": "2.0.3",
        "is-binary-path": "1.0.1",
        "is-glob": "4.0.0",
        "lodash.debounce": "4.0.8",
        "normalize-path": "2.1.1",
        "path-is-absolute": "1.0.1",
        "readdirp": "2.1.0",
        "upath": "1.1.0"
      }
    },
    "ci-info": {
      "version": "1.4.0",
      "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.4.0.tgz",
      "integrity": "sha512-Oqmw2pVfCl8sCL+1QgMywPfdxPJPkC51y4usw0iiE2S9qnEOAqXy8bwl1CpMpnoU39g4iKJTz6QZj+28FvOnjQ=="
    },
    "cipher-base": {
      "version": "1.0.4",
      "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
      "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
      "requires": {
        "inherits": "2.0.3",
        "safe-buffer": "5.1.2"
      }
    },
    "circular-json": {
      "version": "0.3.3",
      "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
      "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A=="
    },
    "class-utils": {
      "version": "0.3.6",
      "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
      "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
      "requires": {
        "arr-union": "3.1.0",
        "define-property": "0.2.5",
        "isobject": "3.0.1",
        "static-extend": "0.1.2"
      },
      "dependencies": {
        "define-property": {
          "version": "0.2.5",
          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
          "requires": {
            "is-descriptor": "0.1.6"
          }
        }
      }
    },
    "cli-boxes": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz",
      "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM="
    },
    "cli-cursor": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
      "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
      "requires": {
        "restore-cursor": "2.0.0"
      }
    },
    "cli-spinners": {
      "version": "1.3.1",
      "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-1.3.1.tgz",
      "integrity": "sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg=="
    },
    "cli-width": {
      "version": "2.2.0",
      "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
      "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk="
    },
    "cliui": {
      "version": "3.2.0",
      "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
      "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
      "requires": {
        "string-width": "1.0.2",
        "strip-ansi": "3.0.1",
        "wrap-ansi": "2.1.0"
      },
      "dependencies": {
        "is-fullwidth-code-point": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
          "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
          "requires": {
            "number-is-nan": "1.0.1"
          }
        },
        "string-width": {
          "version": "1.0.2",
          "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
          "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
          "requires": {
            "code-point-at": "1.1.0",
            "is-fullwidth-code-point": "1.0.0",
            "strip-ansi": "3.0.1"
          }
        }
      }
    },
    "clone-deep": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-2.0.2.tgz",
      "integrity": "sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ==",
      "requires": {
        "for-own": "1.0.0",
        "is-plain-object": "2.0.4",
        "kind-of": "6.0.2",
        "shallow-clone": "1.0.0"
      }
    },
    "co": {
      "version": "4.6.0",
      "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
      "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
    },
    "code-point-at": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
      "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
    },
    "collection-visit": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
      "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
      "requires": {
        "map-visit": "1.0.0",
        "object-visit": "1.0.1"
      }
    },
    "color-convert": {
      "version": "1.9.3",
      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
      "requires": {
        "color-name": "1.1.3"
      }
    },
    "color-name": {
      "version": "1.1.3",
      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
    },
    "combined-stream": {
      "version": "1.0.6",
      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
      "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
      "requires": {
        "delayed-stream": "1.0.0"
      }
    },
    "commander": {
      "version": "2.18.0",
      "resolved": "https://registry.npmjs.org/commander/-/commander-2.18.0.tgz",
      "integrity": "sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ=="
    },
    "commondir": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
      "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs="
    },
    "component-emitter": {
      "version": "1.2.1",
      "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
      "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
    },
    "concat-map": {
      "version": "0.0.1",
      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
    },
    "concat-stream": {
      "version": "1.6.2",
      "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
      "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
      "requires": {
        "buffer-from": "1.1.1",
        "inherits": "2.0.3",
        "readable-stream": "2.3.6",
        "typedarray": "0.0.6"
      }
    },
    "configstore": {
      "version": "3.1.2",
      "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz",
      "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==",
      "requires": {
        "dot-prop": "4.2.0",
        "graceful-fs": "4.1.11",
        "make-dir": "1.3.0",
        "unique-string": "1.0.0",
        "write-file-atomic": "2.3.0",
        "xdg-basedir": "3.0.0"
      }
    },
    "console-browserify": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
      "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
      "requires": {
        "date-now": "0.1.4"
      }
    },
    "console-control-strings": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
      "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
    },
    "constants-browserify": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
      "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U="
    },
    "convert-source-map": {
      "version": "1.6.0",
      "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz",
      "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==",
      "requires": {
        "safe-buffer": "5.1.2"
      }
    },
    "copy-descriptor": {
      "version": "0.1.1",
      "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
      "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="
    },
    "core-js": {
      "version": "2.5.7",
      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
      "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw=="
    },
    "core-util-is": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
    },
    "cosmiconfig": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz",
      "integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==",
      "requires": {
        "is-directory": "0.3.1",
        "js-yaml": "3.12.0",
        "parse-json": "4.0.0",
        "require-from-string": "2.0.2"
      },
      "dependencies": {
        "parse-json": {
          "version": "4.0.0",
          "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
          "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
          "requires": {
            "error-ex": "1.3.2",
            "json-parse-better-errors": "1.0.2"
          }
        }
      }
    },
    "create-ecdh": {
      "version": "4.0.3",
      "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
      "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==",
      "requires": {
        "bn.js": "4.11.8",
        "elliptic": "6.4.1"
      }
    },
    "create-error-class": {
      "version": "3.0.2",
      "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
      "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=",
      "requires": {
        "capture-stack-trace": "1.0.1"
      }
    },
    "create-hash": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
      "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
      "requires": {
        "cipher-base": "1.0.4",
        "inherits": "2.0.3",
        "md5.js": "1.3.4",
        "ripemd160": "2.0.2",
        "sha.js": "2.4.11"
      }
    },
    "create-hmac": {
      "version": "1.1.7",
      "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
      "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
      "requires": {
        "cipher-base": "1.0.4",
        "create-hash": "1.2.0",
        "inherits": "2.0.3",
        "ripemd160": "2.0.2",
        "safe-buffer": "5.1.2",
        "sha.js": "2.4.11"
      }
    },
    "cross-env": {
      "version": "5.2.0",
      "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.2.0.tgz",
      "integrity": "sha512-jtdNFfFW1hB7sMhr/H6rW1Z45LFqyI431m3qU6bFXcQ3Eh7LtBuG3h74o7ohHZ3crrRkkqHlo4jYHFPcjroANg==",
      "requires": {
        "cross-spawn": "6.0.5",
        "is-windows": "1.0.2"
      },
      "dependencies": {
        "cross-spawn": {
          "version": "6.0.5",
          "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
          "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
          "requires": {
            "nice-try": "1.0.5",
            "path-key": "2.0.1",
            "semver": "5.5.1",
            "shebang-command": "1.2.0",
            "which": "1.3.1"
          }
        }
      }
    },
    "cross-spawn": {
      "version": "5.1.0",
      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
      "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
      "requires": {
        "lru-cache": "4.1.3",
        "shebang-command": "1.2.0",
        "which": "1.3.1"
      }
    },
    "crypto-browserify": {
      "version": "3.12.0",
      "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
      "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
      "requires": {
        "browserify-cipher": "1.0.1",
        "browserify-sign": "4.0.4",
        "create-ecdh": "4.0.3",
        "create-hash": "1.2.0",
        "create-hmac": "1.1.7",
        "diffie-hellman": "5.0.3",
        "inherits": "2.0.3",
        "pbkdf2": "3.0.16",
        "public-encrypt": "4.0.2",
        "randombytes": "2.0.6",
        "randomfill": "1.0.4"
      }
    },
    "crypto-random-string": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz",
      "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4="
    },
    "currently-unhandled": {
      "version": "0.4.1",
      "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
      "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
      "requires": {
        "array-find-index": "1.0.2"
      }
    },
    "d": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz",
      "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=",
      "requires": {
        "es5-ext": "0.10.46"
      }
    },
    "damerau-levenshtein": {
      "version": "1.0.4",
      "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz",
      "integrity": "sha1-AxkcQyy27qFou3fzpV/9zLiXhRQ="
    },
    "dashdash": {
      "version": "1.14.1",
      "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
      "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
      "requires": {
        "assert-plus": "1.0.0"
      }
    },
    "date-now": {
      "version": "0.1.4",
      "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
      "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs="
    },
    "debug": {
      "version": "2.6.9",
      "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
      "requires": {
        "ms": "2.0.0"
      }
    },
    "decamelize": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
      "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
    },
    "decode-uri-component": {
      "version": "0.2.0",
      "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
      "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
    },
    "deep-extend": {
      "version": "0.6.0",
      "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
      "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
    },
    "deep-is": {
      "version": "0.1.3",
      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
      "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ="
    },
    "define-properties": {
      "version": "1.1.3",
      "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
      "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
      "requires": {
        "object-keys": "1.0.12"
      }
    },
    "define-property": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
      "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
      "requires": {
        "is-descriptor": "1.0.2",
        "isobject": "3.0.1"
      },
      "dependencies": {
        "is-accessor-descriptor": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
          "requires": {
            "kind-of": "6.0.2"
          }
        },
        "is-data-descriptor": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
          "requires": {
            "kind-of": "6.0.2"
          }
        },
        "is-descriptor": {
          "version": "1.0.2",
          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
          "requires": {
            "is-accessor-descriptor": "1.0.0",
            "is-data-descriptor": "1.0.0",
            "kind-of": "6.0.2"
          }
        }
      }
    },
    "del": {
      "version": "2.2.2",
      "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
      "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
      "requires": {
        "globby": "5.0.0",
        "is-path-cwd": "1.0.0",
        "is-path-in-cwd": "1.0.1",
        "object-assign": "4.1.1",
        "pify": "2.3.0",
        "pinkie-promise": "2.0.1",
        "rimraf": "2.6.2"
      },
      "dependencies": {
        "pify": {
          "version": "2.3.0",
          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
        }
      }
    },
    "delayed-stream": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
      "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
    },
    "delegates": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
      "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
    },
    "des.js": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz",
      "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=",
      "requires": {
        "inherits": "2.0.3",
        "minimalistic-assert": "1.0.1"
      }
    },
    "detect-indent": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
      "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=",
      "requires": {
        "repeating": "2.0.1"
      }
    },
    "diffie-hellman": {
      "version": "5.0.3",
      "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
      "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
      "requires": {
        "bn.js": "4.11.8",
        "miller-rabin": "4.0.1",
        "randombytes": "2.0.6"
      }
    },
    "doctrine": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
      "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
      "requires": {
        "esutils": "2.0.2"
      }
    },
    "domain-browser": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
      "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA=="
    },
    "dot-prop": {
      "version": "4.2.0",
      "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
      "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==",
      "requires": {
        "is-obj": "1.0.1"
      }
    },
    "duplexer": {
      "version": "0.1.1",
      "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
      "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E="
    },
    "duplexer3": {
      "version": "0.1.4",
      "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
      "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI="
    },
    "ecc-jsbn": {
      "version": "0.1.2",
      "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
      "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
      "optional": true,
      "requires": {
        "jsbn": "0.1.1",
        "safer-buffer": "2.1.2"
      }
    },
    "electron-to-chromium": {
      "version": "1.3.64",
      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.64.tgz",
      "integrity": "sha512-CU5ta5MbzRre+WhzKfPBM3HlyZGM7bwNKmiByzFzCfxP3q7cNmGLKopq5Q+LGXza69aIHXk2sZZSh/Oh7TKPIQ=="
    },
    "elliptic": {
      "version": "6.4.1",
      "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz",
      "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==",
      "requires": {
        "bn.js": "4.11.8",
        "brorand": "1.1.0",
        "hash.js": "1.1.5",
        "hmac-drbg": "1.0.1",
        "inherits": "2.0.3",
        "minimalistic-assert": "1.0.1",
        "minimalistic-crypto-utils": "1.0.1"
      }
    },
    "emoji-regex": {
      "version": "6.5.1",
      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.5.1.tgz",
      "integrity": "sha512-PAHp6TxrCy7MGMFidro8uikr+zlJJKJ/Q6mm2ExZ7HwkyR9lSVFfE3kt36qcwa24BQL7y0G9axycGjK1A/0uNQ=="
    },
    "emojis-list": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
      "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k="
    },
    "enhanced-resolve": {
      "version": "3.4.1",
      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz",
      "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=",
      "requires": {
        "graceful-fs": "4.1.11",
        "memory-fs": "0.4.1",
        "object-assign": "4.1.1",
        "tapable": "0.2.8"
      }
    },
    "errno": {
      "version": "0.1.7",
      "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
      "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
      "requires": {
        "prr": "1.0.1"
      }
    },
    "error-ex": {
      "version": "1.3.2",
      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
      "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
      "requires": {
        "is-arrayish": "0.2.1"
      }
    },
    "es-abstract": {
      "version": "1.12.0",
      "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz",
      "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==",
      "requires": {
        "es-to-primitive": "1.1.1",
        "function-bind": "1.1.1",
        "has": "1.0.3",
        "is-callable": "1.1.4",
        "is-regex": "1.0.4"
      }
    },
    "es-to-primitive": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz",
      "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=",
      "requires": {
        "is-callable": "1.1.4",
        "is-date-object": "1.0.1",
        "is-symbol": "1.0.1"
      }
    },
    "es5-ext": {
      "version": "0.10.46",
      "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz",
      "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==",
      "requires": {
        "es6-iterator": "2.0.3",
        "es6-symbol": "3.1.1",
        "next-tick": "1.0.0"
      }
    },
    "es6-iterator": {
      "version": "2.0.3",
      "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
      "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
      "requires": {
        "d": "1.0.0",
        "es5-ext": "0.10.46",
        "es6-symbol": "3.1.1"
      }
    },
    "es6-map": {
      "version": "0.1.5",
      "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz",
      "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=",
      "requires": {
        "d": "1.0.0",
        "es5-ext": "0.10.46",
        "es6-iterator": "2.0.3",
        "es6-set": "0.1.5",
        "es6-symbol": "3.1.1",
        "event-emitter": "0.3.5"
      }
    },
    "es6-set": {
      "version": "0.1.5",
      "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz",
      "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=",
      "requires": {
        "d": "1.0.0",
        "es5-ext": "0.10.46",
        "es6-iterator": "2.0.3",
        "es6-symbol": "3.1.1",
        "event-emitter": "0.3.5"
      }
    },
    "es6-symbol": {
      "version": "3.1.1",
      "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
      "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
      "requires": {
        "d": "1.0.0",
        "es5-ext": "0.10.46"
      }
    },
    "es6-weak-map": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz",
      "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=",
      "requires": {
        "d": "1.0.0",
        "es5-ext": "0.10.46",
        "es6-iterator": "2.0.3",
        "es6-symbol": "3.1.1"
      }
    },
    "escape-string-regexp": {
      "version": "1.0.5",
      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
    },
    "escope": {
      "version": "3.6.0",
      "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz",
      "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=",
      "requires": {
        "es6-map": "0.1.5",
        "es6-weak-map": "2.0.2",
        "esrecurse": "4.2.1",
        "estraverse": "4.2.0"
      }
    },
    "eslint": {
      "version": "4.19.1",
      "resolved": "http://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz",
      "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==",
      "requires": {
        "ajv": "5.5.2",
        "babel-code-frame": "6.26.0",
        "chalk": "2.4.1",
        "concat-stream": "1.6.2",
        "cross-spawn": "5.1.0",
        "debug": "3.1.0",
        "doctrine": "2.1.0",
        "eslint-scope": "3.7.1",
        "eslint-visitor-keys": "1.0.0",
        "espree": "3.5.4",
        "esquery": "1.0.1",
        "esutils": "2.0.2",
        "file-entry-cache": "2.0.0",
        "functional-red-black-tree": "1.0.1",
        "glob": "7.1.3",
        "globals": "11.7.0",
        "ignore": "3.3.10",
        "imurmurhash": "0.1.4",
        "inquirer": "3.3.0",
        "is-resolvable": "1.1.0",
        "js-yaml": "3.12.0",
        "json-stable-stringify-without-jsonify": "1.0.1",
        "levn": "0.3.0",
        "lodash": "4.17.10",
        "minimatch": "3.0.4",
        "mkdirp": "0.5.1",
        "natural-compare": "1.4.0",
        "optionator": "0.8.2",
        "path-is-inside": "1.0.2",
        "pluralize": "7.0.0",
        "progress": "2.0.0",
        "regexpp": "1.1.0",
        "require-uncached": "1.0.3",
        "semver": "5.5.1",
        "strip-ansi": "4.0.0",
        "strip-json-comments": "2.0.1",
        "table": "4.0.2",
        "text-table": "0.2.0"
      },
      "dependencies": {
        "ansi-regex": {
          "version": "3.0.0",
          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
        },
        "debug": {
          "version": "3.1.0",
          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
          "requires": {
            "ms": "2.0.0"
          }
        },
        "globals": {
          "version": "11.7.0",
          "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz",
          "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg=="
        },
        "inquirer": {
          "version": "3.3.0",
          "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
          "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==",
          "requires": {
            "ansi-escapes": "3.1.0",
            "chalk": "2.4.1",
            "cli-cursor": "2.1.0",
            "cli-width": "2.2.0",
            "external-editor": "2.2.0",
            "figures": "2.0.0",
            "lodash": "4.17.10",
            "mute-stream": "0.0.7",
            "run-async": "2.3.0",
            "rx-lite": "4.0.8",
            "rx-lite-aggregates": "4.0.8",
            "string-width": "2.1.1",
            "strip-ansi": "4.0.0",
            "through": "2.3.8"
          }
        },
        "strip-ansi": {
          "version": "4.0.0",
          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
          "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
          "requires": {
            "ansi-regex": "3.0.0"
          }
        }
      }
    },
    "eslint-config-wordpress": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/eslint-config-wordpress/-/eslint-config-wordpress-2.0.0.tgz",
      "integrity": "sha1-UgEgbGlk1kgxUjLt9t+9LpJeTNY="
    },
    "eslint-plugin-jest": {
      "version": "21.22.0",
      "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-21.22.0.tgz",
      "integrity": "sha512-0TzGIZ5moLR9orka/J9lg+7Ezv+S0TsnkavrMmI5xPFnbyIDjc2jLlwtBsaBbdZuOSCl+kcofh9ojknTI9L32Q=="
    },
    "eslint-plugin-jsx-a11y": {
      "version": "6.1.1",
      "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.1.1.tgz",
      "integrity": "sha512-JsxNKqa3TwmPypeXNnI75FntkUktGzI1wSa1LgNZdSOMI+B4sxnr1lSF8m8lPiz4mKiC+14ysZQM4scewUrP7A==",
      "requires": {
        "aria-query": "3.0.0",
        "array-includes": "3.0.3",
        "ast-types-flow": "0.0.7",
        "axobject-query": "2.0.1",
        "damerau-levenshtein": "1.0.4",
        "emoji-regex": "6.5.1",
        "has": "1.0.3",
        "jsx-ast-utils": "2.0.1"
      }
    },
    "eslint-plugin-react": {
      "version": "7.11.1",
      "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.11.1.tgz",
      "integrity": "sha512-cVVyMadRyW7qsIUh3FHp3u6QHNhOgVrLQYdQEB1bPWBsgbNCHdFAeNMquBMCcZJu59eNthX053L70l7gRt4SCw==",
      "requires": {
        "array-includes": "3.0.3",
        "doctrine": "2.1.0",
        "has": "1.0.3",
        "jsx-ast-utils": "2.0.1",
        "prop-types": "15.6.2"
      }
    },
    "eslint-plugin-wordpress": {
      "version": "0.1.0",
      "resolved": "https://registry.npmjs.org/eslint-plugin-wordpress/-/eslint-plugin-wordpress-0.1.0.tgz",
      "integrity": "sha1-PmlvCTJtmRXiZogasUj+0oFhF2I=",
      "requires": {
        "requireindex": "1.1.0"
      }
    },
    "eslint-scope": {
      "version": "3.7.1",
      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz",
      "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=",
      "requires": {
        "esrecurse": "4.2.1",
        "estraverse": "4.2.0"
      }
    },
    "eslint-visitor-keys": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
      "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ=="
    },
    "espree": {
      "version": "3.5.4",
      "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz",
      "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==",
      "requires": {
        "acorn": "5.7.2",
        "acorn-jsx": "3.0.1"
      }
    },
    "esprima": {
      "version": "4.0.1",
      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
      "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
    },
    "esquery": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz",
      "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==",
      "requires": {
        "estraverse": "4.2.0"
      }
    },
    "esrecurse": {
      "version": "4.2.1",
      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
      "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
      "requires": {
        "estraverse": "4.2.0"
      }
    },
    "estraverse": {
      "version": "4.2.0",
      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
      "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM="
    },
    "esutils": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
      "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
    },
    "event-emitter": {
      "version": "0.3.5",
      "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
      "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=",
      "requires": {
        "d": "1.0.0",
        "es5-ext": "0.10.46"
      }
    },
    "events": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
      "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
    },
    "evp_bytestokey": {
      "version": "1.0.3",
      "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
      "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
      "requires": {
        "md5.js": "1.3.4",
        "safe-buffer": "5.1.2"
      }
    },
    "execa": {
      "version": "0.7.0",
      "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
      "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
      "requires": {
        "cross-spawn": "5.1.0",
        "get-stream": "3.0.0",
        "is-stream": "1.1.0",
        "npm-run-path": "2.0.2",
        "p-finally": "1.0.0",
        "signal-exit": "3.0.2",
        "strip-eof": "1.0.0"
      }
    },
    "expand-brackets": {
      "version": "2.1.4",
      "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
      "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
      "requires": {
        "debug": "2.6.9",
        "define-property": "0.2.5",
        "extend-shallow": "2.0.1",
        "posix-character-classes": "0.1.1",
        "regex-not": "1.0.2",
        "snapdragon": "0.8.2",
        "to-regex": "3.0.2"
      },
      "dependencies": {
        "define-property": {
          "version": "0.2.5",
          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
          "requires": {
            "is-descriptor": "0.1.6"
          }
        },
        "extend-shallow": {
          "version": "2.0.1",
          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
          "requires": {
            "is-extendable": "0.1.1"
          }
        }
      }
    },
    "extend": {
      "version": "3.0.2",
      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
      "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
    },
    "extend-shallow": {
      "version": "3.0.2",
      "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
      "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
      "requires": {
        "assign-symbols": "1.0.0",
        "is-extendable": "1.0.1"
      },
      "dependencies": {
        "is-extendable": {
          "version": "1.0.1",
          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
          "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
          "requires": {
            "is-plain-object": "2.0.4"
          }
        }
      }
    },
    "external-editor": {
      "version": "2.2.0",
      "resolved": "http://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
      "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==",
      "requires": {
        "chardet": "0.4.2",
        "iconv-lite": "0.4.24",
        "tmp": "0.0.33"
      }
    },
    "extglob": {
      "version": "2.0.4",
      "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
      "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
      "requires": {
        "array-unique": "0.3.2",
        "define-property": "1.0.0",
        "expand-brackets": "2.1.4",
        "extend-shallow": "2.0.1",
        "fragment-cache": "0.2.1",
        "regex-not": "1.0.2",
        "snapdragon": "0.8.2",
        "to-regex": "3.0.2"
      },
      "dependencies": {
        "define-property": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
          "requires": {
            "is-descriptor": "1.0.2"
          }
        },
        "extend-shallow": {
          "version": "2.0.1",
          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
          "requires": {
            "is-extendable": "0.1.1"
          }
        },
        "is-accessor-descriptor": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
          "requires": {
            "kind-of": "6.0.2"
          }
        },
        "is-data-descriptor": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
          "requires": {
            "kind-of": "6.0.2"
          }
        },
        "is-descriptor": {
          "version": "1.0.2",
          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
          "requires": {
            "is-accessor-descriptor": "1.0.0",
            "is-data-descriptor": "1.0.0",
            "kind-of": "6.0.2"
          }
        }
      }
    },
    "extract-text-webpack-plugin": {
      "version": "3.0.2",
      "resolved": "https://registry.npmjs.org/extract-text-webpack-plugin/-/extract-text-webpack-plugin-3.0.2.tgz",
      "integrity": "sha512-bt/LZ4m5Rqt/Crl2HiKuAl/oqg0psx1tsTLkvWbJen1CtD+fftkZhMaQ9HOtY2gWsl2Wq+sABmMVi9z3DhKWQQ==",
      "requires": {
        "async": "2.6.1",
        "loader-utils": "1.1.0",
        "schema-utils": "0.3.0",
        "webpack-sources": "1.2.0"
      }
    },
    "extsprintf": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
      "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
    },
    "fast-deep-equal": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
      "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ="
    },
    "fast-json-stable-stringify": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
      "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
    },
    "fast-levenshtein": {
      "version": "2.0.6",
      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
      "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
    },
    "figures": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
      "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
      "requires": {
        "escape-string-regexp": "1.0.5"
      }
    },
    "file-entry-cache": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz",
      "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=",
      "requires": {
        "flat-cache": "1.3.0",
        "object-assign": "4.1.1"
      }
    },
    "filesize": {
      "version": "3.6.1",
      "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz",
      "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg=="
    },
    "fill-range": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
      "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
      "requires": {
        "extend-shallow": "2.0.1",
        "is-number": "3.0.0",
        "repeat-string": "1.6.1",
        "to-regex-range": "2.1.1"
      },
      "dependencies": {
        "extend-shallow": {
          "version": "2.0.1",
          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
          "requires": {
            "is-extendable": "0.1.1"
          }
        }
      }
    },
    "find-cache-dir": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz",
      "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=",
      "requires": {
        "commondir": "1.0.1",
        "make-dir": "1.3.0",
        "pkg-dir": "2.0.0"
      }
    },
    "find-up": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
      "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
      "requires": {
        "locate-path": "2.0.0"
      }
    },
    "flat-cache": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz",
      "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=",
      "requires": {
        "circular-json": "0.3.3",
        "del": "2.2.2",
        "graceful-fs": "4.1.11",
        "write": "0.2.1"
      }
    },
    "for-in": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
      "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
    },
    "for-own": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz",
      "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=",
      "requires": {
        "for-in": "1.0.2"
      }
    },
    "forever-agent": {
      "version": "0.6.1",
      "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
      "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
    },
    "form-data": {
      "version": "2.3.2",
      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
      "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
      "requires": {
        "asynckit": "0.4.0",
        "combined-stream": "1.0.6",
        "mime-types": "2.1.20"
      }
    },
    "fragment-cache": {
      "version": "0.2.1",
      "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
      "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
      "requires": {
        "map-cache": "0.2.2"
      }
    },
    "fs-extra": {
      "version": "5.0.0",
      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz",
      "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==",
      "requires": {
        "graceful-fs": "4.1.11",
        "jsonfile": "4.0.0",
        "universalify": "0.1.2"
      }
    },
    "fs.realpath": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
    },
    "fsevents": {
      "version": "1.2.4",
      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz",
      "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==",
      "optional": true,
      "requires": {
        "nan": "2.11.0",
        "node-pre-gyp": "0.10.0"
      },
      "dependencies": {
        "abbrev": {
          "version": "1.1.1",
          "bundled": true,
          "optional": true
        },
        "ansi-regex": {
          "version": "2.1.1",
          "bundled": true
        },
        "aproba": {
          "version": "1.2.0",
          "bundled": true,
          "optional": true
        },
        "are-we-there-yet": {
          "version": "1.1.4",
          "bundled": true,
          "optional": true,
          "requires": {
            "delegates": "1.0.0",
            "readable-stream": "2.3.6"
          }
        },
        "balanced-match": {
          "version": "1.0.0",
          "bundled": true
        },
        "brace-expansion": {
          "version": "1.1.11",
          "bundled": true,
          "requires": {
            "balanced-match": "1.0.0",
            "concat-map": "0.0.1"
          }
        },
        "chownr": {
          "version": "1.0.1",
          "bundled": true,
          "optional": true
        },
        "code-point-at": {
          "version": "1.1.0",
          "bundled": true
        },
        "concat-map": {
          "version": "0.0.1",
          "bundled": true
        },
        "console-control-strings": {
          "version": "1.1.0",
          "bundled": true
        },
        "core-util-is": {
          "version": "1.0.2",
          "bundled": true,
          "optional": true
        },
        "debug": {
          "version": "2.6.9",
          "bundled": true,
          "optional": true,
          "requires": {
            "ms": "2.0.0"
          }
        },
        "deep-extend": {
          "version": "0.5.1",
          "bundled": true,
          "optional": true
        },
        "delegates": {
          "version": "1.0.0",
          "bundled": true,
          "optional": true
        },
        "detect-libc": {
          "version": "1.0.3",
          "bundled": true,
          "optional": true
        },
        "fs-minipass": {
          "version": "1.2.5",
          "bundled": true,
          "optional": true,
          "requires": {
            "minipass": "2.2.4"
          }
        },
        "fs.realpath": {
          "version": "1.0.0",
          "bundled": true,
          "optional": true
        },
        "gauge": {
          "version": "2.7.4",
          "bundled": true,
          "optional": true,
          "requires": {
            "aproba": "1.2.0",
            "console-control-strings": "1.1.0",
            "has-unicode": "2.0.1",
            "object-assign": "4.1.1",
            "signal-exit": "3.0.2",
            "string-width": "1.0.2",
            "strip-ansi": "3.0.1",
            "wide-align": "1.1.2"
          }
        },
        "glob": {
          "version": "7.1.2",
          "bundled": true,
          "optional": true,
          "requires": {
            "fs.realpath": "1.0.0",
            "inflight": "1.0.6",
            "inherits": "2.0.3",
            "minimatch": "3.0.4",
            "once": "1.4.0",
            "path-is-absolute": "1.0.1"
          }
        },
        "has-unicode": {
          "version": "2.0.1",
          "bundled": true,
          "optional": true
        },
        "iconv-lite": {
          "version": "0.4.21",
          "bundled": true,
          "optional": true,
          "requires": {
            "safer-buffer": "2.1.2"
          }
        },
        "ignore-walk": {
          "version": "3.0.1",
          "bundled": true,
          "optional": true,
          "requires": {
            "minimatch": "3.0.4"
          }
        },
        "inflight": {
          "version": "1.0.6",
          "bundled": true,
          "optional": true,
          "requires": {
            "once": "1.4.0",
            "wrappy": "1.0.2"
          }
        },
        "inherits": {
          "version": "2.0.3",
          "bundled": true
        },
        "ini": {
          "version": "1.3.5",
          "bundled": true,
          "optional": true
        },
        "is-fullwidth-code-point": {
          "version": "1.0.0",
          "bundled": true,
          "requires": {
            "number-is-nan": "1.0.1"
          }
        },
        "isarray": {
          "version": "1.0.0",
          "bundled": true,
          "optional": true
        },
        "minimatch": {
          "version": "3.0.4",
          "bundled": true,
          "requires": {
            "brace-expansion": "1.1.11"
          }
        },
        "minimist": {
          "version": "0.0.8",
          "bundled": true
        },
        "minipass": {
          "version": "2.2.4",
          "bundled": true,
          "requires": {
            "safe-buffer": "5.1.1",
            "yallist": "3.0.2"
          }
        },
        "minizlib": {
          "version": "1.1.0",
          "bundled": true,
          "optional": true,
          "requires": {
            "minipass": "2.2.4"
          }
        },
        "mkdirp": {
          "version": "0.5.1",
          "bundled": true,
          "requires": {
            "minimist": "0.0.8"
          }
        },
        "ms": {
          "version": "2.0.0",
          "bundled": true,
          "optional": true
        },
        "needle": {
          "version": "2.2.0",
          "bundled": true,
          "optional": true,
          "requires": {
            "debug": "2.6.9",
            "iconv-lite": "0.4.21",
            "sax": "1.2.4"
          }
        },
        "node-pre-gyp": {
          "version": "0.10.0",
          "bundled": true,
          "optional": true,
          "requires": {
            "detect-libc": "1.0.3",
            "mkdirp": "0.5.1",
            "needle": "2.2.0",
            "nopt": "4.0.1",
            "npm-packlist": "1.1.10",
            "npmlog": "4.1.2",
            "rc": "1.2.7",
            "rimraf": "2.6.2",
            "semver": "5.5.0",
            "tar": "4.4.1"
          }
        },
        "nopt": {
          "version": "4.0.1",
          "bundled": true,
          "optional": true,
          "requires": {
            "abbrev": "1.1.1",
            "osenv": "0.1.5"
          }
        },
        "npm-bundled": {
          "version": "1.0.3",
          "bundled": true,
          "optional": true
        },
        "npm-packlist": {
          "version": "1.1.10",
          "bundled": true,
          "optional": true,
          "requires": {
            "ignore-walk": "3.0.1",
            "npm-bundled": "1.0.3"
          }
        },
        "npmlog": {
          "version": "4.1.2",
          "bundled": true,
          "optional": true,
          "requires": {
            "are-we-there-yet": "1.1.4",
            "console-control-strings": "1.1.0",
            "gauge": "2.7.4",
            "set-blocking": "2.0.0"
          }
        },
        "number-is-nan": {
          "version": "1.0.1",
          "bundled": true
        },
        "object-assign": {
          "version": "4.1.1",
          "bundled": true,
          "optional": true
        },
        "once": {
          "version": "1.4.0",
          "bundled": true,
          "requires": {
            "wrappy": "1.0.2"
          }
        },
        "os-homedir": {
          "version": "1.0.2",
          "bundled": true,
          "optional": true
        },
        "os-tmpdir": {
          "version": "1.0.2",
          "bundled": true,
          "optional": true
        },
        "osenv": {
          "version": "0.1.5",
          "bundled": true,
          "optional": true,
          "requires": {
            "os-homedir": "1.0.2",
            "os-tmpdir": "1.0.2"
          }
        },
        "path-is-absolute": {
          "version": "1.0.1",
          "bundled": true,
          "optional": true
        },
        "process-nextick-args": {
          "version": "2.0.0",
          "bundled": true,
          "optional": true
        },
        "rc": {
          "version": "1.2.7",
          "bundled": true,
          "optional": true,
          "requires": {
            "deep-extend": "0.5.1",
            "ini": "1.3.5",
            "minimist": "1.2.0",
            "strip-json-comments": "2.0.1"
          },
          "dependencies": {
            "minimist": {
              "version": "1.2.0",
              "bundled": true,
              "optional": true
            }
          }
        },
        "readable-stream": {
          "version": "2.3.6",
          "bundled": true,
          "optional": true,
          "requires": {
            "core-util-is": "1.0.2",
            "inherits": "2.0.3",
            "isarray": "1.0.0",
            "process-nextick-args": "2.0.0",
            "safe-buffer": "5.1.1",
            "string_decoder": "1.1.1",
            "util-deprecate": "1.0.2"
          }
        },
        "rimraf": {
          "version": "2.6.2",
          "bundled": true,
          "optional": true,
          "requires": {
            "glob": "7.1.2"
          }
        },
        "safe-buffer": {
          "version": "5.1.1",
          "bundled": true
        },
        "safer-buffer": {
          "version": "2.1.2",
          "bundled": true,
          "optional": true
        },
        "sax": {
          "version": "1.2.4",
          "bundled": true,
          "optional": true
        },
        "semver": {
          "version": "5.5.0",
          "bundled": true,
          "optional": true
        },
        "set-blocking": {
          "version": "2.0.0",
          "bundled": true,
          "optional": true
        },
        "signal-exit": {
          "version": "3.0.2",
          "bundled": true,
          "optional": true
        },
        "string-width": {
          "version": "1.0.2",
          "bundled": true,
          "requires": {
            "code-point-at": "1.1.0",
            "is-fullwidth-code-point": "1.0.0",
            "strip-ansi": "3.0.1"
          }
        },
        "string_decoder": {
          "version": "1.1.1",
          "bundled": true,
          "optional": true,
          "requires": {
            "safe-buffer": "5.1.1"
          }
        },
        "strip-ansi": {
          "version": "3.0.1",
          "bundled": true,
          "requires": {
            "ansi-regex": "2.1.1"
          }
        },
        "strip-json-comments": {
          "version": "2.0.1",
          "bundled": true,
          "optional": true
        },
        "tar": {
          "version": "4.4.1",
          "bundled": true,
          "optional": true,
          "requires": {
            "chownr": "1.0.1",
            "fs-minipass": "1.2.5",
            "minipass": "2.2.4",
            "minizlib": "1.1.0",
            "mkdirp": "0.5.1",
            "safe-buffer": "5.1.1",
            "yallist": "3.0.2"
          }
        },
        "util-deprecate": {
          "version": "1.0.2",
          "bundled": true,
          "optional": true
        },
        "wide-align": {
          "version": "1.1.2",
          "bundled": true,
          "optional": true,
          "requires": {
            "string-width": "1.0.2"
          }
        },
        "wrappy": {
          "version": "1.0.2",
          "bundled": true
        },
        "yallist": {
          "version": "3.0.2",
          "bundled": true
        }
      }
    },
    "fstream": {
      "version": "1.0.11",
      "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",
      "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=",
      "requires": {
        "graceful-fs": "4.1.11",
        "inherits": "2.0.3",
        "mkdirp": "0.5.1",
        "rimraf": "2.6.2"
      }
    },
    "function-bind": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
    },
    "functional-red-black-tree": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
      "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc="
    },
    "gauge": {
      "version": "2.7.4",
      "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
      "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
      "requires": {
        "aproba": "1.2.0",
        "console-control-strings": "1.1.0",
        "has-unicode": "2.0.1",
        "object-assign": "4.1.1",
        "signal-exit": "3.0.2",
        "string-width": "1.0.2",
        "strip-ansi": "3.0.1",
        "wide-align": "1.1.3"
      },
      "dependencies": {
        "is-fullwidth-code-point": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
          "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
          "requires": {
            "number-is-nan": "1.0.1"
          }
        },
        "string-width": {
          "version": "1.0.2",
          "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
          "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
          "requires": {
            "code-point-at": "1.1.0",
            "is-fullwidth-code-point": "1.0.0",
            "strip-ansi": "3.0.1"
          }
        }
      }
    },
    "gaze": {
      "version": "1.1.3",
      "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz",
      "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==",
      "requires": {
        "globule": "1.2.1"
      }
    },
    "get-caller-file": {
      "version": "1.0.3",
      "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
      "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w=="
    },
    "get-stdin": {
      "version": "4.0.1",
      "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
      "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4="
    },
    "get-stream": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
      "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
    },
    "get-value": {
      "version": "2.0.6",
      "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
      "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg="
    },
    "getpass": {
      "version": "0.1.7",
      "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
      "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
      "requires": {
        "assert-plus": "1.0.0"
      }
    },
    "glob": {
      "version": "7.1.3",
      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
      "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
      "requires": {
        "fs.realpath": "1.0.0",
        "inflight": "1.0.6",
        "inherits": "2.0.3",
        "minimatch": "3.0.4",
        "once": "1.4.0",
        "path-is-absolute": "1.0.1"
      }
    },
    "glob-parent": {
      "version": "3.1.0",
      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
      "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
      "requires": {
        "is-glob": "3.1.0",
        "path-dirname": "1.0.2"
      },
      "dependencies": {
        "is-glob": {
          "version": "3.1.0",
          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
          "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
          "requires": {
            "is-extglob": "2.1.1"
          }
        }
      }
    },
    "global-dirs": {
      "version": "0.1.1",
      "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz",
      "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=",
      "requires": {
        "ini": "1.3.5"
      }
    },
    "globals": {
      "version": "9.18.0",
      "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
      "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ=="
    },
    "globby": {
      "version": "5.0.0",
      "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
      "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
      "requires": {
        "array-union": "1.0.2",
        "arrify": "1.0.1",
        "glob": "7.1.3",
        "object-assign": "4.1.1",
        "pify": "2.3.0",
        "pinkie-promise": "2.0.1"
      },
      "dependencies": {
        "pify": {
          "version": "2.3.0",
          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
        }
      }
    },
    "globule": {
      "version": "1.2.1",
      "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz",
      "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==",
      "requires": {
        "glob": "7.1.3",
        "lodash": "4.17.10",
        "minimatch": "3.0.4"
      }
    },
    "got": {
      "version": "6.7.1",
      "resolved": "http://registry.npmjs.org/got/-/got-6.7.1.tgz",
      "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=",
      "requires": {
        "create-error-class": "3.0.2",
        "duplexer3": "0.1.4",
        "get-stream": "3.0.0",
        "is-redirect": "1.0.0",
        "is-retry-allowed": "1.1.0",
        "is-stream": "1.1.0",
        "lowercase-keys": "1.0.1",
        "safe-buffer": "5.1.2",
        "timed-out": "4.0.1",
        "unzip-response": "2.0.1",
        "url-parse-lax": "1.0.0"
      }
    },
    "graceful-fs": {
      "version": "4.1.11",
      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
      "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
    },
    "gzip-size": {
      "version": "4.1.0",
      "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-4.1.0.tgz",
      "integrity": "sha1-iuCWJX6r59acRb4rZ8RIEk/7UXw=",
      "requires": {
        "duplexer": "0.1.1",
        "pify": "3.0.0"
      }
    },
    "har-schema": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
      "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
    },
    "har-validator": {
      "version": "5.0.3",
      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
      "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
      "requires": {
        "ajv": "5.5.2",
        "har-schema": "2.0.0"
      }
    },
    "has": {
      "version": "1.0.3",
      "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
      "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
      "requires": {
        "function-bind": "1.1.1"
      }
    },
    "has-ansi": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
      "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
      "requires": {
        "ansi-regex": "2.1.1"
      }
    },
    "has-flag": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
    },
    "has-unicode": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
      "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
    },
    "has-value": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
      "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
      "requires": {
        "get-value": "2.0.6",
        "has-values": "1.0.0",
        "isobject": "3.0.1"
      }
    },
    "has-values": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
      "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
      "requires": {
        "is-number": "3.0.0",
        "kind-of": "4.0.0"
      },
      "dependencies": {
        "kind-of": {
          "version": "4.0.0",
          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
          "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
          "requires": {
            "is-buffer": "1.1.6"
          }
        }
      }
    },
    "hash-base": {
      "version": "3.0.4",
      "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
      "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
      "requires": {
        "inherits": "2.0.3",
        "safe-buffer": "5.1.2"
      }
    },
    "hash.js": {
      "version": "1.1.5",
      "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz",
      "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==",
      "requires": {
        "inherits": "2.0.3",
        "minimalistic-assert": "1.0.1"
      }
    },
    "hmac-drbg": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
      "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
      "requires": {
        "hash.js": "1.1.5",
        "minimalistic-assert": "1.0.1",
        "minimalistic-crypto-utils": "1.0.1"
      }
    },
    "home-or-tmp": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz",
      "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=",
      "requires": {
        "os-homedir": "1.0.2",
        "os-tmpdir": "1.0.2"
      }
    },
    "hosted-git-info": {
      "version": "2.7.1",
      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz",
      "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w=="
    },
    "http-signature": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
      "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
      "requires": {
        "assert-plus": "1.0.0",
        "jsprim": "1.4.1",
        "sshpk": "1.14.2"
      }
    },
    "https-browserify": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
      "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM="
    },
    "iconv-lite": {
      "version": "0.4.24",
      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
      "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
      "requires": {
        "safer-buffer": "2.1.2"
      }
    },
    "ieee754": {
      "version": "1.1.12",
      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz",
      "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA=="
    },
    "ignore": {
      "version": "3.3.10",
      "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
      "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug=="
    },
    "import-cwd": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz",
      "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=",
      "requires": {
        "import-from": "2.1.0"
      }
    },
    "import-from": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz",
      "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=",
      "requires": {
        "resolve-from": "3.0.0"
      },
      "dependencies": {
        "resolve-from": {
          "version": "3.0.0",
          "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
          "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g="
        }
      }
    },
    "import-lazy": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
      "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM="
    },
    "imurmurhash": {
      "version": "0.1.4",
      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
      "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
    },
    "in-publish": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz",
      "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E="
    },
    "indent-string": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
      "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
      "requires": {
        "repeating": "2.0.1"
      }
    },
    "indexof": {
      "version": "0.0.1",
      "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
      "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10="
    },
    "inflight": {
      "version": "1.0.6",
      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
      "requires": {
        "once": "1.4.0",
        "wrappy": "1.0.2"
      }
    },
    "inherits": {
      "version": "2.0.3",
      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
    },
    "ini": {
      "version": "1.3.5",
      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
      "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
    },
    "inquirer": {
      "version": "5.2.0",
      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz",
      "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==",
      "requires": {
        "ansi-escapes": "3.1.0",
        "chalk": "2.4.1",
        "cli-cursor": "2.1.0",
        "cli-width": "2.2.0",
        "external-editor": "2.2.0",
        "figures": "2.0.0",
        "lodash": "4.17.10",
        "mute-stream": "0.0.7",
        "run-async": "2.3.0",
        "rxjs": "5.5.12",
        "string-width": "2.1.1",
        "strip-ansi": "4.0.0",
        "through": "2.3.8"
      },
      "dependencies": {
        "ansi-regex": {
          "version": "3.0.0",
          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
        },
        "strip-ansi": {
          "version": "4.0.0",
          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
          "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
          "requires": {
            "ansi-regex": "3.0.0"
          }
        }
      }
    },
    "interpret": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz",
      "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ="
    },
    "invariant": {
      "version": "2.2.4",
      "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
      "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
      "requires": {
        "loose-envify": "1.4.0"
      }
    },
    "invert-kv": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
      "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="
    },
    "is-accessor-descriptor": {
      "version": "0.1.6",
      "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
      "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
      "requires": {
        "kind-of": "3.2.2"
      },
      "dependencies": {
        "kind-of": {
          "version": "3.2.2",
          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
          "requires": {
            "is-buffer": "1.1.6"
          }
        }
      }
    },
    "is-arrayish": {
      "version": "0.2.1",
      "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
      "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
    },
    "is-binary-path": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
      "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
      "requires": {
        "binary-extensions": "1.11.0"
      }
    },
    "is-buffer": {
      "version": "1.1.6",
      "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
      "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
    },
    "is-builtin-module": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
      "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
      "requires": {
        "builtin-modules": "1.1.1"
      }
    },
    "is-callable": {
      "version": "1.1.4",
      "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
      "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA=="
    },
    "is-ci": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.0.tgz",
      "integrity": "sha512-plgvKjQtalH2P3Gytb7L61Lmz95g2DlpzFiQyRSFew8WoJKxtKRzrZMeyRN2supblm3Psc8OQGy7Xjb6XG11jw==",
      "requires": {
        "ci-info": "1.4.0"
      }
    },
    "is-data-descriptor": {
      "version": "0.1.4",
      "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
      "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
      "requires": {
        "kind-of": "3.2.2"
      },
      "dependencies": {
        "kind-of": {
          "version": "3.2.2",
          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
          "requires": {
            "is-buffer": "1.1.6"
          }
        }
      }
    },
    "is-date-object": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
      "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY="
    },
    "is-descriptor": {
      "version": "0.1.6",
      "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
      "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
      "requires": {
        "is-accessor-descriptor": "0.1.6",
        "is-data-descriptor": "0.1.4",
        "kind-of": "5.1.0"
      },
      "dependencies": {
        "kind-of": {
          "version": "5.1.0",
          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
          "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="
        }
      }
    },
    "is-directory": {
      "version": "0.3.1",
      "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
      "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE="
    },
    "is-extendable": {
      "version": "0.1.1",
      "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
      "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
    },
    "is-extglob": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
      "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
    },
    "is-finite": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
      "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
      "requires": {
        "number-is-nan": "1.0.1"
      }
    },
    "is-fullwidth-code-point": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
      "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
    },
    "is-glob": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz",
      "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=",
      "requires": {
        "is-extglob": "2.1.1"
      }
    },
    "is-installed-globally": {
      "version": "0.1.0",
      "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz",
      "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=",
      "requires": {
        "global-dirs": "0.1.1",
        "is-path-inside": "1.0.1"
      }
    },
    "is-npm": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz",
      "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ="
    },
    "is-number": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
      "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
      "requires": {
        "kind-of": "3.2.2"
      },
      "dependencies": {
        "kind-of": {
          "version": "3.2.2",
          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
          "requires": {
            "is-buffer": "1.1.6"
          }
        }
      }
    },
    "is-obj": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
      "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8="
    },
    "is-path-cwd": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
      "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0="
    },
    "is-path-in-cwd": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz",
      "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==",
      "requires": {
        "is-path-inside": "1.0.1"
      }
    },
    "is-path-inside": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
      "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
      "requires": {
        "path-is-inside": "1.0.2"
      }
    },
    "is-plain-object": {
      "version": "2.0.4",
      "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
      "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
      "requires": {
        "isobject": "3.0.1"
      }
    },
    "is-promise": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
      "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o="
    },
    "is-redirect": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz",
      "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ="
    },
    "is-regex": {
      "version": "1.0.4",
      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
      "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
      "requires": {
        "has": "1.0.3"
      }
    },
    "is-resolvable": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz",
      "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg=="
    },
    "is-retry-allowed": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz",
      "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ="
    },
    "is-stream": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
      "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
    },
    "is-symbol": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz",
      "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI="
    },
    "is-typedarray": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
      "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
    },
    "is-utf8": {
      "version": "0.2.1",
      "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
      "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI="
    },
    "is-windows": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
      "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="
    },
    "isarray": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
    },
    "isexe": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
    },
    "isobject": {
      "version": "3.0.1",
      "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
      "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
    },
    "isstream": {
      "version": "0.1.2",
      "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
      "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
    },
    "js-base64": {
      "version": "2.4.9",
      "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.9.tgz",
      "integrity": "sha512-xcinL3AuDJk7VSzsHgb9DvvIXayBbadtMZ4HFPx8rUszbW1MuNMlwYVC4zzCZ6e1sqZpnNS5ZFYOhXqA39T7LQ=="
    },
    "js-tokens": {
      "version": "3.0.2",
      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
      "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls="
    },
    "js-yaml": {
      "version": "3.12.0",
      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz",
      "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==",
      "requires": {
        "argparse": "1.0.10",
        "esprima": "4.0.1"
      }
    },
    "jsbn": {
      "version": "0.1.1",
      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
      "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
      "optional": true
    },
    "jsesc": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
      "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s="
    },
    "json-loader": {
      "version": "0.5.7",
      "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz",
      "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w=="
    },
    "json-parse-better-errors": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
      "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
    },
    "json-schema": {
      "version": "0.2.3",
      "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
      "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
    },
    "json-schema-traverse": {
      "version": "0.3.1",
      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
      "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
    },
    "json-stable-stringify-without-jsonify": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
      "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE="
    },
    "json-stringify-safe": {
      "version": "5.0.1",
      "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
      "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
    },
    "json5": {
      "version": "0.5.1",
      "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
      "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="
    },
    "jsonfile": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
      "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
      "requires": {
        "graceful-fs": "4.1.11"
      }
    },
    "jsprim": {
      "version": "1.4.1",
      "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
      "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
      "requires": {
        "assert-plus": "1.0.0",
        "extsprintf": "1.3.0",
        "json-schema": "0.2.3",
        "verror": "1.10.0"
      }
    },
    "jsx-ast-utils": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz",
      "integrity": "sha1-6AGxs5mF4g//yHtA43SAgOLcrH8=",
      "requires": {
        "array-includes": "3.0.3"
      }
    },
    "kind-of": {
      "version": "6.0.2",
      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
      "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
    },
    "latest-version": {
      "version": "3.1.0",
      "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz",
      "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=",
      "requires": {
        "package-json": "4.0.1"
      }
    },
    "lazy-cache": {
      "version": "1.0.4",
      "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
      "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4="
    },
    "lcid": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
      "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
      "requires": {
        "invert-kv": "1.0.0"
      }
    },
    "levn": {
      "version": "0.3.0",
      "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
      "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
      "requires": {
        "prelude-ls": "1.1.2",
        "type-check": "0.3.2"
      }
    },
    "load-json-file": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
      "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
      "requires": {
        "graceful-fs": "4.1.11",
        "parse-json": "2.2.0",
        "pify": "2.3.0",
        "pinkie-promise": "2.0.1",
        "strip-bom": "2.0.0"
      },
      "dependencies": {
        "pify": {
          "version": "2.3.0",
          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
        }
      }
    },
    "loader-runner": {
      "version": "2.3.0",
      "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz",
      "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI="
    },
    "loader-utils": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz",
      "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=",
      "requires": {
        "big.js": "3.2.0",
        "emojis-list": "2.1.0",
        "json5": "0.5.1"
      }
    },
    "locate-path": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
      "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
      "requires": {
        "p-locate": "2.0.0",
        "path-exists": "3.0.0"
      }
    },
    "lodash": {
      "version": "4.17.10",
      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
      "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg=="
    },
    "lodash.assign": {
      "version": "4.2.0",
      "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
      "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc="
    },
    "lodash.clonedeep": {
      "version": "4.5.0",
      "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
      "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8="
    },
    "lodash.debounce": {
      "version": "4.0.8",
      "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
      "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
    },
    "lodash.mergewith": {
      "version": "4.6.1",
      "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz",
      "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ=="
    },
    "lodash.tail": {
      "version": "4.1.1",
      "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz",
      "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ="
    },
    "log-symbols": {
      "version": "2.2.0",
      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
      "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
      "requires": {
        "chalk": "2.4.1"
      }
    },
    "longest": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
      "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc="
    },
    "loose-envify": {
      "version": "1.4.0",
      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
      "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
      "requires": {
        "js-tokens": "3.0.2"
      }
    },
    "loud-rejection": {
      "version": "1.6.0",
      "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
      "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
      "requires": {
        "currently-unhandled": "0.4.1",
        "signal-exit": "3.0.2"
      }
    },
    "lowercase-keys": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
      "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA=="
    },
    "lru-cache": {
      "version": "4.1.3",
      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz",
      "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==",
      "requires": {
        "pseudomap": "1.0.2",
        "yallist": "2.1.2"
      }
    },
    "make-dir": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
      "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
      "requires": {
        "pify": "3.0.0"
      }
    },
    "map-cache": {
      "version": "0.2.2",
      "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
      "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8="
    },
    "map-obj": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
      "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0="
    },
    "map-visit": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
      "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
      "requires": {
        "object-visit": "1.0.1"
      }
    },
    "md5.js": {
      "version": "1.3.4",
      "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz",
      "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=",
      "requires": {
        "hash-base": "3.0.4",
        "inherits": "2.0.3"
      }
    },
    "mem": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
      "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=",
      "requires": {
        "mimic-fn": "1.2.0"
      }
    },
    "memory-fs": {
      "version": "0.4.1",
      "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
      "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
      "requires": {
        "errno": "0.1.7",
        "readable-stream": "2.3.6"
      }
    },
    "meow": {
      "version": "3.7.0",
      "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
      "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
      "requires": {
        "camelcase-keys": "2.1.0",
        "decamelize": "1.2.0",
        "loud-rejection": "1.6.0",
        "map-obj": "1.0.1",
        "minimist": "1.2.0",
        "normalize-package-data": "2.4.0",
        "object-assign": "4.1.1",
        "read-pkg-up": "1.0.1",
        "redent": "1.0.0",
        "trim-newlines": "1.0.0"
      },
      "dependencies": {
        "minimist": {
          "version": "1.2.0",
          "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
        }
      }
    },
    "micromatch": {
      "version": "3.1.10",
      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
      "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
      "requires": {
        "arr-diff": "4.0.0",
        "array-unique": "0.3.2",
        "braces": "2.3.2",
        "define-property": "2.0.2",
        "extend-shallow": "3.0.2",
        "extglob": "2.0.4",
        "fragment-cache": "0.2.1",
        "kind-of": "6.0.2",
        "nanomatch": "1.2.13",
        "object.pick": "1.3.0",
        "regex-not": "1.0.2",
        "snapdragon": "0.8.2",
        "to-regex": "3.0.2"
      }
    },
    "miller-rabin": {
      "version": "4.0.1",
      "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
      "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
      "requires": {
        "bn.js": "4.11.8",
        "brorand": "1.1.0"
      }
    },
    "mime-db": {
      "version": "1.36.0",
      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz",
      "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw=="
    },
    "mime-types": {
      "version": "2.1.20",
      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz",
      "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==",
      "requires": {
        "mime-db": "1.36.0"
      }
    },
    "mimic-fn": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
      "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="
    },
    "minimalistic-assert": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
      "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="
    },
    "minimalistic-crypto-utils": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
      "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo="
    },
    "minimatch": {
      "version": "3.0.4",
      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
      "requires": {
        "brace-expansion": "1.1.11"
      }
    },
    "minimist": {
      "version": "0.0.8",
      "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
      "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
    },
    "mixin-deep": {
      "version": "1.3.1",
      "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz",
      "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==",
      "requires": {
        "for-in": "1.0.2",
        "is-extendable": "1.0.1"
      },
      "dependencies": {
        "is-extendable": {
          "version": "1.0.1",
          "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
          "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
          "requires": {
            "is-plain-object": "2.0.4"
          }
        }
      }
    },
    "mixin-object": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz",
      "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=",
      "requires": {
        "for-in": "0.1.8",
        "is-extendable": "0.1.1"
      },
      "dependencies": {
        "for-in": {
          "version": "0.1.8",
          "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz",
          "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE="
        }
      }
    },
    "mkdirp": {
      "version": "0.5.1",
      "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
      "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
      "requires": {
        "minimist": "0.0.8"
      }
    },
    "ms": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
    },
    "mute-stream": {
      "version": "0.0.7",
      "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
      "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s="
    },
    "nan": {
      "version": "2.11.0",
      "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.0.tgz",
      "integrity": "sha512-F4miItu2rGnV2ySkXOQoA8FKz/SR2Q2sWP0sbTxNxz/tuokeC8WxOhPMcwi0qIyGtVn/rrSeLbvVkznqCdwYnw=="
    },
    "nanomatch": {
      "version": "1.2.13",
      "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
      "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
      "requires": {
        "arr-diff": "4.0.0",
        "array-unique": "0.3.2",
        "define-property": "2.0.2",
        "extend-shallow": "3.0.2",
        "fragment-cache": "0.2.1",
        "is-windows": "1.0.2",
        "kind-of": "6.0.2",
        "object.pick": "1.3.0",
        "regex-not": "1.0.2",
        "snapdragon": "0.8.2",
        "to-regex": "3.0.2"
      }
    },
    "natural-compare": {
      "version": "1.4.0",
      "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
      "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc="
    },
    "neo-async": {
      "version": "2.5.2",
      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.2.tgz",
      "integrity": "sha512-vdqTKI9GBIYcAEbFAcpKPErKINfPF5zIuz3/niBfq8WUZjpT2tytLlFVrBgWdOtqI4uaA/Rb6No0hux39XXDuw=="
    },
    "next-tick": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
      "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw="
    },
    "nice-try": {
      "version": "1.0.5",
      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
    },
    "node-gyp": {
      "version": "3.8.0",
      "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz",
      "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==",
      "requires": {
        "fstream": "1.0.11",
        "glob": "7.1.3",
        "graceful-fs": "4.1.11",
        "mkdirp": "0.5.1",
        "nopt": "3.0.6",
        "npmlog": "4.1.2",
        "osenv": "0.1.5",
        "request": "2.87.0",
        "rimraf": "2.6.2",
        "semver": "5.3.0",
        "tar": "2.2.1",
        "which": "1.3.1"
      },
      "dependencies": {
        "semver": {
          "version": "5.3.0",
          "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
          "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8="
        }
      }
    },
    "node-libs-browser": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz",
      "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==",
      "requires": {
        "assert": "1.4.1",
        "browserify-zlib": "0.2.0",
        "buffer": "4.9.1",
        "console-browserify": "1.1.0",
        "constants-browserify": "1.0.0",
        "crypto-browserify": "3.12.0",
        "domain-browser": "1.2.0",
        "events": "1.1.1",
        "https-browserify": "1.0.0",
        "os-browserify": "0.3.0",
        "path-browserify": "0.0.0",
        "process": "0.11.10",
        "punycode": "1.4.1",
        "querystring-es3": "0.2.1",
        "readable-stream": "2.3.6",
        "stream-browserify": "2.0.1",
        "stream-http": "2.8.3",
        "string_decoder": "1.1.1",
        "timers-browserify": "2.0.10",
        "tty-browserify": "0.0.0",
        "url": "0.11.0",
        "util": "0.10.4",
        "vm-browserify": "0.0.4"
      }
    },
    "node-sass": {
      "version": "4.9.3",
      "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.3.tgz",
      "integrity": "sha512-XzXyGjO+84wxyH7fV6IwBOTrEBe2f0a6SBze9QWWYR/cL74AcQUks2AsqcCZenl/Fp/JVbuEaLpgrLtocwBUww==",
      "requires": {
        "async-foreach": "0.1.3",
        "chalk": "1.1.3",
        "cross-spawn": "3.0.1",
        "gaze": "1.1.3",
        "get-stdin": "4.0.1",
        "glob": "7.1.3",
        "in-publish": "2.0.0",
        "lodash.assign": "4.2.0",
        "lodash.clonedeep": "4.5.0",
        "lodash.mergewith": "4.6.1",
        "meow": "3.7.0",
        "mkdirp": "0.5.1",
        "nan": "2.11.0",
        "node-gyp": "3.8.0",
        "npmlog": "4.1.2",
        "request": "2.87.0",
        "sass-graph": "2.2.4",
        "stdout-stream": "1.4.1",
        "true-case-path": "1.0.3"
      },
      "dependencies": {
        "ansi-styles": {
          "version": "2.2.1",
          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
        },
        "chalk": {
          "version": "1.1.3",
          "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
          "requires": {
            "ansi-styles": "2.2.1",
            "escape-string-regexp": "1.0.5",
            "has-ansi": "2.0.0",
            "strip-ansi": "3.0.1",
            "supports-color": "2.0.0"
          }
        },
        "cross-spawn": {
          "version": "3.0.1",
          "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz",
          "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=",
          "requires": {
            "lru-cache": "4.1.3",
            "which": "1.3.1"
          }
        },
        "supports-color": {
          "version": "2.0.0",
          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
        }
      }
    },
    "nopt": {
      "version": "3.0.6",
      "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
      "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
      "requires": {
        "abbrev": "1.1.1"
      }
    },
    "normalize-package-data": {
      "version": "2.4.0",
      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
      "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==",
      "requires": {
        "hosted-git-info": "2.7.1",
        "is-builtin-module": "1.0.0",
        "semver": "5.5.1",
        "validate-npm-package-license": "3.0.4"
      }
    },
    "normalize-path": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
      "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
      "requires": {
        "remove-trailing-separator": "1.1.0"
      }
    },
    "normalize-range": {
      "version": "0.1.2",
      "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
      "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI="
    },
    "npm-run-path": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
      "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
      "requires": {
        "path-key": "2.0.1"
      }
    },
    "npmlog": {
      "version": "4.1.2",
      "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
      "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
      "requires": {
        "are-we-there-yet": "1.1.5",
        "console-control-strings": "1.1.0",
        "gauge": "2.7.4",
        "set-blocking": "2.0.0"
      }
    },
    "num2fraction": {
      "version": "1.2.2",
      "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
      "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4="
    },
    "number-is-nan": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
      "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
    },
    "oauth-sign": {
      "version": "0.8.2",
      "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
      "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM="
    },
    "object-assign": {
      "version": "4.1.1",
      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
    },
    "object-copy": {
      "version": "0.1.0",
      "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
      "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
      "requires": {
        "copy-descriptor": "0.1.1",
        "define-property": "0.2.5",
        "kind-of": "3.2.2"
      },
      "dependencies": {
        "define-property": {
          "version": "0.2.5",
          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
          "requires": {
            "is-descriptor": "0.1.6"
          }
        },
        "kind-of": {
          "version": "3.2.2",
          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
          "requires": {
            "is-buffer": "1.1.6"
          }
        }
      }
    },
    "object-keys": {
      "version": "1.0.12",
      "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz",
      "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag=="
    },
    "object-visit": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
      "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
      "requires": {
        "isobject": "3.0.1"
      }
    },
    "object.pick": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
      "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
      "requires": {
        "isobject": "3.0.1"
      }
    },
    "once": {
      "version": "1.4.0",
      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
      "requires": {
        "wrappy": "1.0.2"
      }
    },
    "onetime": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
      "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
      "requires": {
        "mimic-fn": "1.2.0"
      }
    },
    "optionator": {
      "version": "0.8.2",
      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
      "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
      "requires": {
        "deep-is": "0.1.3",
        "fast-levenshtein": "2.0.6",
        "levn": "0.3.0",
        "prelude-ls": "1.1.2",
        "type-check": "0.3.2",
        "wordwrap": "1.0.0"
      }
    },
    "ora": {
      "version": "1.4.0",
      "resolved": "https://registry.npmjs.org/ora/-/ora-1.4.0.tgz",
      "integrity": "sha512-iMK1DOQxzzh2MBlVsU42G80mnrvUhqsMh74phHtDlrcTZPK0pH6o7l7DRshK+0YsxDyEuaOkziVdvM3T0QTzpw==",
      "requires": {
        "chalk": "2.4.1",
        "cli-cursor": "2.1.0",
        "cli-spinners": "1.3.1",
        "log-symbols": "2.2.0"
      }
    },
    "os-browserify": {
      "version": "0.3.0",
      "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
      "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc="
    },
    "os-homedir": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
      "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
    },
    "os-locale": {
      "version": "1.4.0",
      "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
      "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
      "requires": {
        "lcid": "1.0.0"
      }
    },
    "os-tmpdir": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
      "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
    },
    "osenv": {
      "version": "0.1.5",
      "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
      "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
      "requires": {
        "os-homedir": "1.0.2",
        "os-tmpdir": "1.0.2"
      }
    },
    "p-finally": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
      "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
    },
    "p-limit": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
      "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
      "requires": {
        "p-try": "1.0.0"
      }
    },
    "p-locate": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
      "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
      "requires": {
        "p-limit": "1.3.0"
      }
    },
    "p-try": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
      "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M="
    },
    "package-json": {
      "version": "4.0.1",
      "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz",
      "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=",
      "requires": {
        "got": "6.7.1",
        "registry-auth-token": "3.3.2",
        "registry-url": "3.1.0",
        "semver": "5.5.1"
      }
    },
    "pako": {
      "version": "1.0.6",
      "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz",
      "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg=="
    },
    "parse-asn1": {
      "version": "5.1.1",
      "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz",
      "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==",
      "requires": {
        "asn1.js": "4.10.1",
        "browserify-aes": "1.2.0",
        "create-hash": "1.2.0",
        "evp_bytestokey": "1.0.3",
        "pbkdf2": "3.0.16"
      }
    },
    "parse-json": {
      "version": "2.2.0",
      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
      "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
      "requires": {
        "error-ex": "1.3.2"
      }
    },
    "pascalcase": {
      "version": "0.1.1",
      "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
      "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ="
    },
    "path-browserify": {
      "version": "0.0.0",
      "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz",
      "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo="
    },
    "path-dirname": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
      "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA="
    },
    "path-exists": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
      "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
    },
    "path-is-absolute": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
    },
    "path-is-inside": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
      "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM="
    },
    "path-key": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
      "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
    },
    "path-parse": {
      "version": "1.0.6",
      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
      "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw=="
    },
    "path-type": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
      "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
      "requires": {
        "graceful-fs": "4.1.11",
        "pify": "2.3.0",
        "pinkie-promise": "2.0.1"
      },
      "dependencies": {
        "pify": {
          "version": "2.3.0",
          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
        }
      }
    },
    "pbkdf2": {
      "version": "3.0.16",
      "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz",
      "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==",
      "requires": {
        "create-hash": "1.2.0",
        "create-hmac": "1.1.7",
        "ripemd160": "2.0.2",
        "safe-buffer": "5.1.2",
        "sha.js": "2.4.11"
      }
    },
    "performance-now": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
      "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
    },
    "pify": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
      "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
    },
    "pinkie": {
      "version": "2.0.4",
      "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
      "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA="
    },
    "pinkie-promise": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
      "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
      "requires": {
        "pinkie": "2.0.4"
      }
    },
    "pkg-dir": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
      "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
      "requires": {
        "find-up": "2.1.0"
      }
    },
    "pluralize": {
      "version": "7.0.0",
      "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz",
      "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow=="
    },
    "posix-character-classes": {
      "version": "0.1.1",
      "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
      "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs="
    },
    "postcss": {
      "version": "6.0.23",
      "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz",
      "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==",
      "requires": {
        "chalk": "2.4.1",
        "source-map": "0.6.1",
        "supports-color": "5.5.0"
      }
    },
    "postcss-load-config": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.0.0.tgz",
      "integrity": "sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ==",
      "requires": {
        "cosmiconfig": "4.0.0",
        "import-cwd": "2.1.0"
      }
    },
    "postcss-loader": {
      "version": "2.1.6",
      "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-2.1.6.tgz",
      "integrity": "sha512-hgiWSc13xVQAq25cVw80CH0l49ZKlAnU1hKPOdRrNj89bokRr/bZF2nT+hebPPF9c9xs8c3gw3Fr2nxtmXYnNg==",
      "requires": {
        "loader-utils": "1.1.0",
        "postcss": "6.0.23",
        "postcss-load-config": "2.0.0",
        "schema-utils": "0.4.7"
      },
      "dependencies": {
        "ajv": {
          "version": "6.5.3",
          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz",
          "integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==",
          "requires": {
            "fast-deep-equal": "2.0.1",
            "fast-json-stable-stringify": "2.0.0",
            "json-schema-traverse": "0.4.1",
            "uri-js": "4.2.2"
          }
        },
        "ajv-keywords": {
          "version": "3.2.0",
          "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz",
          "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo="
        },
        "fast-deep-equal": {
          "version": "2.0.1",
          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
          "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
        },
        "json-schema-traverse": {
          "version": "0.4.1",
          "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
          "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
        },
        "schema-utils": {
          "version": "0.4.7",
          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
          "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==",
          "requires": {
            "ajv": "6.5.3",
            "ajv-keywords": "3.2.0"
          }
        }
      }
    },
    "postcss-value-parser": {
      "version": "3.3.0",
      "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz",
      "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU="
    },
    "prelude-ls": {
      "version": "1.1.2",
      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
      "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ="
    },
    "prepend-http": {
      "version": "1.0.4",
      "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
      "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw="
    },
    "private": {
      "version": "0.1.8",
      "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
      "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg=="
    },
    "process": {
      "version": "0.11.10",
      "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
      "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
    },
    "process-nextick-args": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
      "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
    },
    "progress": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz",
      "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8="
    },
    "prop-types": {
      "version": "15.6.2",
      "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz",
      "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==",
      "requires": {
        "loose-envify": "1.4.0",
        "object-assign": "4.1.1"
      }
    },
    "prr": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
      "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY="
    },
    "pseudomap": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
      "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
    },
    "public-encrypt": {
      "version": "4.0.2",
      "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz",
      "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==",
      "requires": {
        "bn.js": "4.11.8",
        "browserify-rsa": "4.0.1",
        "create-hash": "1.2.0",
        "parse-asn1": "5.1.1",
        "randombytes": "2.0.6"
      }
    },
    "punycode": {
      "version": "1.4.1",
      "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
      "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
    },
    "qs": {
      "version": "6.5.2",
      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
      "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
    },
    "querystring": {
      "version": "0.2.0",
      "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
      "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
    },
    "querystring-es3": {
      "version": "0.2.1",
      "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
      "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM="
    },
    "randombytes": {
      "version": "2.0.6",
      "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz",
      "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==",
      "requires": {
        "safe-buffer": "5.1.2"
      }
    },
    "randomfill": {
      "version": "1.0.4",
      "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
      "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==",
      "requires": {
        "randombytes": "2.0.6",
        "safe-buffer": "5.1.2"
      }
    },
    "raw-loader": {
      "version": "0.5.1",
      "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz",
      "integrity": "sha1-DD0L6u2KAclm2Xh793goElKpeao="
    },
    "rc": {
      "version": "1.2.8",
      "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
      "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
      "requires": {
        "deep-extend": "0.6.0",
        "ini": "1.3.5",
        "minimist": "1.2.0",
        "strip-json-comments": "2.0.1"
      },
      "dependencies": {
        "minimist": {
          "version": "1.2.0",
          "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
        }
      }
    },
    "read-pkg": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
      "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
      "requires": {
        "load-json-file": "1.1.0",
        "normalize-package-data": "2.4.0",
        "path-type": "1.1.0"
      }
    },
    "read-pkg-up": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
      "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
      "requires": {
        "find-up": "1.1.2",
        "read-pkg": "1.1.0"
      },
      "dependencies": {
        "find-up": {
          "version": "1.1.2",
          "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
          "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
          "requires": {
            "path-exists": "2.1.0",
            "pinkie-promise": "2.0.1"
          }
        },
        "path-exists": {
          "version": "2.1.0",
          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
          "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
          "requires": {
            "pinkie-promise": "2.0.1"
          }
        }
      }
    },
    "readable-stream": {
      "version": "2.3.6",
      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
      "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
      "requires": {
        "core-util-is": "1.0.2",
        "inherits": "2.0.3",
        "isarray": "1.0.0",
        "process-nextick-args": "2.0.0",
        "safe-buffer": "5.1.2",
        "string_decoder": "1.1.1",
        "util-deprecate": "1.0.2"
      }
    },
    "readdirp": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz",
      "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=",
      "requires": {
        "graceful-fs": "4.1.11",
        "minimatch": "3.0.4",
        "readable-stream": "2.3.6",
        "set-immediate-shim": "1.0.1"
      }
    },
    "rechoir": {
      "version": "0.6.2",
      "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
      "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
      "requires": {
        "resolve": "1.8.1"
      }
    },
    "redent": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
      "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
      "requires": {
        "indent-string": "2.1.0",
        "strip-indent": "1.0.1"
      }
    },
    "regenerate": {
      "version": "1.4.0",
      "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
      "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg=="
    },
    "regenerator-runtime": {
      "version": "0.11.1",
      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
      "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
    },
    "regenerator-transform": {
      "version": "0.10.1",
      "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz",
      "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==",
      "requires": {
        "babel-runtime": "6.26.0",
        "babel-types": "6.26.0",
        "private": "0.1.8"
      }
    },
    "regex-not": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
      "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
      "requires": {
        "extend-shallow": "3.0.2",
        "safe-regex": "1.1.0"
      }
    },
    "regexpp": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz",
      "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw=="
    },
    "regexpu-core": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz",
      "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=",
      "requires": {
        "regenerate": "1.4.0",
        "regjsgen": "0.2.0",
        "regjsparser": "0.1.5"
      }
    },
    "registry-auth-token": {
      "version": "3.3.2",
      "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz",
      "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==",
      "requires": {
        "rc": "1.2.8",
        "safe-buffer": "5.1.2"
      }
    },
    "registry-url": {
      "version": "3.1.0",
      "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz",
      "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=",
      "requires": {
        "rc": "1.2.8"
      }
    },
    "regjsgen": {
      "version": "0.2.0",
      "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
      "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc="
    },
    "regjsparser": {
      "version": "0.1.5",
      "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz",
      "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=",
      "requires": {
        "jsesc": "0.5.0"
      },
      "dependencies": {
        "jsesc": {
          "version": "0.5.0",
          "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
          "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0="
        }
      }
    },
    "remove-trailing-separator": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
      "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
    },
    "repeat-element": {
      "version": "1.1.3",
      "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
      "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g=="
    },
    "repeat-string": {
      "version": "1.6.1",
      "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
      "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
    },
    "repeating": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
      "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
      "requires": {
        "is-finite": "1.0.2"
      }
    },
    "request": {
      "version": "2.87.0",
      "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz",
      "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==",
      "requires": {
        "aws-sign2": "0.7.0",
        "aws4": "1.8.0",
        "caseless": "0.12.0",
        "combined-stream": "1.0.6",
        "extend": "3.0.2",
        "forever-agent": "0.6.1",
        "form-data": "2.3.2",
        "har-validator": "5.0.3",
        "http-signature": "1.2.0",
        "is-typedarray": "1.0.0",
        "isstream": "0.1.2",
        "json-stringify-safe": "5.0.1",
        "mime-types": "2.1.20",
        "oauth-sign": "0.8.2",
        "performance-now": "2.1.0",
        "qs": "6.5.2",
        "safe-buffer": "5.1.2",
        "tough-cookie": "2.3.4",
        "tunnel-agent": "0.6.0",
        "uuid": "3.3.2"
      }
    },
    "require-directory": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
      "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
    },
    "require-from-string": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
      "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="
    },
    "require-main-filename": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
      "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE="
    },
    "require-uncached": {
      "version": "1.0.3",
      "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
      "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
      "requires": {
        "caller-path": "0.1.0",
        "resolve-from": "1.0.1"
      }
    },
    "requireindex": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.1.0.tgz",
      "integrity": "sha1-5UBLgVV+91225JxacgBIk/4D4WI="
    },
    "resolve": {
      "version": "1.8.1",
      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz",
      "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==",
      "requires": {
        "path-parse": "1.0.6"
      }
    },
    "resolve-from": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz",
      "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY="
    },
    "resolve-pkg": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/resolve-pkg/-/resolve-pkg-1.0.0.tgz",
      "integrity": "sha1-4ZoV54rKLhJEYdySsuOUPvk0lNk=",
      "requires": {
        "resolve-from": "2.0.0"
      },
      "dependencies": {
        "resolve-from": {
          "version": "2.0.0",
          "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
          "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c="
        }
      }
    },
    "resolve-url": {
      "version": "0.2.1",
      "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
      "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo="
    },
    "restore-cursor": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
      "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
      "requires": {
        "onetime": "2.0.1",
        "signal-exit": "3.0.2"
      }
    },
    "ret": {
      "version": "0.1.15",
      "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
      "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="
    },
    "right-align": {
      "version": "0.1.3",
      "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
      "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
      "requires": {
        "align-text": "0.1.4"
      }
    },
    "rimraf": {
      "version": "2.6.2",
      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
      "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
      "requires": {
        "glob": "7.1.3"
      }
    },
    "ripemd160": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
      "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
      "requires": {
        "hash-base": "3.0.4",
        "inherits": "2.0.3"
      }
    },
    "run-async": {
      "version": "2.3.0",
      "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
      "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
      "requires": {
        "is-promise": "2.1.0"
      }
    },
    "rx-lite": {
      "version": "4.0.8",
      "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz",
      "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ="
    },
    "rx-lite-aggregates": {
      "version": "4.0.8",
      "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz",
      "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=",
      "requires": {
        "rx-lite": "4.0.8"
      }
    },
    "rxjs": {
      "version": "5.5.12",
      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz",
      "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==",
      "requires": {
        "symbol-observable": "1.0.1"
      }
    },
    "safe-buffer": {
      "version": "5.1.2",
      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
    },
    "safe-regex": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
      "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
      "requires": {
        "ret": "0.1.15"
      }
    },
    "safer-buffer": {
      "version": "2.1.2",
      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
    },
    "sass-graph": {
      "version": "2.2.4",
      "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz",
      "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=",
      "requires": {
        "glob": "7.1.3",
        "lodash": "4.17.10",
        "scss-tokenizer": "0.2.3",
        "yargs": "7.1.0"
      }
    },
    "sass-loader": {
      "version": "6.0.7",
      "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-6.0.7.tgz",
      "integrity": "sha512-JoiyD00Yo1o61OJsoP2s2kb19L1/Y2p3QFcCdWdF6oomBGKVYuZyqHWemRBfQ2uGYsk+CH3eCguXNfpjzlcpaA==",
      "requires": {
        "clone-deep": "2.0.2",
        "loader-utils": "1.1.0",
        "lodash.tail": "4.1.1",
        "neo-async": "2.5.2",
        "pify": "3.0.0"
      }
    },
    "schema-utils": {
      "version": "0.3.0",
      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz",
      "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=",
      "requires": {
        "ajv": "5.5.2"
      }
    },
    "scss-tokenizer": {
      "version": "0.2.3",
      "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
      "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=",
      "requires": {
        "js-base64": "2.4.9",
        "source-map": "0.4.4"
      },
      "dependencies": {
        "source-map": {
          "version": "0.4.4",
          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
          "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
          "requires": {
            "amdefine": "1.0.1"
          }
        }
      }
    },
    "semver": {
      "version": "5.5.1",
      "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz",
      "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw=="
    },
    "semver-diff": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz",
      "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=",
      "requires": {
        "semver": "5.5.1"
      }
    },
    "set-blocking": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
      "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
    },
    "set-immediate-shim": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
      "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E="
    },
    "set-value": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz",
      "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==",
      "requires": {
        "extend-shallow": "2.0.1",
        "is-extendable": "0.1.1",
        "is-plain-object": "2.0.4",
        "split-string": "3.1.0"
      },
      "dependencies": {
        "extend-shallow": {
          "version": "2.0.1",
          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
          "requires": {
            "is-extendable": "0.1.1"
          }
        }
      }
    },
    "setimmediate": {
      "version": "1.0.5",
      "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
      "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
    },
    "sha.js": {
      "version": "2.4.11",
      "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
      "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
      "requires": {
        "inherits": "2.0.3",
        "safe-buffer": "5.1.2"
      }
    },
    "shallow-clone": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz",
      "integrity": "sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==",
      "requires": {
        "is-extendable": "0.1.1",
        "kind-of": "5.1.0",
        "mixin-object": "2.0.1"
      },
      "dependencies": {
        "kind-of": {
          "version": "5.1.0",
          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
          "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="
        }
      }
    },
    "shebang-command": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
      "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
      "requires": {
        "shebang-regex": "1.0.0"
      }
    },
    "shebang-regex": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
      "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
    },
    "shelljs": {
      "version": "0.8.2",
      "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.2.tgz",
      "integrity": "sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ==",
      "requires": {
        "glob": "7.1.3",
        "interpret": "1.1.0",
        "rechoir": "0.6.2"
      }
    },
    "signal-exit": {
      "version": "3.0.2",
      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
      "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
    },
    "slash": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
      "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU="
    },
    "slice-ansi": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz",
      "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==",
      "requires": {
        "is-fullwidth-code-point": "2.0.0"
      }
    },
    "snapdragon": {
      "version": "0.8.2",
      "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
      "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
      "requires": {
        "base": "0.11.2",
        "debug": "2.6.9",
        "define-property": "0.2.5",
        "extend-shallow": "2.0.1",
        "map-cache": "0.2.2",
        "source-map": "0.5.7",
        "source-map-resolve": "0.5.2",
        "use": "3.1.1"
      },
      "dependencies": {
        "define-property": {
          "version": "0.2.5",
          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
          "requires": {
            "is-descriptor": "0.1.6"
          }
        },
        "extend-shallow": {
          "version": "2.0.1",
          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
          "requires": {
            "is-extendable": "0.1.1"
          }
        },
        "source-map": {
          "version": "0.5.7",
          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
        }
      }
    },
    "snapdragon-node": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
      "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
      "requires": {
        "define-property": "1.0.0",
        "isobject": "3.0.1",
        "snapdragon-util": "3.0.1"
      },
      "dependencies": {
        "define-property": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
          "requires": {
            "is-descriptor": "1.0.2"
          }
        },
        "is-accessor-descriptor": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
          "requires": {
            "kind-of": "6.0.2"
          }
        },
        "is-data-descriptor": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
          "requires": {
            "kind-of": "6.0.2"
          }
        },
        "is-descriptor": {
          "version": "1.0.2",
          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
          "requires": {
            "is-accessor-descriptor": "1.0.0",
            "is-data-descriptor": "1.0.0",
            "kind-of": "6.0.2"
          }
        }
      }
    },
    "snapdragon-util": {
      "version": "3.0.1",
      "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
      "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
      "requires": {
        "kind-of": "3.2.2"
      },
      "dependencies": {
        "kind-of": {
          "version": "3.2.2",
          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
          "requires": {
            "is-buffer": "1.1.6"
          }
        }
      }
    },
    "source-list-map": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz",
      "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A=="
    },
    "source-map": {
      "version": "0.6.1",
      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
    },
    "source-map-resolve": {
      "version": "0.5.2",
      "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz",
      "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==",
      "requires": {
        "atob": "2.1.2",
        "decode-uri-component": "0.2.0",
        "resolve-url": "0.2.1",
        "source-map-url": "0.4.0",
        "urix": "0.1.0"
      }
    },
    "source-map-support": {
      "version": "0.4.18",
      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz",
      "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==",
      "requires": {
        "source-map": "0.5.7"
      },
      "dependencies": {
        "source-map": {
          "version": "0.5.7",
          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
        }
      }
    },
    "source-map-url": {
      "version": "0.4.0",
      "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
      "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM="
    },
    "spdx-correct": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz",
      "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==",
      "requires": {
        "spdx-expression-parse": "3.0.0",
        "spdx-license-ids": "3.0.1"
      }
    },
    "spdx-exceptions": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz",
      "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg=="
    },
    "spdx-expression-parse": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
      "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
      "requires": {
        "spdx-exceptions": "2.1.0",
        "spdx-license-ids": "3.0.1"
      }
    },
    "spdx-license-ids": {
      "version": "3.0.1",
      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz",
      "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w=="
    },
    "split-string": {
      "version": "3.1.0",
      "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
      "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
      "requires": {
        "extend-shallow": "3.0.2"
      }
    },
    "sprintf-js": {
      "version": "1.0.3",
      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
      "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
    },
    "sshpk": {
      "version": "1.14.2",
      "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz",
      "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=",
      "requires": {
        "asn1": "0.2.4",
        "assert-plus": "1.0.0",
        "bcrypt-pbkdf": "1.0.2",
        "dashdash": "1.14.1",
        "ecc-jsbn": "0.1.2",
        "getpass": "0.1.7",
        "jsbn": "0.1.1",
        "safer-buffer": "2.1.2",
        "tweetnacl": "0.14.5"
      }
    },
    "static-extend": {
      "version": "0.1.2",
      "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
      "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
      "requires": {
        "define-property": "0.2.5",
        "object-copy": "0.1.0"
      },
      "dependencies": {
        "define-property": {
          "version": "0.2.5",
          "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
          "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
          "requires": {
            "is-descriptor": "0.1.6"
          }
        }
      }
    },
    "stdout-stream": {
      "version": "1.4.1",
      "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz",
      "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==",
      "requires": {
        "readable-stream": "2.3.6"
      }
    },
    "stream-browserify": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz",
      "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=",
      "requires": {
        "inherits": "2.0.3",
        "readable-stream": "2.3.6"
      }
    },
    "stream-http": {
      "version": "2.8.3",
      "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz",
      "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==",
      "requires": {
        "builtin-status-codes": "3.0.0",
        "inherits": "2.0.3",
        "readable-stream": "2.3.6",
        "to-arraybuffer": "1.0.1",
        "xtend": "4.0.1"
      }
    },
    "string-width": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
      "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
      "requires": {
        "is-fullwidth-code-point": "2.0.0",
        "strip-ansi": "4.0.0"
      },
      "dependencies": {
        "ansi-regex": {
          "version": "3.0.0",
          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
        },
        "strip-ansi": {
          "version": "4.0.0",
          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
          "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
          "requires": {
            "ansi-regex": "3.0.0"
          }
        }
      }
    },
    "string_decoder": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
      "requires": {
        "safe-buffer": "5.1.2"
      }
    },
    "strip-ansi": {
      "version": "3.0.1",
      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
      "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
      "requires": {
        "ansi-regex": "2.1.1"
      }
    },
    "strip-bom": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
      "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
      "requires": {
        "is-utf8": "0.2.1"
      }
    },
    "strip-eof": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
      "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
    },
    "strip-indent": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
      "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
      "requires": {
        "get-stdin": "4.0.1"
      }
    },
    "strip-json-comments": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
      "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
    },
    "style-loader": {
      "version": "0.19.1",
      "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.19.1.tgz",
      "integrity": "sha512-IRE+ijgojrygQi3rsqT0U4dd+UcPCqcVvauZpCnQrGAlEe+FUIyrK93bUDScamesjP08JlQNsFJU+KmPedP5Og==",
      "requires": {
        "loader-utils": "1.1.0",
        "schema-utils": "0.3.0"
      }
    },
    "supports-color": {
      "version": "5.5.0",
      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
      "requires": {
        "has-flag": "3.0.0"
      }
    },
    "symbol-observable": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz",
      "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ="
    },
    "table": {
      "version": "4.0.2",
      "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz",
      "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==",
      "requires": {
        "ajv": "5.5.2",
        "ajv-keywords": "2.1.1",
        "chalk": "2.4.1",
        "lodash": "4.17.10",
        "slice-ansi": "1.0.0",
        "string-width": "2.1.1"
      }
    },
    "tapable": {
      "version": "0.2.8",
      "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz",
      "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI="
    },
    "tar": {
      "version": "2.2.1",
      "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz",
      "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=",
      "requires": {
        "block-stream": "0.0.9",
        "fstream": "1.0.11",
        "inherits": "2.0.3"
      }
    },
    "term-size": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz",
      "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=",
      "requires": {
        "execa": "0.7.0"
      }
    },
    "text-table": {
      "version": "0.2.0",
      "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
      "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ="
    },
    "through": {
      "version": "2.3.8",
      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
      "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
    },
    "timed-out": {
      "version": "4.0.1",
      "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz",
      "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8="
    },
    "timers-browserify": {
      "version": "2.0.10",
      "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz",
      "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==",
      "requires": {
        "setimmediate": "1.0.5"
      }
    },
    "tmp": {
      "version": "0.0.33",
      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
      "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
      "requires": {
        "os-tmpdir": "1.0.2"
      }
    },
    "to-arraybuffer": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
      "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M="
    },
    "to-fast-properties": {
      "version": "1.0.3",
      "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
      "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc="
    },
    "to-object-path": {
      "version": "0.3.0",
      "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
      "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
      "requires": {
        "kind-of": "3.2.2"
      },
      "dependencies": {
        "kind-of": {
          "version": "3.2.2",
          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
          "requires": {
            "is-buffer": "1.1.6"
          }
        }
      }
    },
    "to-regex": {
      "version": "3.0.2",
      "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
      "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
      "requires": {
        "define-property": "2.0.2",
        "extend-shallow": "3.0.2",
        "regex-not": "1.0.2",
        "safe-regex": "1.1.0"
      }
    },
    "to-regex-range": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
      "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
      "requires": {
        "is-number": "3.0.0",
        "repeat-string": "1.6.1"
      }
    },
    "tough-cookie": {
      "version": "2.3.4",
      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz",
      "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==",
      "requires": {
        "punycode": "1.4.1"
      }
    },
    "trim-newlines": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
      "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM="
    },
    "trim-right": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
      "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM="
    },
    "true-case-path": {
      "version": "1.0.3",
      "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz",
      "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==",
      "requires": {
        "glob": "7.1.3"
      }
    },
    "tty-browserify": {
      "version": "0.0.0",
      "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
      "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY="
    },
    "tunnel-agent": {
      "version": "0.6.0",
      "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
      "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
      "requires": {
        "safe-buffer": "5.1.2"
      }
    },
    "tweetnacl": {
      "version": "0.14.5",
      "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
      "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
      "optional": true
    },
    "type-check": {
      "version": "0.3.2",
      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
      "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
      "requires": {
        "prelude-ls": "1.1.2"
      }
    },
    "typedarray": {
      "version": "0.0.6",
      "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
      "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
    },
    "uglify-js": {
      "version": "2.8.29",
      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
      "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
      "requires": {
        "source-map": "0.5.7",
        "uglify-to-browserify": "1.0.2",
        "yargs": "3.10.0"
      },
      "dependencies": {
        "camelcase": {
          "version": "1.2.1",
          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
          "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk="
        },
        "cliui": {
          "version": "2.1.0",
          "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
          "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
          "requires": {
            "center-align": "0.1.3",
            "right-align": "0.1.3",
            "wordwrap": "0.0.2"
          }
        },
        "source-map": {
          "version": "0.5.7",
          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
        },
        "wordwrap": {
          "version": "0.0.2",
          "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
          "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8="
        },
        "yargs": {
          "version": "3.10.0",
          "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
          "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
          "requires": {
            "camelcase": "1.2.1",
            "cliui": "2.1.0",
            "decamelize": "1.2.0",
            "window-size": "0.1.0"
          }
        }
      }
    },
    "uglify-to-browserify": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
      "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=",
      "optional": true
    },
    "uglifyjs-webpack-plugin": {
      "version": "0.4.6",
      "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz",
      "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=",
      "requires": {
        "source-map": "0.5.7",
        "uglify-js": "2.8.29",
        "webpack-sources": "1.2.0"
      },
      "dependencies": {
        "source-map": {
          "version": "0.5.7",
          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
        }
      }
    },
    "union-value": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz",
      "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=",
      "requires": {
        "arr-union": "3.1.0",
        "get-value": "2.0.6",
        "is-extendable": "0.1.1",
        "set-value": "0.4.3"
      },
      "dependencies": {
        "extend-shallow": {
          "version": "2.0.1",
          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
          "requires": {
            "is-extendable": "0.1.1"
          }
        },
        "set-value": {
          "version": "0.4.3",
          "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz",
          "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=",
          "requires": {
            "extend-shallow": "2.0.1",
            "is-extendable": "0.1.1",
            "is-plain-object": "2.0.4",
            "to-object-path": "0.3.0"
          }
        }
      }
    },
    "unique-string": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz",
      "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=",
      "requires": {
        "crypto-random-string": "1.0.0"
      }
    },
    "universalify": {
      "version": "0.1.2",
      "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
      "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
    },
    "unset-value": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
      "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
      "requires": {
        "has-value": "0.3.1",
        "isobject": "3.0.1"
      },
      "dependencies": {
        "has-value": {
          "version": "0.3.1",
          "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
          "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
          "requires": {
            "get-value": "2.0.6",
            "has-values": "0.1.4",
            "isobject": "2.1.0"
          },
          "dependencies": {
            "isobject": {
              "version": "2.1.0",
              "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
              "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
              "requires": {
                "isarray": "1.0.0"
              }
            }
          }
        },
        "has-values": {
          "version": "0.1.4",
          "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
          "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E="
        }
      }
    },
    "unzip-response": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz",
      "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c="
    },
    "upath": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz",
      "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw=="
    },
    "update-notifier": {
      "version": "2.5.0",
      "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz",
      "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==",
      "requires": {
        "boxen": "1.3.0",
        "chalk": "2.4.1",
        "configstore": "3.1.2",
        "import-lazy": "2.1.0",
        "is-ci": "1.2.0",
        "is-installed-globally": "0.1.0",
        "is-npm": "1.0.0",
        "latest-version": "3.1.0",
        "semver-diff": "2.1.0",
        "xdg-basedir": "3.0.0"
      }
    },
    "uri-js": {
      "version": "4.2.2",
      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
      "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
      "requires": {
        "punycode": "2.1.1"
      },
      "dependencies": {
        "punycode": {
          "version": "2.1.1",
          "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
          "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
        }
      }
    },
    "urix": {
      "version": "0.1.0",
      "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
      "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI="
    },
    "url": {
      "version": "0.11.0",
      "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
      "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
      "requires": {
        "punycode": "1.3.2",
        "querystring": "0.2.0"
      },
      "dependencies": {
        "punycode": {
          "version": "1.3.2",
          "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
          "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
        }
      }
    },
    "url-parse-lax": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz",
      "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=",
      "requires": {
        "prepend-http": "1.0.4"
      }
    },
    "use": {
      "version": "3.1.1",
      "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
      "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
    },
    "util": {
      "version": "0.10.4",
      "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
      "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
      "requires": {
        "inherits": "2.0.3"
      }
    },
    "util-deprecate": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
    },
    "uuid": {
      "version": "3.3.2",
      "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
      "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
    },
    "validate-npm-package-license": {
      "version": "3.0.4",
      "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
      "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
      "requires": {
        "spdx-correct": "3.0.0",
        "spdx-expression-parse": "3.0.0"
      }
    },
    "verror": {
      "version": "1.10.0",
      "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
      "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
      "requires": {
        "assert-plus": "1.0.0",
        "core-util-is": "1.0.2",
        "extsprintf": "1.3.0"
      }
    },
    "vm-browserify": {
      "version": "0.0.4",
      "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz",
      "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=",
      "requires": {
        "indexof": "0.0.1"
      }
    },
    "watchpack": {
      "version": "1.6.0",
      "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",
      "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==",
      "requires": {
        "chokidar": "2.0.4",
        "graceful-fs": "4.1.11",
        "neo-async": "2.5.2"
      }
    },
    "webpack": {
      "version": "3.12.0",
      "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.12.0.tgz",
      "integrity": "sha512-Sw7MdIIOv/nkzPzee4o0EdvCuPmxT98+vVpIvwtcwcF1Q4SDSNp92vwcKc4REe7NItH9f1S4ra9FuQ7yuYZ8bQ==",
      "requires": {
        "acorn": "5.7.2",
        "acorn-dynamic-import": "2.0.2",
        "ajv": "6.5.3",
        "ajv-keywords": "3.2.0",
        "async": "2.6.1",
        "enhanced-resolve": "3.4.1",
        "escope": "3.6.0",
        "interpret": "1.1.0",
        "json-loader": "0.5.7",
        "json5": "0.5.1",
        "loader-runner": "2.3.0",
        "loader-utils": "1.1.0",
        "memory-fs": "0.4.1",
        "mkdirp": "0.5.1",
        "node-libs-browser": "2.1.0",
        "source-map": "0.5.7",
        "supports-color": "4.5.0",
        "tapable": "0.2.8",
        "uglifyjs-webpack-plugin": "0.4.6",
        "watchpack": "1.6.0",
        "webpack-sources": "1.2.0",
        "yargs": "8.0.2"
      },
      "dependencies": {
        "ajv": {
          "version": "6.5.3",
          "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz",
          "integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==",
          "requires": {
            "fast-deep-equal": "2.0.1",
            "fast-json-stable-stringify": "2.0.0",
            "json-schema-traverse": "0.4.1",
            "uri-js": "4.2.2"
          }
        },
        "ajv-keywords": {
          "version": "3.2.0",
          "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz",
          "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo="
        },
        "fast-deep-equal": {
          "version": "2.0.1",
          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
          "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
        },
        "has-flag": {
          "version": "2.0.0",
          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
          "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
        },
        "json-schema-traverse": {
          "version": "0.4.1",
          "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
          "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
        },
        "load-json-file": {
          "version": "2.0.0",
          "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
          "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
          "requires": {
            "graceful-fs": "4.1.11",
            "parse-json": "2.2.0",
            "pify": "2.3.0",
            "strip-bom": "3.0.0"
          }
        },
        "os-locale": {
          "version": "2.1.0",
          "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
          "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
          "requires": {
            "execa": "0.7.0",
            "lcid": "1.0.0",
            "mem": "1.1.0"
          }
        },
        "path-type": {
          "version": "2.0.0",
          "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
          "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
          "requires": {
            "pify": "2.3.0"
          }
        },
        "pify": {
          "version": "2.3.0",
          "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
          "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
        },
        "read-pkg": {
          "version": "2.0.0",
          "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
          "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
          "requires": {
            "load-json-file": "2.0.0",
            "normalize-package-data": "2.4.0",
            "path-type": "2.0.0"
          }
        },
        "read-pkg-up": {
          "version": "2.0.0",
          "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz",
          "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
          "requires": {
            "find-up": "2.1.0",
            "read-pkg": "2.0.0"
          }
        },
        "source-map": {
          "version": "0.5.7",
          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
        },
        "strip-bom": {
          "version": "3.0.0",
          "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
          "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM="
        },
        "supports-color": {
          "version": "4.5.0",
          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
          "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
          "requires": {
            "has-flag": "2.0.0"
          }
        },
        "which-module": {
          "version": "2.0.0",
          "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
          "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
        },
        "yargs": {
          "version": "8.0.2",
          "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz",
          "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=",
          "requires": {
            "camelcase": "4.1.0",
            "cliui": "3.2.0",
            "decamelize": "1.2.0",
            "get-caller-file": "1.0.3",
            "os-locale": "2.1.0",
            "read-pkg-up": "2.0.0",
            "require-directory": "2.1.1",
            "require-main-filename": "1.0.1",
            "set-blocking": "2.0.0",
            "string-width": "2.1.1",
            "which-module": "2.0.0",
            "y18n": "3.2.1",
            "yargs-parser": "7.0.0"
          }
        },
        "yargs-parser": {
          "version": "7.0.0",
          "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz",
          "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=",
          "requires": {
            "camelcase": "4.1.0"
          }
        }
      }
    },
    "webpack-sources": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.2.0.tgz",
      "integrity": "sha512-9BZwxR85dNsjWz3blyxdOhTgtnQvv3OEs5xofI0wPYTwu5kaWxS08UuD1oI7WLBLpRO+ylf0ofnXLXWmGb2WMw==",
      "requires": {
        "source-list-map": "2.0.0",
        "source-map": "0.6.1"
      }
    },
    "which": {
      "version": "1.3.1",
      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
      "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
      "requires": {
        "isexe": "2.0.0"
      }
    },
    "which-module": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
      "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8="
    },
    "wide-align": {
      "version": "1.1.3",
      "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
      "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
      "requires": {
        "string-width": "2.1.1"
      }
    },
    "widest-line": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.0.tgz",
      "integrity": "sha1-AUKk6KJD+IgsAjOqDgKBqnYVInM=",
      "requires": {
        "string-width": "2.1.1"
      }
    },
    "window-size": {
      "version": "0.1.0",
      "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
      "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0="
    },
    "wordwrap": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
      "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus="
    },
    "wrap-ansi": {
      "version": "2.1.0",
      "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
      "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
      "requires": {
        "string-width": "1.0.2",
        "strip-ansi": "3.0.1"
      },
      "dependencies": {
        "is-fullwidth-code-point": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
          "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
          "requires": {
            "number-is-nan": "1.0.1"
          }
        },
        "string-width": {
          "version": "1.0.2",
          "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
          "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
          "requires": {
            "code-point-at": "1.1.0",
            "is-fullwidth-code-point": "1.0.0",
            "strip-ansi": "3.0.1"
          }
        }
      }
    },
    "wrappy": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
    },
    "write": {
      "version": "0.2.1",
      "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",
      "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=",
      "requires": {
        "mkdirp": "0.5.1"
      }
    },
    "write-file-atomic": {
      "version": "2.3.0",
      "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz",
      "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==",
      "requires": {
        "graceful-fs": "4.1.11",
        "imurmurhash": "0.1.4",
        "signal-exit": "3.0.2"
      }
    },
    "xdg-basedir": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz",
      "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ="
    },
    "xtend": {
      "version": "4.0.1",
      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
      "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
    },
    "y18n": {
      "version": "3.2.1",
      "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
      "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE="
    },
    "yallist": {
      "version": "2.1.2",
      "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
      "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
    },
    "yargs": {
      "version": "7.1.0",
      "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz",
      "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=",
      "requires": {
        "camelcase": "3.0.0",
        "cliui": "3.2.0",
        "decamelize": "1.2.0",
        "get-caller-file": "1.0.3",
        "os-locale": "1.4.0",
        "read-pkg-up": "1.0.1",
        "require-directory": "2.1.1",
        "require-main-filename": "1.0.1",
        "set-blocking": "2.0.0",
        "string-width": "1.0.2",
        "which-module": "1.0.0",
        "y18n": "3.2.1",
        "yargs-parser": "5.0.0"
      },
      "dependencies": {
        "camelcase": {
          "version": "3.0.0",
          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
          "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo="
        },
        "is-fullwidth-code-point": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
          "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
          "requires": {
            "number-is-nan": "1.0.1"
          }
        },
        "string-width": {
          "version": "1.0.2",
          "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
          "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
          "requires": {
            "code-point-at": "1.1.0",
            "is-fullwidth-code-point": "1.0.0",
            "strip-ansi": "3.0.1"
          }
        }
      }
    },
    "yargs-parser": {
      "version": "5.0.0",
      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz",
      "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=",
      "requires": {
        "camelcase": "3.0.0"
      },
      "dependencies": {
        "camelcase": {
          "version": "3.0.0",
          "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
          "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo="
        }
      }
    }
  }
}
libs/better-framework/gutenberg/dev/.eslintrc.json000064400000012440151214002640016305 0ustar00{
	"root": true,
	"parser": "babel-eslint",
	"extends": [
		"wordpress",
		"plugin:react/recommended",
		"plugin:jsx-a11y/recommended",
		"plugin:jest/recommended"
	],
	"env": {
		"browser": false,
		"es6": true,
		"node": true,
		"mocha": true,
		"jest/globals": true
	},
	"parserOptions": {
		"sourceType": "module",
		"ecmaFeatures": {
			"jsx": true
		}
	},
	"globals": {
		"wp": true,
		"wpApiSettings": true,
		"window": true,
		"document": true
	},
	"plugins": ["react", "jsx-a11y", "jest"],
	"settings": {
		"react": {
			"pragma": "wp"
		}
	},
	"rules": {
		"array-bracket-spacing": ["error", "always"],
		"brace-style": ["error", "1tbs"],
		"camelcase": ["error", { "properties": "never" }],
		"comma-dangle": ["error", "always-multiline"],
		"comma-spacing": "error",
		"comma-style": "error",
		"computed-property-spacing": ["error", "always"],
		"constructor-super": "error",
		"dot-notation": "error",
		"eol-last": "error",
		"eqeqeq": "error",
		"func-call-spacing": "error",
		"indent": ["error", "tab", { "SwitchCase": 1 }],
		"jsx-a11y/label-has-for": [
			"error",
			{
				"required": "id"
			}
		],
		"jsx-a11y/media-has-caption": "off",
		"jsx-a11y/no-noninteractive-tabindex": "off",
		"jsx-a11y/role-has-required-aria-props": "off",
		"jsx-quotes": "error",
		"key-spacing": "error",
		"keyword-spacing": "error",
		"lines-around-comment": "off",
		"no-alert": "error",
		"no-bitwise": "error",
		"no-caller": "error",
		"no-console": "error",
		"no-const-assign": "error",
		"no-debugger": "error",
		"no-dupe-args": "error",
		"no-dupe-class-members": "error",
		"no-dupe-keys": "error",
		"no-duplicate-case": "error",
		"no-duplicate-imports": "error",
		"no-else-return": "error",
		"no-eval": "error",
		"no-extra-semi": "error",
		"no-fallthrough": "error",
		"no-lonely-if": "error",
		"no-mixed-operators": "error",
		"no-mixed-spaces-and-tabs": "error",
		"no-multiple-empty-lines": ["error", { "max": 1 }],
		"no-multi-spaces": "error",
		"no-multi-str": "off",
		"no-negated-in-lhs": "error",
		"no-nested-ternary": "error",
		"no-redeclare": "error",
		"no-restricted-syntax": [
			"error",
			{
				"selector":
					"ImportDeclaration[source.value=/^@wordpress\\u002F.+\\u002F/]",
				"message": "Path access on WordPress dependencies is not allowed."
			},
			{
				"selector": "ImportDeclaration[source.value=/^blocks$/]",
				"message": "Use @wordpress/blocks as import path instead."
			},
			{
				"selector": "ImportDeclaration[source.value=/^components$/]",
				"message": "Use @wordpress/components as import path instead."
			},
			{
				"selector": "ImportDeclaration[source.value=/^date$/]",
				"message": "Use @wordpress/date as import path instead."
			},
			{
				"selector": "ImportDeclaration[source.value=/^editor$/]",
				"message": "Use @wordpress/editor as import path instead."
			},
			{
				"selector": "ImportDeclaration[source.value=/^element$/]",
				"message": "Use @wordpress/element as import path instead."
			},
			{
				"selector": "ImportDeclaration[source.value=/^i18n$/]",
				"message": "Use @wordpress/i18n as import path instead."
			},
			{
				"selector": "ImportDeclaration[source.value=/^data$/]",
				"message": "Use @wordpress/data as import path instead."
			},
			{
				"selector": "ImportDeclaration[source.value=/^utils$/]",
				"message": "Use @wordpress/utils as import path instead."
			},
			{
				"selector":
					"CallExpression[callee.name=/^__|_n|_x$/]:not([arguments.0.type=/^Literal|BinaryExpression$/])",
				"message": "Translate function arguments must be string literals."
			},
			{
				"selector":
					"CallExpression[callee.name=/^_n|_x$/]:not([arguments.1.type=/^Literal|BinaryExpression$/])",
				"message": "Translate function arguments must be string literals."
			},
			{
				"selector":
					"CallExpression[callee.name=_nx]:not([arguments.2.type=/^Literal|BinaryExpression$/])",
				"message": "Translate function arguments must be string literals."
			}
		],
		"no-shadow": "error",
		"no-undef": "error",
		"no-undef-init": "error",
		"no-unreachable": "error",
		"no-unsafe-negation": "error",
		"no-unused-expressions": "error",
		"no-unused-vars": "error",
		"no-useless-computed-key": "error",
		"no-useless-constructor": "error",
		"no-useless-return": "error",
		"no-var": "error",
		"no-whitespace-before-property": "error",
		"object-curly-spacing": ["error", "always"],
		"padded-blocks": ["error", "never"],
		"prefer-const": "error",
		"quote-props": ["error", "as-needed"],
		"react/display-name": "off",
		"react/jsx-curly-spacing": [
			"error",
			{
				"when": "always",
				"children": true
			}
		],
		"react/jsx-equals-spacing": "error",
		"react/jsx-indent": ["error", "tab"],
		"react/jsx-indent-props": ["error", "tab"],
		"react/jsx-key": "error",
		"react/jsx-tag-spacing": "error",
		"react/no-children-prop": "off",
		"react/no-find-dom-node": "warn",
		"react/prop-types": "off",
		"semi": "error",
		"semi-spacing": "error",
		"space-before-blocks": ["error", "always"],
		"space-before-function-paren": ["error", "never"],
		"space-in-parens": ["error", "always"],
		"space-infix-ops": ["error", { "int32Hint": false }],
		"space-unary-ops": [
			"error",
			{
				"overrides": {
					"!": true
				}
			}
		],
		"template-curly-spacing": ["error", "always"],
		"valid-jsdoc": ["error", { "requireReturn": false }],
		"valid-typeof": "error",
		"yoda": "off"
	}
}
libs/better-framework/gutenberg/dev/.editorconfig000064400000000623151214002640016166 0ustar00# This file is for unifying the coding style for different editors and IDEs
# editorconfig.org

# WordPress Coding Standards
# https://make.wordpress.org/core/handbook/coding-standards/

root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = tab

[*.yml]
indent_style = space
indent_size = 2

[*.md]
trim_trailing_whitespace = false
libs/better-framework/gutenberg/dev/src/affects.js000064400000000271151214002640016250 0ustar00

jQuery(document).on('change', ".affect-block-align-on-change :input", function () {

    $("#editor").find('.editor-block-list__block.is-selected').attr('data-align', this.value);
});libs/better-framework/gutenberg/dev/src/fields/image_select.js000064400000003452151214002640020530 0ustar00 class BF_Image_Select extends wp.element.Component {


    constructor() {

        super(...arguments);

        this.inputField = React.createRef();

    }

    componentDidMount() {
        this.inputField.current.addEventListener('input', this.onChange.bind(this), false)

    }

    componentWillUnmount() {
        this.inputField.current.removeEventListener('input', this.onChange.bind(this), false)

    }

    shouldComponentUpdate(nextProps, nextState) {

        // check

        return this.state !== nextState;
    }


    onChange() {

        if (this.props.onChange) {
            // this.props.onChange(this.inputField.current.value);
        }
    }

    render() {

        let currentValue = '0',
            currentLabel = '#label#';

        let items = this.props.options.map(function (option) {

            let currentClass = currentValue === option.id ? 'selected' : '';

            return (
                <li data-value={option.id} data-label={option.label} className={'image-select-option ' + currentClass} key={option.id}>
                    <img src={option.img} alt={option.label}/>
                    <p>{option.label}</p>
                </li>
            )
        });


        return (
            <div className="better-select-image">

                <div className="select-options">
                    <span className="selected-option">{currentLabel}</span>

                    <div className="better-select-image-options">
                        <ul className={'options-list bf-clearfix' + this.props.listStyle}>
                            {items}
                        </ul>
                    </div>
                </div>

                <input type="hidden" value={currentValue} ref={this.inputField}/>
            </div>
        )
    }
}

module.exports = BF_Image_Select;
libs/better-framework/gutenberg/dev/src/fields/heading.js000064400000000647151214002640017511 0ustar00function BF_Heading(props) {

    return (

        <div className="bf-section-container bf-clearfix">
            <div className="bf-section-heading bf-clearfix" data-id={props.id}
                 id={props.id}>
                <div className="bf-section-heading-title bf-clearfix">
                    <h3>{props.title}</h3>
                </div>
            </div>
        </div>
    )
}

module.exports = BF_Heading;
libs/better-framework/gutenberg/dev/src/fields/info.js000064400000001546151214002640017044 0ustar00function BF_Info(props) {

    let icons = {
        help: 'fa fa-support',
        info: 'fa fa-info ',
        warning: 'fa fa-warning',
        danger: 'fa fa-exclamation',
        _default: 'fa fa-info',
    };

    return (

        <div className="bf-section-container bf-clearfix">
            <div
                className={"bf-section-info bf-clearfix " + props.level + " " + props.state}>
                <div className="bf-section-info-title bf-clearfix">
                    <h3>
                        <i className={icons[props.level] || icons._default}></i>
                        {props.title}
                    </h3>
                </div>
                <div className="bf-controls-info-option bf-clearfix" dangerouslySetInnerHTML={{__html: props.note}}>
                </div>
            </div>
        </div>
    )
}

module.exports = BF_Info;
libs/better-framework/gutenberg/dev/src/fields/ajax_select.js000064400000003500151214002640020363 0ustar00class BF_Ajax_Select extends wp.element.Component {

    constructor() {

        super(...arguments);

        this.inputField = React.createRef();
    }

    componentDidMount() {

        this.inputField.current.addEventListener('input', this.onChange.bind(this), false)
    }

    componentWillUnmount() {

        this.inputField.current.removeEventListener('input', this.onChange.bind(this), false)

    }

    shouldComponentUpdate(nextProps, nextState) {

        // check

        return this.state !== nextState;
    }


    onChange() {

        if (this.props.onChange) {
            this.props.onChange(this.inputField.current.value);
        }
    }

    render() {
        
        let LiValues = this.props.values ? this.props.values.map(function(v) {

            return (
                <li id={v.id}>
                    {v.name}
                    <i className="del fa fa-remove"></i>
                </li>
            )
        }) : [];

        let inputValue = '';

        return (
            <div className="bf-ajax_select-field-container">
                <input type="text" className="bf-ajax-suggest-input" placeholder={this.props.placeholder}/>

                <span className="bf-search-loader">
                    <i className="fa fa-search"></i>
                </span>

                <input type="hidden" name={this.props.inputName}
                       ref={this.inputField}
                       value={inputValue} className={this.props.inputClass}
                       data-callback={this.props.callback} data-token={this.props.token}
                />

                <ul className="bf-ajax-suggest-search-results"></ul>

                <ul className="bf-ajax-suggest-controls">
                    {LiValues}
                </ul>
            </div>
        )
    }
}


module.exports = BF_Ajax_Select;
libs/better-framework/gutenberg/dev/src/fields/repeater.js000064400000005027151214002640017716 0ustar00class BF_Repeater extends wp.element.Component {

    constructor(props) {

        super(...arguments);

        let items = [];

        if (props.value && Array.isArray(props.value)) {
            items = props.value;
        }

        this.state = {items};
    }

    shouldComponentUpdate(nextProps, nextState) {

        return this.state !== nextState;
    }

    appendItem() {

        let items = this.state.items.concat([this.props.defaultParams]);

        this.setState({items});
    }

    itemChanged(value) {

        let items = JSON.parse(JSON.stringify(this.repeater.state.items));

        if (!items[this.i]) {
            items[this.i] = {};
        }

        items[this.i][this.id] = value;

        this.repeater.setState({items});

        this.repeater.onChange(items);
    }

    onChange(items) {

        this.props.onChange && this.props.onChange(items||this.state.items);
    }

    prepareChildrenElements(elements, elementsValue, i) {

        return elements.map((element) => {

            let id = element.props.id,
                value = elementsValue && elementsValue[id] ? elementsValue[id] : '';

            let key = id + "__" + i;

            let props = {
                value,
                key,
                i,
                id,
                onChange: this.itemChanged.bind({repeater: this, id, i})
            };

            if (element.props.children) {

                props.children = this.prepareChildrenElements(Array.isArray(element.props.children) ? element.props.children : [element.props.children], elementsValue, i);
            }

            return React.cloneElement(element, props);
        });
    }

    render() {

        let items = this.state.items.map((values, i) => {

            let children = this.prepareChildrenElements(this.props.children, values, i);

            return (
                <div className="bf-repeater-item" key={i}>
                    {children}
                </div>
            )
        });

        return (

            <div className="bf-controls bf-nonrepeater-controls bf-controls-repeater-option no-desc bf-clearfix">
                <div className="bf-repeater-items-container bf-clearfix">
                    {items}
                </div>
                <button className="bf-clone-repeater-item bf-button bf-main-button"
                        onClick={this.appendItem.bind(this)}
                        dangerouslySetInnerHTML={{__html: this.props.addLabel}}>
                </button>
            </div>
        )
    }
}

module.exports = BF_Repeater;
libs/better-framework/gutenberg/dev/src/fields/slider.js000064400000000727151214002640017373 0ustar00function BF_Slider(props) {

    return (
        <div className="bf-slider-field">
            <div className="bf-slider-slider"
                 data-dimension =       {props.dimension} data-animation={props.animation} data-step={props.step}
                 data-val={props.value} data-min={props.min} data-max={props.max}
            ></div>
            <input type="hidden" className="bf-slider-input" value="0"/>
        </div>
    )
}

module.exports = BF_Slider;
libs/better-framework/gutenberg/dev/src/fields/‌image_preview.js000064400000000526151214002640021707 0ustar00function BF_Image_Preview(params) {

    let images = params.urls.map(function (url, k) {

        return <img src={url} className={'image' + k} key={k}/>
    });

    return (

        <div className="info-value"
             style={{textAlign: params.align}}>
            {images}
        </div>
    )
}

module.exports = BF_Image_Preview;
libs/better-framework/gutenberg/dev/src/fields/ajax_action.js000064400000000712151214002640020363 0ustar00function BF_Ajax_action(props) {

    return (
        <div className="bf-ajax_action-field-container">

            <a className="bf-action-button bf-button bf-main-button"
               data-callback={props.callback} data-event={props.event}
               data-token={props.token} data-confirm={props.confirm}
               dangerouslySetInnerHTML={{__html: props.buttonName}}>
            </a>
        </div>

    )
}

module.exports = BF_Ajax_action;
libs/better-framework/gutenberg/dev/src/fields/hr.js000064400000000124151214002640016511 0ustar00function BF_Hr() {
    return (<hr className="bf-hr"/>)
}


module.exports = BF_Hr;
libs/better-framework/gutenberg/dev/src/fields/select_popup.js000064400000004134151214002640020607 0ustar00class BF_Select_Popup extends wp.element.Component {

    constructor() {

        super(...arguments);

        this.inputField = React.createRef();
    }

    componentDidMount() {

        this.inputField.current.addEventListener('input', this.onChange.bind(this), false)
    }

    componentWillUnmount() {

        this.inputField.current.removeEventListener('input', this.onChange.bind(this), false)

    }

    shouldComponentUpdate() {

        return false;
    }


    onChange() {
        //
        if (this.props.onChange) {
            this.props.onChange(this.inputField.current.value);
        }
    }

    render() {

        let labels = this.props.data.texts,
            currentImage = '',
            currentLabel = labels.default_text;

        if (this.props.data && this.props.data.options) {

            let opt = this.props.data.options[this.props.value] ?
                this.props.data.options[this.props.value] : this.props.data.options.default;

            if (opt) {
                currentImage = opt.current_img ? opt.current_img : opt.img;
                currentLabel = opt.label;
            }
        }


        return (

            <div className="select-popup-field bf-clearfix">
                <div className="select-popup-selected-image">
                    <img src={currentImage} alt={this.props.value}/>
                </div>
                <div className="select-popup-selected-info">
                    <div className="active-item-text">
                        {labels.box_pre_title}
                    </div>
                    <div className="active-item-label">{currentLabel}</div>

                    <a href="#" className="button">
                        {labels.box_button}
                    </a>
                </div>

                <script type="application/json" className="select-popup-data">{JSON.stringify(this.props.data)}</script>

                <input type="hidden" name={this.props.id} value={this.props.value} className="select-value"
                       ref={this.inputField}/>
            </div>
        )
    }
}


module.exports = BF_Select_Popup;
libs/better-framework/gutenberg/dev/src/fields/bf_edit_panel.js000064400000000645151214002640020663 0ustar00class BF_Edit_Panel extends wp.element.Component {


    componentDidMount() {

        document.dispatchEvent(
            new CustomEvent('bf-edit-gutenberg-block', {detail: ReactDOM.findDOMNode(this),})
        );
    }

    render() {

        return (
            <div className="bf-edit-gutenberg-block">
                {this.props.children}
            </div>
        );
    }
}


module.exports = BF_Edit_Panel;
libs/better-framework/gutenberg/dev/src/fields/editor.js000064400000002236151214002640017374 0ustar00class BF_Editor extends wp.element.Component {

    constructor() {

        super(...arguments);

        this.inputField = React.createRef();
    }

    componentDidMount() {
        document.dispatchEvent(
            new Event('bf-component-did-mount')
        );

        this.inputField.current.addEventListener('input', this.onChange.bind(this), false)
    }

    componentWillUnmount() {

        this.inputField.current.removeEventListener('input', this.onChange.bind(this), false)

    }
    shouldComponentUpdate(nextProps, nextState) {

        return this.state !== nextState;
    }


    onChange() {

        if (this.props.onChange) {
            this.props.onChange(this.inputField.current.value);
        }
    }

    render() {

        return (
            <div className="bf-editor-wrapper">
                <pre className="bf-editor" data-lang={this.props.lang}
                     data-max-lines={this.props.maxLines}
                     data-min-lines={this.props.minLines}></pre>

                <textarea className="bf-editor-field"  ref={this.inputField}>{this.props.value}</textarea>
            </div>
        )
    }
}


module.exports = BF_Editor;
libs/better-framework/gutenberg/dev/src/fields/bf_section_container.js000064400000002671151214002640022266 0ustar00class BF_Section_Container extends wp.element.Component {

    componentDidMount() {

        document.dispatchEvent(
            new CustomEvent('bf-component-did-mount', {detail: ReactDOM.findDOMNode(this),})
        );
    }

    render() {

        let noHeadingClass = this.props.label.trim() === '' ? ' bf-no-heading' : '';

        let classes = this.props.classes ? this.props.classes : '';

        return (

            <div className={"bf-section-container bf-gutenberg bf-clearfix " + classes}
                 data-param-name={this.props.name}
                 data-param-settings={this.props.show_on ? JSON.stringify(this.props.show_on) : ''}
            >
                <div
                    className={'bf-section bf-clearfix bf-section-' + this.props.type + noHeadingClass}
                    data-id={this.props.name}>

                    <div className={'bf-heading bf-clearfix bf-heading-' + this.props.type}>
                        <h3><label>{this.props.label}</label></h3>
                    </div>

                    <div className="bf-controls bf-clearfix">
                        {this.props.children}
                    </div>

                    <div className="bf-explain bf-nonrepeater-explain bf-clearfix"
                         dangerouslySetInnerHTML={{__html: this.props.description}}>
                    </div>

                </div>
            </div>
        )
    }
}


module.exports = BF_Section_Container;
libs/better-framework/gutenberg/dev/src/fields/term_select.js000064400000004370151214002640020415 0ustar00class BF_Switch extends wp.element.Component {

    constructor() {

        super(...arguments);

        this.inputField = React.createRef();

    }

    componentDidMount() {

        this.inputField.current.addEventListener('input', this.onChange.bind(this), false)


        /// ReactDOM.findDOMNode(this),
        document.dispatchEvent(
            new CustomEvent('bf-component-did-mount', {detail: ReactDOM.findDOMNode(this),})
        );
    }

    componentWillUnmount() {

        this.inputField.current.removeEventListener('input', this.onChange.bind(this), false)
    }

    onChange() {

        this.props.onChange
        &&
        this.props.onChange(this.inputField.current.value);
    }

    render() {

        return (

            <div className="bf-term-select-field">
                <div className="bf-field-term-select-wrapper bf-field-term-select-deferred loading"
                     data-taxonomy={this.props.taxonomy}>
                    Loading...
                </div>

                <div className="bf-field-term-select-help">
                    <label>{this.props.labels.help}</label>

                    <div className="bf-checkbox-multi-state disabled none-state">
                        <span data-state="none"></span>
                    </div>
                    <label>{this.props.labels.not_selected}</label>

                    <div className="bf-checkbox-multi-state disabled active-state">
                        <span className="bf-checkbox-active">
                            <i className="fa fa-check" aria-hidden="true"></i>
                        </span>
                    </div>
                    <label>{this.props.labels.selected}</label>

                    <div className="bf-checkbox-multi-state disabled deactivate-state">
                        <span className="bf-checkbox-active">
                           <i className="fa fa-times" aria-hidden="true"></i>
                        </span>
                    </div>

                    <label>{this.props.labels.excluded}</label>
                </div>

                <input type="hidden" value={this.props.value} ref={this.inputField}
                       className="bf-term-select-value"/>
            </div>
        )
    }
}

module.exports = BF_Switch;
libs/better-framework/gutenberg/dev/src/fields/‌image_radio.js000064400000003663151214002640021331 0ustar00class BF_Image_Radio extends wp.element.Component {


    constructor() {

        super(...arguments);

        this.inputField = React.createRef();

        this.state = {
            active: this.props.value
        }
    }

    componentDidMount() {

        this.inputField.current.addEventListener('input', this.onChange.bind(this), false)
    }

    componentWillUnmount() {

        this.inputField.current.removeEventListener('input', this.onChange.bind(this), false)

    }

    shouldComponentUpdate(nextProps, nextState) {

        // check

        return this.state !== nextState;
    }


    onChange() {

        console.log("#CHANGE");

        let active = this.inputField.current.value;

        if (this.props.onChange) {
            this.props.onChange(active);
        }


        this.setState({active});

    }

    render() {

        let activeValue = this.state.active;

        let options = this.props.options ? this.props.options : [];

        let onChange = this.onChange.bind(this);

        return (
            <div className="image-radio-field">
                {options.map((item, i) => {

                    let key = item.id || i;

                    return (
                        <div className="bf-image-radio-option" key={key}>

                            <label>

                                <input type="radio" onChange={onChange} value={key}
                                       defaultChecked={activeValue === key}/>

                            </label>

                            <img src={item.img} alt={item.label}/>

                            <p className="item-label">
                                {item.label}
                            </p>
                        </div>
                    )
                })}

                <input type="hidden" value={activeValue} ref={this.inputField} className="image-radio-value"/>
            </div>
        )
    }
}

module.exports = BF_Image_Radio;
libs/better-framework/gutenberg/dev/src/fields/icon_select.js000064400000006416151214002640020401 0ustar00class BF_Icon_Select extends wp.element.Component {

    constructor() {

        super(...arguments);

        this.inputs = {
            icon: React.createRef(),
            height: React.createRef(),
            width: React.createRef(),
            code: React.createRef(),
        };
    }

    componentDidMount() {

        this.inputs.icon.current.addEventListener('input', this.onChange.bind(this), false)
    }

    componentWillUnmount() {

        this.inputs.icon.current.removeEventListener('input', this.onChange.bind(this), false)

    }

    shouldComponentUpdate(nextProps, nextState) {

        // check
        return this.state !== nextState;
    }

    iconType(icon) {

        if(! icon) {
            return '';
        }

        if (icon.substr(0, 3) == 'fa-') {
            return 'fontawesome';
        } // BetterStudio Font Icon
        else if (icon.substr(0, 5) == 'bsfi-' || icon.substr(0, 5) == 'bsai-') {

            return 'bs-icons';
        } // Dashicon
        else if (icon.substr(0, 10) == 'dashicons-') {
            return 'Dashicon';
        }

        return 'custom-icon';
    }

    iconTag(icon) {

        if(! icon) {
            return '';
        }

        icon = icon.toString();

        if (icon.substr(0, 3) == 'fa-') {
            return '<i class="bf-icon fa ' + icon + '"></i>';
        } // BetterStudio Font Icon
        else if (icon.substr(0, 5) == 'bsfi-') {

            return '<i class="bf-icon ' + icon + '"></i>';
        } // Dashicon
        else if (icon.substr(0, 10) == 'dashicons-') {
            return '<i class="bf-icon dashicons dashicons-' + icon + '"></i>';
        } // Better Studio Admin Icon
        else if (icon.substr(0, 5) == 'bsai-') {
            return '<i class="bf-icon ' + icon + '"></i>';
        } // Custom Icon -> as URL


        if (icon)
            return '<i class="bf-icon bf-custom-icon bf-custom-icon-url"><img src="' + icon + '"></i>';

        return '';
    }

    onChange() {

        this.props.onChange
        &&
        this.props.onChange({

            font_code: this.inputs.code.current.value,
            icon: this.inputs.icon.current.value,
            type: this.iconType(this.inputs.icon.current.value),
            height: this.inputs.height.current.value,
            width: this.inputs.width.current.value
        });
    }


    render() {

        let value = this.props.value;

        return (

            <div className="bf-icon-modal-handler">

                <div className="select-options">
                    <span className="selected-option"
                          dangerouslySetInnerHTML={{__html: this.iconTag(value && value.icon)}}>
                    </span>
                </div>

                <input type="hidden" className="icon-input" ref={this.inputs.icon} value={value && value.icon}/>
                <input type="hidden" className="icon-input-font-code" ref={this.inputs.code}
                       value={value && value.font_code}/>

                <input type="hidden" className="icon-input-height" ref={this.inputs.height}
                       value={value && value.height}/>
                <input type="hidden" className="icon-input-width" ref={this.inputs.width} value={value && value.width}/>
            </div>
        )
    }
}


module.exports = BF_Icon_Select;
libs/better-framework/gutenberg/dev/src/fields/background_image.js000064400000003334151214002640021367 0ustar00/**
 * todo: add support for type param
 */
class BF_Background_Image extends wp.element.Component {

    constructor() {

        super(...arguments);

        this.inputField = React.createRef();
    }

    componentDidMount() {

        this.inputField.current.addEventListener('input', this.onChange.bind(this), false)
    }

    componentWillUnmount() {

        this.inputField.current.removeEventListener('input', this.onChange.bind(this), false)
    }

    shouldComponentUpdate(nextProps, nextState) {

        // check
        return this.state !== nextState;
    }

    onChange() {

        if (this.props.onChange) {
            this.props.onChange({type: '', img: this.inputField.current.value});
        }
    }

    render() {

        let props = this.props;

        let imageUrl = '';

        if (props.value && props.value.img) {
            imageUrl = props.value.img;
        }

        return (

            <div className="bf-background-image-field">

                <a href="#" className="bf-button bf-main-button bf-background-image-upload-btn"
                   data-mediatitle={props.mediaTitle} buttontext={props.buttonText}
                ><i className="fa fa-upload"></i> {props.uploadLabel}</a>

                <a href="#" className="bf-button bf-background-image-remove-btn"

                ><i className="fa fa-remove"></i> {props.removeLabel}</a>


                <input type="hidden" className={"bf-background-image-input " + props.inputClass}
                       value={imageUrl} ref={this.inputField}/>

                <div className="bf-background-image-preview">
                    <img src={imageUrl}/>
                </div>
            </div>
        )
    }
}


module.exports = BF_Background_Image;
libs/better-framework/gutenberg/dev/src/fields/sorter_checkbox.js000064400000006540151214002640021274 0ustar00class BF_Sorter_Checkbox extends wp.element.Component {

    constructor(props) {

        super(...arguments);

        let items = {};

        if (props.value && Array.isArray(props.value)) {
            items = props.value;
        }

        this.state = {items};

        this.onChange = this.onChange.bind(this);
    }

    componentDidMount() {

        document.dispatchEvent(
            new Event('bf-component-did-mount')
        );
    }

    shouldComponentUpdate(nextProps, nextState) {

        return this.state !== nextState || this.props !== nextProps;
    }

    collectValues() {

        let values = {};

        [...ReactDOM.findDOMNode(this).getElementsByClassName('sorter-checkbox-value')].forEach(function (e) {

            values[e.name] = e.checked ? '1' : '0';
        });

        return values;
    }

    onChange() {

        let inputValues = this.collectValues();

        if (inputValues !== this.state.items) {
            this.setState({items: inputValues})
        }

        if (this.props.onChange) {
            this.props.onChange(inputValues);
        }
    }

    render() {

        let values = this.state.items;

        let li = item => {

            let extraClass = item.cssClass ? item.cssClass : '';
            let activeClass = values[item.id] ? '' : 'checked-item';

            return (
                <li id={'bf-sorter-group-item-' + this.props.id + '-' + item.id} key={item.id}
                    className={extraClass + ' ' + 'item-' + this.props.id + ' ' + activeClass}
                >

                    <label>
                        <input value="1" type="checkbox"
                               defaultChecked={!!values[item.id]}
                               onChange={this.onChange} name={item.id}
                               className="sorter-checkbox-value"/>
                        <p dangerouslySetInnerHTML={{__html: item.label}}></p>
                    </label>

                </li>
            )
        };

        let displayedItems = [];

        let activeAndSelectedItems = this.props.items.filter((item) => {

            let visible = values[item.id] !== -1 && item.cssClass.indexOf('active-item') !== -1;

            if (visible) {
                displayedItems.push(item.id);
            }

            return visible;
        });

        let activeAndDeSelectedItems = this.props.items.filter((item) => {

            let visible = values[item.id] === -1 && item.cssClass.indexOf('active-item') !== -1;

            if (visible) {
                displayedItems.push(item.id);
            }

            return visible;
        });

        let disabledItems = this.props.items.filter((item) => {

            return displayedItems.indexOf(item.id) === -1;
        });


        return (
            <div className="bf-sorter-groups-container">

                <ul id={"bf-sorter-group-" + this.props.id} className={'bf-sorter-list bf-sorter-' + this.props.id}>

                    {
                        activeAndSelectedItems.map(li)
                    }

                    <li key="x2">activeAndDeSelectedItems</li>

                    {
                        activeAndDeSelectedItems.map(li)
                    }

                    {
                        disabledItems.map(li)
                    }
                </ul>
            </div>
        )
    }
}

module.exports = BF_Sorter_Checkbox;
libs/better-framework/gutenberg/dev/src/fields/switch.js000064400000002156151214002640017410 0ustar00class BF_Switch extends wp.element.Component {

    constructor() {

        super(...arguments);

        this.inputField = React.createRef();

    }

    componentDidMount() {

        this.inputField.current.addEventListener('input', this.onChange.bind(this), false)
    }

    componentWillUnmount() {

        this.inputField.current.removeEventListener('input', this.onChange.bind(this), false)

    }

    onChange() {

        if (this.props.onChange) {

            this.props.onChange(parseInt(this.inputField.current.value));
        }
    }

    render() {

        let checked = !!parseInt(this.props.value);

        return (

            <div className="bf-switch bf-clearfix">
                <label
                    className={"cb-enable" + (checked ? ' selected' : '')}><span>{this.props.onLabel}</span></label>
                <label
                    className={"cb-disable" + (checked ? '' : ' selected')}><span>{this.props.offLabel}</span></label>

                <input type="hidden" value="0" className="checkbox" ref={this.inputField}/>
            </div>
        )
    }
}

module.exports = BF_Switch;
libs/better-framework/gutenberg/dev/src/fields/media_image.js000064400000003431151214002640020325 0ustar00class BF_Media_Image extends wp.element.Component {

    constructor() {

        super(...arguments);

        this.inputField = React.createRef();
    }

    componentDidMount() {

        this.inputField.current.addEventListener('input', this.onChange.bind(this), false)
    }

    componentWillUnmount() {

        this.inputField.current.removeEventListener('input', this.onChange.bind(this), false)

    }

    shouldComponentUpdate(nextProps, nextState) {

        // check
        return this.state !== nextState;
    }


    onChange() {

        if (this.props.onChange) {
            this.props.onChange(this.inputField.current.value);
        }
    }

    render() {

        var img = this.props.value;
        
        return (

            <div className="bf-media-image-field">

                <a href="#"
                   className={'bf-button bf-main-button bf-media-image-upload-btn' + (this.props.dataType === 'id' ? 'bf-media-type-id' : '')}
                   data-media-title={this.props.mediaTitle} data-button-text={this.props.mediaButton}
                   data-size={this.props.size}

                ><i className="fa fa-upload"></i> {this.props.uploadLabel}</a>

                <a href="#"
                   className="bf-button bf-media-image-remove-btn"
                   style={{display: img ? 'inline' : 'none'}}
                ><i
                    className="fa fa-remove"></i> {this.props.removeLabel}</a>

                <input type={this.props.showInput ? "text" : "hidden"} className="bf-media-image-input ltr" ref={this.inputField}/>

                <div className="bf-media-image-preview" style={{display: img ? 'block' : 'none'}}>
                    <img src={img}/>
                </div>
            </div>
        )
    }
}


module.exports = BF_Media_Image;
libs/better-framework/gutenberg/dev/src/fields/code.js000064400000000645151214002640017022 0ustar00function BF_Code(params) {

    return (

        <textarea className="bf-code-editor"
                  data-lang={params.lang} data-line-numbers={params.lineNumber}
                  data-auto-close-brackets={params.autoCloseBrackets}
                  data-auto-close-tags={params.autoCloseTags}
                  placeholder={params.placeholder}
        >{params.value}</textarea>
    )
}


module.exports = BF_Code;
libs/better-framework/gutenberg/dev/src/globals.js000064400000002563151214002640016266 0ustar00if (wp && wp.components) {

    wp.components.BF_Repeater = require('./fields/repeater')
    wp.components.BF_Hr = require('./fields/hr')
    wp.components.BF_Info = require('./fields/info')
    wp.components.BF_Heading = require('./fields/heading')
    wp.components.BF_Select_Popup = require('./fields/select_popup')
    wp.components.BF_Icon_Select = require('./fields/icon_select')
    wp.components.BF_Ajax_Action = require('./fields/ajax_action')
    wp.components.BF_Ajax_Select = require('./fields/ajax_select')
    wp.components.BF_Background_Image = require('./fields/background_image')
    wp.components.BF_Code = require('./fields/code')
    wp.components.BF_Editor = require('./fields/editor')
    wp.components.BF_Image_Preview = require('./fields/‌image_preview')
    wp.components.BF_Image_Radio = require('./fields/‌image_radio')
    wp.components.BF_Image_Select = require('./fields/image_select')
    wp.components.BF_Media_Image = require('./fields/media_image')
    wp.components.BF_Slider = require('./fields/slider')
    wp.components.BF_Sorter_Checkbox = require('./fields/sorter_checkbox')
    wp.components.BF_Section_Container = require('./fields/bf_section_container')
    wp.components.BF_Switch = require('./fields/switch')
    wp.components.BF_Term_Select = require('./fields/term_select')
    wp.components.BF_Edit_Panel = require('./fields/bf_edit_panel')
}
libs/better-framework/gutenberg/dev/src/blocks.js000064400000000047151214002640016113 0ustar00import './globals'

import './affects'
libs/better-framework/gutenberg/dev/src/init.php000064400000004206151214002640015755 0ustar00<?php
/**
 * Blocks Initializer
 *
 * Enqueue CSS/JS of all the blocks.
 *
 * @since   1.0.0
 * @package CGB
 */

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Enqueue Gutenberg block assets for both frontend + backend.
 *
 * `wp-blocks`: includes block type registration and related functions.
 *
 * @since 1.0.0
 */
function dev_cgb_block_assets() {

	// Styles.
	wp_enqueue_style(
		'dev-cgb-style-css', // Handle.
		plugins_url( 'dist/blocks.style.build.css', dirname( __FILE__ ) ), // Block style CSS.
		array( 'wp-blocks' ) // Dependency to include the CSS after it.
	// filemtime( plugin_dir_path( __DIR__ ) . 'dist/blocks.style.build.css' ) // Version: filemtime — Gets file modification time.
	);
} // End function dev_cgb_block_assets().

// Hook: Frontend assets.
add_action( 'enqueue_block_assets', 'dev_cgb_block_assets' );

/**
 * Enqueue Gutenberg block assets for backend editor.
 *
 * `wp-blocks`: includes block type registration and related functions.
 * `wp-element`: includes the WordPress Element abstraction for describing the structure of your blocks.
 * `wp-i18n`: To internationalize the block's text.
 *
 * @since 1.0.0
 */
function dev_cgb_editor_assets() {

	// Scripts.
	wp_enqueue_script(
		'dev-cgb-block-js', // Handle.
		plugins_url( '/dist/blocks.build.js', dirname( __FILE__ ) ), // Block.build.js: We register the block here. Built with Webpack.
		array( 'wp-blocks', 'wp-i18n', 'wp-element' ), // Dependencies, defined above.
		// filemtime( plugin_dir_path( __DIR__ ) . 'dist/blocks.build.js' ), // Version: filemtime — Gets file modification time.
		true // Enqueue the script in the footer.
	);

	// Styles.
	wp_enqueue_style(
		'dev-cgb-block-editor-css', // Handle.
		plugins_url( 'dist/blocks.editor.build.css', dirname( __FILE__ ) ), // Block editor CSS.
		array( 'wp-edit-blocks' ) // Dependency to include the CSS after it.
	// filemtime( plugin_dir_path( __DIR__ ) . 'dist/blocks.editor.build.css' ) // Version: filemtime — Gets file modification time.
	);
} // End function dev_cgb_editor_assets().

// Hook: Editor assets.
add_action( 'enqueue_block_editor_assets', 'dev_cgb_editor_assets' );
libs/better-framework/gutenberg/dev/dist/blocks.editor.build.css000064400000000606151214002640021027 0ustar00/**
 * #.# Common SCSS
 *
 * Can include things like variables and mixins
 * that are used across the project.
*/
/**
 * #.# Editor Styles
 *
 * CSS for just Backend enqueued after style.scss
 * which makes it higher in priority.
 */
.wp-block-cgb-block-dev {
  background: #bada55;
  border: 0.2rem solid #292929;
  color: #292929;
  margin: 0 auto;
  max-width: 740px;
  padding: 2rem; }
libs/better-framework/gutenberg/dev/dist/blocks.build.js000064400000107453151214002640017376 0ustar00!function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var n={};t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=0)}([function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(1),o=(n.n(r),n(23));n.n(o)},function(e,t,n){wp&&wp.components&&(wp.components.BF_Repeater=n(2),wp.components.BF_Hr=n(3),wp.components.BF_Info=n(4),wp.components.BF_Heading=n(5),wp.components.BF_Select_Popup=n(6),wp.components.BF_Icon_Select=n(7),wp.components.BF_Ajax_Action=n(8),wp.components.BF_Ajax_Select=n(9),wp.components.BF_Background_Image=n(10),wp.components.BF_Code=n(11),wp.components.BF_Editor=n(12),wp.components.BF_Image_Preview=n(13),wp.components.BF_Image_Radio=n(14),wp.components.BF_Image_Select=n(15),wp.components.BF_Media_Image=n(16),wp.components.BF_Slider=n(17),wp.components.BF_Sorter_Checkbox=n(18),wp.components.BF_Section_Container=n(19),wp.components.BF_Switch=n(20),wp.components.BF_Term_Select=n(21),wp.components.BF_Edit_Panel=n(22))},function(e,t){function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!==typeof t&&"function"!==typeof t?e:t}function o(e,t){if("function"!==typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var i=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),a=function(e){function t(e){n(this,t);var o=r(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments)),i=[];return e.value&&Array.isArray(e.value)&&(i=e.value),o.state={items:i},o}return o(t,e),i(t,[{key:"shouldComponentUpdate",value:function(e,t){return this.state!==t}},{key:"appendItem",value:function(){var e=this.state.items.concat([this.props.defaultParams]);this.setState({items:e})}},{key:"itemChanged",value:function(e){var t=JSON.parse(JSON.stringify(this.repeater.state.items));t[this.i]||(t[this.i]={}),t[this.i][this.id]=e,this.repeater.setState({items:t}),this.repeater.onChange(t)}},{key:"onChange",value:function(e){this.props.onChange&&this.props.onChange(e||this.state.items)}},{key:"prepareChildrenElements",value:function(e,t,n){var r=this;return e.map(function(e){var o=e.props.id,i=t&&t[o]?t[o]:"",a=o+"__"+n,l={value:i,key:a,i:n,id:o,onChange:r.itemChanged.bind({repeater:r,id:o,i:n})};return e.props.children&&(l.children=r.prepareChildrenElements(Array.isArray(e.props.children)?e.props.children:[e.props.children],t,n)),React.cloneElement(e,l)})}},{key:"render",value:function(){var e=this,t=this.state.items.map(function(t,n){var r=e.prepareChildrenElements(e.props.children,t,n);return wp.element.createElement("div",{className:"bf-repeater-item",key:n},r)});return wp.element.createElement("div",{className:"bf-controls bf-nonrepeater-controls bf-controls-repeater-option no-desc bf-clearfix"},wp.element.createElement("div",{className:"bf-repeater-items-container bf-clearfix"},t),wp.element.createElement("button",{className:"bf-clone-repeater-item bf-button bf-main-button",onClick:this.appendItem.bind(this),dangerouslySetInnerHTML:{__html:this.props.addLabel}}))}}]),t}(wp.element.Component);e.exports=a},function(e,t){function n(){return wp.element.createElement("hr",{className:"bf-hr"})}e.exports=n},function(e,t){function n(e){var t={help:"fa fa-support",info:"fa fa-info ",warning:"fa fa-warning",danger:"fa fa-exclamation",_default:"fa fa-info"};return wp.element.createElement("div",{className:"bf-section-container bf-clearfix"},wp.element.createElement("div",{className:"bf-section-info bf-clearfix "+e.level+" "+e.state},wp.element.createElement("div",{className:"bf-section-info-title bf-clearfix"},wp.element.createElement("h3",null,wp.element.createElement("i",{className:t[e.level]||t._default}),e.title)),wp.element.createElement("div",{className:"bf-controls-info-option bf-clearfix",dangerouslySetInnerHTML:{__html:e.note}})))}e.exports=n},function(e,t){function n(e){return wp.element.createElement("div",{className:"bf-section-container bf-clearfix"},wp.element.createElement("div",{className:"bf-section-heading bf-clearfix","data-id":e.id,id:e.id},wp.element.createElement("div",{className:"bf-section-heading-title bf-clearfix"},wp.element.createElement("h3",null,e.title))))}e.exports=n},function(e,t){function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!==typeof t&&"function"!==typeof t?e:t}function o(e,t){if("function"!==typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var i=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),a=function(e){function t(){n(this,t);var e=r(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments));return e.inputField=React.createRef(),e}return o(t,e),i(t,[{key:"componentDidMount",value:function(){this.inputField.current.addEventListener("input",this.onChange.bind(this),!1)}},{key:"componentWillUnmount",value:function(){this.inputField.current.removeEventListener("input",this.onChange.bind(this),!1)}},{key:"shouldComponentUpdate",value:function(){return!1}},{key:"onChange",value:function(){this.props.onChange&&this.props.onChange(this.inputField.current.value)}},{key:"render",value:function(){var e=this.props.data.texts,t="",n=e.default_text;if(this.props.data&&this.props.data.options){var r=this.props.data.options[this.props.value]?this.props.data.options[this.props.value]:this.props.data.options.default;r&&(t=r.current_img?r.current_img:r.img,n=r.label)}return wp.element.createElement("div",{className:"select-popup-field bf-clearfix"},wp.element.createElement("div",{className:"select-popup-selected-image"},wp.element.createElement("img",{src:t,alt:this.props.value})),wp.element.createElement("div",{className:"select-popup-selected-info"},wp.element.createElement("div",{className:"active-item-text"},e.box_pre_title),wp.element.createElement("div",{className:"active-item-label"},n),wp.element.createElement("a",{href:"#",className:"button"},e.box_button)),wp.element.createElement("script",{type:"application/json",className:"select-popup-data"},JSON.stringify(this.props.data)),wp.element.createElement("input",{type:"hidden",name:this.props.id,value:this.props.value,className:"select-value",ref:this.inputField}))}}]),t}(wp.element.Component);e.exports=a},function(e,t){function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!==typeof t&&"function"!==typeof t?e:t}function o(e,t){if("function"!==typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var i=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),a=function(e){function t(){n(this,t);var e=r(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments));return e.inputs={icon:React.createRef(),height:React.createRef(),width:React.createRef(),code:React.createRef()},e}return o(t,e),i(t,[{key:"componentDidMount",value:function(){this.inputs.icon.current.addEventListener("input",this.onChange.bind(this),!1)}},{key:"componentWillUnmount",value:function(){this.inputs.icon.current.removeEventListener("input",this.onChange.bind(this),!1)}},{key:"shouldComponentUpdate",value:function(e,t){return this.state!==t}},{key:"iconType",value:function(e){return e?"fa-"==e.substr(0,3)?"fontawesome":"bsfi-"==e.substr(0,5)||"bsai-"==e.substr(0,5)?"bs-icons":"dashicons-"==e.substr(0,10)?"Dashicon":"custom-icon":""}},{key:"iconTag",value:function(e){return e?(e=e.toString(),"fa-"==e.substr(0,3)?'<i class="bf-icon fa '+e+'"></i>':"bsfi-"==e.substr(0,5)?'<i class="bf-icon '+e+'"></i>':"dashicons-"==e.substr(0,10)?'<i class="bf-icon dashicons dashicons-'+e+'"></i>':"bsai-"==e.substr(0,5)?'<i class="bf-icon '+e+'"></i>':e?'<i class="bf-icon bf-custom-icon bf-custom-icon-url"><img src="'+e+'"></i>':""):""}},{key:"onChange",value:function(){this.props.onChange&&this.props.onChange({font_code:this.inputs.code.current.value,icon:this.inputs.icon.current.value,type:this.iconType(this.inputs.icon.current.value),height:this.inputs.height.current.value,width:this.inputs.width.current.value})}},{key:"render",value:function(){var e=this.props.value;return wp.element.createElement("div",{className:"bf-icon-modal-handler"},wp.element.createElement("div",{className:"select-options"},wp.element.createElement("span",{className:"selected-option",dangerouslySetInnerHTML:{__html:this.iconTag(e&&e.icon)}})),wp.element.createElement("input",{type:"hidden",className:"icon-input",ref:this.inputs.icon,value:e&&e.icon}),wp.element.createElement("input",{type:"hidden",className:"icon-input-font-code",ref:this.inputs.code,value:e&&e.font_code}),wp.element.createElement("input",{type:"hidden",className:"icon-input-height",ref:this.inputs.height,value:e&&e.height}),wp.element.createElement("input",{type:"hidden",className:"icon-input-width",ref:this.inputs.width,value:e&&e.width}))}}]),t}(wp.element.Component);e.exports=a},function(e,t){function n(e){return wp.element.createElement("div",{className:"bf-ajax_action-field-container"},wp.element.createElement("a",{className:"bf-action-button bf-button bf-main-button","data-callback":e.callback,"data-event":e.event,"data-token":e.token,"data-confirm":e.confirm,dangerouslySetInnerHTML:{__html:e.buttonName}}))}e.exports=n},function(e,t){function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!==typeof t&&"function"!==typeof t?e:t}function o(e,t){if("function"!==typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var i=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),a=function(e){function t(){n(this,t);var e=r(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments));return e.inputField=React.createRef(),e}return o(t,e),i(t,[{key:"componentDidMount",value:function(){this.inputField.current.addEventListener("input",this.onChange.bind(this),!1)}},{key:"componentWillUnmount",value:function(){this.inputField.current.removeEventListener("input",this.onChange.bind(this),!1)}},{key:"shouldComponentUpdate",value:function(e,t){return this.state!==t}},{key:"onChange",value:function(){this.props.onChange&&this.props.onChange(this.inputField.current.value)}},{key:"render",value:function(){var e=this.props.values?this.props.values.map(function(e){return wp.element.createElement("li",{id:e.id},e.name,wp.element.createElement("i",{className:"del fa fa-remove"}))}):[];return wp.element.createElement("div",{className:"bf-ajax_select-field-container"},wp.element.createElement("input",{type:"text",className:"bf-ajax-suggest-input",placeholder:this.props.placeholder}),wp.element.createElement("span",{className:"bf-search-loader"},wp.element.createElement("i",{className:"fa fa-search"})),wp.element.createElement("input",{type:"hidden",name:this.props.inputName,ref:this.inputField,value:"",className:this.props.inputClass,"data-callback":this.props.callback,"data-token":this.props.token}),wp.element.createElement("ul",{className:"bf-ajax-suggest-search-results"}),wp.element.createElement("ul",{className:"bf-ajax-suggest-controls"},e))}}]),t}(wp.element.Component);e.exports=a},function(e,t){function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!==typeof t&&"function"!==typeof t?e:t}function o(e,t){if("function"!==typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var i=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),a=function(e){function t(){n(this,t);var e=r(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments));return e.inputField=React.createRef(),e}return o(t,e),i(t,[{key:"componentDidMount",value:function(){this.inputField.current.addEventListener("input",this.onChange.bind(this),!1)}},{key:"componentWillUnmount",value:function(){this.inputField.current.removeEventListener("input",this.onChange.bind(this),!1)}},{key:"shouldComponentUpdate",value:function(e,t){return this.state!==t}},{key:"onChange",value:function(){this.props.onChange&&this.props.onChange({type:"",img:this.inputField.current.value})}},{key:"render",value:function(){var e=this.props,t="";return e.value&&e.value.img&&(t=e.value.img),wp.element.createElement("div",{className:"bf-background-image-field"},wp.element.createElement("a",{href:"#",className:"bf-button bf-main-button bf-background-image-upload-btn","data-mediatitle":e.mediaTitle,buttontext:e.buttonText},wp.element.createElement("i",{className:"fa fa-upload"})," ",e.uploadLabel),wp.element.createElement("a",{href:"#",className:"bf-button bf-background-image-remove-btn"},wp.element.createElement("i",{className:"fa fa-remove"})," ",e.removeLabel),wp.element.createElement("input",{type:"hidden",className:"bf-background-image-input "+e.inputClass,value:t,ref:this.inputField}),wp.element.createElement("div",{className:"bf-background-image-preview"},wp.element.createElement("img",{src:t})))}}]),t}(wp.element.Component);e.exports=a},function(e,t){function n(e){return wp.element.createElement("textarea",{className:"bf-code-editor","data-lang":e.lang,"data-line-numbers":e.lineNumber,"data-auto-close-brackets":e.autoCloseBrackets,"data-auto-close-tags":e.autoCloseTags,placeholder:e.placeholder},e.value)}e.exports=n},function(e,t){function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!==typeof t&&"function"!==typeof t?e:t}function o(e,t){if("function"!==typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var i=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),a=function(e){function t(){n(this,t);var e=r(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments));return e.inputField=React.createRef(),e}return o(t,e),i(t,[{key:"componentDidMount",value:function(){document.dispatchEvent(new Event("bf-component-did-mount")),this.inputField.current.addEventListener("input",this.onChange.bind(this),!1)}},{key:"componentWillUnmount",value:function(){this.inputField.current.removeEventListener("input",this.onChange.bind(this),!1)}},{key:"shouldComponentUpdate",value:function(e,t){return this.state!==t}},{key:"onChange",value:function(){this.props.onChange&&this.props.onChange(this.inputField.current.value)}},{key:"render",value:function(){return wp.element.createElement("div",{className:"bf-editor-wrapper"},wp.element.createElement("pre",{className:"bf-editor","data-lang":this.props.lang,"data-max-lines":this.props.maxLines,"data-min-lines":this.props.minLines}),wp.element.createElement("textarea",{className:"bf-editor-field",ref:this.inputField},this.props.value))}}]),t}(wp.element.Component);e.exports=a},function(e,t){function n(e){var t=e.urls.map(function(e,t){return wp.element.createElement("img",{src:e,className:"image"+t,key:t})});return wp.element.createElement("div",{className:"info-value",style:{textAlign:e.align}},t)}e.exports=n},function(e,t){function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!==typeof t&&"function"!==typeof t?e:t}function o(e,t){if("function"!==typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var i=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),a=function(e){function t(){n(this,t);var e=r(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments));return e.inputField=React.createRef(),e.state={active:e.props.value},e}return o(t,e),i(t,[{key:"componentDidMount",value:function(){this.inputField.current.addEventListener("input",this.onChange.bind(this),!1)}},{key:"componentWillUnmount",value:function(){this.inputField.current.removeEventListener("input",this.onChange.bind(this),!1)}},{key:"shouldComponentUpdate",value:function(e,t){return this.state!==t}},{key:"onChange",value:function(){console.log("#CHANGE");var e=this.inputField.current.value;this.props.onChange&&this.props.onChange(e),this.setState({active:e})}},{key:"render",value:function(){var e=this.state.active,t=this.props.options?this.props.options:[],n=this.onChange.bind(this);return wp.element.createElement("div",{className:"image-radio-field"},t.map(function(t,r){var o=t.id||r;return wp.element.createElement("div",{className:"bf-image-radio-option",key:o},wp.element.createElement("label",null,wp.element.createElement("input",{type:"radio",onChange:n,value:o,defaultChecked:e===o})),wp.element.createElement("img",{src:t.img,alt:t.label}),wp.element.createElement("p",{className:"item-label"},t.label))}),wp.element.createElement("input",{type:"hidden",value:e,ref:this.inputField,className:"image-radio-value"}))}}]),t}(wp.element.Component);e.exports=a},function(e,t){function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!==typeof t&&"function"!==typeof t?e:t}function o(e,t){if("function"!==typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var i=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),a=function(e){function t(){n(this,t);var e=r(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments));return e.inputField=React.createRef(),e}return o(t,e),i(t,[{key:"componentDidMount",value:function(){this.inputField.current.addEventListener("input",this.onChange.bind(this),!1)}},{key:"componentWillUnmount",value:function(){this.inputField.current.removeEventListener("input",this.onChange.bind(this),!1)}},{key:"shouldComponentUpdate",value:function(e,t){return this.state!==t}},{key:"onChange",value:function(){this.props.onChange}},{key:"render",value:function(){var e=this.props.options.map(function(e){var t="0"===e.id?"selected":"";return wp.element.createElement("li",{"data-value":e.id,"data-label":e.label,className:"image-select-option "+t,key:e.id},wp.element.createElement("img",{src:e.img,alt:e.label}),wp.element.createElement("p",null,e.label))});return wp.element.createElement("div",{className:"better-select-image"},wp.element.createElement("div",{className:"select-options"},wp.element.createElement("span",{className:"selected-option"},"#label#"),wp.element.createElement("div",{className:"better-select-image-options"},wp.element.createElement("ul",{className:"options-list bf-clearfix"+this.props.listStyle},e))),wp.element.createElement("input",{type:"hidden",value:"0",ref:this.inputField}))}}]),t}(wp.element.Component);e.exports=a},function(e,t){function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!==typeof t&&"function"!==typeof t?e:t}function o(e,t){if("function"!==typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var i=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),a=function(e){function t(){n(this,t);var e=r(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments));return e.inputField=React.createRef(),e}return o(t,e),i(t,[{key:"componentDidMount",value:function(){this.inputField.current.addEventListener("input",this.onChange.bind(this),!1)}},{key:"componentWillUnmount",value:function(){this.inputField.current.removeEventListener("input",this.onChange.bind(this),!1)}},{key:"shouldComponentUpdate",value:function(e,t){return this.state!==t}},{key:"onChange",value:function(){this.props.onChange&&this.props.onChange(this.inputField.current.value)}},{key:"render",value:function(){var e=this.props.value;return wp.element.createElement("div",{className:"bf-media-image-field"},wp.element.createElement("a",{href:"#",className:"bf-button bf-main-button bf-media-image-upload-btn"+("id"===this.props.dataType?"bf-media-type-id":""),"data-media-title":this.props.mediaTitle,"data-button-text":this.props.mediaButton,"data-size":this.props.size},wp.element.createElement("i",{className:"fa fa-upload"})," ",this.props.uploadLabel),wp.element.createElement("a",{href:"#",className:"bf-button bf-media-image-remove-btn",style:{display:e?"inline":"none"}},wp.element.createElement("i",{className:"fa fa-remove"})," ",this.props.removeLabel),wp.element.createElement("input",{type:this.props.showInput?"text":"hidden",className:"bf-media-image-input ltr",ref:this.inputField}),wp.element.createElement("div",{className:"bf-media-image-preview",style:{display:e?"block":"none"}},wp.element.createElement("img",{src:e})))}}]),t}(wp.element.Component);e.exports=a},function(e,t){function n(e){return wp.element.createElement("div",{className:"bf-slider-field"},wp.element.createElement("div",{className:"bf-slider-slider","data-dimension":e.dimension,"data-animation":e.animation,"data-step":e.step,"data-val":e.value,"data-min":e.min,"data-max":e.max}),wp.element.createElement("input",{type:"hidden",className:"bf-slider-input",value:"0"}))}e.exports=n},function(e,t){function n(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t<e.length;t++)n[t]=e[t];return n}return Array.from(e)}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!==typeof t&&"function"!==typeof t?e:t}function i(e,t){if("function"!==typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var a=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),l=function(e){function t(e){r(this,t);var n=o(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments)),i={};return e.value&&Array.isArray(e.value)&&(i=e.value),n.state={items:i},n.onChange=n.onChange.bind(n),n}return i(t,e),a(t,[{key:"componentDidMount",value:function(){document.dispatchEvent(new Event("bf-component-did-mount"))}},{key:"shouldComponentUpdate",value:function(e,t){return this.state!==t||this.props!==e}},{key:"collectValues",value:function(){var e={};return[].concat(n(ReactDOM.findDOMNode(this).getElementsByClassName("sorter-checkbox-value"))).forEach(function(t){e[t.name]=t.checked?"1":"0"}),e}},{key:"onChange",value:function(){var e=this.collectValues();e!==this.state.items&&this.setState({items:e}),this.props.onChange&&this.props.onChange(e)}},{key:"render",value:function(){var e=this,t=this.state.items,n=function(n){var r=n.cssClass?n.cssClass:"",o=t[n.id]?"":"checked-item";return wp.element.createElement("li",{id:"bf-sorter-group-item-"+e.props.id+"-"+n.id,key:n.id,className:r+" item-"+e.props.id+" "+o},wp.element.createElement("label",null,wp.element.createElement("input",{value:"1",type:"checkbox",defaultChecked:!!t[n.id],onChange:e.onChange,name:n.id,className:"sorter-checkbox-value"}),wp.element.createElement("p",{dangerouslySetInnerHTML:{__html:n.label}})))},r=[],o=this.props.items.filter(function(e){var n=-1!==t[e.id]&&-1!==e.cssClass.indexOf("active-item");return n&&r.push(e.id),n}),i=this.props.items.filter(function(e){var n=-1===t[e.id]&&-1!==e.cssClass.indexOf("active-item");return n&&r.push(e.id),n}),a=this.props.items.filter(function(e){return-1===r.indexOf(e.id)});return wp.element.createElement("div",{className:"bf-sorter-groups-container"},wp.element.createElement("ul",{id:"bf-sorter-group-"+this.props.id,className:"bf-sorter-list bf-sorter-"+this.props.id},o.map(n),wp.element.createElement("li",{key:"x2"},"activeAndDeSelectedItems"),i.map(n),a.map(n)))}}]),t}(wp.element.Component);e.exports=l},function(e,t){function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!==typeof t&&"function"!==typeof t?e:t}function o(e,t){if("function"!==typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var i=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),a=function(e){function t(){return n(this,t),r(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments))}return o(t,e),i(t,[{key:"componentDidMount",value:function(){document.dispatchEvent(new CustomEvent("bf-component-did-mount",{detail:ReactDOM.findDOMNode(this)}))}},{key:"render",value:function(){var e=""===this.props.label.trim()?" bf-no-heading":"",t=this.props.classes?this.props.classes:"";return wp.element.createElement("div",{className:"bf-section-container bf-gutenberg bf-clearfix "+t,"data-param-name":this.props.name,"data-param-settings":this.props.show_on?JSON.stringify(this.props.show_on):""},wp.element.createElement("div",{className:"bf-section bf-clearfix bf-section-"+this.props.type+e,"data-id":this.props.name},wp.element.createElement("div",{className:"bf-heading bf-clearfix bf-heading-"+this.props.type},wp.element.createElement("h3",null,wp.element.createElement("label",null,this.props.label))),wp.element.createElement("div",{className:"bf-controls bf-clearfix"},this.props.children),wp.element.createElement("div",{className:"bf-explain bf-nonrepeater-explain bf-clearfix",dangerouslySetInnerHTML:{__html:this.props.description}})))}}]),t}(wp.element.Component);e.exports=a},function(e,t){function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!==typeof t&&"function"!==typeof t?e:t}function o(e,t){if("function"!==typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var i=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),a=function(e){function t(){n(this,t);var e=r(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments));return e.inputField=React.createRef(),e}return o(t,e),i(t,[{key:"componentDidMount",value:function(){this.inputField.current.addEventListener("input",this.onChange.bind(this),!1)}},{key:"componentWillUnmount",value:function(){this.inputField.current.removeEventListener("input",this.onChange.bind(this),!1)}},{key:"onChange",value:function(){this.props.onChange&&this.props.onChange(parseInt(this.inputField.current.value))}},{key:"render",value:function(){var e=!!parseInt(this.props.value);return wp.element.createElement("div",{className:"bf-switch bf-clearfix"},wp.element.createElement("label",{className:"cb-enable"+(e?" selected":"")},wp.element.createElement("span",null,this.props.onLabel)),wp.element.createElement("label",{className:"cb-disable"+(e?"":" selected")},wp.element.createElement("span",null,this.props.offLabel)),wp.element.createElement("input",{type:"hidden",value:"0",className:"checkbox",ref:this.inputField}))}}]),t}(wp.element.Component);e.exports=a},function(e,t){function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!==typeof t&&"function"!==typeof t?e:t}function o(e,t){if("function"!==typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var i=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),a=function(e){function t(){n(this,t);var e=r(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments));return e.inputField=React.createRef(),e}return o(t,e),i(t,[{key:"componentDidMount",value:function(){this.inputField.current.addEventListener("input",this.onChange.bind(this),!1),document.dispatchEvent(new CustomEvent("bf-component-did-mount",{detail:ReactDOM.findDOMNode(this)}))}},{key:"componentWillUnmount",value:function(){this.inputField.current.removeEventListener("input",this.onChange.bind(this),!1)}},{key:"onChange",value:function(){this.props.onChange&&this.props.onChange(this.inputField.current.value)}},{key:"render",value:function(){return wp.element.createElement("div",{className:"bf-term-select-field"},wp.element.createElement("div",{className:"bf-field-term-select-wrapper bf-field-term-select-deferred loading","data-taxonomy":this.props.taxonomy},"Loading..."),wp.element.createElement("div",{className:"bf-field-term-select-help"},wp.element.createElement("label",null,this.props.labels.help),wp.element.createElement("div",{className:"bf-checkbox-multi-state disabled none-state"},wp.element.createElement("span",{"data-state":"none"})),wp.element.createElement("label",null,this.props.labels.not_selected),wp.element.createElement("div",{className:"bf-checkbox-multi-state disabled active-state"},wp.element.createElement("span",{className:"bf-checkbox-active"},wp.element.createElement("i",{className:"fa fa-check","aria-hidden":"true"}))),wp.element.createElement("label",null,this.props.labels.selected),wp.element.createElement("div",{className:"bf-checkbox-multi-state disabled deactivate-state"},wp.element.createElement("span",{className:"bf-checkbox-active"},wp.element.createElement("i",{className:"fa fa-times","aria-hidden":"true"}))),wp.element.createElement("label",null,this.props.labels.excluded)),wp.element.createElement("input",{type:"hidden",value:this.props.value,ref:this.inputField,className:"bf-term-select-value"}))}}]),t}(wp.element.Component);e.exports=a},function(e,t){function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!==typeof t&&"function"!==typeof t?e:t}function o(e,t){if("function"!==typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var i=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),a=function(e){function t(){return n(this,t),r(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments))}return o(t,e),i(t,[{key:"componentDidMount",value:function(){document.dispatchEvent(new CustomEvent("bf-edit-gutenberg-block",{detail:ReactDOM.findDOMNode(this)}))}},{key:"render",value:function(){return wp.element.createElement("div",{className:"bf-edit-gutenberg-block"},this.props.children)}}]),t}(wp.element.Component);e.exports=a},function(e,t){jQuery(document).on("change",".affect-block-align-on-change :input",function(){$("#editor").find(".editor-block-list__block.is-selected").attr("data-align",this.value)})}]);libs/better-framework/gutenberg/dev/dist/blocks.style.build.css000064400000000513151214002650020677 0ustar00/**
 * #.# Common SCSS
 *
 * Can include things like variables and mixins
 * that are used across the project.
*/
/**
 * #.# Styles
 *
 * CSS for both Frontend+Backend.
 */
.wp-block-cgb-block-dev {
  background: orangered;
  border: 0.2rem solid #292929;
  color: #292929;
  margin: 0 auto;
  max-width: 740px;
  padding: 2rem; }
libs/better-framework/gutenberg/class-bf-gutenberg-field.php000064400000002430151214002650020176 0ustar00<?php


abstract class BF_Gutenberg_Field_Transformer {

	public $wrap_section_container = true;

	/**
	 * @var array
	 */
	protected $field;


	/**
	 *
	 * @param int $iteration
	 *
	 * @return array
	 */
	abstract public function transform_field( $iteration );


	/**
	 * The component name.
	 *
	 * @return string
	 */
	abstract public function component();


	/**
	 * Return value data type.
	 *
	 * @return string
	 */
	public static function data_type() {

		return 'string';
	}

	/**
	 * @param array $field
	 */
	public function init( $field ) {

		$this->field = $field;
	}


	/**
	 * @param string $index
	 *
	 * @return mixed
	 */
	public function field( $index = '' ) {

		if ( $index ) {

			return isset( $this->field[ $index ] ) ? $this->field[ $index ] : null;
		}

		return $this->field;
	}


	/**
	 * @link https://wordpress.org/gutenberg/handbook/block-api/attributes/
	 *
	 * @return array
	 */
	public function the_attribute() {

		if ( $type = static::data_type() ) {

			$items = false; // it will fix Undefined index: items in wp-includes/rest-api.php:093

			return compact( 'type', 'items' );
		}

		return array();
	}


	/**
	 * @return array
	 */
	public function children_items_list() {

		return array();
	}


	public function children_item( $item ) {

		return $item;
	}
}
libs/better-framework/gutenberg/class-bf-html-to-react.php000064400000012345151214002650017621 0ustar00<?php


class BF_HTML_To_React {

	protected $index = 0;

	/**
	 * @param string $markup
	 *
	 * @return array
	 */
	public function transform( $markup ) {

		$prev = libxml_use_internal_errors( true );

		$doc = new DOMDocument( null, 'UTF-8' );

		$doc->loadXml( $markup, null );

		$container = array();

		$this->parse_html( $container, $doc->childNodes );

		libxml_use_internal_errors( $prev );

		return $container;
	}


	protected function parse_html( &$container, DOMNodeList $nodes ) {

		for ( $i = 0; $i < $nodes->length; $i ++ ) {

			$item = $nodes->item( $i );

			if ( ! isset( $item->tagName ) ) {

				if ( trim( $item->nodeValue ) === '' ) {
					continue;
				}
			}

			$children = array();
			$id       = 'tag_' . ++ $this->index;

			$args = $this->get_node_attributes( $item );

			if ( isset( $args['key'] ) ) {

				$key = $args['key'];

				unset( $args['key'] );

			} else {

				$key = $id;
			}

			if ( $this->node_only_contains_text( $item ) ) {
				$args['innerText'] = $item->nodeValue;
			}

			if ( isset( $item->tagName ) ) {

				$tag_name = $item->tagName;

			} else {

				$tag_name          = 'p';
				$args['innerText'] = $item->nodeValue;
			}

			$container[] = array(
				'id'        => $key,
				'key'       => $key,
				'args'      => $args,
				'children'  => $children,
				'component' => self::is_html_tag( $tag_name ) ? 'tag_' . $tag_name : $tag_name,
			);

			if ( ! empty( $item->childNodes->length ) && ! $this->node_only_contains_text( $item ) ) {

				end( $container );
				$key = key( $container );


				$this->parse_html( $container[ $key ]['children'], $item->childNodes );
			}
		}

	}


	protected function node_only_contains_text( $node ) {

		return isset( $node->childNodes ) && $node->childNodes->length === 1 && $this->is_text_node( $node->childNodes->item( 0 ) );
	}

	protected function is_text_node( $node ) {

		return $node instanceof DOMText;
	}

	/**
	 *
	 * Get attributes of the element
	 *
	 * @param DOMElement $node
	 *
	 * @since 1.0.0
	 *
	 * @return array key-value paired attributes
	 */
	public function get_node_attributes( $node ) {

		$attributes = array();

		if ( empty( $node->attributes ) ) {
			return $attributes;
		}

		foreach ( $node->attributes as $attribute ) {
			$attributes[ $attribute->nodeName ] = $attribute->nodeValue;
		}

		return $attributes;
	}

	/**
	 * @param string $tag
	 *
	 * @return bool
	 */
	public static function is_html_tag( $tag ) {

		static $tags = array(
			# HTML Tags
			'button'     => '',
			'a'          => '',
			'abbr'       => '',
			'acronym'    => '',
			'address'    => '',
			'applet'     => '',
			'area'       => '',
			'article'    => '',
			'aside'      => '',
			'audio'      => '',
			'b'          => '',
			'base'       => '',
			'basefont'   => '',
			'bdi'        => '',
			'bdo'        => '',
			'big'        => '',
			'blockquote' => '',
			'body'       => '',
			'br'         => '',
			'canvas'     => '',
			'caption'    => '',
			'center'     => '',
			'cite'       => '',
			'code'       => '',
			'col'        => '',
			'colgroup'   => '',
			'datalist'   => '',
			'dd'         => '',
			'del'        => '',
			'details'    => '',
			'dfn'        => '',
			'dialog'     => '',
			'dir'        => '',
			'div'        => '',
			'dl'         => '',
			'dt'         => '',
			'em'         => '',
			'embed'      => '',
			'fieldset'   => '',
			'figcaption' => '',
			'figure'     => '',
			'font'       => '',
			'footer'     => '',
			'form'       => '',
			'frame'      => '',
			'frameset'   => '',
			'h1'         => '',
			'h2'         => '',
			'h3'         => '',
			'h4'         => '',
			'h5'         => '',
			'h6'         => '',
			'head'       => '',
			'header'     => '',
			'hr'         => '',
			'html'       => '',
			'i'          => '',
			'iframe'     => '',
			'img'        => '',
			'input'      => '',
			'ins'        => '',
			'kbd'        => '',
			'keygen'     => '',
			'label'      => '',
			'legend'     => '',
			'li'         => '',
			'link'       => '',
			'main'       => '',
			'map'        => '',
			'mark'       => '',
			'menu'       => '',
			'menuitem'   => '',
			'meta'       => '',
			'meter'      => '',
			'nav'        => '',
			'noframes'   => '',
			'noscript'   => '',
			'object'     => '',
			'ol'         => '',
			'optgroup'   => '',
			'option'     => '',
			'output'     => '',
			'p'          => '',
			'param'      => '',
			'picture'    => '',
			'pre'        => '',
			'progress'   => '',
			'q'          => '',
			'rp'         => '',
			'rt'         => '',
			'ruby'       => '',
			's'          => '',
			'samp'       => '',
			'script'     => '',
			'section'    => '',
			'select'     => '',
			'small'      => '',
			'source'     => '',
			'span'       => '',
			'strike'     => '',
			'strong'     => '',
			'style'      => '',
			'sub'        => '',
			'summary'    => '',
			'sup'        => '',
			'table'      => '',
			'tbody'      => '',
			'td'         => '',
			'textarea'   => '',
			'tfoot'      => '',
			'th'         => '',
			'thead'      => '',
			'time'       => '',
			'title'      => '',
			'tr'         => '',
			'track'      => '',
			'tt'         => '',
			'u'          => '',
			'ul'         => '',
			'var'        => '',
			'video'      => '',
			'wbr'        => '',
		);

		return isset( $tags[ $tag ] );
	}
}
libs/better-framework/gutenberg/class-bf-gutenberg-shortcode-wrapper.php000064400000020233151214002650022564 0ustar00<?php


class BF_Gutenberg_Shortcode_Wrapper {


	/**
	 * Store list of blocks for gutenberg.
	 *
	 * @var array
	 *
	 * @since 3.9.0
	 */
	protected static $gutenberg_blocks = array();


	/**
	 * Cache storage for gutenberg_blocks_attributes method
	 *
	 * @var array
	 */
	protected static $blocks_attributes = array();


	/**
	 * Cache storage for gutenberg_blocks_attributes method
	 *
	 * @var array
	 */
	protected static $additional_attributes = array();


	/**
	 * @since 3.9.1
	 * @return self
	 */
	public static function instance() {

		$instance = new self();
		$instance->init();

		return $instance;
	}


	/**
	 * Initialize
	 */
	public function init() {

		///
		/// Gutenberg Compatibility
		///
		//
		//add_action( 'init', array( $this, 'register_gutenberg_blocks' ) );

		add_action( 'admin_footer', array( $this, 'enqueue_gutenberg_scripts' ) );

		add_filter( 'block_categories', array( $this, 'register_custom_categories' ) );

		add_action( 'better-framework/fields/term-select-items', array( $this, 'render_term_select_items' ) );

		$this->early_load_all_shortcodes();

	}


	/**
	 * Enqueue gutenberg static dependencies.
	 *
	 * @since 3.9.0
	 * @return bool true when enqueue fired.
	 */
	public function enqueue_gutenberg_scripts() {

		if ( ! $this->is_gutenberg_active() ) {
			return false;
		}

		if ( function_exists( 'is_gutenberg_page' ) && ! is_gutenberg_page() ) {
			return false;
		}

		bf_enqueue_script( 'bf-gutenberg' );

		bf_localize_script(
			'bf-gutenberg',
			'BF_Gutenberg',
			array(

				'blocks'          => self::$gutenberg_blocks,
				'liveEdit'        => self::gutenberg_live_edit_templates(),
				'blockFields'     => self::gutenberg_blocks_fields(),
				'stickyFields'    => self::gutenberg_sticky_fields(),
				'extraAttributes' => self::$additional_attributes,
			)
		);

		return true;
	}


	/**
	 * Is gutenberg active?
	 *
	 * @since 3.9.0
	 * @return bool
	 */
	public static function is_gutenberg_active() {

		if ( ! is_admin() ||
		     bf_is_doing_ajax( 'bf_ajax' ) ||
		     bf_is_block_render_request() ||
		     in_array( $GLOBALS['pagenow'], array( 'post.php', 'post-new.php' ) ) ) {

			if ( function_exists( 'disable_gutenberg' ) ) {

				return ! disable_gutenberg();
			}

			if ( class_exists( 'Classic_Editor' ) ) {

				return self::active_editor() === 'block';
			}

			return function_exists( 'register_block_type' );
		}

		return false;
	}


	/**
	 * Check default active editor in 'Classic Editor' plugin.
	 *
	 * @since 3.10.6
	 * @return string
	 */
	protected static function active_editor() {

		if ( ! class_exists( 'Classic_Editor' ) ) {
			return '';
		}

		$default_editor = get_option( 'classic-editor-replace' );

		if ( get_option( 'classic-editor-allow-users' ) === 'allow' ) {

			$user_options = get_user_option( 'classic-editor-settings' );

			if ( $user_options === 'block' || $user_options === 'classic' ) {

				$default_editor = $user_options;
			}
		}

		return $default_editor;
	}


	/**
	 * @param string $shortcode
	 * @param array  $settings
	 */
	public static function register( $shortcode, $settings = array() ) {

		$settings['id'] = $shortcode;

		if ( isset( $settings['category'] ) ) {
			$settings['category'] = self::sanitize_gutenberg_category( $settings['category'] );
		}

		self::$gutenberg_blocks[ $shortcode ] = $settings;

	}


	/**
	 * @return array
	 */
	public static function gutenberg_blocks_fields() {

		if ( ! class_exists( 'BF_Gutenberg_Fields_Transformer' ) ) {
			require BF_PATH . 'gutenberg/class-bf-gutenberg-fields-transformer.php';
		}

		return BF_Gutenberg_Fields_Transformer::instance()->prepare_blocks_fields(
			array_keys( self::$gutenberg_blocks )
		);
	}


	/**
	 * @return array
	 */
	public static function gutenberg_sticky_fields() {

		if ( ! class_exists( 'BF_Fields_To_Gutenberg' ) ) {
			require BF_PATH . 'gutenberg/class-bf-fields-to-gutenberg.php';
		}

		$fields = $stds = array();

		apply_filters_ref_array( 'better-framework/gutenberg/sticky-fields', array( &$fields ) );
		apply_filters_ref_array( 'better-framework/gutenberg/sticky-stds', array( &$stds ) );

		if ( empty( $fields ) ) {
			return array();
		}

		$converter = new BF_Fields_To_Gutenberg(
			$fields,
			$stds
		);

		self::$additional_attributes = array_merge(
			$converter->list_attributes(),
			self::$additional_attributes
		);

		return $converter->transform();
	}


	/**
	 * @return array
	 */
	public static function gutenberg_blocks_attributes() {

		if ( ! class_exists( 'BF_Gutenberg_Fields_Transformer' ) ) {
			require BF_PATH . 'gutenberg/class-bf-gutenberg-fields-transformer.php';
		}

		return BF_Gutenberg_Fields_Transformer::instance()->prepare_blocks_attributes(
			array_keys( self::$gutenberg_blocks )
		);
	}


	/**
	 * @return array
	 */
	public static function gutenberg_live_edit_templates() {

		if ( ! class_exists( 'BF_Gutenberg_Fields_Transformer' ) ) {
			require BF_PATH . 'gutenberg/class-bf-gutenberg-fields-transformer.php';
		}

		return BF_Gutenberg_Fields_Transformer::instance()->prepare_edit_templates(
			array_keys( self::$gutenberg_blocks )
		);
	}


	/**
	 * @param string $shortcode the shortcode unique ID
	 */
	public static function register_block( $shortcode ) {

		if ( ! function_exists('register_block_type') ) {
			return;
		}

		$block_id = str_replace( '_', '-', $shortcode );
		$block_id = strtolower( $block_id ); // uppercase letters are not allowed

		if ( ! self::$blocks_attributes ) {

			self::$blocks_attributes = self::gutenberg_blocks_attributes();
		}

		if ( ! class_exists( 'BF_Gutenberg_Shortcode_Render' ) ) {

			require BF_PATH . 'gutenberg/class-bf-gutenberg-shortcode-render.php';
		}

		$render_callback = "BF_Gutenberg_Shortcode_Render::$shortcode";
		$attributes      = isset( self::$blocks_attributes[ $shortcode ] ) ? self::$blocks_attributes[ $shortcode ] : array();
		//

		if ( ! empty( $attributes ) ) {
			$attributes['className'] = array( 'type' => 'string' );
		}

		$args = array_filter( compact( 'render_callback', 'attributes' ) );

		register_block_type( "better-studio/$block_id", apply_filters( 'better-framework/gutenberg/block-type-args', $args, $shortcode ) );
	}


	/**
	 * @param array $categories
	 *
	 * @return array
	 */
	public function register_custom_categories( $categories ) {

		$pushed_categories = array();

		foreach ( $categories as $category ) {
			$pushed_categories[] = $category['slug'];
		}

		foreach ( self::$gutenberg_blocks as $block ) {

			if ( empty( $block['category'] ) ) {
				continue;
			}

			$title = $block['category'];
			$slug  = self::sanitize_gutenberg_category( $title );

			if ( ! in_array( $slug, $pushed_categories ) ) {

				array_push( $categories, compact( 'slug', 'title' ) );
				$pushed_categories[] = $slug;
			}
		}

		// Register default category

		if ( ! in_array( 'betterstudio', $pushed_categories ) ) {

			array_push( $categories, array(
				'slug'  => 'betterstudio',
				'title' => __( 'BetterStudio', 'better-studio' ),
			) );
		}

		return $categories;
	}


	/**
	 * @param string $category
	 *
	 * @return string
	 */
	public static function sanitize_gutenberg_category( $category ) {

		$slug = sanitize_title_with_dashes( trim( $category ) );

		if ( $slug === 'embeds' ) {

			return 'embed';
		}

		return $slug;
	}


	/**
	 *
	 */
	public function early_load_all_shortcodes() {

		if ( bf_is_block_render_request() ) {

			BF_Shortcodes_Manager::init_shortcodes( true );
		}
	}


	public function render_term_select_items( $items ) {

		if ( ! class_exists( 'BF_Term_Select' ) ) {
			require BF_PATH . '/core/field-generator/class-bf-term-select.php';
		}

		$results = array();

		foreach ( $items as $id => $item ) {

			if ( ! isset( $item['taxonomy'] ) ) {
				continue;
			}

			ob_start();

			wp_list_categories( array(
				'style'          => 'list',
				'title_li'       => false,
				'taxonomy'       => $item['taxonomy'],
				'walker'         => new BF_Term_Select,
				'selected_terms' => isset( $item['value'] ) ? $item['value'] : '',
				'input_name'     => isset( $item['input_name'] ) ? $item['input_name'] : 'bf-term-select',
				'hide_empty'     => false,
			) );

			$results[ $id ] = ob_get_contents();

			ob_end_clean();
		}

		wp_send_json_success( $results );
	}


	public function gutenberg_additional_attributes() {


	}
}
libs/better-framework/gutenberg/index.php000064400000000050151214002650014546 0ustar00<?php

// Let's show them we are better
libs/better-framework/gutenberg/class-bf-gutenberg-fields-transformer.php000064400000004662151214002650022732 0ustar00<?php


class BF_Gutenberg_Fields_Transformer {

	public static function instance() {

		$instance = new self();
		$instance->init();

		return $instance;
	}


	/**
	 *
	 */
	public function init() {

		if ( is_admin() ) {
			add_action( 'better-framework/shortcodes/gutenberg-fields', array( $this, 'ajax_prepare_fields' ) );
		}
	}


	public function ajax_prepare_fields( $blocks ) {

		wp_send_json_success( $this->prepare_blocks_fields( $blocks ) );
	}


	/**
	 * @param array $blocks
	 *
	 * @return array
	 */
	public function prepare_blocks_fields( $blocks ) {

		$results = array();

		if ( ! class_exists( 'BF_Fields_To_Gutenberg' ) ) {
			require BF_PATH . 'gutenberg/class-bf-fields-to-gutenberg.php';
		}

		foreach ( $blocks as $block ) {

			if ( ! $shortcode = BF_Shortcodes_Manager::factory( $block, array(), true ) ) {
				continue;
			}

			if ( ! $block_fields = $shortcode->get_fields() ) {
				continue;
			}
			$converter = new BF_Fields_To_Gutenberg(
				$block_fields,
				$shortcode->defaults
			);

			$results[ $block ] = $converter->transform();
		}

		return $results;
	}


	/**
	 * @param array $blocks
	 *
	 * @return array
	 */
	public function prepare_blocks_attributes( $blocks ) {

		$results = array();

		if ( ! class_exists( 'BF_Fields_To_Gutenberg' ) ) {
			require BF_PATH . 'gutenberg/class-bf-fields-to-gutenberg.php';
		}

		foreach ( $blocks as $block ) {

			if ( ! $shortcode = BF_Shortcodes_Manager::factory( $block, array(), true ) ) {
				continue;
			}

			if ( ! $block_fields = $shortcode->get_fields() ) {
				continue;
			}

			$converter = new BF_Fields_To_Gutenberg(
				$block_fields
			);
			$fields    = $converter->list_attributes();

			$results[ $block ] = $fields;
		}

		return $results;
	}

	/**
	 * @param array $blocks
	 *
	 * @return array
	 */
	public function prepare_edit_templates( $blocks ) {

		if ( ! class_exists( 'BF_HTML_To_React' ) ) {
			require BF_PATH . 'gutenberg/class-bf-html-to-react.php';
		}

		$converter = new BF_HTML_To_React();

		$results   = array();
		$templates = array();

		foreach ( $blocks as $block ) {

			if ( ! $shortcode = BF_Shortcodes_Manager::factory( $block, array(), true ) ) {
				continue;
			}

			if ( $attrs = $shortcode->gutenberg_attributes() ) {
				$results[ $block ]['attributes'] = $attrs;
			}

			if ( $template = $shortcode->gutenberg_live_edit() ) {
				$results[ $block ]['template'] = $converter->transform( $template );
			}
		}

		return $results;
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-bf-editor.php000064400000001663151214002650022600 0ustar00<?php


class BF_Gutenberg_BF_Editor extends BF_Gutenberg_Field_Transformer {


	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		return array(
			'label'    => isset( $this->field['name'] ) ? $this->field['name'] : '',
			'type'     => isset( $this->field['type'] ) ? $this->field['type'] : '',
			'lang'     => isset( $this->field['lang'] ) ? $this->field['lang'] : '',
			'desc'     => isset( $this->field['desc'] ) ? $this->field['desc'] : '',
			'maxLines' => isset( $this->field['max-lines'] ) ? $this->field['max-lines'] : '',
			'minLines' => isset( $this->field['min-lines'] ) ? $this->field['min-lines'] : '',
		);
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'BF_Editor';
	}


	/**
	 * Return value data type.
	 *
	 * @since 3.9.0
	 * @return string
	 */
	public static function data_type() {

		return 'string';
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-textarea-control.php000064400000001010151214002650024202 0ustar00<?php


class BF_Gutenberg_Textarea_Control extends BF_Gutenberg_Field_Transformer {


	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		return array(
			'label' => $this->field['name'],
		);
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'TextareaControl';
	}


	/**
	 * Return value data type.
	 *
	 * @since 3.9.0
	 * @return string
	 */
	public static function data_type() {

		return 'string';
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-bf-repeater.php000064400000002550151214002650023115 0ustar00<?php


class BF_Gutenberg_BF_Repeater extends BF_Gutenberg_Field_Transformer {


	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		$default_params = wp_parse_args(
			isset( $this->field['default'][0] ) ? $this->field['default'][0] : array(),
			array_fill_keys( array_keys( $this->children_items_list() ), '' )
		);

		return array(
			'defaultParams' => $default_params,
			'label'         => isset( $this->field['name'] ) ? $this->field['name'] : '',
			'addLabel'      => isset( $this->field['add_label'] ) ? $this->field['add_label'] : __( 'Add', 'better-studio' ),
			'deleteLabel'   => isset( $this->field['delete_label'] ) ? $this->field['delete_label'] : __( 'Delete', 'better-studio' ),
			'itemTitle'     => isset( $this->field['item_title'] ) ? $this->field['item_title'] : __( 'Item', 'better-studio' ),
		);
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'BF_Repeater';
	}


	/**
	 * Return value data type.
	 *
	 * @since 3.9.0
	 * @return string
	 */
	public static function data_type() {

		return 'array';
	}


	public function children_items_list() {

		return isset( $this->field['options'] ) ? $this->field['options'] : array();
	}


	public function children_item( $item ) {

		$item['repeater_item'] = $this->field['id'];

		return $item;
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-bf-hr.php000064400000000706151214002650021720 0ustar00<?php


class BF_Gutenberg_BF_Hr extends BF_Gutenberg_Field_Transformer {


	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		return array();
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'BF_Hr';
	}


	/**
	 * Return value data type.
	 *
	 * @since 3.9.0
	 * @return string
	 */
	public static function data_type() {

		return '';
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-bf-icon-select.php000064400000001037151214002650023512 0ustar00<?php


class BF_Gutenberg_BF_Icon_Select extends BF_Gutenberg_Field_Transformer {


	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		$label = isset( $this->field['name'] ) ? $this->field['name'] : '';

		return compact( 'label' );
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'BF_Icon_Select';
	}


	/**
	 * Return value data type.
	 *
	 * @return string
	 */
	public static function data_type() {

		return 'object';
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-bf-select-popup.php000064400000006061151214002650023727 0ustar00<?php


class BF_Gutenberg_BF_Select_Popup extends BF_Gutenberg_Field_Transformer {


	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		return array(
			'label' => isset( $this->field['name'] ) ? $this->field['name'] : '',
			'desc'  => isset( $this->field['desc'] ) ? $this->field['desc'] : '',
			'data'  => $this->prepare_public_data(),
		);
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'BF_Select_Popup';
	}


	/**
	 * Return value data type.
	 *
	 * @since 3.9.0
	 * @return string
	 */
	public static function data_type() {

		return 'string';
	}


	/**
	 * @return array
	 */
	protected function prepare_public_data() {

		if ( ! function_exists( 'bf_field_extra_options' ) ) {

			require BF_PATH . 'core/field-generator/functions.php';
		}

		$this->prepare_deferred_options();

		$public_data = wp_array_slice_assoc( $this->field, bf_field_extra_options( 'select_popup' ) );

		if ( ! isset( $this->field['options'] ) ) {
			return $public_data;
		}

		foreach ( (array) $this->field['options'] as $key => $option ) {
			if ( empty( $option['info'] ) ) {
				$option['info'] = array();
			}
			$option['info']['img']   = $option['img'];
			$option['info']['label'] = $option['label'];

			if ( isset( $option['badges'] ) ) {
				$option['info']['badges'] = $option['badges'];
			}
			if ( isset( $option['class'] ) ) {
				$option['info']['class'] = $option['class'];
			}
			if ( ! empty( $option['current_img'] ) ) {
				$option['info']['current_img'] = $option['current_img'];
			}

			$public_data['options'][ $key ] = bf_map_deep( $option['info'], 'sanitize_text_field' );
		}

		if ( ! isset( $public_data['texts']['box_pre_title'] ) ) {
			$public_data['texts']['box_pre_title'] = __( 'Active item', 'better-studio' );
		}

		if ( ! isset( $public_data['texts']['box_button'] ) ) {
			$public_data['texts']['box_button'] = __( 'Change', 'better-studio' );
		}

		if ( ! isset( $public_data['texts']['default_text'] ) ) {
			$public_data['texts']['default_text'] = __( 'chose one...', 'better-studio' );
		}

		return $public_data;
	}


	/**
	 * @return mixed
	 */
	protected function prepare_deferred_options() {

		if ( isset( $this->field['options'] ) ) {
			return;
		}

		if ( ! isset( $this->field['deferred-options'] ) ) {
			return;
		}

		$this->field['options'] = array();

		if ( is_string( $this->field['deferred-options'] ) && is_callable( $this->field['deferred-options'] ) ) {

			$this->field['options'] = call_user_func( $this->field['deferred-options'] );

		} elseif ( is_array( $this->field['deferred-options'] ) && ! empty( $this->field['deferred-options']['callback'] ) && is_callable( $this->field['deferred-options']['callback'] ) ) {

			if ( isset( $this->field['deferred-options']['args'] ) ) {

				$this->field['options'] = call_user_func_array( $this->field['deferred-options']['callback'], $this->field['deferred-options']['args'] );

			} else {

				$this->field['options'] = call_user_func( $this->field['deferred-options']['callback'] );
			}
		}
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-date-time-picker.php000064400000001061151214002650024041 0ustar00<?php


class BF_Gutenberg_Date_Time_Picker extends BF_Gutenberg_Field_Transformer {

	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		$label = isset( $this->field['name'] ) ? $this->field['name'] : '';

		return compact( 'label' );
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'DateTimePicker';
	}


	/**
	 * Return value data type.
	 *
	 * @since 3.9.0
	 * @return string
	 */
	public static function data_type() {

		return 'string';
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-color-palette.php000064400000001054151214002650023471 0ustar00<?php


class BF_Gutenberg_Color_Palette extends BF_Gutenberg_Field_Transformer {

	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		$label = isset( $this->field['name'] ) ? $this->field['name'] : '';

		return compact( 'label' );
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'ColorPalette';
	}


	/**
	 * Return value data type.
	 *
	 * @since 3.9.0
	 * @return string
	 */
	public static function data_type() {

		return 'string';
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-bf-media-image.php000064400000003027151214002650023445 0ustar00<?php


class BF_Gutenberg_BF_Media_Image extends BF_Gutenberg_Field_Transformer {


	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		return array(
			'label'       => isset( $this->field['name'] ) ? $this->field['name'] : '',
			'type'        => isset( $this->field['type'] ) ? $this->field['type'] : '',
			'desc'        => isset( $this->field['desc'] ) ? $this->field['desc'] : '',
			'uploadLabel' => isset( $this->field['upload_label'] ) ? $this->field['upload_label'] : '',
			'mediaTitle'  => isset( $this->field['media_title'] ) ? $this->field['media_title'] : '',
			'mediaButton' => isset( $this->field['media_button'] ) ? $this->field['media_button'] : '',
			'uploadLabel' => isset( $this->field['upload_label'] ) ? $this->field['upload_label'] : '',
			'removeLabel' => isset( $this->field['remove_label'] ) ? $this->field['remove_label'] : '',
			'inputClass'  => isset( $this->field['input_class'] ) ? $this->field['input_class'] : '',
			'dataType'    => isset( $this->field['data-type'] ) ? $this->field['data-type'] : '',
			'showInput'   => isset( $this->field['show_input'] ) ? $this->field['show_input'] : '',
			'previewSize' => isset( $this->field['preview-size'] ) ? $this->field['preview-size'] : '',
		);
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'BF_Media_Image';
	}


	/**
	 * Return value data type.
	 *
	 * @since 3.9.0
	 * @return string
	 */
	public static function data_type() {

		return 'string';
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-range-control.php000064400000001571151214002650023475 0ustar00<?php


class BF_Gutenberg_Range_Control extends BF_Gutenberg_Field_Transformer {

	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		$field = array(
			'label' => $this->field['name'],
		);

		if ( isset( $this->field['desc'] ) ) {
			$field['desc'] = $this->field['desc'];
		}

		if ( isset( $this->field['min'] ) ) {
			$field['min'] = $this->field['min'];
		}

		if ( isset( $this->field['max'] ) ) {
			$field['max'] = $this->field['max'];
		}

		if ( isset( $this->field['std'] ) ) {
			$field['initialPosition'] = $this->field['std'];
		}


		return $field;
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'RangeControl';
	}


	/**
	 * Return value data type.
	 *
	 * @since 3.9.0
	 * @return string
	 */
	public static function data_type() {

		return 'string';
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-bf-heading.php000064400000001161151214002650022702 0ustar00<?php


class BF_Gutenberg_BF_Heading extends BF_Gutenberg_Field_Transformer {


	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		$title  = $this->field['name'];
		$layout = '';

		if ( isset( $this->field['layout'] ) ) {
			$layout = $this->field['layout'];
		}

		return compact( 'title', 'layout' );
	}


	/**
	 * The component name.
	 *
	 * @return string
	 *
	 */
	public function component() {

		return 'BF_Heading';
	}


	/**
	 * Return value data type.
	 *
	 * @since 3.9.0
	 * @return string
	 */
	public static function data_type() {

		return '';
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-bf-ajax-action.php000064400000001634151214002650023506 0ustar00<?php


class BF_Gutenberg_BF_Ajax_Action extends BF_Gutenberg_Field_Transformer {


	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		return array(
			'label'      => isset( $this->field['name'] ) ? $this->field['name'] : '',
			'buttonName' => isset( $this->field['button-name'] ) ? $this->field['button-name'] : '',
			'callback'   => isset( $this->field['callback'] ) ? $this->field['callback'] : '',
			'confirm'    => isset( $this->field['confirm'] ) ? $this->field['confirm'] : '',
			'token'      => isset( $this->field['callback'] ) ?
				Better_Framework::callback_token( $this->field['callback'] ) : '',
		);
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'BF_Ajax_Action';
	}


	/**
	 * Return value data type.
	 *
	 * @return string
	 */
	public static function data_type() {

		return '';
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-bf-image-radio.php000064400000003307151214002650023465 0ustar00<?php


class BF_Gutenberg_BF_Image_Radio extends BF_Gutenberg_Field_Transformer {


	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		return array(
			'label'   => isset( $this->field['name'] ) ? $this->field['name'] : '',
			'desc'    => isset( $this->field['desc'] ) ? $this->field['desc'] : '',
			'options' => $this->the_options(),
		);
	}


	/**
	 * @return array
	 */
	protected function the_options() {

		$options = array();

		if ( isset( $this->field['options'] ) ) {

			$options = $this->field['options'];

		} elseif ( isset( $this->field['deferred-options'] ) ) {

			if ( is_callable( $this->field['deferred-options'] ) ) {

				$options = call_user_func( $this->field['deferred-options'] );

			} elseif ( isset( $this->field['deferred-options']['callback'] ) ) {

				if ( isset( $this->field['deferred-options']['args'] ) ) {

					$options = call_user_func_array( $this->field['deferred-options']['callback'], $this->field['deferred-options']['args'] );

				} else {

					$options = call_user_func( $this->field['deferred-options']['callback'] );
				}
			}
		}

		return $this->reformat_options( $options );
	}


	/**
	 * @param array $options
	 *
	 * @return array
	 */
	public function reformat_options( &$options ) {

		$reformatted = array();

		foreach ( $options as $id => $option ) {

			$option['id'] = $id;

			array_push( $reformatted, $option );
		}

		return $reformatted;
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'BF_Image_Radio';
	}


	/**
	 * Return value data type.
	 *
	 * @since 3.9.0
	 * @return string
	 */
	public static function data_type() {

		return 'string';
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-bf-code.php000064400000002107151214002650022216 0ustar00<?php


class BF_Gutenberg_BF_Code extends BF_Gutenberg_Field_Transformer {


	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		return array(
			'label'             => isset( $this->field['name'] ) ? $this->field['name'] : '',
			'lang'              => isset( $this->field['lang'] ) ? $this->field['lang'] : '',
			'desc'              => isset( $this->field['desc'] ) ? $this->field['desc'] : '',
			'placeholder'       => isset( $this->field['placeholder'] ) ? $this->field['placeholder'] : '',
			'lineNumbers'       => empty( $this->field['line_numbers'] ) ? 'disable' : 'enable',
			'autoCloseBrackets' => empty( $this->field['auto_close_brackets'] ) ? 'disable' : 'enable',
			'autoCloseTags'     => empty( $this->field['auto_close_tags'] ) ? 'disable' : 'enable',
		);
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'BF_Code';
	}


	/**
	 * Return value data type.
	 *
	 * @since 3.9.0
	 * @return string
	 */
	public static function data_type() {

		return 'string';
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-bf-background-image.php000064400000002253151214002650024505 0ustar00<?php


class BF_Gutenberg_BF_Background_Image extends BF_Gutenberg_Field_Transformer {


	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		return array(
			'label'       => isset( $this->field['name'] ) ? $this->field['name'] : '',
			'desc'        => isset( $this->field['desc'] ) ? $this->field['desc'] : '',
			'uploadLabel' => isset( $this->field['upload_label'] ) ? $this->field['upload_label'] : '',
			'mediaTitle'  => isset( $this->field['media_title'] ) ? $this->field['media_title'] : '',
			'buttonText'  => isset( $this->field['button_text'] ) ? $this->field['button_text'] : '',
			'uploadLabel' => isset( $this->field['upload_label'] ) ? $this->field['upload_label'] : '',
			'removeLabel' => isset( $this->field['remove_label'] ) ? $this->field['remove_label'] : '',
			'inputClass'  => isset( $this->field['input_class'] ) ? $this->field['input_class'] : '',
		);
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'BF_Background_Image';
	}


	/**
	 * Return value data type.
	 *
	 * @return string
	 */
	public static function data_type() {

		return 'array';
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-radio-control.php000064400000001231151214002650023470 0ustar00<?php


class BF_Gutenberg_Radio_Control extends BF_Gutenberg_Field_Transformer {


	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		$options = array();

		foreach ( $this->field['options'] as $value => $label ) {

			$options[] = compact( 'value', 'label' );
		}
		$label = $this->field['name'];

		return compact( 'label', 'options' );
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'RadioControl';
	}


	/**
	 * Return value data type.
	 *
	 * @since 3.9.0
	 * @return string
	 */
	public static function data_type() {

		return 'string';
	}

}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-panel-body.php000064400000001527151214002650022756 0ustar00<?php


class BF_Gutenberg_Panel_Body extends BF_Gutenberg_Field_Transformer {

	/**
	 * @var bool
	 */
	public $wrap_section_container = false;

	public $first_item = true;


	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		return array(
			'title'       => $this->field['name'],
			'initialOpen' => ( isset( $this->field['state'] ) && 'open' === $this->field['state'] ) || $iteration === 1,
		);
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'PanelBody';
	}


	/**
	 * Return value data type.
	 *
	 * @since 3.9.0
	 * @return string
	 */
	public static function data_type() {

		return '';
	}


	public function is_first_panel() {

		if ( $this->first_item ) {

			$this->first_item = false;

			return true;
		}

		return false;
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-bf-term-select.php000064400000001751151214002650023534 0ustar00<?php


class BF_Gutenberg_BF_Term_Select extends BF_Gutenberg_Field_Transformer {


	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		return array(
			'label'  => isset( $this->field['name'] ) ? $this->field['name'] : '',
			'desc'   => isset( $this->field['desc'] ) ? $this->field['desc'] : '',
			'labels' => array(
				'help'         => __( 'Help: Click on check box to', 'better-studio' ),
				'not_selected' => __( 'Not Selected', 'better-studio' ),
				'selected'     => __( 'Selected', 'better-studio' ),
				'excluded'     => __( 'Excluded', 'better-studio' ),
			),

			'taxonomy' => isset( $this->field['taxonomy'] ) ? $this->field['taxonomy'] : 'category',
		);
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'BF_Term_Select';
	}


	/**
	 * Return value data type.
	 *
	 * @since 3.9.0
	 * @return string
	 */
	public static function data_type() {

		return 'string';
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-bf-sorter-checkbox.php000064400000004030151214002650024403 0ustar00<?php


class BF_Gutenberg_BF_Sorter_Checkbox extends BF_Gutenberg_Field_Transformer {


	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		return array(
			'label' => isset( $this->field['name'] ) ? $this->field['name'] : '',
			'desc'  => isset( $this->field['desc'] ) ? $this->field['desc'] : '',
			'items' => $this->listItems(),
		);
	}


	/**
	 * @return array
	 */
	public function listItems() {

		$this->prepare_deferred_options();

		$items = array();

		if ( empty( $this->field['options'] ) ) {

			return $items;
		}

		foreach ( $this->field['options'] as $item_id => $item ) {

			$item['id']       = $item_id;
			$item['cssClass'] = isset( $item['css-class'] ) ? $item['css-class'] : '';

			unset( $item['css-class'] );

			array_push( $items, $item );
		}

		return $items;
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'BF_Sorter_Checkbox';
	}


	/**
	 * Return value data type.
	 *
	 * @since 3.9.0
	 * @return string
	 */
	public static function data_type() {

		return 'object';
	}


	/**
	 * @return mixed
	 */
	protected function prepare_deferred_options() {

		if ( isset( $this->field['options'] ) ) {
			return;
		}

		if ( ! isset( $this->field['deferred-options'] ) ) {
			return;
		}

		$this->field['options'] = array();

		if ( is_string( $this->field['deferred-options'] ) && is_callable( $this->field['deferred-options'] ) ) {

			$this->field['options'] = call_user_func( $this->field['deferred-options'] );

		} elseif ( is_array( $this->field['deferred-options'] ) && ! empty( $this->field['deferred-options']['callback'] ) && is_callable( $this->field['deferred-options']['callback'] ) ) {

			if ( isset( $this->field['deferred-options']['args'] ) ) {

				$this->field['options'] = call_user_func_array( $this->field['deferred-options']['callback'], $this->field['deferred-options']['args'] );

			} else {

				$this->field['options'] = call_user_func( $this->field['deferred-options']['callback'] );
			}
		}
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-tree-select.php000064400000005111151214002650023131 0ustar00<?php


class BF_Gutenberg_Tree_Select extends BF_Gutenberg_Field_Transformer {


	/**
	 * @param int $iteration
	 *
	 * @return array
	 */
	public function transform_field( $iteration ) {

		$label = $this->field['name'];
		$tree  = array();

		// set options from deferred callback

		if ( isset( $this->field['deferred-options'] ) ) {

			if ( is_callable( $this->field['deferred-options'] ) ) {
				$this->field['options'] = call_user_func( $this->field['deferred-options'] );
			} elseif ( is_array( $this->field['deferred-options'] ) && ! empty( $this->field['deferred-options']['callback'] ) && is_callable( $this->field['deferred-options']['callback'] ) ) {

				if ( isset( $this->field['deferred-options']['args'] ) ) {
					$this->field['options'] = call_user_func_array( $this->field['deferred-options']['callback'], $this->field['deferred-options']['args'] );
				} else {
					$this->field['options'] = call_user_func( $this->field['deferred-options']['callback'] );
				}
			}

		}

		if ( ! isset( $this->field['options'] ) ) {

			return array();
		}

		foreach ( $this->field['options'] as $id => $name ) {

			if ( is_array( $name ) ) {

				$tree[] = $this->parse_grouped_field( $name, $id );

			} else {

				$tree[] = compact( 'id', 'name' );
			}
		}

		return compact( 'label', 'tree' );
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'TreeSelect';
	}


	/**
	 * Return value data type.
	 *
	 * @since 3.9.0
	 * @return string
	 */
	public static function data_type() {

		return 'string';
	}


	/**
	 * @link https://wordpress.org/gutenberg/handbook/block-api/attributes/
	 *
	 * @return array
	 */
	public function the_attribute() {

		$enum = array();

		if ( isset( $this->field['options'] ) ) {
			$enum = array_keys( $this->field['options'] );

			foreach ( $this->field['options'] as $key => $option ) {

				$enum[] = $key;

				if ( ! empty( $option['options'] ) && is_array( $option['options'] ) ) {

					$enum = array_merge( $enum, array_keys( $option['options'] ) );
				}
			}

			$enum = array_values( array_unique( $enum ) );
		}

		return array_merge( parent::the_attribute(), compact( 'enum' ) );
	}


	/**
	 * @param $option
	 * @param $id
	 *
	 * @return array
	 */
	protected function parse_grouped_field( $option, $id ) {

		$children = array();

		if ( ! empty( $option['options'] ) ) {

			foreach ( $option['options'] as $child_id => $child_name ) {

				$children[] = array(
					'id'   => $child_id,
					'name' => $child_name,
				);
			}
		}

		$name = $option['label'];

		return compact( 'id', 'name', 'children' );
	}
}
libs/better-framework/gutenberg/adapters/index.php000064400000000050151214002650016351 0ustar00<?php

// Let's show them we are better
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-bf-image-preview.php000064400000001441151214002650024045 0ustar00<?php


class BF_Gutenberg_BF_Image_Preview extends BF_Gutenberg_Field_Transformer {


	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {


		$urls = array();

		if ( empty( $this->field['value'] ) && isset( $this->field['std'] ) ) {

			$urls = (array) $this->field['std'];

		} elseif ( isset( $this->field['value'] ) ) {

			$urls = (array) $this->field['value'];
		}

		$align = isset( $this->field['align'] ) ? $this->field['align'] : '';

		return compact( 'urls', 'align' );
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'BF_Image_Preview';
	}


	/**
	 * Return value data type.
	 *
	 * @since 3.9.0
	 * @return string
	 */
	public static function data_type() {

		return '';
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-bf-switch.php000064400000001403151214002650022603 0ustar00<?php


class BF_Gutenberg_BF_Switch extends BF_Gutenberg_Field_Transformer {

	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		return array(
			'label'    => isset( $this->field['name'] ) ? $this->field['name'] : '',
			'onLabel'  => ! empty( $this->field['on-label'] ) ? $this->field['on-label'] : __( 'On', 'better-studio' ),
			'offLabel' => ! empty( $this->field['off-label'] ) ? $this->field['off-label'] : __( 'Off', 'better-studio' ),
		);
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'BF_Switch';
	}


	/**
	 * Return value data type.
	 *
	 * @since 3.9.0
	 * @return string
	 */
	public static function data_type() {

		return 'string';
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-bf-ajax-select.php000064400000001222151214002650023501 0ustar00<?php


class BF_Gutenberg_BF_Ajax_Select extends BF_Gutenberg_Field_Transformer {


	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		unset( $this->field['get_name'] );
		unset( $this->field['type'] );

		$this->field['label'] = isset( $this->field['name'] ) ? $this->field['name'] : '';

		unset( $this->field['name'] );


		return $this->field;
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'BF_Ajax_Select';
	}


	/**
	 * Return value data type.
	 *
	 * @return string
	 */
	public static function data_type() {

		return 'string';
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-text-control.php000064400000001025151214002650023357 0ustar00<?php


class BF_Gutenberg_Text_Control extends BF_Gutenberg_Field_Transformer {

	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		return array(
			'type'  => 'text',
			'label' => $this->field['name'],
		);
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'TextControl';
	}


	/**
	 * Return value data type.
	 *
	 * @since 3.9.0
	 * @return string
	 */
	public static function data_type() {

		return 'string';
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-bf-image-select.php000064400000003311151214002650023641 0ustar00<?php


class BF_Gutenberg_BF_Image_Select extends BF_Gutenberg_Field_Transformer {


	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		return array(
			'label'   => isset( $this->field['name'] ) ? $this->field['name'] : '',
			'desc'    => isset( $this->field['desc'] ) ? $this->field['desc'] : '',
			'options' => $this->the_options(),
		);
	}


	/**
	 * @return array
	 */
	protected function the_options() {

		$options = array();

		if ( isset( $this->field['options'] ) ) {

			$options = $this->field['options'];

		} elseif ( isset( $this->field['deferred-options'] ) ) {

			if ( is_callable( $this->field['deferred-options'] ) ) {

				$options = call_user_func( $this->field['deferred-options'] );

			} elseif ( isset( $this->field['deferred-options']['callback'] ) ) {

				if ( isset( $this->field['deferred-options']['args'] ) ) {

					$options = call_user_func_array( $this->field['deferred-options']['callback'], $this->field['deferred-options']['args'] );

				} else {

					$options = call_user_func( $this->field['deferred-options']['callback'] );
				}
			}
		}

		return $this->reformat_options( $options );
	}


	/**
	 * @param array $options
	 *
	 * @return array
	 */
	public function reformat_options( &$options ) {

		$reformatted = array();

		foreach ( $options as $id => $option ) {

			$option['id'] = $id;

			array_push( $reformatted, $option );
		}

		return $reformatted;
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'BF_Image_Select';
	}


	/**
	 * Return value data type.
	 *
	 * @since 3.9.0
	 * @return string
	 */
	public static function data_type() {

		return 'string';
	}
}
libs/better-framework/gutenberg/adapters/class-bf-gutenberg-bf-info.php000064400000001333151214002650022237 0ustar00<?php


class BF_Gutenberg_BF_Info extends BF_Gutenberg_Field_Transformer {

	/**
	 * @param int $iteration
	 *
	 * @return mixed
	 */
	public function transform_field( $iteration ) {

		$label = $this->field['name'];
		$note  = $this->field['std'];

		if ( isset( $this->field['state'] ) ) {
			$state = $this->field['state'];
		}
		if ( isset( $this->field['info-type'] ) ) {
			$level = $this->field['info-type'];
		}

		return compact( 'label', 'note', 'state', 'level' );
	}


	/**
	 * The component name.
	 *
	 * @return string
	 */
	public function component() {

		return 'BF_Info';
	}


	/**
	 * Return value data type.
	 *
	 * @since 3.9.0
	 * @return string
	 */
	public static function data_type() {

		return '';
	}
}
libs/better-framework/gutenberg/class-bf-fields-to-gutenberg.php000064400000027400151214002650021005 0ustar00<?php


class BF_Fields_To_Gutenberg {

	/**
	 * @var array
	 */
	protected $fields = array();

	/**
	 * @var array
	 */
	protected $stds = array();


	/**
	 * BF_Fields_To_Gutenberg constructor.
	 *
	 * @param array $fields
	 * @param array $stds
	 *
	 * @since 3.9.0
	 */
	public function __construct( array $fields = array(), $stds = array() ) {

		$this->load_fields( $fields );
		$this->load_stds( $stds );
	}


	/**
	 * Set standard BF fields array.
	 *
	 * @param array $fields
	 *
	 * @since 3.9.0
	 */
	public function load_fields( array $fields ) {

		$this->fields = $fields;
	}


	/**
	 * Set fields default std value.
	 *
	 * @param array $stds
	 *
	 * @since 3.9.0
	 */
	public function load_stds( array $stds ) {

		$this->stds = $stds;
	}


	/**
	 * Get BF fields array.
	 *
	 * @since 3.9.0
	 * @return array
	 */
	public function fields() {

		return $this->fields;
	}


	/**
	 * Transform fields to gutenberg format.
	 *
	 * @since 3.9.0
	 *
	 * @param BF_Gutenberg_Field_Transformer|null $parent_field parent object if exists
	 *
	 * @return array
	 */
	public function transform( BF_Gutenberg_Field_Transformer $parent_field = null ) {

		$container = array();
		$results   = &$container;

		$tab_started = false;
		$iteration   = 0;

		foreach ( $this->fields as $field ) {

			if ( empty( $field['type'] ) ) {

				continue;
			}

			if ( ! isset( $field['std'] ) && isset( $field['id'] ) ) {

				$id = $field['id'];

				if ( isset( $this->stds[ $id ] ) ) {

					$field['std'] = $this->stds[ $id ];
				}
			}

			$field_type = $field['type'];

			if ( 'group_close' === $field_type ) {

				$container = &$results;
				continue;
			}

			if ( 'tab' === $field_type && $tab_started ) {

				$tab_started = false;
				$container   = &$results;
			}

			if ( ! $factory = $this->factory( $field ) ) {
				continue;
			}

			$this->transform_field( $container, $factory, ++ $iteration, $parent_field );

			if ( 'group' === $field_type || 'tab' === $field_type ) {

				$tab_started = true;

				end( $container );
				$key = key( $container );
				//
				$results   = &$container;
				$container = &$container[ $key ]['children'];
			}
		}

		return $results;
	}


	public function list_attributes() {

		$results = array();

		foreach ( $this->fields as $field ) {

			if ( empty( $field['type'] ) ) {
				continue;
			}

			if ( ! $factory = $this->factory( $field ) ) {
				continue;
			}

			if ( $the_attribute = $factory->the_attribute() ) {
				$results[ $factory->field( 'id' ) ] = $the_attribute;
			}
		}

		return $results;
	}


	/**
	 * @param array                          $container
	 * @param BF_Gutenberg_Field_Transformer $field
	 * @param int                            $iteration
	 * @param BF_Gutenberg_Field_Transformer $parent_transformer
	 *
	 * @return bool true on success or false on failure.
	 * @since 3.9.0
	 */
	protected function transform_field( &$container, BF_Gutenberg_Field_Transformer $field, $iteration, BF_Gutenberg_Field_Transformer $parent_transformer = null ) {

		$transformed = $field->transform_field( $iteration );

		if ( ! is_array( $transformed ) ) {

			return false;
		}

		$id = $field->field( 'id' );

		if ( ! isset( $transformed['id'] ) ) {
			$transformed['id'] = $id;
		}

		$data = array(
			'id'        => $id,
			'key'       => $id,
			'component' => $field->component(),
			'args'      => $transformed,
		);

		if ( $attribute = $field->the_attribute() ) {

			$data['attribute'] = $attribute;
		}

		if ( $shared_keys = array_intersect_key( $field->field(), array(
			'include_blocks' => '',
			'exclude_blocks' => '',
			'fixed_class'    => '',
			'action'         => '',
			'std'            => '',
		) )
		) {

			$data = array_merge( $data, $shared_keys );
		}

		if ( $children = $field->children_items_list() ) {

			$children_handler = new self( $children );

			if ( $children_transformed = $children_handler->transform( $field ) ) {

				$data['children'] = $children_transformed;
			}
		}

		if ( $parent_transformer ) {

			$data = $parent_transformer->children_item( $data );
		}

		if ( $field->wrap_section_container ) {

			$container[] = $this->wrap_section_container( $field, $data );

		} else {

			$container[] = $data;
		}

		return true;
	}


	/**
	 * @param BF_Gutenberg_Field_Transformer $field
	 * @param array                          $data
	 *
	 * @return array
	 */
	public function wrap_section_container( $field, $data ) {

		$title = isset( $data['args']['label'] ) ? $data['args']['label'] : '';
		unset( $data['args']['label'] );

		$id = $field->field( 'id' );

		$args = array(
			'type'  => str_replace( array( '_', 'bf-gutenberg-' ), array(
				'-',
				''
			), strtolower( get_class( $field ) ) ),
			'label' => $title,
			'id'    => "field_$id",
			'name'  => $id,
		);

		if ( $classes = $field->field( 'section_class' ) ) {
			$args['classes'] = $classes;
		}

		if ( ! empty( $data['args']['desc'] ) ) {
			$args['description'] = $data['args']['desc'];

			unset( $data['args']['desc'] );
		}

		if ( $show_on = $field->field( 'show_on' ) ) {

			if ( ! function_exists( 'bf_show_on_attributes' ) ) {
				require BF_PATH . '/core/field-generator/functions.php';
			}

			$args['show_on'] = bf_show_on_settings( $field->field() );
		}

		return array(
			'id'        => "field_$id",
			'component' => 'BF_Section_Container',
			'args'      => $args,
			'key'       => "field_$id",
			'children'  => array( $data ),
		);
	}


	/**
	 * @param array $field
	 *
	 * @since 3.9.0
	 * @return BF_Gutenberg_Field_Transformer on success or null on failure.
	 */
	public function factory( array $field ) {


		if ( empty( $field['type'] ) ) {
			return null;
		}

		if ( ! class_exists( 'BF_Gutenberg_Field_Transformer' ) ) {

			require BF_PATH . 'gutenberg/class-bf-gutenberg-field.php';
		}

		switch ( $field['type'] ) {

			case 'text':

				if ( ! class_exists( 'BF_Gutenberg_Text_Control' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-text-control.php';
				}

				$instance = new BF_Gutenberg_Text_Control();

				break;

			case 'textarea':
			case 'wp_editor':

				if ( ! class_exists( 'BF_Gutenberg_Textarea_Control' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-textarea-control.php';
				}

				$instance = new BF_Gutenberg_Textarea_Control();

				break;

			case 'group':
			case 'tab':

				if ( ! class_exists( 'BF_Gutenberg_Panel_Body' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-panel-body.php';
				}

				$instance = new BF_Gutenberg_Panel_Body();

				break;

			case 'select':

				if ( ! class_exists( 'BF_Gutenberg_Tree_Select' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-tree-select.php';
				}

				$instance = new BF_Gutenberg_Tree_Select();

				break;
			case 'checkbox':

				if ( ! class_exists( 'BF_Gutenberg_Radio_Control' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-radio-control.php';
				}

				$instance = new BF_Gutenberg_Radio_Control();

				break;

			case 'switch':

				if ( ! class_exists( 'BF_Gutenberg_BF_Switch' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-bf-switch.php';
				}

				$instance = new BF_Gutenberg_BF_Switch();

				break;

			case 'slider':

				if ( ! class_exists( 'BF_Gutenberg_Range_Control' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-range-control.php';
				}

				$instance = new BF_Gutenberg_Range_Control();

				break;

			case 'date':

				if ( ! class_exists( 'BF_Gutenberg_Date_Time_Picker' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-date-time-picker.php';
				}

				$instance = new BF_Gutenberg_Date_Time_Picker();

				break;

			case 'color':

				if ( ! class_exists( 'BF_Gutenberg_Color_Palette' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-color-palette.php';
				}

				$instance = new BF_Gutenberg_Color_Palette();

				break;

			case 'repeater':

				if ( ! class_exists( 'BF_Gutenberg_BF_Repeater' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-bf-repeater.php';
				}

				$instance = new BF_Gutenberg_BF_Repeater();


				break;

			case 'hr':

				if ( ! class_exists( 'BF_Gutenberg_BF_Hr' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-bf-hr.php';
				}

				$instance = new BF_Gutenberg_BF_Hr();

				break;

			case 'info':

				if ( ! class_exists( 'BF_Gutenberg_BF_Info' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-bf-info.php';
				}

				$instance = new BF_Gutenberg_BF_Info();

				break;

			case 'heading':

				if ( ! class_exists( 'BF_Gutenberg_BF_Heading' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-bf-heading.php';
				}

				$instance = new BF_Gutenberg_BF_Heading();

				break;

			case 'select_popup':

				if ( ! class_exists( 'BF_Gutenberg_BF_Select_Popup' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-bf-select-popup.php';
				}

				$instance = new BF_Gutenberg_BF_Select_Popup();

				break;

			case 'icon_select':

				if ( ! class_exists( 'BF_Gutenberg_BF_Icon_Select' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-bf-icon-select.php';
				}

				$instance = new BF_Gutenberg_BF_Icon_Select();

				break;

			case 'ajax_action':

				if ( ! class_exists( 'BF_Gutenberg_BF_Ajax_Action' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-bf-ajax-action.php';
				}

				$instance = new BF_Gutenberg_BF_Ajax_Action();

				break;

			case 'ajax_select':

				if ( ! class_exists( 'BF_Gutenberg_BF_Ajax_Select' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-bf-ajax-select.php';
				}

				$instance = new BF_Gutenberg_BF_Ajax_Select();

				break;

			case 'background_image':

				if ( ! class_exists( 'BF_Gutenberg_BF_Background_Image' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-bf-background-image.php';
				}

				$instance = new BF_Gutenberg_BF_Background_Image();

				break;

			case 'code':

				if ( ! class_exists( 'BF_Gutenberg_BF_Code' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-bf-code.php';
				}

				$instance = new BF_Gutenberg_BF_Code();

				break;

			case 'editor':

				if ( ! class_exists( 'BF_Gutenberg_BF_Editor' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-bf-editor.php';
				}

				$instance = new BF_Gutenberg_BF_Editor();

				break;

			case 'image_preview':

				if ( ! class_exists( 'BF_Gutenberg_BF_Image_Preview' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-bf-image-preview.php';
				}

				$instance = new BF_Gutenberg_BF_Image_Preview();

				break;

			case 'image_radio':

				if ( ! class_exists( 'BF_Gutenberg_BF_Image_Radio' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-bf-image-radio.php';
				}

				$instance = new BF_Gutenberg_BF_Image_Radio();

				break;

			case 'image_select':

				if ( ! class_exists( 'BF_Gutenberg_BF_Image_Select' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-bf-image-select.php';
				}

				$instance = new BF_Gutenberg_BF_Image_Select();

				break;

			case 'media_image':

				if ( ! class_exists( 'BF_Gutenberg_BF_Media_Image' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-bf-media-image.php';
				}

				$instance = new BF_Gutenberg_BF_Media_Image();

				break;

			case 'sorter_checkbox':

				if ( ! class_exists( 'BF_Gutenberg_BF_Sorter_Checkbox' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-bf-sorter-checkbox.php';
				}

				$instance = new BF_Gutenberg_BF_Sorter_Checkbox();

				break;

			case 'term_select':

				if ( ! class_exists( 'BF_Gutenberg_BF_Term_Select' ) ) {
					require BF_PATH . 'gutenberg/adapters/class-bf-gutenberg-bf-term-select.php';
				}

				$instance = new BF_Gutenberg_BF_Term_Select();

				break;
		}

		if ( isset( $instance ) ) {
			$instance->init( $field );

			return $instance;
		}

		return null;
	}
}
assets/js/widget.js000064400000002450151214002650010300 0ustar00(function( $ ) {
    $.unserialize = function(serializedString){
        var str = decodeURI(serializedString);
        var pairs = str.split('&');
        var obj = {}, p, idx, val;
        for (var i=0, n=pairs.length; i < n; i++) {
            p = pairs[i].split('=');
            idx = p[0];

            if (idx.indexOf("[]") == (idx.length - 2)) {
                // Eh um vetor
                var ind = idx.substring(0, idx.length-2)
                if (obj[ind] === undefined) {
                    obj[ind] = [];
                }
                obj[ind].push(p[1]);
            }
            else {
                obj[idx] = p[1];
            }
        }
        return obj;
    };

    $('.bw-color-field').wpColorPicker();

    jQuery(document).ajaxSuccess(function(e, xhr, settings) {

        var widget_id_base = 'better_weather_widget';

        if( typeof settings.data != "string" )
            return false;

        var _settings = $.unserialize(settings.data);

        if( settings.data.search('action=save-widget') != -1 && settings.data.search('id_base=' + widget_id_base) != -1) {

            var $_widget = $('input[value=better_weather_widget-'+_settings['widget_number']).closest('.widget');
            $_widget.find('.bw-color-field').wpColorPicker();

        }

    });

})( jQuery );assets/img/logo-50x50.png000064400000004162151214002650011046 0ustar00�PNG


IHDR22?��tEXtSoftwareAdobe ImageReadyq�e<#iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.5-c014 79.151481, 2013/03/13-12:09:15        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CC (Macintosh)" xmpMM:InstanceID="xmp.iid:04B56B69CFDC11E38CD1E62EAEFB47D9" xmpMM:DocumentID="xmp.did:04B56B6ACFDC11E38CD1E62EAEFB47D9"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:04B56B67CFDC11E38CD1E62EAEFB47D9" stRef:documentID="xmp.did:04B56B68CFDC11E38CD1E62EAEFB47D9"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>b�\M�IDATx��ZMle~�o�����F��B�Sj�(z�1@==�D=�I1F�QC�x�ƃ'c*�6�b���P���[�ݝ����i+[vgg���Ov�;߼�3���M*��n�C�-r4�4��tDj��x�����k�~��k'"֤-�}j��'z[d&�g�Ζ^ZwD��U�x�H��"*6���y��L�>�U>��(Sŀ�FR�%�b��~/r7H��L�ؚ$���M9��{p��U$��e�f��|c�A�(�/Ȥ�D�ծc�Sn^}%b��S�b��N_o�m#A�˸|�D�mW�~N�s7�u�a��DLL!�nH���P��&Oi�a#�x��>
7|�Q�''����l>���xzFa�D�E�p �ʦ��)Av�|���]7�W���JIcϸ��o�5a���H*�)w����0�}�~�<�|
l���.Q�S&�����79%�����K��j"w��OT=GJL�a�
C��yE���F� 2YS��>�>V$�M�w�a�r�̕9E&�{y�xws�����:�h���y�/K?��y�O֡<�͞v�9�Q�H{K�F�'�k�~D�!�s0��C�9����X���6� ��#5�����IAsY��4���||O�����t���c���UyA�A���83��AW��VY�#�ﴏk�+v��~�Y�T�"u0C�s�f�t����p��d�C��W�X���k��ʞ�/���4rs5l�g�r��.V;��@����d���� pp���7�%ٗ|&"�&P?�9^�,�g�s`��*��=뷁nOб	Y1�4�R*�M2}���Q?-ғ?k[��`_%�T����l��u�
{�ˮ0�ߝ��!t_�SQ|g��[��q�*�W,\��jy��K��i�f��}ĦJ�fg*�t;�u��B����㋱p�4VګȍL�6�8b�3)U�i�Q5E>#�� I�{8��ɖ�&'��]�&
��U��X��w�Rf��'�����v�wk�[�.o��L��)�ʩD7g�I�J2�	�L�ѽ!��%��Y�N�
/{5����,�����V׏��r�Ȣ�yؓ4 a�Pׇ�oG��I�t;��̮r]V_�c5x3�x����ؽ5���k\O�7��ҍ�Q�����K���h"�n����k��6G^�ۍ���h�G�H�H�H���8�`=�܍�j�IEND�B`�assets/img/shortcodes/better-weather-inline.png000064400000004733151214002650015706 0ustar00�PNG


IHDR<,9*��gAMA���a	�IDATh�Zk��W~f���`�.��RY]�@�xAh��?�1��*�!���^�Q��h�?���F��J���RB��jJť�P�H�X��@���egwg����|����3�$%�aΜ��=��y����:|�-��(9�:����k��,��@��o1�'���A��roϞ
�JR�d�oP�7��K�M�M�/�{�+�>0�7ֻBs���@~��z!�b���p��)�7�0�
���r�V�ߙE*�G�p�P�u �,��X	��PƉ"����E�0֣q��%B�*��k����瘣Ak��m~����ǒ&S^��-ص-���&1E@eT׿L�,3��ٕ��!�vIq�T�Gi!=��ОIX�L���qKM��'�B�\�:Sq)�R�DY@�ٌe4�
8A���b�}!j���W&.���}�q��Mz�Xy�̆#���է�	<i��<x�u��4u
FP�L�R2�(BbW���.�k�4B�C���v�ު�Jfؿ�V�vJV���,��t��r�p���]S&X~,e��<�|o̿�yI�����bXz�=ۜT���e=��!Z��5%��2�yfY
�-�L�X�u����Fe*�Jf�?�)�"u�U:1��9���JX���Y���\g�j��Fu�Ќө��-���#�����RRY��_�\���.�v`�[�`��JR,��0kF�#��a���8�zG`�;�l�_e����**��	Z V�u6��>�M9���<��Cf��UQl��<v��9SV���:K��s�ȇ����%p�/KW�n�K�lS��/>�
���M����ע~J/�·7���g�ǠC���hG�8�!AS��S���}F�q���~|⧥���Y�%�M�P*��(V=�_���>݌u�f���_ɛ��0��f&�'�/ƃ�����7��2�:���V����j<�ݛ�܋'q�-���۱�7��w�5kx�x��Z�T9X��p�G�"p���O����u��l���(JfM��+2��;�dž-�����	0���a<��4L���M���3�(���4i2l����(�2S	�עՀC����0o�4�,�y͜V�i���f`���M��F	��m8��˷a��ЗL�iF����s�;�2�0wxEX���:X*�G��Dss=V�W�?�M�V���C����U+e�it�f	���~�|{n^4�~{�Wayj`��oO!MA�;{�Q�_g�̯��
Koh��ųp�;���
z���XѺ�A��U�b�"A@t��YZ����`�4/\0��,��e�jC�h�*%�4o6�_��m�I���$��b^'�x��'�7���Dɤ�w�]{�/k���^q�Z����})`�yMe�c$K��_����X�Y6Ϛ�k�����ӏ,CU�����h���'�D[����l�����<����Xz��3��y�0Y�RW��|���׾��D��bT����D?�)��Ȼ*��VDQ�>�\��?_��h2i1g���9|vX��Z79��)�C�?B���ޅ@�@�J�nĥX:�n���.:4L�h�
[���(�<Z͟�S��z�m�)���v��J�Z�6@M��[Qnj�x�]�l��y&XV-�7>�6�cc��Xȳ��g��/�\������@oY:��h����_�A/-É��z���X�� 0�
��#��(ߴ��h&��}�d[�T�]�\�M݈�� �9�K�2A�q�PX;�%d��J���
#-�	
��t<9d�@�^M���N�-K�q������rss��-Œ�Ksv�Z�`�,[�P݇�3U�^]M��E+�D��Z]Î}�p��!$1�ꂖ�
h��Y�o�vm�ZĹ��;u�R�wo<G��l򜎓�hޟd��M���BL.@K���x���eax�I&�n��9#D�@T�gOГ�'RF���<���؇_��I,^�Al��4N�>�c`��n~��`��������1i�d{��?�{v�b���c����Ɠ�~�ֿ�HT��ʙ�__u����T�����J���\(uv��d8��G���&{�|'v��@CC#�Ϳ����g���<R�S��c����n�+��OuP�U�FQ?u���\��Q��%��7V[�Y�ғ&��Wd���c�����G�	8�)S�F�u�/U#��bzD�"��n�N��8~��Ǽ�)&�X���v�+4��y�`�1��{j�ލ.�eX��+?o��Ύ�}��i�I.��Qi�~��~'>���.��^W)=V���Γ/������w5�
ʛ�'��[�x�����4�����}���_F�{��*G�$_L�d��9W_Y��%mZ��9|�ؙ��*���c�@OIEND�B`�assets/img/shortcodes/better-weather.png000064400000004362151214002660014431 0ustar00�PNG


IHDR<,9*��gAMA���a�IDATh�Zm�\�~�ν3wv&u7kB�	��5&~�#Ė �Ji)h
��Z�T���Z�G�C��B����FhC��b�
1�Fk:jM�Y����̝�>�{��eص;sG,MO����=��}�y�ds�W�8�J(���W��_y�mg��N-�d�b8�v����r�\_f�
���Qz����W敧�O����=0���\:�<�Di��\���	���ps���W��Lc3I[�߉��B}:�U�#�s�\�6�k{^��yʄ�b�u��(َ�!��LQ���k������9�Ak�}�v�cI�tm��cس+��iח34Fm�k��n�"0w9�;-�K�KE�Z0ve]�Cr&�>��>gsj�~K&�i�{��F�ݤ�4\Ƴ�}�%��V�.�}N�l4��G�b_�C
��<��ʁ�#�i�
.�ѳKw�)źf�l�g;�V�&"'��F:��׹P��5A5�MJ�#�Į@s�����bi�6���r���j�T�f8��֖u*V;��3ݶ��D8ț��se���J3iu��}c���Ki���;�R��M'
$ cY����"G0����C_f��,k����k��"Ǐ׹Ѝ�L�|��pz3�!u�j��\m���yKXu}�2��~�Ū�.�X�n���[����;����~�@;ŊW�\<��E�~ֽ+/%Ǭ$Œc8���J���
��ny}(�Qގ1S��k`���:��P�d��%h-�X��5�݋8��?�:�������p9�C?]K�!Zrg�ʕ�<��QH��y���L1�V>�$�S-��v�X
�g��.>o�{��T��V���_���E<��}���Wq��/���ǤC���kG�<�%!Y���+p���d�M�1���g|�0vܺW^vf�MTJ�ݹ�8�];��&��^�0��f&�'�/Ƴ����W.YA�b4-pu�4��\���+x�W��ijo���U7�ƃ~��a�y�=��'���b��/�
߸���<��~�ܝŮ�:�1,6
4̲(�5㖡���O��<v�}�LN5p�#�b��!�}h#�O�""�B?YK'd�6*u�(�2WɆײՌS��?�ձ��Q��,$<��-a�1���e����QBt���ͻp�]�05�`ղ2v�pO<��+��+�j�Qg�t�20�W?�����a�?���?��%�j��춋G�*�U�I���Z�j
��]ŦuK�_޲�UZ^?��¸�#��S�GS��g���묕�U�����Uذ~%�99�����>���q�u�\by�ũX/�İ�nܢw�,��$H�pp��pd߲x��MQ��ixD�	�l�>M��'���7q�m�:����L����!߅���\l޸��}�%)�\-?
k�R�&��ZX�H�Vɾ��r�n9��l��)ܼy-�p�F�KR+6-�Q=>�;~wG�S�C@���&��o+�y��Q�����Pg&���`��xI�}s�<����8f�)��3zkb�r��U�ItB��e+�,M�~^dW�d_��lri1[��X�Y���䜘��"Թ��\�r�?
���Rq?��K�t���܁1<�]t�A�ihB�-�`G&��i-�.Ų�<�����#��
���0?�m�:���߷"njQ1�.=0��N�5�MK����*ppѹC��gu�g��w�[|)��h��=eU���
��+FJx�I��g��I뉾�+vc]z�م�b�^D3�<95C��Ju�˥���3�My�
�y�̻g��E.]�ϩ����&t�/�yK�SHv
4����u��c�1�_�BVr����)nn!^��Y3~��aQ˘��aK*S��S6��,*�b��h%��骕R��{G�5�8.�UZ1*�/�.ncո6A-����;u&PTl��O��3sw.�P[��;�������R�@∌�G��F(���ƬK����'�C�6�L԰}��FoZo�|��'���?B�H�O��L�FI�/�7_���?W������)Ҹc��s�=�U�}u�.��	���{�؏��jP���C�o{ݲ�g<�b���n�=��[n!��{@���7(}o��鶟{�1���p������}�ߺ/��c�[��=�i�{��`������}���t���n�c1�IEND�B`�assets/img/logo.png000064400000003326151214002660010271 0ustar00�PNG


IHDR  szz�tEXtSoftwareAdobe ImageReadyq�e<#iTXtXML:com.adobe.xmp<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.5-c014 79.151481, 2013/03/13-12:09:15        "> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" xmp:CreatorTool="Adobe Photoshop CC (Macintosh)" xmpMM:InstanceID="xmp.iid:04B56B65CFDC11E38CD1E62EAEFB47D9" xmpMM:DocumentID="xmp.did:04B56B66CFDC11E38CD1E62EAEFB47D9"> <xmpMM:DerivedFrom stRef:instanceID="xmp.iid:04B56B63CFDC11E38CD1E62EAEFB47D9" stRef:documentID="xmp.did:04B56B64CFDC11E38CD1E62EAEFB47D9"/> </rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end="r"?>,8�UIIDATx��WKOSA>g���@!e!�l���kMԸ��UI��JѸ7�н��J�n\) Q��ED!��mo��xR�\j���|�Mg�9���J)X�`�Ǻ�MXVeh���9�)2\x��lNX��<D\)S��bFu%�YOy)���i��,��	����L�4A"��3")����d�"r(Z<�,qu0���W�8r�6�ʈor|��q5�NJ�}p�B�5_��NLF��s�J5�i�6r�M4^��cNq��gJx&��3� ��B����\Q�f�}���ݤ�/DmH��Y�3J�V7��&c��p,�'��ˎi[�&ⴄ�[R#R��DW�@H��Qw}����턇	�	uނ� ��'& �����b b�#TJ�N8C8��|��ğ+���䊶�ש�:O
�-�%�IJ���@�b�k��RB��=�j�K���\؄���{�fY���}`���P���E�t��,s�8m��f8�T�7B����3�����(A�rtK�I�H\�\�BL���
NJ}�����"b�N�#�S�cl�LQ�sB>-�������	��R�x�p��q�w�ֆ�Ԙ/��o˕��v'�ѱ-;v�w\��Pf���~��!��tt�)Y�U�Psg�/�c�j^��j�W`f����j(�d8��\H��VT+0P�Џ��@�W�����`w•��bY�����'�]�{'��7�O�T-�b:�B���S��S��;�S��u^(�k�2]�ݥS*�E��s���Ί�Ί?kZ�;�����̓As��'��Kfn|B�ᅫ0��EƐ]�IEND�B`�assets/css/vc-style.css000064400000001232151214002660011111 0ustar00
#BetterWeather-inline .vc_element-icon,
.wpb_BetterWeather-inline .vc_element-icon,

#BetterWeather .vc_element-icon,
.wpb_BetterWeather .vc_element-icon{
    width: 60px !important;
    height: 44px !important;
}


#BetterWeather-inline,
#BetterWeather{
    padding-left: 78px;
}

#BetterWeather-inline .vc_element-icon,
#BetterWeather .vc_element-icon{
    top: 14px;
}

#BetterWeather .vc_element-icon,
.wpb_BetterWeather .vc_element-icon {
    background: url("../img/shortcodes/better-weather.png");
}


#BetterWeather-inline .vc_element-icon,
.wpb_BetterWeather-inline .vc_element-icon {
    background: url("../img/shortcodes/better-weather-inline.png");
}

generator/class-bw-generator-factory.php000064400000001257151214002660014411 0ustar00<?php

/**
 * Handles generation off all generators
 *
 * Class BW_Generator_Factory
 */
class BW_Generator_Factory {

	/**
	 * instance of generator
	 *
	 * @var BW_Frontend
	 */
	private static $instance;

	/**
	 * used for getting instance of generator
	 *
	 * @return BW_Frontend
	 */
	public static function generator() {

		if ( ! isset( self::$instance ) || is_null( self::$instance ) ) {

			require_once Better_Weather::dir_path( 'includes/generator/class-bw-forecast-facade.php' );
			require_once Better_Weather::dir_path( 'includes/generator/class-bw-frontend.php' );

			self::$instance = new BW_Frontend();

			self::$instance->init();

		}

		return self::$instance;
	}

}generator/sources/class-bw-yahoo-source.php000064400000021130151214002660015046 0ustar00<?php


/**
 * Class BW_Yahoo_Source
 */
class BW_Yahoo_Source extends BW_Weather_Source {

	/**
	 * Source constructor
	 *
	 * @param string $app_id
	 * @param string $api_key
	 * @param string $secret_key
	 * @param string $lang
	 */
	public function __construct( $app_id = '', $api_key = '', $lang = '', $secret_key = '' ) {

		$this->source_id = 'yahoo';
		parent::__construct( $app_id, $api_key, $lang, $secret_key );
	}

	/**
	 * Build base url.
	 *
	 * @param $baseURI
	 * @param $method
	 * @param $params
	 *
	 * @since 1.0.0
	 * @return string
	 */
	protected function build_base_string( $baseURI, $method, $params ) {

		$r = array();

		ksort( $params );

		foreach ( $params as $key => $value ) {

			$r[] = "$key=" . rawurlencode( $value );
		}

		return $method . "&" . rawurlencode( $baseURI ) . '&' . rawurlencode( implode( '&', $r ) );
	}

	/**
	 * Build permission header params.
	 *
	 * @param $oauth
	 *
	 * @since 1.0.0
	 * @return string
	 */
	protected function build_authorization_header( $oauth ) {

		$r = 'Authorization: OAuth ';

		$values = array();

		foreach ( $oauth as $key => $value ) {

			$values[] = "$key=\"" . rawurlencode( $value ) . "\"";
		}

		$r .= implode( ', ', $values );

		return $r;
	}

	/**
	 * today[]
	 *      time
	 *      summary
	 *      icon
	 *      temperature
	 *      temperature_max
	 *      temperature_min
	 *      sunrise_time
	 *      sunset_time
	 *
	 *
	 * next_days[]
	 *      []
	 *          time
	 *          day_name
	 *          summary
	 *          icon
	 *          temperature
	 *          temperature_min
	 *          temperature_max
	 *          sunrise_time
	 *          sunset_time
	 *
	 * location[]
	 *      country
	 *      city
	 *      latitude
	 *      longitude
	 *
	 * @param        $location
	 * @param string $unit
	 *
	 * @return array
	 */
	function get_forecast( $location, $unit = 'c' ) {

		$url = 'https://weather-ydn-yql.media.yahoo.com/forecastrss';

		if ( strpos( $location, ',' ) ) {

			list( $lat, $long ) = explode( ',', $location );
		}

		$query = array(
			'location' => $location,
			'format'   => 'json',
			'lat'      => isset( $lat ) ? $lat : '',
			'lon'      => isset( $long ) ? $long : ''
		);

		$oauth = array(
			'oauth_consumer_key'     => $this->get_api_key(),
			'oauth_nonce'            => uniqid( mt_rand( 1, 1000 ) ),
			'oauth_signature_method' => 'HMAC-SHA1',
			'oauth_timestamp'        => time(),
			'oauth_version'          => '1.0'
		);

		$base_info                = $this->build_base_string( $url, 'GET', array_merge( $query, $oauth ) );
		$composite_key            = rawurlencode( $this->get_secret_key() ) . '&';
		$oauth_signature          = base64_encode( hash_hmac( 'sha1', $base_info, $composite_key, true ) );
		$oauth['oauth_signature'] = $oauth_signature;

		$header = array(
			$this->build_authorization_header( $oauth ),
			'X-Yahoo-App-Id: ' . $this->get_app_id()
		);

		$options = array(
			CURLOPT_HTTPHEADER     => $header,
			CURLOPT_HEADER         => false,
			CURLOPT_URL            => $url . '?' . http_build_query( $query ),
			CURLOPT_RETURNTRANSFER => true,
			CURLOPT_SSL_VERIFYPEER => false
		);

		$ch = curl_init();
		curl_setopt_array( $ch, $options );
		$response  = curl_exec( $ch );
		$http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
		curl_close( $ch );

		// Connection Error
		if ( $http_code != 200 ) {
			return array(
				'status' => 'error',
				'title'  => __( 'Connection Error', 'better-studio' ),
				'msg'    => __( 'No any data received from Yahoo Weather.', 'better-studio' ),
				'data'   => $response
			);
		}

		// Try to decode the json
		$r_body = @json_decode( $response, false );
		if ( $r_body === null and json_last_error() !== JSON_ERROR_NONE ) {
			return array(
				'status' => 'error',
				'title'  => __( 'Data Error', 'better-studio' ),
				'msg'    => __( 'Error decoding the json from Yahoo Weather', 'better-studio' ),
				'data'   => $response
			);
		}

		if ( empty( $r_body->forecasts ) || is_null( $r_body->forecasts ) ) {
			return array(
				'status' => 'error',
				'title'  => __( 'Incorrect Location', 'better-studio' ),
				'msg'    => __( 'Entered location ( lat and lang ) is incorrect', 'better-studio' ),
				'data'   => $r_body
			);
		}

		$output = array();

		$data = $r_body;

		// Location
		//
		$output['location']['longitude'] = $data->location->long;
		$output['location']['latitude']  = $data->location->lat;
		$output['location']['country']   = $this->pretty_name( $data->location->country );
		$output['location']['city']      = $this->pretty_name( $data->location->city );


		//
		// Today data
		//
		$output['today']['time']            = strtotime( $data->current_observation->pubDate );
		$output['today']['time_r']          = $this->get_date_translation( $output['today']['time'] );
		$output['today']['summary']         = $this->get_translation( $data->current_observation->condition->text );
		$output['today']['icon']            = $this->get_standard_icon( $data->current_observation->condition->code );
		$output['today']['temperature']     = $this->convert_fahrenheit_to_celsius( $data->current_observation->condition->temperature );
		$output['today']['temperature_min'] = $this->convert_fahrenheit_to_celsius( $data->forecasts[0]->low );
		$output['today']['temperature_max'] = $this->convert_fahrenheit_to_celsius( $data->forecasts[0]->high );
		$output['today']['sunrise_time']    = strtotime( $data->forecasts[0]->date . ' ' . $data->current_observation->astronomy->sunrise );
		$output['today']['sunset_time']     = strtotime( $data->forecasts[0]->date . ' ' . $data->current_observation->astronomy->sunset );


		//
		// Next Days
		//
		unset( $data->forecasts[0] );
		$counter = 0;
		foreach ( $data->forecasts as $day ) {

			if ( $counter > 4 ) {
				break;
			} else {
				$counter ++;
			}

			$output['next_days'][ $counter ] = array(
				'time'            => strtotime( $day->date ),
				'time_r'          => $this->get_date_translation( strtotime( $day->date ) ),
				'day_name'        => $this->get_day_translation( strtotime( $day->date ) ),
				'summary'         => $this->get_translation( $day->text ),
				'icon'            => $this->get_standard_icon( $day->code ),
				'temperature'     => '',
				'temperature_min' => $day->low,
				'temperature_max' => $day->high,
				'sunrise_time'    => '',
				'sunset_time'     => '',
			);
		}

		return array(
			'status' => 'succeed',
			'data'   => $output,
		);

	} // get_remote_data_forecast_io


	/**
	 * Creates standard icons from Aeris Weather condition code
	 *
	 * https://developer.yahoo.com/weather/documentation.html
	 *
	 * @param $condition_code
	 *
	 * @return string
	 */
	function get_standard_icon( $condition_code, $day = true ) {

		switch ( $condition_code ) {

			case 33: // fair (night)
			case 31: // clear (night)
				$_icon = 'clear-night';
				break;

			case 34: // fair (day)
			case 32: // sunny
				$_icon = 'clear-day';
				break;

			case 36: // hot
				if ( $day ) {
					$_icon = 'clear-day';
				} else {
					$_icon = 'clear-night';
				}
				break;

			case 47: // isolated thundershowers
			case 6: // mixed rain and sleet
			case 5: // mixed rain and snow
			case 9: // drizzle
			case 40: // scattered showers
			case 12: // showers
			case 11: // showers
			case 10: // freezing rain
			case 8: // freezing drizzle
				$_icon = 'rain';
				break;

			case 7: // mixed snow and sleet
			case 13: // snow flurries
			case 14: // light snow showers
			case 15: // blowing snow
			case 16: // snow
			case 17: // hail
			case 18: // sleet
			case 35: // mixed rain and hail
			case 41: // heavy snow
			case 42: // scattered snow showers
			case 43: // heavy snow
			case 46: // snow showers
				$_icon = 'snow';
				break;

			case 45: // thundershowers
			case 39: // scattered thunderstorms
			case 38: // scattered thunderstorms
			case 37: // isolated thunderstorms
			case 4: // thunderstorms
			case 3: // severe thunderstorms
			case 2: // hurricane
			case 1: // tropical storm
			case 0: // tornado
			case 24: // windy
			case 23: // blustery
			case 19: // dust
				$_icon = 'wind';
				break;

			case 44: // partly cloudy
				if ( $day ) {
					$_icon = 'partly-cloudy-day';
				} else {
					$_icon = 'partly-cloudy-night';
				}
				break;

			case 29: // partly cloudy (night)
				$_icon = 'partly-cloudy-night';
				break;

			case 30: // partly cloudy (day)
				$_icon = 'partly-cloudy-day';
				break;

			case 28: // mostly cloudy (day)
			case 27: // mostly cloudy (night)
			case 25: // cold
			case 26: // cloudy
				$_icon = 'cloudy';
				break;

			case 22: // smoky
			case 21: // haze
			case 20: // foggy
				$_icon = 'fog';
				break;

			default:
				$_icon = '';

		}

		return $_icon;

	} // get_standard_icon

}generator/sources/class-bw-owm-source.php000064400000017236151214002660014545 0ustar00<?php


/**
 * Class BW_OWM_Source
 */
class BW_OWM_Source extends BW_Weather_Source {

	/**
	 * Source constructor
	 *
	 * @param string $app_id
	 * @param string $api_key
	 * @param string $lang
	 */
	public function __construct( $app_id = '', $api_key = '', $lang = '' ) {
		$this->source_id = 'owm';
		parent::__construct( $app_id, $api_key, $lang );
	}


	/**
	 * today[]
	 *      time
	 *      summary
	 *      icon
	 *      temperature
	 *      temperature_max
	 *      temperature_min
	 *      sunrise_time
	 *      sunset_time
	 *
	 *
	 * next_days[]
	 *      []
	 *          time
	 *          day_name
	 *          summary
	 *          icon
	 *          temperature
	 *          temperature_min
	 *          temperature_max
	 *          sunrise_time
	 *          sunset_time
	 *
	 * location[]
	 *      country
	 *      city
	 *      latitude
	 *      longitude
	 *
	 *
	 * @param        $location
	 * @param string $unit
	 *
	 * @return array
	 */
	function get_forecast( $location, $unit = 'c' ) {

		// Check API Key
		if ( $this->get_api_key() == '' ) {
			return array(
				'status' => 'error',
				'title'  => __( 'No API Key', 'better-studio' ),
				'msg'    => __( 'Obtain API Key from http://openweathermap.org/appid', 'better-studio' ),
				'data'   => 'no data'
			);
		}

		$location = explode( ',', $location );

		// Creates temperature unit
		switch ( $unit ) {

			case 'C':
			case 'c':
				$unit = 'metric';
				break;

			case 'F':
			case 'f':
				$unit = 'imperial';
				break;


			default:
				$unit = 'metric';
				break;
		}

		// Params of URL
		$url_parts = array(
			'lat=' . urlencode( $location[0] ),
			'lon=' . urlencode( $location[1] ),
			'lang=' . $this->get_lang(),
			'cnt=' . 60,
			'units=' . $unit,
			'appid=' . $this->get_api_key(),
		);

		// final URL
		$url = 'http://api.openweathermap.org/data/2.5/forecast?' . implode( '&', $url_parts );

		$r_resp = $this->get_remote_data( $url );

		if ( wp_remote_retrieve_response_code( $r_resp ) != 200 ) {
			return array(
				'status' => 'error',
				'title'  => __( 'API key is incorrect', 'better-studio' ),
				'msg'    => __( 'Please obtain API Key from https://developers.forecast.io/', 'better-studio' ),
				'data'   => __( 'no data', 'better-studio' )
			);
		}

		if ( is_wp_error( $r_resp ) ) {
			if ( is_wp_error( $r_resp ) || ! isset( $r_resp['body'] ) || $r_resp['body'] == FALSE ) {
				return array(
					'status' => 'error',
					'title'  => __( 'Connection Error', 'better-studio' ),
					'msg'    => __( 'Error getting remote data for today forecast. Please check your server configuration', 'better-studio' ),
					'data'   => $r_resp
				);
			}
		}


		// Try to decode the json
		$r_body = @json_decode( wp_remote_retrieve_body( $r_resp ), TRUE );
		if ( $r_body === NULL and json_last_error() !== JSON_ERROR_NONE ) {
			return array(
				'status' => 'error',
				'title'  => __( 'Data Error', 'better-studio' ),
				'msg'    => __( 'Error decoding the json from OpenWeatherMap', 'better-studio' ),
				'data'   => $r_resp
			);
		}


		// Validate location
		if ( $r_body['cod'] != 200 ) {
			return array(
				'status' => 'error',
				'title'  => __( 'Incorrect Location', 'better-studio' ),
				'msg'    => __( 'Entered location ( lat and lang ) is incorrect', 'better-studio' ),
				'data'   => $r_body
			);
		}

		$output = array();

		//
		// Location
		//
		$output['location']['longitude'] = $r_body['city']['coord']['lon'];
		$output['location']['latitude']  = $r_body['city']['coord']['lat'];
		$output['location']['country']   = $this->pretty_name( $r_body['city']['country'] );
		$output['location']['city']      = $this->pretty_name( $r_body['city']['name'] );


		//
		// Today data
		//
		$day                                = current( $r_body['list'][0]['sys'] ) == 'n' ? FALSE : TRUE;
		$output['today']['time']            = $r_body['list'][0]['dt'];
		$output['today']['time_r']          = $this->get_date_translation( $output['today']['time'] );
		$output['today']['summary']         = $this->get_translation( $r_body['list'][0]['weather'][0]['description'] );
		$output['today']['icon']            = $this->get_standard_icon( $r_body['list'][0]['weather'][0]['id'], $day );
		$output['today']['temperature']     = $r_body['list'][0]['main']['temp'];
		$output['today']['temperature_min'] = $r_body['list'][0]['main']['temp_min'];
		$output['today']['temperature_max'] = $r_body['list'][0]['main']['temp_max'];
		$output['today']['sunrise_time']    = '';
		$output['today']['sunset_time']     = '';

		//
		// Next Days
		//
		$date_flag = date( 'D', $output['today']['time'] );
		$counter   = 0;
		foreach ( $r_body['list'] as $day_id => $day ) {

			if ( $date_flag == date( 'D', $day['dt'] ) ) {
				continue;
			} else {
				$date_flag = date( 'D', $day['dt'] );
			}

			if ( $counter > 4 ) {
				break;
			} else {
				$counter ++;
			}

			$output['next_days'][ $counter ] = array(
				'time'            => $day['dt'],
				'time_r'          => $this->get_date_translation( $day['dt'] ),
				'day_name'        => $this->get_day_translation( $day['dt'] ),
				'summary'         => $this->get_translation( $day['weather'][0]['description'] ),
				'icon'            => $this->get_standard_icon( $day['weather'][0]['id'] ),
				'temperature'     => $day['main']['temp'],
				'temperature_min' => $day['main']['temp_min'],
				'temperature_max' => $day['main']['temp_max'],
				'sunrise_time'    => '',
				'sunset_time'     => '',
			);
		}

		return array(
			'status' => 'succeed',
			'data'   => $output,
		);

	} // get_remote_data_forecast_io


	/**
	 * Creates standard icons from OWM weather condition code
	 *
	 * http://openweathermap.org/weather-conditions
	 *
	 * @param $condition_code
	 *
	 * @return string
	 */
	function get_standard_icon( $condition_code, $day = TRUE ) {

		switch ( TRUE ) {

			case $condition_code == 955: // fresh breeze
			case $condition_code == 954: // moderate breeze
			case $condition_code == 953: // gentle breeze
			case $condition_code == 952: // light breeze
			case $condition_code == 951: // calm
			case $condition_code == 904: // hot
			case $condition_code == 903: // cold
			case $condition_code == 800: // clear
				if ( $day ) {
					$_icon = 'clear-day';
				} else {
					$_icon = 'clear-night';
				}
				break;


			case $condition_code == 611: // hail
			case $condition_code >= 300 && $condition_code < 400: // Drizzle
			case $condition_code >= 500 && $condition_code < 600: // Rain
				$_icon = 'rain';
				break;


			case $condition_code == 906: // Sleet
			case $condition_code >= 600 && $condition_code < 700: // Snow
				$_icon = 'snow';
				break;


			case $condition_code == 902: // tornado
			case $condition_code == 901: // tornado
			case $condition_code == 900: // tornado
			case $condition_code == 962: // hurricane
			case $condition_code == 961: // violent storm
			case $condition_code == 960: // storm
			case $condition_code == 959: // severe gale
			case $condition_code == 958: // gale
			case $condition_code == 956: // strong breeze
			case $condition_code == 957: // high wind, near gale
			case $condition_code == 905: // windy
				$_icon = 'wind';
				break;


			case $condition_code >= 200 && $condition_code < 300: // Thunderstorm
				$_icon = 'thunderstorm';
				break;


			case $condition_code == 801: // few clouds
			case $condition_code == 802: // scattered clouds
				if ( $day ) {
					$_icon = 'partly-cloudy-day';
				} else {
					$_icon = 'partly-cloudy-night';
				}
				break;


			case $condition_code >= 700 && $condition_code < 800: // Atmosphere | Fog
				$_icon = 'fog';
				break;

			case $condition_code >= 800 && $condition_code < 810: // Clouds + fallback for new
				$_icon = 'cloudy';
				break;

			default:
				$_icon = '';

		}

		return $_icon;

	} // get_standard_icon

}generator/sources/class-bw-aeris-source.php000064400000015215151214002660015041 0ustar00<?php


/**
 * Class BW_Aeris_Source
 */
class BW_Aeris_Source extends BW_Weather_Source {

	/**
	 * Source constructor
	 *
	 * @param string $app_id
	 * @param string $api_key
	 * @param string $lang
	 */
	public function __construct( $app_id = '', $api_key = '', $lang = '' ) {
		$this->source_id = 'aeris';
		parent::__construct( $app_id, $api_key, $lang );
	}


	/**
	 * today[]
	 *      time
	 *      summary
	 *      icon
	 *      temperature
	 *      temperature_max
	 *      temperature_min
	 *      sunrise_time
	 *      sunset_time
	 *
	 *
	 * next_days[]
	 *      []
	 *          time
	 *          day_name
	 *          summary
	 *          icon
	 *          temperature
	 *          temperature_min
	 *          temperature_max
	 *          sunrise_time
	 *          sunset_time
	 *
	 * location[]
	 *      country
	 *      city
	 *      latitude
	 *      longitude
	 *
	 * @param        $location
	 * @param string $unit
	 *
	 * @return array
	 */
	function get_forecast( $location, $unit = 'c' ) {

		// Check App ID and Key
		if ( $this->get_api_key() == '' ) {
			return array(
				'status' => 'error',
				'title'  => __( 'No API Key', 'better-studio' ),
				'msg'    => __( 'Obtain API Key from http://www.aerisweather.com/account/apps', 'better-studio' ),
				'data'   => 'no data'
			);
		} elseif ( $this->get_api_key() == '' ) {
			return array(
				'status' => 'error',
				'title'  => __( 'No API Key', 'better-studio' ),
				'msg'    => __( 'Obtain API Key from http://www.aerisweather.com/account/apps', 'better-studio' ),
				'data'   => 'no data'
			);
		}

		// Params of URL
		$url_parts = array(
			'p=' . $location,
			'client_secret=' . $this->get_api_key(),
			'client_id=' . $this->get_app_id(),
		);

		// final URL
		$url = 'http://api.aerisapi.com/forecasts?' . implode( '&', $url_parts );

		$r_resp = $this->get_remote_data( $url );

		$output = array();

		// Try to decode the json
		$r_body = @json_decode( wp_remote_retrieve_body( $r_resp ), TRUE );
		if ( $r_body === NULL and json_last_error() !== JSON_ERROR_NONE ) {
			return array(
				'status' => 'error',
				'title'  => __( 'Data Error', 'better-studio' ),
				'msg'    => __( 'Error decoding the json from aerisweather.com', 'better-studio' ),
				'data'   => $r_resp
			);
		}


		if ( $r_body['success'] != TRUE ) {
			return array(
				'status' => 'error',
				'title'  => __( 'Data Error', 'better-studio' ),
				'msg'    => $r_body['error']['description'],
				'data'   => $r_resp
			);
		}

		$day = $r_body['response'][0]['interval'] == 'day';

		$output = array();

		//
		// Location
		//
		$output['location']['longitude'] = $r_body['response'][0]['loc']['long'];
		$output['location']['latitude']  = $r_body['response'][0]['loc']['lat'];
		$_loc                            = explode( '/', current( $r_body['response'][0]['profile'] ) );
		$output['location']['country']   = $this->pretty_name( $_loc[0] );
		$output['location']['city']      = $this->pretty_name( $_loc[1] );


		//
		// Today data
		//
		$output['today']['time']            = $r_body['response'][0]['periods'][0]['timestamp'];
		$output['today']['time_r']          = $this->get_date_translation( $output['today']['time'] );
		$output['today']['summary']         = $r_body['response'][0]['periods'][0]['weatherPrimary'];
		$output['today']['icon']            = $this->get_standard_icon( $r_body['response'][0]['periods'][0]['weatherPrimaryCoded'], $day );
		$output['today']['temperature']     = $r_body['response'][0]['periods'][0]['avgTempC'];
		$output['today']['temperature_min'] = $r_body['response'][0]['periods'][0]['maxTempC'];
		$output['today']['temperature_max'] = $r_body['response'][0]['periods'][0]['minTempC'];
		$output['today']['sunrise_time']    = $r_body['response'][0]['periods'][0]['sunrise'];
		$output['today']['sunset_time']     = $r_body['response'][0]['periods'][0]['sunset'];


		//
		// Next Days
		//
		unset( $r_body['response'][0]['periods'][0] );
		$counter = 0;
		foreach ( $r_body['response'][0]['periods'] as $day ) {

			if ( $counter > 4 ) {
				break;
			} else {
				$counter ++;
			}

			$output['next_days'][ $counter ] = array(
				'time'            => $day['timestamp'],
				'time_r'          => $this->get_date_translation( $day['timestamp'] ),
				'day_name'        => $this->get_day_translation( $day['timestamp'] ),
				'summary'         => $day['weatherPrimary'],
				'icon'            => $this->get_standard_icon( $day['weatherPrimaryCoded'] ),
				'temperature'     => $day['avgTempC'],
				'temperature_min' => $day['maxTempC'],
				'temperature_max' => $day['minTempC'],
				'sunrise_time'    => $day['sunrise'],
				'sunset_time'     => $day['sunset'],
			);
		}

		return array(
			'status' => 'succeed',
			'data'   => $output,
		);

	} // get_remote_data_forecast_io


	/**
	 * Creates standard icons from Aeris Weather condition code
	 *
	 * http://www.aerisweather.com/support/docs/api/reference/weather-codes/
	 *
	 * @param $condition_code
	 *
	 * @return string
	 */
	function get_standard_icon( $condition_code, $day = TRUE ) {

		// get first condition code
		$condition_code = str_replace( '::', '', $condition_code );
		$condition_code = explode( ':', $condition_code );
		$condition_code = end( $condition_code );

		switch ( $condition_code ) {

			case 'FW': // Fair/Mostly sunny
			case 'CL': // Clear
				if ( $day ) {
					$_icon = 'clear-day';
				} else {
					$_icon = 'clear-night';
				}
				break;


			case 'UP': // Unknown precipitation
			case 'WM': // Wintry mix (snow, sleet, rain)
			case 'RS': // Rain/snow mix
			case 'RW': // Rain showers
			case 'R': // Rain
			case 'L': // Drizzle
			case 'FR': // Frost
			case 'ZY': // Freezing spray
			case 'ZR': // Freezing rain
			case 'ZL': // Freezing drizzle
				$_icon = 'rain';
				break;

			case 'A': // Hail
			case 'SI': // Snow/sleet mix
			case 'IP': // Ice pellets / Sleet
			case 'IF': // Ice fog
			case 'IC': // Ice crystals
			case 'BY': // Blowing spray
			case 'BS': // Blowing snow
			case 'SW': // Snow showers
			case 'S': // Snow
				$_icon = 'snow';
				break;


			case 'BR': // Mist
			case 'BN': // Blowing sand
			case 'BD': // Blowing dust
				$_icon = 'wind';
				break;


			case 'WP': // Waterspouts
			case 'T': // Thunderstorms
				$_icon = 'thunderstorm';
				break;


			case 'SC': // Partly cloudy
				if ( $day ) {
					$_icon = 'partly-cloudy-day';
				} else {
					$_icon = 'partly-cloudy-night';
				}
				break;


			case 'OV': // Cloudy/Overcast
			case 'BK': // Mostly Cloudy
				$_icon = 'cloudy';
				break;

			case 'VA': // Volcanic ash
			case 'H': // Haze
			case 'K': // Smoke
			case 'ZF': // Freezing fog
			case 'F': // Fog
				$_icon = 'fog';
				break;

			default:
				$_icon = '';

		}

		return $_icon;

	} // get_standard_icon

}generator/sources/class-bw-forecast-source.php000064400000013622151214002660015544 0ustar00<?php


/**
 * Source for Forecast.io
 */
class BW_Forecast_Source extends BW_Weather_Source {

	/**
	 * Source constructor
	 *
	 * @param string $app_id
	 * @param string $api_key
	 * @param string $lang
	 */
	public function __construct( $app_id = '', $api_key = '', $lang = '' ) {
		$this->source_id = 'forecast';
		parent::__construct( $app_id, $api_key, $lang );
	}


	/**
	 * today[]
	 *      time
	 *      summary
	 *      icon
	 *      temperature
	 *      temperature_max
	 *      temperature_min
	 *      sunrise_time
	 *      sunset_time
	 *
	 *
	 * next_days[]
	 *      []
	 *          time
	 *          day_name
	 *          summary
	 *          icon
	 *          temperature
	 *          temperature_min
	 *          temperature_max
	 *          sunrise_time
	 *          sunset_time
	 *
	 * location[]
	 *      country
	 *      city
	 *      latitude
	 *      longitude
	 *
	 *
	 * @param        $location
	 * @param string $unit
	 *
	 * @return array
	 */
	function get_forecast( $location, $unit = 'c' ) {

		// Check API Key
		if ( $this->get_api_key() == '' ) {
			return array(
				'status' => 'error',
				'title'  => __( 'No API Key', 'better-studio' ),
				'msg'    => __( 'Obtain API Key from https://developers.forecast.io/', 'better-studio' ),
				'data'   => 'no data'
			);
		}

		$url = 'https://api.forecast.io/forecast/' . $this->get_api_key() . '/' . $location . '?exclude=hourly,flags,alerts,minutely';

		// retrieving forecast content
		$r_resp = $this->get_remote_data( $url );

		// Connection Error
		if ( is_wp_error( $r_resp ) || ! isset( $r_resp['body'] ) || $r_resp['body'] == FALSE ) {
			return array(
				'status' => 'error',
				'title'  => __( 'Connection Error', 'better-studio' ),
				'msg'    => __( 'No any data received from Forecast.io!.', 'better-studio' ),
				'data'   => $r_resp
			);
		}

		// incorrect API Key
		if ( wp_remote_retrieve_response_code( $r_resp ) != 200 || preg_match( '~Forbidden~A', $r_resp['body'] ) > 0 ) {
			return array(
				'status' => 'error',
				'title'  => __( 'API key is incorrect', 'better-studio' ),
				'msg'    => __( 'Please obtain API Key from https://developers.forecast.io/', 'better-studio' ),
				'data'   => __( 'no data', 'better-studio' )
			);
		}

		$r_body = @json_decode( wp_remote_retrieve_body( $r_resp ), TRUE );
		if ( $r_body === NULL and json_last_error() !== JSON_ERROR_NONE ) {
			return array(
				'status' => 'error',
				'title'  => __( 'Data Error', 'better-studio' ),
				'msg'    => __( 'Error decoding the json from Forecast.io', 'better-studio' ),
				'data'   => $r_resp
			);
		}

		// Hack for getting today min/max temperature and sunset sunrise time!
		if ( date( 'Y M d', $r_body['daily']['data'][0]['time'] ) == date( 'Y M d', $r_body['currently']['time'] ) ) {
			$past_day_data = $r_body['daily']['data'][0];
		} else {
			$_past_day_data = $this->get_remote_data( 'https://api.forecast.io/forecast/' . $this->get_api_key() . '/' . $location . ',' . strtotime( "-1 day", time() ) . '?exclude=currently,hourly,flags,alerts,minutely' );
			$_past_day_body = @json_decode( wp_remote_retrieve_body( $_past_day_data ), TRUE );

			if ( $_past_day_body === NULL and json_last_error() !== JSON_ERROR_NONE ) {
				$past_day_data = $r_body['daily']['data'][0];
			} else {
				$past_day_data = $_past_day_body['daily']['data'][0];
			}
		}

		//
		// Create result standard data
		//
		$result = array();


		//
		// Location
		//
		$result['location']['latitude']  = $r_body['latitude'];
		$result['location']['longitude'] = $r_body['longitude'];
		$timezone                        = explode( '/', $r_body['timezone'] );
		if ( isset( $timezone[0] ) ) {
			$result['location']['country'] = $this->pretty_name( $timezone[0] );
		} else {
			$result['location']['country'] = '';
		}

		if ( isset( $timezone[1] ) ) {
			$result['location']['city'] = $this->pretty_name( $timezone[1] );
		} else {
			$result['location']['city'] = '';
		}

		//
		// Today
		//
		$result['today']['time']            = $r_body['currently']['time'];
		$result['today']['time_r']          = $this->get_date_translation( $result['today']['time'] );
		$result['today']['summary']         = $this->get_translation( $r_body['currently']['summary'] );
		$result['today']['icon']            = $r_body['currently']['icon'];
		$result['today']['temperature']     = $this->convert_fahrenheit_to_celsius( $r_body['currently']['temperature'] );
		$result['today']['temperature_min'] = $this->convert_fahrenheit_to_celsius( $past_day_data['temperatureMin'] );
		$result['today']['temperature_max'] = $this->convert_fahrenheit_to_celsius( $past_day_data['temperatureMax'] );
		$result['today']['sunrise_time']    = $past_day_data['sunriseTime'];
		$result['today']['sunset_time']     = $past_day_data['sunsetTime'];


		//
		// Next days
		//
		$counter = - 1;

		unset( $r_body['daily']['data'][0] );

		foreach ( $r_body['daily']['data'] as $day ) {

			if ( $counter == - 1 ) {
				$counter ++;
				continue;
			}

			if ( $counter > 4 ) {
				break;
			} else {
				$counter ++;
			}

			$result['next_days'][ $counter ] = array(
				'time'            => $day['time'],
				'time_r'          => $this->get_date_translation( $day['time'] ),
				'day_name'        => $this->get_day_translation( $day['time'] ),
				'summary'         => $this->get_translation( $day['summary'] ),
				'icon'            => $day['icon'],
				'temperature'     => '',
				'temperature_min' => $day['temperatureMin'],
				'temperature_max' => $day['temperatureMax'],
				'sunrise_time'    => $day['sunriseTime'],
				'sunset_time'     => $day['sunriseTime'],
			);
		}

		return array(
			'status' => 'succeed',
			'data'   => $result,
		);

	} // get_remote_data_forecast_io


	/**
	 * Used to get translation id of string in panel
	 *
	 * @param $text
	 *
	 * @return string
	 */
	public function get_trans_id( $text ) {

		$id = str_replace(
			array( ".", "/", "\\", ",", " ", "-" ),
			"_",
			trim( $text )
		);

		return strtolower( 'tr_forecast_' . $id );
	}

}generator/sources/class-bw-weather-source.php000064400000007566151214002660015407 0ustar00<?php


/**
 * Base class for weather sopurces
 */
class BW_Weather_Source {

	/**
	 * Source ID used for internal actions
	 *
	 * @var string
	 */
	protected $source_id = '';

	/**
	 * App ID for source
	 *
	 * @var
	 */
	var $app_id;

	/**
	 * API key for weather source
	 *
	 * @var
	 */
	var $api_key;

	/**
	 * API secret key weather source
	 *
	 * @var
	 */
	var $secret_key;


	/**
	 * Current language for weather API
	 *
	 * @var string
	 */
	var $lang = '';


	/**
	 * Weather source constructor.
	 *
	 * @param string $app_id
	 * @param string $api_key
	 * @param string $lang
	 * @param string $secret_key
	 */
	public function __construct( $app_id = '', $api_key = '', $lang = '', $secret_key = '' ) {

		$this->app_id     = $app_id;
		$this->api_key    = $api_key;
		$this->lang       = $lang;
		$this->secret_key = $secret_key;
	}


	/**
	 * Fethces and returns forecasts data
	 *
	 * @param        $location
	 * @param string $unit
	 *
	 * @return array
	 */
	public function get_forecast( $location, $unit = 'c' ) {

		return array();
	}


	/**
	 * Returns weather API App ID
	 *
	 * @return string
	 */
	public function get_app_id() {

		return $this->app_id;
	}


	/**
	 * Returns weather API key
	 *
	 * @return string
	 */
	public function get_api_key() {

		return $this->api_key;
	}

	/**
	 * Returns weather API Secret key
	 *
	 * @return string
	 */
	public function get_secret_key() {

		return $this->secret_key;
	}


	/**
	 * Returns weather API language
	 *
	 * @return string
	 */
	public function get_lang() {

		return $this->lang;
	}


	/**
	 * Retrieves remote data
	 *
	 * @param       $url
	 * @param array $params
	 *
	 * @return array|\WP_Error
	 */
	public function get_remote_data( $url, $params = array() ) {

		return wp_remote_get( $url, $params );
	}


	/**
	 * Used to get text translation from its id
	 *
	 * @param $text
	 *
	 * @return string
	 */
	public function get_translation( $text, $trans_id = '' ) {

		if ( empty( $trans_id ) ) {
			$trans_id = $this->get_trans_id( $text );
		}

		$trans = Better_Weather::get_option( $trans_id );

		if ( is_null( $trans ) ) {
			// todo add some logging for this!
			return $text;
		} else {

			return $trans;
		}

	}


	/**
	 * Used to get readable date translation
	 *
	 * @param $time
	 *
	 * @return mixed
	 */
	public function get_date_translation( $time ) {

		$pattern = Better_Weather::get_option( 'tr_date' );

		$month  = date( "M", $time );
		$_month = date( "F", $time );

		return str_replace(
			array(
				'%%day%%',
				'%%month%%',
			),
			array(
				date( "d", $time ),
				$this->get_translation( $month, 'tr_month_' . strtolower( $_month ) ),
			),
			$pattern
		);

	}


	/**
	 * Used to get readable day name translation
	 *
	 * @param $time
	 *
	 * @return mixed
	 */
	public function get_day_translation( $time ) {

		$day = date( 'D', $time );

		return $this->get_translation( $day, 'tr_days_' . strtolower( $day ) );

	}


	/**
	 * Used to get translation id of string in panel
	 *
	 * @param $text
	 *
	 * @return string
	 */
	public function get_trans_id( $text ) {

		$id = str_replace(
			array( ".", "/", "\\", ",", " ", "-" ),
			"_",
			trim( $text )
		);

		return strtolower( 'tr_' . $this->source_id . '_' . $id );
	}


	/**
	 * Used to convert Fahrenheit to Celsius
	 *
	 * @param $temp
	 *
	 * @return int
	 */
	function convert_fahrenheit_to_celsius( $temp ) {

		return intval( ( $temp - 32 ) * 5 / 9 );
	}


	/**
	 * Used to convert Fahrenheit to Celsius
	 *
	 * @param $temp
	 *
	 * @return int
	 */
	function convert_celsius_to_fahrenheit( $temp ) {

		return $temp * 9 / 5 + 32;
	}


	/**
	 * Prettifies name
	 *
	 * @param string $name
	 *
	 * @return mixed|string
	 */
	function pretty_name( $name = '' ) {

		$name = str_replace(
			array( ".", "/", "\\", ",", " " ),
			"",
			trim( $name )
		);
		$name = str_replace(
			array( "_", "-" ),
			" ",
			trim( $name )
		);

		return $name;
	}

} // BW_Weather_Sourcegenerator/class-bw-frontend.php000064400000033242151214002660012574 0ustar00<?php


/**
 * Generate all front end codes for better weather
 *
 * IMPORTANT NOTE: Do not create directly instance from this class! just use BW_Generator_Factory factory for getting
 * instance
 */
class BW_Frontend {


	/**
	 * Stores all widgets
	 *
	 * @var array
	 */
	var $widgets = array();


	function init() {
	}


	/**
	 * Used for generating HTML attribute string
	 *
	 * @param string $id
	 * @param string $val
	 *
	 * @return string
	 */
	private function html_attr( $id = '', $val = '' ) {

		if ( is_array( $val ) ) {

			$temp_attr = '';

			foreach ( $val as $_attr_id => $_attr_value ) {
				$temp_attr .= ' ' . $_attr_value;
			}

			return $id . '="' . $temp_attr . '"';

		} else {
			return $id . '="' . $val . '"';
		}

	}


	/**
	 * Generates full attr
	 *
	 * @param $attr
	 *
	 * @return string
	 */
	private function html_attr_full( $attr ) {

		$final_attr = '';

		foreach ( $attr as $attr_id => $attr_value ) {
			$final_attr .= ' ' . $this->html_attr( $attr_id, $attr_value );
		}

		return $final_attr;
	}


	/**
	 * Generate widget
	 *
	 * @param      $options
	 * @param bool $echo
	 *
	 * @return null|string
	 */
	function generate( $options, $echo = TRUE ) {

		ob_start();

		$id                   = $this->get_unique_id();
		$this->widgets[ $id ] = $options;

		$attr       = array();
		$attr['id'] = $id;

		/*
		 * today[]
		 *      time
		 *      summary
		 *      icon
		 *      temperature
		 *      temperature_max
		 *      temperature_min
		 *      sunrise_time
		 *      sunset_time
		 *
		 *
		 * next_days[]
		 *      []
		 *          time
		 *          day_name
		 *          icon
		 *
		 * location[]
		 *      country
		 *      city
		 *      latitude
		 *      longitude
		 */

		$data = $this->get_forecast_data( $options );


		if ( $data['status'] != 'succeed' ) {

			?>
			<div class="better-weather">
				<div class="bw-error">
					<p class="bw-error-sign">&#x26a0;</p>
					<p class="bw-error-title"><?php echo $data['title']; ?></p>
					<p class="bw-error-text"><?php echo $data['msg']; ?></p>
				</div>
			</div>
			<?php

			if ( $echo ) {
				echo ob_get_clean();

				return;
			} else {
				return ob_get_clean();
			}

		}


		// Location name
		if ( ! $options['showLocation'] ) {
			$location_name = FALSE;
		} elseif ( $options['locationName'] ) {
			$location_name = $options['locationName'];
		} else {
			if ( ! empty( $data['data']['location']['city'] ) ) {
				$location_name = $data['data']['location']['city'];
			} elseif ( ! empty( $data['data']['location']['country'] ) ) {
				$location_name = $data['data']['location']['country'];
			} else {
				$location_name = FALSE; // hide it
			}

		}

		// Date
		if ( ! $options['showDate'] ) {
			$date = FALSE;
		} else {
			$date = $data['data']['today']['time_r'];
		}

		// Animated Icon
		$animated_icon = isset( $options['animatedIcons'] ) ? $options['animatedIcons'] : TRUE;
		if ( $animated_icon ) {
			$attr['class'][] = 'animated-icons';
		} else {
			$attr['class'][] = 'static-icons';
		}


		$options['mode'] = 'block';
		$attr['class'][] = 'better-weather';

		if ( $options['style'] == 'normal' ) {
			$attr['class'][] = 'style-normal';
		} else {
			$attr['class'][] = 'style-modern';
		}

		if ( ! isset( $options['naturalBackground'] ) ) {
			$attr['class'][] = 'with-natural-background';
		} elseif ( $options['naturalBackground'] ) {
			$attr['class'][] = 'with-natural-background';
		} else {
			$attr['style'][] = 'background-color:' . $options['bgColor'] . ';';
		}

		if ( $options['nextDays'] ) {
			$attr['class'][] = 'have-next-days';
		}

		// Show unit
		if ( $options['showUnit'] ) {
			$attr['class'][] = 'unit-showed';
		}

		// todo sunrise time!
		$attr['class'][] = 'state-' . $data['data']['today']['icon'];

		// Icon color & font color
		$attr['style'][]         = 'color:' . $options['fontColor'] . ';';
		$attr['data-font-color'] = $options['fontColor'];

		?>
		<div <?php echo $this->html_attr_full( $attr ); ?>>
			<div class="bw_currently">
				<div class="bw_date-loc">
					<?php if ( $location_name ) { ?>
						<span class="bw_location"><?php echo $location_name; ?></span>
					<?php } ?>

					<?php if ( $location_name && $date ) { ?>
						<span class="bw_separator">-</span>
					<?php } ?>

					<?php if ( $date ) { ?>
						<span class="bw_date"><?php echo $date; ?></span>
					<?php } ?>
				</div>

				<?php if ( $options['mode'] != 'inline' ) { ?>
					<div class="bw_degree-up-down">
						<span
								class="bw_up-degree"><?php echo $this->get_pretty_temperature( $data['data']['today']['temperature_max'], $options['unit'], $options['showUnit'] ); ?></span>
						<span
								class="bw_down-degree"><?php echo $this->get_pretty_temperature( $data['data']['today']['temperature_min'], $options['unit'], $options['showUnit'] ); ?></span>
					</div>

					<div class="bw_summary">
						<?php if ( $options['style'] == 'normal' ) { ?>
							<span
									class="bw_icon-container"><?php echo $this->get_icon_tag( $animated_icon, $id . '-summary-icon', $data['data']['today']['icon'], 85, 85 ); ?></span>
						<?php } else { ?>
							<span
									class="bw_icon-container"><?php echo $this->get_icon_tag( $animated_icon, $id . '-summary-icon', $data['data']['today']['icon'], 75, 75 ); ?></span>
						<?php } ?>
						<p><?php echo $data['data']['today']['summary']; ?></p>
					</div>

					<div class="bw_degree">
						<p><?php echo $this->get_pretty_temperature( $data['data']['today']['temperature'], $options['unit'], $options['showUnit'] ); ?></p>
					</div>

				<?php } else { ?>

					<span
							class="bw_icon-container"><?php echo $this->get_icon_tag( $animated_icon, $id . '-summary-icon', $data['data']['today']['icon'] ); ?></span>
					<span
							class="bw_temperature"><p><?php echo $this->get_pretty_temperature( $data['data']['today']['temperature'], $options['unit'], $options['showUnit'] ); ?></p></span>
					<span class="bw_summary"><p><?php echo $data['data']['today']['summary']; ?></p></span>

				<?php } ?>

			</div>

			<?php if ( $options['nextDays'] ) { ?>
				<div class="bw_days">
					<ul class="bw_days-list">
						<li class="bw_day-item bw_day-1">
							<p class="bw_day-title"><?php echo $data['data']['next_days'][1]['day_name']; ?></p>
							<span
									class="bw_icon-container"><?php echo $this->get_icon_tag( FALSE, $id . '-day1-icon', $data['data']['next_days'][1]['icon'], 17, 17 ); ?></span>
						</li>
						<li class="bw_day-item bw_day-2">
							<p class="bw_day-title"><?php echo $data['data']['next_days'][2]['day_name']; ?></p>
							<span
									class="bw_icon-container"><?php echo $this->get_icon_tag( FALSE, $id . '-day2-icon', $data['data']['next_days'][2]['icon'], 17, 17 ); ?></span>
						</li>
						<li class="bw_day-item bw_day-3">
							<p class="bw_day-title"><?php echo $data['data']['next_days'][3]['day_name']; ?></p>
							<span
									class="bw_icon-container"><?php echo $this->get_icon_tag( FALSE, $id . '-day3-icon', $data['data']['next_days'][3]['icon'], 17, 17 ); ?></span>
						</li>
						<li class="bw_day-item bw_day-4">
							<p class="bw_day-title"><?php echo $data['data']['next_days'][4]['day_name']; ?></p>
							<span
									class="bw_icon-container"><?php echo $this->get_icon_tag( FALSE, $id . '-day4-icon', $data['data']['next_days'][4]['icon'], 17, 17 ); ?></span>
						</li>
					</ul>
				</div>
				<?php

			}
			?>
			<div class="bw-loader">
				<div class="bw-loader-icon"></div>
			</div>
		</div>
		<?php

		if ( $echo ) {
			echo ob_get_clean();
		} else {
			return ob_get_clean();
		}
	}


	/**
	 * Generate widget
	 *
	 * @param      $options
	 * @param bool $echo
	 *
	 * @return mixed|void
	 */
	function generate_inline( $options, $echo = TRUE ) {


		ob_start();

		$id                   = $this->get_unique_id();
		$this->widgets[ $id ] = $options;

		$attr       = array();
		$attr['id'] = $id;


		/*
		 * today[]
		 *      time
		 *      summary
		 *      icon
		 *      temperature
		 *      temperature_max
		 *      temperature_min
		 *      sunrise_time
		 *      sunset_time
		 *
		 *
		 * next_days[]
		 *      []
		 *          time
		 *          day_name
		 *          icon
		 *
		 * location[]
		 *      country
		 *      city
		 *      latitude
		 *      longitude
		 */
		$data = $this->get_forecast_data( $options );


		if ( $data['status'] != 'succeed' ) {
			return;
		}

		// Animated Icon
		$animated_icon = isset( $options['animatedIcons'] ) ? $options['animatedIcons'] : TRUE;
		$width         = $height = '';
		if ( $animated_icon ) {

			$attr['class'][] = 'animated-icons';

			switch ( $options['inlineSize'] ) {
				case 'small':
					$width = $height = 18;
					break;
				case 'medium':
					$width = $height = 30;
					break;
				case 'large':
					$width = $height = 55;
					break;
			}

		} else {
			$attr['class'][] = 'static-icons';
		}

		// Create attr array
		$attr['class'][] = 'better-weather-inline';

		// Show unit
		if ( $options['showUnit'] ) {
			$attr['class'][] = 'unit-showed';
		}

		// size
		$attr['data-inline-size'] = $options['inlineSize'];
		$attr['class'][]          = 'bw_size-' . $options['inlineSize'];

		// todo sunrise time!
		//        $attr['class'][] = 'state-' . $data['data']['today']->icon;

		// Icon color & font color
		$attr['style'][]         = 'color:' . $options['fontColor'] . ';';
		$attr['data-font-color'] = $options['fontColor'];

		?>
		<span <?php echo $this->html_attr_full( $attr ); ?>>
		    <span
				    class="bw_icon-container"><?php echo $this->get_icon_tag( $animated_icon, $id . '-summary-icon', $data['data']['today']['icon'], $width, $height ); ?></span>
		    <span
				    class="bw_temperature"><?php echo $this->get_pretty_temperature( $data['data']['today']['temperature'], $options['unit'], $options['showUnit'] ); ?></span>
		    <span class="bw_summary"><?php echo $data['data']['today']['summary']; ?></span>
		</span>
		<?php

		if ( $echo ) {
			echo ob_get_clean();
		} else {
			return ob_get_clean();
		}
	}


	/**
	 * Used to get icon
	 *
	 * @param        $animated
	 * @param string $id
	 * @param string $icon
	 * @param string $width
	 * @param string $height
	 *
	 * @return string
	 */
	function get_icon_tag( $animated, $id = '', $icon = '', $width = '', $height = '' ) {

		if ( $animated ) {

			switch ( $icon ) {
				case 'thunderstorm':
					return $this->get_icon_tag( FALSE, $id, $icon, $width, $height );
					break;
			}

			if ( $width != '' ) {
				return '<canvas id="' . $id . '" class="bw_icon bw_svg-icon" style="height:' . $height . 'px; width:' . $width . 'px;" data-icon="' . $icon . '"></canvas>';
			} else {
				return '<canvas id="' . $id . '" class="bw_icon bw_svg-icon" data-icon="' . $icon . '"></canvas>';
			}

		} else {

			switch ( $icon ) {
				case 'clear-day':
					$_icon = 'wi-day-sunny';
					break;

				case 'clear-night':
					$_icon = 'wi-night-clear';
					break;

				case 'rain':
					$_icon = 'wi-rain';
					break;

				case 'snow':
					$_icon = 'wi-snow';
					break;

				case 'sleet':
					$_icon = 'wi-rain';
					break;

				case 'wind':
					$_icon = 'wi-strong-wind';
					break;

				case 'thunderstorm':
					$_icon = 'wi-lightning';
					break;

				case 'cloudy':
					$_icon = 'wi-cloudy';
					break;

				case 'partly-cloudy-day':
					$_icon = 'wi-day-cloudy';
					break;

				case 'partly-cloudy-night':
					$_icon = 'wi-night-cloudy';
					break;

				case 'fog':
					$_icon = 'wi-fog';
					break;
			}

			if ( ! empty( $_icon ) ) {
				return '<span id="' . $id . '" class="bw_icon hw_static-icon bw_partly-cloudy-day" ><i class="' . $_icon . '"></i></span>';
			}

		}

		return '';
	} // get_icon_tag


	/**
	 * Converts temp to pretty value!
	 *
	 * @param        $temperature
	 * @param string $unit
	 * @param bool   $show_unit
	 *
	 * @return string
	 */
	function get_pretty_temperature( $temperature, $unit = 'C', $show_unit = FALSE ) {

		$unit = strtolower( $unit );

		if ( $unit == 'f' ) {
			return intval( $this->convert_celsius_to_fahrenheit( $temperature ) ) . '°' . ( $show_unit ? ' F' : '' );
		} else {
			return intval( $temperature ) . '°' . ( $show_unit ? ' C' : '' );
		}

	}


	/**
	 * Used to convert Fahrenheit to Celsius
	 *
	 * @param $temp
	 *
	 * @return int
	 */
	function convert_fahrenheit_to_celsius( $temp ) {

		return intval( ( $temp - 32 ) * 5 / 9 );
	}


	/**
	 * Used to convert Fahrenheit to Celsius
	 *
	 * @param $temp
	 *
	 * @return int
	 */
	function convert_celsius_to_fahrenheit( $temp ) {

		return $temp * 9 / 5 + 32;
	}


	/**
	 * Generate unique id widgets
	 *
	 * @return string
	 */
	function get_unique_id() {

		return 'bw-' . uniqid();
	}


	/**
	 * Retrieved data from Forecast.io or cache and return it
	 *
	 * @param $options
	 *
	 * @return array
	 */
	public function get_forecast_data( $options ) {

		// Check location
		if ( isset( $options["location"] ) && $options["location"] != "" ) {
			$location = $options["location"];
		} else {
			$location = "35.6705,139.7409";
		}

		$visitor_location = FALSE;

		// Visitor location
		if ( isset( $options["visitorLocation"] ) && $options["visitorLocation"] ) {
			$_l = Better_Weather::get_user_geo_location();

			if ( ! empty( $_l ) ) {
				$visitor_location = TRUE;
				$location         = $_l;
			}
		}

		$api_source = Better_Weather::get_api_source();

		// If cache is older than 30min, get new data or error if triggered
		if ( ( $data = get_transient( 'bw_location_' . $api_source . '_' . str_replace( ',', '-', $location ) ) ) === FALSE || $visitor_location == TRUE ) {
			$options = new BW_Forecast_Facade();
			$data    = $options->get_forecast( $location );

			if ( $data['status'] == 'succeed' ) {
				set_transient(
					'bw_location_' . $api_source . '_' . str_replace( ',', '-', $location ),
					$data,
					MINUTE_IN_SECONDS * Better_Weather::get_option( 'cache_time' )
				);
			}
		}

		return $data;

	} // get_forecast_data

}
generator/class-bw-forecast-facade.php000064400000004622151214002660013764 0ustar00<?php


/**
 * Facade for selecting and getting data from multiple weather sources
 */
class BW_Forecast_Facade {

	/**
	 * instance of weather source
	 *
	 * @var BW_Weather_Source
	 */
	var $source;


	/**
	 * Raw ID of weather source
	 *
	 * @var string
	 */
	var $source_id = '';


	/**
	 * create correct instance of weather source
	 */
	public function __construct() {

		switch ( $this->source_id = Better_Weather::get_api_source() ) {

			// http://forecast.io/
			case 'forecasts_io':

				require_once Better_Weather::dir_path( 'includes/generator/sources/class-bw-weather-source.php' );
				require_once Better_Weather::dir_path( 'includes/generator/sources/class-bw-forecast-source.php' );

				$this->source = new BW_Forecast_Source(
					'',
					Better_Weather::get_option( 'api_key' ),
					''
				);

				break;

			// http://openweathermap.org/
			case 'owm':

				require_once Better_Weather::dir_path( 'includes/generator/sources/class-bw-weather-source.php' );
				require_once Better_Weather::dir_path( 'includes/generator/sources/class-bw-owm-source.php' );

				$this->source = new BW_OWM_Source(
					'',
					Better_Weather::get_option( 'owm_api_key' ),
					''
				);

				break;

			// http://www.aerisweather.com/
			case 'aerisweather':

				require_once Better_Weather::dir_path( 'includes/generator/sources/class-bw-weather-source.php' );
				require_once Better_Weather::dir_path( 'includes/generator/sources/class-bw-aeris-source.php' );

				$this->source = new BW_Aeris_Source(
					Better_Weather::get_option( 'aerisweather_app_id' ),
					Better_Weather::get_option( 'aerisweather_api_key' ),
					''
				);

				break;
			// https://developer.yahoo.com/weather/
			case 'yahoo':

				require_once Better_Weather::dir_path( 'includes/generator/sources/class-bw-weather-source.php' );
				require_once Better_Weather::dir_path( 'includes/generator/sources/class-bw-yahoo-source.php' );

				$this->source = new BW_Yahoo_Source(
					Better_Weather::get_option( 'yahoo_weather_app_id' ),
					Better_Weather::get_option( 'yahoo_weather_api_key' ),
					'',
					Better_Weather::get_option( 'yahoo_weather_consumer_secret' )
				);

				break;

		}


	} // __construct


	/**
	 * Retrieves forecast from source
	 *
	 * @param        $location
	 * @param string $unit
	 *
	 * @return array
	 */
	public function get_forecast( $location, $unit = 'c' ) {
		return $this->source->get_forecast( $location, $unit );
	}

}options/panel-config.php000064400000003620151214002660011310 0ustar00<?php

// Language  name for smart admin texts
$lang = bf_get_current_lang_raw();
if ( $lang != 'none' ) {
	$lang = bf_get_language_name( $lang );
} else {
	$lang = '';
}

$panel = array(
	'config'     => array(
		'parent'              => false,
		'parent_title'        => '<strong>Better</strong> Ads',
		'slug'                => 'better-studio/better-ads-manager',
		'name'                => __( 'Better Ads Manager', 'better-studio' ),
		'page_title'          => __( 'Better Ads Manager', 'better-studio' ),
		'menu_title'          => __( 'Ads Manager', 'better-studio' ),
		'capability'          => 'manage_options',
		'icon_url'            => null,
		'position'            => '59.2',
		'icon'                => '\e033',
		'exclude_from_export' => false,
	),
	'texts'      => array(
		'panel-desc-lang'     => '<p>' . __( '%s Language Ads.', 'better-studio' ) . '</p>',
		'panel-desc-lang-all' => '<p>' . __( 'All Languages Ads.', 'better-studio' ) . '</p>',
		'reset-button'        => ! empty( $lang ) ? sprintf( __( 'Reset %s Ads', 'better-studio' ), $lang ) : __( 'Reset Ads', 'better-studio' ),
		'reset-button-all'    => __( 'Reset All Ads', 'better-studio' ),
		'reset-confirm'       => ! empty( $lang ) ? sprintf( __( 'Are you sure to reset %s Ads?', 'better-studio' ), $lang ) : __( 'Are you sure to reset Ads?', 'better-studio' ),
		'reset-confirm-all'   => __( 'Are you sure to reset all Ads?', 'better-studio' ),
		'save-button'         => ! empty( $lang ) ? sprintf( __( 'Save %s Ads', 'better-studio' ), $lang ) : __( 'Save Ads', 'better-studio' ),
		'save-button-all'     => __( 'Save All Ads', 'better-studio' ),
		'save-confirm-all'    => __( 'Are you sure to save all Ads? this will override specified Ads per languages', 'better-studio' )
	),
	'panel-name' => _x( 'Better Ads Manager', 'Panel title', 'better-studio' ),
	'panel-desc' => '<p>' . __( 'Manage your ads in better way!', 'better-studio' ) . '</p>',
);
options/panel-std.php000064400000040465151214002660010645 0ustar00<?php


$fields['source-setup']     = array(
	'std' => 'Please select of of following sources and setup the API for fetching weather data from that source.',
);
$fields['forecasts_source'] = array(
	'std' => '',
);

//
// Yahoo Weather API
//
$fields['yahoo_weather_app_id']     = array(
	'std' => '',
);
$fields['yahoo_weather_api_key']    = array(
	'std' => '',
);
$fields['yahoo_weather_consumer_secret'] = array(
	'std' => '',
);

//
// Forecast.io
//
$fields['api_key'] = array(
	'std' => '',
);


//
// OWM
//
$fields['owm_api_key'] = array(
	'std' => '',
);


//
// Aeris Weather API
//
$fields['aerisweather_app_id']  = array(
	'std' => '',
);
$fields['aerisweather_api_key'] = array(
	'std' => '',
);


/**
 * => Style
 */


/**
 * => Style -> Clear Day
 */
$fields['style_all_bg_img']   = array(
	'std' => '',
);
$fields['style_all_bg_color'] = array(
	'std' => '',
);


/**
 * => Style -> Clear Day
 */
$fields['style_clear_day_bg_img']   = array(
	'std' => '',
);
$fields['style_clear_day_bg_color'] = array(
	'std' => '#599ad0',
);


/**
 * => Style -> Clear Night
 */
$fields['style_clear_night_bg_img']   = array(
	'std' => '',
);
$fields['style_clear_night_bg_color'] = array(
	'std' => '#252a26',
);


/**
 * => Style -> Rain
 */
$fields['style_rain_bg_img']   = array(
	'std' => '',
);
$fields['style_rain_bg_color'] = array(
	'std' => '#3b4963',
);


/**
 * => Style -> Snow
 */
$fields['style_snow_bg_img']   = array(
	'std' => '',
);
$fields['style_snow_bg_color'] = array(
	'std' => '#607592',
);


/**
 * => Style -> Cloudy
 */
$fields['style_cloudy_bg_img']   = array(
	'std' => '',
);
$fields['style_cloudy_bg_color'] = array(
	'std' => '#208aae',
);


/**
 * => Style -> Partly Cloudy Day
 */
$fields['style_partly_cloudy_day_bg_img']   = array(
	'std' => '',
);
$fields['style_partly_cloudy_day_bg_color'] = array(
	'std' => '#1A4192',
);


/**
 * => Style -> Partly Cloudy Night
 */
$fields['style_partly_cloudy_night_bg_img']   = array(
	'std' => '',
);
$fields['style_partly_cloudy_night_bg_color'] = array(
	'std' => '#0F0F0F',
);


/**
 * => Style -> Sunrise
 */
$fields['style_sunrise_bg_img']   = array(
	'std' => '',
);
$fields['style_sunrise_bg_color'] = array(
	'std' => '#fd654d',
);


/**
 * => Style -> Sunset
 */
$fields['style_sunset_bg_img']   = array(
	'std' => '',
);
$fields['style_sunset_bg_color'] = array(
	'std' => '#0F0F0F',
);

/**
 * => Style -> Sleet
 */
$fields['style_sleet_bg_img']   = array(
	'std' => '',
);
$fields['style_sleet_bg_color'] = array(
	'std' => '#607592',
);


/**
 * => Style -> Wind
 */
$fields['style_wind_bg_img']   = array(
	'std' => '',
);
$fields['style_wind_bg_color'] = array(
	'std' => '#607592',
);


/**
 * => Style -> Fog
 */
$fields['style_fog_bg_img']   = array(
	'std' => '',
);
$fields['style_fog_bg_color'] = array(
	'std' => '#607592',
);


/**
 * => Style -> Thunderstorm
 */
$fields['style_thunderstorm_bg_img']   = array(
	'std' => '',
);
$fields['style_thunderstorm_bg_color'] = array(
	'std' => '#47456e',
);

$fields['tr_date']            = array(
	'std' => '%%day%% %%month%%',
);
$fields['tr_month_january']   = array(
	'std' => 'January',
);
$fields['tr_month_february']  = array(
	'std' => 'February',
);
$fields['tr_month_march']     = array(
	'std' => 'March',
);
$fields['tr_month_april']     = array(
	'std' => 'April',
);
$fields['tr_month_may']       = array(
	'std' => 'May',
);
$fields['tr_month_june']      = array(
	'std' => 'June',
);
$fields['tr_month_july']      = array(
	'std' => 'July',
);
$fields['tr_month_august']    = array(
	'std' => 'August',
);
$fields['tr_month_september'] = array(
	'std' => 'September',
);
$fields['tr_month_october']   = array(
	'std' => 'October',
);
$fields['tr_month_november']  = array(
	'std' => 'November',
);
$fields['tr_month_december']  = array(
	'std' => 'December',
);

$fields['tr_days_sat'] = array(
	'std' => 'Sat',
);
$fields['tr_days_sun'] = array(
	'std' => 'Sun',
);
$fields['tr_days_mon'] = array(
	'std' => 'Mon',
);
$fields['tr_days_tue'] = array(
	'std' => 'Tue',
);
$fields['tr_days_wed'] = array(
	'std' => 'Wed',
);
$fields['tr_days_thu'] = array(
	'std' => 'Thu',
);
$fields['tr_days_fri'] = array(
	'std' => 'Fri',
);


//
// Yahoo Translation
//
$fields['tr_yahoo_tornado']                 = array(
	'std' => 'Tornado',
);
$fields['tr_yahoo_tropical_storm']          = array(
	'std' => 'Tropical Storm',
);
$fields['tr_yahoo_hurricane']               = array(
	'std' => 'Hurricane',
);
$fields['tr_yahoo_severe_thunderstorms']    = array(
	'std' => 'Severe Thunderstorms',
);
$fields['tr_yahoo_thunderstorms']           = array(
	'std' => 'Thunderstorms',
);
$fields['tr_yahoo_mixed_rain_and_snow']     = array(
	'std' => 'Mixed Rain And Snow',
);
$fields['tr_yahoo_mixed_rain_and_snow']     = array(
	'std' => 'Mixed Rain And Snow',
);
$fields['tr_yahoo_mixed_rain_and_sleet']    = array(
	'std' => 'Mixed Rain And Sleet',
);
$fields['tr_yahoo_mixed_snow_and_sleet']    = array(
	'std' => 'Mixed Snow And Sleet',
);
$fields['tr_yahoo_freezing_drizzle']        = array(
	'std' => 'Freezing Drizzle',
);
$fields['tr_yahoo_drizzle']                 = array(
	'std' => 'Drizzle',
);
$fields['tr_yahoo_freezing_rain']           = array(
	'std' => 'Freezing Rain',
);
$fields['tr_yahoo_showers']                 = array(
	'std' => 'Showers',
);
$fields['tr_yahoo_snow_flurries']           = array(
	'std' => 'Snow Flurries',
);
$fields['tr_yahoo_light_snow_showers']      = array(
	'std' => 'Light Snow Showers',
);
$fields['tr_yahoo_blowing_snow']            = array(
	'std' => 'Blowing Snow',
);
$fields['tr_yahoo_snow']                    = array(
	'std' => 'Snow',
);
$fields['tr_yahoo_hail']                    = array(
	'std' => 'Hail',
);
$fields['tr_yahoo_sleet']                   = array(
	'std' => 'Sleet',
);
$fields['tr_yahoo_dust']                    = array(
	'std' => 'Sleet',
);
$fields['tr_yahoo_haze']                    = array(
	'std' => 'Haze',
);
$fields['tr_yahoo_smoky']                   = array(
	'std' => 'Smoky',
);
$fields['tr_yahoo_blustery']                = array(
	'std' => 'Blustery',
);
$fields['tr_yahoo_windy']                   = array(
	'std' => 'Windy',
);
$fields['tr_yahoo_cold']                    = array(
	'std' => 'Cold',
);
$fields['tr_yahoo_cloudy']                  = array(
	'std' => 'Cloudy',
);
$fields['tr_yahoo_mostly_cloudy']           = array(
	'std' => 'Mostly Cloudy',
);
$fields['tr_yahoo_partly_cloudy']           = array(
	'std' => 'Partly Cloudy',
);
$fields['tr_yahoo_clear']                   = array(
	'std' => 'Clear',
);
$fields['tr_yahoo_sunny']                   = array(
	'std' => 'Sunny',
);
$fields['tr_yahoo_fair']                    = array(
	'std' => 'Fair',
);
$fields['tr_yahoo_mixed_rain_and_hail']     = array(
	'std' => 'Mixed Rain And Hail',
);
$fields['tr_yahoo_hot']                     = array(
	'std' => 'Hot',
);
$fields['tr_yahoo_isolated_thunderstorms']  = array(
	'std' => 'Isolated Thunderstorms',
);
$fields['tr_yahoo_scattered_thunderstorms'] = array(
	'std' => 'Scattered Thunderstorms',
);
$fields['tr_yahoo_scattered_showers']       = array(
	'std' => 'Scattered Showers',
);
$fields['tr_yahoo_heavy_snow']              = array(
	'std' => 'Heavy Snow',
);
$fields['tr_yahoo_scattered_snow_showers']  = array(
	'std' => 'Scattered Snow Showers',
);
$fields['tr_yahoo_thundershowers']          = array(
	'std' => 'Thundershowers',
);
$fields['tr_yahoo_snow_showers']            = array(
	'std' => 'Snow Showers',
);
$fields['tr_yahoo_isolated_thundershowers'] = array(
	'std' => 'Isolated Thundershowers',
);


//
// OWM Translation
//
$fields['tr_owm_thunderstorm_with_light_rain']    = array(
	'std' => 'Thunderstorm With Light Rain',
);
$fields['tr_owm_thunderstorm_with_rain']          = array(
	'std' => 'Thunderstorm With Rain',
);
$fields['tr_owm_thunderstorm_with_heavy_rain']    = array(
	'std' => 'Thunderstorm With Heavy Rain',
);
$fields['tr_owm_light_thunderstorm']              = array(
	'std' => 'Light Thunderstorm',
);
$fields['tr_owm_thunderstorm']                    = array(
	'std' => 'Thunderstorm',
);
$fields['tr_owm_heavy_thunderstorm']              = array(
	'std' => 'Heavy Thunderstorm',
);
$fields['tr_owm_ragged_thunderstorm']             = array(
	'std' => 'Ragged Thunderstorm',
);
$fields['tr_owm_thunderstorm_with_light_drizzle'] = array(
	'std' => 'Thunderstorm With Light Drizzle',
);
$fields['tr_owm_thunderstorm_with_drizzle']       = array(
	'std' => 'Thunderstorm With Drizzle',
);
$fields['tr_owm_thunderstorm_with_heavy_drizzle'] = array(
	'std' => 'Thunderstorm With Heavy Drizzle',
);
$fields['tr_owm_light_intensity_drizzle']         = array(
	'std' => 'Light Intensity Drizzle',
);
$fields['tr_owm_drizzle']                         = array(
	'std' => 'Drizzle',
);
$fields['tr_owm_heavy_intensity_drizzle']         = array(
	'std' => 'Heavy Intensity Drizzle',
);
$fields['tr_owm_light_intensity_drizzle_rain']    = array(
	'std' => 'Light Intensity Drizzle Rain',
);
$fields['tr_owm_drizzle_rain']                    = array(
	'std' => 'Drizzle Rain',
);
$fields['tr_owm_heavy_intensity_drizzle_rain']    = array(
	'std' => 'Heavy Intensity Drizzle Rain',
);
$fields['tr_owm_shower_rain_and_drizzle']         = array(
	'std' => 'Shower Rain And Drizzle',
);
$fields['tr_owm_heavy_shower_rain_and_drizzle']   = array(
	'std' => 'Heavy Shower Rain And Drizzle',
);
$fields['tr_owm_shower_drizzle']                  = array(
	'std' => 'Shower Drizzle',
);
$fields['tr_owm_light_rain']                      = array(
	'std' => 'Light Rain',
);
$fields['tr_owm_moderate_rain']                   = array(
	'std' => 'Moderate Rain',
);
$fields['tr_owm_heavy_intensity_rain']            = array(
	'std' => 'Heavy Intensity Rain',
);
$fields['tr_owm_very_heavy_rain']                 = array(
	'std' => 'Very Heavy Rain',
);
$fields['tr_owm_freezing_rain']                   = array(
	'std' => 'Freezing Rain',
);
$fields['tr_owm_light_intensity_shower_rain']     = array(
	'std' => 'Light Intensity Shower Rain',
);
$fields['tr_owm_shower_rain']                     = array(
	'std' => 'Shower Rain',
);
$fields['tr_owm_heavy_intensity_shower_rain']     = array(
	'std' => 'Heavy Intensity Shower Rain',
);
$fields['tr_owm_ragged_shower_rain']              = array(
	'std' => 'Ragged Shower Rain',
);
$fields['tr_owm_light_snow']                      = array(
	'std' => 'Light Snow',
);
$fields['tr_owm_snow']                            = array(
	'std' => 'Snow',
);
$fields['tr_owm_heavy_snow']                      = array(
	'std' => 'Heavy Snow',
);
$fields['tr_owm_sleet']                           = array(
	'std' => 'Sleet',
);
$fields['tr_owm_shower_sleet']                    = array(
	'std' => 'Shower Sleet',
);
$fields['tr_owm_light_rain_and_snow']             = array(
	'std' => 'Light Rain And Snow',
);
$fields['tr_owm_rain_and_snow']                   = array(
	'std' => 'Rain And Snow',
);
$fields['tr_owm_light_shower_snow']               = array(
	'std' => 'Light Shower Snow',
);
$fields['tr_owm_shower_snow']                     = array(
	'std' => 'Shower Snow',
);
$fields['tr_owm_heavy_shower_snow']               = array(
	'std' => 'Heavy Shower Snow',
);
$fields['tr_owm_mist']                            = array(
	'std' => 'Mist',
);
$fields['tr_owm_smoke']                           = array(
	'std' => 'Smoke',
);
$fields['tr_owm_haze']                            = array(
	'std' => 'Haze',
);
$fields['tr_owm_sand']                            = array(
	'std' => 'Sand',
);
$fields['tr_owm_fog']                             = array(
	'std' => 'Fog',
);
$fields['tr_owm_dust_whirls']                     = array(
	'std' => 'Dust Whirls',
);
$fields['tr_owm_dust']                            = array(
	'std' => 'Dust',
);
$fields['tr_owm_volcanic_ash']                    = array(
	'std' => 'Volcanic Ash',
);
$fields['tr_owm_squalls']                         = array(
	'std' => 'Squalls',
);
$fields['tr_owm_tornado']                         = array(
	'std' => 'Tornado',
);
$fields['tr_owm_clear_sky']                       = array(
	'std' => 'Clear Sky',
);
$fields['tr_owm_few_clouds']                      = array(
	'std' => 'Few Clouds',
);
$fields['tr_owm_scattered_clouds']                = array(
	'std' => 'Scattered Clouds',
);
$fields['tr_owm_broken_clouds']                   = array(
	'std' => 'Broken Clouds',
);
$fields['tr_owm_overcast_clouds']                 = array(
	'std' => 'Overcast Clouds',
);
$fields['tr_owm_tropical_storm']                  = array(
	'std' => 'Tropical Storm',
);
$fields['tr_owm_hurricane']                       = array(
	'std' => 'Hurricane',
);
$fields['tr_owm_cold']                            = array(
	'std' => 'Cold',
);
$fields['tr_owm_hot']                             = array(
	'std' => 'Hot',
);
$fields['tr_owm_windy']                           = array(
	'std' => 'Windy',
);
$fields['tr_owm_hail']                            = array(
	'std' => 'Hail',
);
$fields['tr_owm_calm']                            = array(
	'std' => 'Calm',
);
$fields['tr_owm_light_breeze']                    = array(
	'std' => 'Light Breeze',
);
$fields['tr_owm_gentle_breeze']                   = array(
	'std' => 'Gentle Breeze',
);
$fields['tr_owm_moderate_breeze']                 = array(
	'std' => 'Moderate Breeze',
);
$fields['tr_owm_fresh_breeze']                    = array(
	'std' => 'Fresh Breeze',
);
$fields['tr_owm_strong_breeze']                   = array(
	'std' => 'Strong Breeze',
);
$fields['tr_owm_high_wind']                       = array(
	'std' => 'High Wind',
);
$fields['tr_owm_near_gale']                       = array(
	'std' => 'Near Gale',
);
$fields['tr_owm_gale']                            = array(
	'std' => 'Gale',
);
$fields['tr_owm_severe_gale']                     = array(
	'std' => 'Severe Gale',
);
$fields['tr_owm_storm']                           = array(
	'std' => 'Storm',
);
$fields['tr_owm_violent_storm']                   = array(
	'std' => 'Violent Storm',
);
$fields['tr_owm_hurricane']                       = array(
	'std' => 'Hurricane',
);


//
// Forecast.io Translation
//
$fields['tr_forecast_clear']                    = array(
	'std' => 'Clear',
);
$fields['tr_forecast_rain']                     = array(
	'std' => 'Rain',
);
$fields['tr_forecast_light_rain']               = array(
	'std' => 'Light Rain',
);
$fields['tr_forecast_drizzle']                  = array(
	'std' => 'Drizzle',
);
$fields['tr_forecast_light_rain_and_windy']     = array(
	'std' => 'Light Rain And Windy',
);
$fields['tr_forecast_flurries']                 = array(
	'std' => 'Flurries',
);
$fields['tr_forecast_flurries_df']              = array(
	'std' => 'Flurries DF',
);
$fields['tr_forecast_cloudy']                   = array(
	'std' => 'Cloudy',
);
$fields['tr_forecast_mostly_cloudy']            = array(
	'std' => 'Mostly Cloudy',
);
$fields['tr_forecast_partly_cloudy']            = array(
	'std' => 'Partly Cloudy',
);
$fields['tr_forecast_snow']                     = array(
	'std' => 'Snow',
);
$fields['tr_forecast_light_snow']               = array(
	'std' => 'Light Snow',
);
$fields['tr_forecast_snow_and_breezy']          = array(
	'std' => 'Snow and Breezy',
);
$fields['tr_forecast_snow_and_windy']           = array(
	'std' => 'Snow and Windy',
);
$fields['tr_forecast_sleet']                    = array(
	'std' => 'Sleet',
);
$fields['tr_forecast_wind']                     = array(
	'std' => 'Wind',
);
$fields['tr_forecast_windy_and_mostly_cloudy']  = array(
	'std' => 'Windy And Most Cloudy',
);
$fields['tr_forecast_foggy']                    = array(
	'std' => 'Foggy',
);
$fields['tr_forecast_thunderstorm']             = array(
	'std' => 'Thunderstorm',
);
$fields['tr_forecast_overcast']                 = array(
	'std' => 'Overcast',
);
$fields['tr_forecast_overcast_df']              = array(
	'std' => 'Overcast DF',
);
$fields['tr_forecast_breezy_and_partly_cloudy'] = array(
	'std' => 'Breezy and Partly Cloudy',
);
$fields['tr_forecast_breezy_and_mostly_cloudy'] = array(
	'std' => 'Breezy and Mostly Cloudy',
);
$fields['tr_forecast_breezy_and_overcast']      = array(
	'std' => 'Breezy and Overcast',
);
$fields['tr_forecast_humid_and_mostly_cloudy']  = array(
	'std' => 'Humid and Mostly Cloudy',
);
$fields['tr_forecast_dry_and_partly_cloudy']    = array(
	'std' => 'Dry and Partly Cloudy',
);
$fields['tr_forecast_dry_and_partly_cloudy_df'] = array(
	'std' => 'Dry and Partly Cloudy',
);
$fields['tr_forecast_dry_and_mostly_cloudy']    = array(
	'std' => 'Dry and Mostly Cloudy',
);
$fields['tr_forecast_dry_and_mostly_cloudy_df'] = array(
	'std' => 'Dry and Mostly Cloudy DF',
);


//
// Caching Options
//
$fields['cache_time'] = array(
	'std' => 30,
);
options/panel-css.php000064400000042604151214002660010640 0ustar00<?php

$fields['style_all_bg_img']   = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-clear-day.state-clear-day',
				'.better-weather.with-natural-background.state-clear-night.state-clear-night',
				'.better-weather.with-natural-background.state-rain.state-rain',
				'.better-weather.with-natural-background.state-snow.state-snow',
				'.better-weather.with-natural-background.state-sleet.state-sleet',
				'.better-weather.with-natural-background.state-wind.state-wind',
				'.better-weather.with-natural-background.state-fog.state-fog',
				'.better-weather.with-natural-background.state-thunderstorm.state-thunderstorm',
				'.better-weather.with-natural-background.state-cloudy.state-cloudy',
				'.better-weather.with-natural-background.state-partly-cloudy-day.state-partly-cloudy-day',
				'.better-weather.with-natural-background.state-partly-cloudy-night.state-partly-cloudy-night',
				'.better-weather.with-natural-background.state-sunrise.state-sunrise',
				'.better-weather.with-natural-background.state-sunset.state-sunset',
				'.better-weather.with-natural-background.state-sunset.state-sunset[max-width~="400px"]'
			),
			'prop'     => array( 'background-image' => '%%value%%; background-position: center center !important;' ),
			'type'     => 'background-image'
		)
	)
);
$fields['style_all_bg_color'] = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-clear-day.state-clear-day',
				'.better-weather.with-natural-background.state-clear-night.state-clear-night',
				'.better-weather.with-natural-background.state-rain.state-rain',
				'.better-weather.with-natural-background.state-snow.state-snow',
				'.better-weather.with-natural-background.state-sleet.state-sleet',
				'.better-weather.with-natural-background.state-wind.state-wind',
				'.better-weather.with-natural-background.state-fog.state-fog',
				'.better-weather.with-natural-background.state-thunderstorm.state-thunderstorm',
				'.better-weather.with-natural-background.state-cloudy.state-cloudy',
				'.better-weather.with-natural-background.state-partly-cloudy-day.state-partly-cloudy-day',
				'.better-weather.with-natural-background.state-partly-cloudy-night.state-partly-cloudy-night',
				'.better-weather.with-natural-background.state-sunrise.state-sunrise',
				'.better-weather.with-natural-background.state-sunset.state-sunset',
				'.better-weather.with-natural-background.state-sunset.state-sunset[max-width~="400px"]'
			),
			'prop'     => 'background-color'
		)
	)
);


/**
 * => Style -> Clear Day
 */
$fields['style_clear_day_bg_img']   = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-clear-day.state-clear-day'
			),
			'prop'     => array( 'background-image' => '%%value%%; background-position: center center !important;' ),
			'type'     => 'background-image'
		)
	)
);
$fields['style_clear_day_bg_color'] = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-clear-day.state-clear-day',
			),
			'prop'     => 'background-color'
		)
	)
);


/**
 * => Style -> Clear Night
 */
$fields['style_clear_night_bg_img']   = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-clear-night.state-clear-night'
			),
			'prop'     => array( 'background-image' => '%%value%%; background-position: center center !important;' ),
			'type'     => 'background-image'
		)
	)
);
$fields['style_clear_night_bg_color'] = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-clear-night.state-clear-night',
			),
			'prop'     => 'background-color'
		)
	)
);


/**
 * => Style -> Rain
 */
$fields['style_rain_bg_img']   = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-rain.state-rain'
			),
			'prop'     => array( 'background-image' => '%%value%%; background-position: center center !important;' ),
			'type'     => 'background-image'
		)
	)
);
$fields['style_rain_bg_color'] = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-rain.state-rain',
			),
			'prop'     => 'background-color'
		)
	)
);


/**
 * => Style -> Snow
 */
$fields['style_snow_bg_img']   = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-snow.state-snow'
			),
			'prop'     => array( 'background-image' => '%%value%%; background-position: center center !important;' ),
			'type'     => 'background-image'
		)
	)
);
$fields['style_snow_bg_color'] = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-snow.state-snow',
			),
			'prop'     => 'background-color'
		)
	)
);


/**
 * => Style -> Cloudy
 */
$fields['style_cloudy_bg_img']   = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-cloudy.state-cloudy.state-cloudy.state-cloudy'
			),
			'prop'     => array( 'background-image' => '%%value%%; background-position: center center !important;' ),
			'type'     => 'background-image',
			'after'    => '
					.better-weather.with-natural-background.state-cloudy.state-cloudy.style-modern[max-width~="170px"],
					.better-weather.with-natural-background.state-cloudy.state-cloudy.style-normal[max-width~="170px"],
					.better-weather.with-natural-background.state-cloudy.state-cloudy.style-normal[max-width~="300px"],
					.better-weather.with-natural-background.state-cloudy.state-cloudy.style-modern[max-width~="300px"],
					.better-weather.with-natural-background.state-cloudy.state-cloudy.style-normal[max-width~="400px"],
					.better-weather.with-natural-background.state-cloudy.state-cloudy.style-modern[max-width~="400px"],
					.better-weather.with-natural-background.state-cloudy.state-cloudy.style-normal[max-width~="400px"],
					.better-weather.with-natural-background.state-cloudy.state-cloudy.style-modern[max-width~="400px"],
					.better-weather.with-natural-background.state-cloudy.state-cloudy[max-width~="550px"],
					.better-weather.with-natural-background.state-cloudy.state-cloudy[max-width~="650px"],
					.better-weather.with-natural-background.state-cloudy.state-cloudy[max-width~="830px"],
					.better-weather.with-natural-background.state-cloudy.state-cloudy[max-width~="970px"],
					.better-weather.with-natural-background.state-cloudy.state-cloudy[max-width~="1170px"]
					 {
  background-position: center center !important; }',
		)
	),
);
$fields['style_cloudy_bg_color'] = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-cloudy.state-cloudy',
			),
			'prop'     => 'background-color'
		)
	)
);


/**
 * => Style -> Partly Cloudy Day
 */
$fields['style_partly_cloudy_day_bg_img']   = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-partly-cloudy-day.state-partly-cloudy-day'
			),
			'prop'     => array( 'background-image' => '%%value%%; background-position: center center !important;' ),
			'type'     => 'background-image',
			'after'    => '
					.better-weather.with-natural-background.state-partly-cloudy-day.state-partly-cloudy-day[max-width~="830px"],
					.better-weather.with-natural-background.state-partly-cloudy-day.state-partly-cloudy-day[max-width~="170px"],
					.better-weather.with-natural-background.state-partly-cloudy-day.state-partly-cloudy-day[max-width~="100px"],
					.better-weather.with-natural-background.state-partly-cloudy-day.state-partly-cloudy-day[max-width~="970px"],
					.better-weather.with-natural-background.state-partly-cloudy-day.state-partly-cloudy-day[max-width~="1170px"]{ background-position: center center !important; }',
		)
	),
);
$fields['style_partly_cloudy_day_bg_color'] = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-partly-cloudy-day.state-partly-cloudy-day',
			),
			'prop'     => 'background-color'
		)
	)
);


/**
 * => Style -> Partly Cloudy Night
 */
$fields['style_partly_cloudy_night_bg_img']   = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-partly-cloudy-night.state-partly-cloudy-night'
			),
			'prop'     => array( 'background-image' => '%%value%%; background-position: center center !important;' ),
			'type'     => 'background-image',
			'after'    => '
					.better-weather.with-natural-background.state-partly-cloudy-night.state-partly-cloudy-night.have-next-days[max-width~="400px"],
					.better-weather.with-natural-background.state-partly-cloudy-night.state-partly-cloudy-night[max-width~="1170px"]{ background-position: center center !important; }',
		)
	),
);
$fields['style_partly_cloudy_night_bg_color'] = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-partly-cloudy-night.state-partly-cloudy-night',
			),
			'prop'     => 'background-color'
		)
	)
);


/**
 * => Style -> Sunrise
 */
$fields['style_sunrise_bg_img']   = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-sunrise.state-sunrise'
			),
			'prop'     => array( 'background-image' => '%%value%%; background-position: center center !important;' ),
			'type'     => 'background-image',
			'after'    => '
					.better-weather.with-natural-background.state-sunrise.state-sunrise[max-width~="970px"],
					.better-weather.with-natural-background.state-sunrise.state-sunrise[max-width~="870px"],
					.better-weather.with-natural-background.state-sunrise.state-sunrise[max-width~="770px"],
					.better-weather.with-natural-background.state-sunrise.state-sunrise[max-width~="670px"],
					.better-weather.with-natural-background.state-sunrise.state-sunrise.style-modern[max-width~="400px"],
					.better-weather.with-natural-background.state-sunrise.state-sunrise.style-normal[max-width~="400px"],
					.better-weather.with-natural-background.state-sunrise.state-sunrise.style-modern[max-width~="300px"],
					.better-weather.with-natural-background.state-sunrise.state-sunrise.style-normal[max-width~="300px"],
					.better-weather.with-natural-background.state-sunrise.state-sunrise.style-modern[max-width~="170px"],
					.better-weather.with-natural-background.state-sunrise.state-sunrise.style-normal[max-width~="170px"],
					.better-weather.with-natural-background.state-sunrise.state-sunrise.have-next-days[max-width~="100px"],
					.better-weather.with-natural-background.state-sunrise.state-sunrise[max-width~="100px"],
					.better-weather.with-natural-background.state-sunrise.state-sunrise[max-width~="1070px"],
					.better-weather.with-natural-background.state-sunrise.state-sunrise[max-width~="1170px"]{ background-position: center center !important; }',
		)
	),
);
$fields['style_sunrise_bg_color'] = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-sunrise.state-sunrise',
			),
			'prop'     => 'background-color'
		)
	)
);


/**
 * => Style -> Sunset
 */
$fields['style_sunset_bg_img']   = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-sunset.state-sunset',
				'.better-weather.with-natural-background.state-sunset.state-sunset[max-width~="400px"]'
			),
			'prop'     => array(
				'background-image' => '%%value%% !important; background-position: center center !important;',
			),
			'type'     => 'background-image',
			'after'    => '
					.better-weather.with-natural-background.state-sunset.state-sunset[max-width~="970px"],
					.better-weather.with-natural-background.state-sunset.state-sunset[max-width~="870px"],
					.better-weather.with-natural-background.state-sunset.state-sunset[max-width~="770px"],
					.better-weather.with-natural-background.state-sunset.state-sunset[max-width~="670px"],
					.better-weather.with-natural-background.state-sunset.state-sunset[max-width~="570px"],
					.better-weather.with-natural-background.state-sunset.state-sunset[max-width~="470px"],
					.better-weather.with-natural-background.state-sunset.state-sunset[max-width~="400px"],
					.better-weather.with-natural-background.state-sunset.state-sunset.have-next-days[max-width~="400px"],
					.better-weather.with-natural-background.state-sunset.state-sunset[max-width~="350px"],
					.better-weather.with-natural-background.state-sunset.state-sunset[max-width~="300px"],
					.better-weather.with-natural-background.state-sunset.state-sunset.have-next-days[max-width~="250px"],
					.better-weather.with-natural-background.state-sunset.state-sunset[max-width~="250px"],
					.better-weather.with-natural-background.state-sunset.state-sunset[max-width~="200px"],
					.better-weather.with-natural-background.state-sunset.state-sunset.have-next-days[max-width~="200px"],
					.better-weather.with-natural-background.state-sunset.state-sunset.have-next-days[max-width~="170px"],
					.better-weather.with-natural-background.state-sunset.state-sunset.have-next-days[max-width~="470px"],
					.better-weather.with-natural-background.state-sunset.state-sunset[max-width~="170px"],
					.better-weather.with-natural-background.state-sunset.state-sunset[max-width~="120px"],
					.better-weather.with-natural-background.state-sunset.state-sunset.have-next-days[max-width~="120px"],
					.better-weather.with-natural-background.state-sunset.state-sunset[max-width~="1070px"]{background-position: center center !important; }',
		),
	),
);
$fields['style_sunset_bg_color'] = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-sunset.state-sunset',
			),
			'prop'     => 'background-color'
		)
	)
);

/**
 * => Style -> Sleet
 */
$fields['style_sleet_bg_img']   = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-sleet.state-sleet'
			),
			'prop'     => array( 'background-image' => '%%value%%; background-position: center center !important;' ),
			'type'     => 'background-image'
		)
	)
);
$fields['style_sleet_bg_color'] = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-sleet.state-sleet',
			),
			'prop'     => 'background-color'
		)
	)
);


/**
 * => Style -> Wind
 */
$fields['style_wind_bg_img']   = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-wind.state-wind'
			),
			'prop'     => array( 'background-image' => '%%value%%; background-position: center center !important;' ),
			'type'     => 'background-image'
		)
	)
);
$fields['style_wind_bg_color'] = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-wind.state-wind',
			),
			'prop'     => 'background-color'
		)
	)
);


/**
 * => Style -> Fog
 */
$fields['style_fog_bg_img']   = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-fog.state-fog'
			),
			'prop'     => array( 'background-image' => '%%value%%; background-position: center center !important;' ),
			'type'     => 'background-image'
		)
	)
);
$fields['style_fog_bg_color'] = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-fog.state-fog',
			),
			'prop'     => 'background-color'
		)
	)
);


/**
 * => Style -> Thunderstorm
 */
$fields['style_thunderstorm_bg_img']   = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-thunderstorm.state-thunderstorm'
			),
			'after'    => '
					 .better-weather.with-natural-background.state-thunderstorm.state-thunderstorm[max-width~="970px"],
					 .better-weather.have-next-days.with-natural-background.state-thunderstorm.state-thunderstorm[max-width~="970px"],
					 .better-weather.with-natural-background.state-thunderstorm.state-thunderstorm[max-width~="830px"],
					 .better-weather.with-natural-background.state-thunderstorm.state-thunderstorm[max-width~="650px"],
					 .better-weather.with-natural-background.state-thunderstorm.state-thunderstorm[max-width~="550px"],
					 .better-weather.with-natural-background.state-thunderstorm.state-thunderstorm.style-modern[max-width~="400px"],
					 .better-weather.with-natural-background.state-thunderstorm.state-thunderstorm.style-normal[max-width~="400px"],
					 .better-weather.with-natural-background.state-thunderstorm.state-thunderstorm.style-modern[max-width~="300px"],
					 .better-weather.with-natural-background.state-thunderstorm.state-thunderstorm.style-normal[max-width~="300px"],
					 .better-weather.with-natural-background.state-thunderstorm.state-thunderstorm.style-modern[max-width~="170px"],
					 .better-weather.with-natural-background.state-thunderstorm.state-thunderstorm.style-normal[max-width~="170px"],
					 .better-weather.with-natural-background.state-thunderstorm.state-thunderstorm.style-normal[max-width~="100px"],
					 .better-weather.with-natural-background.state-thunderstorm.state-thunderstorm.style-modern[max-width~="100px"]
					 {
  background-position: center center !important; }',
			'prop'     => array( 'background-image' => '%%value%%; background-position: center center !important;' ),
			'type'     => 'background-image'
		)
	)
);
$fields['style_thunderstorm_bg_color'] = array(
	'css' => array(
		array(
			'selector' => array(
				'.better-weather.with-natural-background.state-thunderstorm.state-thunderstorm',
			),
			'prop'     => 'background-color'
		)
	)
);
options/panel-fields.php000064400000173310151214002660011315 0ustar00<?php


/**
 * 5.1. => General Options
 */
$fields[] = array(
	'name' => __( 'API Key', 'better-studio' ),
	'id'   => 'bw_settings',
	'type' => 'tab',
	'icon' => 'bsai-key'
);


$fields['source-setup'] = array(
	'name'          => __( 'Select Weather Source', 'better-studio' ),
	'id'            => 'source-setup',
	'type'          => 'info',
	'std'           => 'Please select of of following sources and setup the API for fetching weather data from that source.',
	'state'         => 'open',
	'info-type'     => 'warning',
	'section_class' => 'widefat',
);


$fields['forecasts_source'] = array(
	'name'    => __( 'Forecasts Source', 'better-studio' ),
	'id'      => 'forecasts_source',
	'type'    => 'select',
	'options' => array(
		''             => __( 'Automatic - First source was setup', 'better-studio' ),
		'yahoo'        => __( 'Yahoo Weather', 'better-studio' ),
		'forecasts_io' => __( 'Forecasts.io', 'better-studio' ),
		'owm'          => __( 'Open Weather Map', 'better-studio' ),
		'aerisweather' => __( 'Aeris Weather', 'better-studio' ),
	)
);

//
// Yahoo Weather
//
$fields[] = array(
	'name'  => __( 'Yahoo Weather API Key', 'better-studio' ),
	'type'  => 'group',
	'state' => 'close',
);

$fields['yahoo_weather_app_id'] = array(
	'name' => __( 'App ID', 'better-studio' ),
	'id'   => 'yahoo_weather_app_id',
	'desc' => __( 'Enter your own API Key for Forecast.io', 'better-weather' ),
	'type' => 'text',
);

$fields['yahoo_weather_api_key'] = array(
	'name' => __( 'API Key', 'better-studio' ),
	'id'   => 'yahoo_weather_api_key',
	'desc' => __( 'Enter your own API Key for Forecast.io', 'better-weather' ),
	'type' => 'text',
);

$fields['yahoo_weather_consumer_secret'] = array(
	'name' => __( 'Secret Key', 'better-studio' ),
	'id'   => 'yahoo_weather_consumer_secret',
	'desc' => __( 'Enter your own Consumer Secret', 'better-weather' ),
	'type' => 'text',
);

$fields[] = array(
	'name'          => __( 'How to get your own API key!?', 'better-studio' ),
	'id'            => 'qeris-help',
	'type'          => 'info',
	'std'           => '<p>' . __( 'For showing forecast you should get a free API ID and App Key with a simple sign up to the site.', 'better-studio' ) .

	                   '</p><ol><li>' . __( 'You’ll need to <a href="https://login.yahoo.com/account/create?specId=yidReg&altreg=0" target="_blank">create a Yahoo account</a> to set up applications on the Yahoo Developer Network (YDN).', 'better-studio' ) . '</li>
    <li>After you have a Yahoo account, "<a href="https://developer.yahoo.com/apps/create/" target="_blank"><strong>create an application</strong></a>"  to get your Client ID (Consumer Key) and Client Secret (Consumer Secret) for later use in the OpenID Connect / OAuth 2.0 flows.
    <br><br>
    <img class="aligncenter" src="' . Better_Weather::dir_url() . 'img/setup/sign-up-yahoo.png"><br></li>
    <li>Fill form in opened page and hit the <strong>NEXR</strong> button.</li>
    <li>in the <strong>Create Application</strong>  form, provide an application name and a callback domain. The callback domain is where Yahoo will send responses to your authentication request, so you’ll want to be the domain owner.
    <br><br>
    <img class="aligncenter" src="' . Better_Weather::dir_url() . 'img/setup/yahoo-create-app.png"><br></li>
    <li>If your application needs to access private user data from Yahoo APIs, you’ll need to request permissions to Yahoo APIs in the checklist under <strong>API Permissions.</strong> For the purpose of demonstration in this getting started, check <strong>Mail</strong> and then select <strong>Read</strong>.
  </ol>
',
	'state'         => 'open',
	'info-type'     => 'help',
	'section_class' => 'widefat',
);

//
// Forecast.io
//
$fields[]          = array(
	'name'  => __( 'Forecast.io API Key', 'better-studio' ),
	'type'  => 'group',
	'state' => 'close',
);
$fields['api_key'] = array(
	'name' => __( 'API Key', 'better-studio' ),
	'id'   => 'api_key',
	'desc' => __( 'Enter your own API Key for Forecast.io', 'better-weather' ),
	'type' => 'text',
);
$fields[]          = array(
	'name'          => __( 'How to get your own API key!?', 'better-studio' ),
	'id'            => 'forecasts-io-help',
	'type'          => 'info',
	'std'           => '<p>' . __( 'For showing forecast you should get a free API key with a simple sign up to the site.', 'better-studio' ) .

	                   '</p><ol><li>' . __( 'Go to <a href="http://goo.gl/d1d6Ji" target="_blank">https://developer.forecast.io/register</a> and Sing up', 'better-studio' ) . '<br><br><img class="aligncenter" src="' . Better_Weather::dir_url() . 'img/help-singup-page.png"><br></li>
    <li>After you can see your API Key in bottom of page.<br><br><img class="aligncenter" src="' . Better_Weather::dir_url() . 'img/help-singup-page-api.png"><br></li>
    <li>Copy "API Key" and paste that in upper input box.</li>
  </ol>

',
	'state'         => 'open',
	'info-type'     => 'help',
	'section_class' => 'widefat',
);

//
// OWM
//
$fields[]              = array(
	'name'  => __( 'Open Weather Map API Key', 'better-studio' ),
	'type'  => 'group',
	'state' => 'close',
);
$fields['owm_api_key'] = array(
	'name' => __( 'API Key', 'better-studio' ),
	'id'   => 'owm_api_key',
	'desc' => __( 'Enter your own API Key for Forecast.io', 'better-weather' ),
	'type' => 'text',
);
$fields[]              = array(
	'name'          => __( 'How to get your own API key!?', 'better-studio' ),
	'id'            => 'owm-help',
	'type'          => 'info',
	'std'           => '<p>' . __( 'For showing forecast you should get a free API key with a simple sign up to the site.', 'better-studio' ) .

	                   '</p><ol><li>' . __( 'Go to <a href="https://goo.gl/eFj0DF" target="_blank">https://home.openweathermap.org/users/sign_up</a> and Sing up', 'better-studio' ) . '</li>
    <li>In next page enter and name for company field and select "Weather widget for web" in purpose filed and hit the save button..<br><br><img class="aligncenter" src="' . Better_Weather::dir_url() . 'img/setup/owm-1.jpg"><br></li>
    <li>In next page go to the "API Keys" tab and copy Key.<br><br><img class="aligncenter" src="' . Better_Weather::dir_url() . 'img/setup/owm-2.jpg"><br></li>
    <li>Paste that in upper input box.</li>
  </ol>
',
	'state'         => 'open',
	'info-type'     => 'help',
	'section_class' => 'widefat',
);


//
// Aeris Weather API
//
$fields[]                       = array(
	'name'  => __( 'Aeris Weather API Key', 'better-studio' ),
	'type'  => 'group',
	'state' => 'close',
);
$fields['aerisweather_app_id']  = array(
	'name' => __( 'App ID', 'better-studio' ),
	'id'   => 'aerisweather_app_id',
	'desc' => __( 'Enter your own API Key for Forecast.io', 'better-weather' ),
	'type' => 'text',
);
$fields['aerisweather_api_key'] = array(
	'name' => __( 'API Key', 'better-studio' ),
	'id'   => 'aerisweather_api_key',
	'desc' => __( 'Enter your own API Key for Forecast.io', 'better-weather' ),
	'type' => 'text',
);
$fields[]                       = array(
	'name'          => __( 'How to get your own API key!?', 'better-studio' ),
	'id'            => 'qeris-help',
	'type'          => 'info',
	'std'           => '<p>' . __( 'For showing forecast you should get a free API ID and App Key with a simple sign up to the site.', 'better-studio' ) .

	                   '</p><ol><li>' . __( 'Go to <a href="http://goo.gl/hNygjr" target="_blank">http://www.aerisweather.com/signup/</a> and Sing up as Free API Developer.', 'better-studio' ) . '</li>
    <li>In next page click on "<strong>Checkout</strong>" button.</li>
    <li>Fill form in opened page and hit the <strong>NEXR</strong> button.</li>
    <li>Click on <strong>Here</strong> button on next page<br><br><img class="aligncenter" src="' . Better_Weather::dir_url() . 'img/setup/aeris-1.jpg"><br></li>
    <li>Go to Apss tab on opened page and hit the <strong>NEW APPLICATION</strong> Button.<br><br><img class="aligncenter" src="' . Better_Weather::dir_url() . 'img/setup/aeris-2.jpg"><br></li>
    <li>Fill the opened form and hit the <strong>SAVE APP</strong> button.<br><br><img class="aligncenter" src="' . Better_Weather::dir_url() . 'img/setup/aeris-3.jpg"><br></li>
    <li>Refresh the page, Then copy the ID and paste it to upper APP ID field and copy secret and paste it to APP Key field. <strong>SAVE APP</strong> button.<br><br><img class="aligncenter" src="' . Better_Weather::dir_url() . 'img/setup/aeris-4.jpg"><br></li>
  </ol>
',
	'state'         => 'open',
	'info-type'     => 'help',
	'section_class' => 'widefat',
);


/**
 * => Style
 */
$fields[] = array(
	'name'  => __( 'Style', 'better-studio' ),
	'id'    => 'style',
	'type'  => 'tab',
	'icon'  => 'bsai-paint',
	'badge' => array(
		'text'  => __( 'New', 'better-studio' ),
		'color' => '#F47878'
	)
);

$fields[] = array(
	'name'          => __( 'How to customize forecasts style!?', 'better-studio' ),
	'id'            => 'style-help',
	'type'          => 'info',
	'std'           => '<p>' . __( 'You can customize background image and color of all forecasts and also each of them separately.', 'better-studio' ) .

	                   '</p><ul><li><strong>' . __( 'Change All of forecasts:', 'better-studio' ) . '</strong>
    ' . __( 'Use options inside following <strong>All Forecasts Style</strong> option group.', 'better-studio' ) . '</li>

    <li><strong>' . __( 'Customize Each Forecast Style:', 'better-studio' ) . '</strong>
    ' . __( 'Use options inside each forecast option group.', 'better-studio' ) . '</li>
  </ul>

',
	'state'         => 'open',
	'info-type'     => 'help',
	'section_class' => 'widefat',
);


/**
 * => Style -> Clear Day
 */
$fields[]                     = array(
	'name'  => __( 'All Forecasts Style', 'better-studio' ),
	'type'  => 'group',
	'state' => 'close',
);
$fields['style_all_bg_img']   = array(
	'name'         => __( 'Background Image', 'better-studio' ),
	'id'           => 'style_all_bg_img',
	'type'         => 'background_image',
	'upload_label' => __( 'Upload Image', 'better-studio' ),
	'desc'         => __( 'Customize <strong>All Forecasts</strong> background image.', 'better-studio' ),
);
$fields['style_all_bg_color'] = array(
	'name' => __( 'Background Color', 'better-studio' ),
	'id'   => 'style_all_bg_color',
	'type' => 'color',
	'desc' => __( 'Customize <strong>All Forecasts</strong> background color.', 'better-studio' ),
);


/**
 * => Style -> Clear Day
 */
$fields[]                           = array(
	'name'  => __( 'Clear Day Style', 'better-studio' ),
	'type'  => 'group',
	'state' => 'close',
);
$fields['style_clear_day_bg_img']   = array(
	'name'         => __( 'Background Image', 'better-studio' ),
	'id'           => 'style_clear_day_bg_img',
	'type'         => 'background_image',
	'upload_label' => __( 'Upload Image', 'better-studio' ),
	'desc'         => __( 'Customize <strong>Clear Day</strong> background image.', 'better-studio' ),
);
$fields['style_clear_day_bg_color'] = array(
	'name' => __( 'Background Color', 'better-studio' ),
	'id'   => 'style_clear_day_bg_color',
	'type' => 'color',
	'desc' => __( 'Customize <strong>Clear Day</strong> background color.', 'better-studio' ),
);


/**
 * => Style -> Clear Night
 */
$fields[]                             = array(
	'name'  => __( 'Clear Night Style', 'better-studio' ),
	'type'  => 'group',
	'state' => 'close',
);
$fields['style_clear_night_bg_img']   = array(
	'name'         => __( 'Background Image', 'better-studio' ),
	'id'           => 'style_clear_night_bg_img',
	'type'         => 'background_image',
	'upload_label' => __( 'Upload Image', 'better-studio' ),
	'desc'         => __( 'Customize <strong>Clear Night</strong> background image.', 'better-studio' ),
);
$fields['style_clear_night_bg_color'] = array(
	'name' => __( 'Background Color', 'better-studio' ),
	'id'   => 'style_clear_night_bg_color',
	'type' => 'color',
	'desc' => __( 'Customize <strong>Clear Night</strong> background color.', 'better-studio' ),
);


/**
 * => Style -> Rain
 */
$fields[]                      = array(
	'name'  => __( 'Rain Style', 'better-studio' ),
	'type'  => 'group',
	'state' => 'close',
);
$fields['style_rain_bg_img']   = array(
	'name'         => __( 'Background Image', 'better-studio' ),
	'id'           => 'style_rain_bg_img',
	'type'         => 'background_image',
	'upload_label' => __( 'Upload Image', 'better-studio' ),
	'desc'         => __( 'Customize <strong>Rain</strong> background image.', 'better-studio' ),
);
$fields['style_rain_bg_color'] = array(
	'name' => __( 'Background Color', 'better-studio' ),
	'id'   => 'style_rain_bg_color',
	'type' => 'color',
	'desc' => __( 'Customize <strong>Rain</strong> background color.', 'better-studio' ),
);


/**
 * => Style -> Snow
 */
$fields[]                      = array(
	'name'  => __( 'Snow Style', 'better-studio' ),
	'type'  => 'group',
	'state' => 'close',
);
$fields['style_snow_bg_img']   = array(
	'name'         => __( 'Background Image', 'better-studio' ),
	'id'           => 'style_snow_bg_img',
	'type'         => 'background_image',
	'upload_label' => __( 'Upload Image', 'better-studio' ),
	'desc'         => __( 'Customize <strong>Snow</strong> background image.', 'better-studio' ),
);
$fields['style_snow_bg_color'] = array(
	'name' => __( 'Background Color', 'better-studio' ),
	'id'   => 'style_snow_bg_color',
	'type' => 'color',
	'desc' => __( 'Customize <strong>Snow</strong> background color.', 'better-studio' ),
);


/**
 * => Style -> Cloudy
 */
$fields[]                        = array(
	'name'  => __( 'Cloudy Style', 'better-studio' ),
	'type'  => 'group',
	'state' => 'close',
);
$fields['style_cloudy_bg_img']   = array(
	'name'         => __( 'Background Image', 'better-studio' ),
	'id'           => 'style_cloudy_bg_img',
	'type'         => 'background_image',
	'upload_label' => __( 'Upload Image', 'better-studio' ),
	'desc'         => __( 'Customize <strong>Cloudy</strong> background image.', 'better-studio' ),
);
$fields['style_cloudy_bg_color'] = array(
	'name' => __( 'Background Color', 'better-studio' ),
	'id'   => 'style_cloudy_bg_color',
	'type' => 'color',
	'desc' => __( 'Customize <strong>Cloudy</strong> background color.', 'better-studio' ),
);


/**
 * => Style -> Partly Cloudy Day
 */
$fields[]                                   = array(
	'name'  => __( 'Partly Cloudy Day Style', 'better-studio' ),
	'type'  => 'group',
	'state' => 'close',
);
$fields['style_partly_cloudy_day_bg_img']   = array(
	'name'         => __( 'Background Image', 'better-studio' ),
	'id'           => 'style_partly_cloudy_day_bg_img',
	'type'         => 'background_image',
	'upload_label' => __( 'Upload Image', 'better-studio' ),
	'desc'         => __( 'Customize <strong>Partly Cloudy Day</strong> background image.', 'better-studio' ),
);
$fields['style_partly_cloudy_day_bg_color'] = array(
	'name' => __( 'Background Color', 'better-studio' ),
	'id'   => 'style_partly_cloudy_day_bg_color',
	'type' => 'color',
	'desc' => __( 'Customize <strong>Partly Cloudy Day</strong> background color.', 'better-studio' ),
);


/**
 * => Style -> Partly Cloudy Night
 */
$fields[]                                     = array(
	'name'  => __( 'Partly Cloudy Night Style', 'better-studio' ),
	'type'  => 'group',
	'state' => 'close',
);
$fields['style_partly_cloudy_night_bg_img']   = array(
	'name'         => __( 'Background Image', 'better-studio' ),
	'id'           => 'style_partly_cloudy_night_bg_img',
	'type'         => 'background_image',
	'upload_label' => __( 'Upload Image', 'better-studio' ),
	'desc'         => __( 'Customize <strong>Partly Cloudy Night</strong> background image.', 'better-studio' ),
);
$fields['style_partly_cloudy_night_bg_color'] = array(
	'name' => __( 'Background Color', 'better-studio' ),
	'id'   => 'style_partly_cloudy_night_bg_color',
	'type' => 'color',
	'desc' => __( 'Customize <strong>Partly Cloudy Night</strong> background color.', 'better-studio' ),
);


/**
 * => Style -> Sunrise
 */
$fields[]                         = array(
	'name'  => __( 'Sunrise Style', 'better-studio' ),
	'type'  => 'group',
	'state' => 'close',
);
$fields['style_sunrise_bg_img']   = array(
	'name'         => __( 'Background Image', 'better-studio' ),
	'id'           => 'style_sunrise_bg_img',
	'type'         => 'background_image',
	'upload_label' => __( 'Upload Image', 'better-studio' ),
	'desc'         => __( 'Customize <strong>Sunrise</strong> background image.', 'better-studio' ),
);
$fields['style_sunrise_bg_color'] = array(
	'name' => __( 'Background Color', 'better-studio' ),
	'id'   => 'style_sunrise_bg_color',
	'type' => 'color',
	'desc' => __( 'Customize <strong>Sunrise</strong> background color.', 'better-studio' ),
);


/**
 * => Style -> Sunset
 */
$fields[]                        = array(
	'name'  => __( 'Sunset Style', 'better-studio' ),
	'type'  => 'group',
	'state' => 'close',
);
$fields['style_sunset_bg_img']   = array(
	'name'         => __( 'Background Image', 'better-studio' ),
	'id'           => 'style_sunset_bg_img',
	'type'         => 'background_image',
	'upload_label' => __( 'Upload Image', 'better-studio' ),
	'desc'         => __( 'Customize <strong>Sunset</strong> background image.', 'better-studio' ),
);
$fields['style_sunset_bg_color'] = array(
	'name' => __( 'Background Color', 'better-studio' ),
	'id'   => 'style_sunset_bg_color',
	'type' => 'color',
	'desc' => __( 'Customize <strong>Sunset</strong> background color.', 'better-studio' ),
);

/**
 * => Style -> Sleet
 */
$fields[]                       = array(
	'name'  => __( 'Sleet Style', 'better-studio' ),
	'type'  => 'group',
	'state' => 'close',
);
$fields['style_sleet_bg_img']   = array(
	'name'         => __( 'Background Image', 'better-studio' ),
	'id'           => 'style_sleet_bg_img',
	'type'         => 'background_image',
	'upload_label' => __( 'Upload Image', 'better-studio' ),
	'desc'         => __( 'Customize <strong>Sleet</strong> background image.', 'better-studio' ),
);
$fields['style_sleet_bg_color'] = array(
	'name' => __( 'Background Color', 'better-studio' ),
	'id'   => 'style_sleet_bg_color',
	'type' => 'color',
	'desc' => __( 'Customize <strong>Sleet</strong> background color.', 'better-studio' ),
);


/**
 * => Style -> Wind
 */
$fields[]                      = array(
	'name'  => __( 'Wind Style', 'better-studio' ),
	'type'  => 'group',
	'state' => 'close',
);
$fields['style_wind_bg_img']   = array(
	'name'         => __( 'Background Image', 'better-studio' ),
	'id'           => 'style_wind_bg_img',
	'type'         => 'background_image',
	'upload_label' => __( 'Upload Image', 'better-studio' ),
	'desc'         => __( 'Customize <strong>Wind</strong> background image.', 'better-studio' ),
);
$fields['style_wind_bg_color'] = array(
	'name' => __( 'Background Color', 'better-studio' ),
	'id'   => 'style_wind_bg_color',
	'type' => 'color',
	'desc' => __( 'Customize <strong>Wind</strong> background color.', 'better-studio' ),
);


/**
 * => Style -> Fog
 */
$fields[]                     = array(
	'name'  => __( 'Fog Style', 'better-studio' ),
	'type'  => 'group',
	'state' => 'close',
);
$fields['style_fog_bg_img']   = array(
	'name'         => __( 'Background Image', 'better-studio' ),
	'id'           => 'style_fog_bg_img',
	'type'         => 'background_image',
	'upload_label' => __( 'Upload Image', 'better-studio' ),
	'desc'         => __( 'Customize <strong>Fog</strong> background image.', 'better-studio' ),
);
$fields['style_fog_bg_color'] = array(
	'name' => __( 'Background Color', 'better-studio' ),
	'id'   => 'style_fog_bg_color',
	'type' => 'color',
	'desc' => __( 'Customize <strong>Fog</strong> background color.', 'better-studio' ),
);


/**
 * => Style -> Thunderstorm
 */
$fields[]                              = array(
	'name'  => __( 'Thunderstorm Style', 'better-studio' ),
	'type'  => 'group',
	'state' => 'close',
);
$fields['style_thunderstorm_bg_img']   = array(
	'name'         => __( 'Background Image', 'better-studio' ),
	'id'           => 'style_thunderstorm_bg_img',
	'type'         => 'background_image',
	'upload_label' => __( 'Upload Image', 'better-studio' ),
	'desc'         => __( 'Customize <strong>Thunderstorm</strong> background image.', 'better-studio' ),
);
$fields['style_thunderstorm_bg_color'] = array(
	'name' => __( 'Background Color', 'better-studio' ),
	'id'   => 'style_thunderstorm_bg_color',
	'type' => 'color',
	'desc' => __( 'Customize <strong>Thunderstorm</strong> background color.', 'better-studio' ),
);


$fields[] = array(
	'name'  => __( 'Translations', 'better-studio' ),
	'id'    => 'translation',
	'type'  => 'tab',
	'icon'  => 'bsai-translation',
	'badge' => array(
		'text'  => __( 'New', 'better-studio' ),
		'color' => '#62D393'
	)
);

// todo add reset translation button ;)


$fields[]                     = array(
	'name'  => __( 'Months Name Translations', 'better-studio' ),
	'id'    => 'tr_month',
	'type'  => 'group',
	'state' => 'close',
);
$fields['tr_date']            = array(
	'name'            => __( 'Date translation', 'better-studio' ),
	'id'              => 'tr_date',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
	'desc'            => __( 'You can use this keywords<br>
<strong>%%day%%</strong>: Day.<br>
<strong>%%month%%</strong>: Month.', 'better-studio' ),
);
$fields['tr_month_january']   = array(
	'name'            => __( 'January', 'better-studio' ),
	'id'              => 'tr_month_january',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_month_february']  = array(
	'name'            => __( 'February', 'better-studio' ),
	'id'              => 'tr_month_february',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_month_march']     = array(
	'name'            => __( 'March', 'better-studio' ),
	'id'              => 'tr_month_march',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_month_april']     = array(
	'name'            => __( 'April', 'better-studio' ),
	'id'              => 'tr_month_april',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_month_may']       = array(
	'name'            => __( 'May', 'better-studio' ),
	'id'              => 'tr_month_may',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_month_june']      = array(
	'name'            => __( 'June', 'better-studio' ),
	'id'              => 'tr_month_june',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_month_july']      = array(
	'name'            => __( 'July', 'better-studio' ),
	'id'              => 'tr_month_july',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_month_august']    = array(
	'name'            => __( 'August', 'better-studio' ),
	'id'              => 'tr_month_august',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_month_september'] = array(
	'name'            => __( 'September', 'better-studio' ),
	'id'              => 'tr_month_september',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_month_october']   = array(
	'name'            => __( 'October', 'better-studio' ),
	'id'              => 'tr_month_october',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_month_november']  = array(
	'name'            => __( 'November', 'better-studio' ),
	'id'              => 'tr_month_november',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_month_december']  = array(
	'name'            => __( 'December', 'better-studio' ),
	'id'              => 'tr_month_december',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);

$fields[]              = array(
	'name'  => __( 'Days Name Translations', 'better-studio' ),
	'id'    => 'tr_day',
	'type'  => 'group',
	'state' => 'close',
);
$fields['tr_days_sat'] = array(
	'name'            => __( 'Sat', 'better-studio' ),
	'id'              => 'tr_days_sat',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_days_sun'] = array(
	'name'            => __( 'Sun', 'better-studio' ),
	'id'              => 'tr_days_sun',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_days_mon'] = array(
	'name'            => __( 'Mon', 'better-studio' ),
	'id'              => 'tr_days_mon',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_days_tue'] = array(
	'name'            => __( 'Tue', 'better-studio' ),
	'id'              => 'tr_days_tue',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_days_wed'] = array(
	'name'            => __( 'Wed', 'better-studio' ),
	'id'              => 'tr_days_wed',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_days_thu'] = array(
	'name'            => __( 'Thu', 'better-studio' ),
	'id'              => 'tr_days_thu',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_days_fri'] = array(
	'name'            => __( 'Fri', 'better-studio' ),
	'id'              => 'tr_days_fri',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);


$fields[] = array( 'type' => 'group_close' ); // Close last group

$fields[] = array( 'type' => 'hr' );

//
// Yahoo Translation
//
$fields[]                                   = array(
	'name'  => __( 'Weather Yahoo Translations', 'better-studio' ),
	'id'    => 'tr_yahoo',
	'type'  => 'group',
	'state' => 'close',
);
$fields['tr_yahoo_tornado']                 = array(
	'name'            => __( 'Tornado', 'better-studio' ),
	'id'              => 'tr_yahoo_tornado',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_tropical_storm']          = array(
	'name'            => __( 'Tropical Storm', 'better-studio' ),
	'id'              => 'tr_yahoo_tropical_storm',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_hurricane']               = array(
	'name'            => __( 'Hurricane', 'better-studio' ),
	'id'              => 'tr_yahoo_hurricane',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_severe_thunderstorms']    = array(
	'name'            => __( 'Severe Thunderstorms', 'better-studio' ),
	'id'              => 'tr_yahoo_severe_thunderstorms',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_thunderstorms']           = array(
	'name'            => __( 'Thunderstorms', 'better-studio' ),
	'id'              => 'tr_yahoo_thunderstorms',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_mixed_rain_and_snow']     = array(
	'name'            => __( 'Mixed Rain And Snow', 'better-studio' ),
	'id'              => 'tr_yahoo_mixed_rain_and_snow',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_mixed_rain_and_snow']     = array(
	'name'            => __( 'Mixed Rain And Snow', 'better-studio' ),
	'id'              => 'tr_yahoo_mixed_rain_and_snow',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_mixed_rain_and_sleet']    = array(
	'name'            => __( 'Mixed Rain And Sleet', 'better-studio' ),
	'id'              => 'tr_yahoo_mixed_rain_and_sleet',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_mixed_snow_and_sleet']    = array(
	'name'            => __( 'Mixed Snow And Sleet', 'better-studio' ),
	'id'              => 'tr_yahoo_mixed_snow_and_sleet',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_freezing_drizzle']        = array(
	'name'            => __( 'Freezing Drizzle', 'better-studio' ),
	'id'              => 'tr_yahoo_freezing_drizzle',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_drizzle']                 = array(
	'name'            => __( 'Drizzle', 'better-studio' ),
	'id'              => 'tr_yahoo_drizzle',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_freezing_rain']           = array(
	'name'            => __( 'Freezing Rain', 'better-studio' ),
	'id'              => 'tr_yahoo_freezing_rain',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_showers']                 = array(
	'name'            => __( 'Showers', 'better-studio' ),
	'id'              => 'tr_yahoo_showers',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_snow_flurries']           = array(
	'name'            => __( 'Snow Flurries', 'better-studio' ),
	'id'              => 'tr_yahoo_snow_flurries',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_light_snow_showers']      = array(
	'name'            => __( 'Light Snow Showers', 'better-studio' ),
	'id'              => 'tr_yahoo_light_snow_showers',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_blowing_snow']            = array(
	'name'            => __( 'Blowing Snow', 'better-studio' ),
	'id'              => 'tr_yahoo_blowing_snow',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_snow']                    = array(
	'name'            => __( 'Snow', 'better-studio' ),
	'id'              => 'tr_yahoo_snow',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_hail']                    = array(
	'name'            => __( 'Hail', 'better-studio' ),
	'id'              => 'tr_yahoo_hail',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_sleet']                   = array(
	'name'            => __( 'Sleet', 'better-studio' ),
	'id'              => 'tr_yahoo_sleet',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_dust']                    = array(
	'name'            => __( 'Dust', 'better-studio' ),
	'id'              => 'tr_yahoo_dust',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_haze']                    = array(
	'name'            => __( 'Haze', 'better-studio' ),
	'id'              => 'tr_yahoo_haze',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_smoky']                   = array(
	'name'            => __( 'Smoky', 'better-studio' ),
	'id'              => 'tr_yahoo_smoky',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_blustery']                = array(
	'name'            => __( 'Blustery', 'better-studio' ),
	'id'              => 'tr_yahoo_blustery',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_windy']                   = array(
	'name'            => __( 'Windy', 'better-studio' ),
	'id'              => 'tr_yahoo_windy',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_cold']                    = array(
	'name'            => __( 'Cold', 'better-studio' ),
	'id'              => 'tr_yahoo_cold',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_cloudy']                  = array(
	'name'            => __( 'Cloudy', 'better-studio' ),
	'id'              => 'tr_yahoo_cloudy',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_mostly_cloudy']           = array(
	'name'            => __( 'Mostly Cloudy', 'better-studio' ),
	'id'              => 'tr_yahoo_mostly_cloudy',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_partly_cloudy']           = array(
	'name'            => __( 'Partly Cloudy', 'better-studio' ),
	'id'              => 'tr_yahoo_partly_cloudy',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_clear']                   = array(
	'name'            => __( 'Clear', 'better-studio' ),
	'id'              => 'tr_yahoo_clear',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_sunny']                   = array(
	'name'            => __( 'Sunny', 'better-studio' ),
	'id'              => 'tr_yahoo_sunny',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_fair']                    = array(
	'name'            => __( 'Fair', 'better-studio' ),
	'id'              => 'tr_yahoo_fair',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_mixed_rain_and_hail']     = array(
	'name'            => __( 'Mixed Rain And Hail', 'better-studio' ),
	'id'              => 'tr_yahoo_mixed_rain_and_hail',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_hot']                     = array(
	'name'            => __( 'Hot', 'better-studio' ),
	'id'              => 'tr_yahoo_hot',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_isolated_thunderstorms']  = array(
	'name'            => __( 'Isolated Thunderstorms', 'better-studio' ),
	'id'              => 'tr_yahoo_isolated_thunderstorms',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_scattered_thunderstorms'] = array(
	'name'            => __( 'Scattered Thunderstorms', 'better-studio' ),
	'id'              => 'tr_yahoo_scattered_thunderstorms',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_scattered_showers']       = array(
	'name'            => __( 'Scattered Showers', 'better-studio' ),
	'id'              => 'tr_yahoo_scattered_showers',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_heavy_snow']              = array(
	'name'            => __( 'Heavy Snow', 'better-studio' ),
	'id'              => 'tr_yahoo_heavy_snow',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_scattered_snow_showers']  = array(
	'name'            => __( 'Scattered Snow Showers', 'better-studio' ),
	'id'              => 'tr_yahoo_scattered_snow_showers',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_thundershowers']          = array(
	'name'            => __( 'Thundershowers', 'better-studio' ),
	'id'              => 'tr_yahoo_thundershowers',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_snow_showers']            = array(
	'name'            => __( 'Snow Showers', 'better-studio' ),
	'id'              => 'tr_yahoo_snow_showers',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_yahoo_isolated_thundershowers'] = array(
	'name'            => __( 'Isolated Thundershowers', 'better-studio' ),
	'id'              => 'tr_yahoo_isolated_thundershowers',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);


//
// OWM Translation
//
$fields[]                                         = array(
	'name'  => __( 'Open Weather Map Translation', 'better-studio' ),
	'id'    => 'tr_owm',
	'type'  => 'group',
	'state' => 'close',
);
$fields['tr_owm_thunderstorm_with_light_rain']    = array(
	'name'            => __( 'Thunderstorm With Light Rain', 'better-studio' ),
	'id'              => 'tr_owm_thunderstorm_with_light_rain',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_thunderstorm_with_rain']          = array(
	'name'            => __( 'Thunderstorm With Rain', 'better-studio' ),
	'id'              => 'tr_owm_thunderstorm_with_rain',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_thunderstorm_with_heavy_rain']    = array(
	'name'            => __( 'Thunderstorm With Heavy Rain', 'better-studio' ),
	'id'              => 'tr_owm_thunderstorm_with_heavy_rain',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_light_thunderstorm']              = array(
	'name'            => __( 'Light Thunderstorm', 'better-studio' ),
	'id'              => 'tr_owm_light_thunderstorm',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_thunderstorm']                    = array(
	'name'            => __( 'Thunderstorm', 'better-studio' ),
	'id'              => 'tr_owm_thunderstorm',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_heavy_thunderstorm']              = array(
	'name'            => __( 'Heavy Thunderstorm', 'better-studio' ),
	'id'              => 'tr_owm_heavy_thunderstorm',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_ragged_thunderstorm']             = array(
	'name'            => __( 'Ragged Thunderstorm', 'better-studio' ),
	'id'              => 'tr_owm_ragged_thunderstorm',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_thunderstorm_with_light_drizzle'] = array(
	'name'            => __( 'Thunderstorm With Light Drizzle', 'better-studio' ),
	'id'              => 'tr_owm_thunderstorm_with_light_drizzle',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_thunderstorm_with_drizzle']       = array(
	'name'            => __( 'Thunderstorm With Drizzle', 'better-studio' ),
	'id'              => 'tr_owm_thunderstorm_with_drizzle',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_thunderstorm_with_heavy_drizzle'] = array(
	'name'            => __( 'Thunderstorm With Heavy Drizzle', 'better-studio' ),
	'id'              => 'tr_owm_thunderstorm_with_heavy_drizzle',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_light_intensity_drizzle']         = array(
	'name'            => __( 'Light Intensity Drizzle', 'better-studio' ),
	'id'              => 'tr_owm_light_intensity_drizzle',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_drizzle']                         = array(
	'name'            => __( 'Drizzle', 'better-studio' ),
	'id'              => 'tr_owm_drizzle',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_heavy_intensity_drizzle']         = array(
	'name'            => __( 'Heavy Intensity Drizzle', 'better-studio' ),
	'id'              => 'tr_owm_heavy_intensity_drizzle',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_light_intensity_drizzle_rain']    = array(
	'name'            => __( 'Light Intensity Drizzle Rain', 'better-studio' ),
	'id'              => 'tr_owm_light_intensity_drizzle_rain',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_drizzle_rain']                    = array(
	'name'            => __( 'Drizzle Rain', 'better-studio' ),
	'id'              => 'tr_owm_drizzle_rain',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_heavy_intensity_drizzle_rain']    = array(
	'name'            => __( 'Heavy Intensity Drizzle Rain', 'better-studio' ),
	'id'              => 'tr_owm_heavy_intensity_drizzle_rain',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_shower_rain_and_drizzle']         = array(
	'name'            => __( 'Shower Rain And Drizzle', 'better-studio' ),
	'id'              => 'tr_owm_shower_rain_and_drizzle',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_heavy_shower_rain_and_drizzle']   = array(
	'name'            => __( 'Heavy Shower Rain And Drizzle', 'better-studio' ),
	'id'              => 'tr_owm_heavy_shower_rain_and_drizzle',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_shower_drizzle']                  = array(
	'name'            => __( 'Shower Drizzle', 'better-studio' ),
	'id'              => 'tr_owm_shower_drizzle',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_light_rain']                      = array(
	'name'            => __( 'Light Rain', 'better-studio' ),
	'id'              => 'tr_owm_light_rain',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_moderate_rain']                   = array(
	'name'            => __( 'Moderate Rain', 'better-studio' ),
	'id'              => 'tr_owm_moderate_rain',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_heavy_intensity_rain']            = array(
	'name'            => __( 'Heavy Intensity Rain', 'better-studio' ),
	'id'              => 'tr_owm_heavy_intensity_rain',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_very_heavy_rain']                 = array(
	'name'            => __( 'Very Heavy Rain', 'better-studio' ),
	'id'              => 'tr_owm_very_heavy_rain',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_freezing_rain']                   = array(
	'name'            => __( 'Freezing Rain', 'better-studio' ),
	'id'              => 'tr_owm_freezing_rain',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_light_intensity_shower_rain']     = array(
	'name'            => __( 'Light Intensity Shower Rain', 'better-studio' ),
	'id'              => 'tr_owm_light_intensity_shower_rain',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_shower_rain']                     = array(
	'name'            => __( 'Shower Rain', 'better-studio' ),
	'id'              => 'tr_owm_shower_rain',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_heavy_intensity_shower_rain']     = array(
	'name'            => __( 'Heavy Intensity Shower Rain', 'better-studio' ),
	'id'              => 'tr_owm_heavy_intensity_shower_rain',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_ragged_shower_rain']              = array(
	'name'            => __( 'Ragged Shower Rain', 'better-studio' ),
	'id'              => 'tr_owm_ragged_shower_rain',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_light_snow']                      = array(
	'name'            => __( 'Light Snow', 'better-studio' ),
	'id'              => 'tr_owm_light_snow',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_snow']                            = array(
	'name'            => __( 'Snow', 'better-studio' ),
	'id'              => 'tr_owm_snow',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_heavy_snow']                      = array(
	'name'            => __( 'Heavy Snow', 'better-studio' ),
	'id'              => 'tr_owm_heavy_snow',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_sleet']                           = array(
	'name'            => __( 'Sleet', 'better-studio' ),
	'id'              => 'tr_owm_sleet',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_shower_sleet']                    = array(
	'name'            => __( 'Shower Sleet', 'better-studio' ),
	'id'              => 'tr_owm_shower_sleet',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_light_rain_and_snow']             = array(
	'name'            => __( 'Light Rain And Snow', 'better-studio' ),
	'id'              => 'tr_owm_light_rain_and_snow',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_rain_and_snow']                   = array(
	'name'            => __( 'Rain And Snow', 'better-studio' ),
	'id'              => 'tr_owm_rain_and_snow',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_light_shower_snow']               = array(
	'name'            => __( 'Light Shower Snow', 'better-studio' ),
	'id'              => 'tr_owm_light_shower_snow',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_shower_snow']                     = array(
	'name'            => __( 'Shower Snow', 'better-studio' ),
	'id'              => 'tr_owm_shower_snow',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_heavy_shower_snow']               = array(
	'name'            => __( 'Heavy Shower Snow', 'better-studio' ),
	'id'              => 'tr_owm_heavy_shower_snow',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_mist']                            = array(
	'name'            => __( 'Mist', 'better-studio' ),
	'id'              => 'tr_owm_mist',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_smoke']                           = array(
	'name'            => __( 'Smoke', 'better-studio' ),
	'id'              => 'tr_owm_smoke',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_haze']                            = array(
	'name'            => __( 'Haze', 'better-studio' ),
	'id'              => 'tr_owm_haze',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_sand']                            = array(
	'name'            => __( 'Sand', 'better-studio' ),
	'id'              => 'tr_owm_sand',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_fog']                             = array(
	'name'            => __( 'Fog', 'better-studio' ),
	'id'              => 'tr_owm_fog',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_dust_whirls']                     = array(
	'name'            => __( 'Dust Whirls', 'better-studio' ),
	'id'              => 'tr_owm_dust_whirls',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_dust']                            = array(
	'name'            => __( 'Dust', 'better-studio' ),
	'id'              => 'tr_owm_dust',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_volcanic_ash']                    = array(
	'name'            => __( 'Volcanic Ash', 'better-studio' ),
	'id'              => 'tr_owm_volcanic_ash',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_squalls']                         = array(
	'name'            => __( 'Squalls', 'better-studio' ),
	'id'              => 'tr_owm_squalls',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_tornado']                         = array(
	'name'            => __( 'Tornado', 'better-studio' ),
	'id'              => 'tr_owm_tornado',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_clear_sky']                       = array(
	'name'            => __( 'Clear Sky', 'better-studio' ),
	'id'              => 'tr_owm_clear_sky',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_few_clouds']                      = array(
	'name'            => __( 'Few Clouds', 'better-studio' ),
	'id'              => 'tr_owm_few_clouds',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_scattered_clouds']                = array(
	'name'            => __( 'Scattered Clouds', 'better-studio' ),
	'id'              => 'tr_owm_scattered_clouds',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_broken_clouds']                   = array(
	'name'            => __( 'Broken Clouds', 'better-studio' ),
	'id'              => 'tr_owm_broken_clouds',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_overcast_clouds']                 = array(
	'name'            => __( 'Overcast Clouds', 'better-studio' ),
	'id'              => 'tr_owm_overcast_clouds',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_tropical_storm']                  = array(
	'name'            => __( 'Tropical Storm', 'better-studio' ),
	'id'              => 'tr_owm_tropical_storm',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_hurricane']                       = array(
	'name'            => __( 'Hurricane', 'better-studio' ),
	'id'              => 'tr_owm_hurricane',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_cold']                            = array(
	'name'            => __( 'Cold', 'better-studio' ),
	'id'              => 'tr_owm_cold',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_hot']                             = array(
	'name'            => __( 'Hot', 'better-studio' ),
	'id'              => 'tr_owm_hot',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_windy']                           = array(
	'name'            => __( 'Windy', 'better-studio' ),
	'id'              => 'tr_owm_windy',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_hail']                            = array(
	'name'            => __( 'Hail', 'better-studio' ),
	'id'              => 'tr_owm_hail',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_calm']                            = array(
	'name'            => __( 'Calm', 'better-studio' ),
	'id'              => 'tr_owm_calm',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_light_breeze']                    = array(
	'name'            => __( 'Light Breeze', 'better-studio' ),
	'id'              => 'tr_owm_light_breeze',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_gentle_breeze']                   = array(
	'name'            => __( 'Gentle Breeze', 'better-studio' ),
	'id'              => 'tr_owm_gentle_breeze',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_moderate_breeze']                 = array(
	'name'            => __( 'Moderate Breeze', 'better-studio' ),
	'id'              => 'tr_owm_moderate_breeze',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_fresh_breeze']                    = array(
	'name'            => __( 'Fresh Breeze', 'better-studio' ),
	'id'              => 'tr_owm_fresh_breeze',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_strong_breeze']                   = array(
	'name'            => __( 'Strong Breeze', 'better-studio' ),
	'id'              => 'tr_owm_strong_breeze',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_high_wind']                       = array(
	'name'            => __( 'High Wind', 'better-studio' ),
	'id'              => 'tr_owm_high_wind',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_near_gale']                       = array(
	'name'            => __( 'Near Gale', 'better-studio' ),
	'id'              => 'tr_owm_near_gale',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_gale']                            = array(
	'name'            => __( 'Gale', 'better-studio' ),
	'id'              => 'tr_owm_gale',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_severe_gale']                     = array(
	'name'            => __( 'Severe Gale', 'better-studio' ),
	'id'              => 'tr_owm_severe_gale',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_storm']                           = array(
	'name'            => __( 'Storm', 'better-studio' ),
	'id'              => 'tr_owm_storm',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_violent_storm']                   = array(
	'name'            => __( 'Violent Storm', 'better-studio' ),
	'id'              => 'tr_owm_violent_storm',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_owm_hurricane']                       = array(
	'name'            => __( 'Hurricane', 'better-studio' ),
	'id'              => 'tr_owm_hurricane',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);


//
// Forecast.io Translation
//

$fields[]                                       = array(
	'name'  => __( 'Weather Forecast Translations', 'better-studio' ),
	'id'    => 'tr_forecast',
	'type'  => 'group',
	'state' => 'close',
);
$fields['tr_forecast_clear']                    = array(
	'name'            => __( 'Clear', 'better-studio' ),
	'id'              => 'tr_forecast_clear',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_rain']                     = array(
	'name'            => __( 'Rain', 'better-studio' ),
	'id'              => 'tr_forecast_rain',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_light_rain']               = array(
	'name'            => __( 'Light Rain', 'better-studio' ),
	'id'              => 'tr_forecast_light_rain',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_drizzle']                  = array(
	'name'            => __( 'Drizzle', 'better-studio' ),
	'id'              => 'tr_forecast_drizzle',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_light_rain_and_windy']     = array(
	'name'            => __( 'Light Rain And Windy', 'better-studio' ),
	'id'              => 'tr_forecast_light_rain_and_windy',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_flurries']                 = array(
	'name'            => __( 'Flurries', 'better-studio' ),
	'id'              => 'tr_forecast_flurries',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_flurries_df']              = array(
	'name'            => __( 'Flurries DF', 'better-studio' ),
	'id'              => 'tr_forecast_flurries_df',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
	'desc'            => __( 'DF: Daylight Factor', 'better-studio' ),
);
$fields['tr_forecast_cloudy']                   = array(
	'name'            => __( 'Cloudy', 'better-studio' ),
	'id'              => 'tr_forecast_cloudy',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_mostly_cloudy']            = array(
	'name'            => __( 'Mostly Cloudy', 'better-studio' ),
	'id'              => 'tr_forecast_mostly_cloudy',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_partly_cloudy']            = array(
	'name'            => __( 'Partly Cloudy', 'better-studio' ),
	'id'              => 'tr_forecast_partly_cloudy',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_snow']                     = array(
	'name'            => __( 'Snow', 'better-studio' ),
	'id'              => 'tr_forecast_snow',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_light_snow']               = array(
	'name'            => __( 'Light Snow', 'better-studio' ),
	'id'              => 'tr_forecast_light_snow',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_snow_and_breezy']          = array(
	'name'            => __( 'Snow and Breezy', 'better-studio' ),
	'id'              => 'tr_forecast_snow_and_breezy',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_snow_and_windy']           = array(
	'name'            => __( 'Snow and Windy', 'better-studio' ),
	'id'              => 'tr_forecast_snow_and_windy',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_sleet']                    = array(
	'name'            => __( 'Sleet', 'better-studio' ),
	'id'              => 'tr_forecast_sleet',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_wind']                     = array(
	'name'            => __( 'Wind', 'better-studio' ),
	'id'              => 'tr_forecast_wind',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_windy_and_mostly_cloudy']  = array(
	'name'            => __( 'Windy And Most Cloudy', 'better-studio' ),
	'id'              => 'tr_forecast_windy_and_mostly_cloudy',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_foggy']                    = array(
	'name'            => __( 'Foggy', 'better-studio' ),
	'id'              => 'tr_forecast_foggy',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_thunderstorm']             = array(
	'name'            => __( 'Thunderstorm', 'better-studio' ),
	'id'              => 'tr_forecast_thunderstorm',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_overcast']                 = array(
	'name'            => __( 'Overcast', 'better-studio' ),
	'id'              => 'tr_forecast_overcast',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_overcast_df']              = array(
	'name'            => __( 'Overcast DF', 'better-studio' ),
	'id'              => 'tr_forecast_overcast_df',
	'type'            => 'text',
	'desc'            => __( 'DF: Daylight Factor', 'better-studio' ),
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_breezy_and_partly_cloudy'] = array(
	'name'            => __( 'Breezy and Partly Cloudy', 'better-studio' ),
	'id'              => 'tr_forecast_breezy_and_partly_cloudy',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_breezy_and_mostly_cloudy'] = array(
	'name'            => __( 'Breezy and Mostly Cloudy', 'better-studio' ),
	'id'              => 'tr_forecast_breezy_and_mostly_cloudy',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_breezy_and_overcast']      = array(
	'name'            => __( 'Breezy and Overcast', 'better-studio' ),
	'id'              => 'tr_forecast_breezy_and_overcast',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_humid_and_mostly_cloudy']  = array(
	'name'            => __( 'Humid and Mostly Cloudy', 'better-studio' ),
	'id'              => 'tr_forecast_humid_and_mostly_cloudy',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_dry_and_partly_cloudy']    = array(
	'name'            => __( 'Dry and Partly Cloudy', 'better-studio' ),
	'id'              => 'tr_forecast_dry_and_partly_cloudy',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_dry_and_partly_cloudy_df'] = array(
	'name'            => __( 'Dry and Partly Cloudy DF', 'better-studio' ),
	'id'              => 'tr_forecast_dry_and_partly_cloudy_df',
	'type'            => 'text',
	'desc'            => __( 'DF: Daylight Factor', 'better-studio' ),
	'container_class' => 'highlight-hover',
);

$fields['tr_forecast_dry_and_mostly_cloudy']    = array(
	'name'            => __( 'Dry and Mostly Cloudy', 'better-studio' ),
	'id'              => 'tr_forecast_dry_and_mostly_cloudy',
	'type'            => 'text',
	'container_class' => 'highlight-hover',
);
$fields['tr_forecast_dry_and_mostly_cloudy_df'] = array(
	'name'            => __( 'Dry and Mostly Cloudy DF', 'better-studio' ),
	'id'              => 'tr_forecast_dry_and_mostly_cloudy_df',
	'type'            => 'text',
	'desc'            => __( 'DF: Daylight Factor', 'better-studio' ),
	'container_class' => 'highlight-hover',
);


//
// Aeris Weather Translation
//

$fields[] = array(
	'name'  => __( 'Aeris Weather Translation', 'better-studio' ),
	'id'    => 'tr_aeris',
	'type'  => 'group',
	'state' => 'close',
);
$fields[] = array(
	'name'          => __( 'Sorry!', 'better-studio' ),
	'std'           => __( 'Aeris Weather source did not supports translation.', 'better-studio' ),
	'id'            => 'aeris-tr',
	'type'          => 'info',
	'state'         => 'open',
	'info-type'     => 'warning',
	'section_class' => 'widefat',
);


//
// Caching Options
//
$fields[]             = array(
	'name' => __( 'Caching Options', 'better-studio' ),
	'id'   => 'cache_options_title',
	'type' => 'tab',
	'icon' => 'bsai-database',
);
$fields['cache_time'] = array(
	'name'    => __( 'Maximum Lifetime of Cache', 'better-studio' ),
	'id'      => 'cache_time',
	'type'    => 'select',
	'options' => array(
		30  => __( '30 Minutes', 'better-studio' ),
		60  => __( '1 Hour', 'better-studio' ),
		90  => __( '1 Hour and 30 Minutes', 'better-studio' ),
		120 => __( '2 Hour', 'better-studio' ),
		150 => __( '2 Hour and 30 Minutes', 'better-studio' ),
		180 => __( '3 Hour', 'better-studio' ),
	)
);
$fields[]             = array(
	'name'        => __( 'Clear Data Base Saved Caches', 'better-studio' ),
	'id'          => 'cache_clear_all',
	'type'        => 'ajax_action',
	'button-name' => '<i class="fa fa-refresh"></i> ' . __( 'Purge All Caches', 'better-studio' ),
	'callback'    => 'Better_Weather::clear_cache_all',
	'confirm'     => __( 'Are you sure for deleting all caches?', 'better-studio' ),
	'desc'        => __( 'This allows you to clear all caches that are saved in data base.', 'better-studio' )
);

$fields[] = array(
	'name'       => __( 'Backup & Restore', 'better-studio' ),
	'id'         => 'backup_restore',
	'type'       => 'tab',
	'icon'       => 'bsai-export-import',
	'margin-top' => '30',
);
$fields[] = array(
	'name'      => __( 'Backup / Export', 'better-studio' ),
	'id'        => 'backup_export_options',
	'type'      => 'export',
	'file_name' => 'betterweather-options-backup',
	'panel_id'  => Better_Weather::$panel_id,
	'desc'      => __( 'This allows you to create a backup of your options and settings. Please note, it will not backup anything else.', 'better-studio' )
);
$fields[] = array(
	'name'     => __( 'Restore / Import', 'better-studio' ),
	'id'       => 'import_restore_options',
	'type'     => 'import',
	'panel_id' => Better_Weather::$panel_id,
	'desc'     => __( '<strong>It will override your current settings!</strong> Please make sure to select a valid backup file.', 'better-studio' )
);
options/panel.php000064400000036073151214002660010055 0ustar00<?php

add_filter( 'better-framework/panel/add', 'better_ads_manager_panel_add', 10 );

if ( ! function_exists( 'better_ads_manager_panel_add' ) ) {
	/**
	 * Callback: Ads panel
	 *
	 * Filter: better-framework/panel/options
	 *
	 * @param $panels
	 *
	 * @return array
	 */
	function better_ads_manager_panel_add( $panels ) {

		$panels['better_ads_manager'] = array(
			'id'  => 'better_ads_manager',
			'css' => true,
		);

		return $panels;
	}
}


add_filter( 'better-framework/panel/better_ads_manager/config', 'better_ads_manager_panel_config', 10 );

if ( ! function_exists( 'better_ads_manager_panel_config' ) ) {
	/**
	 * Callback: Init's BF options
	 *
	 * @param $panel
	 *
	 * @return array
	 */
	function better_ads_manager_panel_config( $panel ) {

		include Better_Ads_Manager::dir_path( 'includes/options/panel-config.php' );

		return $panel;
	}
}


add_filter( 'better-framework/panel/better_ads_manager/fields', '_better_ads_options_post_ads_tab', 30 );

/**
 * Ads "Post Ads" tab to options
 *
 * @param $fields
 *
 * @return array
 */
function _better_ads_options_post_ads_tab( $fields ) {

	$fields['post_ads_tab'] = array(
		'name' => __( 'Post Ads', 'better-studio' ),
		'id'   => 'post_ads_tab',
		'type' => 'tab',
		'icon' => 'bsai-page-text',
	);

	return $fields;
}


add_filter( 'better-framework/panel/better_ads_manager/fields', '_better_ads_options_post_top_ads', 33 );

/**
 * Ads "Post Ads" tab to options
 *
 * @param $fields
 *
 * @return array
 */
function _better_ads_options_post_top_ads( $fields ) {

	$fields['_post_content_ads_h'] = array(
		'name'   => __( 'Post Content Ads', 'better-studio' ),
		'id'     => '_post_content_ads_h',
		'type'   => 'heading',
		'layout' => 'style-2',
	);

	better_ads_inject_ad_field_to_fields( $fields, array(
		'group'       => true,
		'group_title' => __( 'Above Post Content', 'better-studio' ),
		'id_prefix'   => 'ad_post_top',
		'group_state' => 'close',
	) );

	return $fields;
}

add_filter( 'better-framework/panel/better_ads_manager/fields', '_better_ads_options_post_middle_ads', 35 );

/**
 * Ads "Post Bottom Ads" to options
 *
 * @param $fields
 *
 * @return array
 */
function _better_ads_options_post_middle_ads( $fields ) {

	better_ads_inject_ad_field_to_fields( $fields, array(
		'group'       => true,
		'group_title' => __( 'Middle Post Content', 'better-studio' ),
		'group_desc'  => __( 'Ads that will be shown exactly in middle of post content.', 'better-studio' ),
		'id_prefix'   => 'ad_post_middle',
		'group_state' => 'close',
	) );

	return $fields;
}


add_filter( 'better-framework/panel/better_ads_manager/fields', '_better_ads_options_post_bottom_ads', 37 );

/**
 * Ads "Post Bottom Ads" to options
 *
 * @param $fields
 *
 * @return array
 */
function _better_ads_options_post_bottom_ads( $fields ) {

	better_ads_inject_ad_field_to_fields( $fields, array(
		'group'       => true,
		'group_title' => __( 'Below Post Content', 'better-studio' ),
		'id_prefix'   => 'ad_post_bottom',
		'group_state' => 'close',
	) );

	return $fields;
}


add_filter( 'better-framework/panel/better_ads_manager/fields', '_better_ads_options_post_inline_ads', 33 );

/**
 * Ads "Post Ads" tab to options
 *
 * @param $fields
 *
 * @return array
 */
function _better_ads_options_post_inline_ads( $fields ) {

	better_ads_inject_ad_repeater_field_to_fields( $fields, array(
			'id_prefix'        => 'ad_post_inline',
			'group_title'      => __( 'Inside Post Content (After X Paragraph)', 'better-studio' ),
			'field_desc'       => __( 'Add inline adds inside post content. <br>You can add multiple inline adds for multiple location of post content.', 'better-studio' ),
			'field_add_label'  => '<i class="fa fa-plus"></i> ' . __( 'Add New Inline Ad', 'better-studio' ),
			'field_item_title' => __( 'Inline Ad', 'better-studio' ),
			'group_auto_close' => true,
			'field_end_fields' => array(
				'paragraph' => array(
					'name'          => __( 'After Paragraph', 'better-studio' ),
					'id'            => 'paragraph',
					'desc'          => __( 'Content of each post will analyzed and it will inject an ad after the selected number of paragraphs.', 'better-studio' ),
					'input-desc'    => __( 'After how many paragraphs the ad will display.', 'better-studio' ),
					'type'          => 'text',
					'show_on'       => array(
						array(
							'type=banner',
						),
						array(
							'type=campaign',
						),
					),
					'ad-id'         => 'ad_post_inline',
					'repeater_item' => true,
				)
			),
		)
	);

	return $fields;
}


add_filter( 'better-framework/panel/better_ads_manager/fields', '_better_ads_options_custom_css_js', 90 );

/**
 * Ads "Custom CSS/JS" to options
 *
 * @param $fields
 *
 * @return array
 */
function _better_ads_options_custom_css_js( $fields ) {

	include Better_Ads_Manager::dir_path( 'includes/options/panel-fields-css.php' );

	return $fields;
}


add_filter( 'better-framework/panel/better_ads_manager/fields', '_better_ads_options_overrides_fields', 79.9 );

/**
 * Add override section
 *
 * @param $fields
 *
 * @return array
 */
function _better_ads_options_overrides_fields( $fields ) {

	//
	// Ajax -> BF Ajax Tab -> Override Settings Tab
	//
	if (
		bf_is_doing_ajax( 'bf_ajax' ) &&
		isset( $_REQUEST['panelID'] ) &&
		$_REQUEST['panelID'] === 'better_ads_manager' /*&&
			( isset( $_REQUEST['reqID'] ) && $_REQUEST['reqID'] === 'fetch-deferred-field' )*/ /*&&
			( isset( $_REQUEST['sectionID'] ) && $_REQUEST['sectionID'] === 'override_settings' )*/
	) {

		$fields['override_settings'] = array(
			'name'       => __( 'Override Ads', 'better-studio' ),
			'id'         => 'override_settings',
			'type'       => 'tab',
			'icon'       => 'bsai-sitemap',
			'badge'      => array(
				'text'  => __( 'New', 'better-studio' ),
				'color' => '#d54e21'
			),
			'margin-top' => 20,
			'ajax-tab'   => true
		);

		$fields['reset_override_settings'] = array(
			'name'               => __( 'Reset Ad Overrides', 'better-studio' ),
			'id'                 => 'reset_override_settings',
			'type'               => 'ajax_action',
			'button-name'        => '<i class="fa fa-refresh"></i> ' . __( 'Reset All Overrides', 'better-studio' ),
			'callback'           => 'Better_Ads_Manager::reset_typography_options',
			'confirm'            => __( 'Are you sure for resetting ad overrides?', 'better-studio' ),
			'desc'               => __( 'This allows you to remove all ad overrides.', 'better-studio' ),
			'ajax-section-field' => 'override_settings',
		);

		$section_fields = array(); // fields of ajax tab
		$sections       = better_ads_get_override_sections_list();

		foreach ( $sections as $type_id => $type ) {

			// close all prev groups
			$section_fields[ $type_id . '-type-label-close' ] = array(
				'type'         => 'group_close',
				'level'        => 'all',
				'ajax-section' => 'override_settings',
			);

			$section_fields[ $type_id . '-type-label' ] = array(
				'name'               => $type['label'],
				'id'                 => $type_id . '-type-label',
				'type'               => 'heading',
				'layout'             => 'style-2',
				'ajax-section-field' => 'override_settings',
			);

			foreach ( $type['items'] as $section ) {

				$section_fields[ $section['id'] . '_top_level' ] = array(
					'name'                      => $section['label'] . ' Ads',
					'id'                        => $section['id'] . '_top_level',
					'type'                      => 'group',
					'level'                     => 1,
					'state'                     => 'close',
					'ajax-section'              => 'bf-ajax-group',
					'ajax-section-field'        => 'override_settings',
					'ajax-section-handler'      => 'better_ads_section_override_fields_list',
					'ajax-section-handler-args' => array(
						'id'           => $section['id'] . '_top_level',
						'type'         => $type_id,
						'section'      => $section['id'],
						'section-name' => $section['label'],
					),
					'ajax-section-handler-type' => 'field-generator',
				);

				$section_fields[ $section['id'] . '_top_level-close' ] = array(
					'type'               => 'group_close',
					'level'              => 'all',
					'id'                 => $section['id'] . '_top_level-close',
					'ajax-section-field' => 'override_settings',
				);
			}

		}

		return $fields + $section_fields;

	} else {

		$fields['override_settings'] = array(
			'name'       => __( 'Override Ads', 'better-studio' ),
			'id'         => 'override_settings',
			'type'       => 'tab',
			'icon'       => 'bsai-sitemap',
			'badge'      => array(
				'text'  => __( 'New', 'better-studio' ),
				'color' => '#d54e21'
			),
			'margin-top' => 20,
			'ajax-tab'   => true
		);

	}

	return $fields;
}


add_filter( 'better-framework/panel/better_ads_manager/fields', '_better_ads_options_lazy_loading', 86 );
add_filter( 'better-framework/panel/better_ads_manager/fields', '_better_ads_options_advanced', 86 );


/**
 * Advanced Settings Tab
 *
 * @param $fields
 *
 * @return array
 */
function _better_ads_options_advanced( $fields ) {

	$fields['advanced_settings'] = array(
		'name'  => __( 'Advanced Settings', 'better-studio' ),
		'id'    => 'advanced_settings',
		'type'  => 'tab',
		'icon'  => 'bsai-gear',
		'badge' => array(
			'text'  => __( 'New', 'better-studio' ),
			'color' => '#d54e21'
		),
	);

	$fields['html_block_tags'] = array(
		'name' => __( 'Consider These Tags as New Paragraph', 'better-studio' ),
		'desc' => __( 'Separate tags name with comma. This tags will be used in adding inline ad. <code>Example: p,div,table</code>', 'better-studio' ),
		'id'   => 'html_block_tags',
		'type' => 'text',
	);

	$fields['caption_position'] = array(
		'name'    => __( 'Ads Caption Location', 'better-studio' ),
		'desc'    => __( 'Chose the location of ads.', 'better-studio' ),
		'id'      => 'caption_position',
		'type'    => 'select',
		'options' => array(
			'above' => __( 'Above Ads', 'better-studio' ),
			'below' => __( 'Below Ads', 'better-studio' ),
		)
	);

	return $fields;
}


/**
 * Advanced Settings Tab
 *
 * @param $fields
 *
 * @return array
 */
function _better_ads_options_lazy_loading( $fields ) {

	$fields['lazy_loading_tab'] = array(
		'name'       => __( 'Lazy Loading Ads', 'better-studio' ),
		'id'         => 'lazy_loading_tab',
		'type'       => 'tab',
		'icon'       => 'bsai-gear',
		'margin-top' => 20,
		'badge'      => array(
			'text'  => __( 'New', 'better-studio' ),
			'color' => '#d54e21'
		),
	);

	$fields['lazy_loading_ads']  = array(
		'name'    => __( 'Lazy Load Ads?', 'better-studio' ),
		'desc'    => __( 'Load ads only when they are on user view report. <br><br><strong style="color:red;">Currently this only works for AdSense ad format.</strong>', 'better-studio' ),
		'id'      => 'lazy_loading_ads',
		'type'    => 'select',
		'options' => array(
			'enable'  => __( 'Yes, Lazy load all Ads', 'better-studio' ),
			'disable' => __( 'No, Load ads as normal', 'better-studio' ),
		)
	);
	$fields['lazy_loading_text'] = array(
		'name' => __( 'Loading text', 'better-studio' ),
		'desc' => __( 'Load ads only when they are on user view report.', 'better-studio' ),
		'id'   => 'lazy_loading_text',
		'type' => 'text',
	);

	return $fields;
}


add_filter( 'better-framework/panel/better_ads_manager/fields', '_better_ads_options_dfp_section', 85 );

/**
 * DFP
 *
 * @param $fields
 *
 * @return array
 */
function _better_ads_options_dfp_section( $fields ) {

	$fields['dfp_settings'] = array(
		'name'       => __( 'Google DFP', 'better-studio' ),
		'id'         => 'dfp_settings',
		'type'       => 'tab',
		'icon'       => 'bsai-header',
		'margin-top' => 20,
		'badge'      => array(
			'text'  => __( 'New', 'better-studio' ),
			'color' => '#d54e21'
		),
	);

	$fields['dfp_code'] = array(
		'name' => __( 'DFP Before &lt;/head&gt; Code', 'better-studio' ),
		'desc' => __( 'Enter your DFP setup code for before &lt;/head&gt;. With entering it you can create ad banner and select this spots to show them.', 'better-studio' ),
		'id'   => 'dfp_code',
		'type' => 'textarea',
	);

	return $fields;
}


add_filter( 'better-framework/panel/better_ads_manager/fields', '_better_ads_options_import_export', 100 );

/**
 * Ads "Custom CSS/JS" to options
 *
 * @param $fields
 *
 * @return array
 */
function _better_ads_options_import_export( $fields ) {

	bf_inject_panel_import_export_fields( $fields, array(
		'panel-id'         => Better_Ads_Manager::$panel_id,
		'export-file-name' => 'better-ads-backup',
	) );

	return $fields;
}


add_filter( 'better-framework/panel/better_ads_manager/std', '_better_ads_options_std', 33 );

/**
 * Ads "Post Ads" tab to options
 *
 * @param $fields
 *
 * @return array
 */
function _better_ads_options_std( $fields ) {

	// Above Post
	$fields['ad_post_top_type']     = array(
		'std' => '',
	);
	$fields['ad_post_top_banner']   = array(
		'std' => 'none',
	);
	$fields['ad_post_top_campaign'] = array(
		'std' => 'none',
	);
	$fields['ad_post_top_count']    = array(
		'std' => 1,
	);
	$fields['ad_post_top_columns']  = array(
		'std' => 1,
	);
	$fields['ad_post_top_orderby']  = array(
		'std' => 'rand',
	);
	$fields['ad_post_top_order']    = array(
		'std' => 'ASC',
	);
	$fields['ad_post_top_align']    = array(
		'std' => 'center',
	);


	//  middle ads
	$fields['ad_post_middle_type']     = array(
		'std' => '',
	);
	$fields['ad_post_middle_banner']   = array(
		'std' => 'none',
	);
	$fields['ad_post_middle_campaign'] = array(
		'std' => 'none',
	);
	$fields['ad_post_middle_count']    = array(
		'std' => 1,
	);
	$fields['ad_post_middle_columns']  = array(
		'std' => 1,
	);
	$fields['ad_post_middle_orderby']  = array(
		'std' => 'rand',
	);
	$fields['ad_post_middle_order']    = array(
		'std' => 'ASC',
	);
	$fields['ad_post_middle_align']    = array(
		'std' => 'center',
	);


	// Post Bottom
	$fields['ad_post_bottom_type']     = array(
		'std' => '',
	);
	$fields['ad_post_bottom_banner']   = array(
		'std' => 'none',
	);
	$fields['ad_post_bottom_campaign'] = array(
		'std' => 'none',
	);
	$fields['ad_post_bottom_count']    = array(
		'std' => 1,
	);
	$fields['ad_post_bottom_columns']  = array(
		'std' => 1,
	);
	$fields['ad_post_bottom_orderby']  = array(
		'std' => 'rand',
	);
	$fields['ad_post_bottom_order']    = array(
		'std' => 'ASC',
	);
	$fields['ad_post_bottom_align']    = array(
		'std' => 'center',
	);


	// Post inline
	$fields['ad_post_inline'] = array(
		'default' => array(
			array(
				'type'      => '',
				'campaign'  => 'none',
				'banner'    => 'none',
				'paragraph' => 3,
				'count'     => 3,
				'columns'   => 3,
				'orderby'   => 'rand',
				'order'     => 'ASC',
				'align'     => 'center',
			),
		),
		'std'     => array(
			array(
				'type'      => '',
				'campaign'  => 'none',
				'banner'    => 'none',
				'position'  => 'center',
				'paragraph' => 3,
				'count'     => 3,
				'columns'   => 3,
				'orderby'   => 'rand',
				'order'     => 'ASC',
				'align'     => 'center',
			),
		),
	);

	// Custom code
	$fields['custom_css_code']    = array(
		'std' => '',
	);
	$fields['custom_header_code'] = array(
		'std' => '',
	);

	// Lazy Load
	$fields['lazy_loading_ads']  = array(
		'std' => 'disable',
	);
	$fields['lazy_loading_text'] = array(
		'std' => 'Loading...',
	);

	// Advanced
	$fields['html_block_tags']  = array(
		'std' => '',
	);
	$fields['caption_position'] = array(
		'std' => 'below',
	);

	return $fields;
}
widgets/class-better-ads-widget.php000064400000011176151214525620013352 0ustar00<?php


/**
 * Better Ads Widget
 */
class Better_Ads_Widget extends BF_Widget {


	/**
	 * Register widget with WordPress.
	 */
	function __construct() {

		// Back end form fields
		$this->fields = array(
			array(
				'name'          => __( 'Title', 'better-studio' ),
				'attr_id'       => 'title',
				'type'          => 'text',
				'section_class' => 'widefat',
			),
			array(
				'name'          => __( 'Ad Type', 'better-studio' ),
				'input-desc'    => __( 'Choose simple banner or campaign..', 'better-studio' ),
				'attr_id'       => 'type',
				'type'          => 'select',
				'section_class' => 'widefat',
				"options"       => array(
					''         => __( '-- Select Ad Type --', 'better-studio' ),
					'campaign' => __( 'Campaign', 'better-studio' ),
					'banner'   => __( 'Banner', 'better-studio' ),
				),
			),
			array(
				'name'               => __( 'Banner', 'better-studio' ),
				'attr_id'            => 'banner',
				'type'               => 'select',
				'deferred-options'   => array(
					'callback' => 'better_ads_get_banners_option',
					'args'     => array(
						- 1,
						true
					),
				),
				'filter-field'       => 'type',
				'filter-field-value' => 'banner',
			),
			array(
				'name'               => __( 'Campaign', 'better-studio' ),
				'attr_id'            => 'campaign',
				'type'               => 'select',
				'deferred-options'   => array(
					'callback' => 'better_ads_get_campaigns_option',
					'args'     => array(
						- 1,
						true
					),
				),
				'filter-field'       => 'type',
				'filter-field-value' => 'campaign',
			),
			array(
				'name'               => __( 'Max Amount of Allowed Banners', 'better-studio' ),
				'input-desc'         => __( 'Leave empty to show all banners.', 'better-studio' ),
				'attr_id'            => 'count',
				'type'               => 'text',
				'filter-field'       => 'type',
				'filter-field-value' => 'campaign',
			),
			array(
				'name'               => __( 'Columns', 'better-studio' ),
				'attr_id'            => 'columns',
				'type'               => 'select',
				"options"            => array(
					1 => __( '1 Column', 'better-studio' ),
					2 => __( '2 Column', 'better-studio' ),
					3 => __( '3 Column', 'better-studio' ),
				),
				'filter-field'       => 'type',
				'filter-field-value' => 'campaign',
			),
			array(
				'name'               => __( 'Order By', 'better-studio' ),
				'attr_id'            => 'orderby',
				'type'               => 'select',
				'section_class'      => 'widefat',
				"options"            => array(
					'date'  => __( 'Date', 'better-studio' ),
					'title' => __( 'Title', 'better-studio' ),
					'rand'  => __( 'Rand', 'better-studio' ),
				),
				'filter-field'       => 'type',
				'filter-field-value' => 'campaign',
			),
			array(
				'name'               => __( 'Order', 'better-studio' ),
				'attr_id'            => 'order',
				'type'               => 'select',
				'section_class'      => 'widefat',
				"options"            => array(
					'ASC'  => __( 'Ascending', 'better-studio' ),
					'DESC' => __( 'Descending', 'better-studio' ),
				),
				'filter-field'       => 'type',
				'filter-field-value' => 'campaign',
			),
			array(
				'name'          => __( 'Align', 'better-studio' ),
				'attr_id'       => 'align',
				'type'          => 'select',
				'section_class' => 'widefat',
				"options"       => array(
					'left'   => __( 'Left', 'better-studio' ),
					'center' => __( 'Center', 'better-studio' ),
					'right'  => __( 'Right', 'better-studio' ),
				),
			),
			array(
				'name'          => __( 'Show Captions', 'better-studio' ),
				'attr_id'       => 'show-caption',
				'type'          => 'select',
				'section_class' => 'widefat',
				"options"       => array(
					1 => __( 'Show caption\'s', 'better-studio' ),
					0 => __( 'Hide caption\'s', 'better-studio' ),
				),
			),
			array(
				'name'          => __( 'Lazy Load Ad?', 'better-studio' ),
				'desc'          => __( 'Chose the behaviour of lazy loading.', 'better-studio' ),
				'attr_id'       => 'lazy-load',
				'type'          => 'select',
				"options"       => array(
					''        => __( '-- Inherit from panel --', 'better-studio' ),
					'enable'  => __( 'Yes, Lazy load this ad', 'better-studio' ),
					'disable' => __( 'No, Load this Ad as normal', 'better-studio' ),
				),
				'std'           => 'center',
				'show_on'       => array(
					array(
						'type=banner',
					),
					array(
						'type=campaign',
					),
				),
				'section_class' => 'widefat',
			),
		);

		parent::__construct(
			'better-ads',
			__( 'Better Ads', 'better-studio' ),
			array( 'description' => __( 'Show campaign and banners.', 'better-studio' ) )
		);
	}
}
shortcodes/class-better-ads-shortcode.php000064400000017614151214525620014573 0ustar00<?php


class Better_Ads_Shortcode extends BF_Shortcode {

	function __construct( $id, $options ) {

		$id = 'better-ads';

		$this->widget_id = 'better ads';

		$this->name = __( 'Ad Box', 'better-studio' );

		$this->description = 'BetterAds ad box';

		$_options = array(
			'defaults'              => array(
				'title'           => '',
				'type'            => '',
				'banner'          => 'none',
				'campaign'        => 'none',
				'count'           => 2,
				'columns'         => 1,
				'align'           => 'center',
				'lazy-load'       => '',
				'order'           => 'ASC',
				'orderby'         => 'rand',
				'float'           => 'none',
				'show-caption'    => true,
				'bs-show-desktop' => true,
				'bs-show-tablet'  => true,
				'bs-show-phone'   => true,
			),
			'have_widget'           => true,
			'have_vc_add_on'        => true,
			'have_tinymce_add_on'   => apply_filters( 'better-ads/shortcode/live-preview', true ),
			'have_gutenberg_add_on' => apply_filters( 'better-ads/shortcode/live-preview', true ),
		);

		$_options = wp_parse_args( $_options, $options );

		parent::__construct( $id, $_options );

	}


	/**
	 * Handle displaying of shortcode
	 *
	 * @param array  $atts
	 * @param string $content
	 *
	 * @return string
	 */
	function display( array $atts, $content = '' ) {

		// ad can not be shown
		if ( ! better_ads_ad_can_be_shown( bf_get_current_sidebar() ? 'widget' : 'shortcode' ) ) {
			return '';
		}

		// Add float class to shortcodes that are not inside a widget sidebar!
		if ( ! bf_get_current_sidebar() && isset( $atts['align'] ) ) {
			$atts['float'] = $atts['align'];
		}

		ob_start();
		echo Better_Ads_Manager()->show_ads( $atts );

		return ob_get_clean();

	}


	/**
	 * Registers Visual Composer Add-on
	 */
	function register_vc_add_on() {

		vc_map( array(
			"name"           => $this->name,
			"base"           => $this->id,
			"description"    => $this->description,
			"weight"         => 10,
			"wrapper_height" => 'full',

			"category" => __( 'Content', 'better-studio' ),
			"params"   => $this->vc_map_listing_all()
		) );

	} // register_vc_add_on


	/**
	 * Fields for all panels
	 *
	 * @return array
	 */
	public function get_fields() {

		return array(

			array(
				'type' => 'tab',
				'name' => __( 'General', 'better-studio' ),
				'id'   => 'general_tab',
			),
			array(
				"name"           => __( 'Ad Type', 'better-studio' ),
				"type"           => 'select',
				"id"             => 'type',
				'options'        => array(
					''         => __( '-- Select Ad Type', 'better-studio' ),
					'campaign' => __( 'Campaign', 'better-studio' ),
					'banner'   => __( 'Banner', 'better-studio' ),
				),
				//
				"vc_admin_label" => true,
			),
			//
			// Banner
			//
			array(
				"type"             => 'select',
				"name"             => __( 'Banner', 'better-studio' ),
				"id"               => 'banner',
				'deferred-options' => array(
					'callback' => 'better_ads_get_banners_option',
					'args'     => array(
						- 1,
						true
					),
				),
				'show_on'          => array(
					array( 'type=banner' ),
				),
				//
				"vc_admin_label"   => true,
			),
			//
			// Campaign
			//
			array(
				"type"             => 'select',
				"name"             => __( 'Campaign', 'better-studio' ),
				"id"               => 'campaign',
				'deferred-options' => array(
					'callback' => 'better_ads_get_campaigns_option',
					'args'     => array(
						- 1,
						true
					),
				),
				'show_on'          => array(
					array( 'type=campaign' ),
				),
				//
				"vc_admin_label"   => true,
			),
			array(
				"type"           => 'text',
				"name"           => __( 'Max Amount of Allowed Banners', 'better-studio' ),
				"desc"           => __( 'Leave empty to show all banners.', 'better-studio' ),
				"id"             => 'count',
				'show_on'        => array(
					array( 'type=campaign' ),
				),
				//
				"vc_admin_label" => false,
			),
			array(
				"type"           => 'select',
				"name"           => __( 'Columns', 'better-studio' ),
				"id"             => 'columns',
				"options"        => array(
					1 => __( '1 Column', 'better-studio' ),
					2 => __( '2 Column', 'better-studio' ),
					3 => __( '3 Column', 'better-studio' ),
				),
				'show_on'        => array(
					array( 'type=campaign' ),
				),
				//
				"vc_admin_label" => false,
			),
			array(
				"type"           => 'select',
				"name"           => __( 'Order By', 'better-studio' ),
				"id"             => 'orderby',
				"options"        => array(
					'date'  => __( 'Date', 'better-studio' ),
					'title' => __( 'Title', 'better-studio' ),
					'rand'  => __( 'Rand', 'better-studio' ),
				),
				'show_on'        => array(
					array( 'type=campaign' ),
				),
				'section_class'  => 'affect-block-align-on-change',
				//
				"vc_admin_label" => false,
			),
			array(
				"type"           => 'select',
				"name"           => __( 'Order', 'better-studio' ),
				"id"             => 'order',
				"options"        => array(
					'ASC'  => __( 'Ascending', 'better-studio' ),
					'DESC' => __( 'Descending', 'better-studio' ),
				),
				'show_on'        => array(
					array( 'type=campaign' ),
				),
				//
				"vc_admin_label" => false,
			),
			array(
				"type"           => 'select',
				"name"           => __( 'Align', 'better-studio' ),
				"id"             => 'align',
				"options"        => array(
					'left'   => __( 'Left', 'better-studio' ),
					'center' => __( 'Center', 'better-studio' ),
					'right'  => __( 'Right', 'better-studio' ),
				),
				'show_on'        => array(
					array( 'type=campaign' ),
					array( 'type=banner' ),
				),
				//
				"vc_admin_label" => false,
			),
			array(
				"type"           => 'select',
				"name"           => __( 'Show Captions', 'better-studio' ),
				"id"             => 'show-caption',
				"options"        => array(
					1 => __( 'Show caption\'s', 'better-studio' ),
					0 => __( 'Hide caption\'s', 'better-studio' ),
				),
				'show_on'        => array(
					array( 'type=campaign' ),
					array( 'type=banner' ),
				),
				//
				"vc_admin_label" => false,
			),
			array(
				'name'           => __( 'Lazy Load Ad?', 'better-studio' ),
				'desc'           => __( 'Chose the behaviour of lazy loading.', 'better-studio' ),
				'id'             => 'lazy-load',
				'type'           => 'select',
				"options"        => array(
					''        => __( '-- Inherit from panel --', 'better-studio' ),
					'enable'  => __( 'Yes, Lazy load this ad', 'better-studio' ),
					'disable' => __( 'No, Load this Ad as normal', 'better-studio' ),
				),
				'std'            => 'center',
				'show_on'        => array(
					array(
						'type=banner',
					),
					array(
						'type=campaign',
					),
				),
				'section_class'  => 'better-ads-ad-field',
				//
				"vc_admin_label" => false,
			),
		);
	}


	/**
	 * Registers configuration of tinyMCE views
	 *
	 * @return array
	 */
	function tinymce_settings() {

		$styles = array(
			array(
				'type' => 'custom',
				'url'  => bf_append_suffix( Better_Ads_Manager::dir_url( 'css/bam' ), '.css' ),
			),
		);

		return array(
			'name'   => __( 'Better Ads', 'better-studio' ),
			'styles' => $styles,
		);
	}


	/**
	 * Registers Page Builder Add-on
	 */
	function page_builder_settings() {

		return array(
			'name'           => __( 'Better Ads', 'better-studio' ),
			"id"             => $this->id,
			"weight"         => 10,
			"wrapper_height" => 'full',
			"category"       => $this->block_category(),
			'icon_url'       => Better_Ads_Manager::dir_url( 'images/vc-better-ads.png' ),

		);
	} // page_builder_settings


	/**
	 * Page builder block/map category.
	 */
	public function block_category() {

		global $pagenow;

		if ( defined( 'GUTENBERG_VERSION' ) && GUTENBERG_VERSION ) {

			// can not use is_gutenberg_page() function

			if ( in_array( $pagenow, array(
					'post.php',
					'post-new.php'
				) ) && ! isset( $_GET['classic-editor'] )
			) {

				return 'common';
			}

		}

		return __( 'Better Studio', 'better-studio' );
	}
}
.DS_Store000064400000020004151214525620006226 0ustar00Bud1bwspblob� @� @� @� @libsbwspblob�bplist00�	
			]ShowStatusBar_SidebarWidthTenElevenOrLater[ShowToolbar[ShowTabView_ContainerShowSidebar\WindowBounds[ShowSidebar[ShowPathbar	#@g�		_{{895, 322}, {1427, 869}}	'FR^u�����������libslsvCblob�bplist00�		IJKL_useRelativeDates_showIconPreviewWcolumns_calculateAllSizesXtextSizeZsortColumnXiconSize_viewOptionsVersion		�"&+05:?D�
		ZidentifierUwidthYascendingWvisibleTnameM		�
WvisibleUwidthYascending#Xubiquity�
	\dateModified�	�
#[dateCreated�
'(	Tsizea	�
,-		Tkinds		�
12	Ulabeld	�
67	WversionK	�
;<	Xcomments,	�
@A^dateLastOpened��
GYdateAdded#@(Tname#@0,>FZcnw���������������������!-./8=?@AJOQRS\bdefowyz{������������������M�libslsvpblob^bplist00�		FGHD_useRelativeDates_showIconPreviewWcolumns_calculateAllSizesXtextSizeZsortColumnXiconSize_viewOptionsVersion		�
#(-27<AXcomments^dateLastOpened[dateCreatedTsizeUlabelTkindWversionTname\dateModified�	WvisibleUwidthYascendingUindex,	� "��%'��	*,	a�/	1d	�	4	6	s	�9	;K	�	>	@	M	�	%D	#@(Tname#@0,>FZcnw��������������&')*,5689;DEGHJSTVWYbcefhqrtuw������������I�libsvSrnlongEDSDB `� @� @� @� "��%'��	*,	a�/	1d	�	4	6	s	�9	;K	�	>	@	M	�	%D	#@(Tname#@0,>FZcnw��������������&')*,5689;DEGHJSTVWYbcefhqrtuw������������I�libsvSrnlongfia/bam-fia.php000064400000001701151214525620007312 0ustar00<?php
/**
 * bam-fia.php
 *---------------------------
 * Handles all compatibility tasks for FIA
 *
 */


BAM_FIA::init();


/**
 * Better Ads Manager Facebook Instant Article compatibility
 *
 * @since 1.18.5
 */
class BAM_FIA {


	/**
	 *
	 * @since 1.18.5
	 */
	public static function init() {

		// Custom rules
		add_filter( 'instant_articles_transformer_custom_rules_loaded', array(
			'BAM_FIA',
			'customize_role_transformer'
		) );
	}


	/**
	 * Injects BAM custom rules into FIA plugin
	 *
	 * @param $transformer Transformer
	 *
	 * @return \Transformer
	 */
	public static function customize_role_transformer( $transformer ) {

		// Reads from child theme to override it
		$path = Better_Ads_Manager::dir_path( '/includes/fia/rules-configuration.json' );

		$json = bf_get_local_file_content( $path );

		$json = Better_Ads_Manager()->make_prefix_undetectable( $json );

		$transformer->loadRules( $json );

		return $transformer;
	}
} // BAM_FIA
fia/rules-configuration.json000064400000000405151214525620012177 0ustar00{
  "rules": [
    {
      "class": "PassThroughRule",
      "selector": "div.bsac"
    },
    {
      "class": "PassThroughRule",
      "selector": "div.bsac-container"
    },
    {
      "class": "PassThroughRule",
      "selector": "div.fia-pass"
    }
  ]
}options/metabox-fields-responsive-cb.php000064400000021126151214525660014441 0ustar00<?php

$universal_ads_size = array(
	'240_240'  => '240 x 400 - ' . __( 'Regional ad sizes', 'better-studio' ),
	'580_400'  => '580 x 400 - ' . __( 'Regional ad sizes', 'better-studio' ),
	'250_360'  => '250 x 360 - ' . __( 'Regional ad sizes', 'better-studio' ),
	'980_120'  => '980 x 120 - ' . __( 'Regional ad sizes', 'better-studio' ),
	'750_100'  => '750 x 100 - ' . __( 'Regional ad sizes', 'better-studio' ),
	'750_200'  => '750 x 200 - ' . __( 'Regional ad sizes', 'better-studio' ),
	'750_300'  => '750 x 300 - ' . __( 'Regional ad sizes', 'better-studio' ),
	'930_180'  => '930 x 180 - ' . __( 'Regional ad sizes', 'better-studio' ),
	'120_90'   => '120 x 90',
	'120_240'  => '120 x 240',
	'120_600'  => '120 x 600',
	'125_125'  => '125 x 125',
	'160_160'  => '160 x 90',
	'160_600'  => '160 x 600',
	'180_90'   => '180 x 90',
	'180_150'  => '180 x 150',
	'200_90'   => '200 x 90',
	'200_200'  => '200 x 200',
	'234_60'   => '234 x 60',
	'250_250'  => '250 x 250',
	'320_100'  => '320 x 100',
	'300_250'  => '300 x 250',
	'300_600'  => '300 x 600',
	'300_1050' => '300 x 1050',
	'320_50'   => '320 x 50',
	'336_280'  => '336 x 280',
	'360_300'  => '360 x 300',
	'435_300'  => '435 x 300',
	'468_15'   => '468 x 15',
	'468_60'   => '468 x 60',
	'640_165'  => '640 x 165',
	'640_190'  => '640 x 190',
	'640_300'  => '640 x 300',
	'728_15'   => '728 x 15',
	'728_90'   => '728 x 90',
	'970_90'   => '970 x 90',
	'970_250'  => '970 x 250',
);

$size_list = array(
	'' => 'Auto',
	array(
		'label'   => __( 'General Shapes', 'better-studio' ),
		'options' => array(
			'rectangle'  => __( 'Rectangle Ad', 'better-studio' ),
			'vertical'   => __( 'Vertical Ad', 'better-studio' ),
			'horizontal' => __( 'Horizontal Ad', 'better-studio' ),
		),
	),
	array(
		'label'   => __( 'Universal Ad Sizes', 'better-studio' ),
		'options' => apply_filters( 'better-ads/universal-ad-sizes', $universal_ads_size ),
	),
);

?>
<table class="better-ads-table resp-table">
	<thead>
	<tr>
		<th class="td-device"><?php esc_html_e( 'Device', 'better-studio' ); ?></th>
		<th class="td-show"><?php esc_html_e( 'Show / Hide', 'better-studio' ); ?></th>
		<th class="td-size"><?php esc_html_e( 'Custom Size', 'better-studio' ); ?></th>
	</tr>
	</thead>
	<tbody>
	<tr>
		<td class="td-device"><?php esc_html_e( 'Desktop', 'better-studio' ); ?></td>
		<td class="td-show">
			<?php $field_show = bf_get_post_meta( 'show_desktop', get_the_ID(), '1' ); ?>
			<div class="bf-switch">
				<label
						class="cb-enable <?php echo $field_show == '1' ? 'selected' : ''; ?>"><span><?php esc_html_e( 'Show', 'better-studio' ); ?></span></label>
				<label
						class="cb-disable <?php echo $field_show == '0' ? 'selected' : ''; ?>"><span><?php esc_html_e( 'Hide', 'better-studio' ); ?></span></label>
				<input type="hidden" name="bf-metabox-option[better_ads_banner_options][show_desktop]"
				       value="<?php echo $field_show; ?>" class="checkbox">
			</div>
		</td>
		<td class="td-size">
			<?php $field_size = bf_get_post_meta( 'size_desktop', get_the_ID() ); ?>
			<div class="bf-select-option-container ">
				<select name="bf-metabox-option[better_ads_banner_options][size_desktop]">
					<?php

					foreach ( $size_list as $size_id => $size ) {

						if ( is_array( $size ) ) {

							?>
							<optgroup label="<?php echo $size['label']; ?>">
								<?php

								foreach ( $size['options'] as $size_id => $size ) {
									?>
									<option
											value="<?php echo $size_id ?>" <?php selected( $field_size, $size_id ) ?>><?php echo $size ?></option>
									<?php
								}

								?>
							</optgroup>
							<?php


						} else {
							?>
							<option
									value="<?php echo $size_id ?>" <?php selected( $field_size, $size_id ) ?>><?php echo $size ?></option>
							<?php
						}

					}

					?>
				</select>
			</div>
		</td>
	</tr>
	<tr>
		<td class="td-device"><?php esc_html_e( 'Tablet - Landscape', 'better-studio' ); ?></td>
		<td class="td-show">
			<?php $field_show = bf_get_post_meta( 'show_tablet_landscape', get_the_ID(), '1' ); ?>
			<div class="bf-switch">
				<label
						class="cb-enable <?php echo $field_show == '1' ? 'selected' : ''; ?>"><span><?php esc_html_e( 'Show', 'better-studio' ); ?></span></label>
				<label
						class="cb-disable <?php echo $field_show == '0' ? 'selected' : ''; ?>"><span><?php esc_html_e( 'Hide', 'better-studio' ); ?></span></label>
				<input type="hidden" name="bf-metabox-option[better_ads_banner_options][show_tablet_landscape]"
				       value="<?php echo $field_show; ?>" class="checkbox">
			</div>
		</td>
		<td class="td-size">
			<?php $field_size = bf_get_post_meta( 'size_tablet_landscape', get_the_ID(), '' ); ?>
			<div class="bf-select-option-container ">
				<select name="bf-metabox-option[better_ads_banner_options][size_tablet_landscape]">
					<?php

					foreach ( $size_list as $size_id => $size ) {

						if ( is_array( $size ) ) {

							?>
							<optgroup label="<?php echo $size['label']; ?>">
								<?php

								foreach ( $size['options'] as $size_id => $size ) {
									?>
									<option
											value="<?php echo $size_id ?>" <?php selected( $field_size, $size_id ) ?>><?php echo $size ?></option>
									<?php
								}

								?>
							</optgroup>
							<?php


						} else {
							?>
							<option
									value="<?php echo $size_id ?>" <?php selected( $field_size, $size_id ) ?>><?php echo $size ?></option>
							<?php
						}

					}

					?>
				</select>
			</div>
		</td>
	</tr>
	<tr>
		<td class="td-device"><?php esc_html_e( 'Tablet - Portrait', 'better-studio' ); ?></td>
		<td class="td-show">
			<?php $field_show = bf_get_post_meta( 'show_tablet_portrait', get_the_ID(), '1' ); ?>
			<div class="bf-switch">
				<label
						class="cb-enable <?php echo $field_show == '1' ? 'selected' : ''; ?>"><span><?php esc_html_e( 'Show', 'better-studio' ); ?></span></label>
				<label
						class="cb-disable <?php echo $field_show == '0' ? 'selected' : ''; ?>"><span><?php esc_html_e( 'Hide', 'better-studio' ); ?></span></label>
				<input type="hidden" name="bf-metabox-option[better_ads_banner_options][show_tablet_portrait]"
				       value="<?php echo $field_show; ?>" class="checkbox">
			</div>
		</td>
		<td class="td-size">
			<?php $field_size = bf_get_post_meta( 'size_tablet_portrait', get_the_ID(), '' ); ?>
			<div class="bf-select-option-container ">
				<select name="bf-metabox-option[better_ads_banner_options][size_tablet_portrait]">
					<?php

					foreach ( $size_list as $size_id => $size ) {

						if ( is_array( $size ) ) {

							?>
							<optgroup label="<?php echo $size['label']; ?>">
								<?php

								foreach ( $size['options'] as $size_id => $size ) {
									?>
									<option
											value="<?php echo $size_id ?>" <?php selected( $field_size, $size_id ) ?>><?php echo $size ?></option>
									<?php
								}

								?>
							</optgroup>
							<?php


						} else {
							?>
							<option
									value="<?php echo $size_id ?>" <?php selected( $field_size, $size_id ) ?>><?php echo $size ?></option>
							<?php
						}

					}

					?>
				</select>
			</div>
		</td>
	</tr>
	<tr>
		<td class="td-device"><?php esc_html_e( 'Mobile', 'better-studio' ); ?></td>
		<td class="td-show">
			<?php $field_show = bf_get_post_meta( 'show_phone', get_the_ID(), '1' ); ?>
			<div class="bf-switch">
				<label
						class="cb-enable <?php echo $field_show == '1' ? 'selected' : ''; ?>"><span><?php esc_html_e( 'Show', 'better-studio' ); ?></span></label>
				<label
						class="cb-disable <?php echo $field_show == '0' ? 'selected' : ''; ?>"><span><?php esc_html_e( 'Hide', 'better-studio' ); ?></span></label>
				<input type="hidden" name="bf-metabox-option[better_ads_banner_options][show_phone]"
				       value="<?php echo $field_show; ?>" class="checkbox">
			</div>
		</td>
		<td class="td-size">
			<?php $field_size = bf_get_post_meta( 'size_phone', get_the_ID(), '' ); ?>
			<div class="bf-select-option-container ">
				<select name="bf-metabox-option[better_ads_banner_options][size_phone]">
					<?php

					foreach ( $size_list as $size_id => $size ) {

						if ( is_array( $size ) ) {

							?>
							<optgroup label="<?php echo $size['label']; ?>">
								<?php

								foreach ( $size['options'] as $size_id => $size ) {
									?>
									<option
											value="<?php echo $size_id ?>" <?php selected( $field_size, $size_id ) ?>><?php echo $size ?></option>
									<?php
								}

								?>
							</optgroup>
							<?php


						} else {
							?>
							<option
									value="<?php echo $size_id ?>" <?php selected( $field_size, $size_id ) ?>><?php echo $size ?></option>
							<?php
						}

					}

					?>
				</select>
			</div>
		</td>
	</tr>
	</tbody>
</table>
options/metabox-std.php000064400000004466151214525660011220 0ustar00<?php

/**
 * => Banner Options
 */
$fields['campaign']        = array(
	'std' => 'none',
);
$fields['format']          = array(
	'std' => 'normal',
);
$fields['type']            = array(
	'std' => 'code',
);
$fields['code']            = array(
	'std' => '',
);
$fields['dfp_spot']        = array(
	'std' => '',
);
$fields['custom_dfp_code'] = array(
	'std' => '',
);
$fields['custom_code']     = array(
	'std' => '',
);
$fields['img']             = array(
	'std' => '',
);
$fields['url']             = array(
	'std' => '',
);
$fields['target']          = array(
	'std' => '_blank',
);
$fields['caption']         = array(
	'std' => '',
);
$fields['no_follow']       = array(
	'std' => false,
);
$fields['amp_size']        = array(
	'std' => '300_250',
);
$fields['amp_size_width']  = array(
	'std' => '250',
);
$fields['amp_size_height'] = array(
	'std' => '300',
);


// Following fields only added to make the previous field be saved!
// BF only saves the field you defined to it!
$fields['show_desktop']          = array(
	'type'     => 'id-holder',
	'save-std' => true,
);
$fields['size_desktop']          = array(
	'type'     => 'id-holder',
	'save-std' => true,
);
$fields['show_tablet_portrait']  = array(
	'type'     => 'id-holder',
	'save-std' => true,
);
$fields['size_tablet_portrait']  = array(
	'type'     => 'id-holder',
	'save-std' => true,
);
$fields['show_tablet_landscape'] = array(
	'type'     => 'id-holder',
	'save-std' => true,
);
$fields['size_tablet_landscape'] = array(
	'type'     => 'id-holder',
	'save-std' => true,
);
$fields['show_phone']            = array(
	'type'     => 'id-holder',
	'save-std' => true,
);
$fields['size_phone']            = array(
	'type'     => 'id-holder',
	'save-std' => true,
);


/**
 * => Advanced Settings
 */
$fields['custom_class'] = array(
	'std' => '',
);
$fields['custom_id']    = array(
	'std' => '',
);
$fields['custom_css']   = array(
	'std' => '',
);


/**
 * => AdBlock Fallback
 */
$fields['fallback_type']      = array(
	'std' => 'image',
);
$fields['fallback_code']      = array(
	'std' => '',
);
$fields['fallback_img']       = array(
	'std' => '',
);
$fields['fallback_caption']   = array(
	'std' => '',
);
$fields['fallback_url']       = array(
	'std' => '',
);
$fields['fallback_target']    = array(
	'std' => '_blank',
);
$fields['fallback_no_follow'] = array(
	'std' => false,
);
options/panel-fields-css.php000064400000002232151214525660012107 0ustar00<?php

$fields[]                     = array(
	'name'       => __( 'Custom CSS/JS', 'better-studio' ),
	'id'         => 'custom_css_settings',
	'type'       => 'tab',
	'icon'       => 'bsai-css3',
	'margin-top' => '20',
);
$fields['custom_css_code']    = array(
	'name'       => __( 'Custom CSS Code', 'better-studio' ),
	'id'         => 'custom_css_code',
	'type'       => 'textarea',
	'desc'       => __( 'Paste your CSS code, do not include any tags or HTML in the field. Any custom CSS entered here will override the theme CSS. In some cases, the !important tag may be needed.', 'better-studio' ),
	'input-desc' => __( 'Please <strong>do not</strong> put code inside &lt;style&gt;&lt;/style&gt; tags.', 'better-studio' ),
);
$fields['custom_header_code'] = array(
	'name'       => __( 'HTML/JS Code before &lt;/head&gt;', 'better-studio' ),
	'id'         => 'custom_header_code',
	'input-desc' => __( 'Please put js code inside &lt;script&gt;&lt;/script&gt; tags.', 'better-studio' ),
	'type'       => 'textarea',
	'desc'       => __( 'This code will be placed before &lt;/head&gt; tag in html. Useful if you have an external script that requires it.', 'better-studio' )
);
options/metabox-fields.php000064400000033445151214525660011673 0ustar00<?php

/**
 * => Banner Options
 */
$fields['ad_options'] = array(
	'name' => __( 'Ad', 'better-studio' ),
	'id'   => 'ad_options',
	'type' => 'tab',
	'icon' => 'bsai-advertise',
);
$fields['format']     = array(
	'name'          => __( 'Ad Format', 'better-studio' ),
	'desc'          => __( 'Choose format of ad.', 'better-studio' ),
	'id'            => 'format',
	'type'          => 'image_radio',
	'section_class' => 'style-floated-left bordered bam-image_format',
	'options'       => array(
		'normal' => array(
			'img'   => Better_Ads_Manager::dir_url( '/images/adformat-normal.png?v=' . Better_Ads_Manager::get_version() ),
			'label' => __( 'Normal Ad', 'better-studio' ),
		),
		'amp'    => array(
			'img'   => Better_Ads_Manager::dir_url( '/images/adformat-amp.png?v=' . Better_Ads_Manager::get_version() ),
			'label' => __( 'AMP Ad', 'better-studio' ),
		),
	)
);
$fields['type']       = array(
	'name'          => __( 'Ad Type', 'better-studio' ),
	'desc'          => __( 'Choose type of ad.', 'better-studio' ),
	'id'            => 'type',
	'type'          => 'image_radio',
	'section_class' => 'style-floated-left bordered bam-image_type',
	'options'       => array(
		'code'        => array(
			'img'   => Better_Ads_Manager::dir_url( '/images/adtype-adsense.png?v=' . Better_Ads_Manager::get_version() ),
			'label' => __( 'AdSense Ad', 'better-studio' ),
		),
		'dfp'         => array(
			'img'   => Better_Ads_Manager::dir_url( '/images/adtype-dfp.png?v=' . Better_Ads_Manager::get_version() ),
			'label' => __( 'Google DFP', 'better-studio' ),
		),
		'image'       => array(
			'img'   => Better_Ads_Manager::dir_url( '/images/adtype-image.png?v=' . Better_Ads_Manager::get_version() ),
			'label' => __( 'Image Ad', 'better-studio' ),
		),
		'custom_code' => array(
			'img'   => Better_Ads_Manager::dir_url( '/images/adtype-custom-code.png?v=' . Better_Ads_Manager::get_version() ),
			'label' => __( 'HTML Ad', 'better-studio' ),
		),
	),
);
$fields['code']       = array(
	'name'               => __( 'Google Adsense Code', 'better-studio' ),
	'id'                 => 'code',
	'desc'               => __( 'Paste your Google Adsense.', 'better-studio' ),
	'type'               => 'textarea',
	'section_class'      => 'pre-resp',
	'filter-field'       => 'type',
	'filter-field-value' => 'code',
);
$fields['dfp_spot']   = array(
	'name'             => __( 'Select DTP Spot', 'better-studio' ),
	'id'               => 'dfp_spot',
	'desc'             => __( 'Select DFP sport from list.', 'better-studio' ),
	'type'             => 'select',
	'deferred-options' => 'bam_deferred_dfp_spot_options',
	'show_on'          => array(
		array(
			'type=dfp',
		)
	),
);

$dfp = Better_Ads_Manager::get_option( 'dfp_code' );

if ( empty( $dfp ) ) {
	$fields['dfp_spot']['desc'] = __( '<strong style="color: red">Required:</strong> DFP before &lt;/head&gt; code was not entered. <br><br>', 'better-studio' );

	$fields['dfp_spot']['desc'] .= '<a href="' . admin_url( 'admin.php?page=better-studio/better-ads-manager' ) . '"><strong>' .
	                               __( 'Please enter DFP before &lt;/head&gt; code in Better Ads Manager panel.', 'better-studio' )
	                               . '</strong></a>';
}

$fields['custom_dfp_code'] = array(
	'name'    => __( 'Custom DFP Ad Code', 'better-studio' ),
	'id'      => 'custom_dfp_code',
	'desc'    => __( 'Paste any ad code here.', 'better-studio' ),
	'type'    => 'textarea',
	'show_on' => array(
		array(
			'type=dfp',
			'dfp_spot=custom',
		)
	)
);
$fields['custom_code']     = array(
	'name'               => __( 'Custom Ad Code', 'better-studio' ),
	'id'                 => 'custom_code',
	'desc'               => __( 'Paste any ad code here. <br><br><code>Note:</code> You can use HTML and Shortcodes in this field.', 'better-studio' ),
	'type'               => 'textarea',
	'section_class'      => 'pre-resp',
	'filter-field'       => 'type',
	'filter-field-value' => 'custom_code',
);
$fields['img']             = array(
	'name'               => __( 'Image', 'better-studio' ),
	'id'                 => 'img',
	'desc'               => __( 'Upload or chose ad image.', 'better-studio' ),
	'type'               => 'media_image',
	'media_title'        => __( 'Select or Upload Ad Image', 'better-studio' ),
	'media_button'       => __( 'Select Image', 'better-studio' ),
	'upload_label'       => __( 'Upload Ad Image', 'better-studio' ),
	'remove_label'       => __( 'Remove ', 'better-studio' ),
	'show_input'         => true,
	'input_placeholder'  => __( 'External banner link...', 'better-studio' ),
	'filter-field'       => 'type',
	'filter-field-value' => 'image',
);
$fields['url']             = array(
	'name'               => __( 'Link', 'better-studio' ),
	'id'                 => 'url',
	'desc'               => __( 'Paste you ad link here.', 'better-studio' ),
	'type'               => 'text',
	'filter-field'       => 'type',
	'filter-field-value' => 'image',
);
$fields['target']          = array(
	'name'               => __( 'Link Target', 'better-studio' ),
	'desc'               => __( 'Choose where to open the link?', 'better-studio' ),
	'id'                 => 'target',
	'type'               => 'select',
	"options"            => array(
		'_blank'  => __( '_blank - in new window or tab', 'better-studio' ),
		'_self'   => __( '_self - in the same frame as it was clicked', 'better-studio' ),
		'_parent' => __( '_parent - in the parent frame', 'better-studio' ),
		'_top'    => __( '_top - in the full body of the window', 'better-studio' ),
	),
	'filter-field'       => 'type',
	'filter-field-value' => 'image',
);
$fields['no_follow']       = array(
	'name'               => __( 'Link Rel No Follow', 'better-studio' ),
	'desc'               => __( 'Do you want to add rel nofollow to your link?', 'better-studio' ),
	'id'                 => 'no_follow',
	'type'               => 'switch',
	'section_class'      => 'pre-resp',
	'on-label'           => __( 'Yes', 'better-studio' ),
	'off-label'          => __( 'No', 'better-studio' ),
	'filter-field'       => 'type',
	'filter-field-value' => 'image',
);
$fields['amp_size']        = array(
	'name'    => __( 'Ad Size', 'better-studio' ),
	'desc'    => __( 'Chose Ad Size', 'better-studio' ),
	'id'      => 'amp_size',
	'type'    => 'select',
	"options" => array(
		'custom'  => __( '-- Custom Ad Size --', 'better-studio' ),
		'240_240' => __( '240 x 400', 'better-studio' ),
		'250_360' => __( '250 x 360', 'better-studio' ),
		'300_250' => __( '300 x 250 - Suggested', 'better-studio' ),
		'320_140' => __( '320 x 140', 'better-studio' ),
		'400_300' => __( '400 x 300', 'better-studio' ),
	),
	'show_on' => array(
		array(
			'format=amp',
			'type=code'
		),
	),
);
$fields['amp_size_width']  = array(
	'name'    => __( 'Ad Custom Width', 'better-studio' ),
	'desc'    => __( 'Enter only number without px or %.', 'better-studio' ),
	'id'      => 'amp_size_width',
	'type'    => 'text',
	'show_on' => array(
		array(
			'format=amp',
			'type=code',
			'amp_size=custom',
		),
	),
);
$fields['amp_size_height'] = array(
	'name'    => __( 'Ad Custom Height', 'better-studio' ),
	'desc'    => __( 'Enter only number without px or %.', 'better-studio' ),
	'id'      => 'amp_size_height',
	'type'    => 'text',
	'show_on' => array(
		array(
			'format=amp',
			'type=code',
			'amp_size=custom',
		),
	),
);
$fields['caption']         = array(
	'name' => __( 'Caption', 'better-studio' ),
	'id'   => 'caption',
	'desc' => __( 'Optional caption that will be shown after ad.', 'better-studio' ),
	'type' => 'text',
);
$fields[]                  = array(
	'name'            => '',
	'id'              => 'responsive_options',
	'section_class'   => 'full-width-controls',
	'container_class' => 'responsive-field-container',
	'type'            => 'custom',
	'input_callback'  => 'better_ads_field_responsive_callback'
);
// Following fields only added to make the previous field be saved!
// BF only saves the field you defined to it!
$fields['show_desktop']          = array(
	'type'     => 'id-holder',
	'save-std' => true,
);
$fields['size_desktop']          = array(
	'type'     => 'id-holder',
	'save-std' => true,
);
$fields['show_tablet_portrait']  = array(
	'type'     => 'id-holder',
	'save-std' => true,
);
$fields['size_tablet_portrait']  = array(
	'type'     => 'id-holder',
	'save-std' => true,
);
$fields['show_tablet_landscape'] = array(
	'type'     => 'id-holder',
	'save-std' => true,
);
$fields['size_tablet_landscape'] = array(
	'type'     => 'id-holder',
	'save-std' => true,
);
$fields['show_phone']            = array(
	'type'     => 'id-holder',
	'save-std' => true,
);
$fields['size_phone']            = array(
	'type'     => 'id-holder',
	'save-std' => true,
);


/**
 * => Advanced Settings
 */
$fields['style_tab']    = array(
	'name' => __( 'Style', 'better-studio' ),
	'id'   => 'style_tab',
	'type' => 'tab',
	'icon' => 'bsai-paint',
);
$fields['custom_class'] = array(
	'name' => __( 'Custom Class', 'better-studio' ),
	'id'   => 'custom_class',
	'type' => 'text',
	'desc' => __( 'This classes will be added to banner wrapper tag.<br>Separate classes with space.', 'better-studio' )
);
$fields['custom_id']    = array(
	'name' => __( 'Custom ID', 'better-studio' ),
	'id'   => 'custom_id',
	'type' => 'text',
	'desc' => __( 'This id will be added to banner wrapper tag.', 'better-studio' )
);
$fields['custom_css']   = array(
	'name' => __( 'Custom CSS', 'better-studio' ),
	'id'   => 'custom_css',
	'type' => 'textarea',
	'desc' => __( 'Paste your CSS code, do not include any tags or HTML in the field. Any custom CSS entered here will override the default CSS. In some cases, the !important tag may be needed.', 'better-studio' )
);


/**
 * => AdBlock Fallback
 * todo change icon to better one
 */
$fields['adblock_options']    = array(
	'name'       => __( 'Ad Blockers', 'better-studio' ),
	'id'         => 'adblock_options',
	'type'       => 'tab',
	'icon'       => 'bsai-delete',
	'margin-top' => '20',
	'badge'      => array(
		'text'  => __( 'New', 'better-studio' ),
		'color' => '#62D393'
	)
);
$fields['adblock-help']       = array(
	'name'          => __( 'Ad Blockers Fallback', 'better-studio' ),
	'id'            => 'adblock-help',
	'type'          => 'info',
	'std'           => __( '<p>Ad Blockers prevents page elements, mainly advertisements from being displayed that can hurts the main purpose of your site advertisement goals.</p>
                <p>We take and advanced attention to this and you can use following options to make fallback for when the main ad was detected with blockers.</p>
                <p><strong>Note:</strong> Ad Blockers can not detect simple image ads but use this option to external ad generators like Google Adsense.</p>', 'better-studio' ),
	'state'         => 'open',
	'info-type'     => 'help',
	'section_class' => 'widefat',
);
$fields['fallback_type']      = array(
	'name'    => __( 'Fallback Type', 'better-studio' ),
	'desc'    => __( 'Choose type of fallback for ad.', 'better-studio' ),
	'id'      => 'fallback_type',
	'type'    => 'select',
	'options' => array(
		'image' => __( 'Image', 'better-studio' ),
		'code'  => __( 'HTML Code', 'better-studio' ),
	)
);
$fields['fallback_code']      = array(
	'name'               => __( 'Custom HTML Code', 'better-studio' ),
	'id'                 => 'fallback_code',
	'desc'               => __( 'Paste your custom HTML code. Yo can add css code also within &lt;style&gt;&lt;/style&gt;', 'better-studio' ),
	'type'               => 'textarea',
	'container_class'    => 'fallback-code-field',
	'filter-field'       => 'fallback_type',
	'filter-field-value' => 'code',
);
$fields['fallback_img']       = array(
	'name'               => __( 'Fallback Image', 'better-studio' ),
	'id'                 => 'fallback_img',
	'desc'               => __( 'Upload or chose fallback image for ad.', 'better-studio' ),
	'type'               => 'media_image',
	'media_title'        => __( 'Select or Upload Ad Image', 'better-studio' ),
	'media_button'       => __( 'Select Image', 'better-studio' ),
	'upload_label'       => __( 'Upload Image', 'better-studio' ),
	'remove_label'       => __( 'Remove', 'better-studio' ),
	'filter-field'       => 'fallback_type',
	'filter-field-value' => 'image',
);
$fields['fallback_caption']   = array(
	'name'               => __( 'Caption', 'better-studio' ),
	'id'                 => 'fallback_caption',
	'desc'               => __( 'Optional caption that will be shown after Image.', 'better-studio' ),
	'type'               => 'text',
	'filter-field'       => 'fallback_type',
	'filter-field-value' => 'image',
);
$fields['fallback_url']       = array(
	'name'               => __( 'Link', 'better-studio' ),
	'id'                 => 'fallback_url',
	'desc'               => __( 'Paste you ad link here.', 'better-studio' ),
	'type'               => 'text',
	'filter-field'       => 'fallback_type',
	'filter-field-value' => 'image',
);
$fields['fallback_target']    = array(
	'name'               => __( 'Link Target', 'better-studio' ),
	'desc'               => __( 'Choose where To Open The link?', 'better-studio' ),
	'id'                 => 'fallback_target',
	'type'               => 'select',
	"options"            => array(
		'_blank'  => __( '_blank - in new window or tab', 'better-studio' ),
		'_self'   => __( '_self - in the same frame as it was clicked', 'better-studio' ),
		'_parent' => __( '_parent - in the parent frame', 'better-studio' ),
		'_top'    => __( '_top - in the full body of the window', 'better-studio' ),
	),
	'filter-field'       => 'fallback_type',
	'filter-field-value' => 'image',
);
$fields['fallback_no_follow'] = array(
	'name'               => __( 'Link Rel No Follow', 'better-studio' ),
	'desc'               => __( 'Do you want to add rel nofollow to your link?', 'better-studio' ),
	'id'                 => 'fallback_no_follow',
	'type'               => 'switch',
	'on-label'           => __( 'Yes', 'better-studio' ),
	'off-label'          => __( 'No', 'better-studio' ),
	'filter-field'       => 'fallback_type',
	'filter-field-value' => 'image',
);

options/taxonomy.php000064400000012203151214525660010633 0ustar00<?php

add_filter( 'better-framework/taxonomy/metabox/add', 'better_ads_manager_taxonomy_metabox_add', 20 );

if ( ! function_exists( 'better_ads_manager_taxonomy_metabox_add' ) ) {
	/**
	 * Adds metabox for taxonomies
	 *
	 * @param $metabox array
	 *
	 * @return array
	 */
	function better_ads_manager_taxonomy_metabox_add( $metabox ) {

		$metabox['better_ads_taxonomy_metabox'] = array(
			'panel-id' => Better_Ads_Manager::$panel_id,
			'css'      => true,
		);

		return $metabox;
	}
}


add_filter( 'better-framework/taxonomy/metabox/better_ads_taxonomy_metabox/config', 'better_ads_manager_taxonomy_metabox_config', 10 );

if ( ! function_exists( 'better_ads_manager_taxonomy_metabox_config' ) ) {
	/**
	 * Configs taxonomy metabox
	 *
	 * @return array
	 */
	function better_ads_manager_taxonomy_metabox_config() {

		//
		// Support to custom taxonomies
		//

		$sections = better_ads_get_override_sections_list();

		if ( empty( $sections['taxonomy']['items'] ) ) {
			return array();
		}

		$taxonomies = array_keys( $sections['taxonomy']['items'] );

		return array(
			'taxonomies' => $taxonomies,
			'name'       => __( 'Better Ads Manager', 'better-studio' )
		);

	} // better_ads_manager_metabox_config
} // if


add_filter( 'better-framework/taxonomy/metabox/better_ads_taxonomy_metabox/std', 'better_ads_manager_taxonomy_metabox_std', 10 );

if ( ! function_exists( 'better_ads_manager_taxonomy_metabox_std' ) ) {
	/**
	 * Configs taxonomy metabox STD's
	 *
	 * @param $fields
	 *
	 * @return array
	 */
	function better_ads_manager_taxonomy_metabox_std( $fields ) {

		global $tag;

		//
		// Current term inside ajax tab
		//
		if ( bf_is_doing_ajax() ) {

			if ( ! ( isset( $_POST['action'] ) && $_POST['action'] == 'bf_ajax' && $_POST['type'] == 'taxonomy' ) ) {
				return $fields;
			} else {


				$tag = get_term( $_POST['object_id'] );

				if ( ! $tag || is_wp_error( $tag ) ) {
					return $fields;
				}
			}
		}

		if ( empty( $tag->taxonomy ) ) {
			return $fields;
		}

		$sections = better_ads_get_override_sections_list();
		$section  = $sections['taxonomy']['items'][ $tag->taxonomy ];
		$args     = array(
			'id'           => $section['id'] . '_top_level',
			'section-name' => $section['label'],
			'section'      => $section['id'],
			'type'         => 'taxonomy',
		);

		foreach ( better_ads_section_override_fields_list( $args ) as $id => $field ) {
			$fields[ $id ] = array(
				'std'      => isset( $field['std'] ) ? $field['std'] : '',
				'save-std' => false,
			);
		}

		$fields['bam_disable_all']          = array(
			'std'      => '',
			'save-std' => false,
		);
		$fields['bam_disable_locations']    = array(
			'std'      => '',
			'save-std' => false,
		);
		$fields['bam_disable_widgets']      = array(
			'std'      => '',
			'save-std' => false,
		);
		$fields['bam_disable_post_content'] = array(
			'std'      => '',
			'save-std' => false,
		);

		return $fields;
	}
}


add_filter( 'better-framework/taxonomy/metabox/better_ads_taxonomy_metabox/fields', 'better_ads_manager_taxonomy_metabox_fields', 10 );

if ( ! function_exists( 'better_ads_manager_taxonomy_metabox_fields' ) ) {
	/**
	 * Configs taxonomy metabox fields
	 *
	 * @param $fields
	 *
	 * @return array
	 */
	function better_ads_manager_taxonomy_metabox_fields( $fields ) {

		$taxonomy = '';

		if ( bf_is_doing_ajax() ) {

			global $wp_version, $wpdb;

			if ( isset( $_REQUEST['object_id'] ) ) {

				$params = array( $_REQUEST['object_id'] );
				if ( version_compare( '4.4.0', $wp_version, '>' ) ) { // WP < 4.4 support
					// Get taxonomy by term id
					$params[1] = $wpdb->get_var( $wpdb->prepare( "SELECT taxonomy FROM $wpdb->term_taxonomy WHERE term_id = %d", $_REQUEST['object_id'] ) );
				}

				$term = call_user_func_array( 'get_term', $params );

				if ( $term && ! is_wp_error( $term ) ) {
					$taxonomy = $term->taxonomy;
				}


			} elseif ( isset( $_REQUEST['taxonomy'] ) && taxonomy_exists( $_REQUEST['taxonomy'] ) ) {

				$taxonomy = $_REQUEST['taxonomy'];

			}

		} else {
			global $taxonomy;
		}

		if ( ! $taxonomy ) {
			return $fields;
		}

		$sections       = better_ads_get_override_sections_list();
		$section_fields = array(); // fields of ajax tab


		$fields['ads'] = array(
			'name' => __( 'Ads', 'better-studio' ),
			'id'   => 'ads',
			'type' => 'tab',
			'icon' => 'bsai-advertise',
		);

		$fields = better_ads_section_disable_fields_list( $fields, array(
			'type' => 'taxonomy'
		) );

		if ( isset( $sections['taxonomy']['items'][ $taxonomy ] ) ) {

			$fields['ads_override'] = array(
				'name'         => __( 'Override Ads', 'better-studio' ),
				'id'           => 'ads_override',
				'type'         => 'tab',
				'icon'         => 'bsai-goal',
				'ajax-section' => 'bf-ajax-tab',
			);

			$section_fields = better_ads_section_override_fields_list(
				array(
					'id'                 => $sections['taxonomy']['items'][ $taxonomy ]['id'] . '_top_level',
					'type'               => 'taxonomy',
					'section'            => $sections['taxonomy']['items'][ $taxonomy ]['id'],
					'section-name'       => $sections['taxonomy']['items'][ $taxonomy ]['label'],
					'ajax-section-field' => 'ads_override',
				)
			);
		}

		return $fields + $section_fields;
	}
}
options/metabox.php000064400000024405151214525660010423 0ustar00<?php


add_filter( 'better-framework/metabox/add', 'better_ads_manager_metabox_add', 100 );

if ( ! function_exists( 'better_ads_manager_metabox_add' ) ) {
	/**
	 * Adds metabox to BF
	 *
	 * @param $metabox array
	 *
	 * @return array
	 */
	function better_ads_manager_metabox_add( $metabox ) {

		$metabox['better_ads_banner_options'] = array(
			'panel-id' => Better_Ads_Manager::$panel_id,
		);

		$metabox['better_ads_banner_campaign_options'] = array(
			'panel-id' => Better_Ads_Manager::$panel_id,
		);

		$metabox['better_ads_campaign_options'] = array(
			'panel-id' => Better_Ads_Manager::$panel_id,
		);

		$metabox['better_ads_post_metabox'] = array(
			'panel-id' => Better_Ads_Manager::$panel_id,
		);

		return $metabox;
	}
}

add_filter( 'better-framework/metabox/better_ads_banner_options/config', 'better_ads_manager_metabox_banner_config', 10 );

if ( ! function_exists( 'better_ads_manager_metabox_banner_config' ) ) {
	/**
	 * Configs custom metaboxe
	 *
	 * @param $config
	 *
	 * @return array
	 */
	function better_ads_manager_metabox_banner_config( $config ) {

		return array(
			'title'    => __( 'Banner Options', 'better-studio' ),
			'pages'    => array( 'better-banner' ),
			'context'  => 'normal',
			'prefix'   => false,
			'priority' => 'high'
		);

	} // better_ads_manager_metabox_config
} // if

add_filter( 'better-framework/metabox/better_ads_banner_options/std', 'better_ads_manager_metabox_std', 10 );

if ( ! function_exists( 'better_ads_manager_metabox_std' ) ) {
	/**
	 * Configs metaboxe STD's
	 *
	 * @param $fields
	 *
	 * @return array
	 */
	function better_ads_manager_metabox_std( $fields ) {

		include Better_Ads_Manager::dir_path( 'includes/options/metabox-std.php' );

		return $fields;
	}
}


add_filter( 'better-framework/metabox/better_ads_banner_options/fields', 'better_ads_manager_metabox_fields', 10 );

if ( ! function_exists( 'better_ads_manager_metabox_fields' ) ) {
	/**
	 * Configs metaboxe fields
	 *
	 * @param $fields
	 *
	 * @return array
	 */
	function better_ads_manager_metabox_fields( $fields ) {

		include Better_Ads_Manager::dir_path( 'includes/options/metabox-fields.php' );

		return $fields;
	}
}

if ( ! function_exists( 'better_ads_field_responsive_callback' ) ) {
	/**
	 * Callback for responsive field
	 *
	 * @since 1.4.1
	 */
	function better_ads_field_responsive_callback() {

		include Better_Ads_Manager::dir_path( 'includes/options/metabox-fields-responsive-cb.php' );

	} // better_ads_field_responsive_callback
}


add_filter( 'better-framework/metabox/better_ads_campaign_options/config', 'better_ads_manager_metabox_campaign_config', 10 );

if ( ! function_exists( 'better_ads_manager_metabox_campaign_config' ) ) {
	/**
	 * Configs custom metaboxe
	 *
	 * @param $config
	 *
	 * @return array
	 */
	function better_ads_manager_metabox_campaign_config( $config ) {

		return array(
			'title'    => __( 'Better Campaign Options', 'better-studio' ),
			'pages'    => array( 'better-campaign' ),
			'context'  => 'normal',
			'prefix'   => false,
			'priority' => 'high'
		);

	} // better_ads_manager_metabox_config
} // if


add_filter( 'better-framework/metabox/better_ads_campaign_options/fields', 'better_ads_manager_metabox_campaign_fields', 10 );

if ( ! function_exists( 'better_ads_manager_metabox_campaign_fields' ) ) {
	/**
	 * Configs metaboxe fields
	 *
	 * @param $fields
	 *
	 * @return array
	 */
	function better_ads_manager_metabox_campaign_fields( $fields ) {

		$fields['campaign_options'] = array(
			'name' => __( 'Campaign', 'better-studio' ),
			'id'   => 'campaign_options',
			'type' => 'tab',
			'icon' => 'bsai-gear',
		);
		$fields['desc']             = array(
			'name'          => __( 'Campaign Note & Description', 'better-studio' ),
			'id'            => 'desc',
			'type'          => 'textarea',
			'section_class' => 'full-with-both',
		);

		return $fields;
	}
}


add_filter( 'better-framework/metabox/better_ads_campaign_options/std', 'better_ads_manager_metabox_campaign_std', 10 );

if ( ! function_exists( 'better_ads_manager_metabox_campaign_std' ) ) {
	/**
	 * Configs metaboxe fields
	 *
	 * @param $fields
	 *
	 * @return array
	 */
	function better_ads_manager_metabox_campaign_std( $fields ) {

		$fields['desc'] = array(
			'std' => '',
		);

		return $fields;
	}
}


add_filter( 'better-framework/metabox/better_ads_banner_campaign_options/config', 'better_ads_manager_metabox_banner_campaign_config', 10 );

if ( ! function_exists( 'better_ads_manager_metabox_banner_campaign_config' ) ) {
	/**
	 * Configs custom metaboxe
	 *
	 * @param $config
	 *
	 * @return array
	 */
	function better_ads_manager_metabox_banner_campaign_config( $config ) {

		return array(
			'title'    => __( 'Campaign of Ad', 'better-studio' ),
			'pages'    => array( 'better-banner' ),
			'context'  => 'side',
			'prefix'   => false,
			'priority' => 'high'
		);

	} // better_ads_manager_metabox_config
} // if


add_filter( 'better-framework/metabox/better_ads_banner_campaign_options/fields', 'better_ads_manager_metabox_banner_campaign_fields', 10 );

if ( ! function_exists( 'better_ads_manager_metabox_banner_campaign_fields' ) ) {
	/**
	 * Configs metaboxe fields
	 *
	 * @param $fields
	 *
	 * @return array
	 */
	function better_ads_manager_metabox_banner_campaign_fields( $fields ) {

		$fields['campaign'] = array(
			'name'             => __( 'Select a campaign for this ad', 'better-studio' ),
			'input-desc'       => __( 'Hold the "CTRL in Windows" or "Command in Mac" to select multiple items.', 'better-studio' ),
			'id'               => 'campaign',
			'type'             => 'select',
			'section_class'    => 'full-with-both',
			'container_class'  => 'campaign-field',
			'deferred-options' => array(
				'callback' => 'better_ads_get_campaigns_option',
				'args'     => array(
					- 1,
					true
				),
			),
			'section-css'      => array(
				'background' => '#f7f7f7',
			),
			'multiple'         => true,
		);

		return $fields;
	}
}


add_filter( 'better-framework/metabox/better_ads_banner_campaign_options/std', 'better_ads_manager_metabox_banner_campaign_std', 10 );

if ( ! function_exists( 'better_ads_manager_metabox_banner_campaign_std' ) ) {
	/**
	 * Configs metaboxe fields
	 *
	 * @param $fields
	 *
	 * @return array
	 */
	function better_ads_manager_metabox_banner_campaign_std( $fields ) {

		$fields['campaign'] = array(
			'std' => '',
		);

		return $fields;
	}
}


add_filter( 'better-framework/metabox/better_ads_post_metabox/config', 'better_ads_manager_post_metabox', 15 );

if ( ! function_exists( 'better_ads_manager_post_metabox' ) ) {
	/**
	 * Configs custom metabox
	 *
	 * @return array
	 */
	function better_ads_manager_post_metabox() {

		$sections = better_ads_get_override_sections_list();

		if ( empty( $sections['post_type']['items'] ) ) {
			return array();
		}

		return array(
			'title'   => __( 'Better Ads Manager', 'better-studio' ),
			'pages'   => array_keys( $sections['post_type']['items'] ),
			'context' => 'normal',
			'prefix'  => false,
		);

	} // better_ads_manager_metabox_config
} // if


add_filter( 'better-framework/metabox/better_ads_post_metabox/std', 'better_ads_manager_post_metabox_std', 10 );

if ( ! function_exists( 'better_ads_manager_post_metabox_std' ) ) {
	/**
	 * Configs metaboxe STD's
	 *
	 * @param $fields
	 *
	 * @return array
	 */
	function better_ads_manager_post_metabox_std( $fields ) {

		if ( bf_is_doing_ajax() ) {

			if ( ! isset( $_REQUEST['object_id'] ) ) {
				return $fields;
			}

			if ( ! ( $post = get_post( $_REQUEST['object_id'] ) ) ) {
				return $fields;
			}
		} else {
			global $post;
		}

		if ( empty( $post ) ) {
			return $fields;
		}


		$sections = better_ads_get_override_sections_list();

		if ( ! isset( $sections['post_type']['items'][ $post->post_type ] ) ) {
			return $fields;
		}

		$section = $sections['post_type']['items'][ $post->post_type ];

		$args = array(
			'id'           => $section['id'] . '_top_level',
			'section-name' => $section['label'],
			'section'      => $section['id'],
			'type'         => 'post_type',
		);

		foreach ( better_ads_section_override_fields_list( $args ) as $id => $field ) {
			$fields[ $id ] = array(
				'std'      => isset( $field['std'] ) ? $field['std'] : '',
				'save-std' => false,
			);
		}

		$fields['bam_disable_all']          = array(
			'std'      => '',
			'save-std' => false,
		);
		$fields['bam_disable_locations']    = array(
			'std'      => '',
			'save-std' => false,
		);
		$fields['bam_disable_widgets']      = array(
			'std'      => '',
			'save-std' => false,
		);
		$fields['bam_disable_post_content'] = array(
			'std'      => '',
			'save-std' => false,
		);

		return $fields;
	}
}


add_filter( 'better-framework/metabox/better_ads_post_metabox/fields', 'better_ads_manager_post_metabox_fields', 10 );

if ( ! function_exists( 'better_ads_manager_post_metabox_fields' ) ) {
	/**
	 * Configs metabox fields
	 *
	 * @param $fields
	 *
	 * @return array
	 */
	function better_ads_manager_post_metabox_fields( $fields ) {

		if ( bf_is_doing_ajax() ) {

			if ( ! isset( $_REQUEST['object_id'] ) ) {
				return $fields;
			}

			if ( ! ( $post = get_post( $_REQUEST['object_id'] ) ) ) {
				return $fields;
			}

		} else {
			global $post;
		}

		if ( empty( $post ) ) {
			return $fields;
		}


		$sections       = better_ads_get_override_sections_list();
		$section_fields = array(); // fields of ajax tab

		$fields['ads'] = array(
			'name' => __( 'Ads', 'better-studio' ),
			'id'   => 'ads',
			'type' => 'tab',
			'icon' => 'bsai-advertise',
		);

		$fields = better_ads_section_disable_fields_list( $fields, array(
			'type' => 'post'
		) );

		if ( isset( $sections['post_type']['items'][ $post->post_type ] ) ) {

			$fields['ads_override'] = array(
				'name'         => __( 'Override Ads', 'better-studio' ),
				'id'           => 'ads_override',
				'type'         => 'tab',
				'icon'         => 'bsai-goal',
				'ajax-section' => 'bf-ajax-tab',
			);

			$section_fields = better_ads_section_override_fields_list(
				array(
					'id'                 => $sections['post_type']['items'][ $post->post_type ]['id'] . '_top_level',
					'type'               => 'post_type',
					'section'            => $sections['post_type']['items'][ $post->post_type ]['id'],
					'section-name'       => $sections['post_type']['items'][ $post->post_type ]['label'],
					'ajax-section-field' => 'ads_override',
				)
			);

		}

		return $fields + $section_fields;
	}
}dynamics/editor_css.php000064400000001352151214525660011232 0ustar00<?php
/***
 *
 * Special CSS for TinyMCE
 *
 */

$default_printed = FALSE;

?>
.mce-content-body *[data-wpview-type="better-ads"]{
	margin-bottom: 25px;
	outline: 1px dashed transparent !important;
	transition: all .5s ease;
}
.mce-content-body:hover *[data-wpview-type="better-ads"]{
	outline-color: #e9e9e9 !important;
}
.mce-content-body *[data-wpview-type="better-ads"][data-mce-selected]{
	outline-color: #3372a0 !important;
}
.mce-content-body *[data-wpview-type="better-ads"][data-wpview-text*="%22%20align%3D%22right"]{
	float: right;
width: auto !important;
	margin-left: 25px;
}
.mce-content-body *[data-wpview-type="better-ads"][data-wpview-text*="%22%20align%3D%22left"]{
	float: left;
	width: auto !important;
	margin-right: 25px;
}

F1le Man4ger