<?php
/*
Plugin Name: Link Library
Plugin URI: https://ylefebvre.github.io/wordpress-plugins/link-library/
Description: Display links on pages with a variety of options
Version: 7.8.4
Author: Yannick Lefebvre
Author URI: http://ylefebvre.github.io/
Text Domain: link-library

A plugin for the blogging MySQL/PHP-based WordPress.
Copyright 2025 Yannick Lefebvre

Translations:
French Translation courtesy of Michel G. et Luc Capronnier
Danish Translation courtesy of GeorgWP (http://wordpress.blogos.dk)
Italian Translation courtesy of Gianni Diurno
Serbian Translation courtesy of Ogi Djuraskovic (firstsiteguide.com)

This program is free software; you can redistribute it and/or
modify it under the terms of the GNUs General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

You can also view a copy of the HTML version of the GNU General Public
License at http://www.gnu.org/copyleft/gpl.html

I, Yannick Lefebvre, can be contacted via e-mail at ylefebvre@gmail.com
*/

// Exit if login page
if ( !function_exists( 'is_login' ) || ( function_exists( 'is_login' ) && !is_login() ) ) {
	update_option( 'link_manager_enabled', 0 );

	require_once(ABSPATH . '/wp-admin/includes/bookmark.php');
	require_once plugin_dir_path( __FILE__ ) . 'link-library-defaults.php';
	require_once plugin_dir_path( __FILE__ ) . 'rssfeed.php';
	require_once plugin_dir_path( __FILE__ ) . '/upvote-downvote/thumbs-rating.php';

	global $my_link_library_plugin;
	global $my_link_library_plugin_admin;

	function link_library_tweak_plugins_http_filter( $response, $r, $url ) {
		if ( stristr( $url, 'api.wordpress.org/plugins/update-check/1.1' ) ) {
			$wpapi_response = json_decode( $response['body'] );
			$wpapi_response->plugins = link_library_modify_http_response( $wpapi_response->plugins );
			$response['body'] = json_encode( $wpapi_response );
		}

		return $response;
	}

	function link_library_get_terms_filter_only_publish( $terms, $taxonomies, $args ) {
		global $wpdb;
		global $hide_if_empty_filter;

		$taxonomy = $taxonomies[0];
		if ( ! is_array( $terms ) && count( $terms ) < 1 ) {
			return $terms;
		}

		$filtered_terms = array();

		foreach ( $terms as $term ) {
			$result = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->posts p JOIN $wpdb->term_relationships rl ON p.ID = rl.object_id WHERE rl.term_taxonomy_id = $term->term_id AND p.post_status = 'publish' LIMIT 1" );

			if ( intval( $result ) > 0 || ( !$hide_if_empty_filter && 0 == intval( $result ) ) ) {
				$filtered_terms[] = $term;
			}
		}
		return $filtered_terms;
	}

	function link_library_get_terms_filter_publish_pending( $terms, $taxonomies, $args ) {
		global $wpdb;
		global $hide_if_empty_filter;

		$taxonomy = $taxonomies[0];
		if ( ! is_array( $terms ) && count( $terms ) < 1 ) {
			return $terms;
		}

		$filtered_terms = array();

		foreach ( $terms as $term ) {
			$result = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->posts p JOIN $wpdb->term_relationships rl ON p.ID = rl.object_id WHERE rl.term_taxonomy_id = $term->term_id AND ( p.post_status = 'publish' or p.post_status = 'pending' ) LIMIT 1" );
			if ( intval( $result ) > 0 || ( !$hide_if_empty_filter && 0 == intval( $result ) ) ) {
				$filtered_terms[] = $term;
			}
		}
		return $filtered_terms;
	}

	function link_library_get_terms_filter_publish_draft( $terms, $taxonomies, $args ) {
		global $wpdb;
		global $hide_if_empty_filter;

		$taxonomy = $taxonomies[0];
		if ( ! is_array( $terms ) && count( $terms ) < 1 ) {
			return $terms;
		}

		$filtered_terms = array();

		foreach ( $terms as $term ) {
			$result = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->posts p JOIN $wpdb->term_relationships rl ON p.ID = rl.object_id WHERE rl.term_taxonomy_id = $term->term_id AND ( p.post_status = 'publish' or p.post_status = 'draft' ) LIMIT 1" );
			if ( intval( $result ) > 0 || ( !$hide_if_empty_filter && 0 == intval( $result ) ) ) {
				$filtered_terms[] = $term;
			}
		}
		return $filtered_terms;
	}

	function link_library_get_terms_filter_publish_draft_pending( $terms, $taxonomies, $args ) {
		global $wpdb;
		global $hide_if_empty_filter;

		$taxonomy = $taxonomies[0];
		if ( ! is_array( $terms ) && count( $terms ) < 1 ) {
			return $terms;
		}

		$filtered_terms = array();

		foreach ( $terms as $term ) {
			$result = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->posts p JOIN $wpdb->term_relationships rl ON p.ID = rl.object_id WHERE rl.term_taxonomy_id = $term->term_id AND ( p.post_status = 'publish' or p.post_status = 'draft' or p.post_status = 'pending' ) LIMIT 1" );
			if ( intval( $result ) > 0 || ( !$hide_if_empty_filter && 0 == intval( $result ) ) ) {
				$filtered_terms[] = $term;
			}
		}
		return $filtered_terms;
	}

	function link_library_strposX( $haystack, $needle, $number ) {
		if( $number == '1' ){
			return strpos($haystack, $needle);
		} elseif( $number > '1' ){
			return strpos( $haystack, $needle, link_library_strposX( $haystack, $needle, $number - 1 ) + strlen( $needle ) );
		} else {
			return error_log( 'Error: Value for parameter $number is out of range' );
		}
	}

	function link_library_modify_http_response( $plugins_response ) {

		foreach ( $plugins_response as $response_key => $plugin_response ) {
			if ( plugin_basename(__FILE__) == $plugin_response->plugin ) {
				if ( 3 <= substr_count( $plugin_response->new_version, '.' ) ) {
					$plugin_info = get_plugin_data( __FILE__ );
					$period_position = link_library_strposX( $plugin_info['Version'], '.', 3 );
					if ( false !== $period_position ) {
						$current_version = substr( $plugin_info['Version'], 0, $period_position );
					} else {
						$current_version = $plugin_info['Version'];
					}

					$period_position2 = link_library_strposX( $plugin_response->new_version, '.', 3 );
					if ( false !== $period_position ) {
						$new_version = substr( $plugin_response->new_version, 0, $period_position2 );
					} else {
						$new_version = $plugin_response->new_version;
					}

					$version_diff = version_compare( $current_version, $new_version );

					if ( -1 < $version_diff ) {
						unset( $plugins_response->$response_key );
					}
				}
			}
		}

		return $plugins_response;
	}

	function ll_expand_posts_search( $search, $query ) {
		global $wpdb;

		if ( $query->query_vars['post_type'] == 'link_library_links' && !empty( $query->query['s'] ) ) {

			$query_words = explode( ' ', $query->query['s'] );
			if ( ! empty( $query_words ) ) {
				$number_of_words = sizeof( $query_words );
				if ( $number_of_words > 5 ) {
					$number_of_words = 5;
				}

				$sql = "
				or exists (
					select * from {$wpdb->postmeta} where post_id={$wpdb->posts}.ID
					and meta_key in ( 'link_description', 'link_notes', 'link_textfield', 'link_url' )
					";

				for ( $counter = 0; $counter < $number_of_words; $counter ++ ) {
					$sql .= 'and meta_value like %s ';
				}

				$sql .= "
				)
				";

				$like = array();

				foreach ( $query_words as $index => $query_word ) {
					$like[ $index ] = '%' . $wpdb->esc_like( $query_words[ $index ] ) . '%';
				}

				if ( 1 == $number_of_words ) {
					$search = preg_replace( "#\({$wpdb->posts}.post_title LIKE [^)]+\)\K#", $wpdb->prepare( $sql, $like[0] ), $search );
				} elseif ( 2 == $number_of_words ) {
					$search = preg_replace( "#\({$wpdb->posts}.post_title LIKE [^)]+\)\K#", $wpdb->prepare( $sql, $like[0], $like[1] ), $search );
				} elseif ( 3 == $number_of_words ) {
					$search = preg_replace( "#\({$wpdb->posts}.post_title LIKE [^)]+\)\K#", $wpdb->prepare( $sql, $like[0], $like[1], $like[2] ), $search );
				} elseif ( 4 == $number_of_words ) {
					$search = preg_replace( "#\({$wpdb->posts}.post_title LIKE [^)]+\)\K#", $wpdb->prepare( $sql, $like[0], $like[1], $like[2], $like[3] ), $search );
				} elseif ( 5 == $number_of_words ) {
					$search = preg_replace( "#\({$wpdb->posts}.post_title LIKE [^)]+\)\K#", $wpdb->prepare( $sql, $like[0], $like[1], $like[2], $like[3], $like[4] ), $search );
				}

			}
		}

		return $search;
	}

	/*********************************** Link Library Class *****************************************************************************/
	class link_library_plugin {

		//constructor of class, PHP4 compatible construction for backward compatibility
		function __construct() {

			// Functions to be called when plugin is activated and deactivated
			register_activation_hook( __FILE__, array( $this, 'll_install' ) );
			register_deactivation_hook( __FILE__, array( $this, 'll_uninstall' ) );

			add_action( 'init', array( $this, 'll_init' ) );
			add_action( 'wp_loaded', array( $this, 'll_update_60' ) );

			$newoptions = get_option( 'LinkLibraryPP1', '' );

			if ( empty( $newoptions ) ) {
				global $my_link_library_plugin_admin;

				if ( empty( $my_link_library_plugin_admin ) ) {
					require plugin_dir_path( __FILE__ ) . 'link-library-admin.php';
					$my_link_library_plugin_admin = new link_library_plugin_admin();
				}

				ll_reset_options( 1, 'list', 'return_and_set' );
				ll_reset_gen_settings( 'return_and_set' );
			}

			$genoptions = get_option( 'LinkLibraryGeneral' );
			$genoptions = wp_parse_args( $genoptions, ll_reset_gen_settings( 'return' ) );

			// Add short codes
			add_shortcode( 'link-library', array( $this, 'link_library_func' ) );
			add_shortcode( 'link-library-cats', array( $this, 'link_library_cats_func' ) );
			add_shortcode( 'cats-link-library', array( $this, 'link_library_cats_func' ) );
			add_shortcode( 'link-library-search', array( $this, 'link_library_search_func' ) );
			add_shortcode( 'search-link-library', array( $this, 'link_library_search_func' ) );
			add_shortcode( 'link-library-addlink', array( $this, 'link_library_addlink_func' ) );
			add_shortcode( 'addlink-link-library', array( $this, 'link_library_addlink_func' ) );
			add_shortcode( 'link-library-addlinkcustommsg', array( $this, 'link_library_addlink_func' ) );
			add_shortcode( 'addlinkcustommsg-link-library', array( $this, 'link_library_addlink_func' ) );
			add_shortcode( 'link-library-count', array( $this, 'link_library_count_func' ) );
			add_shortcode( 'link-library-filters', array( $this, 'link_library_filters' ) );
			add_shortcode( 'link-library-tagcloud', array( $this, 'link_library_tagcloud' ) );
			add_shortcode( 'rss-library', array( $this, 'rss_library_func' ) );

			// Function to determine if Link Library is used on a page before printing headers
			// the_posts gets triggered before wp_head
			add_filter( 'the_posts', array( $this, 'conditionally_add_scripts_and_styles' ) );

			// Function to print information in page header when plugin present
			add_action( 'wp_head', array( $this, 'll_rss_link' ) );

			add_filter( 'wp_title', array( $this, 'll_title_creator' ) );

			add_filter( 'get_the_excerpt', array( $this, 'll_display_single_link' ) );
			add_filter( 'the_excerpt', array( $this, 'll_display_single_link' ) );
			add_filter( 'post_type_link', array( $this, 'll_get_permalink' ), 10, 4 );
			add_filter( 'the_title', array( $this, 'll_get_title' ), 10, 2 );

			add_filter( 'block_categories_all', array( $this, 'll_block_categories' ), 10, 2 );
			add_action( 'rest_api_init', array( $this, 'll_rest_api_init' ) );
			

			// Re-write rules filters to allow for custom permalinks
			add_filter( 'rewrite_rules_array', array( $this, 'll_insertMyRewriteRules' ) );
			add_filter( 'query_vars', array( $this, 'll_insertMyRewriteQueryVars' ) );

			add_action( 'template_redirect', array( $this, 'll_template_redirect' ) );
			add_filter( 'template_include', array( $this, 'll_template_include' ) );
			add_action( 'wp_ajax_link_library_tracker', array( $this, 'link_library_ajax_tracker' ) );
			add_action( 'wp_ajax_nopriv_link_library_tracker', array( $this, 'link_library_ajax_tracker' ) );
			add_action( 'wp_ajax_link_library_ajax_update', array( $this, 'link_library_func') );
			add_action( 'wp_ajax_nopriv_link_library_ajax_update', array( $this, 'link_library_func') );
			add_action( 'wp_ajax_link_library_generate_image', array( $this, 'link_library_generate_image') );
			add_action( 'wp_ajax_nopriv_link_library_generate_image', array( $this, 'link_library_generate_image') );
			add_action( 'wp_ajax_link_library_popup_content', array( $this, 'll_popup_content') );
			add_action( 'wp_ajax_nopriv_link_library_popup_content', array( $this, 'll_popup_content') );

			add_action( 'wp_enqueue_scripts', array( $this, 'll_register_script' ) );

			add_filter( 'posts_where', array( $this, 'll_posts_where' ), 10, 2 );

			// Load text domain for translation of admin pages and text strings
			load_plugin_textdomain( 'link-library', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );

			add_filter( 'kses_allowed_protocols', array( $this, 'll_add_protocols' ) );

			add_filter( 'wp_feed_cache_transient_lifetime' , array( $this, 'feed_cache_filter_handler' ) );

			add_filter( 'post_type_link', array( $this, 'permalink_structure' ), 10, 4 );

			add_action('auth_redirect', array( $this, 'add_pending_count_filter') ); // modify esc_attr on auth_redirect
			add_action('admin_menu', array( $this, 'esc_attr_restore' ) ); // restore on admin_menu (very soon)

			if ( $genoptions['add_to_main_rss'] ) {
				add_action( 'request', array( $this, 'link_library_rss_feed_request' ) );
				add_filter( 'the_content_feed', array( $this, 'll_display_single_link' ) );
			}

			add_action( 'link_library_import_links', array( $this, 'll_import_links' ), 10, 0 );
			add_action( 'link_library_gen_thumbs', array( $this, 'll_gen_thumbs' ), 10, 0 );
		}

		function ll_import_links() {
			require_once plugin_dir_path( __FILE__ ) . 'link-library-link-importer.php';

			$genoptions = get_option( 'LinkLibraryGeneral' );
			$genoptions = wp_parse_args( $genoptions, ll_reset_gen_settings( 'return' ) );

			$row = 0;
			$successfulimport = 0;
			$successfulupdate = 0;

			link_library_import_links( $genoptions, $row, $successfulimport, $successfulupdate );
		}

		function ll_gen_thumbs() {
			require_once plugin_dir_path( __FILE__ ) . 'link-library-image-generator.php';

			$options = array();
			$options['categorylist_cpt'] = '';
			$options['uselocalimagesoverthumbshots'] = true;

			link_library_image_generator( $this, $options, true );
		}

		function ll_rest_api_init() {
			register_rest_route( 'link-library/v1', '/settingslist', array(
				'methods' => 'GET',
				'callback' => array( $this, 'll_rest_settings_list' ),
				'permission_callback' => '__return_true'
			) );
		}

		function ll_rest_settings_list( WP_REST_Request $request ) {
			$genoptions = get_option( 'LinkLibraryGeneral' );
			$genoptions = wp_parse_args( $genoptions, ll_reset_gen_settings( 'return' ) );
			
			if ( empty( $genoptions['numberstylesets'] ) ) {
				$numberofsets = 1;
			} else {
				$numberofsets = $genoptions['numberstylesets'];
			}
			$settings_array = array();
			for ( $counter = 1; $counter <= $numberofsets; $counter ++ ) {
				$tempoptionname = "LinkLibraryPP" . $counter;
				$tempoptions          = get_option( $tempoptionname );
				
				if ( ! empty( $tempoptions ) && isset( $tempoptions['settingssetname'] ) ) {
					$settings_array[$counter] = $tempoptions['settingssetname'];
				}
			}

			$response = new WP_REST_Response( $settings_array );

			return $response;
		}

		function ll_block_categories( $categories, $post ) {
			return array_merge(
				$categories,
				array(
					array(
						'slug' => 'link-library',
						'title' => __( 'Link Library', 'link-library' ),
						'icon'  => 'wordpress',
					),
				)
			);
		}

		function ll_posts_where( $where, $query ) {
			global $wpdb;

			$starts_with = $query->get( 'link_starts_with' );

			if ( $starts_with ) {
				$where .= " AND $wpdb->posts.post_title LIKE '$starts_with%'";
			}

			return $where;
		}

		function link_library_rss_feed_request( $qv ) {

			if ( isset( $qv['feed'] ) && !isset( $qv['post_type'] ) ) {
				$qv['post_type'] = array( 'post', 'link_library_links' );
			} elseif ( isset( $qv['feed'] ) && isset( $qv['post_type'] ) ) {
				$qv['post_type'][] = 'link_library_links';
			}
				
			return $qv;
		}


		function add_pending_count_filter() {
			add_filter('attribute_escape', array( $this, 'remove_esc_attr_and_count' ), 20, 2);
		}

		function esc_attr_restore() {
			remove_filter('attribute_escape', array( $this, 'remove_esc_attr_and_count' ), 20, 2);
		}

		function remove_esc_attr_and_count( $safe_text = '', $text = '' ) {
			if ( substr_count($text, '%%PENDING_COUNT%%') ) {
				$text = trim( str_replace('%%PENDING_COUNT%%', '', $text) );
				// run only once!
				remove_filter('attribute_escape', 'remove_esc_attr_and_count', 20, 2);
				$safe_text = esc_attr($text);
				// remember to set the right cpt name below
				$linkmoderatecount = 0;

				$args = array(
					'numberposts'   => -1,
					'post_type'     => 'link_library_links',
					'post_status'   => array( 'pending' )
				);
				$linkmoderatecount = count( get_posts( $args ) );
				if ( $linkmoderatecount > 0 ) {
					// we have pending, add the count
					$text = esc_attr($text) . '<span class="awaiting-mod count-' . $linkmoderatecount . '"><span class="pending-count">' . $linkmoderatecount . '</span></span>';
					return $text;
				}
			}
			return $safe_text;
		}

		function feed_cache_filter_handler( $seconds ) {
			$genoptions = get_option( 'LinkLibraryGeneral' );
			$genoptions = wp_parse_args( $genoptions, ll_reset_gen_settings( 'return' ) );

			return $genoptions['rsscachedelay'];
		}

		function ll_init() {
			$genoptions = get_option( 'LinkLibraryGeneral' );
			$genoptions = wp_parse_args( $genoptions, ll_reset_gen_settings( 'return' ) );

			$post_type_args = array(
				'labels' => array(
					'name' => __( 'Link Library', 'link-library' ),
					'singular_name' => __( 'Link', 'link-library' ),
					'add_new' => __( 'Add New', 'link-library' ),
					'add_new_item' => __( 'Add New Link', 'link-library' ),
					'edit' => __( 'Edit', 'link-library' ),
					'edit_item' => __( 'Edit Link', 'link-library' ),
					'new_item' => __( 'New Link', 'link-library' ),
					'view' => __( 'View', 'link-library' ),
					'view_item' => __( 'View Link', 'link-library' ),
					'search_items' => __( 'Search Links', 'link-library' ),
					'not_found' => __( 'No Links found', 'link-library' ),
					'not_found_in_trash' => __( 'No Links found in Trash', 'link-library' ),
					'parent' => __( 'Parent Link', 'link-library' ),
					'all_items' => __( 'All Links', 'link-library' ),
					'menu_name' => _x('Link Library %%PENDING_COUNT%%', 'Link Library', 'link-library'),
				),
				'show_in_nav_menu' => true,
				'show_ui' => true,
				'exclude_from_search' => !$genoptions['exclude_from_search'],
				'publicly_queryable' => $genoptions['publicly_queryable'],
				'menu_position' => 10,
				'supports' =>
					array( 'title', 'editor', 'comments' ),
				'taxonomies' => array( $genoptions['cattaxonomy'], $genoptions['tagtaxonomy'] ),
				'menu_icon' =>
					'dashicons-admin-links',
				'has_archive' => false,
				'rewrite' => array( 'slug' => $genoptions['cptslug'] . '/%' . $genoptions['cattaxonomy'] . '%' )
			);

			if ( class_exists( 'WPGraphQL' ) ) {
				$post_type_args['show_in_graphql'] = true;
				$post_type_args['hierarchical'] = true;
				$post_type_args['graphql_single_name'] = 'linklibrary';
				$post_type_args['graphql_plural_name'] = 'linklibrary';
			}		

			if ( $genoptions['exclude_from_search'] && $genoptions['publicly_queryable'] ) {
				unset( $post_type_args['exclude_from_search'] );
				unset( $post_type_args['publicly_queryable'] );
				$post_type_args['public'] = true;
			}

			if ( $genoptions['showexcerpt'] ) {
				$post_type_args['supports'][] = 'excerpt';
			}

			register_post_type( 'link_library_links', $post_type_args );

			register_taxonomy(
				'link_library_category',
				'link_library_links',
				array(
					'labels' => array(
						'name' => __( 'Link Library Categories', 'link-library' ),
						'add_new_item' => __( 'Add New Link Library Category', 'link-library' ),
						'new_item_name' => __( 'New Link Library Category', 'link-library' )
					),
					'show_ui' => ( $genoptions['cattaxonomy'] == 'link_library_category' ? true : false ),
					'show_tagcloud' => false,
					'hierarchical' => true,
					'rewrite' => $genoptions['publicly_queryable'],
					'show_in_rest' => true
				)
			);

			register_taxonomy(
				'link_library_tags',
				'link_library_links',
				array(
					'hierarchical' => false,
					'labels' => array( 'name' => __( 'Tags', 'link-library' ),
									'add_new_item' => __( 'Add New Link Library Tag', 'link-library' ),
									'new_item_name' => __( 'New Link Library Tag', 'link-library' ) ),
					'show_ui' => ( $genoptions['tagtaxonomy'] == 'link_library_tags' ? true : false ),
					'rewrite' => false,
					'show_in_rest' => true
				)
			);

			add_feed( 'linklibraryfeed', 'link_library_generate_rss_feed' );

			if ( function_exists( 'register_block_type' ) ) {
				$asset_file = include( plugin_dir_path( __FILE__ ) . 'build/index.asset.php');
		
				wp_register_script(
					'link-library-block',
					plugins_url( 'build/index.js', __FILE__ ),
					$asset_file['dependencies'],
					$asset_file['version']
				);
			
				register_block_type( 'link-library/link-block', array( 
					'editor_script' => 'link-library-block',
					'render_callback' => array( $this, 'link_library_func' ),
					'attributes'  => array(
						'settings'    => array(
							'type'  => 'string',
							'default'   => '1',
						),
						'linkorderoverride'    => array(
							'type'  => 'string',
							'default'   => '',
						),
						'linkdirectionoverride'    => array(
							'type'  => 'string',
							'default'   => '',
						),
						'categorylistoverride'    => array(
							'type'  => 'array',
							'default'   => array(),
							'items'   => array(
								'type' => 'string',
							),
						),
						'excludecategoryoverride'    => array(
							'type'  => 'array',
							'default'   => array(),
							'items'   => array(
								'type' => 'string',
							),
						),
						'taglistoverride'    => array(
							'type'  => 'array',
							'default'   => array(),
							'items'   => array(
								'type' => 'string',
							),
						),
						'maxlinksoverride'    => array(
							'type'  => 'string',
							'default'   => '',
						),
						'notesoverride'    => array(
							'type'  => 'boolean',
							'default'   => false,
						),
						'descoverride'    => array(
							'type'  => 'boolean',
							'default'   => false,
						),
						'rssoverride'    => array(
							'type'  => 'boolean',
							'default'   => false,
						),
						'categorylistoverrideCSV' => array(
							'type' => 'string',
							'default' => '',
						),
						'excludecategoryoverrideCSV' => array(
							'type' => 'string',
							'default' => '',
						),
						'taglistoverrideCSV' => array(
							'type' => 'string',
							'default' => '',
						),
					),
				) );

				register_block_type( 'link-library/cats-block', array(
					'editor_script' => 'link-library-block',
					'render_callback' => array( $this, 'link_library_cats_func' ),
					'attributes'  => array(
						'settings'    => array(
							'type'  => 'string',
							'default'   => '1',
						),
						'categorylistoverride'    => array(
							'type'  => 'array',
							'default'   => array(),
							'items'   => array(
								'type' => 'string',
							),
						),
						'excludecategoryoverride'    => array(
							'type'  => 'array',
							'default'   => array(),
							'items'   => array(
								'type' => 'string',
							),
						),
						'taglistoverride'    => array(
							'type'  => 'array',
							'default'   => array(),
							'items'   => array(
								'type' => 'string',
							),
						),
						'targetlibrary'    => array(
							'type'  => 'string',
							'default'   => '',
						),
						'categorylistoverrideCSV' => array(
							'type' => 'string',
							'default' => '',
						),
						'excludecategoryoverrideCSV' => array(
							'type' => 'string',
							'default' => '',
						),
						'taglistoverrideCSV' => array(
							'type' => 'string',
							'default' => '',
						),
					),
				) );
				
				register_block_type( 'link-library/addlink-block', array(
					'editor_script' => 'link-library-block',
					'render_callback' => array( $this, 'link_library_addlink_func' ),
					'attributes'  => array(
						'settings'    => array(
							'type'  => 'string',
							'default'   => '1',
						),
					),
				) );

				register_block_type( 'link-library/search-block', array(
					'editor_script' => 'link-library-block',
					'render_callback' => array( $this, 'link_library_search_func' ),
					'attributes'  => array(
						'settings'    => array(
							'type'  => 'string',
							'default'   => '1',
						),
					),
				) );

				register_block_type( 'link-library/count-block', array(
					'editor_script' => 'link-library-block',
					'render_callback' => array( $this, 'link_library_count_func' ),
					'attributes'  => array(
						'settings'    => array(
							'type'  => 'string',
							'default'   => '1',
						),
					),
				) );
			}	
		}

		function link_library_block_callback( $attributes ) {
			$settings = 1;

			if ( isset( $attributes['settingsid']) && !empty( $attributes['settingsid'] ) ) {
				$settings = $attributes['settingsid'];
			}
			
			$genoptions = get_option( 'LinkLibraryGeneral' );
			$genoptions = wp_parse_args( $genoptions, ll_reset_gen_settings( 'return' ) );

			$linkcount = 1;
			
			$settingsname = 'LinkLibraryPP' . $settings;
			$options = get_option( $settingsname );
			$options = wp_parse_args( $options, ll_reset_options( 1, 'list', 'return' ) );

			if ( isset( $attributes['categoryOverrideArray'] ) && !empty( $attributes['categoryOverrideArray'] ) ) {
				$options['categorylist_cpt'] = implode( ',', $attributes['categoryOverrideArray'] );
			}		

			require_once plugin_dir_path( __FILE__ ) . 'render-link-library-sc.php';
		
			return RenderLinkLibrary( $linkcount, $this, $genoptions, $options, $settings, false, 0, 0, true, false );	  
		}

		function link_library_cats_block_callback( $attributes ) {
			$settings = 1;

			if ( isset( $attributes['settingsid']) && !empty( $attributes['settingsid'] ) ) {
				$settings = $attributes['settingsid'];
			}
			
			$genoptions = get_option( 'LinkLibraryGeneral' );
			$genoptions = wp_parse_args( $genoptions, ll_reset_gen_settings( 'return' ) );

			$linkcount = 1;
			
			$settingsname = 'LinkLibraryPP' . $settings;
			$options = get_option( $settingsname );
			$options = wp_parse_args( $options, ll_reset_options( 1, 'list', 'return' ) );

			if ( isset( $attributes['categoryOverrideArray'] ) && !empty( $attributes['categoryOverrideArray'] ) ) {
				$options['categorylist_cpt'] = implode( ',', $attributes['categoryOverrideArray'] );
			}		
			$targetlibrary = $settings;

			require_once plugin_dir_path( __FILE__ ) . 'render-link-library-cats-sc.php';
		
			return RenderLinkLibraryCategories( $this, $genoptions, $options, $settings, $targetlibrary );	  
		}

		function ll_update_60() {

			$link_library_60_update = get_option( 'LinkLibrary60Update' );
			$genoptions = get_option( 'LinkLibraryGeneral' );

			if ( isset( $_GET['ll60reupdate'] ) ) {
				if ( !current_user_can( 'manage_options' ) ) {
					return;
				}

				check_admin_referer( 'll60reupdate' );

				global $wpdb;

				$wpdb->get_results ( 'DELETE a,b,c
										FROM wp_posts a
										LEFT JOIN wp_term_relationships b
											ON (a.ID = b.object_id)
										LEFT JOIN wp_postmeta c
											ON (a.ID = c.post_id)
										WHERE a.post_type = \'link_library_links\';' );

				$link_category_terms = get_terms( 'link_library_category', array( 'fields' => 'ids', 'hide_empty' => false ) );
				foreach ( $link_category_terms as $value ) {
					wp_delete_term( $value, 'link_library_category' );
				}

				require plugin_dir_path( __FILE__ ) . 'link-library-update-60.php';
				link_library_60_update( $this );
			} elseif ( isset( $_GET['continue60update'] ) ) {
				if ( !current_user_can( 'manage_options' ) ) {
					return;
				}

				require plugin_dir_path( __FILE__ ) . 'link-library-update-60.php';
				link_library_60_update( $this, true );
			} else {
				if ( ( false == $link_library_60_update && !empty( $genoptions ) ) ) {
					if ( !current_user_can( 'manage_options' ) ) {
						return;
					}
					
					require plugin_dir_path( __FILE__ ) . 'link-library-update-60.php';
					link_library_60_update( $this );
				}
			}
		}

		function permalink_structure( $post_link, $post, $leavename, $sample ) {

			$genoptions = get_option( 'LinkLibraryGeneral' );
			$genoptions = wp_parse_args( $genoptions, ll_reset_gen_settings( 'return' ) );

			if ( $post->post_type == 'link_library_links' ) {
				if ( !$genoptions['publicly_queryable'] ) {
					$link_url = get_post_meta( $post->ID, 'link_url', true );

					if ( !empty( $link_url ) ) {
						$post_link = $link_url;
					}
				} else {
					if ( !empty( $post_link ) && false !== strpos( $post_link, '%' . $genoptions['cattaxonomy'] . '%' ) ) {
						$link_cat_type_term = get_the_terms( $post->ID, $genoptions['cattaxonomy'] );
						if ( !empty( $link_cat_type_term ) ) {
							$post_link = str_replace( '%' . $genoptions['cattaxonomy'] . '%', array_pop( $link_cat_type_term )->slug, $post_link );
						}
					}
				}
			}

			return $post_link;
		}

		/************************** Link Library Installation Function **************************/
		function ll_install() {
			global $wpdb;

			if ( function_exists( 'is_multisite' ) && is_multisite() ) {
				if ( isset( $_GET['networkwide'] ) && ( $_GET['networkwide'] == 1 ) ) {
					$originalblog = $wpdb->blogid;

					$bloglist = $wpdb->get_col( 'SELECT blog_id FROM ' . $wpdb->blogs );
					foreach ( $bloglist as $blog ) {
						switch_to_blog( $blog );
						$this->create_table_and_settings();
					}
					switch_to_blog( $originalblog );
					return;
				}
			}
			$this->create_table_and_settings();
		}

		function new_network_site( $blog_id, $user_id, $domain, $path, $site_id, $meta ) {
			global $wpdb;

			if ( ! function_exists( 'is_plugin_active_for_network' ) )
				require_once( ABSPATH . '/wp-admin/includes/plugin.php' );

			if ( is_plugin_active_for_network( 'link-library/link-library.php' ) ) {
				$originalblog = $wpdb->blogid;
				switch_to_blog( $blog_id );
				$this->create_table_and_settings();
				switch_to_blog( $originalblog );
			}
		}

		function create_table_and_settings() {
			global $wpdb;

			$genoptions = get_option( 'LinkLibraryGeneral' );

			if ( !empty( $genoptions ) ) {
				if ( empty( $genoptions['schemaversion'] ) || floatval( $genoptions['schemaversion'] ) < 3.5 ) {
					$genoptions['schemaversion'] = '3.5';
					update_option( 'LinkLibraryGeneral', $genoptions );
				} elseif ( floatval( $genoptions['schemaversion'] ) < '4.6' ) {
					$genoptions['schemaversion'] = '4.6';
					update_option( 'LinkLibraryGeneral', $genoptions );
				} elseif ( floatval( $genoptions['schemaversion'] ) < '4.7' ) {
					$genoptions['schemaversion'] = '4.7';
					update_option( 'LinkLibraryGeneral', $genoptions );
				} elseif ( floatval( $genoptions['schemaversion'] ) < '4.9' ) {
					$genoptions['schemaversion'] = '4.9';
					update_option( 'LinkLibraryGeneral', $genoptions );
				}

				for ( $i = 1; $i <= $genoptions['numberstylesets']; $i++ ) {
					$settingsname = 'LinkLibraryPP' . $i;
					$options = get_option( $settingsname );
					$options = wp_parse_args( $options, ll_reset_options( 1, 'list', 'return' ) );

					if ( !empty( $options ) ) {
						if ( empty( $options['showname'] ) ) {
							$options['showname'] = true;
						}

						if ( isset( $options['show_image_and_name'] ) && $options['show_image_and_name'] == true ) {
							$options['showname'] = true;
							$options['show_images'] = true;
						}

						if ( empty( $options['sourcename'] ) ) {
							$options['sourcename'] = 'primary';
						}

						if ( empty( $options['sourceimage'] ) ) {
							$options['sourceimage'] = 'primary';
						}

						if ( empty( $options['dragndroporder'] ) ) {
							if ( $options['imagepos'] == 'beforename' ) {
								$options['dragndroporder'] = '1,2,3,4,5,6,7,8,9,10,11,12';
							} elseif ( $options['imagepos'] == 'aftername' ) {
								$options['dragndroporder'] = '2,1,3,4,5,6,7,8,9,10,11,12';
							} elseif ( $options['imagepos'] == 'afterrssicons' ) {
								$options['dragndroporder'] = '2,3,4,5,6,1,7,8,9,10,11,12';
							}
						} else if ( !empty( $options['dragndroporder'] ) ) {
							$elementarray = explode( ',', $options['dragndroporder'] );

							$allelements = array( '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12' );
							foreach ( $allelements as $element ) {
								if ( !in_array( $element, $elementarray ) ) {
									$elementarray[] = $element;
									$options['dragndroporder'] = implode( ',', $elementarray );
								}
							}
						}

						if ( $options['flatlist'] === true ) {
							$options['flatlist'] = 'unordered';
						} elseif ( $options['flatlist'] === false ) {
							$options['flatlist'] = 'table';
						}
					}

					update_option( $settingsname, $options );
				}
			} else {
				update_option( 'LinkLibrary60Update', true );
			}

			$genoptions['schemaversion'] = '5.0';
			update_option( 'LinkLibraryGeneral', $genoptions );
		}

		function remove_querystring_var( $url, $key ) {

			$keypos = strpos( $url, $key );
			if ( $keypos ) {
				$ampersandpos = strpos( $url, '&', $keypos );
				$newurl = substr( $url, 0, $keypos - 1 );

				if ( $ampersandpos ) {
					$newurl .= substr($url, $ampersandpos);
				}
			} else {
				$newurl = $url;
			}

			return $newurl;
		}

		/************************** Link Library Uninstall Function **************************/
		function ll_uninstall() {
			$genoptions = get_option( 'LinkLibraryGeneral' );

			if ( !empty( $genoptions ) ) {
				if ( isset( $genoptions['stylesheet'] ) && isset( $genoptions['fullstylesheet'] ) && !empty( $genoptions['stylesheet'] ) && empty( $genoptions['fullstylesheet'] ) ) {
					$stylesheetlocation = plugins_url( $genoptions['stylesheet'], __FILE__ );
					if ( file_exists( $stylesheetlocation ) )
						$genoptions['fullstylesheet'] = file_get_contents( $stylesheetlocation );

					update_option( 'LinkLibraryGeneral', $genoptions );
				}
			}
		}

		function ll_register_script() {
			wp_register_script( 'form-validator', plugins_url( '/form-validator/jquery.form-validator.min.js' , __FILE__ ), array( 'jquery' ), '1.0.0', true );
			wp_register_script( 'tiptip', plugins_url( '/tiptip/jquery.tipTip.minified.js' , __FILE__ ), array( 'jquery' ), '1.0.0', true );
		}

		function db_prefix() {
			global $wpdb;
			if ( method_exists( $wpdb, 'get_blog_prefix' ) ) {
				return $wpdb->get_blog_prefix();
			} else {
				return $wpdb->prefix;
			}
		}

		function ll_add_protocols( $protocols ) {
			$genoptions = get_option( 'LinkLibraryGeneral' );

			if ( isset( $genoptions['extraprotocols'] ) && !empty( $genoptions['extraprotocols'] ) ) {
				$extra_protocol_array = explode( ',', $genoptions['extraprotocols'] );

				if ( !empty( $extra_protocol_array ) ) {
					foreach( $extra_protocol_array as $extra_protocol ) {
						$protocols[] = $extra_protocol;
					}
				}
			}

			return $protocols;
		}

		/******************************************** Print style data to header *********************************************/

		function ll_rss_link() {
			global $llstylesheet, $rss_settings, $settingssetsids;

			if ( !empty( $rss_settings ) ) {
				$settingsname = 'LinkLibraryPP' . $rss_settings;
				$options = get_option( $settingsname );
				$options = wp_parse_args( $options, ll_reset_options( 1, 'list', 'return' ) );

				$feedtitle = ( empty( $options['rssfeedtitle'] ) ? __('Link Library Generated Feed', 'link-library') : $options['rssfeedtitle'] );

				$xpath = $this->relativePath( dirname( __FILE__ ), ABSPATH );
				echo '<link rel="alternate" type="application/rss+xml" title="' . esc_html( stripslashes( $feedtitle ) ) . '" href="' . home_url('/feed/linklibraryfeed?settingsset=' . $rss_settings/* . '&xpath=' . $xpath*/) . '" />';
				unset( $xpath );
			}

			if ( $llstylesheet ) {
				$genoptions = get_option( 'LinkLibraryGeneral' );
				if ( isset( $genoptions['fullstylesheet'] ) ) {
					echo "<style id='LinkLibraryStyle' type='text/css'>\n";
					echo stripslashes( sanitize_text_field( $genoptions['fullstylesheet'] ) );
					echo "</style>\n";
				}
			}

			if ( !empty( $settingssetsids ) ) {
				$processedsettings = array();
				foreach ( $settingssetsids as $setting ) {
					if ( !in_array( $setting, $processedsettings ) ) {
						$processedsettings[] = $setting;
						$settingsname = 'LinkLibraryPP' . $setting;
						$options = get_option( $settingsname );
						$options = wp_parse_args( $options, ll_reset_options( 1, 'list', 'return' ) );

						if ( !empty( $options['stylesheet'] ) ) {
							echo "<style id='LinkLibrarySettings" . $setting . "Style' type='text/css'>\n";
							echo stripslashes( sanitize_text_field( $options['stylesheet'] ) ) . "\n";
							echo "</style>\n";
						}
					}				
				}
			}
		}

		/****************************************** Add Link Category name to page title when option is present ********************************/
		function ll_title_creator( $title ) {
			global $wp_query;
			global $wpdb;
			global $llstylesheet;

			if ( $llstylesheet ) {
				$genoptions = get_option( 'LinkLibraryGeneral' );

				$categoryname = ( isset( $wp_query->query_vars['cat_name'] ) ? $wp_query->query_vars['cat_name'] : '' );
				$catid = ( isset( $_GET['cat_id'] ) ? intval( $_GET['cat_id'] ) : '' );

				$linkcatquery = 'SELECT t.name ';
				$linkcatquery .= 'FROM ' . $this->db_prefix() . 'terms t LEFT JOIN ' . $this->db_prefix(). 'term_taxonomy tt ON (t.term_id = tt.term_id) ';
				$linkcatquery .= 'LEFT JOIN ' . $this->db_prefix() . 'term_relationships tr ON (tt.term_taxonomy_id = tr.term_taxonomy_id) ';
				$linkcatquery .= 'WHERE tt.taxonomy = "link_category" AND ';

				if ( !empty( $categoryname ) ) {
					$linkcatquery .= 't.slug = "' . $categoryname . '"';
					$nicecatname = $wpdb->get_var( $linkcatquery );
					return $title . $genoptions['pagetitleprefix'] . $nicecatname . $genoptions['pagetitlesuffix'];
				} elseif ( !empty( $catid ) ) {
					$linkcatquery .= 't.term_id = "' . $catid . '"';
					$nicecatname = $wpdb->get_var( $linkcatquery );
					return $title . $genoptions['pagetitleprefix'] . $nicecatname . $genoptions['pagetitlesuffix'];
				}
			}

			return $title;
		}

		function ll_get_permalink( $url, $post_id, $sample, $type ) {
			if ( !is_admin() && is_search() && 'link_library_links' == get_post_type() ) {
				$genoptions = get_option( 'LinkLibraryGeneral' );
				$genoptions = wp_parse_args( $genoptions, ll_reset_gen_settings( 'return' ) );

				if ( $genoptions['globalsearchresultslinkurl'] ) {
					$link_url = get_post_meta( get_the_ID(), 'link_url', true );

					if ( !empty( $link_url ) ) {
						return $link_url;
					}	
				}
			}

			return $url;		
		}

		function ll_get_title( $title, $id = null ) {
			if ( !is_admin() && is_search() && 'link_library_links' == get_post_type() ) {
				$genoptions = get_option( 'LinkLibraryGeneral' );
				$genoptions = wp_parse_args( $genoptions, ll_reset_gen_settings( 'return' ) );

				$post = get_post( $id );
				if ( $post instanceof WP_Post && !empty( $genoptions['globalsearchresultstitleprefix'] ) ) {
					return $genoptions['globalsearchresultstitleprefix'] . $title;
				}			
			}

			return $title;
		}

		/************************************* Function to add to rewrite rules for permalink support **********************************/
		function ll_insertMyRewriteRules( $rules ) {
			$newrules = array();

			$genoptions = get_option( 'LinkLibraryGeneral' );
			$genoptions = wp_parse_args( $genoptions, ll_reset_gen_settings( 'return' ) );

			if ( !empty( $genoptions ) ) {
				for ( $i = 1; $i <= $genoptions['numberstylesets']; $i++ ) {
					$settingsname = 'LinkLibraryPP' . $i;
					$options = get_option( $settingsname );
					$options = wp_parse_args( $options, ll_reset_options( 1, 'list', 'return' ) );

					if ( $options['enablerewrite'] && !empty( $options['rewritepage'] ) ) {
						if ( is_multisite() ) {
							$newrules['(' . $options['rewritepage'] . ')/(.+?)$'] = 'index.php?pagename=$matches[2]&cat_name=$matches[3]';
						} else {
							$newrules['(' . $options['rewritepage'] . ')/(.+?)$'] = 'index.php?pagename=$matches[1]&cat_name=$matches[2]';
						}
					}

					if ( $options['publishrssfeed'] ) {
						$xpath = $this->relativePath( dirname( __FILE__ ), ABSPATH );

						if ( !empty( $options['rssfeedaddress'] ) ) {
							$newrules['(' . $options['rssfeedaddress'] . ')/(.+?)$'] = home_url() . '/feed/linklibraryfeed?settingsset=$matches[1]';
						}
						unset( $xpath );
					}
				}
			}

			return $newrules + $rules;
		}

		// Adding the id var so that WP recognizes it
		function ll_insertMyRewriteQueryVars( $vars ) {
			array_push( $vars, 'cat_name' );
			return $vars;
		}

		function relativePath( $from, $to, $ps = DIRECTORY_SEPARATOR ) {
			$arFrom = explode( $ps, rtrim( $from, $ps ) );
			$arTo = explode( $ps, rtrim( $to, $ps ) );
			while( count( $arFrom ) && count( $arTo ) && ( $arFrom[0] == $arTo[0] ) ) {
				array_shift( $arFrom );
				array_shift( $arTo );
			}
			$return = str_pad( '', count($arFrom) * 3, '..'.$ps ) . implode( $ps, $arTo );

			// Don't disclose anything about the path is it's not needed, i.e. is the standard
			if( $return === '../../../' ) {
				$return = '';
			}

			return $return;
		}

		function CheckReciprocalLink( $RecipCheckAddress = '', $external_link = '', $request_type = 'reciprocal' ) {
			$response = wp_remote_get( $external_link, array( 'user-agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36', 'timeout' => 10 ) );

			if( is_wp_error( $response ) ) {
				$data = file_get_contents( $external_link );
				if ( false !== $data ) {
					return 'exists_found';
				} else {
					$response_code = $response->get_error_code();
					if ( 'http_request_failed' == $response_code ) {
						return 'error_403';
					}
				}			
			} elseif ( $response['response']['code'] == '200' ) {

				$original_protocol = '';
				$actual_protocol = '';

				if ( false !== strpos( $external_link, 'http://' ) ) {
					$original_protocol = 'http://';
				} else if ( false !== strpos( $external_link, 'https://' ) ) {
					$original_protocol = 'https://';
				}

				if ( false !== strpos( $response['http_response']->get_response_object()->url, 'http://' ) ) {
					$actual_protocol = 'http://';
				} else if ( false !== strpos( $response['http_response']->get_response_object()->url, 'https://' ) ) {
					$actual_protocol = 'https://';
				}

				$link_url_without_protocol = str_replace( 'http://', '', $external_link );
				$link_url_without_protocol = str_replace( 'https://', '', $link_url_without_protocol );
				$link_url_without_protocol = rtrim( $link_url_without_protocol, '/' );

				$response_url_without_protocol = str_replace( 'http://', '', $response['http_response']->get_response_object()->url );
				$response_url_without_protocol = str_replace( 'https://', '', $response_url_without_protocol );
				$response_url_without_protocol = rtrim( $response_url_without_protocol, '/' );

				$parse_original_url = parse_url( $external_link );
				$parse_actual_url = parse_url( $response['http_response']->get_response_object()->url );

				if ( ( 'broken' == $request_type || 'rss' == $request_type || 'secondary' == $request_type || 'image' == $request_type ) && $parse_original_url['host'] != $parse_actual_url['host'] ) {
					$original_host_segments = explode( '.', $parse_original_url['host'] );
					$actual_host_segments = explode( '.', $parse_actual_url['host'] );

					if ( sizeof( $actual_host_segments ) > sizeof( $original_host_segments ) ) {
						if ( $original_host_segments[ sizeof( $original_host_segments ) - 1 ] == $actual_host_segments[ sizeof( $actual_host_segments ) - 1] && $original_host_segments[ sizeof( $original_host_segments ) - 2 ] == $actual_host_segments[ sizeof( $actual_host_segments ) - 2] ) {
							return 'exists_subdomain_redirect';
						}
					}				
				}

				if ( ( 'broken' == $request_type || 'rss' == $request_type || 'secondary' == $request_type || 'image' == $request_type ) && $parse_original_url['host'] == $parse_actual_url['host'] && $link_url_without_protocol != $response_url_without_protocol ) {
					$basename = basename( $parse_actual_url['path'] );
					if ( false !== strpos( $basename, '.' ) ) {
						return 'exists_redirected_fileurl';
					} else {
						return 'exists_redirected_subfolder';
					}				
				}
				
				if ( ( 'broken' == $request_type || 'rss' == $request_type || 'secondary' == $request_type || 'image' == $request_type ) && $link_url_without_protocol != $response_url_without_protocol ) {
					return 'exists_redirected';
				} elseif ( ( 'broken' == $request_type || 'rss' == $request_type || 'secondary' == $request_type || 'image' == $request_type ) && !empty( $original_protocol ) && !empty( $actual_protocol ) && $original_protocol != $actual_protocol ) {
					return 'exists_protocol_redirect';
				} elseif ( ( 'broken' == $request_type || 'rss' == $request_type || 'secondary' == $request_type || 'image' == $request_type ) && empty( $RecipCheckAddress ) ) {
					return 'exists_notfound';
				} else {
					return 'exists_found';
				} 			
				
				if ( 'reciprocal' == $request_type && strpos( $response['body'], $RecipCheckAddress ) === false ) {
					return 'exists_notfound';
				} elseif ( 'reciprocal' == $request_type && strpos( $response['body'], $RecipCheckAddress ) !== false ) {
					return 'exists_found';
				}
			}

			return 'unreachable';
		}

		/* Output for users trying to directly call Link Library function, as was possible in pre-1.0 versions */

		function LinkLibraryCategories() {
			return __( 'Link Library no longer supports calling this function with individual arguments. Please use the admin panel to configure Link Library and the do_shortcode function to use Link Library output in your code.', 'link-library' );
		}

		function LinkLibrary() {
			return __( 'Link Library no longer supports calling this function with individual arguments. Please use the admin panel to configure Link Library and the do_shortcode function to use Link Library output in your code.', 'link-library' );
		}

		/********************************************** Function to Process [link-library-cats] shortcode *********************************************/

		function link_library_cats_func( $atts ) {
			$categorylistoverride = '';
			$excludecategoryoverride = '';
			$settings = '';
			$targetlibrary = '';

			if ( isset( $atts['categorylistoverride'] ) && !empty( $atts['categorylistoverride'] ) && is_array( $atts['categorylistoverride'] ) ) {
				$atts['categorylistoverride'] = implode( ',', $atts['categorylistoverride'] );
			}

			if ( isset( $atts['categorylistoverrideCSV'] ) && !empty( $atts['categorylistoverrideCSV'] ) ) {
				$atts['categorylistoverride'] = $atts['categorylistoverrideCSV'];
			}

			if ( isset( $atts['excludecategoryoverride'] ) && !empty( $atts['excludecategoryoverride'] ) && is_array( $atts['excludecategoryoverride'] ) ) {
				$atts['excludecategoryoverride'] = implode( ',', $atts['excludecategoryoverride'] );
			}

			if ( isset( $atts['excludecategoryoverrideCSV'] ) && !empty( $atts['excludecategoryoverrideCSV'] ) ) {
				$atts['excludecategoryoverride'] = $atts['excludecategoryoverrideCSV'];
			}

			if ( isset( $atts['taglistoverride'] ) && !empty( $atts['taglistoverride'] ) && is_array( $atts['taglistoverride'] ) ) {
				$atts['taglistoverride'] = implode( ',', $atts['taglistoverride'] );
			}

			if ( isset( $atts['taglistoverrideCSV'] ) && !empty( $atts['taglistoverrideCSV'] ) ) {
				$atts['taglistoverrideCSV'] = $atts['taglistoverrideCSV'];
			}

			extract( shortcode_atts( array (
				'categorylistoverride' => '',
				'excludecategoryoverride' => '',
				'settings' => '',
				'targetlibrary' => '',
				'taglistoverride' => '',
				'parent_cat_id' => 0
			), $atts ) );

			$genoptions = get_option( 'LinkLibraryGeneral' );
			$genoptions = wp_parse_args( $genoptions, ll_reset_gen_settings( 'return' ) );

			if ( empty( $settings ) ) {
				$settings = 1;
			}

			if ( $settings > $genoptions['numberstylesets'] ) {
				$settings = 1;
			}

			$settingsname = 'LinkLibraryPP' . intval( $settings );
			$options = get_option( $settingsname );
			$options = wp_parse_args( $options, ll_reset_options( 1, 'list', 'return' ) );

			if ( empty( $options ) ) {
				$settingsname = 'LinkLibraryPP1';
				$options = get_option( $settingsname );
				$options = wp_parse_args( $options, ll_reset_options( 1, 'list', 'return' ) );
			}

			if ( !empty( $categorylistoverride ) ) {
				$options['categorylist_cpt'] = $categorylistoverride;

				$update_list = false;
				$category_list_array = explode( ',', $categorylistoverride );
				foreach( $category_list_array as $index => $category_text ) {
					if ( !is_numeric( $category_text ) ) {
						$update_list = true;
						$matched_term = get_term_by( 'slug', $category_text, $genoptions['cattaxonomy'] );

						if ( $matched_term ) {
							$category_list_array[$index] = $matched_term->term_id;
						} else {
							unset( $category_list_array[$index] );
						}
					}
				}
				if ( $update_list ) {
					$options['categorylist_cpt'] = implode( ',', $category_list_array );
				}
			}

			if ( !empty( $excludecategoryoverride ) ) {
				$options['excludecategorylist_cpt'] = $excludecategoryoverride;

				$update_list = false;
				$exclude_category_list_array = explode( ',', $excludecategoryoverride );
				foreach( $exclude_category_list_array as $index => $category_text ) {
					if ( !is_numeric( $category_text ) ) {
						$update_list = true;
						$matched_term = get_term_by( 'slug', $category_text, $genoptions['cattaxonomy'] );

						if ( $matched_term ) {
							$exclude_category_list_array[$index] = $matched_term->term_id;
						} else {
							unset( $exclude_category_list_array[$index] );
						}
					}
				}
				if ( $update_list ) {
					$options['categorylist_cpt'] = implode( ',', $exclude_category_list_array );
				}
			}

			if ( !empty( $taglistoverride ) ) {
				$options['taglist_cpt'] = $taglistoverride;

				$update_list = false;
				$tag_list_array = explode( ',', $taglistoverride );
				foreach( $tag_list_array as $index => $tag_text ) {
					if ( !is_numeric( $tag_text ) ) {
						$update_list = true;
						$matched_term = get_term_by( 'slug', $tag_text, $genoptions['tagtaxonomy'] );

						if ( $matched_term ) {
							$tag_list_array[$index] = $matched_term->term_id;
						} else {
							unset( $tag_list_array[$index] );
						}
					}
				}
				if ( $update_list ) {
					$options['taglist_cpt'] = implode( ',', $tag_list_array );
				}
			}

			if ( !empty( $excludetagoverride ) ) {
				$options['excludetaglist_cpt'] = $excludetagoverride;

				$update_list = false;
				$exclude_tag_list_array = explode( ',', $excludetagoverride );
				foreach( $exclude_tag_list_array as $index => $tag_text ) {
					if ( !is_numeric( $tag_text ) ) {
						$update_list = true;
						$matched_term = get_term_by( 'slug', $tag_text, $genoptions['tagtaxonomy'] );

						if ( $matched_term ) {
							$exclude_tag_list_array[$index] = $matched_term->term_id;
						} else {
							unset( $exclude_tag_list_array[$index] );
						}
					}
				}
				if ( $update_list ) {
					$options['excludetaglist_cpt'] = implode( ',', $exclude_tag_list_array );
				}
			}

			if ( $genoptions['debugmode'] ) {
				$mainoutputstarttime = microtime( true );
				$timeoutputstart = "\n<!-- Start Link Library Cats Time: " . $mainoutputstarttime . "-->\n";
			}

			require_once plugin_dir_path( __FILE__ ) . 'render-link-library-cats-sc.php';

			if ( $genoptions['debugmode'] ) {
				$timeoutput = "\n<!-- [link-library-cats] shortcode execution time: " . ( microtime( true ) - $mainoutputstarttime ) . "-->\n";
			}


			$parent_id_array = array();
			return ( true == $genoptions['debugmode'] ? $timeoutputstart : '' ) . RenderLinkLibraryCategories( $this, $genoptions, $options, intval( $settings ), $targetlibrary, $parent_cat_id, 0, $parent_id_array )  . ( true == $genoptions['debugmode'] ? $timeoutput : '' );
		}

		/********************************************** Function to Process [link-library-search] shortcode *********************************************/

		function link_library_search_func($atts) {
			$settings = '';
			$genoptions = get_option( 'LinkLibraryGeneral' );
			$genoptions = wp_parse_args( $genoptions, ll_reset_gen_settings( 'return' ) );

			extract(shortcode_atts(array(
				'settings' => ''
			), $atts));

			if ( empty( $settings ) ) {
				$settings = 1;
			}

			if ( $settings > $genoptions['numberstylesets'] ) {
				$settings = 1;
			}

			$settingsname = 'LinkLibraryPP' . intval( $settings );
			$options = get_option( $settingsname );
			$options = wp_parse_args( $options, ll_reset_options( 1, 'list', 'return' ) );

			if ( empty( $options ) ) {
				$settingsname = 'LinkLibraryPP1';
				$options = get_option( $settingsname );
				$options = wp_parse_args( $options, ll_reset_options( 1, 'list', 'return' ) );
			}

			require_once plugin_dir_path( __FILE__ ) . 'render-link-library-search-sc.php';
			return RenderLinkLibrarySearchForm( $options );
		}

		/********************************************** Function to Process [link-library-add-link] shortcode *********************************************/

		function link_library_addlink_func( $atts, $content, $code ) {
			$settings = '';
			$categorylistoverride = '';
			$excludecategoryoverride = '';
			$addlinkdefaultcatoverride = '';

			extract(shortcode_atts(array(
				'settings' => '',
				'categorylistoverride' => '',
				'excludecategoryoverride' => '',
				'addlinkdefaultcatoverride' => ''
			), $atts));

			if ( empty( $code ) || is_object( $code ) ) {
				$code = 'link-library-addlink';
			}

			$genoptions = get_option( 'LinkLibraryGeneral' );
			$genoptions = wp_parse_args( $genoptions, ll_reset_gen_settings( 'return' ) );

			if ( empty( $settings ) ) {
				$settings = 1;
			} else if ( isset( $_POST['settings'] ) ) {
				$settings = intval( $_POST['settings'] );
			}

			if ( $settings > $genoptions['numberstylesets'] ) {
				$settings = 1;
			}

			$settingsname = 'LinkLibraryPP' . intval( $settings );
			$options = get_option( $settingsname );
			$options = wp_parse_args( $options, ll_reset_options( 1, 'list', 'return' ) );

			if ( empty( $options ) ) {
				$settingsname = 'LinkLibraryPP1';
				$options = get_option( $settingsname );
				$options = wp_parse_args( $options, ll_reset_options( 1, 'list', 'return' ) );
			}

			if ( !empty( $categorylistoverride ) ) {
				$options['categorylist_cpt'] = $categorylistoverride;
			} elseif ( !empty( $options['addlinkcatlistoverride'] ) ) {
				$options['categorylist_cpt'] = $options['addlinkcatlistoverride'];
			}

			if ( !empty( $excludecategoryoverride ) ) {
				$options['excludecategorylist_cpt'] = $excludecategoryoverride;
			}

			if ( !empty( $addlinkdefaultcatoverride ) ) {
				$options['addlinkdefaultcat'] = $addlinkdefaultcatoverride;
			}

			require_once plugin_dir_path( __FILE__ ) . 'render-link-library-addlink-sc.php';
			if ( 'inline' == $options['addlinkformdisplaymode'] ) {
				return RenderLinkLibraryAddLinkForm( $this, $genoptions, $options, intval( $settings ), $code );
			} elseif ( 'popup' == $options['addlinkformdisplaymode'] ) {
				return RenderLinkLibraryAddLinkButton( $this, $genoptions, $options, intval( $settings ), $code );
			}
			
		}

		/********************************************** Function to Process [link-library-count] shortcode ***************************************/

		function link_library_count_func( $atts ) {
			extract( shortcode_atts( array(
				'categorylistoverride' => '',
				'excludecategoryoverride' => '',
				'settings' => ''
			), $atts ) );

			$genoptions = get_option( 'LinkLibraryGeneral' );
			$genoptions = wp_parse_args( $genoptions, ll_reset_gen_settings( 'return' ) );

			if ( empty( $settings ) ) {
				$settings = 1;
			} else if ( isset( $_POST['settings'] ) ) {
				$settings = intval( $_POST['settings'] );
			}

			if ( $settings > $genoptions['numberstylesets'] ) {
				$settings = 1;
			}

			$settingsname = 'LinkLibraryPP' . intval( $settings );
			$options = get_option( $settingsname );
			$options = wp_parse_args( $options, ll_reset_options( 1, 'list', 'return' ) );

			if ( empty( $options ) ) {
				$settingsname = 'LinkLibraryPP1';
				$options = get_option( $settingsname );
				$options = wp_parse_args( $options, ll_reset_options( 1, 'list', 'return' ) );
			}

			$linkeditoruser = current_user_can( 'manage_options' );

			if ( !empty( $categorylistoverride ) ) {
				$options['categorylist_cpt'] = $categorylistoverride;
			}

			if ( !empty( $excludecategoryoverride ) ) {
				$options['excludecategorylist_cpt'] = $excludecategoryoverride;
			}

			$link_query_args = array( 'post_type' => 'link_library_links', 'posts_per_page' => -1 );
			$link_query_args['post_status'] = array( 'publish' );

			if ( !empty( $options['categorylist_cpt'] ) ) {
				$catlistarray = explode( ',', $options['categorylist_cpt'] );
				$link_query_args['tax_query'] = array( array( 'taxonomy' => $genoptions['cattaxonomy'],
															'field' => 'term_id',
															'terms' => $catlistarray,
															'operator' => 'IN' ) );
			}

			if ( !empty( $options['excludecategorylist_cpt'] ) ) {
				$catlistexcludearray = explode( ',', $options['excludecategorylist_cpt'] );
				$link_query_args['tax_query'] = array( array( 'taxonomy' => $genoptions['cattaxonomy'],
															'field' => 'term_id',
															'terms' => $catlistexcludearray,
															'operator' => 'NOT IN' ) );
			}

			if ( $options['showuserlinks'] ) {
				$link_query_args['post_status'][] = 'pending';
			}

			if ( $options['showinvisible'] || ( $options['showinvisibleadmin'] && $linkeditoruser ) ) {
				$link_query_args['post_status'][] = 'draft';
			}

			if ( $options['showscheduledlinks'] ) {
				$link_query_args['post_status'][] = 'future';
			}

			$the_link_query = new WP_Query( $link_query_args );

			wp_reset_postdata();

			return $the_link_query->found_posts;
		}

		/********************************************** Function to Process [link-library-filters] shortcode ***************************************/

		function link_library_filters( $atts ) {
			extract( shortcode_atts( array(
				'includetagsids' => '',
				'excludetagsids' => '',
				'showtagfilters' => true,
				'taglabel' => __( 'Tag', 'link-library' ),
				'showpricefilters' => true,
				'pricelabel' => __( 'Price', 'link-library' ),
				'alphabeticlabel' => __( 'Link Name', 'link-library' ),
				'showalphabeticfilters' => true,
				'showapplybutton' => false,
				'settings' => ''
			), $atts ) );

			$genoptions = get_option( 'LinkLibraryGeneral' );
			$genoptions = wp_parse_args( $genoptions, ll_reset_gen_settings( 'return' ) );

			if ( empty( $settings ) ) {
				$settings = 1;
			} else if ( isset( $_POST['settings'] ) ) {
				$settings = intval( $_POST['settings'] );
			}

			if ( $settings > $genoptions['numberstylesets'] ) {
				$settings = 1;
			}

			$settingsname = 'LinkLibraryPP' . intval( $settings );
			$options = get_option( $settingsname );
			$options = wp_parse_args( $options, ll_reset_options( 1, 'list', 'return' ) );

			if ( empty( $options ) ) {
				$settingsname = 'LinkLibraryPP1';
				$options = get_option( $settingsname );
				$options = wp_parse_args( $options, ll_reset_options( 1, 'list', 'return' ) );
			}

			require_once plugin_dir_path( __FILE__ ) . 'render-link-library-tag-filter-sc.php';
			return RenderLinkLibraryFilterBox( $this, $genoptions, $options, intval( $settings ), $includetagsids, $excludetagsids, $showtagfilters, $taglabel, $showpricefilters, $pricelabel, $showalphabeticfilters, $alphabeticlabel, $showapplybutton );
		}

		/********************************************** Function to Process [link-library] shortcode *********************************************/

		function link_library_func( $atts = '' ) {
			if ( isset( $_POST['ajaxupdate'] ) ) {
				check_ajax_referer( 'link_library_ajax_refresh' );
			}

			$settings = '';
			$notesoverride = '';
			$descoverride = '';
			$rssoverride = '';
			$categorylistoverride = '';
			$excludecategoryoverride = '';
			$tableoverride = '';
			$singlelinkid = '';
			$showonecatonlyoverride = false;
			$taglistoverride = '';
			$maxlinksoverride = '';
			$linkorderoverride = '';
			$linkdirectionoverride = '';
			$addlinkdefaultcatoverride = '';
			$urltextfilteroverride = '';

			if ( isset( $atts['categorylistoverride'] ) && !empty( $atts['categorylistoverride'] ) && is_array( $atts['categorylistoverride'] ) ) {
				$atts['categorylistoverride'] = implode( ',', $atts['categorylistoverride'] );
			}

			if ( isset( $atts['categorylistoverrideCSV'] ) && !empty( $atts['categorylistoverrideCSV'] ) ) {
				$atts['categorylistoverride'] = $atts['categorylistoverrideCSV'];
			}

			if ( isset( $atts['excludecategoryoverride'] ) && !empty( $atts['excludecategoryoverride'] ) && is_array( $atts['excludecategoryoverride'] ) ) {
				$atts['excludecategoryoverride'] = implode( ',', $atts['excludecategoryoverride'] );
			}

			if ( isset( $atts['excludecategoryoverrideCSV'] ) && !empty( $atts['excludecategoryoverrideCSV'] ) ) {
				$atts['excludecategoryoverride'] = $atts['excludecategoryoverrideCSV'];
			}

			if ( isset( $atts['taglistoverride'] ) && !empty( $atts['taglistoverride'] ) && is_array( $atts['taglistoverride'] ) ) {
				$atts['taglistoverride'] = implode( ',', $atts['taglistoverride'] );
			}
			
			if ( isset( $atts['taglistoverrideCSV'] ) && !empty( $atts['taglistoverrideCSV'] ) ) {
				$atts['taglistoverride'] = $atts['taglistoverrideCSV'];
			}	

			extract( shortcode_atts( array(
				'categorylistoverride' => '',
				'excludecategoryoverride' => '',
				'notesoverride' => '',
				'descoverride' => '',
				'rssoverride' => '',
				'tableoverride' => '',
				'settings' => '',
				'singlelinkid' => '',
				'showonecatonlyoverride' => '',
				'taglistoverride' => '',
				'excludetagoverride' => '',
				'maxlinksoverride' => '',
				'linkorderoverride' => '',
				'linkdirectionoverride' => '',
				'addlinkdefaultcatoverride' => '',
				'urltextfilteroverride' => '',
			), $atts ) );

			$genoptions = get_option( 'LinkLibraryGeneral' );
			$genoptions = wp_parse_args( $genoptions, ll_reset_gen_settings( 'return' ) );

			if ( floatval( $genoptions['schemaversion'] ) < '5.0' ) {
				$this->ll_install();
			}

			if ( empty( $settings ) && !isset( $_POST['settings'] ) ) {
				$settings = 1;
			} else if ( isset( $_POST['settings'] ) ) {
				$settings = intval( $_POST['settings'] );
			}

			if ( $settings > $genoptions['numberstylesets'] ) {
				$settings = 1;
			}

			$settingsname = 'LinkLibraryPP' . intval( $settings );
			$options = get_option( $settingsname );
			$options = wp_parse_args( $options, ll_reset_options( 1, 'list', 'return' ) );

			if ( empty( $options ) ) {
				$settingsname = 'LinkLibraryPP1';
				$options = get_option( $settingsname );
				$options = wp_parse_args( $options, ll_reset_options( 1, 'list', 'return' ) );
			}

			$options['AJAXcatid'] = '';
			$options['AJAXpageid'] = '';

			if ( !empty( $notesoverride ) ) {
				$options['shownotes'] = $notesoverride;
			}

			if ( !empty( $descoverride ) ) {
				$options['showdescription'] = $descoverride;
			}

			if ( !empty( $rssoverride ) ) {
				$options['show_rss'] = $rssoverride;
			}

			if ( !empty( $maxlinksoverride ) ) {
				$options['maxlinks'] = intval( $maxlinksoverride );
			}

			if ( !empty( $urltextfilteroverride ) ) {
				$options['urltextfilter'] = $urltextfilteroverride;
			}

			if ( !empty( $linkorderoverride ) ) {
				$validlinkorder = array( 'name', 'id', 'random', 'date', 'hits', 'scpo', 'pubdate', 'uservotes' );
				if ( in_array( $linkorderoverride, $validlinkorder ) ) {
					$options['linkorder'] = $linkorderoverride;
				}
			}

			if ( !empty( $linkdirectionoverride ) ) {
				$validlinkdirection = array( 'ASC', 'DESC' );
				if ( in_array( $linkdirectionoverride, $validlinkdirection ) ) {
					$options['linkdirection'] = $linkdirectionoverride;
				}
			}

			if ( !empty( $categorylistoverride ) ) {
				$options['categorylist_cpt'] = $categorylistoverride;

				$update_list = false;
				$category_list_array = explode( ',', $categorylistoverride );
				foreach( $category_list_array as $index => $category_text ) {
					if ( !is_numeric( $category_text ) ) {
						$update_list = true;
						$matched_term = get_term_by( 'slug', $category_text, $genoptions['cattaxonomy'] );

						if ( $matched_term ) {
							$category_list_array[$index] = $matched_term->term_id;
						} else {
							unset( $category_list_array[$index] );
						}
					}
				}
				if ( $update_list ) {
					$options['categorylist_cpt'] = implode( ',', $category_list_array );
				}
			}

			if ( !empty( $excludecategoryoverride ) ) {
				$options['excludecategorylist_cpt'] = $excludecategoryoverride;

				$update_list = false;
				$exclude_category_list_array = explode( ',', $excludecategoryoverride );
				foreach( $exclude_category_list_array as $index => $category_text ) {
					if ( !is_numeric( $category_text ) ) {
						$update_list = true;
						$matched_term = get_term_by( 'slug', $category_text, $genoptions['cattaxonomy'] );

						if ( $matched_term ) {
							$exclude_category_list_array[$index] = $matched_term->term_id;
						} else {
							unset( $exclude_category_list_array[$index] );
						}
					}
				}
				if ( $update_list ) {
					$options['excludecategorylist_cpt'] = implode( ',', $exclude_category_list_array );
				}
			}

			if ( !empty( $taglistoverride ) ) {
				$options['taglist_cpt'] = $taglistoverride;

				$update_list = false;
				$tag_list_array = explode( ',', $taglistoverride );
				foreach( $tag_list_array as $index => $tag_text ) {
					if ( !is_numeric( $tag_text ) ) {
						$update_list = true;
						$matched_term = get_term_by( 'slug', $tag_text, $genoptions['tagtaxonomy'] );

						if ( $matched_term ) {
							$tag_list_array[$index] = $matched_term->term_id;
						} else {
							unset( $tag_list_array[$index] );
						}
					}
				}
				if ( $update_list ) {
					$options['taglist_cpt'] = implode( ',', $tag_list_array );
				}
			}

			if ( !empty( $excludecategoryoverride ) ) {
				$options['excludetaglist_cpt'] = $excludetagoverride;

				$update_list = false;
				$exclude_tag_list_array = explode( ',', $excludetagoverride );
				foreach( $exclude_tag_list_array as $index => $tag_text ) {
					if ( !is_numeric( $tag_text ) ) {
						$update_list = true;
						$matched_term = get_term_by( 'slug', $tag_text, $genoptions['tagtaxonomy'] );

						if ( $matched_term ) {
							$exclude_tag_list_array[$index] = $matched_term->term_id;
						} else {
							unset( $exclude_tag_list_array[$index] );
						}
					}
				}
				if ( $update_list ) {
					$options['excludetaglist_cpt'] = implode( ',', $exclude_category_list_array );
				}
			}

			if ( !empty( $singlelinkid ) ) {
				$options['singlelinkid'] = $singlelinkid;
			}

			if ( $showonecatonlyoverride == 'false' || $showonecatonlyoverride == 'true' ) {
				if ( $showonecatonlyoverride == 'false' ) {
					$options['showonecatonly'] = false;
				} elseif ( $showonecatonlyoverride == 'true' ) {
					$options['showonecatonly'] = true;
				}
			}

			if ( $options['showonecatonly'] ) {
				if ( !empty( $categorylistoverride ) && !empty( $options['defaultsinglecat_cpt'] ) ) {
					if ( !str_contains( $categorylistoverride, ',' ) ) {
						$options['defaultsinglecat_cpt'] = $categorylistoverride;
					}
				}
			}

			if ( !empty( $tableoverride ) ) {
				$options['displayastable'] = $tableoverride;
			}

			if ( isset( $_POST['ajaxupdate'] ) ) {
				if ( isset( $_POST['id'] ) ) {
					$catID = intval( $_POST['id'] );
					$options['AJAXcatid'] = $catID;
				}

				if ( isset( $_POST['linkresultpage'] ) ) {
					$pageID = intval( $_POST['linkresultpage'] );
					$options['AJAXpageid'] = $pageID;
				}
			}

			$linklibraryoutput = '';

			if ( $genoptions['debugmode'] ) {
				$linklibraryoutput .= "\n<!-- Library Settings Info:" . print_r( $options, true ) . "-->\n";
				$mainoutputstarttime = microtime( true );
				$linklibraryoutput .= "\n<!-- Start Time: " . $mainoutputstarttime . "-->\n";
			}

			require_once plugin_dir_path( __FILE__ ) . 'render-link-library-sc.php';
			$linkcount = 1;
			$linklibraryoutput .= RenderLinkLibrary( $linkcount, $this, $genoptions, $options, intval( $settings ), false, 0, 0, true, false );

			if ( isset( $_POST['ajaxupdate'] ) ) {
				echo $linklibraryoutput;

				if ( $genoptions['debugmode'] ) {
					echo "\n<!-- Execution Time: " . ( microtime( true ) - $mainoutputstarttime ) . "-->\n";
				}
				exit;
			} else {
				if ( $genoptions['debugmode'] ) {
					$timeoutput = "\n<!-- [link-library] shortcode execution time: " . ( microtime( true ) - $mainoutputstarttime ) . "-->\n";
				}
				return $linklibraryoutput . ( true == $genoptions['debugmode'] ? $timeoutput : '' );
			}
		}

		/********************************************** Function to Process [link-library] shortcode *********************************************/

		function rss_library_func( $atts = '' ) {
			$settings = '';
			$categorylistoverride = '';
			$excludecategoryoverride = '';
			$taglistoverride = '';

			if ( isset( $atts['categorylistoverride'] ) && !empty( $atts['categorylistoverride'] ) && is_array( $atts['categorylistoverride'] ) ) {
				$atts['categorylistoverride'] = implode( ',', $atts['categorylistoverride'] );
			}

			if ( isset( $atts['categorylistoverrideCSV'] ) && !empty( $atts['categorylistoverrideCSV'] ) ) {
				$atts['categorylistoverride'] = $atts['categorylistoverrideCSV'];
			}

			if ( isset( $atts['excludecategoryoverride'] ) && !empty( $atts['excludecategoryoverride'] ) && is_array( $atts['excludecategoryoverride'] ) ) {
				$atts['excludecategoryoverride'] = implode( ',', $atts['excludecategoryoverride'] );
			}

			if ( isset( $atts['excludecategoryoverrideCSV'] ) && !empty( $atts['excludecategoryoverrideCSV'] ) ) {
				$atts['excludecategoryoverride'] = $atts['excludecategoryoverrideCSV'];
			}

			if ( isset( $atts['taglistoverride'] ) && !empty( $atts['taglistoverride'] ) && is_array( $atts['taglistoverride'] ) ) {
				$atts['taglistoverride'] = implode( ',', $atts['taglistoverride'] );
			}
			
			if ( isset( $atts['taglistoverrideCSV'] ) && !empty( $atts['taglistoverrideCSV'] ) ) {
				$atts['taglistoverride'] = $atts['taglistoverrideCSV'];
			}	

			extract( shortcode_atts( array(
				'settings' => '',
				'categorylistoverride' => '',
				'excludecategoryoverride' => '',
				'taglistoverride' => '',
			), $atts ) );

			$genoptions = get_option( 'LinkLibraryGeneral' );
			$genoptions = wp_parse_args( $genoptions, ll_reset_gen_settings( 'return' ) );

			if ( floatval( $genoptions['schemaversion'] ) < '5.0' ) {
				$this->ll_install();
			}

			if ( empty( $settings ) && !isset( $_POST['settings'] ) ) {
				$settings = 1;
			} else if ( isset( $_POST['settings'] ) ) {
				$settings = intval( $_POST['settings'] );
			}

			if ( $settings > $genoptions['numberstylesets'] ) {
				$settings = 1;
			}

			$settingsname = 'LinkLibraryPP' . intval( $settings );
			$options = get_option( $settingsname );
			$options = wp_parse_args( $options, ll_reset_options( 1, 'list', 'return' ) );

			if ( !empty( $categorylistoverride ) ) {
				$options['categorylist_cpt'] = $categorylistoverride;

				$update_list = false;
				$category_list_array = explode( ',', $categorylistoverride );
				foreach( $category_list_array as $index => $category_text ) {
					if ( !is_numeric( $category_text ) ) {
						$update_list = true;
						$matched_term = get_term_by( 'slug', $category_text, $genoptions['cattaxonomy'] );

						if ( $matched_term ) {
							$category_list_array[$index] = $matched_term->term_id;
						} else {
							unset( $category_list_array[$index] );
						}
					}
				}
				if ( $update_list ) {
					$options['categorylist_cpt'] = implode( ',', $category_list_array );
				}
			}

			if ( !empty( $excludecategoryoverride ) ) {
				$options['excludecategorylist_cpt'] = $excludecategoryoverride;

				$update_list = false;
				$exclude_category_list_array = explode( ',', $excludecategoryoverride );
				foreach( $exclude_category_list_array as $index => $category_text ) {
					if ( !is_numeric( $category_text ) ) {
						$update_list = true;
						$matched_term = get_term_by( 'slug', $category_text, $genoptions['cattaxonomy'] );

						if ( $matched_term ) {
							$exclude_category_list_array[$index] = $matched_term->term_id;
						} else {
							unset( $exclude_category_list_array[$index] );
						}
					}
				}
				if ( $update_list ) {
					$options['excludecategorylist_cpt'] = implode( ',', $exclude_category_list_array );
				}
			}

			if ( !empty( $taglistoverride ) ) {
				$options['taglist_cpt'] = $taglistoverride;

				$update_list = false;
				$tag_list_array = explode( ',', $taglistoverride );
				foreach( $tag_list_array as $index => $tag_text ) {
					if ( !is_numeric( $tag_text ) ) {
						$update_list = true;
						$matched_term = get_term_by( 'slug', $tag_text, $genoptions['tagtaxonomy'] );

						if ( $matched_term ) {
							$tag_list_array[$index] = $matched_term->term_id;
						} else {
							unset( $tag_list_array[$index] );
						}
					}
				}
				if ( $update_list ) {
					$options['taglist_cpt'] = implode( ',', $tag_list_array );
				}
			}

			if ( !empty( $excludecategoryoverride ) ) {
				$options['excludetaglist_cpt'] = $excludetagoverride;

				$update_list = false;
				$exclude_tag_list_array = explode( ',', $excludetagoverride );
				foreach( $exclude_tag_list_array as $index => $tag_text ) {
					if ( !is_numeric( $tag_text ) ) {
						$update_list = true;
						$matched_term = get_term_by( 'slug', $tag_text, $genoptions['tagtaxonomy'] );

						if ( $matched_term ) {
							$exclude_tag_list_array[$index] = $matched_term->term_id;
						} else {
							unset( $exclude_tag_list_array[$index] );
						}
					}
				}
				if ( $update_list ) {
					$options['excludetaglist_cpt'] = implode( ',', $exclude_category_list_array );
				}
			}

			$linklibraryoutput = '';

			if ( $genoptions['debugmode'] ) {
				$linklibraryoutput .= "\n<!-- RSS Library Settings Info:" . print_r( $options, true ) . "-->\n";
				$mainoutputstarttime = microtime( true );
				$linklibraryoutput .= "\n<!-- Start Time: " . $mainoutputstarttime . "-->\n";
			}

			require_once plugin_dir_path( __FILE__ ) . 'render-rss-library-sc.php';
			$linkcount = 1;
			$rss_array_items = array();
			$linklibraryoutput .= RenderRSSLibrary( $this, $genoptions, $options, intval( $settings ), 0, 0, false, $linkcount, $rss_array_items );

			if ( $genoptions['debugmode'] ) {
				$timeoutput = "\n<!-- [link-library] shortcode execution time: " . ( microtime( true ) - $mainoutputstarttime ) . "-->\n";
			}
			return $linklibraryoutput . ( true == $genoptions['debugmode'] ? $timeoutput : '' );
		}	

		function link_library_tagcloud( $atts = '' ) {
			$genoptions = get_option( 'LinkLibraryGeneral' );
			$genoptions = wp_parse_args( $genoptions, ll_reset_gen_settings( 'return' ) );
			
			$link_library_terms = get_terms( array( 'taxonomy' => $genoptions['cattaxonomy'] ) );
			$output = wp_generate_tag_cloud( $link_library_terms );
			return $output;
		}

		function conditionally_add_scripts_and_styles( $posts ) {
			if ( empty( $posts ) ) {
				return $posts;
			}

			global $llstylesheet;
			global $settingssetsids;
			$settingssetsids = array();
			$load_jquery = false;
			$load_thickbox = false;
			$load_colorbox = false;
			$load_recaptcha = false;
			$load_masonry = false;
			$load_style = '';
			$has_block = false;

			if ( $llstylesheet ) {
				$load_style = true;
			} else {
				$load_style = false;
			}

			$genoptions = get_option( 'LinkLibraryGeneral' );
			$genoptions = wp_parse_args( $genoptions, ll_reset_gen_settings( 'return' ) );

			if ( is_admin() ) {
				$load_jquery = false;
				$load_thickbox = false;
				$load_colorbox = false;
				$load_style = false;
			} else {
				foreach ( $posts as $post ) {
					if ( 'link_library_links' != get_post_type( $post->ID ) ) {
						$tag_array = array( 'link-library', 'link-library-cats', 'link-library-addlink', 'link-library-search', 'link-library-count', 'rss-library' );
						preg_match_all( '/' . get_shortcode_regex() . '/s', $post->post_content, $matches );
						if( isset( $matches[2] ) ) {
							foreach( ( array ) $matches[2] as $key => $value ) {
								$load_style = true;
								foreach( $tag_array as $tag ) {
									if( $tag === $value ) {
										if ( 'link-library-addlink' == $tag ) {
											$load_recaptcha = true;
										}
										$atts_list = shortcode_parse_atts( $matches[3][$key] );
										if ( !empty( $atts_list ) ) {
											foreach ( $atts_list as $key => $value ) {
												if ( $key = 'settings' && ( empty( $settingssetsids ) || false === array_search( $value, $settingssetsids ) ) ) {
													$settingssetsids[] = intval( $value );
												}							 
											}								
										} else {
											$settingssetsids[] = 1;
										}
										
									}							
								}						
							}
						}

						if ( function_exists( 'has_blocks' ) && function_exists( 'parse_blocks' ) ) {
							if ( has_blocks( $post->ID ) ) {
								$blocks = parse_blocks( $post->post_content );
			
								foreach ( $blocks as $block ) {
									if ( in_array( $block['blockName'], array( 'link-library/link-block', 'link-library/cat-block', 'link-library/search-block', 'link-library/addlink-block', 'link-library/count-block' ) ) ) {
										$load_style = true;
									}
		
									if ( in_array( $block['blockName'], array( 'link-library/addlink-block' ) ) ) {
										$load_recaptcha = true;
									}
		
									if ( isset( $block['attr']['settings'] ) && false === array_search( $block['attr']['settings'], $settingssetsids ) ) {
										$settingssetsids[] = $block['attr']['settings'];
									} elseif ( !isset( $block['attr']['settings'] ) ) {
										$settingssetsids[] = 1;
									}
								}
							}
						}					
					}
				}

				if ( empty( $settingssetsids ) ) {
					$settingssetsids[] = 1;
				}

				if ( $settingssetsids ) {
					foreach ( $settingssetsids as $settingsetid ) {
						$settingsname = 'LinkLibraryPP' . $settingsetid;
						$options = get_option( $settingsname );
						$options = wp_parse_args( $options, ll_reset_options( 1, 'list', 'return' ) );

						if ( $options['showonecatonly'] ) {
							$load_jquery = true;
						}

						if ( 'linkmasonrygrid' == $options['displayastable'] || 'categorymasonrygrid' == $options['displayastable'] ) {
							$load_masonry = true;
						}

						if ( $options['rsspreview'] || ( isset( $options['enable_link_popup'] ) && $options['enable_link_popup'] ) ) {
							$load_thickbox = true;
						}

						if ( $options['publishrssfeed'] == true ) {
							global $rss_settings;
							$rss_settings = $settingsetid;
						}

						if ( $options['addlinkformdisplaymode'] ) {
							$load_colorbox = true;
						}
					}
				}

				if ( !empty( $genoptions['includescriptcss'] ) ) {
					$pagelist = explode ( ',', $genoptions['includescriptcss'] );
					$loadscripts = false;
					foreach( $pagelist as $pageid ) {
						if ( ( $pageid == 'front' && is_front_page() ) ||
							( $pageid == 'category' && is_category() ) ||
							( $pageid == 'all') ||
							( is_page( $pageid ) ) ) {
							$load_jquery = true;
							$load_thickbox = true;
							$load_style = true;
						}
					}
				}
			}

			if ( $load_style ) {
				$llstylesheet = true;
			} else {
				$llstylesheet = false;
			}

			if ( $load_jquery ) {
				wp_enqueue_script( 'jquery' );
			}

			if ( $load_thickbox ) {
				wp_enqueue_script( 'thickbox' );
				wp_enqueue_style ( 'thickbox' );
			}

			if ( $load_colorbox ) {
				wp_enqueue_script( 'colorbox', plugins_url( 'colorbox/jquery.colorbox-min.js', __FILE__ ), array( 'jquery' ), "1.3.9" );
				wp_enqueue_style( 'colorboxstyle', plugins_url( 'colorbox/colorbox.css', __FILE__ ) );
			}

			if ( $load_recaptcha && $genoptions['captchagenerator'] ) {
				wp_enqueue_script( 'google_recaptcha', 'https://www.google.com/recaptcha/api.js', array(), false, true );
			}

			if ( $load_masonry ) {
				wp_enqueue_script( 'jquery-masonry' );
			}		

			return $posts;
		}

		function ll_popup_content() {
			require_once plugin_dir_path( __FILE__ ) . 'linkpopup.php';
			link_library_popup_content( $this );
		}

		function ll_template_redirect( $template ) {
			if ( !empty( $_POST['link_library_user_link_submission'] ) ) {
				require_once plugin_dir_path( __FILE__ ) . 'usersubmission.php';
				link_library_process_user_submission( $this );
				return '';
			} elseif ( !empty( $_GET['link_library_rss_preview'] ) ) {
				require_once plugin_dir_path( __FILE__ ) . 'rsspreview.php';
				link_library_generate_rss_preview( $this );
				return '';
			} elseif( !empty( $_GET['link_library_css'] ) ) {
				require_once plugin_dir_path( __FILE__ ) . 'cssgenerator.php';
				link_library_generate_css( $this );
				return '';
			} elseif ( !empty( $_GET['link_library_popup_content'] ) ) {
				require_once plugin_dir_path( __FILE__ ) . 'render-link-library-addlink-sc.php';
				link_library_link_submission_popup_form( $this );
				exit();
			} else {
				return $template;
			}
		}

		function ll_template_include( $template_path ) {
			if ( get_post_type() == 'link_library_links' && is_single() && !is_admin() ) {
				// checks if the file exists in the theme first,
				// otherwise serve the file from the plugin
				if ( $theme_file = locate_template( array ( 'single-link_library_links.php' ) ) ) {
					$template_path = $theme_file;
				} else {
					add_filter( 'the_content', array( $this, 'll_display_single_link' ), 20 );
				}
			}
			return $template_path;
		}

		function ll_get_string_between($string, $start, $end){
			$string = ' ' . $string;
			$ini = strpos($string, $start);
			if ($ini == 0) return '';
			$ini += strlen($start);
			$len = strpos($string, $end, $ini) - $ini;
			return substr($string, $ini, $len);
		}

		function ll_replace_all_between( $beginning, $end, $string, $replace ) {
			$beginningPos = strpos($string, $beginning);
			$endPos = strpos($string, $end);
			if ($beginningPos === false || $endPos === false) {
				return $string;
			}

			$textToDelete = substr($string, $beginningPos, ($endPos + strlen($end)) - $beginningPos);

			return str_replace($textToDelete, $replace, $string);
		}

		function ll_display_single_link( $content ) {

			$genoptions = get_option( 'LinkLibraryGeneral' );
			$genoptions = wp_parse_args( $genoptions, ll_reset_gen_settings( 'return' ) );

			if ( ( is_search() || is_feed() ) && 'link_library_links' == get_post_type() ) {
				$content = htmlspecialchars_decode( stripslashes( $genoptions['global_search_results_layout'] ) );	
			} elseif ( is_single() && 'link_library_links' == get_post_type() ) {
				$content = htmlspecialchars_decode( stripslashes( $genoptions['single_link_layout'] ) );
			} else {
				return $content;
			}		

			$item_id = get_the_ID();
			if ( !empty( $item_id ) ) {
				$link = get_post( get_the_ID() );
				if ( !empty( $link ) ) {
					$link_url = esc_url( get_post_meta( get_the_ID(), 'link_url', true ) );
					$link_description = esc_html( get_post_meta( get_the_ID(), 'link_description', true ) );
					$link_large_description = get_post_meta( get_the_ID(), 'link_textfield', true );
					$link_image = esc_url( get_post_meta( get_the_ID(), 'link_image', true ) );
					$link_price = number_format( floatval( get_post_meta( get_the_ID(), 'link_price', true ) ), 2 );
					$link_price_currency = $this->ll_get_string_between( $content, '[currency]', '[/currency]' );
					$link_price_currency_or_free = $this->ll_get_string_between( $content, '[currency_or_free]', '[/currency_or_free]' );
					$link_email = esc_html( get_post_meta( get_the_ID(), 'link_email', true ) );
					$link_phone_number = esc_html( get_post_meta( get_the_ID(), 'link_telephone', true ) );

					$link_terms = wp_get_post_terms( get_the_ID(), $genoptions['cattaxonomy'] );
					$link_terms_list = '';
					$link_terms_array = array();
					if ( is_array( $link_terms ) ) {
						foreach( $link_terms as $link_term ) {
							$link_terms_array[] = $link_term->name;
						}

						if ( !empty( $link_terms_array ) ) {
							$link_terms_list = implode( ', ', $link_terms_array );
						}
					}

					if ( false !== strpos( $content, '[if_link_address]' ) && false !== strpos( $content, '[/if_link_address]' ) ) {
						if ( empty( $link_url ) ) {
							$content = preg_replace( '/\[if_link_address].*\[\/if_link_address\]?/', '', $content );
						} else {
							$content = str_replace( '[if_link_address]', '', $content );
							$content = str_replace( '[/if_link_address]', '', $content );
						}
					}

					if ( false !== strpos( $content, '[if_link_image]' ) && false !== strpos( $content, '[/if_link_image]' ) ) {
						if ( empty( $link_image ) ) {
							$content = preg_replace( '/\[if_link_image].*\[\/if_link_image\]?/', '', $content );
						} else {
							$content = str_replace( '[if_link_image]', '', $content );
							$content = str_replace( '[/if_link_image]', '', $content );
						}
					}

					$content = str_replace( '[link_title]', $link->post_title, $content );
					$content = str_replace( '[link_content]', $link->post_content, $content );
					$content = str_replace( '[link_description]', $link_description, $content );
					$content = str_replace( '[link_large_description]', $link_large_description, $content );
					$content = str_replace( '[link_image]', $link_image, $content );
					$content = str_replace( '[link_email]', $link_email, $content );
					$content = str_replace( '[link_telephone]', $link_phone_number, $content );

					$content = str_replace( '[link_price]', $link_price, $content );
					$content = $this->ll_replace_all_between( '[currency]', '[/currency]', $content, $link_price_currency );

					if ( floatval( $link_price ) > 0.0 ) {
						$content = str_replace( '[link_price_or_free]', $link_price, $content );
						$content = $this->ll_replace_all_between( '[currency_or_free]', '[/currency_or_free]', $content, $link_price_currency_or_free );
					} else {
						$content = str_replace( '[link_price_or_free]', __( 'Free', 'link-library' ), $content );
						$content = $this->ll_replace_all_between( '[currency_or_free]', '[/currency_or_free]', $content, '' );
					}

					$content = str_replace( '[link_address]', $link_url, $content );
					$content = str_replace( '[link]', '<a href="' . $link_url . '">' . $link->post_title . '</a>', $content );
					$content = str_replace( '[link_category]', $link_terms_list, $content );
				}
			}

			global $wp_embed;
			$content = $wp_embed->run_shortcode( $content );

			$content = do_shortcode( $content );

			//return nl2br( $content );
			return $content;
		}

		function link_library_ajax_tracker() {
			require_once plugin_dir_path( __FILE__ ) . 'tracker.php';
			link_library_process_ajax_tracker( $this );
		}

		function link_library_generate_image() {
			global $my_link_library_plugin_admin;

			if ( empty( $my_link_library_plugin_admin ) ) {
				require_once plugin_dir_path( __FILE__ ) . 'link-library-admin.php';
				$my_link_library_plugin_admin = new link_library_plugin_admin();
			}

			require_once plugin_dir_path( __FILE__ ) . 'link-library-image-generator.php';
			link_library_ajax_image_generator( $my_link_library_plugin_admin );
		}
	}

	global $my_link_library_plugin;
	$my_link_library_plugin = new link_library_plugin();

	if ( is_admin() ) {

		/* Determine update method selected by user under General Settings or under Network Settings */
		$updatechannel = 'standard';

		if ( ( function_exists( 'is_multisite' ) && !is_multisite() ) || !function_exists( 'is_multisite' ) ) {
			$genoptions = get_option( 'LinkLibraryGeneral' );
			$genoptions = wp_parse_args( $genoptions, ll_reset_gen_settings( 'return' ) );

			if ( !empty( $genoptions['updatechannel'] ) ) {
				$updatechannel = $genoptions['updatechannel'];
			}
		} else if ( function_exists( 'is_multisite' ) && function_exists( 'is_network_admin' ) && is_multisite() && is_network_admin() ) {
			$networkoptions = get_site_option( 'LinkLibraryNetworkOptions' );

			if ( isset( $networkoptions ) && !empty( $networkoptions['updatechannel'] ) ) {
				$updatechannel = $networkoptions['updatechannel'];
			}
		}

		/* Install filter is user selected monthly updates to filter out dot dot dot minor releases (e.g. 5.8.8.x) */
		if ( 'monthly' == $updatechannel ) {
			add_filter( 'http_response', 'link_library_tweak_plugins_http_filter', 10, 3 );
		}

		if ( empty( $my_link_library_plugin_admin ) ) {
			global $my_link_library_plugin_admin;
			require plugin_dir_path( __FILE__ ) . 'link-library-admin.php';
			$my_link_library_plugin_admin = new link_library_plugin_admin();
		}
	}

	add_action( 'widgets_init', 'll_create_widgets' );

	function ll_create_widgets() {
		register_widget( 'Link_Library_Widget' );
	}

	class Link_Library_Widget extends WP_Widget {
		// Construction function
		function __construct () {
			parent::__construct( 'link_library', 'Link Library',
				array( 'description' =>
						'Displays links as configured under Link Library configurations' ) );
		}

		function form( $instance ) {
			$genoptions = get_option( 'LinkLibraryGeneral' );
			$genoptions = wp_parse_args( $genoptions, ll_reset_gen_settings( 'return' ) );

			$selected_library = ( !empty( $instance['selected_library'] ) ? $instance['selected_library'] : 1 );
			$widget_title = ( !empty( $instance['widget_title'] ) ? esc_attr( $instance['widget_title'] ) : 'Links' );
			$category_list_override = ( !empty( $instance['cat_list_override'] ) ? esc_attr( $instance['cat_list_override'] ) : '' );
			?>
			<p>
				<label for="<?php echo $this->get_field_id( 'widget_title' ); ?>">
					<?php echo 'Widget Title:'; ?>
					<input type="text"
						id="<?php echo $this->get_field_id( 'widget_title' );?>"
						name="<?php echo $this->get_field_name( 'widget_title' ); ?>"
						value="<?php echo $widget_title; ?>" />
				</label>
			</p>
			<p>
				<label for="<?php echo $this->get_field_id( 'selected_library' ); ?>">
					<?php echo 'Select library configuration to display:'; ?>
					<select id="<?php echo $this->get_field_id( 'selected_library' ); ?>"
							name="<?php echo $this->get_field_name( 'selected_library' ); ?>">
						<?php if ( empty( $genoptions['numberstylesets'] ) ) {
							$numberofsets = 1;
						} else {
							$numberofsets = $genoptions['numberstylesets'];
						}

						for ( $counter = 1; $counter <= $numberofsets; $counter ++ ) {
							$tempoptionname = "LinkLibraryPP" . $counter;
							$tempoptions          = get_option( $tempoptionname );
							$tempoptions = wp_parse_args( $tempoptions, ll_reset_options( 1, 'list', 'return' ) );

							echo '<option value="' . $counter . '" ' . selected( $selected_library, $counter ) . '>' . $tempoptions['settingssetname'] . '</option>';
						}
						?>
					</select>
				</label>
			</p>
			<p>
				<label for="<?php echo $this->get_field_id( 'cat_list_override' ); ?>">
					<?php echo 'Comma-separated list of categories to display:'; ?>
					<input type="text"
						id="<?php echo $this->get_field_id( 'cat_list_override' );?>"
						name="<?php echo $this->get_field_name( 'cat_list_override' ); ?>"
						value="<?php echo $category_list_override; ?>" />
				</label>
			</p>
		<?php }

		function widget( $args, $instance ) {
			// Extract members of args array as individual variables
			extract( $args );
			// Retrieve widget configuration options
			$selected_library = ( !empty( $instance['selected_library'] ) ? $instance['selected_library'] : 1 );
			$widget_title = ( !empty( $instance['widget_title'] ) ? esc_attr( $instance['widget_title'] ) : 'Links' );
			$category_list_override = ( !empty( $instance['cat_list_override'] ) ? esc_attr( $instance['cat_list_override'] ) : '' );

			// Display widget title
			echo $before_widget . $before_title;
			echo apply_filters( 'widget_title', $widget_title );
			echo $after_title;

			$shortcode_string = '[link-library settings="' . $selected_library . '"';

			if ( !empty( $category_list_override ) ) {
				$shortcode_string .= ' categorylistoverride="' . $category_list_override . '"';
			}
			
			$shortcode_string .= ']';

			echo do_shortcode( $shortcode_string );

			echo $after_widget;
		}
	}

	if ( ! function_exists('linklibrary_write_log')) {
		function linklibrary_write_log ( $log )  {
			if ( is_array( $log ) || is_object( $log ) ) {
				error_log( print_r( $log, true ) );
			} else {
				error_log( $log );
			}
		}
	}
}

add_filter('wp_get_object_terms', function($terms, $object_ids, $taxonomies, $args)
{
    if ( !$terms && basename( $_SERVER['PHP_SELF'] ) == 'post-new.php' ) {

        // Category - note: only 1 category is supported currently
        if ( $taxonomies == "'link_library_category'" && isset( $_REQUEST['link_library_cat'] ) ) {			
            $id = intval( $_REQUEST['link_library_cat'] );

            if ( $id ) {
                return array( $id );
            }
        }
    }
    return $terms;
}, 10, 4);
