diff --git a/functions.php b/functions.php
new file mode 100644
index 0000000..a80314b
--- /dev/null
+++ b/functions.php
@@ -0,0 +1,261 @@
+ 'Font Awesome Icons',
+ 'slug' => 'font-awesome',
+ 'required' => true,
+ ),
+
+ // Optional plugins
+ array(
+ 'name' => 'Black Studio TinyMCE Widget',
+ 'slug' => 'black-studio-tinymce-widget',
+ 'required' => true,
+ ),
+
+ array(
+ 'name' => 'Events Manager',
+ 'slug' => 'events-manager',
+ 'required' => true,
+ ),
+
+ array(
+ 'name' => 'Exclude Pages',
+ 'slug' => 'exclude-pages',
+ 'required' => true,
+ ),
+
+ array(
+ 'name' => 'Genesis Simple Edits',
+ 'slug' => 'genesis-simple-edits',
+ 'required' => true,
+ ),
+
+ array(
+ 'name' => 'MapPress Easy Google Maps',
+ 'slug' => 'mappress-google-maps-for-wordpress',
+ 'required' => true,
+ ),
+
+ array(
+ 'name' => 'My Page Order',
+ 'slug' => 'my-page-order',
+ 'required' => true,
+ ),
+
+ array(
+ 'name' => 'NextGen Gallery',
+ 'slug' => 'nextgen-gallery',
+ 'required' => true,
+ ),
+
+ array(
+ 'name' => 'Post Thumbnail Editor',
+ 'slug' => 'post-thumbnail-editor',
+ 'required' => true,
+ ),
+
+ array(
+ 'name' => 'Social Media Widget',
+ 'slug' => 'social-media-widget',
+ 'required' => true,
+ ),
+
+ array(
+ 'name' => 'Widget Context',
+ 'slug' => 'widget-context',
+ 'required' => true,
+ ),
+
+ array(
+ 'name' => 'Genesis Featured Widget Amplified',
+ 'slug' => 'genesis-featured-widget-amplified',
+ 'required' => true,
+ ),
+
+ array(
+ 'name' => 'Respond.js',
+ 'slug' => 'respondjs',
+ 'required' => true,
+ ),
+
+ array(
+ 'name' => 'Simple Image Sizes',
+ 'slug' => 'simple-image-sizes',
+ 'required' => true,
+ ),
+
+ array(
+ 'name' => 'Types - Custom Fields and Custom Post Types Management',
+ 'slug' => 'types',
+ 'required' => true,
+ ),
+
+ );
+
+ // Change this to your theme text domain, used for internationalising strings
+ $theme_text_domain = 'mightyminnow';
+
+ /**
+ * Array of configuration settings. Amend each line as needed.
+ * If you want the default strings to be available under your own theme domain,
+ * leave the strings uncommented.
+ * Some of the strings are added into a sprintf, so see the comments at the
+ * end of each line for what each argument will be.
+ */
+ $config = array(
+ 'domain' => $theme_text_domain, // Text domain - likely want to be the same as your theme.
+ 'default_path' => '', // Default absolute path to pre-packaged plugins
+ 'parent_menu_slug' => 'themes.php', // Default parent menu slug
+ 'parent_url_slug' => 'themes.php', // Default parent URL slug
+ 'menu' => 'install-required-plugins', // Menu slug
+ 'has_notices' => true, // Show admin notices or not
+ 'is_automatic' => true, // Automatically activate plugins after installation or not
+ 'message' => '', // Message to output right before the plugins table
+ 'strings' => array(
+ 'page_title' => __( 'Install Required Plugins', $theme_text_domain ),
+ 'menu_title' => __( 'Install Plugins', $theme_text_domain ),
+ 'installing' => __( 'Installing Plugin: %s', $theme_text_domain ), // %1$s = plugin name
+ 'oops' => __( 'Something went wrong with the plugin API.', $theme_text_domain ),
+ 'notice_can_install_required' => _n_noop( 'This theme requires the following plugin: %1$s.', 'This theme requires the following plugins: %1$s.' ), // %1$s = plugin name(s)
+ 'notice_can_install_recommended' => _n_noop( 'This theme recommends the following plugin: %1$s.', 'This theme recommends the following plugins: %1$s.' ), // %1$s = plugin name(s)
+ 'notice_cannot_install' => _n_noop( 'Sorry, but you do not have the correct permissions to install the %s plugin. Contact the administrator of this site for help on getting the plugin installed.', 'Sorry, but you do not have the correct permissions to install the %s plugins. Contact the administrator of this site for help on getting the plugins installed.' ), // %1$s = plugin name(s)
+ 'notice_can_activate_required' => _n_noop( 'The following required plugin is currently inactive: %1$s.', 'The following required plugins are currently inactive: %1$s.' ), // %1$s = plugin name(s)
+ 'notice_can_activate_recommended' => _n_noop( 'The following recommended plugin is currently inactive: %1$s.', 'The following recommended plugins are currently inactive: %1$s.' ), // %1$s = plugin name(s)
+ 'notice_cannot_activate' => _n_noop( 'Sorry, but you do not have the correct permissions to activate the %s plugin. Contact the administrator of this site for help on getting the plugin activated.', 'Sorry, but you do not have the correct permissions to activate the %s plugins. Contact the administrator of this site for help on getting the plugins activated.' ), // %1$s = plugin name(s)
+ 'notice_ask_to_update' => _n_noop( 'The following plugin needs to be updated to its latest version to ensure maximum compatibility with this theme: %1$s.', 'The following plugins need to be updated to their latest version to ensure maximum compatibility with this theme: %1$s.' ), // %1$s = plugin name(s)
+ 'notice_cannot_update' => _n_noop( 'Sorry, but you do not have the correct permissions to update the %s plugin. Contact the administrator of this site for help on getting the plugin updated.', 'Sorry, but you do not have the correct permissions to update the %s plugins. Contact the administrator of this site for help on getting the plugins updated.' ), // %1$s = plugin name(s)
+ 'install_link' => _n_noop( 'Begin installing plugin', 'Begin installing plugins' ),
+ 'activate_link' => _n_noop( 'Activate installed plugin', 'Activate installed plugins' ),
+ 'return' => __( 'Return to Required Plugins Installer', $theme_text_domain ),
+ 'plugin_activated' => __( 'Plugin activated successfully.', $theme_text_domain ),
+ 'complete' => __( 'All plugins installed and activated successfully. %s', $theme_text_domain ), // %1$s = dashboard link
+ 'nag_type' => 'updated' // Determines admin notice type - can only be 'updated' or 'error'
+ )
+ );
+
+ tgmpa( $plugins, $config );
+
+}
+add_action( 'tgmpa_register', 'register_required_plugins' );
+
+
+/*===========================================
+ * Auto & Mobile Navigation
+===========================================*/
+
+function mm_nav_modifications() {
+
+ // Auto-generate nav if Genesis theme setting is checked
+ if ( 1 == genesis_get_option( 'auto_nav' ) ) {
+
+ // Replace existing nav with auto-generated nav
+ function mm_auto_nav() {
+
+ $args = array(
+ 'echo' => false,
+ 'show_home' => genesis_get_option( 'include_home_link' ),
+ 'menu_class' => ''
+ );
+
+ $ul_class = 'menu genesis-nav-menu menu-primary';
+
+ $nav = preg_replace('/
/', '', wp_page_menu( $args ) , 1);
+
+ $nav_markup_open = genesis_markup( array(
+ 'html5' => '',
+ 'xhtml' => '',
+ 'context' => 'nav-primary',
+ 'echo' => false,
+ ) );
+ $nav_markup_open .= genesis_structural_wrap( 'menu-primary', 'open', 0 );
+
+ $nav_markup_close = genesis_structural_wrap( 'menu-primary', 'close', 0 );
+ $nav_markup_close .= genesis_html5() ? '' : '
';
+
+ echo apply_filters ( 'mm_do_nav', $nav_markup_open . $nav . $nav_markup_close );
+ }
+ add_action( 'genesis_do_nav', 'mm_auto_nav', 10 );
+
+ }
+
+ // Add mobile menu button
+ function mm_add_mobile_nav() {
+ echo '';
+ }
+ add_action( 'genesis_after_header', 'mm_add_mobile_nav', 0 );
+
+
+}
+add_action( 'init', 'mm_nav_modifications' );
+
+
+/*===========================================
+ * Footer
+===========================================*/
+function mm_custom_footer($output) {
+ return $output . '[footer_childtheme_link before=""] by MIGHTYminnow
';
+}
+add_filter( 'genesis_footer_output', 'mm_custom_footer' );
+/*===========================================
+ * Shortcodes
+===========================================*/
\ No newline at end of file
diff --git a/includes/admin.php b/includes/admin.php
new file mode 100644
index 0000000..26c5a29
--- /dev/null
+++ b/includes/admin.php
@@ -0,0 +1,88 @@
+
+
+ /> Automatically generate nav menu (replaces custom/manual menu with auto-generated menu)
+ /> Include Home Link
+
+
+
+ Custom footer text
+
+
+
+ * @author Gary Jones
+ * @copyright Copyright (c) 2012, Thomas Griffin
+ * @license http://opensource.org/licenses/gpl-2.0.php GPL v2 or later
+ * @link https://github.com/thomasgriffin/TGM-Plugin-Activation
+ */
+
+/*
+ Copyright 2012 Thomas Griffin (email : thomas@thomasgriffinmedia.com)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License, version 3, as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+if ( ! class_exists( 'TGM_Plugin_Activation' ) ) {
+ /**
+ * Automatic plugin installation and activation library.
+ *
+ * Creates a way to automatically install and activate plugins from within themes.
+ * The plugins can be either pre-packaged, downloaded from the WordPress
+ * Plugin Repository or downloaded from a private repository.
+ *
+ * @since 1.0.0
+ *
+ * @package TGM-Plugin-Activation
+ * @author Thomas Griffin
+ * @author Gary Jones
+ */
+ class TGM_Plugin_Activation {
+
+ /**
+ * Holds a copy of itself, so it can be referenced by the class name.
+ *
+ * @since 1.0.0
+ *
+ * @var TGM_Plugin_Activation
+ */
+ static $instance;
+
+ /**
+ * Holds arrays of plugin details.
+ *
+ * @since 1.0.0
+ *
+ * @var array
+ */
+ public $plugins = array();
+
+ /**
+ * Parent menu slug for plugins page.
+ *
+ * @since 2.2.0
+ *
+ * @var string Parent menu slug. Defaults to 'themes.php'.
+ */
+ public $parent_menu_slug = 'themes.php';
+
+ /**
+ * Parent URL slug for URL references.
+ *
+ * This is useful if you want to place the custom plugins page as a
+ * submenu item under a custom parent menu.
+ *
+ * @since 2.2.0
+ *
+ * @var string Parent URL slug. Defaults to 'themes.php'.
+ */
+ public $parent_url_slug = 'themes.php';
+
+ /**
+ * Name of the querystring argument for the admin page.
+ *
+ * @since 1.0.0
+ *
+ * @var string
+ */
+ public $menu = 'install-required-plugins';
+
+ /**
+ * Default absolute path to folder containing pre-packaged plugin zip files.
+ *
+ * @since 2.0.0
+ *
+ * @var string Absolute path prefix to packaged zip file location. Default is empty string.
+ */
+ public $default_path = '';
+
+ /**
+ * Flag to show admin notices or not.
+ *
+ * @since 2.1.0
+ *
+ * @var boolean
+ */
+ public $has_notices = true;
+
+ /**
+ * Flag to set automatic activation of plugins. Off by default.
+ *
+ * @since 2.2.0
+ *
+ * @var boolean
+ */
+ public $is_automatic = false;
+
+ /**
+ * Optional message to display before the plugins table.
+ *
+ * @since 2.2.0
+ *
+ * @var string Message filtered by wp_kses_post(). Default is empty string.
+ */
+ public $message = '';
+
+ /**
+ * Holds configurable array of strings.
+ *
+ * Default values are added in the constructor.
+ *
+ * @since 2.0.0
+ *
+ * @var array
+ */
+ public $strings = array();
+
+ /**
+ * Adds a reference of this object to $instance, populates default strings,
+ * does the tgmpa_init action hook, and hooks in the interactions to init.
+ *
+ * @since 1.0.0
+ *
+ * @see TGM_Plugin_Activation::init()
+ */
+ public function __construct() {
+
+ self::$instance =& $this;
+
+ $this->strings = array(
+ 'page_title' => __( 'Install Required Plugins', 'tgmpa' ),
+ 'menu_title' => __( 'Install Plugins', 'tgmpa' ),
+ 'installing' => __( 'Installing Plugin: %s', 'tgmpa' ),
+ 'oops' => __( 'Something went wrong.', 'tgmpa' ),
+ 'notice_can_install_required' => _n_noop( 'This theme requires the following plugin: %1$s.', 'This theme requires the following plugins: %1$s.' ),
+ 'notice_can_install_recommended' => _n_noop( 'This theme recommends the following plugin: %1$s.', 'This theme recommends the following plugins: %1$s.' ),
+ 'notice_cannot_install' => _n_noop( 'Sorry, but you do not have the correct permissions to install the %s plugin. Contact the administrator of this site for help on getting the plugin installed.', 'Sorry, but you do not have the correct permissions to install the %s plugins. Contact the administrator of this site for help on getting the plugins installed.' ),
+ 'notice_can_activate_required' => _n_noop( 'The following required plugin is currently inactive: %1$s.', 'The following required plugins are currently inactive: %1$s.' ),
+ 'notice_can_activate_recommended' => _n_noop( 'The following recommended plugin is currently inactive: %1$s.', 'The following recommended plugins are currently inactive: %1$s.' ),
+ 'notice_cannot_activate' => _n_noop( 'Sorry, but you do not have the correct permissions to activate the %s plugin. Contact the administrator of this site for help on getting the plugin activated.', 'Sorry, but you do not have the correct permissions to activate the %s plugins. Contact the administrator of this site for help on getting the plugins activated.' ),
+ 'notice_ask_to_update' => _n_noop( 'The following plugin needs to be updated to its latest version to ensure maximum compatibility with this theme: %1$s.', 'The following plugins need to be updated to their latest version to ensure maximum compatibility with this theme: %1$s.' ),
+ 'notice_cannot_update' => _n_noop( 'Sorry, but you do not have the correct permissions to update the %s plugin. Contact the administrator of this site for help on getting the plugin updated.', 'Sorry, but you do not have the correct permissions to update the %s plugins. Contact the administrator of this site for help on getting the plugins updated.' ),
+ 'install_link' => _n_noop( 'Begin installing plugin', 'Begin installing plugins' ),
+ 'activate_link' => _n_noop( 'Activate installed plugin', 'Activate installed plugins' ),
+ 'return' => __( 'Return to Required Plugins Installer', 'tgmpa' ),
+ 'dashboard' => __( 'Return to the dashboard', 'tgmpa' ),
+ 'plugin_activated' => __( 'Plugin activated successfully.', 'tgmpa' ),
+ 'activated_successfully' => __( 'The following plugin was activated successfully:', 'tgmpa' ),
+ 'complete' => __( 'All plugins installed and activated successfully. %1$s', 'tgmpa' ),
+ 'dismiss' => __( 'Dismiss this notice', 'tgmpa' ),
+ );
+
+ /** Announce that the class is ready, and pass the object (for advanced use) */
+ do_action_ref_array( 'tgmpa_init', array( &$this ) );
+
+ /** When the rest of WP has loaded, kick-start the rest of the class */
+ add_action( 'init', array( &$this, 'init' ) );
+
+ }
+
+ /**
+ * Initialise the interactions between this class and WordPress.
+ *
+ * Hooks in three new methods for the class: admin_menu, notices and styles.
+ *
+ * @since 2.0.0
+ *
+ * @see TGM_Plugin_Activation::admin_menu()
+ * @see TGM_Plugin_Activation::notices()
+ * @see TGM_Plugin_Activation::styles()
+ */
+ public function init() {
+
+ do_action( 'tgmpa_register' );
+ /** After this point, the plugins should be registered and the configuration set */
+
+ /** Proceed only if we have plugins to handle */
+ if ( $this->plugins ) {
+ $sorted = array(); // Prepare variable for sorting
+
+ foreach ( $this->plugins as $plugin )
+ $sorted[] = $plugin['name'];
+
+ array_multisort( $sorted, SORT_ASC, $this->plugins ); // Sort plugins alphabetically by name
+
+ add_action( 'admin_menu', array( &$this, 'admin_menu' ) );
+ add_action( 'admin_head', array( &$this, 'dismiss' ) );
+ add_filter( 'install_plugin_complete_actions', array( &$this, 'actions' ) );
+
+ /** Load admin bar in the header to remove flash when installing plugins */
+ if ( $this->is_tgmpa_page() ) {
+ remove_action( 'wp_footer', 'wp_admin_bar_render', 1000 );
+ remove_action( 'admin_footer', 'wp_admin_bar_render', 1000 );
+ add_action( 'wp_head', 'wp_admin_bar_render', 1000 );
+ add_action( 'admin_head', 'wp_admin_bar_render', 1000 );
+ }
+
+ if ( $this->has_notices ) {
+ add_action( 'admin_notices', array( &$this, 'notices' ) );
+ add_action( 'admin_init', array( &$this, 'admin_init' ), 1 );
+ add_action( 'admin_enqueue_scripts', array( &$this, 'thickbox' ) );
+ add_action( 'switch_theme', array( &$this, 'update_dismiss' ) );
+ }
+
+ /** Setup the force activation hook */
+ foreach ( $this->plugins as $plugin ) {
+ if ( isset( $plugin['force_activation'] ) && true === $plugin['force_activation'] ) {
+ add_action( 'admin_init', array( &$this, 'force_activation' ) );
+ break;
+ }
+ }
+
+ /** Setup the force deactivation hook */
+ foreach ( $this->plugins as $plugin ) {
+ if ( isset( $plugin['force_deactivation'] ) && true === $plugin['force_deactivation'] ) {
+ add_action( 'switch_theme', array( &$this, 'force_deactivation' ) );
+ break;
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Handles calls to show plugin information via links in the notices.
+ *
+ * We get the links in the admin notices to point to the TGMPA page, rather
+ * than the typical plugin-install.php file, so we can prepare everything
+ * beforehand.
+ *
+ * WP doesn't make it easy to show the plugin information in the thickbox -
+ * here we have to require a file that includes a function that does the
+ * main work of displaying it, enqueue some styles, set up some globals and
+ * finally call that function before exiting.
+ *
+ * Down right easy once you know how...
+ *
+ * @since 2.1.0
+ *
+ * @global string $tab Used as iframe div class names, helps with styling
+ * @global string $body_id Used as the iframe body ID, helps with styling
+ * @return null Returns early if not the TGMPA page.
+ */
+ public function admin_init() {
+
+ if ( ! $this->is_tgmpa_page() )
+ return;
+
+ if ( isset( $_REQUEST['tab'] ) && 'plugin-information' == $_REQUEST['tab'] ) {
+ require_once ABSPATH . 'wp-admin/includes/plugin-install.php'; // Need for install_plugin_information()
+
+ wp_enqueue_style( 'plugin-install' );
+
+ global $tab, $body_id;
+ $body_id = $tab = 'plugin-information';
+
+ install_plugin_information();
+
+ exit;
+ }
+
+ }
+
+ /**
+ * Enqueues thickbox scripts/styles for plugin info.
+ *
+ * Thickbox is not automatically included on all admin pages, so we must
+ * manually enqueue it for those pages.
+ *
+ * Thickbox is only loaded if the user has not dismissed the admin
+ * notice or if there are any plugins left to install and activate.
+ *
+ * @since 2.1.0
+ */
+ public function thickbox() {
+
+ if ( ! get_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice', true ) )
+ add_thickbox();
+
+ }
+
+ /**
+ * Adds submenu page under 'Appearance' tab.
+ *
+ * This method adds the submenu page letting users know that a required
+ * plugin needs to be installed.
+ *
+ * This page disappears once the plugin has been installed and activated.
+ *
+ * @since 1.0.0
+ *
+ * @see TGM_Plugin_Activation::init()
+ * @see TGM_Plugin_Activation::install_plugins_page()
+ */
+ public function admin_menu() {
+
+ // Make sure privileges are correct to see the page
+ if ( ! current_user_can( 'install_plugins' ) )
+ return;
+
+ $this->populate_file_path();
+
+ foreach ( $this->plugins as $plugin ) {
+ if ( ! is_plugin_active( $plugin['file_path'] ) ) {
+ add_submenu_page(
+ $this->parent_menu_slug, // Parent menu slug
+ $this->strings['page_title'], // Page title
+ $this->strings['menu_title'], // Menu title
+ 'edit_theme_options', // Capability
+ $this->menu, // Menu slug
+ array( &$this, 'install_plugins_page' ) // Callback
+ );
+ break;
+ }
+ }
+
+ }
+
+ /**
+ * Echoes plugin installation form.
+ *
+ * This method is the callback for the admin_menu method function.
+ * This displays the admin page and form area where the user can select to install and activate the plugin.
+ *
+ * @since 1.0.0
+ *
+ * @return null Aborts early if we're processing a plugin installation action
+ */
+ public function install_plugins_page() {
+
+ /** Store new instance of plugin table in object */
+ $plugin_table = new TGMPA_List_Table;
+
+ /** Return early if processing a plugin installation action */
+ if ( isset( $_POST[sanitize_key( 'action' )] ) && 'tgmpa-bulk-install' == $_POST[sanitize_key( 'action' )] && $plugin_table->process_bulk_actions() || $this->do_plugin_install() )
+ return;
+
+ ?>
+
+
+
+
+ prepare_items(); ?>
+
+ message ) ) _e( wp_kses_post( $this->message ), 'tgmpa' ); ?>
+
+
+
+
+ $this->menu,
+ 'plugin' => $plugin['slug'],
+ 'plugin_name' => $plugin['name'],
+ 'plugin_source' => $plugin['source'],
+ 'tgmpa-install' => 'install-plugin',
+ ),
+ admin_url( $this->parent_url_slug )
+ ),
+ 'tgmpa-install'
+ );
+ $method = ''; // Leave blank so WP_Filesystem can populate it as necessary
+ $fields = array( sanitize_key( 'tgmpa-install' ) ); // Extra fields to pass to WP_Filesystem
+
+ if ( false === ( $creds = request_filesystem_credentials( $url, $method, false, false, $fields ) ) )
+ return true;
+
+ if ( ! WP_Filesystem( $creds ) ) {
+ request_filesystem_credentials( $url, $method, true, false, $fields ); // Setup WP_Filesystem
+ return true;
+ }
+
+ require_once ABSPATH . 'wp-admin/includes/plugin-install.php'; // Need for plugins_api
+ require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; // Need for upgrade classes
+
+ /** Set plugin source to WordPress API link if available */
+ if ( isset( $plugin['source'] ) && 'repo' == $plugin['source'] ) {
+ $api = plugins_api( 'plugin_information', array( 'slug' => $plugin['slug'], 'fields' => array( 'sections' => false ) ) );
+
+ if ( is_wp_error( $api ) )
+ wp_die( $this->strings['oops'] . var_dump( $api ) );
+
+ if ( isset( $api->download_link ) )
+ $plugin['source'] = $api->download_link;
+ }
+
+ /** Set type, based on whether the source starts with http:// or https:// */
+ $type = preg_match( '|^http(s)?://|', $plugin['source'] ) ? 'web' : 'upload';
+
+ /** Prep variables for Plugin_Installer_Skin class */
+ $title = sprintf( $this->strings['installing'], $plugin['name'] );
+ $url = add_query_arg( array( 'action' => 'install-plugin', 'plugin' => $plugin['slug'] ), 'update.php' );
+ if ( isset( $_GET['from'] ) )
+ $url .= add_query_arg( 'from', urlencode( stripslashes( $_GET['from'] ) ), $url );
+
+ $nonce = 'install-plugin_' . $plugin['slug'];
+
+ /** Prefix a default path to pre-packaged plugins */
+ $source = ( 'upload' == $type ) ? $this->default_path . $plugin['source'] : $plugin['source'];
+
+ /** Create a new instance of Plugin_Upgrader */
+ $upgrader = new Plugin_Upgrader( $skin = new Plugin_Installer_Skin( compact( 'type', 'title', 'url', 'nonce', 'plugin', 'api' ) ) );
+
+ /** Perform the action and install the plugin from the $source urldecode() */
+ $upgrader->install( $source );
+
+ /** Flush plugins cache so we can make sure that the installed plugins list is always up to date */
+ wp_cache_flush();
+
+ /** Only activate plugins if the config option is set to true */
+ if ( $this->is_automatic ) {
+ $plugin_activate = $upgrader->plugin_info(); // Grab the plugin info from the Plugin_Upgrader method
+ $activate = activate_plugin( $plugin_activate ); // Activate the plugin
+ $this->populate_file_path(); // Re-populate the file path now that the plugin has been installed and activated
+
+ if ( is_wp_error( $activate ) ) {
+ echo '' . $activate->get_error_message() . '
';
+ echo '' . $this->strings['return'] . '
';
+ return true; // End it here if there is an error with automatic activation
+ }
+ else {
+ echo '' . $this->strings['plugin_activated'] . '
';
+ }
+ }
+
+ /** Display message based on if all plugins are now active or not */
+ $complete = array();
+ foreach ( $this->plugins as $plugin ) {
+ if ( ! is_plugin_active( $plugin['file_path'] ) ) {
+ echo '' . $this->strings['return'] . '
';
+ $complete[] = $plugin;
+ break;
+ }
+ /** Nothing to store */
+ else {
+ $complete[] = '';
+ }
+ }
+
+ /** Filter out any empty entries */
+ $complete = array_filter( $complete );
+
+ /** All plugins are active, so we display the complete string and hide the plugin menu */
+ if ( empty( $complete ) ) {
+ echo '' . sprintf( $this->strings['complete'], '' . $this->strings['domain'] . ' ' ) . '
';
+ echo '';
+ }
+
+ return true;
+ }
+ /** Checks for actions from hover links to process the activation */
+ elseif ( isset( $_GET[sanitize_key( 'plugin' )] ) && ( isset( $_GET[sanitize_key( 'tgmpa-activate' )] ) && 'activate-plugin' == $_GET[sanitize_key( 'tgmpa-activate' )] ) ) {
+ check_admin_referer( 'tgmpa-activate', 'tgmpa-activate-nonce' );
+
+ /** Populate $plugin array with necessary information */
+ $plugin['name'] = $_GET[sanitize_key( 'plugin_name' )];
+ $plugin['slug'] = $_GET[sanitize_key( 'plugin' )];
+ $plugin['source'] = $_GET[sanitize_key( 'plugin_source' )];
+
+ $plugin_data = get_plugins( '/' . $plugin['slug'] ); // Retrieve all plugins
+ $plugin_file = array_keys( $plugin_data ); // Retrieve all plugin files from installed plugins
+ $plugin_to_activate = $plugin['slug'] . '/' . $plugin_file[0]; // Match plugin slug with appropriate plugin file
+ $activate = activate_plugin( $plugin_to_activate ); // Activate the plugin
+
+ if ( is_wp_error( $activate ) ) {
+ echo '' . $activate->get_error_message() . '
';
+ echo '' . $this->strings['return'] . '
';
+ return true; // End it here if there is an error with activation
+ }
+ else {
+ /** Make sure message doesn't display again if bulk activation is performed immediately after a single activation */
+ if ( ! isset( $_POST[sanitize_key( 'action' )] ) ) {
+ $msg = $this->strings['activated_successfully'] . ' ' . $plugin['name'] . ' ';
+ echo '';
+ }
+ }
+ }
+
+ return false;
+
+ }
+
+ /**
+ * Echoes required plugin notice.
+ *
+ * Outputs a message telling users that a specific plugin is required for
+ * their theme. If appropriate, it includes a link to the form page where
+ * users can install and activate the plugin.
+ *
+ * @since 1.0.0
+ *
+ * @global object $current_screen
+ * @return null Returns early if we're on the Install page
+ */
+ public function notices() {
+
+ global $current_screen;
+
+ /** Remove nag on the install page */
+ if ( $this->is_tgmpa_page() )
+ return;
+
+ $installed_plugins = get_plugins(); // Retrieve a list of all the plugins
+ $this->populate_file_path();
+
+ $message = array(); // Store the messages in an array to be outputted after plugins have looped through
+ $install_link = false; // Set to false, change to true in loop if conditions exist, used for action link 'install'
+ $install_link_count = 0; // Used to determine plurality of install action link text
+ $activate_link = false; // Set to false, change to true in loop if conditions exist, used for action link 'activate'
+ $activate_link_count = 0; // Used to determine plurality of activate action link text
+
+ foreach ( $this->plugins as $plugin ) {
+ /** If the plugin is installed and active, check for minimum version argument before moving forward */
+ if ( is_plugin_active( $plugin['file_path'] ) ) {
+ /** A minimum version has been specified */
+ if ( isset( $plugin['version'] ) ) {
+ if ( isset( $installed_plugins[$plugin['file_path']]['Version'] ) ) {
+ /** If the current version is less than the minimum required version, we display a message */
+ if ( version_compare( $installed_plugins[$plugin['file_path']]['Version'], $plugin['version'], '<' ) ) {
+ if ( current_user_can( 'install_plugins' ) )
+ $message['notice_ask_to_update'][] = $plugin['name'];
+ else
+ $message['notice_cannot_update'][] = $plugin['name'];
+ }
+ }
+ /** Can't find the plugin, so iterate to the next condition */
+ else {
+ continue;
+ }
+ }
+ /** No minimum version specified, so iterate over the plugin */
+ else {
+ continue;
+ }
+ }
+
+ /** Not installed */
+ if ( ! isset( $installed_plugins[$plugin['file_path']] ) ) {
+ $install_link = true; // We need to display the 'install' action link
+ $install_link_count++; // Increment the install link count
+ if ( current_user_can( 'install_plugins' ) ) {
+ if ( $plugin['required'] )
+ $message['notice_can_install_required'][] = $plugin['name'];
+ /** This plugin is only recommended */
+ else
+ $message['notice_can_install_recommended'][] = $plugin['name'];
+ }
+ /** Need higher privileges to install the plugin */
+ else {
+ $message['notice_cannot_install'][] = $plugin['name'];
+ }
+ }
+ /** Installed but not active */
+ elseif ( is_plugin_inactive( $plugin['file_path'] ) ) {
+ $activate_link = true; // We need to display the 'activate' action link
+ $activate_link_count++; // Increment the activate link count
+ if ( current_user_can( 'activate_plugins' ) ) {
+ if ( ( isset( $plugin['required'] ) ) && ( $plugin['required'] ) )
+ $message['notice_can_activate_required'][] = $plugin['name'];
+ /** This plugin is only recommended */
+ else {
+ $message['notice_can_activate_recommended'][] = $plugin['name'];
+ }
+ }
+ /** Need higher privileges to activate the plugin */
+ else {
+ $message['notice_cannot_activate'][] = $plugin['name'];
+ }
+ }
+ }
+
+ /** Only process the nag messages if the user has not dismissed them already */
+ if ( ! get_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice', true ) ) {
+ /** If we have notices to display, we move forward */
+ if ( ! empty( $message ) ) {
+ krsort( $message ); // Sort messages
+ $rendered = ''; // Display all nag messages as strings
+
+ /** Grab all plugin names */
+ foreach ( $message as $type => $plugin_groups ) {
+ $linked_plugin_groups = array();
+
+ /** Count number of plugins in each message group to calculate singular/plural message */
+ $count = count( $plugin_groups );
+
+ /** Loop through the plugin names to make the ones pulled from the .org repo linked */
+ foreach ( $plugin_groups as $plugin_group_single_name ) {
+ $external_url = $this->_get_plugin_data_from_name( $plugin_group_single_name, 'external_url' );
+ $source = $this->_get_plugin_data_from_name( $plugin_group_single_name, 'source' );
+
+ if ( $external_url && preg_match( '|^http(s)?://|', $external_url ) ) {
+ $linked_plugin_groups[] = '' . $plugin_group_single_name . ' ';
+ }
+ elseif ( ! $source || preg_match( '|^http://wordpress.org/extend/plugins/|', $source ) ) {
+ $url = add_query_arg(
+ array(
+ 'tab' => 'plugin-information',
+ 'plugin' => $this->_get_plugin_data_from_name( $plugin_group_single_name ),
+ 'TB_iframe' => 'true',
+ 'width' => '640',
+ 'height' => '500',
+ ),
+ admin_url( 'plugin-install.php' )
+ );
+
+ $linked_plugin_groups[] = '' . $plugin_group_single_name . ' ';
+ }
+ else {
+ $linked_plugin_groups[] = $plugin_group_single_name; // No hyperlink
+ }
+
+ if ( isset( $linked_plugin_groups ) && (array) $linked_plugin_groups )
+ $plugin_groups = $linked_plugin_groups;
+ }
+
+ $last_plugin = array_pop( $plugin_groups ); // Pop off last name to prep for readability
+ $imploded = empty( $plugin_groups ) ? '' . $last_plugin . ' ' : '' . ( implode( ', ', $plugin_groups ) . ' and ' . $last_plugin . ' ' );
+
+ $rendered .= '' . sprintf( translate_nooped_plural( $this->strings[$type], $count, 'tgmpa' ), $imploded, $count ) . '
'; // All messages now stored
+ }
+
+ /** Setup variables to determine if action links are needed */
+ $show_install_link = $install_link ? '' . translate_nooped_plural( $this->strings['install_link'], $install_link_count, 'tgmpa' ) . ' ' : '';
+ $show_activate_link = $activate_link ? '' . translate_nooped_plural( $this->strings['activate_link'], $activate_link_count, 'tgmpa' ) . ' ' : '';
+
+ /** Define all of the action links */
+ $action_links = apply_filters(
+ 'tgmpa_notice_action_links',
+ array(
+ 'install' => ( current_user_can( 'install_plugins' ) ) ? $show_install_link : '',
+ 'activate' => ( current_user_can( 'activate_plugins' ) ) ? $show_activate_link : '',
+ 'dismiss' => '' . $this->strings['dismiss'] . ' ',
+ )
+ );
+
+ $action_links = array_filter( $action_links ); // Remove any empty array items
+ if ( $action_links )
+ $rendered .= '' . implode( ' | ', $action_links ) . '
';
+
+ /** Register the nag messages and prepare them to be processed */
+ if ( isset( $this->strings['nag_type'] ) )
+ add_settings_error( 'tgmpa', 'tgmpa', $rendered, sanitize_html_class( strtolower( $this->strings['nag_type'] ), 'updated' ) );
+ else
+ add_settings_error( 'tgmpa', 'tgmpa', $rendered, 'updated' );
+ }
+ }
+
+ /** Admin options pages already output settings_errors, so this is to avoid duplication */
+ if ( 'options-general' !== $current_screen->parent_base )
+ settings_errors( 'tgmpa' );
+
+ }
+
+ /**
+ * Add dismissable admin notices.
+ *
+ * Appends a link to the admin nag messages. If clicked, the admin notice disappears and no longer is visible to users.
+ *
+ * @since 2.1.0
+ */
+ public function dismiss() {
+
+ if ( isset( $_GET[sanitize_key( 'tgmpa-dismiss' )] ) )
+ update_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice', 1 );
+
+ }
+
+ /**
+ * Add individual plugin to our collection of plugins.
+ *
+ * If the required keys are not set, the plugin is not added.
+ *
+ * @since 2.0.0
+ *
+ * @param array $plugin Array of plugin arguments.
+ */
+ public function register( $plugin ) {
+
+ if ( ! isset( $plugin['slug'] ) || ! isset( $plugin['name'] ) )
+ return;
+
+ $this->plugins[] = $plugin;
+
+ }
+
+ /**
+ * Amend default configuration settings.
+ *
+ * @since 2.0.0
+ *
+ * @param array $config
+ */
+ public function config( $config ) {
+
+ $keys = array( 'default_path', 'parent_menu_slug', 'parent_url_slug', 'domain', 'has_notices', 'menu', 'is_automatic', 'message', 'strings' );
+
+ foreach ( $keys as $key ) {
+ if ( isset( $config[$key] ) ) {
+ if ( is_array( $config[$key] ) ) {
+ foreach ( $config[$key] as $subkey => $value )
+ $this->{$key}[$subkey] = $value;
+ } else {
+ $this->$key = $config[$key];
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Amend action link after plugin installation.
+ *
+ * @since 2.0.0
+ *
+ * @param array $install_actions Existing array of actions
+ * @return array Amended array of actions
+ */
+ public function actions( $install_actions ) {
+
+ /** Remove action links on the TGMPA install page */
+ if ( $this->is_tgmpa_page() )
+ return false;
+
+ return $install_actions;
+
+ }
+
+ /**
+ * Set file_path key for each installed plugin.
+ *
+ * @since 2.1.0
+ */
+ public function populate_file_path() {
+
+ /** Add file_path key for all plugins */
+ foreach ( $this->plugins as $plugin => $values )
+ $this->plugins[$plugin]['file_path'] = $this->_get_plugin_basename_from_slug( $values['slug'] );
+
+ }
+
+ /**
+ * Helper function to extract the file path of the plugin file from the
+ * plugin slug, if the plugin is installed.
+ *
+ * @since 2.0.0
+ *
+ * @param string $slug Plugin slug (typically folder name) as provided by the developer
+ * @return string Either file path for plugin if installed, or just the plugin slug
+ */
+ protected function _get_plugin_basename_from_slug( $slug ) {
+
+ $keys = array_keys( get_plugins() );
+
+ foreach ( $keys as $key ) {
+ if ( preg_match( '|^' . $slug .'|', $key ) )
+ return $key;
+ }
+
+ return $slug;
+
+ }
+
+ /**
+ * Retrieve plugin data, given the plugin name.
+ *
+ * Loops through the registered plugins looking for $name. If it finds it,
+ * it returns the $data from that plugin. Otherwise, returns false.
+ *
+ * @since 2.1.0
+ *
+ * @param string $name Name of the plugin, as it was registered
+ * @param string $data Optional. Array key of plugin data to return. Default is slug
+ * @return string|boolean Plugin slug if found, false otherwise.
+ */
+ protected function _get_plugin_data_from_name( $name, $data = 'slug' ) {
+
+ foreach ( $this->plugins as $plugin => $values ) {
+ if ( $name == $values['name'] && isset( $values[$data] ) )
+ return $values[$data];
+ }
+
+ return false;
+
+ }
+
+ /**
+ * Determine if we're on the TGMPA Install page.
+ *
+ * We use $current_screen when it is available, and a slightly less ideal
+ * conditional when it isn't (like when displaying the plugin information
+ * thickbox).
+ *
+ * @since 2.1.0
+ *
+ * @global object $current_screen
+ * @return boolean True when on the TGMPA page, false otherwise.
+ */
+ protected function is_tgmpa_page() {
+
+ global $current_screen;
+
+ if ( ! is_null( $current_screen ) && $this->parent_menu_slug == $current_screen->parent_file && isset( $_GET['page'] ) && $this->menu === $_GET['page'] )
+ return true;
+
+ if ( isset( $_GET['page'] ) && $this->menu === $_GET['page'] )
+ return true;
+
+ return false;
+
+ }
+
+ /**
+ * Delete dismissable nag option when theme is switched.
+ *
+ * This ensures that the user is again reminded via nag of required
+ * and/or recommended plugins if they re-activate the theme.
+ *
+ * @since 2.1.1
+ */
+ public function update_dismiss() {
+
+ delete_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice' );
+
+ }
+
+ /**
+ * Forces plugin activation if the parameter 'force_activation' is
+ * set to true.
+ *
+ * This allows theme authors to specify certain plugins that must be
+ * active at all times while using the current theme.
+ *
+ * Please take special care when using this parameter as it has the
+ * potential to be harmful if not used correctly. Setting this parameter
+ * to true will not allow the specified plugin to be deactivated unless
+ * the user switches themes.
+ *
+ * @since 2.2.0
+ */
+ public function force_activation() {
+
+ /** Set file_path parameter for any installed plugins */
+ $this->populate_file_path();
+
+ $installed_plugins = get_plugins();
+
+ foreach ( $this->plugins as $plugin ) {
+ /** Oops, plugin isn't there so iterate to next condition */
+ if ( isset( $plugin['force_activation'] ) && $plugin['force_activation'] && ! isset( $installed_plugins[$plugin['file_path']] ) )
+ continue;
+ /** There we go, activate the plugin */
+ elseif ( isset( $plugin['force_activation'] ) && $plugin['force_activation'] && is_plugin_inactive( $plugin['file_path'] ) )
+ activate_plugin( $plugin['file_path'] );
+ }
+
+ }
+
+ /**
+ * Forces plugin deactivation if the parameter 'force_deactivation'
+ * is set to true.
+ *
+ * This allows theme authors to specify certain plugins that must be
+ * deactived upon switching from the current theme to another.
+ *
+ * Please take special care when using this parameter as it has the
+ * potential to be harmful if not used correctly.
+ *
+ * @since 2.2.0
+ */
+ public function force_deactivation() {
+
+ /** Set file_path parameter for any installed plugins */
+ $this->populate_file_path();
+
+ foreach ( $this->plugins as $plugin ) {
+ /** Only proceed forward if the paramter is set to true and plugin is active */
+ if ( isset( $plugin['force_deactivation'] ) && $plugin['force_deactivation'] && is_plugin_active( $plugin['file_path'] ) )
+ deactivate_plugins( $plugin['file_path'] );
+ }
+
+ }
+
+ }
+}
+
+/** Create a new instance of the class */
+new TGM_Plugin_Activation;
+
+if ( ! function_exists( 'tgmpa' ) ) {
+ /**
+ * Helper function to register a collection of required plugins.
+ *
+ * @since 2.0.0
+ * @api
+ *
+ * @param array $plugins An array of plugin arrays
+ * @param array $config Optional. An array of configuration values
+ */
+ function tgmpa( $plugins, $config = array() ) {
+
+ foreach ( $plugins as $plugin )
+ TGM_Plugin_Activation::$instance->register( $plugin );
+
+ if ( $config )
+ TGM_Plugin_Activation::$instance->config( $config );
+
+ }
+}
+
+/**
+ * WP_List_Table isn't always available. If it isn't available,
+ * we load it here.
+ *
+ * @since 2.2.0
+ */
+if ( ! class_exists( 'WP_List_Table' ) )
+ require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
+
+if ( ! class_exists( 'TGMPA_List_Table' ) ) {
+ /**
+ * List table class for handling plugins.
+ *
+ * Extends the WP_List_Table class to provide a future-compatible
+ * way of listing out all required/recommended plugins.
+ *
+ * Gives users an interface similar to the Plugin Administration
+ * area with similar (albeit stripped down) capabilities.
+ *
+ * This class also allows for the bulk install of plugins.
+ *
+ * @since 2.2.0
+ *
+ * @package TGM-Plugin-Activation
+ * @author Thomas Griffin
+ * @author Gary Jones
+ */
+ class TGMPA_List_Table extends WP_List_Table {
+
+ /**
+ * References parent constructor and sets defaults for class.
+ *
+ * The constructor also grabs a copy of $instance from the TGMPA class
+ * and stores it in the global object TGM_Plugin_Activation::$instance.
+ *
+ * @since 2.2.0
+ *
+ * @global unknown $status
+ * @global string $page
+ */
+ public function __construct() {
+
+ global $status, $page;
+
+ parent::__construct(
+ array(
+ 'singular' => 'plugin',
+ 'plural' => 'plugins',
+ 'ajax' => false,
+ )
+ );
+
+ }
+
+ /**
+ * Gathers and renames all of our plugin information to be used by
+ * WP_List_Table to create our table.
+ *
+ * @since 2.2.0
+ *
+ * @return array $table_data Information for use in table
+ */
+ protected function _gather_plugin_data() {
+
+ /** Load thickbox for plugin links */
+ TGM_Plugin_Activation::$instance->admin_init();
+ TGM_Plugin_Activation::$instance->thickbox();
+
+ /** Prep variables for use and grab list of all installed plugins */
+ $table_data = array();
+ $i = 0;
+ $installed_plugins = get_plugins();
+
+ foreach ( TGM_Plugin_Activation::$instance->plugins as $plugin ) {
+ if ( is_plugin_active( $plugin['file_path'] ) )
+ continue; // No need to display plugins if they are installed and activated
+
+ $table_data[$i]['sanitized_plugin'] = $plugin['name'];
+ $table_data[$i]['slug'] = $this->_get_plugin_data_from_name( $plugin['name'] );
+
+ $external_url = $this->_get_plugin_data_from_name( $plugin['name'], 'external_url' );
+ $source = $this->_get_plugin_data_from_name( $plugin['name'], 'source' );
+
+ if ( $external_url && preg_match( '|^http(s)?://|', $external_url ) ) {
+ $table_data[$i]['plugin'] = '' . $plugin['name'] . ' ';
+ }
+ elseif ( ! $source || preg_match( '|^http://wordpress.org/extend/plugins/|', $source ) ) {
+ $url = add_query_arg(
+ array(
+ 'tab' => 'plugin-information',
+ 'plugin' => $this->_get_plugin_data_from_name( $plugin['name'] ),
+ 'TB_iframe' => 'true',
+ 'width' => '640',
+ 'height' => '500',
+ ),
+ admin_url( 'plugin-install.php' )
+ );
+
+ $table_data[$i]['plugin'] = '' . $plugin['name'] . ' ';
+ }
+ else {
+ $table_data[$i]['plugin'] = '' . $plugin['name'] . ' '; // No hyperlink
+ }
+
+ if ( isset( $table_data[$i]['plugin'] ) && (array) $table_data[$i]['plugin'] )
+ $plugin['name'] = $table_data[$i]['plugin'];
+
+ if ( isset( $plugin['external_url'] ) ) {
+ /** The plugin is linked to an external source */
+ $table_data[$i]['source'] = __( 'External Link', 'tgmpa' );
+ }
+ elseif ( isset( $plugin['source'] ) ) {
+ /** The plugin must be from a private repository */
+ if ( preg_match( '|^http(s)?://|', $plugin['source'] ) )
+ $table_data[$i]['source'] = __( 'Private Repository', 'tgmpa' );
+ /** The plugin is pre-packaged with the theme */
+ else
+ $table_data[$i]['source'] = __( 'Pre-Packaged', 'tgmpa' );
+ }
+ /** The plugin is from the WordPress repository */
+ else {
+ $table_data[$i]['source'] = __( 'WordPress Repository', 'tgmpa' );
+ }
+
+ $table_data[$i]['type'] = $plugin['required'] ? __( 'Required', 'tgmpa' ) : __( 'Recommended', 'tgmpa' );
+
+ if ( ! isset( $installed_plugins[$plugin['file_path']] ) )
+ $table_data[$i]['status'] = sprintf( '%1$s', __( 'Not Installed', 'tgmpa' ) );
+ elseif ( is_plugin_inactive( $plugin['file_path'] ) )
+ $table_data[$i]['status'] = sprintf( '%1$s', __( 'Installed But Not Activated', 'tgmpa' ) );
+
+ $table_data[$i]['file_path'] = $plugin['file_path'];
+ $table_data[$i]['url'] = isset( $plugin['source'] ) ? $plugin['source'] : 'repo';
+
+ $i++;
+ }
+
+ /** Sort plugins by Required/Recommended type and by alphabetical listing within each type */
+ $resort = array();
+ $req = array();
+ $rec = array();
+
+ /** Grab all the plugin types */
+ foreach ( $table_data as $plugin )
+ $resort[] = $plugin['type'];
+
+ /** Sort each plugin by type */
+ foreach ( $resort as $type )
+ if ( 'Required' == $type )
+ $req[] = $type;
+ else
+ $rec[] = $type;
+
+ /** Sort alphabetically each plugin type array, merge them and then sort in reverse (lists Required plugins first) */
+ sort( $req );
+ sort( $rec );
+ array_merge( $resort, $req, $rec );
+ array_multisort( $resort, SORT_DESC, $table_data );
+
+ return $table_data;
+
+ }
+
+ /**
+ * Retrieve plugin data, given the plugin name. Taken from the
+ * TGM_Plugin_Activation class.
+ *
+ * Loops through the registered plugins looking for $name. If it finds it,
+ * it returns the $data from that plugin. Otherwise, returns false.
+ *
+ * @since 2.2.0
+ *
+ * @param string $name Name of the plugin, as it was registered
+ * @param string $data Optional. Array key of plugin data to return. Default is slug
+ * @return string|boolean Plugin slug if found, false otherwise
+ */
+ protected function _get_plugin_data_from_name( $name, $data = 'slug' ) {
+
+ foreach ( TGM_Plugin_Activation::$instance->plugins as $plugin => $values ) {
+ if ( $name == $values['name'] && isset( $values[$data] ) )
+ return $values[$data];
+ }
+
+ return false;
+
+ }
+
+ /**
+ * Create default columns to display important plugin information
+ * like type, action and status.
+ *
+ * @since 2.2.0
+ *
+ * @param array $item
+ * @param string $column_name
+ */
+ public function column_default( $item, $column_name ) {
+
+ switch ( $column_name ) {
+ case 'source':
+ case 'type':
+ case 'status':
+ return $item[$column_name];
+ }
+
+ }
+
+ /**
+ * Create default title column along with action links of 'Install'
+ * and 'Activate'.
+ *
+ * @since 2.2.0
+ *
+ * @param array $item
+ * @return string The action hover links
+ */
+ public function column_plugin( $item ) {
+
+ $installed_plugins = get_plugins();
+
+ /** No need to display any hover links */
+ if ( is_plugin_active( $item['file_path'] ) )
+ $actions = array();
+
+ /** We need to display the 'Install' hover link */
+ if ( ! isset( $installed_plugins[$item['file_path']] ) ) {
+ $actions = array(
+ 'install' => sprintf(
+ 'Install ',
+ wp_nonce_url(
+ add_query_arg(
+ array(
+ 'page' => TGM_Plugin_Activation::$instance->menu,
+ 'plugin' => $item['slug'],
+ 'plugin_name' => $item['sanitized_plugin'],
+ 'plugin_source' => $item['url'],
+ 'tgmpa-install' => 'install-plugin',
+ ),
+ admin_url( TGM_Plugin_Activation::$instance->parent_url_slug )
+ ),
+ 'tgmpa-install'
+ ),
+ $item['sanitized_plugin']
+ ),
+ );
+ }
+ /** We need to display the 'Activate' hover link */
+ elseif ( is_plugin_inactive( $item['file_path'] ) ) {
+ $actions = array(
+ 'activate' => sprintf(
+ 'Activate ',
+ add_query_arg(
+ array(
+ 'page' => TGM_Plugin_Activation::$instance->menu,
+ 'plugin' => $item['slug'],
+ 'plugin_name' => $item['sanitized_plugin'],
+ 'plugin_source' => $item['url'],
+ 'tgmpa-activate' => 'activate-plugin',
+ 'tgmpa-activate-nonce' => wp_create_nonce( 'tgmpa-activate' ),
+ ),
+ admin_url( TGM_Plugin_Activation::$instance->parent_url_slug )
+ ),
+ $item['sanitized_plugin']
+ ),
+ );
+ }
+
+ return sprintf( '%1$s %2$s', $item['plugin'], $this->row_actions( $actions ) );
+
+ }
+
+ /**
+ * Required for bulk installing.
+ *
+ * Adds a checkbox for each plugin.
+ *
+ * @since 2.2.0
+ *
+ * @param array $item
+ * @return string The input checkbox with all necessary info
+ */
+ public function column_cb( $item ) {
+
+ $value = $item['file_path'] . ',' . $item['url'] . ',' . $item['sanitized_plugin'];
+ return sprintf( ' ', $this->_args['singular'], $value, $item['sanitized_plugin'] );
+
+ }
+
+ /**
+ * Sets default message within the plugins table if no plugins
+ * are left for interaction.
+ *
+ * Hides the menu item to prevent the user from clicking and
+ * getting a permissions error.
+ *
+ * @since 2.2.0
+ */
+ public function no_items() {
+
+ printf( __( 'No plugins to install or activate. Return to the Dashboard ', 'tgmpa' ), admin_url() );
+ echo '';
+
+ }
+
+ /**
+ * Output all the column information within the table.
+ *
+ * @since 2.2.0
+ *
+ * @return array $columns The column names
+ */
+ public function get_columns() {
+
+ $columns = array(
+ 'cb' => ' ',
+ 'plugin' => __( 'Plugin', 'tgmpa' ),
+ 'source' => __( 'Source', 'tgmpa' ),
+ 'type' => __( 'Type', 'tgmpa' ),
+ 'status' => __( 'Status', 'tgmpa' )
+ );
+
+ return $columns;
+
+ }
+
+ /**
+ * Defines all types of bulk actions for handling
+ * registered plugins.
+ *
+ * @since 2.2.0
+ *
+ * @return array $actions The bulk actions for the plugin install table
+ */
+ public function get_bulk_actions() {
+
+ $actions = array(
+ 'tgmpa-bulk-install' => __( 'Install', 'tgmpa' ),
+ 'tgmpa-bulk-activate' => __( 'Activate', 'tgmpa' ),
+ );
+
+ return $actions;
+
+ }
+
+ /**
+ * Processes bulk installation and activation actions.
+ *
+ * The bulk installation process looks either for the $_POST
+ * information or for the plugin info within the $_GET variable if
+ * a user has to use WP_Filesystem to enter their credentials.
+ *
+ * @since 2.2.0
+ */
+ public function process_bulk_actions() {
+
+ /** Bulk installation process */
+ if ( 'tgmpa-bulk-install' === $this->current_action() ) {
+ check_admin_referer( 'bulk-' . $this->_args['plural'] );
+
+ /** Prep variables to be populated */
+ $plugins_to_install = array();
+ $plugin_installs = array();
+ $plugin_path = array();
+ $plugin_name = array();
+
+ /** Look first to see if information has been passed via WP_Filesystem */
+ if ( isset( $_GET[sanitize_key( 'plugins' )] ) )
+ $plugins = explode( ',', stripslashes( $_GET[sanitize_key( 'plugins' )] ) );
+ /** Looks like the user can use the direct method, take from $_POST */
+ elseif ( isset( $_POST[sanitize_key( 'plugin' )] ) )
+ $plugins = (array) $_POST[sanitize_key( 'plugin' )];
+ /** Nothing has been submitted */
+ else
+ $plugins = array();
+
+ $a = 0; // Incremental variable
+
+ /** Grab information from $_POST if available */
+ if ( isset( $_POST[sanitize_key( 'plugin' )] ) ) {
+ foreach ( $plugins as $plugin_data )
+ $plugins_to_install[] = explode( ',', $plugin_data );
+
+ foreach ( $plugins_to_install as $plugin_data ) {
+ $plugin_installs[] = $plugin_data[0];
+ $plugin_path[] = $plugin_data[1];
+ $plugin_name[] = $plugin_data[2];
+ }
+ }
+ /** Information has been passed via $_GET */
+ else {
+ foreach ( $plugins as $key => $value ) {
+ /** Grab plugin slug for each plugin */
+ if ( 0 == $key % 3 || 0 == $key ) {
+ $plugins_to_install[] = $value;
+ $plugin_installs[] = $value;
+ }
+ $a++;
+ }
+ }
+
+ /** Look first to see if information has been passed via WP_Filesystem */
+ if ( isset( $_GET[sanitize_key( 'plugin_paths' )] ) )
+ $plugin_paths = explode( ',', stripslashes( $_GET[sanitize_key( 'plugin_paths' )] ) );
+ /** Looks like the user doesn't need to enter his FTP creds */
+ elseif ( isset( $_POST[sanitize_key( 'plugin' )] ) )
+ $plugin_paths = (array) $plugin_path;
+ /** Nothing has been submitted */
+ else
+ $plugin_paths = array();
+
+ /** Look first to see if information has been passed via WP_Filesystem */
+ if ( isset( $_GET[sanitize_key( 'plugin_names' )] ) )
+ $plugin_names = explode( ',', stripslashes( $_GET[sanitize_key( 'plugin_names' )] ) );
+ /** Looks like the user doesn't need to enter his FTP creds */
+ elseif ( isset( $_POST[sanitize_key( 'plugin' )] ) )
+ $plugin_names = (array) $plugin_name;
+ /** Nothing has been submitted */
+ else
+ $plugin_names = array();
+
+ $b = 0; // Incremental variable
+
+ /** Loop through plugin slugs and remove already installed plugins from the list */
+ foreach ( $plugin_installs as $key => $plugin ) {
+ if ( preg_match( '|.php$|', $plugin ) ) {
+ unset( $plugin_installs[$key] );
+
+ /** If the plugin path isn't in the $_GET variable, we can unset the corresponding path */
+ if ( ! isset( $_GET[sanitize_key( 'plugin_paths' )] ) )
+ unset( $plugin_paths[$b] );
+
+ /** If the plugin name isn't in the $_GET variable, we can unset the corresponding name */
+ if ( ! isset( $_GET[sanitize_key( 'plugin_names' )] ) )
+ unset( $plugin_names[$b] );
+ }
+ $b++;
+ }
+
+ /** No need to proceed further if we have no plugins to install */
+ if ( empty( $plugin_installs ) )
+ return false;
+
+ /** Reset array indexes in case we removed already installed plugins */
+ $plugin_installs = array_values( $plugin_installs );
+ $plugin_paths = array_values( $plugin_paths );
+ $plugin_names = array_values( $plugin_names );
+
+ /** If we grabbed our plugin info from $_GET, we need to decode it for use */
+ $plugin_installs = array_map( 'urldecode', $plugin_installs );
+ $plugin_paths = array_map( 'urldecode', $plugin_paths );
+ $plugin_names = array_map( 'urldecode', $plugin_names );
+
+ /** Pass all necessary information via URL if WP_Filesystem is needed */
+ $url = wp_nonce_url(
+ add_query_arg(
+ array(
+ 'page' => TGM_Plugin_Activation::$instance->menu,
+ 'tgmpa-action' => 'install-selected',
+ 'plugins' => urlencode( implode( ',', $plugins ) ),
+ 'plugin_paths' => urlencode( implode( ',', $plugin_paths ) ),
+ 'plugin_names' => urlencode( implode( ',', $plugin_names ) ),
+ ),
+ admin_url( TGM_Plugin_Activation::$instance->parent_url_slug )
+ ),
+ 'bulk-plugins'
+ );
+ $method = ''; // Leave blank so WP_Filesystem can populate it as necessary
+ $fields = array( sanitize_key( 'action' ), sanitize_key( '_wp_http_referer' ), sanitize_key( '_wpnonce' ) ); // Extra fields to pass to WP_Filesystem
+
+ if ( false === ( $creds = request_filesystem_credentials( $url, $method, false, false, $fields ) ) )
+ return true;
+
+ if ( ! WP_Filesystem( $creds ) ) {
+ request_filesystem_credentials( $url, $method, true, false, $fields ); // Setup WP_Filesystem
+ return true;
+ }
+
+ require_once ABSPATH . 'wp-admin/includes/plugin-install.php'; // Need for plugins_api
+ require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; // Need for upgrade classes
+
+ /** Store all information in arrays since we are processing a bulk installation */
+ $api = array();
+ $sources = array();
+ $install_path = array();
+
+ $c = 0; // Incremental variable
+
+ /** Loop through each plugin to install and try to grab information from WordPress API, if not create 'tgmpa-empty' scalar */
+ foreach ( $plugin_installs as $plugin ) {
+ $api[$c] = plugins_api( 'plugin_information', array( 'slug' => $plugin, 'fields' => array( 'sections' => false ) ) ) ? plugins_api( 'plugin_information', array( 'slug' => $plugin, 'fields' => array( 'sections' => false ) ) ) : (object) $api[$c] = 'tgmpa-empty';
+ $c++;
+ }
+
+ if ( is_wp_error( $api ) )
+ wp_die( TGM_Plugin_Activation::$instance->strings['oops'] . var_dump( $api ) );
+
+ $d = 0; // Incremental variable
+
+ /** Capture download links from $api or set install link to pre-packaged/private repo */
+ foreach ( $api as $object ) {
+ $sources[$d] = isset( $object->download_link ) && 'repo' == $plugin_paths[$d] ? $object->download_link : $plugin_paths[$d];
+ $d++;
+ }
+
+ /** Finally, all the data is prepared to be sent to the installer */
+ $url = add_query_arg( array( 'page' => TGM_Plugin_Activation::$instance->menu ), admin_url( TGM_Plugin_Activation::$instance->parent_url_slug ) );
+ $nonce = 'bulk-plugins';
+ $names = $plugin_names;
+
+ /** Create a new instance of TGM_Bulk_Installer */
+ $installer = new TGM_Bulk_Installer( $skin = new TGM_Bulk_Installer_Skin( compact( 'url', 'nonce', 'names' ) ) );
+
+ /** Wrap the install process with the appropriate HTML */
+ echo '';
+ screen_icon( apply_filters( 'tgmpa_default_screen_icon', 'themes' ) );
+ echo '
' . esc_html( get_admin_page_title() ) . ' ';
+ /** Process the bulk installation submissions */
+ $installer->bulk_install( $sources );
+ echo '';
+
+ return true;
+ }
+
+ /** Bulk activation process */
+ if ( 'tgmpa-bulk-activate' === $this->current_action() ) {
+ check_admin_referer( 'bulk-' . $this->_args['plural'] );
+
+ /** Grab plugin data from $_POST */
+ $plugins = isset( $_POST[sanitize_key( 'plugin' )] ) ? (array) $_POST[sanitize_key( 'plugin' )] : array();
+ $plugins_to_activate = array();
+
+ /** Split plugin value into array with plugin file path, plugin source and plugin name */
+ foreach ( $plugins as $i => $plugin )
+ $plugins_to_activate[] = explode( ',', $plugin );
+
+ foreach ( $plugins_to_activate as $i => $array ) {
+ if ( ! preg_match( '|.php$|', $array[0] ) ) // Plugins that haven't been installed yet won't have the correct file path
+ unset( $plugins_to_activate[$i] );
+ }
+
+ /** Return early if there are no plugins to activate */
+ if ( empty( $plugins_to_activate ) )
+ return;
+
+ $plugins = array();
+ $plugin_names = array();
+
+ foreach ( $plugins_to_activate as $plugin_string ) {
+ $plugins[] = $plugin_string[0];
+ $plugin_names[] = $plugin_string[2];
+ }
+
+ $count = count( $plugin_names ); // Count so we can use _n function
+ $last_plugin = array_pop( $plugin_names ); // Pop off last name to prep for readability
+ $imploded = empty( $plugin_names ) ? '' . $last_plugin . ' ' : '' . ( implode( ', ', $plugin_names ) . ' and ' . $last_plugin . ' .' );
+
+ /** Now we are good to go - let's start activating plugins */
+ $activate = activate_plugins( $plugins );
+
+ if ( is_wp_error( $activate ) )
+ echo '' . $activate->get_error_message() . '
';
+ else
+ printf( '', _n( 'The following plugin was activated successfully:', 'The following plugins were activated successfully:', $count, 'tgmpa' ), $imploded );
+
+ /** Update recently activated plugins option */
+ $recent = (array) get_option( 'recently_activated' );
+
+ foreach ( $plugins as $plugin => $time )
+ if ( isset( $recent[$plugin] ) )
+ unset( $recent[$plugin] );
+
+ update_option( 'recently_activated', $recent );
+
+ unset( $_POST ); // Reset the $_POST variable in case user wants to perform one action after another
+ }
+ }
+
+ /**
+ * Prepares all of our information to be outputted into a usable table.
+ *
+ * @since 2.2.0
+ */
+ public function prepare_items() {
+
+ $per_page = 100; // Set it high so we shouldn't have to worry about pagination
+ $columns = $this->get_columns(); // Get all necessary column information
+ $hidden = array(); // No columns to hide, but we must set as an array
+ $sortable = array(); // No reason to make sortable columns
+ $this->_column_headers = array( $columns, $hidden, $sortable ); // Get all necessary column headers
+
+ /** Process our bulk actions here */
+ $this->process_bulk_actions();
+
+ /** Store all of our plugin data into $items array so WP_List_Table can use it */
+ $this->items = $this->_gather_plugin_data();
+
+ }
+
+ }
+}
+
+/**
+ * The WP_Upgrader file isn't always available. If it isn't available,
+ * we load it here.
+ *
+ * We check to make sure no action or activation keys are set so that WordPress
+ * doesn't try to re-include the class when processing upgrades or installs outside
+ * of the class.
+ *
+ * @since 2.2.0
+ */
+if ( ! class_exists( 'WP_Upgrader' ) && ( isset( $_GET[sanitize_key( 'page' )] ) && TGM_Plugin_Activation::$instance->menu === $_GET[sanitize_key( 'page' )] ) ) {
+ require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
+
+ if ( ! class_exists( 'TGM_Bulk_Installer' ) ) {
+ /**
+ * Installer class to handle bulk plugin installations.
+ *
+ * Extends WP_Upgrader and customizes to suit the installation of multiple
+ * plugins.
+ *
+ * @since 2.2.0
+ *
+ * @package TGM-Plugin-Activation
+ * @author Thomas Griffin
+ * @author Gary Jones
+ */
+ class TGM_Bulk_Installer extends WP_Upgrader {
+
+ /**
+ * Holds result of bulk plugin installation.
+ *
+ * @since 2.2.0
+ *
+ * @var string
+ */
+ public $result;
+
+ /**
+ * Flag to check if bulk installation is occurring or not.
+ *
+ * @since 2.2.0
+ *
+ * @var boolean
+ */
+ public $bulk = false;
+
+ /**
+ * Processes the bulk installation of plugins.
+ *
+ * @since 2.2.0
+ *
+ * @param array $packages The plugin sources needed for installation
+ * @return string|boolean Install confirmation messages on success, false on failure
+ */
+ public function bulk_install( $packages ) {
+
+ /** Pass installer skin object and set bulk property to true */
+ $this->init();
+ $this->bulk = true;
+
+ /** Set install strings and automatic activation strings (if config option is set to true) */
+ $this->install_strings();
+ if ( TGM_Plugin_Activation::$instance->is_automatic )
+ $this->activate_strings();
+
+ /** Run the header string to notify user that the process has begun */
+ $this->skin->header();
+
+ /** Connect to the Filesystem */
+ $res = $this->fs_connect( array( WP_CONTENT_DIR, WP_PLUGIN_DIR ) );
+ if ( ! $res ) {
+ $this->skin->footer();
+ return false;
+ }
+
+ /** Set the bulk header and prepare results array */
+ $this->skin->bulk_header();
+ $results = array();
+
+ /** Get the total number of packages being processed and iterate as each package is successfully installed */
+ $this->update_count = count( $packages );
+ $this->update_current = 0;
+
+ /** Loop through each plugin and process the installation */
+ foreach ( $packages as $plugin ) {
+ $this->update_current++; // Increment counter
+
+ /** Do the plugin install */
+ $result = $this->run(
+ array(
+ 'package' => $plugin, // The plugin source
+ 'destination' => WP_PLUGIN_DIR, // The destination dir
+ 'clear_destination' => false, // Do we want to clear the destination or not?
+ 'clear_working' => true, // Remove original install file
+ 'is_multi' => true, // Are we processing multiple installs?
+ 'hook_extra' => array( 'plugin' => $plugin, ), // Pass plugin source as extra data
+ )
+ );
+
+ /** Store installation results in result property */
+ $results[$plugin] = $this->result;
+
+ /** Prevent credentials auth screen from displaying multiple times */
+ if ( false === $result )
+ break;
+ }
+
+ /** Pass footer skin strings */
+ $this->skin->bulk_footer();
+ $this->skin->footer();
+
+ /** Return our results */
+ return $results;
+
+ }
+
+ /**
+ * Performs the actual installation of each plugin.
+ *
+ * This method also activates the plugin in the automatic flag has been
+ * set to true for the TGMPA class.
+ *
+ * @since 2.2.0
+ *
+ * @param array $options The installation cofig options
+ * @return null/array Return early if error, array of installation data on success
+ */
+ public function run( $options ) {
+
+ /** Default config options */
+ $defaults = array(
+ 'package' => '',
+ 'destination' => '',
+ 'clear_destination' => false,
+ 'clear_working' => true,
+ 'is_multi' => false,
+ 'hook_extra' => array(),
+ );
+
+ /** Parse default options with config options from $this->bulk_upgrade and extract them */
+ $options = wp_parse_args( $options, $defaults );
+ extract( $options );
+
+ /** Connect to the Filesystem */
+ $res = $this->fs_connect( array( WP_CONTENT_DIR, $destination ) );
+ if ( ! $res )
+ return false;
+
+ /** Return early if there is an error connecting to the Filesystem */
+ if ( is_wp_error( $res ) ) {
+ $this->skin->error( $res );
+ return $res;
+ }
+
+ /** Call $this->header separately if running multiple times */
+ if ( ! $is_multi )
+ $this->skin->header();
+
+ /** Set strings before the package is installed */
+ $this->skin->before();
+
+ /** Download the package (this just returns the filename of the file if the package is a local file) */
+ $download = $this->download_package( $package );
+ if ( is_wp_error( $download ) ) {
+ $this->skin->error( $download );
+ $this->skin->after();
+ return $download;
+ }
+
+ /** Don't accidentally delete a local file */
+ $delete_package = ( $download != $package );
+
+ /** Unzip file into a temporary working directory */
+ $working_dir = $this->unpack_package( $download, $delete_package );
+ if ( is_wp_error( $working_dir ) ) {
+ $this->skin->error( $working_dir );
+ $this->skin->after();
+ return $working_dir;
+ }
+
+ /** Install the package into the working directory with all passed config options */
+ $result = $this->install_package(
+ array(
+ 'source' => $working_dir,
+ 'destination' => $destination,
+ 'clear_destination' => $clear_destination,
+ 'clear_working' => $clear_working,
+ 'hook_extra' => $hook_extra,
+ )
+ );
+
+ /** Pass the result of the installation */
+ $this->skin->set_result( $result );
+
+ /** Set correct strings based on results */
+ if ( is_wp_error( $result ) ) {
+ $this->skin->error( $result );
+ $this->skin->feedback( 'process_failed' );
+ }
+ /** The plugin install is successful */
+ else {
+ $this->skin->feedback( 'process_success' );
+ }
+
+ /** Only process the activation of installed plugins if the automatic flag is set to true */
+ if ( TGM_Plugin_Activation::$instance->is_automatic ) {
+ /** Flush plugins cache so we can make sure that the installed plugins list is always up to date */
+ wp_cache_flush();
+
+ /** Get the installed plugin file and activate it */
+ $plugin_info = $this->plugin_info( $package );
+ $activate = activate_plugin( $plugin_info );
+
+ /** Re-populate the file path now that the plugin has been installed and activated */
+ TGM_Plugin_Activation::$instance->populate_file_path();
+
+ /** Set correct strings based on results */
+ if ( is_wp_error( $activate ) ) {
+ $this->skin->error( $activate );
+ $this->skin->feedback( 'activation_failed' );
+ }
+ /** The plugin activation is successful */
+ else {
+ $this->skin->feedback( 'activation_success' );
+ }
+ }
+
+ /** Flush plugins cache so we can make sure that the installed plugins list is always up to date */
+ wp_cache_flush();
+
+ /** Set install footer strings */
+ $this->skin->after();
+ if ( ! $is_multi )
+ $this->skin->footer();
+
+ return $result;
+
+ }
+
+ /**
+ * Sets the correct install strings for the installer skin to use.
+ *
+ * @since 2.2.0
+ */
+ public function install_strings() {
+
+ $this->strings['no_package'] = __( 'Install package not available.', 'tgmpa' );
+ $this->strings['downloading_package'] = __( 'Downloading install package from %s …', 'tgmpa' );
+ $this->strings['unpack_package'] = __( 'Unpacking the package…', 'tgmpa' );
+ $this->strings['installing_package'] = __( 'Installing the plugin…', 'tgmpa' );
+ $this->strings['process_failed'] = __( 'Plugin install failed.', 'tgmpa' );
+ $this->strings['process_success'] = __( 'Plugin installed successfully.', 'tgmpa' );
+
+ }
+
+ /**
+ * Sets the correct activation strings for the installer skin to use.
+ *
+ * @since 2.2.0
+ */
+ public function activate_strings() {
+
+ $this->strings['activation_failed'] = __( 'Plugin activation failed.', 'tgmpa' );
+ $this->strings['activation_success'] = __( 'Plugin activated successfully.', 'tgmpa' );
+
+ }
+
+ /**
+ * Grabs the plugin file from an installed plugin.
+ *
+ * @since 2.2.0
+ *
+ * @return string|boolean Return plugin file on success, false on failure
+ */
+ public function plugin_info() {
+
+ /** Return false if installation result isn't an array or the destination name isn't set */
+ if ( ! is_array( $this->result ) )
+ return false;
+ if ( empty( $this->result['destination_name'] ) )
+ return false;
+
+ /** Get the installed plugin file or return false if it isn't set */
+ $plugin = get_plugins( '/' . $this->result['destination_name'] );
+ if ( empty( $plugin ) )
+ return false;
+
+ /** Assume the requested plugin is the first in the list */
+ $pluginfiles = array_keys( $plugin );
+
+ return $this->result['destination_name'] . '/' . $pluginfiles[0];
+
+ }
+
+ }
+ }
+
+ if ( ! class_exists( 'TGM_Bulk_Installer_Skin' ) ) {
+ /**
+ * Installer skin to set strings for the bulk plugin installations..
+ *
+ * Extends Bulk_Upgrader_Skin and customizes to suit the installation of multiple
+ * plugins.
+ *
+ * @since 2.2.0
+ *
+ * @package TGM-Plugin-Activation
+ * @author Thomas Griffin
+ * @author Gary Jones
+ */
+ class TGM_Bulk_Installer_Skin extends Bulk_Upgrader_Skin {
+
+ /**
+ * Holds plugin info for each individual plugin installation.
+ *
+ * @since 2.2.0
+ *
+ * @var array
+ */
+ public $plugin_info = array();
+
+ /**
+ * Holds names of plugins that are undergoing bulk installations.
+ *
+ * @since 2.2.0
+ *
+ * @var array
+ */
+ public $plugin_names = array();
+
+ /**
+ * Integer to use for iteration through each plugin installation.
+ *
+ * @since 2.2.0
+ *
+ * @var integer
+ */
+ public $i = 0;
+
+ /**
+ * Constructor. Parses default args with new ones and extracts them for use.
+ *
+ * @since 2.2.0
+ *
+ * @param array $args Arguments to pass for use within the class
+ */
+ public function __construct( $args = array() ) {
+
+ /** Parse default and new args */
+ $defaults = array( 'url' => '', 'nonce' => '', 'names' => array() );
+ $args = wp_parse_args( $args, $defaults );
+
+ /** Set plugin names to $this->plugin_names property */
+ $this->plugin_names = $args['names'];
+
+ /** Extract the new args */
+ parent::__construct( $args );
+
+ }
+
+ /**
+ * Sets install skin strings for each individual plugin.
+ *
+ * Checks to see if the automatic activation flag is set and uses the
+ * the proper strings accordingly.
+ *
+ * @since 2.2.0
+ */
+ public function add_strings() {
+
+ /** Automatic activation strings */
+ if ( TGM_Plugin_Activation::$instance->is_automatic ) {
+ $this->upgrader->strings['skin_upgrade_start'] = __( 'The installation and activation process is starting. This process may take a while on some hosts, so please be patient.', 'tgmpa' );
+ $this->upgrader->strings['skin_update_successful'] = __( '%1$s installed and activated successfully.', 'tgmpa' ) . ' ' . __( 'Show Details', 'tgmpa' ) . ' ' . __( 'Hide Details', 'tgmpa' ) . ' . ';
+ $this->upgrader->strings['skin_upgrade_end'] = __( 'All installations and activations have been completed.', 'tgmpa' );
+ $this->upgrader->strings['skin_before_update_header'] = __( 'Installing and Activating Plugin %1$s (%2$d/%3$d)', 'tgmpa' );
+ }
+ /** Default installation strings */
+ else {
+ $this->upgrader->strings['skin_upgrade_start'] = __( 'The installation process is starting. This process may take a while on some hosts, so please be patient.', 'tgmpa' );
+ $this->upgrader->strings['skin_update_failed_error'] = __( 'An error occurred while installing %1$s: %2$s .', 'tgmpa' );
+ $this->upgrader->strings['skin_update_failed'] = __( 'The installation of %1$s failed.', 'tgmpa' );
+ $this->upgrader->strings['skin_update_successful'] = __( '%1$s installed successfully.', 'tgmpa' ) . ' ' . __( 'Show Details', 'tgmpa' ) . ' ' . __( 'Hide Details', 'tgmpa' ) . ' . ';
+ $this->upgrader->strings['skin_upgrade_end'] = __( 'All installations have been completed.', 'tgmpa' );
+ $this->upgrader->strings['skin_before_update_header'] = __( 'Installing Plugin %1$s (%2$d/%3$d)', 'tgmpa' );
+ }
+
+ }
+
+ /**
+ * Outputs the header strings and necessary JS before each plugin installation.
+ *
+ * @since 2.2.0
+ */
+ public function before( $title='' ) {
+
+ /** We are currently in the plugin installation loop, so set to true */
+ $this->in_loop = true;
+
+ printf( '' . $this->upgrader->strings['skin_before_update_header'] . ' ', $this->plugin_names[$this->i], $this->upgrader->update_current, $this->upgrader->update_count );
+ echo '';
+ echo '';
+
+ /** Flush header output buffer */
+ $this->before_flush_output();
+
+ }
+
+ /**
+ * Outputs the footer strings and necessary JS after each plugin installation.
+ *
+ * Checks for any errors and outputs them if they exist, else output
+ * success strings.
+ *
+ * @since 2.2.0
+ */
+ public function after( $title='' ) {
+
+ /** Close install strings */
+ echo '
';
+
+ /** Output error strings if an error has occurred */
+ if ( $this->error || ! $this->result ) {
+ if ( $this->error )
+ echo '' . sprintf( $this->upgrader->strings['skin_update_failed_error'], $this->plugin_names[$this->i], $this->error ) . '
';
+ else
+ echo '' . sprintf( $this->upgrader->strings['skin_update_failed'], $this->plugin_names[$this->i] ) . '
';
+
+ echo '';
+ }
+
+ /** If the result is set and there are no errors, success! */
+ if ( ! empty( $this->result ) && ! is_wp_error( $this->result ) ) {
+ echo '' . sprintf( $this->upgrader->strings['skin_update_successful'], $this->plugin_names[$this->i], 'jQuery(\'#progress-' . esc_js( $this->upgrader->update_current ) . '\').toggle();jQuery(\'span\', this).toggle(); return false;' ) . '
';
+ echo '';
+ }
+
+ /** Set in_loop and error to false and flush footer output buffer */
+ $this->reset();
+ $this->after_flush_output();
+
+ }
+
+ /**
+ * Outputs links after bulk plugin installation is complete.
+ *
+ * @since 2.2.0
+ */
+ public function bulk_footer() {
+
+ /** Serve up the string to say installations (and possibly activations) are complete */
+ parent::bulk_footer();
+
+ /** Flush plugins cache so we can make sure that the installed plugins list is always up to date */
+ wp_cache_flush();
+
+ /** Display message based on if all plugins are now active or not */
+ $complete = array();
+ foreach ( TGM_Plugin_Activation::$instance->plugins as $plugin ) {
+ if ( ! is_plugin_active( $plugin['file_path'] ) ) {
+ echo '' . TGM_Plugin_Activation::$instance->strings['return'] . '
';
+ $complete[] = $plugin;
+ break;
+ }
+ /** Nothing to store */
+ else {
+ $complete[] = '';
+ }
+ }
+
+ /** Filter out any empty entries */
+ $complete = array_filter( $complete );
+
+ /** All plugins are active, so we display the complete string and hide the menu to protect users */
+ if ( empty( $complete ) ) {
+ echo '' . sprintf( TGM_Plugin_Activation::$instance->strings['complete'], '' . __( 'Return to the Dashboard', 'tgmpa' ) . ' ' ) . '
';
+ echo '';
+ }
+
+ }
+
+ /**
+ * Flush header output buffer.
+ *
+ * @since 2.2.0
+ */
+ public function before_flush_output() {
+
+ wp_ob_end_flush_all();
+ flush();
+
+ }
+
+ /**
+ * Flush footer output buffer and iterate $this->i to make sure the
+ * installation strings reference the correct plugin.
+ *
+ * @since 2.2.0
+ */
+ public function after_flush_output() {
+
+ wp_ob_end_flush_all();
+ flush();
+ $this->i++;
+
+ }
+
+ }
+ }
+}
diff --git a/includes/mm-jquery.js b/includes/mm-jquery.js
new file mode 100644
index 0000000..3a8210c
--- /dev/null
+++ b/includes/mm-jquery.js
@@ -0,0 +1,57 @@
+// as the page loads, cal these scripts
+jQuery(document).ready(function() {
+
+ var h = window.location.host.toLowerCase();
+ jQuery("a[href^='http']:not([href*='" + h + "']), a[href$='.pdf'], a[hrefjQuery$='.mp3'], a[href$='.m4a'], a[href$='.wav']").attr("target", "_blank");
+
+ // Specifically for press kit link
+ jQuery("a[href*='press-kit']").attr("target", "_blank");
+ jQuery("a[href^='http://']:not([href*='" + h + "'])").addClass("externalLink");
+ jQuery("a[href^='https://']:not([href*='" + h + "'])").addClass("externalLink");
+ jQuery("img").parent().removeClass("externalLink");
+
+ // Niceify the HRs
+ jQuery('hr').wrap('
');
+
+ // Add classes to different types of media links
+ jQuery('a[href^="http://www.youtube"]').removeClass('externalLink');
+ jQuery('a[href^="mailto:"]').addClass('emailLink');
+ jQuery('a[href*=".pdf"]').attr({"target":"_blank"});
+ jQuery('a[href*=".pdf"]').addClass('pdfLink');
+ jQuery("img").parent().removeClass("pdfLink");
+
+ // Add classes to parts of lists
+ jQuery('li:last-child').addClass('last');
+ jQuery('li:first-child').addClass('first');
+ jQuery('.children').parent('li').addClass('parent');
+
+ // Mobile navigation button
+ jQuery('#menu-button').click(function() {
+ var button = jQuery(this);
+ button.toggleClass('open');
+ jQuery('.menu-primary').slideToggle();
+ });
+
+ // Mobile navigation icons
+ var closedIcon = '+';
+ var openIcon = '-';
+
+ jQuery('.genesis-nav-menu .parent:not(.current-menu-item, .current_page_item, .current_page_parent, .current_page_ancestor) > a').after('' + closedIcon + ' ');
+ jQuery('.genesis-nav-menu .parent.current-menu-item > a, .genesis-nav-menu .parent.current_page_item > a, .genesis-nav-menu .parent.current_page_parent > a, .genesis-nav-menu .parent.current_page_ancestor > a').after('' + openIcon + ' ');
+
+ jQuery('.sub-icon').click(function() {
+ var icon = jQuery(this);
+ icon.next('ul').slideToggle();
+ if ( icon.text().indexOf( closedIcon ) !== -1 )
+ icon.text(openIcon);
+ else if ( icon.text().indexOf( openIcon ) !== -1 )
+ icon.text(closedIcon);
+ });
+
+}); /* end of as page load scripts */
+
+
+// executes when complete page is fully loaded, including all frames, objects and images
+jQuery(window).load(function() {
+
+});
diff --git a/screenshot.png b/screenshot.png
new file mode 100644
index 0000000..715cf18
Binary files /dev/null and b/screenshot.png differ
diff --git a/style.css b/style.css
new file mode 100644
index 0000000..3c50021
--- /dev/null
+++ b/style.css
@@ -0,0 +1,1628 @@
+/*
+ Theme Name: Trestle
+ Theme URI: http://www.mightyminnow.com/2013/08/our-new-mobile-first-child-theme-for-genesis-2-0/
+ Template: genesis
+ Description: This is a "Mobile First" child theme based on the default Genesis 2.0 Sample Theme .
+ Author: MIGHTYminnow
+ Author URI: http://www.mightyminnow.com/
+ Version: 1.0
+*/
+
+/* Table of Contents
+
+ - Imports
+ - HTML5 Reset
+ - Baseline Normalize
+ - Box Sizing
+ - Float Clearing
+ - Defaults
+ - Typographical Elements
+ - Headings
+ - Objects
+ - Forms
+ - Tables
+ - Structure and Layout
+ - Site Containers
+ - Column Widths and Positions
+ - Column Classes
+ - Common Classes
+ - WordPress
+ - Genesis
+ - Titles
+ - Widgets
+ - Featured Content
+ - Plugins
+ - Genesis eNews Extended
+ - Genesis Latest Tweets
+ - Gravity Forms
+ - Jetpack
+ - Site Header
+ - Title Area
+ - Widget Area
+ - Site Navigation
+ - Header Navigation
+ - Primary Navigation
+ - Secondary Navigation
+ - Content Area
+ - Entries
+ - Pagination
+ - Comments
+ - Sidebars
+ - Footer Widgets
+ - Site Footer
+ - General Components
+ - Media Queries
+
+*/
+
+
+/*
+HTML5 Reset
+---------------------------------------------------------------------------------------------------- */
+
+/* Baseline Normalize
+ normalize.css v2.1.2 | MIT License | git.io/normalize
+--------------------------------------------- */
+
+article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden]{display:none}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{font-size:2em;margin:.67em 0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}mark{background:#ff0;color:#000}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}button,input{line-height:normal}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}
+
+/* Box Sizing
+--------------------------------------------- */
+
+*,
+input[type="search"] {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+/* Float Clearing
+--------------------------------------------- */
+
+.archive-pagination:before,
+.clearfix:before,
+.entry:before,
+.entry-pagination:before,
+.footer-widgets:before,
+.nav-primary:before,
+.nav-secondary:before,
+.site-container:before,
+.site-footer:before,
+.site-header:before,
+.site-inner:before,
+.wrap:before {
+ content: " ";
+ display: table;
+}
+
+.archive-pagination:after,
+.clearfix:after,
+.entry:after,
+.entry-pagination:after,
+.footer-widgets:after,
+.nav-primary:after,
+.nav-secondary:after,
+.site-container:after,
+.site-footer:after,
+.site-header:after,
+.site-inner:after,
+.wrap:after {
+ clear: both;
+ content: " ";
+ display: table;
+}
+
+
+/*
+Defaults
+---------------------------------------------------------------------------------------------------- */
+
+/* Typographical Elements
+--------------------------------------------- */
+
+html {
+ font-size: 62.5%; /* 10px browser default */
+}
+
+body {
+ background-color: #fff;
+ color: #666;
+ font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+ font-size: 16px;
+ font-size: 1.6rem;
+ font-weight: 300;
+ line-height: 1.625;
+}
+
+a,
+button,
+input:focus,
+input[type="button"],
+input[type="reset"],
+input[type="submit"],
+textarea:focus,
+.button {
+ -webkit-transition: all 0.1s ease-in-out;
+ -moz-transition: all 0.1s ease-in-out;
+ -ms-transition: all 0.1s ease-in-out;
+ -o-transition: all 0.1s ease-in-out;
+ transition: all 0.1s ease-in-out;
+}
+
+::-moz-selection {
+ background-color: #333;
+ color: #fff;
+}
+
+::selection {
+ background-color: #333;
+ color: #fff;
+}
+
+a {
+ color: #666;
+ text-decoration: none;
+}
+
+a img {
+ margin-bottom: -4px;
+ margin-bottom: -0.4rem;
+}
+
+a:hover {
+ color: #333;
+}
+
+p {
+ margin: 0 0 24px;
+ margin: 0 0 2.4rem;
+ padding: 0;
+}
+
+strong {
+ font-weight: 700;
+}
+
+ol,
+ul {
+ margin: 0;
+ padding: 0;
+}
+
+blockquote,
+blockquote::before {
+ color: #999;
+}
+
+blockquote {
+ margin: 40px 40px 24px;
+ margin: 4rem 4rem 2.4rem;
+}
+
+blockquote::before {
+ content: "\201C";
+ display: block;
+ font-size: 30px;
+ font-size: 3rem;
+ height: 0;
+ left: -20px;
+ position: relative;
+ top: -10px;
+}
+
+.entry-content code {
+ background-color: #333;
+ color: #ddd;
+}
+
+cite {
+ font-style: normal;
+}
+
+/* Headings
+--------------------------------------------- */
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ color: #333;
+ font-family: Lato, sans-serif;
+ font-weight: 700;
+ line-height: 1.2;
+ margin: 0 0 16px;
+ margin: 0 0 1.6rem;
+}
+
+h1 {
+ font-size: 36px;
+ font-size: 3.6rem;
+}
+
+h2 {
+ font-size: 30px;
+ font-size: 3rem;
+}
+
+h3 {
+ font-size: 24px;
+ font-size: 2.4rem;
+}
+
+h4 {
+ font-size: 20px;
+ font-size: 2rem;
+}
+
+h5 {
+ font-size: 18px;
+ font-size: 1.8rem;
+}
+
+h6 {
+ font-size: 16px;
+ font-size: 1.6rem;
+}
+
+/* Objects
+--------------------------------------------- */
+
+embed,
+iframe,
+img,
+object,
+video,
+.wp-caption {
+ max-width: 100%;
+}
+
+img {
+ height: auto;
+ width: auto; /* IE8 */
+}
+
+/* Forms
+--------------------------------------------- */
+
+input,
+select,
+textarea {
+ background-color: #fff;
+ border: 1px solid #ddd;
+ border-radius: 3px;
+ box-shadow: 1px 1px 3px #eee inset;
+ color: #999;
+ font-size: 14px;
+ font-size: 1.4rem;
+ padding: 15px;
+ padding: 1.5rem;
+ width: 100%;
+}
+
+input:focus,
+textarea:focus {
+ border: 1px solid #999;
+ outline: none;
+}
+
+::-moz-placeholder {
+ color: #999;
+ opacity: 1;
+}
+
+::-webkit-input-placeholder {
+ color: #999;
+}
+
+button,
+input[type="button"],
+input[type="reset"],
+input[type="submit"],
+.button,
+.entry-content .button {
+ background-color: #333;
+ border: none;
+ box-shadow: none;
+ color: #fff;
+ cursor: pointer;
+ padding: 16px 24px;
+ padding: 1.6rem 2.4rem;
+ text-transform: uppercase;
+ width: auto;
+}
+
+button:hover,
+input:hover[type="button"],
+input:hover[type="reset"],
+input:hover[type="submit"],
+.button:hover,
+.entry-content .button:hover {
+ background-color: #f15123;
+}
+
+.entry-content .button:hover {
+ color: #fff;
+}
+
+.button {
+ border-radius: 3px;
+ display: inline-block;
+}
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-results-button {
+ display: none;
+}
+
+/* Tables
+--------------------------------------------- */
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+ line-height: 2;
+ margin-bottom: 40px;
+ margin-bottom: 4rem;
+ width: 100%;
+}
+
+tbody {
+ border-bottom: 1px solid #ddd;
+}
+
+th,
+td {
+ text-align: left;
+}
+
+th {
+ font-weight: bold;
+ text-transform: uppercase;
+}
+
+td {
+ border-top: 1px solid #ddd;
+ padding: 6px 0;
+ padding: 0.6rem 0;
+}
+
+
+/*
+Structure and Layout
+---------------------------------------------------------------------------------------------------- */
+
+/* Site Containers
+--------------------------------------------- */
+.site-inner,
+.wrap {
+ margin: 0 auto;
+ max-width: 1140px;
+}
+
+.site-inner {
+ clear: both;
+}
+
+.content-sidebar-wrap,
+#ez-home-container-wrap {
+ clear: both;
+ padding: 20px;
+ padding: 2rem;
+}
+
+/* Column Widths and Positions
+--------------------------------------------- */
+
+/* Wrapping div for .content and .sidebar-primary */
+
+.content-sidebar-wrap {
+ float: left;
+ width: 100%;
+}
+
+.content-sidebar-sidebar .content-sidebar-wrap {
+ float: left;
+}
+
+.sidebar-content-sidebar .content-sidebar-wrap,
+.sidebar-sidebar-content .content-sidebar-wrap {
+ float: right;
+}
+
+/* Content */
+
+.content-sidebar .content,
+.content-sidebar-sidebar .content,
+.sidebar-content-sidebar .content {
+ float: left;
+}
+
+.content {
+ float: right;
+ width: 100%;
+}
+
+/* Primary Sidebar */
+
+.sidebar-primary {
+ float: right;
+ width: 100%;
+}
+
+.sidebar-content .sidebar-primary,
+.sidebar-sidebar-content .sidebar-primary {
+ float: left;
+}
+
+/* Secondary Sidebar */
+
+.sidebar-secondary {
+ float: left;
+ width: 100%;
+}
+
+.content-sidebar-sidebar .sidebar-secondary {
+ float: right;
+}
+
+/* Column Classes
+ Link: http://twitter.github.io/bootstrap/assets/css/bootstrap-responsive.css
+--------------------------------------------- */
+
+.five-sixths,
+.four-sixths,
+.one-fourth,
+.one-half,
+.one-sixth,
+.one-third,
+.three-fourths,
+.three-sixths,
+.two-fourths,
+.two-sixths,
+.two-thirds {
+ float: left;
+ margin: 0;
+ width: 100%;
+}
+
+
+/*
+Common Classes
+---------------------------------------------------------------------------------------------------- */
+
+/* WordPress
+--------------------------------------------- */
+
+.avatar {
+ float: left;
+}
+
+.alignleft .avatar {
+ margin-right: 24px;
+ margin-right: 2.4rem;
+}
+
+.alignright .avatar {
+ margin-left: 24px;
+ margin-left: 2.4rem;
+}
+
+.sticky {
+}
+
+img.centered,
+.aligncenter {
+ display: block;
+ margin: 0 auto 24px;
+ margin: 0 auto 2.4rem;
+}
+
+img.alignnone {
+ margin-bottom: 12px;
+ margin-bottom: 1.2rem;
+}
+
+.alignleft {
+ float: left;
+ text-align: left;
+}
+
+.alignright {
+ float: right;
+ text-align: right;
+}
+
+img.alignleft,
+.wp-caption.alignleft {
+ margin: 0 24px 24px 0;
+ margin: 0 2.4rem 2.4rem 0;
+}
+
+img.alignright,
+.wp-caption.alignright {
+ margin: 0 0 24px 24px;
+ margin: 0 0 2.4rem 2.4rem;
+}
+
+.wp-caption-text {
+ font-size: 14px;
+ font-size: 1.4rem;
+ font-weight: 700;
+ text-align: center;
+}
+
+.gallery-caption {
+}
+
+.widget_calendar table {
+ width: 100%;
+}
+
+.widget_calendar td,
+.widget_calendar th {
+ text-align: center;
+}
+
+/* Genesis
+--------------------------------------------- */
+
+.breadcrumb {
+ margin-bottom: 20px;
+ margin-bottom: 2rem;
+}
+
+.archive-description,
+.author-box {
+ background-color: #fff;
+ margin-bottom: 40px;
+ margin-bottom: 4rem;
+}
+
+.author-box-title {
+ color: #333;
+ font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+ font-size: 16px;
+ font-size: 1.6rem;
+ margin-bottom: 4px;
+ margin-bottom: 0.4rem;
+}
+
+.author-box a {
+ border-bottom: 1px solid #ddd;
+}
+
+.author-box p {
+ margin-bottom: 0;
+}
+
+.author-box .avatar {
+ margin-right: 24px;
+ margin-right: 2.4rem;
+}
+
+/* Titles
+--------------------------------------------- */
+
+.entry-title {
+ font-size: 36px;
+ font-size: 3.6rem;
+ line-height: 1;
+}
+
+.entry-title a,
+.sidebar .widget-title a {
+ color: #333;
+}
+
+.entry-title a:hover {
+ color: #666;
+}
+
+.widget-title {
+ font-size: 16px;
+ font-size: 1.6rem;
+ margin-bottom: 24px;
+ margin-bottom: 2.4rem;
+ text-transform: uppercase;
+}
+
+.sidebar .widget-title a {
+ border: none;
+}
+
+.archive-title {
+ font-size: 20px;
+ font-size: 2rem;
+ margin-bottom: 24px;
+ margin-bottom: 2.4rem;
+}
+
+
+/*
+Widgets
+---------------------------------------------------------------------------------------------------- */
+
+/* Featured Content
+--------------------------------------------- */
+
+.featured-content .entry {
+ border-bottom: 2px solid #f5f5f5;
+ margin-bottom: 20px;
+ margin-bottom: 2rem;
+ padding: 0 0 24px;
+ padding: 0 0 2.4rem;
+}
+
+.featured-content .entry-title {
+ border: none;
+ font-size: 24px;
+ font-size: 2.4rem;
+ line-height: 1.2;
+}
+
+.featured-content .entry-title a {
+ border: none;
+}
+
+
+/*
+Plugins
+---------------------------------------------------------------------------------------------------- */
+
+/* Genesis eNews Extended
+--------------------------------------------- */
+
+.enews-widget {
+ color: #999;
+}
+
+.sidebar .widget.enews-widget {
+ background-color: #333;
+}
+
+.sidebar .enews-widget {
+ padding: 40px;
+ padding: 4rem;
+}
+
+.enews-widget .widget-title {
+ color: #fff;
+}
+
+.enews-widget input {
+ margin-bottom: 16px;
+ margin-bottom: 1.6rem;
+}
+
+.enews-widget input:focus {
+ border: 1px solid #ddd;
+}
+
+.enews-widget input[type="submit"] {
+ background-color: #f15123;
+ color: #fff;
+ margin: 0;
+ width: 100%;
+}
+
+.enews-widget input:hover[type="submit"] {
+ background-color: #fff;
+ color: #333;
+}
+
+/* Genesis Latest Tweets
+--------------------------------------------- */
+
+.latest-tweets ul li {
+ margin-bottom: 16px;
+ margin-bottom: 1.6rem;
+}
+
+/* Gravity Forms
+--------------------------------------------- */
+
+div.gform_wrapper input[type="email"],
+div.gform_wrapper input[type="text"],
+div.gform_wrapper textarea,
+div.gform_wrapper .ginput_complex label {
+ font-size: 16px;
+ font-size: 1.6rem;
+ padding: 16px;
+ padding: 1.6rem;
+}
+
+div.gform_wrapper .ginput_complex label {
+ padding: 0;
+}
+
+div.gform_wrapper li,
+div.gform_wrapper form li {
+ margin: 16px 0 0;
+ margin: 1.6rem 0 0;
+}
+
+div.gform_wrapper .gform_footer input[type="submit"] {
+ font-size: 14px;
+ font-size: 1.4rem;
+}
+
+/* Jetpack
+--------------------------------------------- */
+
+img#wpstats {
+ display: none;
+}
+
+
+/*
+Site Header
+---------------------------------------------------------------------------------------------------- */
+
+.site-header {
+ background-color: #fff;
+}
+
+.site-header .wrap {
+ padding: 20px;
+ padding: 2rem;
+}
+
+/* Title Area
+--------------------------------------------- */
+
+.title-area {
+ float: left;
+ font-family: Lato, sans-serif;
+ font-weight: 700;
+ padding: 16px 0;
+ padding: 1.6rem 0;
+ width: 100%;
+ text-align: center;
+}
+
+.header-image .title-area {
+ padding: 0;
+}
+
+.site-title {
+ font-size: 28px;
+ font-size: 2.8rem;
+ line-height: 1;
+ margin: 0 0 8px;
+ margin: 0 0 0.8rem;
+ text-transform: uppercase;
+}
+
+.site-title a,
+.site-title a:hover {
+ color: #333;
+}
+
+.site-description {
+ color: #999;
+ font-size: 16px;
+ font-size: 1.6rem;
+ font-weight: 300;
+ line-height: 1;
+ margin-bottom: 0;
+}
+
+/* Full width header, no widgets */
+
+.header-full-width .title-area,
+.header-full-width .site-title {
+ width: 100%;
+}
+
+.header-image .site-description,
+.header-image .site-title a {
+ display: block;
+ text-indent: -9999px;
+}
+
+/* Logo, hide text */
+
+.header-image .site-header .wrap {
+ background: url(images/logo.png) no-repeat;
+ background-position: center top;
+ padding: 0;
+}
+
+.header-image .site-title a {
+ float: left;
+ min-height: 164px;
+ width: 100%;
+}
+
+/* Widget Area
+--------------------------------------------- */
+
+.site-header .widget-area {
+ width: 100%;
+ text-align: center;
+}
+
+.site-header .search-form {
+ margin: 10px auto ;
+ margin: 1rem auto;
+ text-align: center;
+}
+
+
+/*
+Site Navigation
+---------------------------------------------------------------------------------------------------- */
+#menu-button {
+ display: block;
+ margin: 0 20px 10px;
+ text-align: center;
+}
+
+.nav-primary {
+ margin: 0 20px;
+ border-radius: 3px;
+ overflow: hidden;
+}
+
+.genesis-nav-menu {
+ clear: both;
+ color: #999;
+ font-family: Lato, sans-serif;
+ line-height: 1.5;
+ width: 100%;
+}
+
+.genesis-nav-menu .menu-item,
+.genesis-nav-menu li {
+ position: relative;
+ display: inline-block;
+}
+
+.genesis-nav-menu a {
+ border: none;
+ color: #999;
+ display: block;
+ padding: 20px;
+ padding: 2rem;
+ position: relative;
+}
+
+.genesis-nav-menu a:hover,
+.genesis-nav-menu .current-menu-item > a,
+.genesis-nav-menu .current_page_item > a
+.genesis-nav-menu .sub-menu .current-menu-item > a:hover,
+.genesis-nav-menu .sub-menu .current_page_item > a:hover {
+ color: #333;
+}
+
+.genesis-nav-menu .sub-menu .current-menu-item > a,
+.genesis-nav-menu ul .current_page_item > a {
+ color: #333;
+}
+
+.genesis-nav-menu > .menu-item > a,
+.genesis-nav-menu > li > a {
+ text-transform: uppercase;
+}
+
+.genesis-nav-menu .sub-menu,
+.genesis-nav-menu ul {
+ display: none;
+ background-color: #fff;
+ border-bottom: 1px solid #eee;
+ -webkit-transition: opacity .4s ease-in-out;
+ -moz-transition: opacity .4s ease-in-out;
+ -ms-transition: opacity .4s ease-in-out;
+ -o-transition: opacity .4s ease-in-out;
+ transition: opacity .4s ease-in-out;
+}
+
+.genesis-nav-menu .current-menu-item > .sub-menu,
+.genesis-nav-menu .current_page_item > ul,
+.genesis-nav-menu .current_page_parent > ul,
+.genesis-nav-menu .current_page_ancestor > ul {
+ display: block;
+}
+
+.genesis-nav-menu .sub-menu,
+.genesis-nav-menu ul {
+ font-size: .9em;
+}
+
+.genesis-nav-menu .sub-menu a,
+.genesis-nav-menu ul a {
+ border: 1px solid #eee;
+ border-bottom: none;
+ padding: 10px 20px;
+ padding: 1rem 2rem;
+ position: relative;
+}
+
+.genesis-nav-menu > .right {
+ display: none;
+}
+
+.genesis-nav-menu > .rss > a {
+ margin-left: 48px;
+ margin-left: 4.8rem;
+}
+
+.genesis-nav-menu > .search {
+ padding: 14px 0 0;
+ padding: 1.4rem 0 0;
+}
+
+/* Site Header Navigation
+--------------------------------------------- */
+
+.site-header .sub-menu {
+ border-top: 1px solid #eee;
+}
+
+.site-header .sub-menu .sub-menu {
+ margin-top: -55px;
+}
+
+.site-header .menu a {
+ font-size: .8em;
+ padding: 15px 10px;
+ padding: 1.5rem 1rem;
+}
+
+/* Primary / Mobile Navigation
+--------------------------------------------- */
+
+.nav-primary {
+ background-color: #333;
+}
+
+.nav-primary .genesis-nav-menu li {
+ display: block;
+}
+
+.nav-primary .genesis-nav-menu > li {
+ border-top: 1px solid #444;
+}
+
+.nav-primary .genesis-nav-menu a {
+ padding-right: 50px;
+ padding-right: 5rem;
+}
+
+.nav-primary a:hover,
+.nav-primary .current-menu-item > a,
+.nav-primary .current_page_item > a {
+ color: #fff;
+}
+
+.nav-primary .genesis-nav-menu .sub-icon {
+ position: absolute;
+ z-index: 99;
+ top: 0;
+ bottom: 0;
+ right: 0;
+ width: 50px;
+ padding-left: 0;
+ padding-right: 0;
+ background-color: transparent;
+ border: none;
+ text-align: center;
+}
+
+.primary-nav .genesis-nav-menu ul ul a {
+ padding-left: 40px;
+}
+
+.nav-primary .sub-menu a:hover,
+.nav-primary ul ul a:hover {
+ color: #333;
+}
+
+/* Secondary Navigation
+--------------------------------------------- */
+
+.nav-secondary {
+ background-color: #fff;
+}
+
+
+/*
+Content Area
+---------------------------------------------------------------------------------------------------- */
+
+/* Entries
+--------------------------------------------- */
+
+.entry {
+ background-color: #fff;
+ border-radius: 3px;
+ margin-bottom: 40px;
+ margin-bottom: 4rem;
+}
+
+.entry-content a {
+ border-bottom: 1px solid #ddd;
+ color: #f15123;
+}
+
+.entry-content a:hover {
+ color: #333;
+}
+
+.entry-content .attachment a,
+.entry-content .gallery a {
+ border: none;
+}
+
+.entry-content ol,
+.entry-content p,
+.entry-content ul,
+.quote-caption {
+ margin-bottom: 26px;
+ margin-bottom: 2.6rem;
+}
+
+.entry-content ol,
+.entry-content ul {
+ margin-left: 40px;
+ margin-left: 4rem;
+}
+
+.entry-content ol li {
+ list-style-type: decimal;
+}
+
+.entry-content ul li {
+ list-style-type: disc;
+}
+
+.entry-content ol ol,
+.entry-content ul ul {
+ margin-bottom: 0;
+}
+
+.entry-content .search-form {
+ width: 50%;
+}
+
+.entry-meta {
+ color: #999;
+ font-size: 14px;
+ font-size: 1.4rem;
+}
+
+.entry-meta a {
+ border-bottom: 1px solid #ddd;
+}
+
+.entry-header .entry-meta {
+ margin-bottom: 24px;
+ margin-bottom: 2.4rem;
+}
+
+.entry-footer .entry-meta {
+ border-top: 2px solid #f5f5f5;
+ padding-top: 12px;
+ padding-top: 1.2rem;
+}
+
+.entry-comments-link::before {
+ content: "\2014";
+ margin: 0 6px 0 2px;
+ margin: 0 0.6rem 0 0.2rem;
+}
+
+.entry-categories,
+.entry-tags {
+ display: block;
+}
+
+/* Pagination
+--------------------------------------------- */
+
+.archive-pagination,
+.entry-pagination {
+ font-size: 14px;
+ font-size: 1.4rem;
+ margin: 40px 0;
+ margin: 4rem 0;
+}
+
+.archive-pagination li {
+ display: inline;
+}
+
+.archive-pagination li a {
+ background-color: #333;
+ border-radius: 3px;
+ color: #fff;
+ cursor: pointer;
+ display: inline-block;
+ padding: 8px 12px;
+ padding: 0.8rem 1.2rem;
+}
+
+.archive-pagination li a:hover,
+.archive-pagination li.active a {
+ background-color: #f15123;
+}
+
+.entry-pagination a {
+ border-bottom: 1px solid #ddd;
+}
+
+/* Comments
+--------------------------------------------- */
+
+.comment-respond,
+.entry-comments,
+.entry-pings {
+ background-color: #fff;
+ margin-bottom: 40px;
+ margin-bottom: 4rem;
+}
+
+.comment-respond a,
+.entry-comments a {
+ border-bottom: 1px solid #ddd;
+}
+
+.comment-content {
+ clear: both;
+}
+
+.entry-comments .comment-author {
+ margin-bottom: 0;
+}
+
+.comment-respond input[type="email"],
+.comment-respond input[type="text"],
+.comment-respond input[type="url"] {
+ width: 50%
+}
+
+.comment-respond label {
+ display: block;
+ margin-right: 12px;
+ margin-right: 1.2rem;
+}
+
+.comment-list li,
+.ping-list li {
+ list-style-type: none;
+}
+
+.comment-list li {
+ margin-top: 24px;
+ margin-top: 2.4rem;
+ padding: 32px;
+ padding: 3.2rem;
+}
+
+.comment-list li li {
+ margin-right: -32px;
+ margin-right: -3.2rem;
+}
+
+li.comment {
+ background-color: #f5f5f5;
+ border: 2px solid #fff;
+ border-right: none;
+}
+
+.comment .avatar {
+ margin: 0 16px 24px 0;
+ margin: 0 1.6rem 2.4rem 0;
+}
+
+.entry-pings .reply {
+ display: none;
+}
+
+.bypostauthor {
+}
+
+.form-allowed-tags {
+ background-color: #f5f5f5;
+ font-size: 14px;
+ font-size: 1.4rem;
+ padding: 24px;
+ padding: 2.4rem;
+}
+
+
+/*
+Sidebars
+---------------------------------------------------------------------------------------------------- */
+
+.sidebar {
+ color: #999;
+}
+
+.sidebar a {
+ border-bottom: 1px solid #ddd;
+}
+
+.sidebar p:last-child {
+ margin-bottom: 0;
+}
+
+.sidebar li {
+ list-style-type: none;
+ margin-bottom: 6px;
+ margin-bottom: 0.6rem;
+ word-wrap: break-word;
+}
+
+.sidebar ul > li:last-child {
+ margin-bottom: 0;
+}
+
+.sidebar .widget {
+ background-color: #fff;
+ border-radius: 3px;
+ margin-bottom: 40px;
+ margin-bottom: 4rem;
+}
+
+
+/*
+Footer Widgets
+---------------------------------------------------------------------------------------------------- */
+
+.footer-widgets {
+ background-color: #333;
+ color: #999;
+ clear: both;
+ padding: 40px 5% 16px;
+ padding: 4rem 5% 1.6rem;
+}
+
+
+
+.footer-widgets-1,
+.footer-widgets-2,
+.footer-widgets-3 {
+ width: 100%;
+}
+
+.footer-widgets-1,
+.footer-widgets-2 {
+ float: left;
+}
+
+.footer-widgets-3 {
+ float: right;
+}
+
+.footer-widgets a {
+ border-bottom: 1px solid #666;
+ color: #999;
+}
+
+.footer-widgets a:hover {
+ color: #ddd;
+}
+
+.footer-widgets .widget {
+ margin-bottom: 24px;
+ margin-bottom: 2.4rem;
+}
+
+.footer-widgets .widget-title {
+ color: #fff;
+}
+
+.footer-widgets li {
+ list-style-type: none;
+ margin-bottom: 6px;
+ margin-bottom: 0.6rem;
+ word-wrap: break-word;
+}
+
+.footer-widgets .search-form input:focus {
+ border: 1px solid #ddd;
+}
+
+
+/*
+Site Footer
+---------------------------------------------------------------------------------------------------- */
+
+.site-footer {
+ background-color: #fff;
+ color: #999;
+ font-size: 14px;
+ font-size: 1.4rem;
+ padding: 24px 0;
+ padding: 2.4rem 0;
+ text-align: center;
+}
+
+.site-footer a {
+ border-bottom: 1px solid #ddd;
+}
+
+.site-footer p {
+ margin-bottom: .75em;
+}
+
+.site-footer p:last-child {
+ margin-bottom: 0;
+}
+
+
+/*
+General Components
+---------------------------------------------------------------------------------------------------- */
+
+/* Search Form */
+.search-form {
+ padding-right: 115px;
+}
+
+.search-form input[type="submit"] {
+ float: right;
+ max-width: 108px;
+ margin-right: -115px;
+}
+
+/*
+Media Queries
+---------------------------------------------------------------------------------------------------- */
+
+@media only screen and (-webkit-min-device-pixel-ratio: 1.5),
+ only screen and (-moz-min-device-pixel-ratio: 1.5),
+ only screen and (-o-min-device-pixel-ratio: 3/2),
+ only screen and (min-device-pixel-ratio: 1.5) {
+
+ .header-image .site-header .wrap {
+ background: url(images/logo@2x.png) no-repeat left;
+ background-size: 320px 164px;
+ }
+
+}
+
+@media only screen and (min-width: 768px) {
+
+ body {
+ background-color: #f5f5f5;
+ }
+
+ .title-area {
+ text-align: left;
+ }
+
+ .header-image .site-header .wrap {
+ background-position: left top;
+ }
+
+ .header-image .site-header .widget-area {
+ padding: 40px 0;
+ padding: 4rem 0;
+ }
+
+ .header-widget-area .widget {
+ float: right;
+ clear: right;
+ }
+
+ .site-header .menu .last a {
+ padding-right: 0;
+ }
+
+ .site-header .search-form {
+ float: right;
+ margin-top: 24px;
+ margin-top: 2.4rem;
+ }
+
+ .site-header .widget-area {
+ width: auto;
+ }
+
+ .site-header .genesis-nav-menu {
+ text-align: right;
+ }
+
+ .wrap {
+ padding-left: 0;
+ padding-right: 0;
+ }
+
+ .content {
+ width: 66.5%;
+ }
+
+ .full-width-content .content {
+ width: 100%;
+ }
+
+ .sidebar-content-sidebar .content,
+ .sidebar-sidebar-content .content,
+ .content-sidebar-sidebar .content {
+ width: 40%;
+ }
+
+ .entry, .sidebar .widget {
+ padding: 30px 40px;
+ padding: 3rem 4rem;
+ }
+
+ .sidebar-secondary {
+ width: 180px;
+ }
+
+ .footer-widgets-1 {
+ margin-right: 40px;
+ margin-right: 4rem;
+ }
+
+ .entry-footer .entry-meta {
+ border-top: 2px solid #f5f5f5;
+ margin: 0 -40px;
+ margin: 0 -4rem;
+ padding: 32px 40px 8px;
+ padding: 3.2rem 4rem 0.8rem;
+ }
+
+ .footer-widgets {
+ padding: 40px 0 16px;
+ padding: 4rem 0 1.6rem;
+ }
+
+ .footer-widgets-1,
+ .footer-widgets-2,
+ .footer-widgets-3,
+ .sidebar-primary,
+ .title-area {
+ width: 30%;
+ }
+
+ .five-sixths,
+ .four-sixths,
+ .one-fourth,
+ .one-half,
+ .one-sixth,
+ .one-third,
+ .three-fourths,
+ .three-sixths,
+ .two-fourths,
+ .two-sixths,
+ .two-thirds {
+ margin-left: 2.564102564102564%;
+ }
+
+ .one-half,
+ .three-sixths,
+ .two-fourths {
+ width: 48.717948717948715%;
+ }
+
+ .one-third,
+ .two-sixths {
+ width: 31.623931623931625%;
+ }
+
+ .four-sixths,
+ .two-thirds {
+ width: 65.81196581196582%;
+ }
+
+ .one-fourth {
+ width: 23.076923076923077%;
+ }
+
+ .three-fourths {
+ width: 74.35897435897436%;
+ }
+
+ .one-sixth {
+ width: 14.52991452991453%;
+ }
+
+ .five-sixths {
+ width: 82.90598290598291%;
+ }
+
+ .first {
+ clear: both;
+ margin-left: 0;
+ }
+
+ /* Mobile Navigation
+ --------------------------------------------- */
+ #menu-button {
+ display: none;
+ }
+
+ .nav-primary {
+ margin: 0;
+ border-radius: 0;
+ overflow: visible;
+ }
+
+ .nav-primary .genesis-nav-menu {
+ display: block !important;
+ }
+
+ .nav-primary .genesis-nav-menu .menu-item,
+ .nav-primary .genesis-nav-menu li {
+ display: inline-block;
+ text-align: left;
+ }
+
+ .nav-primary .genesis-nav-menu > li {
+ border-top: none;
+ }
+
+ .nav-primary .genesis-nav-menu .sub-menu,
+ .nav-primary .genesis-nav-menu ul {
+ display: block;
+ left: -9999px;
+ opacity: 0;
+ position: absolute;
+ width: 200px;
+ z-index: 99;
+ font-size: 1em;
+ }
+
+ .nav-primary .genesis-nav-menu .sub-icon {
+ display: none;
+ }
+
+ .nav-primary .genesis-nav-menu a {
+ padding: 20px;
+ padding: 2rem;
+ }
+
+ .nav-primary .genesis-nav-menu ul a,
+ .nav-primary .genesis-nav-menu ul ul a {
+ position: relative;
+ padding: 10px 20px;
+ padding: 1rem 2rem;
+ width: 200px;
+ font-size: .9em;
+ }
+
+ .nav-primary .genesis-nav-menu > .parent > a:after {
+ content: "\f0d7";
+ position: relative;
+ top: -.2em;
+ margin-left: 8px;
+ font-family: FontAwesome;
+ font-size: .6em;
+ }
+
+ .nav-primary .genesis-nav-menu ul .parent > a:after {
+ content: "\f0da";
+ position: absolute;
+ top: 1em;
+ right: 8px;
+ margin: 0;
+ font-family: FontAwesome;
+ font-size: .8em;
+ vertical-align: middle;
+ }
+
+ .nav-primary .genesis-nav-menu .menu-item:hover,
+ .nav-primary .genesis-nav-menu li:hover {
+ position: relative;
+ }
+
+ .nav-primary .genesis-nav-menu .menu-item:hover > .sub-menu,
+ .nav-primary .genesis-nav-menu li:hover > ul {
+ left: auto;
+ opacity: 1;
+ }
+
+ .nav-primary .genesis-nav-menu .sub-menu .menu-item:hover > .sub-menu,
+ .nav-primary .genesis-nav-menu ul li:hover > ul {
+ top: 0;
+ left: 100%;
+ margin-left: -1px;
+ }
+
+}
\ No newline at end of file